xref: /petsc/src/mat/impls/is/matis.c (revision 53b44cf51312b26b3ce2b752e5e7a5f785862b3a)
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;
4475d48cdbSStefano 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   const PetscScalar *sc;
347c9225affSStefano Zampini   PetscScalar       *aa;
348c9225affSStefano Zampini   const PetscInt    *ii,*jj;
349c9225affSStefano Zampini   PetscInt          i,n,m;
350c9225affSStefano Zampini   PetscInt          *ecount,**eneighs,n_neigh,*neigh,*n_shared,**shared;
351c9225affSStefano Zampini   PetscBool         flg;
352c9225affSStefano Zampini   PetscErrorCode    ierr;
353c9225affSStefano Zampini 
354c9225affSStefano Zampini   PetscFunctionBegin;
355c9225affSStefano Zampini   ierr = VecGetLocalSize(matis->counter,&n);CHKERRQ(ierr);
356c9225affSStefano Zampini   ierr = PetscCalloc1(n,&ecount);CHKERRQ(ierr);
357c9225affSStefano Zampini   ierr = PetscMalloc1(n,&eneighs);CHKERRQ(ierr);
358c9225affSStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(A->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
359c9225affSStefano Zampini   for (i=1,m=0;i<n_neigh;i++) {
360c9225affSStefano Zampini     PetscInt j;
361c9225affSStefano Zampini 
362c9225affSStefano Zampini     m += n_shared[i];
363c9225affSStefano Zampini     for (j=0;j<n_shared[i];j++) ecount[shared[i][j]]++;
364c9225affSStefano Zampini   }
365c9225affSStefano Zampini   if (n) { ierr = PetscMalloc1(m,&eneighs[0]);CHKERRQ(ierr); }
366c9225affSStefano Zampini   for (i=1;i<n;i++) eneighs[i] = eneighs[i-1] + ecount[i-1];
367c9225affSStefano Zampini   ierr = PetscMemzero(ecount,n*sizeof(PetscInt));CHKERRQ(ierr);
368c9225affSStefano Zampini   for (i=1;i<n_neigh;i++) {
369c9225affSStefano Zampini     PetscInt j;
370c9225affSStefano Zampini 
371c9225affSStefano Zampini     for (j=0;j<n_shared[i];j++) {
372c9225affSStefano Zampini       PetscInt k = shared[i][j];
373c9225affSStefano Zampini 
374c9225affSStefano Zampini       eneighs[k][ecount[k]] = neigh[i];
375c9225affSStefano Zampini       ecount[k]++;
376c9225affSStefano Zampini     }
377c9225affSStefano Zampini   }
378c9225affSStefano Zampini   for (i=0;i<n;i++) { ierr = PetscSortRemoveDupsInt(&ecount[i],eneighs[i]);CHKERRQ(ierr); }
379c9225affSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(A->rmap->mapping,&n_neigh,&neigh,&n_shared,&shared);CHKERRQ(ierr);
380c9225affSStefano Zampini   ierr = VecGetArrayRead(matis->counter,&sc);CHKERRQ(ierr);
381c9225affSStefano Zampini   ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&m,&ii,&jj,&flg);CHKERRQ(ierr);
382c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
383c9225affSStefano Zampini   if (m != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %D != %D",m,n);
384c9225affSStefano Zampini   ierr = MatSeqAIJGetArray(matis->A,&aa);CHKERRQ(ierr);
385c9225affSStefano Zampini   for (i=0;i<n;i++) {
386c9225affSStefano Zampini     if (PetscUnlikely(ecount[i])) {
387c9225affSStefano Zampini       PetscInt          j;
388c9225affSStefano Zampini 
389c9225affSStefano Zampini       for (j=ii[i];j<ii[i+1];j++) {
390c9225affSStefano Zampini         PetscInt i2 = jj[j],p,p2;
391c9225affSStefano Zampini         PetscScalar scal = 1.0;
392c9225affSStefano Zampini 
393c9225affSStefano Zampini         for (p=0;p<ecount[i];p++) {
394c9225affSStefano Zampini           for (p2=0;p2<ecount[i2];p2++) {
395c9225affSStefano Zampini             if (eneighs[i][p] == eneighs[i2][p2]) { scal += 1.0; break; }
396c9225affSStefano Zampini           }
397c9225affSStefano Zampini         }
398c9225affSStefano Zampini         aa[j] /= scal;
399c9225affSStefano Zampini       }
400c9225affSStefano Zampini     }
401c9225affSStefano Zampini   }
402c9225affSStefano Zampini   ierr = PetscFree(ecount);CHKERRQ(ierr);
403c9225affSStefano Zampini   if (n) {
404c9225affSStefano Zampini     ierr = PetscFree(eneighs[0]);CHKERRQ(ierr);
405c9225affSStefano Zampini   }
406c9225affSStefano Zampini   ierr = PetscFree(eneighs);CHKERRQ(ierr);
407c9225affSStefano Zampini   ierr = MatSeqAIJRestoreArray(matis->A,&aa);CHKERRQ(ierr);
408c9225affSStefano Zampini   ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&m,&ii,&jj,&flg);CHKERRQ(ierr);
409c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
410c9225affSStefano Zampini   ierr = VecRestoreArrayRead(matis->counter,&sc);CHKERRQ(ierr);
411c9225affSStefano Zampini   PetscFunctionReturn(0);
412c9225affSStefano Zampini }
413c9225affSStefano Zampini 
414c9225affSStefano Zampini static PetscErrorCode MatMPIXAIJComputeLocalToGlobalMapping_Private(Mat A, ISLocalToGlobalMapping *l2g)
415c9225affSStefano Zampini {
416c9225affSStefano Zampini   Mat            /*Ad,*/Ao;
417c9225affSStefano Zampini   IS             is;
418c9225affSStefano Zampini   MPI_Comm       comm;
419c9225affSStefano Zampini   const PetscInt *garray;
420c9225affSStefano Zampini   PetscInt       bs, mode = 0;
421c9225affSStefano Zampini   PetscBool      ismpiaij,ismpibaij,useAl2g = PETSC_FALSE;
422c9225affSStefano Zampini   PetscErrorCode ierr;
423c9225affSStefano Zampini 
424c9225affSStefano Zampini   PetscFunctionBegin;
425c9225affSStefano Zampini   ierr = PetscOptionsGetBool(((PetscObject)A)->options,((PetscObject)A)->prefix,"-mat_aij_is_usel2g",&useAl2g,NULL);CHKERRQ(ierr);
426c9225affSStefano Zampini   if (useAl2g) {
427c9225affSStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,l2g,NULL);CHKERRQ(ierr);
428c9225affSStefano Zampini     PetscFunctionReturn(0);
429c9225affSStefano Zampini   }
430c9225affSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
431c9225affSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij);CHKERRQ(ierr);
432c9225affSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr);
433c9225affSStefano Zampini   if (ismpiaij) {
434c9225affSStefano Zampini     bs   = 1;
435c9225affSStefano Zampini     ierr = MatMPIAIJGetSeqAIJ(A,NULL,&Ao,&garray);CHKERRQ(ierr);
436c9225affSStefano Zampini   } else if (ismpibaij) {
437c9225affSStefano Zampini     ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
438c9225affSStefano Zampini     ierr = MatMPIBAIJGetSeqBAIJ(A,NULL,&Ao,&garray);CHKERRQ(ierr);
439c9225affSStefano Zampini   } else SETERRQ1(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name);
440c9225affSStefano Zampini   if (!garray) SETERRQ(comm,PETSC_ERR_ARG_WRONGSTATE,"garray not present");
441c9225affSStefano Zampini   switch(mode) {
442c9225affSStefano Zampini   default:
443c9225affSStefano Zampini     if (A->rmap->n) {
444c9225affSStefano Zampini       PetscInt i,dc,oc,stc,*aux;
445c9225affSStefano Zampini 
446c9225affSStefano Zampini       ierr = MatGetLocalSize(A,NULL,&dc);CHKERRQ(ierr);
447c9225affSStefano Zampini       ierr = MatGetLocalSize(Ao,NULL,&oc);CHKERRQ(ierr);
448c9225affSStefano Zampini       ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr);
449c9225affSStefano Zampini       ierr = PetscMalloc1((dc+oc)/bs,&aux);CHKERRQ(ierr);
450c9225affSStefano Zampini       for (i=0; i<dc/bs; i++) aux[i]       = i+stc/bs;
451c9225affSStefano Zampini       for (i=0; i<oc/bs; i++) aux[i+dc/bs] = garray[i];
452c9225affSStefano Zampini       ierr = ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
453c9225affSStefano Zampini     } else {
454c9225affSStefano Zampini       ierr = ISCreateBlock(comm,1,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
455c9225affSStefano Zampini     }
456c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,l2g);CHKERRQ(ierr);
457c9225affSStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
458c9225affSStefano Zampini   }
459c9225affSStefano Zampini   PetscFunctionReturn(0);
460c9225affSStefano Zampini }
461c9225affSStefano Zampini 
462c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
463c9225affSStefano Zampini {
464c9225affSStefano Zampini   Mat                    lA,Ad,Ao,B = NULL;
4656989cf23SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
4666989cf23SStefano Zampini   IS                     is;
4676989cf23SStefano Zampini   MPI_Comm               comm;
4686989cf23SStefano Zampini   void                   *ptrs[2];
4696989cf23SStefano Zampini   const char             *names[2] = {"_convert_csr_aux","_convert_csr_data"};
470c9225affSStefano Zampini   const PetscInt         *garray;
4716989cf23SStefano Zampini   PetscScalar            *dd,*od,*aa,*data;
472c9225affSStefano Zampini   const PetscInt         *di,*dj,*oi,*oj;
473c9225affSStefano Zampini   const PetscInt         *odi,*odj,*ooi,*ooj;
4746989cf23SStefano Zampini   PetscInt               *aux,*ii,*jj;
475c9225affSStefano Zampini   PetscInt               bs,lc,dr,dc,oc,str,stc,nnz,i,jd,jo,cum;
476c9225affSStefano Zampini   PetscBool              flg,ismpiaij,ismpibaij,was_inplace = PETSC_FALSE;
477c9225affSStefano Zampini   PetscMPIInt            size;
4786989cf23SStefano Zampini   PetscErrorCode         ierr;
4796989cf23SStefano Zampini 
480ab4d48faSStefano Zampini   PetscFunctionBegin;
4816989cf23SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
482c9225affSStefano Zampini   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
483c9225affSStefano Zampini   if (size == 1) {
484c9225affSStefano Zampini     ierr = MatConvert_SeqXAIJ_IS(A,type,reuse,newmat);CHKERRQ(ierr);
485c9225affSStefano Zampini     PetscFunctionReturn(0);
486c9225affSStefano Zampini   }
487c9225affSStefano Zampini   if (reuse != MAT_REUSE_MATRIX && A->cmap->N == A->rmap->N) {
488c9225affSStefano Zampini     ierr = MatMPIXAIJComputeLocalToGlobalMapping_Private(A,&rl2g);CHKERRQ(ierr);
489c9225affSStefano Zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
490c9225affSStefano Zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
491c9225affSStefano Zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
492c9225affSStefano Zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,rl2g);CHKERRQ(ierr);
493c9225affSStefano Zampini     ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
494c9225affSStefano Zampini     ierr = MatSetBlockSize(B,bs);CHKERRQ(ierr);
495c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
496c9225affSStefano Zampini     if (reuse == MAT_INPLACE_MATRIX) was_inplace = PETSC_TRUE;
497c9225affSStefano Zampini     reuse = MAT_REUSE_MATRIX;
498c9225affSStefano Zampini   }
499c9225affSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
500c9225affSStefano Zampini     Mat            *newlA, lA;
501c9225affSStefano Zampini     IS             rows, cols;
502c9225affSStefano Zampini     const PetscInt *ridx, *cidx;
503c9225affSStefano Zampini     PetscInt       rbs, cbs, nr, nc;
504c9225affSStefano Zampini 
505c9225affSStefano Zampini     if (!B) B = *newmat;
506c9225affSStefano Zampini     ierr = MatGetLocalToGlobalMapping(B,&rl2g,&cl2g);CHKERRQ(ierr);
507c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockIndices(rl2g,&ridx);CHKERRQ(ierr);
508c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockIndices(cl2g,&cidx);CHKERRQ(ierr);
509c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(rl2g,&nr);CHKERRQ(ierr);
510c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(cl2g,&nc);CHKERRQ(ierr);
511c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(rl2g,&rbs);CHKERRQ(ierr);
512c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(cl2g,&cbs);CHKERRQ(ierr);
513c9225affSStefano Zampini     ierr = ISCreateBlock(comm,rbs,nr/rbs,ridx,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
514c9225affSStefano Zampini     if (rl2g != cl2g) {
515c9225affSStefano Zampini       ierr = ISCreateBlock(comm,cbs,nc/cbs,cidx,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
516c9225affSStefano Zampini     } else {
517c9225affSStefano Zampini       ierr = PetscObjectReference((PetscObject)rows);CHKERRQ(ierr);
518c9225affSStefano Zampini       cols = rows;
519c9225affSStefano Zampini     }
520c9225affSStefano Zampini     ierr = MatISGetLocalMat(B,&lA);CHKERRQ(ierr);
521c9225affSStefano Zampini     ierr = MatCreateSubMatrices(A,1,&rows,&cols,MAT_INITIAL_MATRIX,&newlA);CHKERRQ(ierr);
522c9225affSStefano Zampini     ierr = MatConvert(newlA[0],MATSEQAIJ,MAT_INPLACE_MATRIX,&newlA[0]);CHKERRQ(ierr);
523c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreBlockIndices(rl2g,&ridx);CHKERRQ(ierr);
524c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreBlockIndices(cl2g,&cidx);CHKERRQ(ierr);
525c9225affSStefano Zampini     ierr = ISDestroy(&rows);CHKERRQ(ierr);
526c9225affSStefano Zampini     ierr = ISDestroy(&cols);CHKERRQ(ierr);
527c9225affSStefano Zampini     if (!lA->preallocated) { /* first time */
528c9225affSStefano Zampini       ierr = MatDuplicate(newlA[0],MAT_COPY_VALUES,&lA);CHKERRQ(ierr);
529c9225affSStefano Zampini       ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
530c9225affSStefano Zampini       ierr = PetscObjectDereference((PetscObject)lA);CHKERRQ(ierr);
531c9225affSStefano Zampini     }
532c9225affSStefano Zampini     ierr = MatCopy(newlA[0],lA,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
533c9225affSStefano Zampini     ierr = MatDestroySubMatrices(1,&newlA);CHKERRQ(ierr);
534c9225affSStefano Zampini     ierr = MatISScaleDisassembling_Private(B);CHKERRQ(ierr);
535c9225affSStefano Zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
536c9225affSStefano Zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
537c9225affSStefano Zampini     if (was_inplace) { ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr); }
538c9225affSStefano Zampini     else *newmat = B;
539c9225affSStefano Zampini     PetscFunctionReturn(0);
540c9225affSStefano Zampini   }
541c9225affSStefano Zampini   /* rectangular case, just compress out the column space */
542c9225affSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij);CHKERRQ(ierr);
543c9225affSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr);
544c9225affSStefano Zampini   if (ismpiaij) {
545c9225affSStefano Zampini     bs   = 1;
546c9225affSStefano Zampini     ierr = MatMPIAIJGetSeqAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
547c9225affSStefano Zampini   } else if (ismpibaij) {
548c9225affSStefano Zampini     ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
549c9225affSStefano Zampini     ierr = MatMPIBAIJGetSeqBAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
550c9225affSStefano Zampini     ierr = MatConvert(Ad,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ad);CHKERRQ(ierr);
551c9225affSStefano Zampini     ierr = MatConvert(Ao,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ao);CHKERRQ(ierr);
552c9225affSStefano Zampini   } else SETERRQ1(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name);
553c9225affSStefano Zampini   ierr = MatSeqAIJGetArray(Ad,&dd);CHKERRQ(ierr);
554c9225affSStefano Zampini   ierr = MatSeqAIJGetArray(Ao,&od);CHKERRQ(ierr);
555c9225affSStefano Zampini   if (!garray) SETERRQ(comm,PETSC_ERR_ARG_WRONGSTATE,"garray not present");
5566989cf23SStefano Zampini 
5576989cf23SStefano Zampini   /* access relevant information from MPIAIJ */
5586989cf23SStefano Zampini   ierr = MatGetOwnershipRange(A,&str,NULL);CHKERRQ(ierr);
5596989cf23SStefano Zampini   ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr);
5606989cf23SStefano Zampini   ierr = MatGetLocalSize(A,&dr,&dc);CHKERRQ(ierr);
561c9225affSStefano Zampini   ierr = MatGetLocalSize(Ao,NULL,&oc);CHKERRQ(ierr);
562c9225affSStefano Zampini   ierr = MatGetRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&di,&dj,&flg);CHKERRQ(ierr);
563c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
564c9225affSStefano Zampini   ierr = MatGetRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&oi,&oj,&flg);CHKERRQ(ierr);
565c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
566c9225affSStefano Zampini   nnz = di[dr] + oi[dr];
567c9225affSStefano Zampini   /* store original pointers to be restored later */
568c9225affSStefano Zampini   odi = di; odj = dj; ooi = oi; ooj = oj;
5696989cf23SStefano Zampini 
5706989cf23SStefano Zampini   /* generate l2g maps for rows and cols */
571c9225affSStefano Zampini   ierr = ISCreateStride(comm,dr/bs,str/bs,1,&is);CHKERRQ(ierr);
572c9225affSStefano Zampini   if (bs > 1) {
573c9225affSStefano Zampini     IS is2;
574c9225affSStefano Zampini 
575c9225affSStefano Zampini     ierr = ISGetLocalSize(is,&i);CHKERRQ(ierr);
576c9225affSStefano Zampini     ierr = ISGetIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
577c9225affSStefano Zampini     ierr = ISCreateBlock(comm,bs,i,aux,PETSC_COPY_VALUES,&is2);CHKERRQ(ierr);
578c9225affSStefano Zampini     ierr = ISRestoreIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
579c9225affSStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
580c9225affSStefano Zampini     is   = is2;
581c9225affSStefano Zampini   }
5826989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
5836989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
584e363d98aSStefano Zampini   if (dr) {
585c9225affSStefano Zampini     ierr = PetscMalloc1((dc+oc)/bs,&aux);CHKERRQ(ierr);
586c9225affSStefano Zampini     for (i=0; i<dc/bs; i++) aux[i]       = i+stc/bs;
587c9225affSStefano Zampini     for (i=0; i<oc/bs; i++) aux[i+dc/bs] = garray[i];
588c9225affSStefano Zampini     ierr = ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
589e363d98aSStefano Zampini     lc   = dc+oc;
590e363d98aSStefano Zampini   } else {
591c9225affSStefano Zampini     ierr = ISCreateBlock(comm,bs,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
592e363d98aSStefano Zampini     lc   = 0;
593e363d98aSStefano Zampini   }
5946989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
5956989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
5966989cf23SStefano Zampini 
5976989cf23SStefano Zampini   /* create MATIS object */
598c9225affSStefano Zampini   ierr = MatCreate(comm,&B);CHKERRQ(ierr);
599c9225affSStefano Zampini   ierr = MatSetSizes(B,dr,dc,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
600c9225affSStefano Zampini   ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
601c9225affSStefano Zampini   ierr = MatSetBlockSize(B,bs);CHKERRQ(ierr);
602c9225affSStefano Zampini   ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
6036989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
6046989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
6056989cf23SStefano Zampini 
6066989cf23SStefano Zampini   /* merge local matrices */
6076989cf23SStefano Zampini   ierr = PetscMalloc1(nnz+dr+1,&aux);CHKERRQ(ierr);
6086989cf23SStefano Zampini   ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr);
6096989cf23SStefano Zampini   ii   = aux;
6106989cf23SStefano Zampini   jj   = aux+dr+1;
6116989cf23SStefano Zampini   aa   = data;
6126989cf23SStefano Zampini   *ii  = *(di++) + *(oi++);
6136989cf23SStefano Zampini   for (jd=0,jo=0,cum=0;*ii<nnz;cum++)
6146989cf23SStefano Zampini   {
6156989cf23SStefano Zampini      for (;jd<*di;jd++) { *jj++ = *dj++;      *aa++ = *dd++; }
6166989cf23SStefano Zampini      for (;jo<*oi;jo++) { *jj++ = *oj++ + dc; *aa++ = *od++; }
6176989cf23SStefano Zampini      *(++ii) = *(di++) + *(oi++);
6186989cf23SStefano Zampini   }
6196989cf23SStefano Zampini   for (;cum<dr;cum++) *(++ii) = nnz;
620c9225affSStefano Zampini 
621c9225affSStefano Zampini   ierr = MatRestoreRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&odi,&odj,&flg);CHKERRQ(ierr);
622c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
623c9225affSStefano Zampini   ierr = MatRestoreRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&ooi,&ooj,&flg);CHKERRQ(ierr);
624c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
625c9225affSStefano Zampini   ierr = MatSeqAIJRestoreArray(Ad,&dd);CHKERRQ(ierr);
626c9225affSStefano Zampini   ierr = MatSeqAIJRestoreArray(Ao,&od);CHKERRQ(ierr);
627c9225affSStefano Zampini 
6286989cf23SStefano Zampini   ii   = aux;
6296989cf23SStefano Zampini   jj   = aux+dr+1;
6306989cf23SStefano Zampini   aa   = data;
631e363d98aSStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,lc,ii,jj,aa,&lA);CHKERRQ(ierr);
6326989cf23SStefano Zampini 
6336989cf23SStefano Zampini   /* create containers to destroy the data */
6346989cf23SStefano Zampini   ptrs[0] = aux;
6356989cf23SStefano Zampini   ptrs[1] = data;
6366989cf23SStefano Zampini   for (i=0; i<2; i++) {
6376989cf23SStefano Zampini     PetscContainer c;
6386989cf23SStefano Zampini 
6396989cf23SStefano Zampini     ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr);
6406989cf23SStefano Zampini     ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr);
641b81c21eeSStefano Zampini     ierr = PetscContainerSetUserDestroy(c,PetscContainerUserDestroyDefault);CHKERRQ(ierr);
6426989cf23SStefano Zampini     ierr = PetscObjectCompose((PetscObject)lA,names[i],(PetscObject)c);CHKERRQ(ierr);
6436989cf23SStefano Zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
6446989cf23SStefano Zampini   }
645c9225affSStefano Zampini   if (ismpibaij) { /* destroy converted local matrices */
646c9225affSStefano Zampini     ierr = MatDestroy(&Ad);CHKERRQ(ierr);
647c9225affSStefano Zampini     ierr = MatDestroy(&Ao);CHKERRQ(ierr);
648c9225affSStefano Zampini   }
6496989cf23SStefano Zampini 
6506989cf23SStefano Zampini   /* finalize matrix */
651c9225affSStefano Zampini   ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
6526989cf23SStefano Zampini   ierr = MatDestroy(&lA);CHKERRQ(ierr);
653c9225affSStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
654c9225affSStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
655c9225affSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
656c9225affSStefano Zampini     ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
657c9225affSStefano Zampini   } else *newmat = B;
6586989cf23SStefano Zampini   PetscFunctionReturn(0);
6596989cf23SStefano Zampini }
6606989cf23SStefano Zampini 
661cf0a3239SStefano Zampini /*@
6623d996552SStefano Zampini    MatISSetUpSF - Setup star forest objects used by MatIS.
663cf0a3239SStefano Zampini 
664cf0a3239SStefano Zampini    Collective on MPI_Comm
665cf0a3239SStefano Zampini 
666cf0a3239SStefano Zampini    Input Parameters:
667cf0a3239SStefano Zampini +  A - the matrix
668cf0a3239SStefano Zampini 
669cf0a3239SStefano Zampini    Level: advanced
670cf0a3239SStefano Zampini 
67195452b02SPatrick Sanan    Notes:
67295452b02SPatrick Sanan     This function does not need to be called by the user.
673cf0a3239SStefano Zampini 
674cf0a3239SStefano Zampini .keywords: matrix
675cf0a3239SStefano Zampini 
676cf0a3239SStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatISGetLocalMat()
677cf0a3239SStefano Zampini @*/
678cf0a3239SStefano Zampini PetscErrorCode  MatISSetUpSF(Mat A)
679cf0a3239SStefano Zampini {
6807fa8f2d3SStefano Zampini   PetscErrorCode ierr;
6817fa8f2d3SStefano Zampini 
6827fa8f2d3SStefano Zampini   PetscFunctionBegin;
683cf0a3239SStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
684cf0a3239SStefano Zampini   PetscValidType(A,1);
685cf0a3239SStefano Zampini   ierr = PetscTryMethod(A,"MatISSetUpSF_C",(Mat),(A));CHKERRQ(ierr);
6867fa8f2d3SStefano Zampini   PetscFunctionReturn(0);
6877fa8f2d3SStefano Zampini }
6887fa8f2d3SStefano Zampini 
6895e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
6905e3038f0Sstefano_zampini {
6915e3038f0Sstefano_zampini   Mat                    **nest,*snest,**rnest,lA,B;
6925e3038f0Sstefano_zampini   IS                     *iscol,*isrow,*islrow,*islcol;
6935e3038f0Sstefano_zampini   ISLocalToGlobalMapping rl2g,cl2g;
6945e3038f0Sstefano_zampini   MPI_Comm               comm;
6955b003df0Sstefano_zampini   PetscInt               *lr,*lc,*l2gidxs;
6965b003df0Sstefano_zampini   PetscInt               i,j,nr,nc,rbs,cbs;
6979e7b2b25Sstefano_zampini   PetscBool              convert,lreuse,*istrans;
6985e3038f0Sstefano_zampini   PetscErrorCode         ierr;
6995e3038f0Sstefano_zampini 
700ab4d48faSStefano Zampini   PetscFunctionBegin;
7015e3038f0Sstefano_zampini   ierr   = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr);
7025e3038f0Sstefano_zampini   lreuse = PETSC_FALSE;
7035e3038f0Sstefano_zampini   rnest  = NULL;
7045e3038f0Sstefano_zampini   if (reuse == MAT_REUSE_MATRIX) {
7055e3038f0Sstefano_zampini     PetscBool ismatis,isnest;
7065e3038f0Sstefano_zampini 
7075e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
7085e3038f0Sstefano_zampini     if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type);
7095e3038f0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
7105e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr);
7115e3038f0Sstefano_zampini     if (isnest) {
7125e3038f0Sstefano_zampini       ierr   = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr);
7135e3038f0Sstefano_zampini       lreuse = (PetscBool)(i == nr && j == nc);
7145e3038f0Sstefano_zampini       if (!lreuse) rnest = NULL;
7155e3038f0Sstefano_zampini     }
7165e3038f0Sstefano_zampini   }
7175e3038f0Sstefano_zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
7185b003df0Sstefano_zampini   ierr = PetscCalloc2(nr,&lr,nc,&lc);CHKERRQ(ierr);
7199e7b2b25Sstefano_zampini   ierr = PetscCalloc6(nr,&isrow,nc,&iscol,
7205e3038f0Sstefano_zampini                       nr,&islrow,nc,&islcol,
7219e7b2b25Sstefano_zampini                       nr*nc,&snest,nr*nc,&istrans);CHKERRQ(ierr);
7225e3038f0Sstefano_zampini   ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr);
7235e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
7245e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
7255e3038f0Sstefano_zampini       PetscBool ismatis;
7269e7b2b25Sstefano_zampini       PetscInt  l1,l2,lb1,lb2,ij=i*nc+j;
7275e3038f0Sstefano_zampini 
7285e3038f0Sstefano_zampini       /* Null matrix pointers are allowed in MATNEST */
7295e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
7305e3038f0Sstefano_zampini 
7315e3038f0Sstefano_zampini       /* Nested matrices should be of type MATIS */
7329e7b2b25Sstefano_zampini       ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij]);CHKERRQ(ierr);
7339e7b2b25Sstefano_zampini       if (istrans[ij]) {
7349e7b2b25Sstefano_zampini         Mat T,lT;
7359e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
7369e7b2b25Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis);CHKERRQ(ierr);
7379e7b2b25Sstefano_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);
7389e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(T,&lT);CHKERRQ(ierr);
7399e7b2b25Sstefano_zampini         ierr = MatCreateTranspose(lT,&snest[ij]);CHKERRQ(ierr);
7409e7b2b25Sstefano_zampini       } else {
7415e3038f0Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr);
7425e3038f0Sstefano_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);
7439e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr);
7449e7b2b25Sstefano_zampini       }
7455e3038f0Sstefano_zampini 
7465e3038f0Sstefano_zampini       /* Check compatibility of local sizes */
7475e3038f0Sstefano_zampini       ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr);
7489e7b2b25Sstefano_zampini       ierr = MatGetBlockSizes(snest[ij],&lb1,&lb2);CHKERRQ(ierr);
7495e3038f0Sstefano_zampini       if (!l1 || !l2) continue;
7505e3038f0Sstefano_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);
7515e3038f0Sstefano_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);
7525e3038f0Sstefano_zampini       lr[i] = l1;
7535e3038f0Sstefano_zampini       lc[j] = l2;
7545e3038f0Sstefano_zampini 
7555e3038f0Sstefano_zampini       /* check compatibilty for local matrix reusage */
7565e3038f0Sstefano_zampini       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
7575e3038f0Sstefano_zampini     }
7585e3038f0Sstefano_zampini   }
7595e3038f0Sstefano_zampini 
7605e3038f0Sstefano_zampini #if defined (PETSC_USE_DEBUG)
7615e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for rows */
7625e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
7635e3038f0Sstefano_zampini     rl2g = NULL;
7645e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
7655e3038f0Sstefano_zampini       PetscInt n1,n2;
7665e3038f0Sstefano_zampini 
7675e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
7689e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
7699e7b2b25Sstefano_zampini         Mat T;
7709e7b2b25Sstefano_zampini 
7719e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
7729e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,NULL,&cl2g);CHKERRQ(ierr);
7739e7b2b25Sstefano_zampini       } else {
7745e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr);
7759e7b2b25Sstefano_zampini       }
7765e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
7775e3038f0Sstefano_zampini       if (!n1) continue;
7785e3038f0Sstefano_zampini       if (!rl2g) {
7795e3038f0Sstefano_zampini         rl2g = cl2g;
7805e3038f0Sstefano_zampini       } else {
7815e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
7825e3038f0Sstefano_zampini         PetscBool      same;
7835e3038f0Sstefano_zampini 
7845e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
7855e3038f0Sstefano_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);
7865e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
7875e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
7885e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
7895e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
7905e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
7915e3038f0Sstefano_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);
7925e3038f0Sstefano_zampini       }
7935e3038f0Sstefano_zampini     }
7945e3038f0Sstefano_zampini   }
7955e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for columns */
7965e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
7975e3038f0Sstefano_zampini     rl2g = NULL;
7985e3038f0Sstefano_zampini     for (j=0;j<nr;j++) {
7995e3038f0Sstefano_zampini       PetscInt n1,n2;
8005e3038f0Sstefano_zampini 
8015e3038f0Sstefano_zampini       if (!nest[j][i]) continue;
8029e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
8039e7b2b25Sstefano_zampini         Mat T;
8049e7b2b25Sstefano_zampini 
8059e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[j][i],&T);CHKERRQ(ierr);
8069e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,&cl2g,NULL);CHKERRQ(ierr);
8079e7b2b25Sstefano_zampini       } else {
8085e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr);
8099e7b2b25Sstefano_zampini       }
8105e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
8115e3038f0Sstefano_zampini       if (!n1) continue;
8125e3038f0Sstefano_zampini       if (!rl2g) {
8135e3038f0Sstefano_zampini         rl2g = cl2g;
8145e3038f0Sstefano_zampini       } else {
8155e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
8165e3038f0Sstefano_zampini         PetscBool      same;
8175e3038f0Sstefano_zampini 
8185e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
8195e3038f0Sstefano_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);
8205e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
8215e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
8225e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
8235e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
8245e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
8255e3038f0Sstefano_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);
8265e3038f0Sstefano_zampini       }
8275e3038f0Sstefano_zampini     }
8285e3038f0Sstefano_zampini   }
8295e3038f0Sstefano_zampini #endif
8305e3038f0Sstefano_zampini 
8315e3038f0Sstefano_zampini   B = NULL;
8325e3038f0Sstefano_zampini   if (reuse != MAT_REUSE_MATRIX) {
8335b003df0Sstefano_zampini     PetscInt stl;
8345b003df0Sstefano_zampini 
8355e3038f0Sstefano_zampini     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
8365e3038f0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) stl += lr[i];
8375e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
8385b003df0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) {
8395e3038f0Sstefano_zampini       Mat            usedmat;
8405e3038f0Sstefano_zampini       Mat_IS         *matis;
8415e3038f0Sstefano_zampini       const PetscInt *idxs;
8425e3038f0Sstefano_zampini 
8435e3038f0Sstefano_zampini       /* local IS for local NEST */
8445b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
8455e3038f0Sstefano_zampini 
8465e3038f0Sstefano_zampini       /* l2gmap */
8475e3038f0Sstefano_zampini       j = 0;
8485e3038f0Sstefano_zampini       usedmat = nest[i][j];
8499e7b2b25Sstefano_zampini       while (!usedmat && j < nc-1) usedmat = nest[i][++j];
8509e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid row mat");
8519e7b2b25Sstefano_zampini 
8529e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
8539e7b2b25Sstefano_zampini         Mat T;
8549e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
8559e7b2b25Sstefano_zampini         usedmat = T;
8569e7b2b25Sstefano_zampini       }
85782d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
8585e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
8595e3038f0Sstefano_zampini       ierr  = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr);
8609e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
8619e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
8629e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
8639e7b2b25Sstefano_zampini       } else {
8645e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
8655e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
8669e7b2b25Sstefano_zampini       }
8675e3038f0Sstefano_zampini       ierr = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr);
8685e3038f0Sstefano_zampini       stl += lr[i];
8695e3038f0Sstefano_zampini     }
8705e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr);
8715e3038f0Sstefano_zampini 
8725e3038f0Sstefano_zampini     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
8735e3038f0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) stl += lc[i];
8745e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
8755b003df0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) {
8765e3038f0Sstefano_zampini       Mat            usedmat;
8775e3038f0Sstefano_zampini       Mat_IS         *matis;
8785e3038f0Sstefano_zampini       const PetscInt *idxs;
8795e3038f0Sstefano_zampini 
8805e3038f0Sstefano_zampini       /* local IS for local NEST */
8815b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
8825e3038f0Sstefano_zampini 
8835e3038f0Sstefano_zampini       /* l2gmap */
8845e3038f0Sstefano_zampini       j = 0;
8855e3038f0Sstefano_zampini       usedmat = nest[j][i];
8869e7b2b25Sstefano_zampini       while (!usedmat && j < nr-1) usedmat = nest[++j][i];
8879e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid column mat");
8889e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
8899e7b2b25Sstefano_zampini         Mat T;
8909e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
8919e7b2b25Sstefano_zampini         usedmat = T;
8929e7b2b25Sstefano_zampini       }
89382d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
8945e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
8955e3038f0Sstefano_zampini       ierr  = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr);
8969e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
8979e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
8989e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
8999e7b2b25Sstefano_zampini       } else {
9005e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
9015e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
9029e7b2b25Sstefano_zampini       }
9035e3038f0Sstefano_zampini       ierr = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr);
9045e3038f0Sstefano_zampini       stl += lc[i];
9055e3038f0Sstefano_zampini     }
9065e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr);
9075e3038f0Sstefano_zampini 
9085e3038f0Sstefano_zampini     /* Create MATIS */
9095e3038f0Sstefano_zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
9105e3038f0Sstefano_zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
9115e3038f0Sstefano_zampini     ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr);
9125e3038f0Sstefano_zampini     ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr);
9135e3038f0Sstefano_zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
9145e3038f0Sstefano_zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
9155e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
9165e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
9175e3038f0Sstefano_zampini     ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
9189e7b2b25Sstefano_zampini     for (i=0;i<nr*nc;i++) {
9199e7b2b25Sstefano_zampini       if (istrans[i]) {
9209e7b2b25Sstefano_zampini         ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
9219e7b2b25Sstefano_zampini       }
9229e7b2b25Sstefano_zampini     }
9235e3038f0Sstefano_zampini     ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
9245e3038f0Sstefano_zampini     ierr = MatDestroy(&lA);CHKERRQ(ierr);
9255e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9265e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9275e3038f0Sstefano_zampini     if (reuse == MAT_INPLACE_MATRIX) {
9285e3038f0Sstefano_zampini       ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
9295e3038f0Sstefano_zampini     } else {
9305e3038f0Sstefano_zampini       *newmat = B;
9315e3038f0Sstefano_zampini     }
9325e3038f0Sstefano_zampini   } else {
9335e3038f0Sstefano_zampini     if (lreuse) {
9345e3038f0Sstefano_zampini       ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
9355e3038f0Sstefano_zampini       for (i=0;i<nr;i++) {
9365e3038f0Sstefano_zampini         for (j=0;j<nc;j++) {
9375e3038f0Sstefano_zampini           if (snest[i*nc+j]) {
9385e3038f0Sstefano_zampini             ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr);
9399e7b2b25Sstefano_zampini             if (istrans[i*nc+j]) {
9409e7b2b25Sstefano_zampini               ierr = MatDestroy(&snest[i*nc+j]);CHKERRQ(ierr);
9419e7b2b25Sstefano_zampini             }
9425e3038f0Sstefano_zampini           }
9435e3038f0Sstefano_zampini         }
9445e3038f0Sstefano_zampini       }
9455e3038f0Sstefano_zampini     } else {
9465b003df0Sstefano_zampini       PetscInt stl;
9475b003df0Sstefano_zampini       for (i=0,stl=0;i<nr;i++) {
9485b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
9495b003df0Sstefano_zampini         stl  += lr[i];
9505e3038f0Sstefano_zampini       }
9515b003df0Sstefano_zampini       for (i=0,stl=0;i<nc;i++) {
9525b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
9535b003df0Sstefano_zampini         stl  += lc[i];
9545e3038f0Sstefano_zampini       }
9555e3038f0Sstefano_zampini       ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
956ab4d48faSStefano Zampini       for (i=0;i<nr*nc;i++) {
9579e7b2b25Sstefano_zampini         if (istrans[i]) {
9589e7b2b25Sstefano_zampini           ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
9599e7b2b25Sstefano_zampini         }
960ab4d48faSStefano Zampini       }
9615e3038f0Sstefano_zampini       ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
9625e3038f0Sstefano_zampini       ierr = MatDestroy(&lA);CHKERRQ(ierr);
9635e3038f0Sstefano_zampini     }
9645e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9655e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9665e3038f0Sstefano_zampini   }
9675e3038f0Sstefano_zampini 
9685b003df0Sstefano_zampini   /* Create local matrix in MATNEST format */
9695b003df0Sstefano_zampini   convert = PETSC_FALSE;
9705b003df0Sstefano_zampini   ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr);
9715b003df0Sstefano_zampini   if (convert) {
9725b003df0Sstefano_zampini     Mat              M;
9735b003df0Sstefano_zampini     MatISLocalFields lf;
9745b003df0Sstefano_zampini     PetscContainer   c;
9755b003df0Sstefano_zampini 
9765b003df0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
9775b003df0Sstefano_zampini     ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr);
9785b003df0Sstefano_zampini     ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr);
9795b003df0Sstefano_zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
9805b003df0Sstefano_zampini 
9815b003df0Sstefano_zampini     /* attach local fields to the matrix */
9825b003df0Sstefano_zampini     ierr = PetscNew(&lf);CHKERRQ(ierr);
9835b003df0Sstefano_zampini     ierr = PetscCalloc2(nr,&lf->rf,nc,&lf->cf);CHKERRQ(ierr);
9845b003df0Sstefano_zampini     for (i=0;i<nr;i++) {
9855b003df0Sstefano_zampini       PetscInt n,st;
9865b003df0Sstefano_zampini 
9875b003df0Sstefano_zampini       ierr = ISGetLocalSize(islrow[i],&n);CHKERRQ(ierr);
9885b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islrow[i],&st,NULL);CHKERRQ(ierr);
9895b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->rf[i]);CHKERRQ(ierr);
9905b003df0Sstefano_zampini     }
9915b003df0Sstefano_zampini     for (i=0;i<nc;i++) {
9925b003df0Sstefano_zampini       PetscInt n,st;
9935b003df0Sstefano_zampini 
9945b003df0Sstefano_zampini       ierr = ISGetLocalSize(islcol[i],&n);CHKERRQ(ierr);
9955b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islcol[i],&st,NULL);CHKERRQ(ierr);
9965b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->cf[i]);CHKERRQ(ierr);
9975b003df0Sstefano_zampini     }
9985b003df0Sstefano_zampini     lf->nr = nr;
9995b003df0Sstefano_zampini     lf->nc = nc;
10005b003df0Sstefano_zampini     ierr = PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c);CHKERRQ(ierr);
10015b003df0Sstefano_zampini     ierr = PetscContainerSetPointer(c,lf);CHKERRQ(ierr);
10025b003df0Sstefano_zampini     ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private);CHKERRQ(ierr);
10035b003df0Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c);CHKERRQ(ierr);
10045b003df0Sstefano_zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
10055b003df0Sstefano_zampini   }
10065b003df0Sstefano_zampini 
10075e3038f0Sstefano_zampini   /* Free workspace */
10085e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
10095e3038f0Sstefano_zampini     ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr);
10105e3038f0Sstefano_zampini   }
10115e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
10125e3038f0Sstefano_zampini     ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr);
10135e3038f0Sstefano_zampini   }
10149e7b2b25Sstefano_zampini   ierr = PetscFree6(isrow,iscol,islrow,islcol,snest,istrans);CHKERRQ(ierr);
10155b003df0Sstefano_zampini   ierr = PetscFree2(lr,lc);CHKERRQ(ierr);
10165e3038f0Sstefano_zampini   PetscFunctionReturn(0);
10175e3038f0Sstefano_zampini }
10185e3038f0Sstefano_zampini 
1019ad219c80Sstefano_zampini static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r)
1020ad219c80Sstefano_zampini {
1021ad219c80Sstefano_zampini   Mat_IS            *matis = (Mat_IS*)A->data;
1022ad219c80Sstefano_zampini   Vec               ll,rr;
1023ad219c80Sstefano_zampini   const PetscScalar *Y,*X;
1024ad219c80Sstefano_zampini   PetscScalar       *x,*y;
1025ad219c80Sstefano_zampini   PetscErrorCode    ierr;
1026ad219c80Sstefano_zampini 
1027ad219c80Sstefano_zampini   PetscFunctionBegin;
1028ad219c80Sstefano_zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
1029ad219c80Sstefano_zampini   if (l) {
1030ad219c80Sstefano_zampini     ll   = matis->y;
1031ad219c80Sstefano_zampini     ierr = VecGetArrayRead(l,&Y);CHKERRQ(ierr);
1032ad219c80Sstefano_zampini     ierr = VecGetArray(ll,&y);CHKERRQ(ierr);
1033ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
1034ad219c80Sstefano_zampini   } else {
1035ad219c80Sstefano_zampini     ll = NULL;
1036ad219c80Sstefano_zampini   }
1037ad219c80Sstefano_zampini   if (r) {
1038ad219c80Sstefano_zampini     rr   = matis->x;
1039ad219c80Sstefano_zampini     ierr = VecGetArrayRead(r,&X);CHKERRQ(ierr);
1040ad219c80Sstefano_zampini     ierr = VecGetArray(rr,&x);CHKERRQ(ierr);
1041ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
1042ad219c80Sstefano_zampini   } else {
1043ad219c80Sstefano_zampini     rr = NULL;
1044ad219c80Sstefano_zampini   }
1045ad219c80Sstefano_zampini   if (ll) {
1046ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
1047ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(l,&Y);CHKERRQ(ierr);
1048ad219c80Sstefano_zampini     ierr = VecRestoreArray(ll,&y);CHKERRQ(ierr);
1049ad219c80Sstefano_zampini   }
1050ad219c80Sstefano_zampini   if (rr) {
1051ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
1052ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(r,&X);CHKERRQ(ierr);
1053ad219c80Sstefano_zampini     ierr = VecRestoreArray(rr,&x);CHKERRQ(ierr);
1054ad219c80Sstefano_zampini   }
1055ad219c80Sstefano_zampini   ierr = MatDiagonalScale(matis->A,ll,rr);CHKERRQ(ierr);
1056ad219c80Sstefano_zampini   PetscFunctionReturn(0);
1057ad219c80Sstefano_zampini }
1058ad219c80Sstefano_zampini 
10597fa8f2d3SStefano Zampini static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo)
10607fa8f2d3SStefano Zampini {
10617fa8f2d3SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
10627fa8f2d3SStefano Zampini   MatInfo        info;
10637fa8f2d3SStefano Zampini   PetscReal      isend[6],irecv[6];
10647fa8f2d3SStefano Zampini   PetscInt       bs;
10657fa8f2d3SStefano Zampini   PetscErrorCode ierr;
10667fa8f2d3SStefano Zampini 
10677fa8f2d3SStefano Zampini   PetscFunctionBegin;
10687fa8f2d3SStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
10697fa8f2d3SStefano Zampini   if (matis->A->ops->getinfo) {
10707fa8f2d3SStefano Zampini     ierr     = MatGetInfo(matis->A,MAT_LOCAL,&info);CHKERRQ(ierr);
10717fa8f2d3SStefano Zampini     isend[0] = info.nz_used;
10727fa8f2d3SStefano Zampini     isend[1] = info.nz_allocated;
10737fa8f2d3SStefano Zampini     isend[2] = info.nz_unneeded;
10747fa8f2d3SStefano Zampini     isend[3] = info.memory;
10757fa8f2d3SStefano Zampini     isend[4] = info.mallocs;
10767fa8f2d3SStefano Zampini   } else {
10777fa8f2d3SStefano Zampini     isend[0] = 0.;
10787fa8f2d3SStefano Zampini     isend[1] = 0.;
10797fa8f2d3SStefano Zampini     isend[2] = 0.;
10807fa8f2d3SStefano Zampini     isend[3] = 0.;
10817fa8f2d3SStefano Zampini     isend[4] = 0.;
10827fa8f2d3SStefano Zampini   }
10837fa8f2d3SStefano Zampini   isend[5] = matis->A->num_ass;
10847fa8f2d3SStefano Zampini   if (flag == MAT_LOCAL) {
10857fa8f2d3SStefano Zampini     ginfo->nz_used      = isend[0];
10867fa8f2d3SStefano Zampini     ginfo->nz_allocated = isend[1];
10877fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = isend[2];
10887fa8f2d3SStefano Zampini     ginfo->memory       = isend[3];
10897fa8f2d3SStefano Zampini     ginfo->mallocs      = isend[4];
10907fa8f2d3SStefano Zampini     ginfo->assemblies   = isend[5];
10917fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_MAX) {
10927fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,6,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
10937fa8f2d3SStefano Zampini 
10947fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
10957fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
10967fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
10977fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
10987fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
10997fa8f2d3SStefano Zampini     ginfo->assemblies   = irecv[5];
11007fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_SUM) {
11017fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
11027fa8f2d3SStefano Zampini 
11037fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
11047fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
11057fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
11067fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
11077fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
11087fa8f2d3SStefano Zampini     ginfo->assemblies   = A->num_ass;
1109d7f69cd0SStefano Zampini   }
1110d7f69cd0SStefano Zampini   ginfo->block_size        = bs;
1111d7f69cd0SStefano Zampini   ginfo->fill_ratio_given  = 0;
1112d7f69cd0SStefano Zampini   ginfo->fill_ratio_needed = 0;
1113d7f69cd0SStefano Zampini   ginfo->factor_mallocs    = 0;
11145e3038f0Sstefano_zampini   PetscFunctionReturn(0);
11155e3038f0Sstefano_zampini }
11165e3038f0Sstefano_zampini 
1117d7f69cd0SStefano Zampini PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
1118d7f69cd0SStefano Zampini {
1119d7f69cd0SStefano Zampini   Mat                    C,lC,lA;
1120d7f69cd0SStefano Zampini   PetscErrorCode         ierr;
1121d7f69cd0SStefano Zampini 
1122d7f69cd0SStefano Zampini   PetscFunctionBegin;
1123cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) {
1124cf37664fSBarry Smith     ISLocalToGlobalMapping rl2g,cl2g;
1125d7f69cd0SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
1126d7f69cd0SStefano Zampini     ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr);
1127d7f69cd0SStefano Zampini     ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
1128d7f69cd0SStefano Zampini     ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
1129d7f69cd0SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
1130d7f69cd0SStefano Zampini     ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr);
1131cf37664fSBarry Smith   } else {
1132cf37664fSBarry Smith     C = *B;
1133d7f69cd0SStefano Zampini   }
1134d7f69cd0SStefano Zampini 
1135d7f69cd0SStefano Zampini   /* perform local transposition */
1136d7f69cd0SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
1137d7f69cd0SStefano Zampini   ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr);
1138d7f69cd0SStefano Zampini   ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
1139d7f69cd0SStefano Zampini   ierr = MatDestroy(&lC);CHKERRQ(ierr);
1140d7f69cd0SStefano Zampini 
1141cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) {
1142d7f69cd0SStefano Zampini     *B = C;
1143d7f69cd0SStefano Zampini   } else {
1144d7f69cd0SStefano Zampini     ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr);
1145d7f69cd0SStefano Zampini   }
11467aa7aec5Sstefano_zampini   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11477aa7aec5Sstefano_zampini   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1148d7f69cd0SStefano Zampini   PetscFunctionReturn(0);
1149d7f69cd0SStefano Zampini }
1150d7f69cd0SStefano Zampini 
11513fd1c9e7SStefano Zampini PetscErrorCode  MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
11523fd1c9e7SStefano Zampini {
11533fd1c9e7SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
11543fd1c9e7SStefano Zampini   PetscErrorCode ierr;
11553fd1c9e7SStefano Zampini 
11563fd1c9e7SStefano Zampini   PetscFunctionBegin;
11574b89b9cdSStefano Zampini   if (D) { /* MatShift_IS pass D = NULL */
11583fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11593fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11603fd1c9e7SStefano Zampini   }
11613fd1c9e7SStefano Zampini   ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr);
11623fd1c9e7SStefano Zampini   ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr);
11633fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
11643fd1c9e7SStefano Zampini }
11653fd1c9e7SStefano Zampini 
11663fd1c9e7SStefano Zampini PetscErrorCode  MatShift_IS(Mat A,PetscScalar a)
11673fd1c9e7SStefano Zampini {
11684b89b9cdSStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
11693fd1c9e7SStefano Zampini   PetscErrorCode ierr;
11703fd1c9e7SStefano Zampini 
11713fd1c9e7SStefano Zampini   PetscFunctionBegin;
11724b89b9cdSStefano Zampini   ierr = VecSet(is->y,a);CHKERRQ(ierr);
11733fd1c9e7SStefano Zampini   ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr);
11743fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
11753fd1c9e7SStefano Zampini }
11763fd1c9e7SStefano Zampini 
1177f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1178f26d0771SStefano Zampini {
1179f26d0771SStefano Zampini   PetscErrorCode ierr;
1180f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
1181f26d0771SStefano Zampini 
1182f26d0771SStefano Zampini   PetscFunctionBegin;
1183f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1184f26d0771SStefano 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);
1185f26d0771SStefano Zampini #endif
1186f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
1187f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
1188b4f971dfSStefano Zampini   ierr = MatSetValuesLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
1189f26d0771SStefano Zampini   PetscFunctionReturn(0);
1190f26d0771SStefano Zampini }
1191f26d0771SStefano Zampini 
1192f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1193f26d0771SStefano Zampini {
1194f26d0771SStefano Zampini   PetscErrorCode ierr;
1195f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
1196f26d0771SStefano Zampini 
1197f26d0771SStefano Zampini   PetscFunctionBegin;
1198f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1199f26d0771SStefano 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);
1200f26d0771SStefano Zampini #endif
1201f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
1202f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
1203b4f971dfSStefano Zampini   ierr = MatSetValuesBlockedLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
1204f26d0771SStefano Zampini   PetscFunctionReturn(0);
1205f26d0771SStefano Zampini }
1206f26d0771SStefano Zampini 
1207f0ae7da4SStefano Zampini static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
1208a8116848SStefano Zampini {
1209a8116848SStefano Zampini   PetscInt      *owners = map->range;
1210a8116848SStefano Zampini   PetscInt       n      = map->n;
1211a8116848SStefano Zampini   PetscSF        sf;
1212a8116848SStefano Zampini   PetscInt      *lidxs,*work = NULL;
1213a8116848SStefano Zampini   PetscSFNode   *ridxs;
1214a8116848SStefano Zampini   PetscMPIInt    rank;
1215a8116848SStefano Zampini   PetscInt       r, p = 0, len = 0;
1216a8116848SStefano Zampini   PetscErrorCode ierr;
1217a8116848SStefano Zampini 
1218a8116848SStefano Zampini   PetscFunctionBegin;
1219fd3a879cSJed Brown   if (on) *on = 0;              /* squelch -Wmaybe-uninitialized */
1220a8116848SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */
1221a8116848SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
1222a8116848SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
1223a8116848SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
1224a8116848SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
1225a8116848SStefano Zampini   for (r = 0; r < N; ++r) {
1226a8116848SStefano Zampini     const PetscInt idx = idxs[r];
1227a8116848SStefano 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);
1228a8116848SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
1229a8116848SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
1230a8116848SStefano Zampini     }
1231a8116848SStefano Zampini     ridxs[r].rank = p;
1232a8116848SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
1233a8116848SStefano Zampini   }
1234a8116848SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
1235a8116848SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
1236a8116848SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
1237a8116848SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
1238f0ae7da4SStefano Zampini   if (ogidxs) { /* communicate global idxs */
1239a8116848SStefano Zampini     PetscInt cum = 0,start,*work2;
1240f0ae7da4SStefano Zampini 
1241f0ae7da4SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
1242a8116848SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
1243a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
1244a8116848SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
1245a8116848SStefano Zampini     start -= cum;
1246a8116848SStefano Zampini     cum = 0;
1247a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
1248a8116848SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
1249a8116848SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
1250a8116848SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
1251a8116848SStefano Zampini   }
1252a8116848SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
1253a8116848SStefano Zampini   /* Compress and put in indices */
1254a8116848SStefano Zampini   for (r = 0; r < n; ++r)
1255a8116848SStefano Zampini     if (lidxs[r] >= 0) {
1256a8116848SStefano Zampini       if (work) work[len] = work[r];
1257a8116848SStefano Zampini       lidxs[len++] = r;
1258a8116848SStefano Zampini     }
1259a8116848SStefano Zampini   if (on) *on = len;
1260a8116848SStefano Zampini   if (oidxs) *oidxs = lidxs;
1261a8116848SStefano Zampini   if (ogidxs) *ogidxs = work;
1262a8116848SStefano Zampini   PetscFunctionReturn(0);
1263a8116848SStefano Zampini }
1264a8116848SStefano Zampini 
12657dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
1266a8116848SStefano Zampini {
1267a8116848SStefano Zampini   Mat               locmat,newlocmat;
1268a8116848SStefano Zampini   Mat_IS            *newmatis;
1269a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
1270a8116848SStefano Zampini   Vec               rtest,ltest;
1271a8116848SStefano Zampini   const PetscScalar *array;
1272a8116848SStefano Zampini #endif
1273a8116848SStefano Zampini   const PetscInt    *idxs;
1274a8116848SStefano Zampini   PetscInt          i,m,n;
1275a8116848SStefano Zampini   PetscErrorCode    ierr;
1276a8116848SStefano Zampini 
1277a8116848SStefano Zampini   PetscFunctionBegin;
1278a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
1279a8116848SStefano Zampini     PetscBool ismatis;
1280a8116848SStefano Zampini 
1281a8116848SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
1282a8116848SStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
1283a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
1284a8116848SStefano Zampini     if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
1285a8116848SStefano Zampini     if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
1286a8116848SStefano Zampini   }
1287a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
1288a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
1289a8116848SStefano Zampini   ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
1290a8116848SStefano Zampini   ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
1291a8116848SStefano Zampini   ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
1292a8116848SStefano Zampini   for (i=0;i<n;i++) {
1293a8116848SStefano Zampini     ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
1294a8116848SStefano Zampini   }
1295a8116848SStefano Zampini   ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
1296a8116848SStefano Zampini   ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
1297a8116848SStefano Zampini   ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
1298a8116848SStefano Zampini   ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
1299a8116848SStefano Zampini   ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
1300fd479f66SMatthew 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]));
1301a8116848SStefano Zampini   ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
1302a8116848SStefano Zampini   ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
1303a8116848SStefano Zampini   ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
1304a8116848SStefano Zampini   ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
1305a8116848SStefano Zampini   for (i=0;i<n;i++) {
1306a8116848SStefano Zampini     ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
1307a8116848SStefano Zampini   }
1308a8116848SStefano Zampini   ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
1309a8116848SStefano Zampini   ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
1310a8116848SStefano Zampini   ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
1311a8116848SStefano Zampini   ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
1312a8116848SStefano Zampini   ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
1313fd479f66SMatthew 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]));
1314a8116848SStefano Zampini   ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
1315a8116848SStefano Zampini   ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
1316a8116848SStefano Zampini   ierr = VecDestroy(&rtest);CHKERRQ(ierr);
1317a8116848SStefano Zampini   ierr = VecDestroy(&ltest);CHKERRQ(ierr);
1318a8116848SStefano Zampini #endif
1319a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
1320a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
1321a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
1322a8116848SStefano Zampini     IS                     is;
1323a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
1324306cf5c7SStefano Zampini     PetscInt               ll,newloc,irbs,icbs,arbs,acbs,rbs,cbs;
132594342113SStefano Zampini     PetscBool              cong;
1326a8116848SStefano Zampini     MPI_Comm               comm;
1327a8116848SStefano Zampini 
1328a8116848SStefano Zampini     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
1329306cf5c7SStefano Zampini     ierr = MatGetBlockSizes(mat,&arbs,&acbs);CHKERRQ(ierr);
1330306cf5c7SStefano Zampini     ierr = ISGetBlockSize(irow,&irbs);CHKERRQ(ierr);
1331306cf5c7SStefano Zampini     ierr = ISGetBlockSize(icol,&icbs);CHKERRQ(ierr);
1332306cf5c7SStefano Zampini     rbs  = arbs == irbs ? irbs : 1;
1333306cf5c7SStefano Zampini     cbs  = acbs == icbs ? icbs : 1;
1334a8116848SStefano Zampini     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
1335a8116848SStefano Zampini     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
1336a8116848SStefano Zampini     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
1337a8116848SStefano Zampini     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
1338a8116848SStefano Zampini     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1339306cf5c7SStefano Zampini     ierr = MatSetBlockSizes(*newmat,rbs,cbs);CHKERRQ(ierr);
1340a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
1341a8116848SStefano Zampini     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
1342f0ae7da4SStefano Zampini     ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
1343a8116848SStefano Zampini     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
13443d996552SStefano Zampini     ierr = MatISSetUpSF(mat);CHKERRQ(ierr);
13453d996552SStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,matis->sf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
1346a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
1347a8116848SStefano Zampini     ierr = PetscFree(lidxs);CHKERRQ(ierr);
1348a8116848SStefano Zampini     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
1349a8116848SStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
1350a8116848SStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
13513d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
1352a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
1353a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
13543d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++)
1355a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
1356a8116848SStefano Zampini         lidxs[newloc] = i;
1357a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
1358a8116848SStefano Zampini       }
1359a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1360a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
1361306cf5c7SStefano Zampini     ierr = ISLocalToGlobalMappingSetBlockSize(rl2g,rbs);CHKERRQ(ierr);
1362a8116848SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
1363a8116848SStefano Zampini     /* local is to extract local submatrix */
1364a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
1365a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
136694342113SStefano Zampini     ierr = MatHasCongruentLayouts(mat,&cong);CHKERRQ(ierr);
136794342113SStefano Zampini     if (cong && irow == icol && matis->csf == matis->sf) {
1368a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
1369a8116848SStefano Zampini       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
1370a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
1371a8116848SStefano Zampini     } else {
1372a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
1373a8116848SStefano Zampini 
1374a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
1375a8116848SStefano Zampini       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
1376f0ae7da4SStefano Zampini       ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
1377a8116848SStefano Zampini       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
13783d996552SStefano Zampini       ierr = PetscMemzero(matis->csf_rootdata,matis->csf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
1379a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
1380a8116848SStefano Zampini       ierr = PetscFree(lidxs);CHKERRQ(ierr);
1381a8116848SStefano Zampini       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
1382a8116848SStefano Zampini       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
1383a8116848SStefano Zampini       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
13843d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
1385a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
1386a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
13873d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++)
1388a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
1389a8116848SStefano Zampini           lidxs[newloc] = i;
1390a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
1391a8116848SStefano Zampini         }
1392a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1393a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
1394306cf5c7SStefano Zampini       ierr = ISLocalToGlobalMappingSetBlockSize(cl2g,cbs);CHKERRQ(ierr);
1395a8116848SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
1396a8116848SStefano Zampini       /* local is to extract local submatrix */
1397a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
1398a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
1399a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
1400a8116848SStefano Zampini     }
1401a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
1402a8116848SStefano Zampini   } else {
1403a8116848SStefano Zampini     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
1404a8116848SStefano Zampini   }
1405a8116848SStefano Zampini   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
1406a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
14077dae84e0SHong Zhang   ierr = MatCreateSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
1408a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
1409a8116848SStefano Zampini     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
1410a8116848SStefano Zampini     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
1411a8116848SStefano Zampini   }
1412a8116848SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1413a8116848SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1414a8116848SStefano Zampini   PetscFunctionReturn(0);
1415a8116848SStefano Zampini }
1416a8116848SStefano Zampini 
1417a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
14182b404112SStefano Zampini {
14192b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
14202b404112SStefano Zampini   PetscBool      ismatis;
14212b404112SStefano Zampini   PetscErrorCode ierr;
14222b404112SStefano Zampini 
14232b404112SStefano Zampini   PetscFunctionBegin;
14242b404112SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
14252b404112SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
14262b404112SStefano Zampini   b = (Mat_IS*)B->data;
14272b404112SStefano Zampini   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
1428cdc753b6SBarry Smith   ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
14292b404112SStefano Zampini   PetscFunctionReturn(0);
14302b404112SStefano Zampini }
14312b404112SStefano Zampini 
1432a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
14336bd84002SStefano Zampini {
1434527b2640SStefano Zampini   Vec               v;
1435527b2640SStefano Zampini   const PetscScalar *array;
1436527b2640SStefano Zampini   PetscInt          i,n;
14376bd84002SStefano Zampini   PetscErrorCode    ierr;
14386bd84002SStefano Zampini 
14396bd84002SStefano Zampini   PetscFunctionBegin;
1440527b2640SStefano Zampini   *missing = PETSC_FALSE;
1441527b2640SStefano Zampini   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
1442527b2640SStefano Zampini   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
1443527b2640SStefano Zampini   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1444527b2640SStefano Zampini   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
1445527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
1446527b2640SStefano Zampini   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
1447527b2640SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
1448527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
1449527b2640SStefano Zampini   if (d) {
1450527b2640SStefano Zampini     *d = -1;
1451527b2640SStefano Zampini     if (*missing) {
1452527b2640SStefano Zampini       PetscInt rstart;
1453527b2640SStefano Zampini       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
1454527b2640SStefano Zampini       *d = i+rstart;
1455527b2640SStefano Zampini     }
1456527b2640SStefano Zampini   }
14576bd84002SStefano Zampini   PetscFunctionReturn(0);
14586bd84002SStefano Zampini }
14596bd84002SStefano Zampini 
1460cf0a3239SStefano Zampini static PetscErrorCode MatISSetUpSF_IS(Mat B)
146128f4e0baSStefano Zampini {
146228f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
146328f4e0baSStefano Zampini   const PetscInt *gidxs;
14644f2d7cafSStefano Zampini   PetscInt       nleaves;
146528f4e0baSStefano Zampini   PetscErrorCode ierr;
146628f4e0baSStefano Zampini 
146728f4e0baSStefano Zampini   PetscFunctionBegin;
14684f2d7cafSStefano Zampini   if (matis->sf) PetscFunctionReturn(0);
146975d48cdbSStefano Zampini   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
147075d48cdbSStefano Zampini   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
147128f4e0baSStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
14723bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
14734f2d7cafSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(B->rmap->mapping,&nleaves);CHKERRQ(ierr);
14744f2d7cafSStefano Zampini   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
14753bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
14764f2d7cafSStefano Zampini   ierr = PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
1477a8116848SStefano Zampini   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
14783d996552SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(B->cmap->mapping,&nleaves);CHKERRQ(ierr);
1479a8116848SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
1480a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
14813d996552SStefano Zampini     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
1482a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
14833d996552SStefano Zampini     ierr = PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
1484a8116848SStefano Zampini   } else {
1485a8116848SStefano Zampini     matis->csf = matis->sf;
1486a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
1487a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
1488a8116848SStefano Zampini   }
148928f4e0baSStefano Zampini   PetscFunctionReturn(0);
149028f4e0baSStefano Zampini }
14912e1947a5SStefano Zampini 
1492eb82efa4SStefano Zampini /*@
149375d48cdbSStefano Zampini    MatISStoreL2L - Store local-to-local operators during the Galerkin process of MatPtAP.
149475d48cdbSStefano Zampini 
149575d48cdbSStefano Zampini    Collective on MPI_Comm
149675d48cdbSStefano Zampini 
149775d48cdbSStefano Zampini    Input Parameters:
149875d48cdbSStefano Zampini +  A - the matrix
149975d48cdbSStefano Zampini -  store - the boolean flag
150075d48cdbSStefano Zampini 
150175d48cdbSStefano Zampini    Level: advanced
150275d48cdbSStefano Zampini 
150375d48cdbSStefano Zampini    Notes:
150475d48cdbSStefano Zampini 
150575d48cdbSStefano Zampini .keywords: matrix
150675d48cdbSStefano Zampini 
150775d48cdbSStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatPtAP()
150875d48cdbSStefano Zampini @*/
150975d48cdbSStefano Zampini PetscErrorCode  MatISStoreL2L(Mat A, PetscBool store)
151075d48cdbSStefano Zampini {
151175d48cdbSStefano Zampini   PetscErrorCode ierr;
151275d48cdbSStefano Zampini 
151375d48cdbSStefano Zampini   PetscFunctionBegin;
151475d48cdbSStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
151575d48cdbSStefano Zampini   PetscValidType(A,1);
151675d48cdbSStefano Zampini   PetscValidLogicalCollectiveBool(A,store,2);
151775d48cdbSStefano Zampini   ierr = PetscTryMethod(A,"MatISStoreL2L_C",(Mat,PetscBool),(A,store));CHKERRQ(ierr);
151875d48cdbSStefano Zampini   PetscFunctionReturn(0);
151975d48cdbSStefano Zampini }
152075d48cdbSStefano Zampini 
152175d48cdbSStefano Zampini static PetscErrorCode MatISStoreL2L_IS(Mat A, PetscBool store)
152275d48cdbSStefano Zampini {
152375d48cdbSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(A->data);
152475d48cdbSStefano Zampini   PetscErrorCode ierr;
152575d48cdbSStefano Zampini 
152675d48cdbSStefano Zampini   PetscFunctionBegin;
152775d48cdbSStefano Zampini   matis->storel2l = store;
152875d48cdbSStefano Zampini   if (!store) {
152975d48cdbSStefano Zampini     ierr = PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",NULL);CHKERRQ(ierr);
153075d48cdbSStefano Zampini   }
153175d48cdbSStefano Zampini   PetscFunctionReturn(0);
153275d48cdbSStefano Zampini }
153375d48cdbSStefano Zampini 
153475d48cdbSStefano Zampini /*@
1535f03112d0SStefano Zampini    MatISFixLocalEmpty - Compress out zero local rows from the local matrices
1536f03112d0SStefano Zampini 
1537f03112d0SStefano Zampini    Collective on MPI_Comm
1538f03112d0SStefano Zampini 
1539f03112d0SStefano Zampini    Input Parameters:
1540f03112d0SStefano Zampini +  A - the matrix
1541f03112d0SStefano Zampini -  fix - the boolean flag
1542f03112d0SStefano Zampini 
1543f03112d0SStefano Zampini    Level: advanced
1544f03112d0SStefano Zampini 
1545f03112d0SStefano Zampini    Notes: When fix is true, new local matrices and l2g maps are generated during the final assembly process.
1546f03112d0SStefano Zampini 
1547f03112d0SStefano Zampini .keywords: matrix
1548f03112d0SStefano Zampini 
1549f03112d0SStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatAssemblyEnd(), MAT_FINAL_ASSEMBLY
1550f03112d0SStefano Zampini @*/
1551f03112d0SStefano Zampini PetscErrorCode  MatISFixLocalEmpty(Mat A, PetscBool fix)
1552f03112d0SStefano Zampini {
1553f03112d0SStefano Zampini   PetscErrorCode ierr;
1554f03112d0SStefano Zampini 
1555f03112d0SStefano Zampini   PetscFunctionBegin;
1556f03112d0SStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
1557f03112d0SStefano Zampini   PetscValidType(A,1);
1558f03112d0SStefano Zampini   PetscValidLogicalCollectiveBool(A,fix,2);
1559f03112d0SStefano Zampini   ierr = PetscTryMethod(A,"MatISFixLocalEmpty_C",(Mat,PetscBool),(A,fix));CHKERRQ(ierr);
1560f03112d0SStefano Zampini   PetscFunctionReturn(0);
1561f03112d0SStefano Zampini }
1562f03112d0SStefano Zampini 
1563f03112d0SStefano Zampini static PetscErrorCode MatISFixLocalEmpty_IS(Mat A, PetscBool fix)
1564f03112d0SStefano Zampini {
1565f03112d0SStefano Zampini   Mat_IS *matis = (Mat_IS*)(A->data);
1566f03112d0SStefano Zampini 
1567f03112d0SStefano Zampini   PetscFunctionBegin;
1568f03112d0SStefano Zampini   matis->locempty = fix;
1569f03112d0SStefano Zampini   PetscFunctionReturn(0);
1570f03112d0SStefano Zampini }
1571f03112d0SStefano Zampini 
1572f03112d0SStefano Zampini /*@
1573a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
1574a88811baSStefano Zampini 
1575a88811baSStefano Zampini    Collective on MPI_Comm
1576a88811baSStefano Zampini 
1577a88811baSStefano Zampini    Input Parameters:
1578a88811baSStefano Zampini +  B - the matrix
1579a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1580a88811baSStefano Zampini            (same value is used for all local rows)
1581a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
1582a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
1583a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
1584a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
1585a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
1586a88811baSStefano Zampini            the diagonal entry even if it is zero.
1587a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1588a88811baSStefano Zampini            submatrix (same value is used for all local rows).
1589a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
1590a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
1591a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
1592a88811baSStefano Zampini            structure. The size of this array is equal to the number
1593a88811baSStefano Zampini            of local rows, i.e 'm'.
1594a88811baSStefano Zampini 
1595a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
1596a88811baSStefano Zampini 
1597a88811baSStefano Zampini    Level: intermediate
1598a88811baSStefano Zampini 
159995452b02SPatrick Sanan    Notes:
160095452b02SPatrick Sanan     This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
1601a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
1602a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
1603a88811baSStefano Zampini 
1604a88811baSStefano Zampini .keywords: matrix
1605a88811baSStefano Zampini 
16063c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
1607a88811baSStefano Zampini @*/
16082e1947a5SStefano Zampini PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
16092e1947a5SStefano Zampini {
16102e1947a5SStefano Zampini   PetscErrorCode ierr;
16112e1947a5SStefano Zampini 
16122e1947a5SStefano Zampini   PetscFunctionBegin;
16132e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
16142e1947a5SStefano Zampini   PetscValidType(B,1);
16152e1947a5SStefano Zampini   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
16162e1947a5SStefano Zampini   PetscFunctionReturn(0);
16172e1947a5SStefano Zampini }
16182e1947a5SStefano Zampini 
1619844bd0d7SStefano Zampini /* this is used by DMDA */
1620844bd0d7SStefano Zampini PETSC_EXTERN PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
16212e1947a5SStefano Zampini {
16222e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
162328f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
16242e1947a5SStefano Zampini   PetscErrorCode ierr;
16252e1947a5SStefano Zampini 
16262e1947a5SStefano Zampini   PetscFunctionBegin;
16276c4ed002SBarry Smith   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
1628cf0a3239SStefano Zampini   ierr = MatISSetUpSF(B);CHKERRQ(ierr);
16294f2d7cafSStefano Zampini 
16304f2d7cafSStefano Zampini   if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz;
16314f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
16324f2d7cafSStefano Zampini 
16334f2d7cafSStefano Zampini   if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz;
16344f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
16354f2d7cafSStefano Zampini 
163628f4e0baSStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
163728f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
163828f4e0baSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
163928f4e0baSStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
16404f2d7cafSStefano Zampini 
16414f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
164228f4e0baSStefano Zampini   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
16430f2f62c7SStefano Zampini #if defined(PETSC_HAVE_HYPRE)
16440f2f62c7SStefano Zampini   ierr = MatHYPRESetPreallocation(matis->A,0,matis->sf_leafdata,0,NULL);CHKERRQ(ierr);
16450f2f62c7SStefano Zampini #endif
16464f2d7cafSStefano Zampini 
16474f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
164828f4e0baSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
16494f2d7cafSStefano Zampini 
16504f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i]-i;
165128f4e0baSStefano Zampini   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
16520f2f62c7SStefano Zampini 
16530f2f62c7SStefano Zampini   /* for other matrix types */
16540f2f62c7SStefano Zampini   ierr = MatSetUp(matis->A);CHKERRQ(ierr);
16552e1947a5SStefano Zampini   PetscFunctionReturn(0);
16562e1947a5SStefano Zampini }
1657b4319ba4SBarry Smith 
16583927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
16593927de2eSStefano Zampini {
16603927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
16613927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
1662ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
16633927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
16643927de2eSStefano Zampini   PetscInt        lrows,lcols;
16653927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
1666f03112d0SStefano Zampini   PetscMPIInt     size;
16673927de2eSStefano Zampini   PetscBool       isdense,issbaij;
16683927de2eSStefano Zampini   PetscErrorCode  ierr;
16693927de2eSStefano Zampini 
16703927de2eSStefano Zampini   PetscFunctionBegin;
1671f03112d0SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRQ(ierr);
16723927de2eSStefano Zampini   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
16733927de2eSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
16743927de2eSStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
16753927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
16763927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1677ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1678ecf5a873SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
16797230de76SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1680ecf5a873SStefano Zampini   } else {
1681ecf5a873SStefano Zampini     global_indices_c = global_indices_r;
1682ecf5a873SStefano Zampini   }
1683ecf5a873SStefano Zampini 
16843927de2eSStefano Zampini   if (issbaij) {
16853927de2eSStefano Zampini     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
16863927de2eSStefano Zampini   }
16873927de2eSStefano Zampini   /*
1688ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
16893927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
16903927de2eSStefano Zampini   */
1691cf0a3239SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
16923927de2eSStefano Zampini   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
16933927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
16943927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
16953927de2eSStefano Zampini   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
16963927de2eSStefano Zampini   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
1697f03112d0SStefano Zampini   for (i=0;i<size;i++) {
16983927de2eSStefano Zampini     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
16993927de2eSStefano Zampini       row_ownership[j] = i;
17003927de2eSStefano Zampini     }
17013927de2eSStefano Zampini   }
17027230de76SStefano Zampini   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
17033927de2eSStefano Zampini 
17043927de2eSStefano Zampini   /*
17053927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
17063927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
17073927de2eSStefano Zampini   */
17083927de2eSStefano Zampini   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
17093927de2eSStefano Zampini   /* preallocation as a MATAIJ */
17103927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
17113927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
171212dfadf8SStefano Zampini       PetscInt owner = row_ownership[global_indices_r[i]];
171312dfadf8SStefano Zampini       for (j=0;j<local_cols;j++) {
1714ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
17153927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
17163927de2eSStefano Zampini           my_dnz[i] += 1;
17173927de2eSStefano Zampini         } else { /* offdiag block */
17183927de2eSStefano Zampini           my_onz[i] += 1;
17193927de2eSStefano Zampini         }
17203927de2eSStefano Zampini       }
17213927de2eSStefano Zampini     }
1722bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
1723bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
1724bb1015c3SStefano Zampini     PetscBool      done;
1725bb1015c3SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1726938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1727bb1015c3SStefano Zampini     jptr = jj;
1728bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
1729bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
1730bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
1731bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
1732bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
1733bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
1734bb1015c3SStefano Zampini           my_dnz[i] += 1;
1735bb1015c3SStefano Zampini         } else { /* offdiag block */
1736bb1015c3SStefano Zampini           my_onz[i] += 1;
1737bb1015c3SStefano Zampini         }
1738bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
1739bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
1740bb1015c3SStefano Zampini           owner = row_ownership[index_col];
1741bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1742bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
1743bb1015c3SStefano Zampini           } else {
1744bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
1745bb1015c3SStefano Zampini           }
1746bb1015c3SStefano Zampini         }
1747bb1015c3SStefano Zampini       }
1748bb1015c3SStefano Zampini     }
1749bb1015c3SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1750938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1751bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
17523927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
17533927de2eSStefano Zampini       const PetscInt *cols;
1754ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
17553927de2eSStefano Zampini       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
17563927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
17573927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
1758ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
17593927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
17603927de2eSStefano Zampini           my_dnz[i] += 1;
17613927de2eSStefano Zampini         } else { /* offdiag block */
17623927de2eSStefano Zampini           my_onz[i] += 1;
17633927de2eSStefano Zampini         }
17643927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
1765d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
17663927de2eSStefano Zampini           owner = row_ownership[index_col];
17673927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1768d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
17693927de2eSStefano Zampini           } else {
1770d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
17713927de2eSStefano Zampini           }
17723927de2eSStefano Zampini         }
17733927de2eSStefano Zampini       }
17743927de2eSStefano Zampini       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
17753927de2eSStefano Zampini     }
17763927de2eSStefano Zampini   }
1777ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
17787230de76SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1779ecf5a873SStefano Zampini   }
17804f619741Sstefano_zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
17813927de2eSStefano Zampini   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
1782ecf5a873SStefano Zampini 
1783ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
17843927de2eSStefano Zampini   if (maxreduce) {
17853927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
17863927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
1787bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
17883927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
17893927de2eSStefano Zampini   } else {
17903927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
17913927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
1792bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
17933927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
17943927de2eSStefano Zampini   }
17953927de2eSStefano Zampini   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
17963927de2eSStefano Zampini 
1797*53b44cf5SStefano Zampini 
1798*53b44cf5SStefano Zampini 
17993927de2eSStefano Zampini   /* Resize preallocation if overestimated */
18003927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
18013927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
18023927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
18033927de2eSStefano Zampini   }
18041670daf9Sstefano_zampini 
18051670daf9Sstefano_zampini   /* Set preallocation */
1806268753edSStefano Zampini   ierr = MatSeqAIJSetPreallocation(B,0,dnz);CHKERRQ(ierr);
18073927de2eSStefano Zampini   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
1808*53b44cf5SStefano Zampini   for (i=0;i<lrows;i+=bs) {
1809*53b44cf5SStefano Zampini     PetscInt b, d = dnz[i],o = onz[i];
1810*53b44cf5SStefano Zampini 
1811*53b44cf5SStefano Zampini     for (b=1;b<bs;b++) {
1812*53b44cf5SStefano Zampini       d = PetscMax(d,dnz[i+b]);
1813*53b44cf5SStefano Zampini       o = PetscMax(o,onz[i+b]);
1814*53b44cf5SStefano Zampini     }
1815*53b44cf5SStefano Zampini     dnz[i/bs] = PetscMin(d/bs + d%bs,lcols/bs);
1816*53b44cf5SStefano Zampini     onz[i/bs] = PetscMin(o/bs + o%bs,(cols-lcols)/bs);
18173927de2eSStefano Zampini   }
1818268753edSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(B,bs,0,dnz);CHKERRQ(ierr);
18193927de2eSStefano Zampini   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
18203927de2eSStefano Zampini   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
18213927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
18223927de2eSStefano Zampini   if (issbaij) {
18233927de2eSStefano Zampini     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
18243927de2eSStefano Zampini   }
18259be90c3fSStefano Zampini   ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
18263927de2eSStefano Zampini   PetscFunctionReturn(0);
18273927de2eSStefano Zampini }
18283927de2eSStefano Zampini 
1829487b449aSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_IS_XAIJ(Mat mat, MatType mtype, MatReuse reuse, Mat *M)
1830b7ce53b6SStefano Zampini {
1831b7ce53b6SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1832487b449aSStefano Zampini   Mat            local_mat,MT;
1833b7ce53b6SStefano Zampini   /* info on mat */
1834*53b44cf5SStefano Zampini   PetscInt       rbs,cbs,rows,cols,lrows,lcols;
1835b7ce53b6SStefano Zampini   PetscInt       local_rows,local_cols;
1836b9ed4604SStefano Zampini   PetscBool      isseqdense,isseqsbaij,isseqaij,isseqbaij;
1837b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1838b9ed4604SStefano Zampini   PetscBool      lb[4],bb[4];
1839b9ed4604SStefano Zampini #endif
1840f03112d0SStefano Zampini   PetscMPIInt    size;
1841b7ce53b6SStefano Zampini   /* values insertion */
1842b7ce53b6SStefano Zampini   PetscScalar    *array;
1843b7ce53b6SStefano Zampini   /* work */
1844b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1845b7ce53b6SStefano Zampini 
1846b7ce53b6SStefano Zampini   PetscFunctionBegin;
1847b7ce53b6SStefano Zampini   /* get info from mat */
1848f03112d0SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
1849f03112d0SStefano Zampini   if (size == 1 && mat->rmap->N == matis->A->rmap->N && mat->cmap->N == matis->A->cmap->N) {
18501670daf9Sstefano_zampini     Mat      B;
1851*53b44cf5SStefano Zampini     IS       irows = NULL,icols = NULL;
1852487b449aSStefano Zampini     PetscInt rbs,cbs;
18531670daf9Sstefano_zampini 
1854487b449aSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr);
1855487b449aSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr);
1856*53b44cf5SStefano Zampini     if (reuse != MAT_REUSE_MATRIX) { /* check if l2g maps are one-to-one */
1857*53b44cf5SStefano Zampini       IS             rows,cols;
1858*53b44cf5SStefano Zampini       const PetscInt *ridxs,*cidxs;
1859*53b44cf5SStefano Zampini       PetscInt       i,nw,*work;
1860*53b44cf5SStefano Zampini 
1861*53b44cf5SStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
1862*53b44cf5SStefano Zampini       ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&nw);CHKERRQ(ierr);
1863*53b44cf5SStefano Zampini       nw   = nw/rbs;
1864*53b44cf5SStefano Zampini       ierr = PetscCalloc1(nw,&work);CHKERRQ(ierr);
1865*53b44cf5SStefano Zampini       for (i=0;i<nw;i++) work[ridxs[i]] += 1;
1866*53b44cf5SStefano Zampini       for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break;
1867*53b44cf5SStefano Zampini       if (i == nw) {
1868*53b44cf5SStefano Zampini         ierr = ISCreateBlock(PETSC_COMM_SELF,rbs,nw,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
1869acdf38a7Sstefano_zampini         ierr = ISSetPermutation(rows);CHKERRQ(ierr);
1870*53b44cf5SStefano Zampini         ierr = ISInvertPermutation(rows,PETSC_DECIDE,&irows);CHKERRQ(ierr);
1871acdf38a7Sstefano_zampini         ierr = ISDestroy(&rows);CHKERRQ(ierr);
1872*53b44cf5SStefano Zampini       }
1873*53b44cf5SStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
1874*53b44cf5SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
1875*53b44cf5SStefano Zampini       if (irows && mat->rmap->mapping != mat->cmap->mapping) {
1876*53b44cf5SStefano Zampini         ierr = ISLocalToGlobalMappingGetBlockIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
1877*53b44cf5SStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(mat->cmap->mapping,&nw);CHKERRQ(ierr);
1878*53b44cf5SStefano Zampini         nw   = nw/cbs;
1879*53b44cf5SStefano Zampini         ierr = PetscCalloc1(nw,&work);CHKERRQ(ierr);
1880*53b44cf5SStefano Zampini         for (i=0;i<nw;i++) work[cidxs[i]] += 1;
1881*53b44cf5SStefano Zampini         for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break;
1882*53b44cf5SStefano Zampini         if (i == nw) {
1883*53b44cf5SStefano Zampini           ierr = ISCreateBlock(PETSC_COMM_SELF,cbs,nw,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
1884*53b44cf5SStefano Zampini           ierr = ISSetPermutation(cols);CHKERRQ(ierr);
1885*53b44cf5SStefano Zampini           ierr = ISInvertPermutation(cols,PETSC_DECIDE,&icols);CHKERRQ(ierr);
1886*53b44cf5SStefano Zampini           ierr = ISDestroy(&cols);CHKERRQ(ierr);
1887*53b44cf5SStefano Zampini         }
1888*53b44cf5SStefano Zampini         ierr = ISLocalToGlobalMappingRestoreBlockIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
1889*53b44cf5SStefano Zampini         ierr = PetscFree(work);CHKERRQ(ierr);
1890*53b44cf5SStefano Zampini       } else if (irows) {
1891*53b44cf5SStefano Zampini         ierr  = PetscObjectReference((PetscObject)irows);CHKERRQ(ierr);
1892*53b44cf5SStefano Zampini         icols = irows;
1893*53b44cf5SStefano Zampini       }
1894*53b44cf5SStefano Zampini     } else {
1895*53b44cf5SStefano Zampini       ierr = PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject*)&irows);CHKERRQ(ierr);
1896*53b44cf5SStefano Zampini       ierr = PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject*)&icols);CHKERRQ(ierr);
1897*53b44cf5SStefano Zampini       if (irows) { ierr = PetscObjectReference((PetscObject)irows);CHKERRQ(ierr); }
1898*53b44cf5SStefano Zampini       if (icols) { ierr = PetscObjectReference((PetscObject)icols);CHKERRQ(ierr); }
1899*53b44cf5SStefano Zampini     }
1900*53b44cf5SStefano Zampini     if (!irows || !icols) {
1901*53b44cf5SStefano Zampini       ierr = ISDestroy(&icols);CHKERRQ(ierr);
1902*53b44cf5SStefano Zampini       ierr = ISDestroy(&irows);CHKERRQ(ierr);
1903*53b44cf5SStefano Zampini       goto general_assembly;
1904*53b44cf5SStefano Zampini     }
1905487b449aSStefano Zampini     ierr = MatConvert(matis->A,(rbs == cbs && rbs > 1) ? MATSEQBAIJ : MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
1906487b449aSStefano Zampini     if (reuse != MAT_INPLACE_MATRIX) {
19077dae84e0SHong Zhang       ierr = MatCreateSubMatrix(B,irows,icols,reuse,M);CHKERRQ(ierr);
1908*53b44cf5SStefano Zampini       ierr = PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject)irows);CHKERRQ(ierr);
1909*53b44cf5SStefano Zampini       ierr = PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject)icols);CHKERRQ(ierr);
1910487b449aSStefano Zampini     } else {
1911487b449aSStefano Zampini       Mat C;
1912487b449aSStefano Zampini 
1913487b449aSStefano Zampini       ierr = MatCreateSubMatrix(B,irows,icols,MAT_INITIAL_MATRIX,&C);CHKERRQ(ierr);
1914487b449aSStefano Zampini       ierr = MatHeaderReplace(mat,&C);CHKERRQ(ierr);
1915487b449aSStefano Zampini     }
1916acdf38a7Sstefano_zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
1917acdf38a7Sstefano_zampini     ierr = ISDestroy(&icols);CHKERRQ(ierr);
1918acdf38a7Sstefano_zampini     ierr = ISDestroy(&irows);CHKERRQ(ierr);
19197c03b4e8SStefano Zampini     PetscFunctionReturn(0);
19207c03b4e8SStefano Zampini   }
1921*53b44cf5SStefano Zampini general_assembly:
1922b7ce53b6SStefano Zampini   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
1923*53b44cf5SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr);
1924*53b44cf5SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr);
19253cfa4ea4SStefano Zampini   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
1926b7ce53b6SStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
1927b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
19284099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
1929b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
1930b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij);CHKERRQ(ierr);
1931b9ed4604SStefano Zampini   if (!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name);
1932b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1933b9ed4604SStefano Zampini   lb[0] = isseqdense;
1934b9ed4604SStefano Zampini   lb[1] = isseqaij;
1935b9ed4604SStefano Zampini   lb[2] = isseqbaij;
1936b9ed4604SStefano Zampini   lb[3] = isseqsbaij;
1937b9ed4604SStefano Zampini   ierr = MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
1938b9ed4604SStefano Zampini   if (!bb[0] && !bb[1] && !bb[2] && !bb[3]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type");
1939b9ed4604SStefano Zampini #endif
1940b7ce53b6SStefano Zampini 
1941487b449aSStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
1942487b449aSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)mat),&MT);CHKERRQ(ierr);
1943487b449aSStefano Zampini     ierr = MatSetSizes(MT,lrows,lcols,rows,cols);CHKERRQ(ierr);
1944487b449aSStefano Zampini     ierr = MatSetType(MT,mtype);CHKERRQ(ierr);
1945*53b44cf5SStefano Zampini     ierr = MatSetBlockSizes(MT,rbs,cbs);CHKERRQ(ierr);
1946487b449aSStefano Zampini     ierr = MatISSetMPIXAIJPreallocation_Private(mat,MT,PETSC_FALSE);CHKERRQ(ierr);
1947b7ce53b6SStefano Zampini   } else {
1948*53b44cf5SStefano Zampini     PetscInt mrbs,mcbs,mrows,mcols,mlrows,mlcols;
1949487b449aSStefano Zampini 
1950b7ce53b6SStefano Zampini     /* some checks */
1951487b449aSStefano Zampini     MT   = *M;
1952*53b44cf5SStefano Zampini     ierr = MatGetBlockSizes(MT,&mrbs,&mcbs);CHKERRQ(ierr);
1953487b449aSStefano Zampini     ierr = MatGetSize(MT,&mrows,&mcols);CHKERRQ(ierr);
1954487b449aSStefano Zampini     ierr = MatGetLocalSize(MT,&mlrows,&mlcols);CHKERRQ(ierr);
19556c4ed002SBarry Smith     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
19566c4ed002SBarry Smith     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
19576c4ed002SBarry Smith     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
19586c4ed002SBarry Smith     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
1959*53b44cf5SStefano Zampini     if (mrbs != rbs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong row block size (%d != %d)",rbs,mrbs);
1960*53b44cf5SStefano Zampini     if (mcbs != cbs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong col block size (%d != %d)",cbs,mcbs);
1961487b449aSStefano Zampini     ierr = MatZeroEntries(MT);CHKERRQ(ierr);
1962b7ce53b6SStefano Zampini   }
1963d9a9e74cSStefano Zampini 
1964b9ed4604SStefano Zampini   if (isseqsbaij) {
1965d9a9e74cSStefano Zampini     ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
1966d9a9e74cSStefano Zampini   } else {
1967d9a9e74cSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
1968d9a9e74cSStefano Zampini     local_mat = matis->A;
1969d9a9e74cSStefano Zampini   }
1970686e3a49SStefano Zampini 
1971b7ce53b6SStefano Zampini   /* Set values */
1972487b449aSStefano Zampini   ierr = MatSetLocalToGlobalMapping(MT,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
1973b9ed4604SStefano Zampini   if (isseqdense) { /* special case for dense local matrices */
197465066ba5SStefano Zampini     PetscInt i,*dummy;
1975ecf5a873SStefano Zampini 
197665066ba5SStefano Zampini     ierr = PetscMalloc1(PetscMax(local_rows,local_cols),&dummy);CHKERRQ(ierr);
197765066ba5SStefano Zampini     for (i=0;i<PetscMax(local_rows,local_cols);i++) dummy[i] = i;
1978487b449aSStefano Zampini     ierr = MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1979d9a9e74cSStefano Zampini     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
1980487b449aSStefano Zampini     ierr = MatSetValuesLocal(MT,local_rows,dummy,local_cols,dummy,array,ADD_VALUES);CHKERRQ(ierr);
1981d9a9e74cSStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
198265066ba5SStefano Zampini     ierr = PetscFree(dummy);CHKERRQ(ierr);
1983686e3a49SStefano Zampini   } else if (isseqaij) {
1984ecf5a873SStefano Zampini     PetscInt  i,nvtxs,*xadj,*adjncy;
1985686e3a49SStefano Zampini     PetscBool done;
1986686e3a49SStefano Zampini 
1987d9a9e74cSStefano Zampini     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1988938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1989d9a9e74cSStefano Zampini     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
1990686e3a49SStefano Zampini     for (i=0;i<nvtxs;i++) {
1991487b449aSStefano Zampini       ierr = MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
1992686e3a49SStefano Zampini     }
1993d9a9e74cSStefano Zampini     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1994938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1995d9a9e74cSStefano Zampini     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
1996686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
1997ecf5a873SStefano Zampini     PetscInt i;
1998c0962df8SStefano Zampini 
1999686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
2000686e3a49SStefano Zampini       PetscInt       j;
2001ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
2002686e3a49SStefano Zampini 
2003ecf5a873SStefano Zampini       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
2004487b449aSStefano Zampini       ierr = MatSetValuesLocal(MT,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
2005ecf5a873SStefano Zampini       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
2006686e3a49SStefano Zampini     }
2007b7ce53b6SStefano Zampini   }
2008487b449aSStefano Zampini   ierr = MatAssemblyBegin(MT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2009d9a9e74cSStefano Zampini   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
2010487b449aSStefano Zampini   ierr = MatAssemblyEnd(MT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2011b9ed4604SStefano Zampini   if (isseqdense) {
2012487b449aSStefano Zampini     ierr = MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
2013487b449aSStefano Zampini   }
2014487b449aSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
2015487b449aSStefano Zampini     ierr = MatHeaderReplace(mat,&MT);CHKERRQ(ierr);
2016487b449aSStefano Zampini   } else if (reuse == MAT_INITIAL_MATRIX) {
2017487b449aSStefano Zampini     *M = MT;
2018b7ce53b6SStefano Zampini   }
2019b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
2020b7ce53b6SStefano Zampini }
2021b7ce53b6SStefano Zampini 
2022b7ce53b6SStefano Zampini /*@
2023b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
2024b7ce53b6SStefano Zampini 
2025b7ce53b6SStefano Zampini   Input Parameter:
2026b7ce53b6SStefano Zampini .  mat - the matrix (should be of type MATIS)
2027b7ce53b6SStefano Zampini .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
2028b7ce53b6SStefano Zampini 
2029b7ce53b6SStefano Zampini   Output Parameter:
2030b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
2031b7ce53b6SStefano Zampini 
2032b7ce53b6SStefano Zampini   Level: developer
2033b7ce53b6SStefano Zampini 
203495452b02SPatrick Sanan   Notes:
2035487b449aSStefano Zampini     This function has been deprecated and it will be removed in future releases. Update your code to use the MatConvert() interface.
2036b7ce53b6SStefano Zampini 
2037487b449aSStefano Zampini .seealso: MATIS, MatConvert()
2038b7ce53b6SStefano Zampini @*/
2039b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
2040b7ce53b6SStefano Zampini {
2041b7ce53b6SStefano Zampini   PetscErrorCode ierr;
2042b7ce53b6SStefano Zampini 
2043b7ce53b6SStefano Zampini   PetscFunctionBegin;
2044b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2045b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
2046b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
2047487b449aSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
2048b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
2049b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
20506c4ed002SBarry Smith     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
2051b7ce53b6SStefano Zampini   }
2052487b449aSStefano Zampini   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatType,MatReuse,Mat*),(mat,MATAIJ,reuse,newmat));CHKERRQ(ierr);
2053b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
2054b7ce53b6SStefano Zampini }
2055b7ce53b6SStefano Zampini 
2056ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
2057ad6194a2SStefano Zampini {
2058ad6194a2SStefano Zampini   PetscErrorCode ierr;
2059ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
2060c9225affSStefano Zampini   PetscInt       rbs,cbs,m,n,M,N;
2061ad6194a2SStefano Zampini   Mat            B,localmat;
2062ad6194a2SStefano Zampini 
2063ad6194a2SStefano Zampini   PetscFunctionBegin;
2064c9225affSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr);
2065c9225affSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr);
2066ad6194a2SStefano Zampini   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
2067ad6194a2SStefano Zampini   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
2068c9225affSStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),rbs == cbs ? rbs : 1,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr);
2069ad6194a2SStefano Zampini   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
2070ad6194a2SStefano Zampini   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
2071b3317aa8SStefano Zampini   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
2072b0f2910eSStefano Zampini   if (matis->sf) {
2073b0f2910eSStefano Zampini     Mat_IS *bmatis = (Mat_IS*)(B->data);
2074b0f2910eSStefano Zampini 
2075b0f2910eSStefano Zampini     ierr       = PetscObjectReference((PetscObject)matis->sf);CHKERRQ(ierr);
2076b0f2910eSStefano Zampini     bmatis->sf = matis->sf;
2077b0f2910eSStefano Zampini     ierr       = PetscMalloc2(matis->sf->nroots,&bmatis->sf_rootdata,matis->sf->nleaves,&bmatis->sf_leafdata);CHKERRQ(ierr);
2078b0f2910eSStefano Zampini     if (matis->sf != matis->csf) {
2079b0f2910eSStefano Zampini       ierr        = PetscObjectReference((PetscObject)matis->csf);CHKERRQ(ierr);
2080b0f2910eSStefano Zampini       bmatis->csf = matis->csf;
2081b0f2910eSStefano Zampini       ierr        = PetscMalloc2(matis->csf->nroots,&bmatis->csf_rootdata,matis->csf->nleaves,&bmatis->csf_leafdata);CHKERRQ(ierr);
2082b0f2910eSStefano Zampini     } else {
2083b0f2910eSStefano Zampini       bmatis->csf          = bmatis->sf;
2084b0f2910eSStefano Zampini       bmatis->csf_leafdata = bmatis->sf_leafdata;
2085b0f2910eSStefano Zampini       bmatis->csf_rootdata = bmatis->sf_rootdata;
2086b0f2910eSStefano Zampini     }
2087b0f2910eSStefano Zampini   }
2088ad6194a2SStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2089ad6194a2SStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2090ad6194a2SStefano Zampini   *newmat = B;
2091ad6194a2SStefano Zampini   PetscFunctionReturn(0);
2092ad6194a2SStefano Zampini }
2093ad6194a2SStefano Zampini 
2094a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
209569796d55SStefano Zampini {
209669796d55SStefano Zampini   PetscErrorCode ierr;
209769796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
209869796d55SStefano Zampini   PetscBool      local_sym;
209969796d55SStefano Zampini 
210069796d55SStefano Zampini   PetscFunctionBegin;
210169796d55SStefano Zampini   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
2102b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
210369796d55SStefano Zampini   PetscFunctionReturn(0);
210469796d55SStefano Zampini }
210569796d55SStefano Zampini 
2106a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
210769796d55SStefano Zampini {
210869796d55SStefano Zampini   PetscErrorCode ierr;
210969796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
211069796d55SStefano Zampini   PetscBool      local_sym;
211169796d55SStefano Zampini 
211269796d55SStefano Zampini   PetscFunctionBegin;
211369796d55SStefano Zampini   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
2114b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
211569796d55SStefano Zampini   PetscFunctionReturn(0);
211669796d55SStefano Zampini }
211769796d55SStefano Zampini 
211845471136SStefano Zampini static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool  *flg)
211945471136SStefano Zampini {
212045471136SStefano Zampini   PetscErrorCode ierr;
212145471136SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
212245471136SStefano Zampini   PetscBool      local_sym;
212345471136SStefano Zampini 
212445471136SStefano Zampini   PetscFunctionBegin;
212545471136SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
212645471136SStefano Zampini     *flg = PETSC_FALSE;
212745471136SStefano Zampini     PetscFunctionReturn(0);
212845471136SStefano Zampini   }
212945471136SStefano Zampini   ierr = MatIsStructurallySymmetric(matis->A,&local_sym);CHKERRQ(ierr);
213045471136SStefano Zampini   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
213145471136SStefano Zampini   PetscFunctionReturn(0);
213245471136SStefano Zampini }
213345471136SStefano Zampini 
2134a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
2135b4319ba4SBarry Smith {
2136dfbe8321SBarry Smith   PetscErrorCode ierr;
2137b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
2138b4319ba4SBarry Smith 
2139b4319ba4SBarry Smith   PetscFunctionBegin;
21406bf464f9SBarry Smith   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
2141e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
2142e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
21436bf464f9SBarry Smith   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
21446bf464f9SBarry Smith   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
21453fd1c9e7SStefano Zampini   ierr = VecDestroy(&b->counter);CHKERRQ(ierr);
2146a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
2147a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
2148a8116848SStefano Zampini   if (b->sf != b->csf) {
2149a8116848SStefano Zampini     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
2150a8116848SStefano Zampini     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
2151f03112d0SStefano Zampini   } else b->csf = NULL;
215228f4e0baSStefano Zampini   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
215328f4e0baSStefano Zampini   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
2154bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
2155dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
2156bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
2157b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
2158b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
21592e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
2160cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",NULL);CHKERRQ(ierr);
216175d48cdbSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",NULL);CHKERRQ(ierr);
2162f03112d0SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",NULL);CHKERRQ(ierr);
2163487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",NULL);CHKERRQ(ierr);
2164487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",NULL);CHKERRQ(ierr);
2165487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",NULL);CHKERRQ(ierr);
2166487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",NULL);CHKERRQ(ierr);
2167487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",NULL);CHKERRQ(ierr);
2168487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",NULL);CHKERRQ(ierr);
2169487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",NULL);CHKERRQ(ierr);
2170b4319ba4SBarry Smith   PetscFunctionReturn(0);
2171b4319ba4SBarry Smith }
2172b4319ba4SBarry Smith 
2173a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
2174b4319ba4SBarry Smith {
2175dfbe8321SBarry Smith   PetscErrorCode ierr;
2176b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
2177b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
2178b4319ba4SBarry Smith 
2179b4319ba4SBarry Smith   PetscFunctionBegin;
2180b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
2181e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2182e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2183b4319ba4SBarry Smith 
2184b4319ba4SBarry Smith   /* multiply the local matrix */
2185b4319ba4SBarry Smith   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
2186b4319ba4SBarry Smith 
2187b4319ba4SBarry Smith   /* scatter product back into global memory */
21882dcb1b2aSMatthew Knepley   ierr = VecSet(y,zero);CHKERRQ(ierr);
2189e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2190e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2191b4319ba4SBarry Smith   PetscFunctionReturn(0);
2192b4319ba4SBarry Smith }
2193b4319ba4SBarry Smith 
2194a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
21952e74eeadSLisandro Dalcin {
2196650997f4SStefano Zampini   Vec            temp_vec;
21972e74eeadSLisandro Dalcin   PetscErrorCode ierr;
21982e74eeadSLisandro Dalcin 
21992e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
2200650997f4SStefano Zampini   if (v3 != v2) {
2201650997f4SStefano Zampini     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
2202650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
2203650997f4SStefano Zampini   } else {
2204650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
2205650997f4SStefano Zampini     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
2206650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
2207650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
2208650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
2209650997f4SStefano Zampini   }
22102e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
22112e74eeadSLisandro Dalcin }
22122e74eeadSLisandro Dalcin 
2213a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
22142e74eeadSLisandro Dalcin {
22152e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
22162e74eeadSLisandro Dalcin   PetscErrorCode ierr;
22172e74eeadSLisandro Dalcin 
2218e176bc59SStefano Zampini   PetscFunctionBegin;
22192e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
2220e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2221e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
22222e74eeadSLisandro Dalcin 
22232e74eeadSLisandro Dalcin   /* multiply the local matrix */
2224e176bc59SStefano Zampini   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
22252e74eeadSLisandro Dalcin 
22262e74eeadSLisandro Dalcin   /* scatter product back into global vector */
2227e176bc59SStefano Zampini   ierr = VecSet(x,0);CHKERRQ(ierr);
2228e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2229e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
22302e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
22312e74eeadSLisandro Dalcin }
22322e74eeadSLisandro Dalcin 
2233a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
22342e74eeadSLisandro Dalcin {
2235650997f4SStefano Zampini   Vec            temp_vec;
22362e74eeadSLisandro Dalcin   PetscErrorCode ierr;
22372e74eeadSLisandro Dalcin 
22382e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
2239650997f4SStefano Zampini   if (v3 != v2) {
2240650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
2241650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
2242650997f4SStefano Zampini   } else {
2243650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
2244650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
2245650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
2246650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
2247650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
2248650997f4SStefano Zampini   }
22492e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
22502e74eeadSLisandro Dalcin }
22512e74eeadSLisandro Dalcin 
2252a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
2253b4319ba4SBarry Smith {
2254b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
2255dfbe8321SBarry Smith   PetscErrorCode ierr;
2256b4319ba4SBarry Smith   PetscViewer    sviewer;
2257ee2491ecSStefano Zampini   PetscBool      isascii,view = PETSC_TRUE;
2258b4319ba4SBarry Smith 
2259b4319ba4SBarry Smith   PetscFunctionBegin;
2260ee2491ecSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
2261ee2491ecSStefano Zampini   if (isascii)  {
2262ee2491ecSStefano Zampini     PetscViewerFormat format;
2263ee2491ecSStefano Zampini 
2264ee2491ecSStefano Zampini     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
2265ee2491ecSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE;
2266ee2491ecSStefano Zampini   }
2267ee2491ecSStefano Zampini   if (!view) PetscFunctionReturn(0);
22683f08860eSBarry Smith   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
2269b4319ba4SBarry Smith   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
22703f08860eSBarry Smith   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
22716e520ac8SStefano Zampini   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2272b4319ba4SBarry Smith   PetscFunctionReturn(0);
2273b4319ba4SBarry Smith }
2274b4319ba4SBarry Smith 
2275a8116848SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
2276b4319ba4SBarry Smith {
2277dfbe8321SBarry Smith   PetscErrorCode ierr;
2278e176bc59SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
2279b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2280e176bc59SStefano Zampini   Vec            cglobal,rglobal;
2281b4319ba4SBarry Smith 
2282b4319ba4SBarry Smith   PetscFunctionBegin;
2283784ac674SJed Brown   PetscCheckSameComm(A,1,rmapping,2);
2284e176bc59SStefano Zampini   PetscCheckSameComm(A,1,cmapping,3);
22853bbff08aSStefano Zampini   /* Destroy any previous data */
228670cf5478SStefano Zampini   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
228770cf5478SStefano Zampini   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
22883fd1c9e7SStefano Zampini   ierr = VecDestroy(&is->counter);CHKERRQ(ierr);
2289e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
2290e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
22911c47cb0fSStefano Zampini   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
2292872cf891SStefano Zampini   if (is->csf != is->sf) {
2293872cf891SStefano Zampini     ierr = PetscSFDestroy(&is->csf);CHKERRQ(ierr);
2294872cf891SStefano Zampini     ierr = PetscFree2(is->csf_rootdata,is->csf_leafdata);CHKERRQ(ierr);
2295f03112d0SStefano Zampini   } else is->csf = NULL;
229628f4e0baSStefano Zampini   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
229728f4e0baSStefano Zampini   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
22983bbff08aSStefano Zampini 
22993bbff08aSStefano Zampini   /* Setup Layout and set local to global maps */
2300fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
2301fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
2302e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
2303e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
2304e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
2305e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
23066625354bSStefano Zampini   /* check if the two mappings are actually the same for square matrices (DOLFIN passes 2 different objects) */
23076625354bSStefano Zampini   if (rmapping != cmapping && A->rmap->N == A->cmap->N) {
23086625354bSStefano Zampini     PetscBool same,gsame;
23096625354bSStefano Zampini 
23106625354bSStefano Zampini     same = PETSC_FALSE;
23116625354bSStefano Zampini     if (nr == nc && cbs == rbs) {
23126625354bSStefano Zampini       const PetscInt *idxs1,*idxs2;
23136625354bSStefano Zampini 
23146625354bSStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(rmapping,&idxs1);CHKERRQ(ierr);
23156625354bSStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(cmapping,&idxs2);CHKERRQ(ierr);
23166625354bSStefano Zampini       ierr = PetscMemcmp(idxs1,idxs2,(nr/rbs)*sizeof(PetscInt),&same);CHKERRQ(ierr);
23176625354bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(rmapping,&idxs1);CHKERRQ(ierr);
23186625354bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(cmapping,&idxs2);CHKERRQ(ierr);
23196625354bSStefano Zampini     }
23206625354bSStefano Zampini     ierr = MPIU_Allreduce(&same,&gsame,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
23216625354bSStefano Zampini     if (gsame) cmapping = rmapping;
23226625354bSStefano Zampini   }
2323*53b44cf5SStefano Zampini   ierr = PetscLayoutSetBlockSize(A->rmap,rbs);CHKERRQ(ierr);
2324*53b44cf5SStefano Zampini   ierr = PetscLayoutSetBlockSize(A->cmap,cbs);CHKERRQ(ierr);
23256625354bSStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
23266625354bSStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
23276625354bSStefano Zampini 
23286625354bSStefano Zampini   /* Create the local matrix A */
2329f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
2330e176bc59SStefano Zampini   ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr);
2331e176bc59SStefano Zampini   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
2332e176bc59SStefano Zampini   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
2333ff130e51SJed Brown   ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
2334ff130e51SJed Brown   ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
2335b4319ba4SBarry Smith   ierr = MatSetFromOptions(is->A);CHKERRQ(ierr);
2336c77832edSStefano Zampini   ierr = PetscLayoutSetUp(is->A->rmap);CHKERRQ(ierr);
2337c77832edSStefano Zampini   ierr = PetscLayoutSetUp(is->A->cmap);CHKERRQ(ierr);
2338b4319ba4SBarry Smith 
2339f26d0771SStefano Zampini   if (!is->islocalref) { /* setup scatters and local vectors for MatMult */
2340*53b44cf5SStefano Zampini     IS             from;
2341*53b44cf5SStefano Zampini     const PetscInt *garray;
2342*53b44cf5SStefano Zampini 
2343b4319ba4SBarry Smith     /* Create the local work vectors */
23443bbff08aSStefano Zampini     ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
2345b4319ba4SBarry Smith 
2346e176bc59SStefano Zampini     /* setup the global to local scatters */
2347e176bc59SStefano Zampini     ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
2348*53b44cf5SStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockIndices(rmapping,&garray);CHKERRQ(ierr);
2349*53b44cf5SStefano Zampini     ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),rbs,nr/rbs,garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
2350*53b44cf5SStefano Zampini     ierr = VecScatterCreate(rglobal,from,is->y,NULL,&is->rctx);CHKERRQ(ierr);
2351*53b44cf5SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreBlockIndices(rmapping,&garray);CHKERRQ(ierr);
2352e176bc59SStefano Zampini     ierr = ISDestroy(&from);CHKERRQ(ierr);
2353*53b44cf5SStefano Zampini     if (rmapping != cmapping) {
2354*53b44cf5SStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(cmapping,&garray);CHKERRQ(ierr);
2355*53b44cf5SStefano Zampini       ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),cbs,nc/cbs,garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
2356*53b44cf5SStefano Zampini       ierr = VecScatterCreate(cglobal,from,is->x,NULL,&is->cctx);CHKERRQ(ierr);
2357*53b44cf5SStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(cmapping,&garray);CHKERRQ(ierr);
2358*53b44cf5SStefano Zampini       ierr = ISDestroy(&from);CHKERRQ(ierr);
2359e176bc59SStefano Zampini     } else {
2360e176bc59SStefano Zampini       ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
2361e176bc59SStefano Zampini       is->cctx = is->rctx;
2362e176bc59SStefano Zampini     }
23633fd1c9e7SStefano Zampini 
23643fd1c9e7SStefano Zampini     /* interface counter vector (local) */
23653fd1c9e7SStefano Zampini     ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr);
23663fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
23673fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
23683fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
23693fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
23703fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
23713fd1c9e7SStefano Zampini 
23723fd1c9e7SStefano Zampini     /* free workspace */
2373e176bc59SStefano Zampini     ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
2374e176bc59SStefano Zampini     ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
23756bf464f9SBarry Smith     ierr = ISDestroy(&from);CHKERRQ(ierr);
2376f26d0771SStefano Zampini   }
237748ff6bf3SStefano Zampini   ierr = MatSetUp(A);CHKERRQ(ierr);
2378b4319ba4SBarry Smith   PetscFunctionReturn(0);
2379b4319ba4SBarry Smith }
2380b4319ba4SBarry Smith 
2381a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
23822e74eeadSLisandro Dalcin {
23832e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
23842e74eeadSLisandro Dalcin   PetscErrorCode ierr;
238597563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
238697563a80SStefano Zampini   PetscInt       i,zm,zn;
238797563a80SStefano Zampini #endif
2388f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
23892e74eeadSLisandro Dalcin 
23902e74eeadSLisandro Dalcin   PetscFunctionBegin;
23912e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG)
2392f26d0771SStefano 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);
239397563a80SStefano Zampini   /* count negative indices */
239497563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
239597563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
23962e74eeadSLisandro Dalcin #endif
239797563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
239897563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
239997563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
240097563a80SStefano Zampini   /* count negative indices (should be the same as before) */
240197563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
240297563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
2403b4f971dfSStefano 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");
2404b4f971dfSStefano 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");
240597563a80SStefano Zampini #endif
24062e74eeadSLisandro Dalcin   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
24072e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
24082e74eeadSLisandro Dalcin }
24092e74eeadSLisandro Dalcin 
2410a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
241197563a80SStefano Zampini {
241297563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
241397563a80SStefano Zampini   PetscErrorCode ierr;
241497563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
241597563a80SStefano Zampini   PetscInt       i,zm,zn;
241697563a80SStefano Zampini #endif
2417f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
241897563a80SStefano Zampini 
241997563a80SStefano Zampini   PetscFunctionBegin;
242097563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
2421f26d0771SStefano 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);
242297563a80SStefano Zampini   /* count negative indices */
242397563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
242497563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
242597563a80SStefano Zampini #endif
242697563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
242797563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
242897563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
242997563a80SStefano Zampini   /* count negative indices (should be the same as before) */
243097563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
243197563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
2432b4f971dfSStefano 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");
2433b4f971dfSStefano 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");
243497563a80SStefano Zampini #endif
2435d59cf9ebSStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
243697563a80SStefano Zampini   PetscFunctionReturn(0);
243797563a80SStefano Zampini }
243897563a80SStefano Zampini 
2439a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
2440b4319ba4SBarry Smith {
2441dfbe8321SBarry Smith   PetscErrorCode ierr;
2442b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2443b4319ba4SBarry Smith 
2444b4319ba4SBarry Smith   PetscFunctionBegin;
2445b4f971dfSStefano Zampini   if (is->A->rmap->mapping) {
2446872cf891SStefano Zampini     ierr = MatSetValuesLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2447872cf891SStefano Zampini   } else {
2448b4319ba4SBarry Smith     ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2449872cf891SStefano Zampini   }
2450b4319ba4SBarry Smith   PetscFunctionReturn(0);
2451b4319ba4SBarry Smith }
2452b4319ba4SBarry Smith 
2453a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
2454f0006bf2SLisandro Dalcin {
2455f0006bf2SLisandro Dalcin   PetscErrorCode ierr;
2456f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
2457f0006bf2SLisandro Dalcin 
2458f0006bf2SLisandro Dalcin   PetscFunctionBegin;
2459b4f971dfSStefano Zampini   if (is->A->rmap->mapping) {
2460b4f971dfSStefano Zampini #if defined(PETSC_USE_DEBUG)
2461b4f971dfSStefano Zampini     PetscInt ibs,bs;
2462b4f971dfSStefano Zampini 
2463b4f971dfSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(is->A->rmap->mapping,&ibs);CHKERRQ(ierr);
2464b4f971dfSStefano Zampini     ierr = MatGetBlockSize(is->A,&bs);CHKERRQ(ierr);
2465b4f971dfSStefano Zampini     if (ibs != bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Different block sizes! local mat %D, local l2g map %D",bs,ibs);
2466b4f971dfSStefano Zampini #endif
2467b4f971dfSStefano Zampini     ierr = MatSetValuesBlockedLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2468b4f971dfSStefano Zampini   } else {
2469f0006bf2SLisandro Dalcin     ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2470b4f971dfSStefano Zampini   }
2471f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
2472f0006bf2SLisandro Dalcin }
2473f0006bf2SLisandro Dalcin 
2474f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
2475f0ae7da4SStefano Zampini {
2476f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
2477f0ae7da4SStefano Zampini   PetscErrorCode ierr;
2478f0ae7da4SStefano Zampini 
2479f0ae7da4SStefano Zampini   PetscFunctionBegin;
2480f0ae7da4SStefano Zampini   if (!n) {
2481f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
2482f0ae7da4SStefano Zampini   } else {
2483f0ae7da4SStefano Zampini     PetscInt i;
2484f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
2485f0ae7da4SStefano Zampini 
2486f0ae7da4SStefano Zampini     if (columns) {
2487f0ae7da4SStefano Zampini       ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
2488f0ae7da4SStefano Zampini     } else {
2489f0ae7da4SStefano Zampini       ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
2490f0ae7da4SStefano Zampini     }
2491f0ae7da4SStefano Zampini     if (diag != 0.) {
2492f0ae7da4SStefano Zampini       const PetscScalar *array;
2493f0ae7da4SStefano Zampini       ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr);
2494f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
2495f0ae7da4SStefano Zampini         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
2496f0ae7da4SStefano Zampini       }
2497f0ae7da4SStefano Zampini       ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr);
2498f0ae7da4SStefano Zampini     }
2499f0ae7da4SStefano Zampini     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2500f0ae7da4SStefano Zampini     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2501f0ae7da4SStefano Zampini   }
2502f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
2503f0ae7da4SStefano Zampini }
2504f0ae7da4SStefano Zampini 
2505f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
25062e74eeadSLisandro Dalcin {
25076e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
25086e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
25096e520ac8SStefano Zampini   PetscInt       *lrows;
25102e74eeadSLisandro Dalcin   PetscErrorCode ierr;
25112e74eeadSLisandro Dalcin 
25122e74eeadSLisandro Dalcin   PetscFunctionBegin;
2513f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG)
2514f0ae7da4SStefano Zampini   if (columns || diag != 0. || (x && b)) {
2515f0ae7da4SStefano Zampini     PetscBool cong;
251626b0207aSStefano Zampini 
2517f0ae7da4SStefano Zampini     ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr);
251826b0207aSStefano Zampini     cong = (PetscBool)(cong && matis->sf == matis->csf);
2519268753edSStefano 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");
2520268753edSStefano 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");
2521268753edSStefano 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");
2522f0ae7da4SStefano Zampini   }
2523f0ae7da4SStefano Zampini #endif
25246e520ac8SStefano Zampini   /* get locally owned rows */
2525f0ae7da4SStefano Zampini   ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr);
25266e520ac8SStefano Zampini   /* fix right hand side if needed */
25276e520ac8SStefano Zampini   if (x && b) {
25286e520ac8SStefano Zampini     const PetscScalar *xx;
25296e520ac8SStefano Zampini     PetscScalar       *bb;
25306e520ac8SStefano Zampini 
25316e520ac8SStefano Zampini     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
25326e520ac8SStefano Zampini     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
25336e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
25346e520ac8SStefano Zampini     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
25356e520ac8SStefano Zampini     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
25362e74eeadSLisandro Dalcin   }
25376e520ac8SStefano Zampini   /* get rows associated to the local matrices */
25383d996552SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
25396e520ac8SStefano Zampini   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
25406e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr);
25416e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
25426e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
25436e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
25446e520ac8SStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
25456e520ac8SStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
25466e520ac8SStefano Zampini   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
25476e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
2548f0ae7da4SStefano Zampini   ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr);
25496e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
25502e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
25512e74eeadSLisandro Dalcin }
25522e74eeadSLisandro Dalcin 
2553f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
2554b4319ba4SBarry Smith {
2555dfbe8321SBarry Smith   PetscErrorCode ierr;
2556b4319ba4SBarry Smith 
2557b4319ba4SBarry Smith   PetscFunctionBegin;
2558f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr);
2559f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
2560f0ae7da4SStefano Zampini }
25612205254eSKarl Rupp 
2562f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
2563f0ae7da4SStefano Zampini {
2564f0ae7da4SStefano Zampini   PetscErrorCode ierr;
2565f0ae7da4SStefano Zampini 
2566f0ae7da4SStefano Zampini   PetscFunctionBegin;
2567f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr);
2568b4319ba4SBarry Smith   PetscFunctionReturn(0);
2569b4319ba4SBarry Smith }
2570b4319ba4SBarry Smith 
2571a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
2572b4319ba4SBarry Smith {
2573b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2574dfbe8321SBarry Smith   PetscErrorCode ierr;
2575b4319ba4SBarry Smith 
2576b4319ba4SBarry Smith   PetscFunctionBegin;
2577b4319ba4SBarry Smith   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
2578b4319ba4SBarry Smith   PetscFunctionReturn(0);
2579b4319ba4SBarry Smith }
2580b4319ba4SBarry Smith 
2581a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
2582b4319ba4SBarry Smith {
2583b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2584dfbe8321SBarry Smith   PetscErrorCode ierr;
2585b4319ba4SBarry Smith 
2586b4319ba4SBarry Smith   PetscFunctionBegin;
2587b4319ba4SBarry Smith   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
2588872cf891SStefano Zampini   /* fix for local empty rows/cols */
2589872cf891SStefano Zampini   if (is->locempty && type == MAT_FINAL_ASSEMBLY) {
2590872cf891SStefano Zampini     Mat                    newlA;
2591f03112d0SStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g;
2592f03112d0SStefano Zampini     IS                     nzr,nzc;
2593f03112d0SStefano Zampini     PetscInt               nr,nc,nnzr,nnzc;
2594f03112d0SStefano Zampini     PetscBool              lnewl2g,newl2g;
2595872cf891SStefano Zampini 
2596f03112d0SStefano Zampini     ierr = MatGetSize(is->A,&nr,&nc);CHKERRQ(ierr);
2597f03112d0SStefano Zampini     ierr = MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_FALSE,PETSC_SMALL,&nzr);CHKERRQ(ierr);
2598f03112d0SStefano Zampini     if (!nzr) {
2599f03112d0SStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nr,0,1,&nzr);CHKERRQ(ierr);
2600872cf891SStefano Zampini     }
2601f03112d0SStefano Zampini     ierr = MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_TRUE,PETSC_SMALL,&nzc);CHKERRQ(ierr);
2602f03112d0SStefano Zampini     if (!nzc) {
2603f03112d0SStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nc,0,1,&nzc);CHKERRQ(ierr);
2604872cf891SStefano Zampini     }
2605f03112d0SStefano Zampini     ierr = ISGetSize(nzr,&nnzr);CHKERRQ(ierr);
2606f03112d0SStefano Zampini     ierr = ISGetSize(nzc,&nnzc);CHKERRQ(ierr);
2607f03112d0SStefano Zampini     if (nnzr != nr || nnzc != nc) {
2608f03112d0SStefano Zampini       ISLocalToGlobalMapping l2g;
2609f03112d0SStefano Zampini       IS                     is1,is2;
2610f03112d0SStefano Zampini 
2611f03112d0SStefano Zampini       /* need new global l2g map */
2612f03112d0SStefano Zampini       lnewl2g = PETSC_TRUE;
2613f03112d0SStefano Zampini       ierr    = MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
2614f03112d0SStefano Zampini 
2615872cf891SStefano Zampini       /* extract valid submatrix */
2616f03112d0SStefano Zampini       ierr = MatCreateSubMatrix(is->A,nzr,nzc,MAT_INITIAL_MATRIX,&newlA);CHKERRQ(ierr);
2617f03112d0SStefano Zampini 
2618f03112d0SStefano Zampini       /* attach local l2g maps for successive calls of MatSetValues on the local matrix */
2619f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(nzr,&l2g);CHKERRQ(ierr);
2620f03112d0SStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nr,0,1,&is1);CHKERRQ(ierr);
2621f03112d0SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_MASK,is1,&is2);CHKERRQ(ierr);
2622872cf891SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
2623f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is2,&rl2g);CHKERRQ(ierr);
2624f03112d0SStefano Zampini       ierr = ISDestroy(&is1);CHKERRQ(ierr);
2625f03112d0SStefano Zampini       ierr = ISDestroy(&is2);CHKERRQ(ierr);
2626f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(nzc,&l2g);CHKERRQ(ierr);
2627f03112d0SStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nc,0,1,&is1);CHKERRQ(ierr);
2628f03112d0SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_MASK,is1,&is2);CHKERRQ(ierr);
2629f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
2630f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is2,&cl2g);CHKERRQ(ierr);
2631f03112d0SStefano Zampini       ierr = ISDestroy(&is1);CHKERRQ(ierr);
2632f03112d0SStefano Zampini       ierr = ISDestroy(&is2);CHKERRQ(ierr);
2633f03112d0SStefano Zampini       ierr = MatSetLocalToGlobalMapping(newlA,rl2g,cl2g);CHKERRQ(ierr);
2634f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2635f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2636f03112d0SStefano Zampini     } else { /* local matrix fully populated */
2637f03112d0SStefano Zampini       lnewl2g = PETSC_FALSE;
2638f03112d0SStefano Zampini       ierr    = MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
2639f03112d0SStefano Zampini       ierr    = PetscObjectReference((PetscObject)is->A);CHKERRQ(ierr);
2640f03112d0SStefano Zampini       newlA   = is->A;
2641f03112d0SStefano Zampini     }
2642f03112d0SStefano Zampini     /* attach new global l2g map if needed */
2643f03112d0SStefano Zampini     if (newl2g) {
2644f03112d0SStefano Zampini       IS             gnzr,gnzc;
2645f03112d0SStefano Zampini       const PetscInt *grid,*gcid;
2646f03112d0SStefano Zampini 
2647f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(A->rmap->mapping,nzr,&gnzr);CHKERRQ(ierr);
2648f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(A->cmap->mapping,nzc,&gnzc);CHKERRQ(ierr);
2649f03112d0SStefano Zampini       ierr = ISGetIndices(gnzr,&grid);CHKERRQ(ierr);
2650f03112d0SStefano Zampini       ierr = ISGetIndices(gnzc,&gcid);CHKERRQ(ierr);
2651f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nnzr,grid,PETSC_COPY_VALUES,&rl2g);CHKERRQ(ierr);
2652f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nnzc,gcid,PETSC_COPY_VALUES,&cl2g);CHKERRQ(ierr);
2653f03112d0SStefano Zampini       ierr = ISRestoreIndices(gnzr,&grid);CHKERRQ(ierr);
2654f03112d0SStefano Zampini       ierr = ISRestoreIndices(gnzc,&gcid);CHKERRQ(ierr);
2655f03112d0SStefano Zampini       ierr = ISDestroy(&gnzr);CHKERRQ(ierr);
2656f03112d0SStefano Zampini       ierr = ISDestroy(&gnzc);CHKERRQ(ierr);
2657f03112d0SStefano Zampini       ierr = MatSetLocalToGlobalMapping(A,rl2g,cl2g);CHKERRQ(ierr);
2658f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2659f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2660f03112d0SStefano Zampini     }
2661872cf891SStefano Zampini     ierr = MatISSetLocalMat(A,newlA);CHKERRQ(ierr);
2662872cf891SStefano Zampini     ierr = MatDestroy(&newlA);CHKERRQ(ierr);
2663f03112d0SStefano Zampini     ierr = ISDestroy(&nzr);CHKERRQ(ierr);
2664f03112d0SStefano Zampini     ierr = ISDestroy(&nzc);CHKERRQ(ierr);
2665872cf891SStefano Zampini     is->locempty = PETSC_FALSE;
2666f03112d0SStefano Zampini   }
2667b4319ba4SBarry Smith   PetscFunctionReturn(0);
2668b4319ba4SBarry Smith }
2669b4319ba4SBarry Smith 
2670a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
2671b4319ba4SBarry Smith {
2672b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
2673b4319ba4SBarry Smith 
2674b4319ba4SBarry Smith   PetscFunctionBegin;
2675b4319ba4SBarry Smith   *local = is->A;
2676b4319ba4SBarry Smith   PetscFunctionReturn(0);
2677b4319ba4SBarry Smith }
2678b4319ba4SBarry Smith 
26793b3b1effSJed Brown static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat,Mat *local)
26803b3b1effSJed Brown {
26813b3b1effSJed Brown   PetscFunctionBegin;
26823b3b1effSJed Brown   *local = NULL;
26833b3b1effSJed Brown   PetscFunctionReturn(0);
26843b3b1effSJed Brown }
26853b3b1effSJed Brown 
2686b4319ba4SBarry Smith /*@
2687b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
2688b4319ba4SBarry Smith 
2689b4319ba4SBarry Smith   Input Parameter:
2690b4319ba4SBarry Smith .  mat - the matrix
2691b4319ba4SBarry Smith 
2692b4319ba4SBarry Smith   Output Parameter:
2693eb82efa4SStefano Zampini .  local - the local matrix
2694b4319ba4SBarry Smith 
2695b4319ba4SBarry Smith   Level: advanced
2696b4319ba4SBarry Smith 
2697b4319ba4SBarry Smith   Notes:
2698b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
2699b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
2700b4319ba4SBarry Smith   of the MatSetValues() operation.
2701b4319ba4SBarry Smith 
27023b3b1effSJed Brown   Call MatISRestoreLocalMat() when finished with the local matrix.
270396a6f129SJed Brown 
2704b4319ba4SBarry Smith .seealso: MATIS
2705b4319ba4SBarry Smith @*/
27067087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
2707b4319ba4SBarry Smith {
27084ac538c5SBarry Smith   PetscErrorCode ierr;
2709b4319ba4SBarry Smith 
2710b4319ba4SBarry Smith   PetscFunctionBegin;
27110700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2712b4319ba4SBarry Smith   PetscValidPointer(local,2);
27134ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
2714b4319ba4SBarry Smith   PetscFunctionReturn(0);
2715b4319ba4SBarry Smith }
2716b4319ba4SBarry Smith 
27173b3b1effSJed Brown /*@
27183b3b1effSJed Brown     MatISRestoreLocalMat - Restores the local matrix obtained with MatISGetLocalMat()
27193b3b1effSJed Brown 
27203b3b1effSJed Brown   Input Parameter:
27213b3b1effSJed Brown .  mat - the matrix
27223b3b1effSJed Brown 
27233b3b1effSJed Brown   Output Parameter:
27243b3b1effSJed Brown .  local - the local matrix
27253b3b1effSJed Brown 
27263b3b1effSJed Brown   Level: advanced
27273b3b1effSJed Brown 
27283b3b1effSJed Brown .seealso: MATIS
27293b3b1effSJed Brown @*/
27303b3b1effSJed Brown PetscErrorCode MatISRestoreLocalMat(Mat mat,Mat *local)
27313b3b1effSJed Brown {
27323b3b1effSJed Brown   PetscErrorCode ierr;
27333b3b1effSJed Brown 
27343b3b1effSJed Brown   PetscFunctionBegin;
27353b3b1effSJed Brown   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
27363b3b1effSJed Brown   PetscValidPointer(local,2);
27373b3b1effSJed Brown   ierr = PetscUseMethod(mat,"MatISRestoreLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
27383b3b1effSJed Brown   PetscFunctionReturn(0);
27393b3b1effSJed Brown }
27403b3b1effSJed Brown 
2741a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
27423b03a366Sstefano_zampini {
27433b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
27443b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
27453b03a366Sstefano_zampini   PetscErrorCode ierr;
27463b03a366Sstefano_zampini 
27473b03a366Sstefano_zampini   PetscFunctionBegin;
27484e4c7dbeSStefano Zampini   if (is->A) {
27493b03a366Sstefano_zampini     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
27503b03a366Sstefano_zampini     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
2751f0ae7da4SStefano 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);
27524e4c7dbeSStefano Zampini   }
27533b03a366Sstefano_zampini   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
27543b03a366Sstefano_zampini   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
27553b03a366Sstefano_zampini   is->A = local;
27563b03a366Sstefano_zampini   PetscFunctionReturn(0);
27573b03a366Sstefano_zampini }
27583b03a366Sstefano_zampini 
27593b03a366Sstefano_zampini /*@
2760eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
27613b03a366Sstefano_zampini 
27623b03a366Sstefano_zampini   Input Parameter:
27633b03a366Sstefano_zampini .  mat - the matrix
2764eb82efa4SStefano Zampini .  local - the local matrix
27653b03a366Sstefano_zampini 
27663b03a366Sstefano_zampini   Output Parameter:
27673b03a366Sstefano_zampini 
27683b03a366Sstefano_zampini   Level: advanced
27693b03a366Sstefano_zampini 
27703b03a366Sstefano_zampini   Notes:
27713b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
27723b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
27733b03a366Sstefano_zampini 
27743b03a366Sstefano_zampini .seealso: MATIS
27753b03a366Sstefano_zampini @*/
27763b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
27773b03a366Sstefano_zampini {
27783b03a366Sstefano_zampini   PetscErrorCode ierr;
27793b03a366Sstefano_zampini 
27803b03a366Sstefano_zampini   PetscFunctionBegin;
27813b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2782b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
27833b03a366Sstefano_zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
27843b03a366Sstefano_zampini   PetscFunctionReturn(0);
27853b03a366Sstefano_zampini }
27863b03a366Sstefano_zampini 
2787a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
27886726f965SBarry Smith {
27896726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
27906726f965SBarry Smith   PetscErrorCode ierr;
27916726f965SBarry Smith 
27926726f965SBarry Smith   PetscFunctionBegin;
27936726f965SBarry Smith   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
27946726f965SBarry Smith   PetscFunctionReturn(0);
27956726f965SBarry Smith }
27966726f965SBarry Smith 
2797a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
27982e74eeadSLisandro Dalcin {
27992e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
28002e74eeadSLisandro Dalcin   PetscErrorCode ierr;
28012e74eeadSLisandro Dalcin 
28022e74eeadSLisandro Dalcin   PetscFunctionBegin;
28032e74eeadSLisandro Dalcin   ierr = MatScale(is->A,a);CHKERRQ(ierr);
28042e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
28052e74eeadSLisandro Dalcin }
28062e74eeadSLisandro Dalcin 
2807a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
28082e74eeadSLisandro Dalcin {
28092e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
28102e74eeadSLisandro Dalcin   PetscErrorCode ierr;
28112e74eeadSLisandro Dalcin 
28122e74eeadSLisandro Dalcin   PetscFunctionBegin;
28132e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
2814e176bc59SStefano Zampini   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
28152e74eeadSLisandro Dalcin 
28162e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
28172e74eeadSLisandro Dalcin   ierr = VecSet(v,0);CHKERRQ(ierr);
2818e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2819e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
28202e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
28212e74eeadSLisandro Dalcin }
28222e74eeadSLisandro Dalcin 
2823a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
28246726f965SBarry Smith {
28256726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
28266726f965SBarry Smith   PetscErrorCode ierr;
28276726f965SBarry Smith 
28286726f965SBarry Smith   PetscFunctionBegin;
28294e0d8c25SBarry Smith   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
28306726f965SBarry Smith   PetscFunctionReturn(0);
28316726f965SBarry Smith }
28326726f965SBarry Smith 
2833f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
2834f26d0771SStefano Zampini {
2835f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
2836f26d0771SStefano Zampini   Mat_IS         *x;
2837f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2838f26d0771SStefano Zampini   PetscBool      ismatis;
2839f26d0771SStefano Zampini #endif
2840f26d0771SStefano Zampini   PetscErrorCode ierr;
2841f26d0771SStefano Zampini 
2842f26d0771SStefano Zampini   PetscFunctionBegin;
2843f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2844f26d0771SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
2845f26d0771SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
2846f26d0771SStefano Zampini #endif
2847f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
2848f26d0771SStefano Zampini   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
2849f26d0771SStefano Zampini   PetscFunctionReturn(0);
2850f26d0771SStefano Zampini }
2851f26d0771SStefano Zampini 
2852f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
2853f26d0771SStefano Zampini {
2854f26d0771SStefano Zampini   Mat                    lA;
2855f26d0771SStefano Zampini   Mat_IS                 *matis;
2856f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
2857f26d0771SStefano Zampini   IS                     is;
2858f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
2859f26d0771SStefano Zampini   PetscInt               nrg;
2860f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
2861f26d0771SStefano Zampini   PetscErrorCode         ierr;
2862f26d0771SStefano Zampini 
2863f26d0771SStefano Zampini   PetscFunctionBegin;
2864f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
2865f26d0771SStefano Zampini   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
2866f26d0771SStefano Zampini   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
2867f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
2868f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2869f0ae7da4SStefano 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 than maximum possible %D",i,rl[i],nrg);
2870f26d0771SStefano Zampini #endif
2871f26d0771SStefano Zampini   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
2872f26d0771SStefano Zampini   /* map from [0,nrl) to row */
2873f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
2874f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2875f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = nrg;
2876f26d0771SStefano Zampini #else
2877f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
2878f26d0771SStefano Zampini #endif
2879f26d0771SStefano Zampini   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
2880f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
2881f26d0771SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2882f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
2883f26d0771SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
2884f26d0771SStefano Zampini   /* compute new l2g map for columns */
2885f26d0771SStefano Zampini   if (col != row || A->rmap->mapping != A->cmap->mapping) {
2886f26d0771SStefano Zampini     const PetscInt *cg,*cl;
2887f26d0771SStefano Zampini     PetscInt       ncg;
2888f26d0771SStefano Zampini     PetscInt       ncl;
2889f26d0771SStefano Zampini 
2890f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2891f26d0771SStefano Zampini     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
2892f26d0771SStefano Zampini     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
2893f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
2894f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2895f0ae7da4SStefano 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 than maximum possible %D",i,cl[i],ncg);
2896f26d0771SStefano Zampini #endif
2897f26d0771SStefano Zampini     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
2898f26d0771SStefano Zampini     /* map from [0,ncl) to col */
2899f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
2900f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2901f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = ncg;
2902f26d0771SStefano Zampini #else
2903f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
2904f26d0771SStefano Zampini #endif
2905f26d0771SStefano Zampini     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
2906f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2907f26d0771SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2908f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
2909f26d0771SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
2910f26d0771SStefano Zampini   } else {
2911f26d0771SStefano Zampini     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
2912f26d0771SStefano Zampini     cl2g = rl2g;
2913f26d0771SStefano Zampini   }
2914f26d0771SStefano Zampini   /* create the MATIS submatrix */
2915f26d0771SStefano Zampini   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
2916f26d0771SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
2917f26d0771SStefano Zampini   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2918f26d0771SStefano Zampini   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
2919b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
2920f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
2921f26d0771SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
2922f26d0771SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
2923f26d0771SStefano Zampini   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
2924f26d0771SStefano Zampini   ierr = MatSetUp(*submat);CHKERRQ(ierr);
2925f26d0771SStefano Zampini   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2926f26d0771SStefano Zampini   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2927f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2928f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2929f26d0771SStefano Zampini   /* remove unsupported ops */
2930f26d0771SStefano Zampini   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2931f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
2932f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
2933f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
2934f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
2935f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
2936f26d0771SStefano Zampini   PetscFunctionReturn(0);
2937f26d0771SStefano Zampini }
2938f26d0771SStefano Zampini 
2939872cf891SStefano Zampini static PetscErrorCode MatSetFromOptions_IS(PetscOptionItems *PetscOptionsObject, Mat A)
2940872cf891SStefano Zampini {
2941872cf891SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
2942872cf891SStefano Zampini   PetscErrorCode ierr;
2943872cf891SStefano Zampini 
2944872cf891SStefano Zampini   PetscFunctionBegin;
2945872cf891SStefano Zampini   ierr = PetscOptionsHead(PetscOptionsObject,"MATIS options");CHKERRQ(ierr);
2946872cf891SStefano Zampini   ierr = PetscObjectOptionsBegin((PetscObject)A);
2947f03112d0SStefano Zampini   ierr = PetscOptionsBool("-matis_fixempty","Fix local matrices in case of empty local rows/columns","MatISFixLocalEmpty",a->locempty,&a->locempty,NULL);CHKERRQ(ierr);
294875d48cdbSStefano Zampini   ierr = PetscOptionsBool("-matis_storel2l","Store local-to-local matrices generated from PtAP operations","MatISStoreL2L",a->storel2l,&a->storel2l,NULL);CHKERRQ(ierr);
2949872cf891SStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
2950872cf891SStefano Zampini   PetscFunctionReturn(0);
2951872cf891SStefano Zampini }
2952872cf891SStefano Zampini 
2953284134d9SBarry Smith /*@
29543c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
2955284134d9SBarry Smith        process but not across processes.
2956284134d9SBarry Smith 
2957284134d9SBarry Smith    Input Parameters:
2958284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
2959e176bc59SStefano Zampini .     bs      - block size of the matrix
2960df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
2961e176bc59SStefano Zampini .     rmap    - local to global map for rows
2962e176bc59SStefano Zampini -     cmap    - local to global map for cols
2963284134d9SBarry Smith 
2964284134d9SBarry Smith    Output Parameter:
2965284134d9SBarry Smith .    A - the resulting matrix
2966284134d9SBarry Smith 
29678e6c10adSSatish Balay    Level: advanced
29688e6c10adSSatish Balay 
296995452b02SPatrick Sanan    Notes:
297095452b02SPatrick Sanan     See MATIS for more details.
29716fdf41d1SStefano Zampini           m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors
29726fdf41d1SStefano Zampini           used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
29733c212e90SHong Zhang           If either rmap or cmap are NULL, then the matrix is assumed to be square.
2974284134d9SBarry Smith 
2975284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
2976284134d9SBarry Smith @*/
2977e176bc59SStefano Zampini PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
2978284134d9SBarry Smith {
2979284134d9SBarry Smith   PetscErrorCode ierr;
2980284134d9SBarry Smith 
2981284134d9SBarry Smith   PetscFunctionBegin;
29826fdf41d1SStefano Zampini   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings");
2983284134d9SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
2984284134d9SBarry Smith   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
29856fdf41d1SStefano Zampini   if (bs > 0) {
2986284134d9SBarry Smith     ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
29876fdf41d1SStefano Zampini   }
2988284134d9SBarry Smith   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
2989e176bc59SStefano Zampini   if (rmap && cmap) {
2990e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
2991e176bc59SStefano Zampini   } else if (!rmap) {
2992e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
2993e176bc59SStefano Zampini   } else {
2994e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
2995e176bc59SStefano Zampini   }
2996284134d9SBarry Smith   PetscFunctionReturn(0);
2997284134d9SBarry Smith }
2998284134d9SBarry Smith 
2999b4319ba4SBarry Smith /*MC
3000f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
3001b4319ba4SBarry Smith    This stores the matrices in globally unassembled form. Each processor
3002b4319ba4SBarry Smith    assembles only its local Neumann problem and the parallel matrix vector
3003b4319ba4SBarry Smith    product is handled "implicitly".
3004b4319ba4SBarry Smith 
3005b4319ba4SBarry Smith    Operations Provided:
30066726f965SBarry Smith +  MatMult()
30072e74eeadSLisandro Dalcin .  MatMultAdd()
30082e74eeadSLisandro Dalcin .  MatMultTranspose()
30092e74eeadSLisandro Dalcin .  MatMultTransposeAdd()
30106726f965SBarry Smith .  MatZeroEntries()
30116726f965SBarry Smith .  MatSetOption()
30122e74eeadSLisandro Dalcin .  MatZeroRows()
30132e74eeadSLisandro Dalcin .  MatSetValues()
301497563a80SStefano Zampini .  MatSetValuesBlocked()
30156726f965SBarry Smith .  MatSetValuesLocal()
301697563a80SStefano Zampini .  MatSetValuesBlockedLocal()
30172e74eeadSLisandro Dalcin .  MatScale()
30182e74eeadSLisandro Dalcin .  MatGetDiagonal()
30192b404112SStefano Zampini .  MatMissingDiagonal()
30202b404112SStefano Zampini .  MatDuplicate()
30212b404112SStefano Zampini .  MatCopy()
3022f26d0771SStefano Zampini .  MatAXPY()
30237dae84e0SHong Zhang .  MatCreateSubMatrix()
3024f26d0771SStefano Zampini .  MatGetLocalSubMatrix()
3025d7f69cd0SStefano Zampini .  MatTranspose()
302675d48cdbSStefano Zampini .  MatPtAP() (with P of AIJ type)
30276726f965SBarry Smith -  MatSetLocalToGlobalMapping()
3028b4319ba4SBarry Smith 
3029b4319ba4SBarry Smith    Options Database Keys:
303075d48cdbSStefano Zampini + -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
303175d48cdbSStefano Zampini . -matis_fixempty - Fixes local matrices in case of empty local rows/columns.
303275d48cdbSStefano Zampini - -matis_storel2l - stores the local-to-local operators generated by the Galerkin process of MatPtAP().
3033b4319ba4SBarry Smith 
303495452b02SPatrick Sanan    Notes:
303595452b02SPatrick Sanan     Options prefix for the inner matrix are given by -is_mat_xxx
3036b4319ba4SBarry Smith 
3037b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
3038b4319ba4SBarry Smith 
3039b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
3040eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
3041b4319ba4SBarry Smith 
3042b4319ba4SBarry Smith   Level: advanced
3043b4319ba4SBarry Smith 
3044f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
3045b4319ba4SBarry Smith 
3046b4319ba4SBarry Smith M*/
3047b4319ba4SBarry Smith 
30488cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
3049b4319ba4SBarry Smith {
3050dfbe8321SBarry Smith   PetscErrorCode ierr;
3051b4319ba4SBarry Smith   Mat_IS         *b;
3052b4319ba4SBarry Smith 
3053b4319ba4SBarry Smith   PetscFunctionBegin;
3054b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
3055b4319ba4SBarry Smith   A->data = (void*)b;
3056b4319ba4SBarry Smith 
3057e176bc59SStefano Zampini   /* matrix ops */
3058e176bc59SStefano Zampini   ierr = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
3059b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
30602e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
30612e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
30622e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
3063b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
3064b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
30652e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
306698921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
3067b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
3068f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
30692e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
3070f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
3071b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
3072b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
3073b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
30746726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
30752e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
30762e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
30776726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
307869796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
307969796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
308045471136SStefano Zampini   A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS;
3081ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
30826bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
30832b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
3084659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
30857dae84e0SHong Zhang   A->ops->createsubmatrix         = MatCreateSubMatrix_IS;
3086f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
30873fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
30883fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
3089d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
30907fa8f2d3SStefano Zampini   A->ops->getinfo                 = MatGetInfo_IS;
3091ad219c80Sstefano_zampini   A->ops->diagonalscale           = MatDiagonalScale_IS;
3092872cf891SStefano Zampini   A->ops->setfromoptions          = MatSetFromOptions_IS;
3093b4319ba4SBarry Smith 
3094b7ce53b6SStefano Zampini   /* special MATIS functions */
3095bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
30963b3b1effSJed Brown   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISRestoreLocalMat_C",MatISRestoreLocalMat_IS);CHKERRQ(ierr);
3097bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
3098487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
30992e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
3100cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",MatISSetUpSF_IS);CHKERRQ(ierr);
310175d48cdbSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",MatISStoreL2L_IS);CHKERRQ(ierr);
3102f03112d0SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",MatISFixLocalEmpty_IS);CHKERRQ(ierr);
3103487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3104487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3105487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3106487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3107487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3108487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3109487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
311017667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
3111b4319ba4SBarry Smith   PetscFunctionReturn(0);
3112b4319ba4SBarry Smith }
3113