xref: /petsc/src/mat/impls/is/matis.c (revision 844bd0d74a9e6c2eab5c50bd1fef55548c8f4269)
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*/
116989cf23SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
124f2d7cafSStefano Zampini #include <petsc/private/sfimpl.h>
1328f4e0baSStefano Zampini 
14f26d0771SStefano Zampini #define MATIS_MAX_ENTRIES_INSERTION 2048
15b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat,PetscInt,const PetscInt*,PetscInt,const PetscInt*,const PetscScalar*,InsertMode);
16b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat,PetscInt,const PetscInt*,PetscInt,const PetscInt*,const PetscScalar*,InsertMode);
17f26d0771SStefano Zampini 
1875d48cdbSStefano Zampini static PetscErrorCode MatISContainerDestroyPtAP_Private(void *ptr)
1975d48cdbSStefano Zampini {
2075d48cdbSStefano Zampini   MatISPtAP      ptap = (MatISPtAP)ptr;
2175d48cdbSStefano Zampini   PetscErrorCode ierr;
2275d48cdbSStefano Zampini 
2375d48cdbSStefano Zampini   PetscFunctionBegin;
2475d48cdbSStefano Zampini   ierr = MatDestroySubMatrices(ptap->ris1 ? 2 : 1,&ptap->lP);CHKERRQ(ierr);
2575d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->cis0);CHKERRQ(ierr);
2675d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->cis1);CHKERRQ(ierr);
2775d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->ris0);CHKERRQ(ierr);
2875d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->ris1);CHKERRQ(ierr);
2975d48cdbSStefano Zampini   ierr = PetscFree(ptap);CHKERRQ(ierr);
3075d48cdbSStefano Zampini   PetscFunctionReturn(0);
3175d48cdbSStefano Zampini }
3275d48cdbSStefano Zampini 
3375d48cdbSStefano Zampini static PetscErrorCode MatPtAPNumeric_IS_XAIJ(Mat A, Mat P, Mat C)
3475d48cdbSStefano Zampini {
3575d48cdbSStefano Zampini   MatISPtAP      ptap;
3675d48cdbSStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
3775d48cdbSStefano Zampini   Mat            lA,lC;
3875d48cdbSStefano Zampini   MatReuse       reuse;
3975d48cdbSStefano Zampini   IS             ris[2],cis[2];
4075d48cdbSStefano Zampini   PetscContainer c;
4175d48cdbSStefano Zampini   PetscInt       n;
4275d48cdbSStefano Zampini   PetscErrorCode ierr;
4375d48cdbSStefano Zampini 
4475d48cdbSStefano Zampini   PetscFunctionBegin;
4575d48cdbSStefano Zampini   ierr = PetscObjectQuery((PetscObject)(C),"_MatIS_PtAP",(PetscObject*)&c);CHKERRQ(ierr);
4675d48cdbSStefano Zampini   if (!c) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing PtAP information");
4775d48cdbSStefano Zampini   ierr   = PetscContainerGetPointer(c,(void**)&ptap);CHKERRQ(ierr);
4875d48cdbSStefano Zampini   ris[0] = ptap->ris0;
4975d48cdbSStefano Zampini   ris[1] = ptap->ris1;
5075d48cdbSStefano Zampini   cis[0] = ptap->cis0;
5175d48cdbSStefano Zampini   cis[1] = ptap->cis1;
5275d48cdbSStefano Zampini   n      = ptap->ris1 ? 2 : 1;
5375d48cdbSStefano Zampini   reuse  = ptap->lP ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX;
5475d48cdbSStefano Zampini   ierr   = MatCreateSubMatrices(P,n,ris,cis,reuse,&ptap->lP);CHKERRQ(ierr);
5575d48cdbSStefano Zampini 
5675d48cdbSStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
5775d48cdbSStefano Zampini   ierr = MatISGetLocalMat(C,&lC);CHKERRQ(ierr);
5875d48cdbSStefano Zampini   if (ptap->ris1) { /* unsymmetric A mapping */
5975d48cdbSStefano Zampini     Mat lPt;
6075d48cdbSStefano Zampini 
6175d48cdbSStefano Zampini     ierr = MatTranspose(ptap->lP[1],MAT_INITIAL_MATRIX,&lPt);CHKERRQ(ierr);
6275d48cdbSStefano Zampini     ierr = MatMatMatMult(lPt,lA,ptap->lP[0],reuse,ptap->fill,&lC);CHKERRQ(ierr);
6375d48cdbSStefano Zampini     if (matis->storel2l) {
6475d48cdbSStefano Zampini       ierr = PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",(PetscObject)lPt);CHKERRQ(ierr);
6575d48cdbSStefano Zampini     }
6675d48cdbSStefano Zampini     ierr = MatDestroy(&lPt);CHKERRQ(ierr);
6775d48cdbSStefano Zampini   } else {
6875d48cdbSStefano Zampini     ierr = MatPtAP(lA,ptap->lP[0],reuse,ptap->fill,&lC);CHKERRQ(ierr);
6975d48cdbSStefano Zampini     if (matis->storel2l) {
7075d48cdbSStefano Zampini      ierr = PetscObjectCompose((PetscObject)(C),"_MatIS_PtAP_l2l",(PetscObject)ptap->lP[0]);CHKERRQ(ierr);
7175d48cdbSStefano Zampini     }
7275d48cdbSStefano Zampini   }
7375d48cdbSStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
7475d48cdbSStefano Zampini     ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
7575d48cdbSStefano Zampini     ierr = MatDestroy(&lC);CHKERRQ(ierr);
7675d48cdbSStefano Zampini   }
7775d48cdbSStefano Zampini   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7875d48cdbSStefano Zampini   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7975d48cdbSStefano Zampini   PetscFunctionReturn(0);
8075d48cdbSStefano Zampini }
8175d48cdbSStefano Zampini 
8275d48cdbSStefano Zampini static PetscErrorCode MatGetNonzeroColumnsLocal_Private(Mat PT,IS *cis)
8375d48cdbSStefano Zampini {
8475d48cdbSStefano Zampini   Mat            Po,Pd;
8575d48cdbSStefano Zampini   IS             zd,zo;
8675d48cdbSStefano Zampini   const PetscInt *garray;
8775d48cdbSStefano Zampini   PetscInt       *aux,i,bs;
8875d48cdbSStefano Zampini   PetscInt       dc,stc,oc,ctd,cto;
8975d48cdbSStefano Zampini   PetscBool      ismpiaij,ismpibaij,isseqaij,isseqbaij;
9075d48cdbSStefano Zampini   MPI_Comm       comm;
9175d48cdbSStefano Zampini   PetscErrorCode ierr;
9275d48cdbSStefano Zampini 
9375d48cdbSStefano Zampini   PetscFunctionBegin;
9475d48cdbSStefano Zampini   PetscValidHeaderSpecific(PT,MAT_CLASSID,1);
9575d48cdbSStefano Zampini   PetscValidPointer(cis,2);
9675d48cdbSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)PT,&comm);CHKERRQ(ierr);
9775d48cdbSStefano Zampini   bs   = 1;
9875d48cdbSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)PT,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
9975d48cdbSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)PT,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr);
10004637862SRichard Tran Mills   ierr = PetscObjectBaseTypeCompare((PetscObject)PT,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
10175d48cdbSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)PT,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
10275d48cdbSStefano Zampini   if (isseqaij || isseqbaij) {
10375d48cdbSStefano Zampini     Pd = PT;
10475d48cdbSStefano Zampini     Po = NULL;
10575d48cdbSStefano Zampini     garray = NULL;
10675d48cdbSStefano Zampini   } else if (ismpiaij) {
10775d48cdbSStefano Zampini     ierr = MatMPIAIJGetSeqAIJ(PT,&Pd,&Po,&garray);CHKERRQ(ierr);
10875d48cdbSStefano Zampini   } else if (ismpibaij) {
10975d48cdbSStefano Zampini     ierr = MatMPIBAIJGetSeqBAIJ(PT,&Pd,&Po,&garray);CHKERRQ(ierr);
11075d48cdbSStefano Zampini     ierr = MatGetBlockSize(PT,&bs);CHKERRQ(ierr);
11175d48cdbSStefano Zampini   } else SETERRQ1(comm,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(PT))->type_name);
11275d48cdbSStefano Zampini 
11375d48cdbSStefano Zampini   /* identify any null columns in Pd or Po */
11422f7620eSStefano Zampini   /* We use a tolerance comparison since it may happen that, with geometric multigrid,
11522f7620eSStefano Zampini      some of the columns are not really zero, but very close to */
11675d48cdbSStefano Zampini   zo = zd = NULL;
11775d48cdbSStefano Zampini   if (Po) {
11822f7620eSStefano Zampini     ierr = MatFindNonzeroRowsOrCols_Basic(Po,PETSC_TRUE,PETSC_SMALL,&zo);CHKERRQ(ierr);
11975d48cdbSStefano Zampini   }
12022f7620eSStefano Zampini   ierr = MatFindNonzeroRowsOrCols_Basic(Pd,PETSC_TRUE,PETSC_SMALL,&zd);CHKERRQ(ierr);
12175d48cdbSStefano Zampini 
12275d48cdbSStefano Zampini   ierr = MatGetLocalSize(PT,NULL,&dc);CHKERRQ(ierr);
12375d48cdbSStefano Zampini   ierr = MatGetOwnershipRangeColumn(PT,&stc,NULL);CHKERRQ(ierr);
12475d48cdbSStefano Zampini   if (Po) { ierr = MatGetLocalSize(Po,NULL,&oc);CHKERRQ(ierr); }
12575d48cdbSStefano Zampini   else oc = 0;
12675d48cdbSStefano Zampini   ierr = PetscMalloc1((dc+oc)/bs,&aux);CHKERRQ(ierr);
12775d48cdbSStefano Zampini   if (zd) {
12875d48cdbSStefano Zampini     const PetscInt *idxs;
12975d48cdbSStefano Zampini     PetscInt       nz;
13075d48cdbSStefano Zampini 
13175d48cdbSStefano Zampini     /* this will throw an error if bs is not valid */
13275d48cdbSStefano Zampini     ierr = ISSetBlockSize(zd,bs);CHKERRQ(ierr);
13375d48cdbSStefano Zampini     ierr = ISGetLocalSize(zd,&nz);CHKERRQ(ierr);
13475d48cdbSStefano Zampini     ierr = ISGetIndices(zd,&idxs);CHKERRQ(ierr);
13575d48cdbSStefano Zampini     ctd  = nz/bs;
13675d48cdbSStefano Zampini     for (i=0; i<ctd; i++) aux[i] = (idxs[bs*i]+stc)/bs;
13775d48cdbSStefano Zampini     ierr = ISRestoreIndices(zd,&idxs);CHKERRQ(ierr);
13875d48cdbSStefano Zampini   } else {
13975d48cdbSStefano Zampini     ctd = dc/bs;
14075d48cdbSStefano Zampini     for (i=0; i<ctd; i++) aux[i] = i+stc/bs;
14175d48cdbSStefano Zampini   }
14275d48cdbSStefano Zampini   if (zo) {
14375d48cdbSStefano Zampini     const PetscInt *idxs;
14475d48cdbSStefano Zampini     PetscInt       nz;
14575d48cdbSStefano Zampini 
14675d48cdbSStefano Zampini     /* this will throw an error if bs is not valid */
14775d48cdbSStefano Zampini     ierr = ISSetBlockSize(zo,bs);CHKERRQ(ierr);
14875d48cdbSStefano Zampini     ierr = ISGetLocalSize(zo,&nz);CHKERRQ(ierr);
14975d48cdbSStefano Zampini     ierr = ISGetIndices(zo,&idxs);CHKERRQ(ierr);
15075d48cdbSStefano Zampini     cto  = nz/bs;
15175d48cdbSStefano Zampini     for (i=0; i<cto; i++) aux[i+ctd] = garray[idxs[bs*i]/bs];
15275d48cdbSStefano Zampini     ierr = ISRestoreIndices(zo,&idxs);CHKERRQ(ierr);
15375d48cdbSStefano Zampini   } else {
15475d48cdbSStefano Zampini     cto = oc/bs;
15575d48cdbSStefano Zampini     for (i=0; i<cto; i++) aux[i+ctd] = garray[i];
15675d48cdbSStefano Zampini   }
15775d48cdbSStefano Zampini   ierr = ISCreateBlock(comm,bs,ctd+cto,aux,PETSC_OWN_POINTER,cis);CHKERRQ(ierr);
15875d48cdbSStefano Zampini   ierr = ISDestroy(&zd);CHKERRQ(ierr);
15975d48cdbSStefano Zampini   ierr = ISDestroy(&zo);CHKERRQ(ierr);
16075d48cdbSStefano Zampini   PetscFunctionReturn(0);
16175d48cdbSStefano Zampini }
16275d48cdbSStefano Zampini 
16375d48cdbSStefano Zampini static PetscErrorCode MatPtAPSymbolic_IS_XAIJ(Mat A,Mat P,PetscReal fill,Mat *C)
16475d48cdbSStefano Zampini {
16575d48cdbSStefano Zampini   Mat                    PT;
16675d48cdbSStefano Zampini   MatISPtAP              ptap;
16775d48cdbSStefano Zampini   ISLocalToGlobalMapping Crl2g,Ccl2g,rl2g,cl2g;
16875d48cdbSStefano Zampini   PetscContainer         c;
16975d48cdbSStefano Zampini   const PetscInt         *garray;
17075d48cdbSStefano Zampini   PetscInt               ibs,N,dc;
17175d48cdbSStefano Zampini   MPI_Comm               comm;
17275d48cdbSStefano Zampini   PetscErrorCode         ierr;
17375d48cdbSStefano Zampini 
17475d48cdbSStefano Zampini   PetscFunctionBegin;
17575d48cdbSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
17675d48cdbSStefano Zampini   ierr = MatCreate(comm,C);CHKERRQ(ierr);
17775d48cdbSStefano Zampini   ierr = MatSetType(*C,MATIS);CHKERRQ(ierr);
17875d48cdbSStefano Zampini   ierr = MatGetSize(P,NULL,&N);CHKERRQ(ierr);
17975d48cdbSStefano Zampini   ierr = MatGetLocalSize(P,NULL,&dc);CHKERRQ(ierr);
18075d48cdbSStefano Zampini   ierr = MatSetSizes(*C,dc,dc,N,N);CHKERRQ(ierr);
18175d48cdbSStefano Zampini /* Not sure about this
18275d48cdbSStefano Zampini   ierr = MatGetBlockSizes(P,NULL,&ibs);CHKERRQ(ierr);
18375d48cdbSStefano Zampini   ierr = MatSetBlockSize(*C,ibs);CHKERRQ(ierr);
18475d48cdbSStefano Zampini */
18575d48cdbSStefano Zampini 
18675d48cdbSStefano Zampini   ierr = PetscNew(&ptap);CHKERRQ(ierr);
18775d48cdbSStefano Zampini   ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr);
18875d48cdbSStefano Zampini   ierr = PetscContainerSetPointer(c,ptap);CHKERRQ(ierr);
18975d48cdbSStefano Zampini   ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyPtAP_Private);CHKERRQ(ierr);
19075d48cdbSStefano Zampini   ierr = PetscObjectCompose((PetscObject)(*C),"_MatIS_PtAP",(PetscObject)c);CHKERRQ(ierr);
19175d48cdbSStefano Zampini   ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
19275d48cdbSStefano Zampini   ptap->fill = fill;
19375d48cdbSStefano Zampini 
19475d48cdbSStefano Zampini   ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
19575d48cdbSStefano Zampini 
19675d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cl2g,&ibs);CHKERRQ(ierr);
19775d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cl2g,&N);CHKERRQ(ierr);
19875d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockIndices(cl2g,&garray);CHKERRQ(ierr);
19975d48cdbSStefano Zampini   ierr = ISCreateBlock(comm,ibs,N/ibs,garray,PETSC_COPY_VALUES,&ptap->ris0);CHKERRQ(ierr);
20075d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreBlockIndices(cl2g,&garray);CHKERRQ(ierr);
20175d48cdbSStefano Zampini 
20275d48cdbSStefano Zampini   ierr = MatCreateSubMatrix(P,ptap->ris0,NULL,MAT_INITIAL_MATRIX,&PT);CHKERRQ(ierr);
20375d48cdbSStefano Zampini   ierr = MatGetNonzeroColumnsLocal_Private(PT,&ptap->cis0);CHKERRQ(ierr);
20475d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(ptap->cis0,&Ccl2g);CHKERRQ(ierr);
20575d48cdbSStefano Zampini   ierr = MatDestroy(&PT);CHKERRQ(ierr);
20675d48cdbSStefano Zampini 
20775d48cdbSStefano Zampini   Crl2g = NULL;
20875d48cdbSStefano Zampini   if (rl2g != cl2g) { /* unsymmetric A mapping */
20975d48cdbSStefano Zampini     PetscBool same,lsame = PETSC_FALSE;
21075d48cdbSStefano Zampini     PetscInt  N1,ibs1;
21175d48cdbSStefano Zampini 
21275d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(rl2g,&N1);CHKERRQ(ierr);
21375d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(rl2g,&ibs1);CHKERRQ(ierr);
21475d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockIndices(rl2g,&garray);CHKERRQ(ierr);
21575d48cdbSStefano Zampini     ierr = ISCreateBlock(comm,ibs,N/ibs,garray,PETSC_COPY_VALUES,&ptap->ris1);CHKERRQ(ierr);
21675d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreBlockIndices(rl2g,&garray);CHKERRQ(ierr);
21775d48cdbSStefano Zampini     if (ibs1 == ibs && N1 == N) { /* check if the l2gmaps are the same */
21875d48cdbSStefano Zampini       const PetscInt *i1,*i2;
21975d48cdbSStefano Zampini 
22075d48cdbSStefano Zampini       ierr = ISBlockGetIndices(ptap->ris0,&i1);CHKERRQ(ierr);
22175d48cdbSStefano Zampini       ierr = ISBlockGetIndices(ptap->ris1,&i2);CHKERRQ(ierr);
22275d48cdbSStefano Zampini       ierr = PetscMemcmp(i1,i2,N*sizeof(*i1),&lsame);CHKERRQ(ierr);
22375d48cdbSStefano Zampini     }
22475d48cdbSStefano Zampini     ierr = MPIU_Allreduce(&lsame,&same,1,MPIU_BOOL,MPI_LAND,comm);CHKERRQ(ierr);
22575d48cdbSStefano Zampini     if (same) {
22675d48cdbSStefano Zampini       ierr = ISDestroy(&ptap->ris1);CHKERRQ(ierr);
22775d48cdbSStefano Zampini     } else {
22875d48cdbSStefano Zampini       ierr = MatCreateSubMatrix(P,ptap->ris1,NULL,MAT_INITIAL_MATRIX,&PT);CHKERRQ(ierr);
22975d48cdbSStefano Zampini       ierr = MatGetNonzeroColumnsLocal_Private(PT,&ptap->cis1);CHKERRQ(ierr);
23075d48cdbSStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(ptap->cis1,&Crl2g);CHKERRQ(ierr);
23175d48cdbSStefano Zampini       ierr = MatDestroy(&PT);CHKERRQ(ierr);
23275d48cdbSStefano Zampini     }
23375d48cdbSStefano Zampini   }
23475d48cdbSStefano Zampini /* Not sure about this
23575d48cdbSStefano Zampini   if (!Crl2g) {
23675d48cdbSStefano Zampini     ierr = MatGetBlockSize(*C,&ibs);CHKERRQ(ierr);
23775d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingSetBlockSize(Ccl2g,ibs);CHKERRQ(ierr);
23875d48cdbSStefano Zampini   }
23975d48cdbSStefano Zampini */
24075d48cdbSStefano Zampini   ierr = MatSetLocalToGlobalMapping(*C,Crl2g ? Crl2g : Ccl2g,Ccl2g);CHKERRQ(ierr);
24175d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&Crl2g);CHKERRQ(ierr);
24275d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&Ccl2g);CHKERRQ(ierr);
24375d48cdbSStefano Zampini 
24475d48cdbSStefano Zampini   (*C)->ops->ptapnumeric = MatPtAPNumeric_IS_XAIJ;
24575d48cdbSStefano Zampini   PetscFunctionReturn(0);
24675d48cdbSStefano Zampini }
24775d48cdbSStefano Zampini 
24875d48cdbSStefano Zampini PETSC_INTERN PetscErrorCode MatPtAP_IS_XAIJ(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C)
24975d48cdbSStefano Zampini {
25075d48cdbSStefano Zampini   PetscErrorCode ierr;
25175d48cdbSStefano Zampini 
25275d48cdbSStefano Zampini   PetscFunctionBegin;
25375d48cdbSStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
25475d48cdbSStefano Zampini     ierr = PetscLogEventBegin(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr);
25575d48cdbSStefano Zampini     ierr = MatPtAPSymbolic_IS_XAIJ(A,P,fill,C);CHKERRQ(ierr);
25675d48cdbSStefano Zampini     ierr = PetscLogEventEnd(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr);
25775d48cdbSStefano Zampini   }
25875d48cdbSStefano Zampini   ierr = PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
25975d48cdbSStefano Zampini   ierr = ((*C)->ops->ptapnumeric)(A,P,*C);CHKERRQ(ierr);
26075d48cdbSStefano Zampini   ierr = PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
26175d48cdbSStefano Zampini   PetscFunctionReturn(0);
26275d48cdbSStefano Zampini }
26375d48cdbSStefano Zampini 
2645b003df0Sstefano_zampini static PetscErrorCode MatISContainerDestroyFields_Private(void *ptr)
2655b003df0Sstefano_zampini {
2665b003df0Sstefano_zampini   MatISLocalFields lf = (MatISLocalFields)ptr;
2675b003df0Sstefano_zampini   PetscInt         i;
2685b003df0Sstefano_zampini   PetscErrorCode   ierr;
2695b003df0Sstefano_zampini 
270ab4d48faSStefano Zampini   PetscFunctionBegin;
2715b003df0Sstefano_zampini   for (i=0;i<lf->nr;i++) {
2725b003df0Sstefano_zampini     ierr = ISDestroy(&lf->rf[i]);CHKERRQ(ierr);
2735b003df0Sstefano_zampini   }
2745b003df0Sstefano_zampini   for (i=0;i<lf->nc;i++) {
2755b003df0Sstefano_zampini     ierr = ISDestroy(&lf->cf[i]);CHKERRQ(ierr);
2765b003df0Sstefano_zampini   }
2775b003df0Sstefano_zampini   ierr = PetscFree2(lf->rf,lf->cf);CHKERRQ(ierr);
2785b003df0Sstefano_zampini   ierr = PetscFree(lf);CHKERRQ(ierr);
2795b003df0Sstefano_zampini   PetscFunctionReturn(0);
2805b003df0Sstefano_zampini }
281a72627d2SStefano Zampini 
2826989cf23SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
2836989cf23SStefano Zampini {
2846989cf23SStefano Zampini   Mat_MPIAIJ             *aij  = (Mat_MPIAIJ*)A->data;
2856989cf23SStefano Zampini   Mat_SeqAIJ             *diag = (Mat_SeqAIJ*)(aij->A->data);
2866989cf23SStefano Zampini   Mat_SeqAIJ             *offd = (Mat_SeqAIJ*)(aij->B->data);
2876989cf23SStefano Zampini   Mat                    lA;
2886989cf23SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
2896989cf23SStefano Zampini   IS                     is;
2906989cf23SStefano Zampini   MPI_Comm               comm;
2916989cf23SStefano Zampini   void                   *ptrs[2];
2926989cf23SStefano Zampini   const char             *names[2] = {"_convert_csr_aux","_convert_csr_data"};
2936989cf23SStefano Zampini   PetscScalar            *dd,*od,*aa,*data;
2946989cf23SStefano Zampini   PetscInt               *di,*dj,*oi,*oj;
2956989cf23SStefano Zampini   PetscInt               *aux,*ii,*jj;
296e363d98aSStefano Zampini   PetscInt               lc,dr,dc,oc,str,stc,nnz,i,jd,jo,cum;
2976989cf23SStefano Zampini   PetscErrorCode         ierr;
2986989cf23SStefano Zampini 
299ab4d48faSStefano Zampini   PetscFunctionBegin;
3006989cf23SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
3016989cf23SStefano Zampini   if (!aij->garray) SETERRQ(comm,PETSC_ERR_SUP,"garray not present");
3026989cf23SStefano Zampini 
3036989cf23SStefano Zampini   /* access relevant information from MPIAIJ */
3046989cf23SStefano Zampini   ierr = MatGetOwnershipRange(A,&str,NULL);CHKERRQ(ierr);
3056989cf23SStefano Zampini   ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr);
3066989cf23SStefano Zampini   ierr = MatGetLocalSize(A,&dr,&dc);CHKERRQ(ierr);
3076989cf23SStefano Zampini   di   = diag->i;
3086989cf23SStefano Zampini   dj   = diag->j;
3096989cf23SStefano Zampini   dd   = diag->a;
3106989cf23SStefano Zampini   oc   = aij->B->cmap->n;
3116989cf23SStefano Zampini   oi   = offd->i;
3126989cf23SStefano Zampini   oj   = offd->j;
3136989cf23SStefano Zampini   od   = offd->a;
3146989cf23SStefano Zampini   nnz  = diag->i[dr] + offd->i[dr];
3156989cf23SStefano Zampini 
3166989cf23SStefano Zampini   /* generate l2g maps for rows and cols */
3176989cf23SStefano Zampini   ierr = ISCreateStride(comm,dr,str,1,&is);CHKERRQ(ierr);
3186989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
3196989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
320e363d98aSStefano Zampini   if (dr) {
3216989cf23SStefano Zampini     ierr = PetscMalloc1(dc+oc,&aux);CHKERRQ(ierr);
3226989cf23SStefano Zampini     for (i=0; i<dc; i++) aux[i]    = i+stc;
3236989cf23SStefano Zampini     for (i=0; i<oc; i++) aux[i+dc] = aij->garray[i];
3246989cf23SStefano Zampini     ierr = ISCreateGeneral(comm,dc+oc,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
325e363d98aSStefano Zampini     lc   = dc+oc;
326e363d98aSStefano Zampini   } else {
327e363d98aSStefano Zampini     ierr = ISCreateGeneral(comm,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
328e363d98aSStefano Zampini     lc   = 0;
329e363d98aSStefano Zampini   }
3306989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
3316989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
3326989cf23SStefano Zampini 
3336989cf23SStefano Zampini   /* create MATIS object */
3346989cf23SStefano Zampini   ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
3356989cf23SStefano Zampini   ierr = MatSetSizes(*newmat,dr,dc,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
3366989cf23SStefano Zampini   ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
3376989cf23SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
3386989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
3396989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
3406989cf23SStefano Zampini 
3416989cf23SStefano Zampini   /* merge local matrices */
3426989cf23SStefano Zampini   ierr = PetscMalloc1(nnz+dr+1,&aux);CHKERRQ(ierr);
3436989cf23SStefano Zampini   ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr);
3446989cf23SStefano Zampini   ii   = aux;
3456989cf23SStefano Zampini   jj   = aux+dr+1;
3466989cf23SStefano Zampini   aa   = data;
3476989cf23SStefano Zampini   *ii  = *(di++) + *(oi++);
3486989cf23SStefano Zampini   for (jd=0,jo=0,cum=0;*ii<nnz;cum++)
3496989cf23SStefano Zampini   {
3506989cf23SStefano Zampini      for (;jd<*di;jd++) { *jj++ = *dj++;      *aa++ = *dd++; }
3516989cf23SStefano Zampini      for (;jo<*oi;jo++) { *jj++ = *oj++ + dc; *aa++ = *od++; }
3526989cf23SStefano Zampini      *(++ii) = *(di++) + *(oi++);
3536989cf23SStefano Zampini   }
3546989cf23SStefano Zampini   for (;cum<dr;cum++) *(++ii) = nnz;
3556989cf23SStefano Zampini   ii   = aux;
3566989cf23SStefano Zampini   jj   = aux+dr+1;
3576989cf23SStefano Zampini   aa   = data;
358e363d98aSStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,lc,ii,jj,aa,&lA);CHKERRQ(ierr);
3596989cf23SStefano Zampini 
3606989cf23SStefano Zampini   /* create containers to destroy the data */
3616989cf23SStefano Zampini   ptrs[0] = aux;
3626989cf23SStefano Zampini   ptrs[1] = data;
3636989cf23SStefano Zampini   for (i=0; i<2; i++) {
3646989cf23SStefano Zampini     PetscContainer c;
3656989cf23SStefano Zampini 
3666989cf23SStefano Zampini     ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr);
3676989cf23SStefano Zampini     ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr);
368b81c21eeSStefano Zampini     ierr = PetscContainerSetUserDestroy(c,PetscContainerUserDestroyDefault);CHKERRQ(ierr);
3696989cf23SStefano Zampini     ierr = PetscObjectCompose((PetscObject)lA,names[i],(PetscObject)c);CHKERRQ(ierr);
3706989cf23SStefano Zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
3716989cf23SStefano Zampini   }
3726989cf23SStefano Zampini 
3736989cf23SStefano Zampini   /* finalize matrix */
3746989cf23SStefano Zampini   ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
3756989cf23SStefano Zampini   ierr = MatDestroy(&lA);CHKERRQ(ierr);
3766989cf23SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3776989cf23SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3786989cf23SStefano Zampini   PetscFunctionReturn(0);
3796989cf23SStefano Zampini }
3806989cf23SStefano Zampini 
381cf0a3239SStefano Zampini /*@
3823d996552SStefano Zampini    MatISSetUpSF - Setup star forest objects used by MatIS.
383cf0a3239SStefano Zampini 
384cf0a3239SStefano Zampini    Collective on MPI_Comm
385cf0a3239SStefano Zampini 
386cf0a3239SStefano Zampini    Input Parameters:
387cf0a3239SStefano Zampini +  A - the matrix
388cf0a3239SStefano Zampini 
389cf0a3239SStefano Zampini    Level: advanced
390cf0a3239SStefano Zampini 
39195452b02SPatrick Sanan    Notes:
39295452b02SPatrick Sanan     This function does not need to be called by the user.
393cf0a3239SStefano Zampini 
394cf0a3239SStefano Zampini .keywords: matrix
395cf0a3239SStefano Zampini 
396cf0a3239SStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatISGetLocalMat()
397cf0a3239SStefano Zampini @*/
398cf0a3239SStefano Zampini PetscErrorCode  MatISSetUpSF(Mat A)
399cf0a3239SStefano Zampini {
4007fa8f2d3SStefano Zampini   PetscErrorCode ierr;
4017fa8f2d3SStefano Zampini 
4027fa8f2d3SStefano Zampini   PetscFunctionBegin;
403cf0a3239SStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
404cf0a3239SStefano Zampini   PetscValidType(A,1);
405cf0a3239SStefano Zampini   ierr = PetscTryMethod(A,"MatISSetUpSF_C",(Mat),(A));CHKERRQ(ierr);
4067fa8f2d3SStefano Zampini   PetscFunctionReturn(0);
4077fa8f2d3SStefano Zampini }
4087fa8f2d3SStefano Zampini 
4095e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
4105e3038f0Sstefano_zampini {
4115e3038f0Sstefano_zampini   Mat                    **nest,*snest,**rnest,lA,B;
4125e3038f0Sstefano_zampini   IS                     *iscol,*isrow,*islrow,*islcol;
4135e3038f0Sstefano_zampini   ISLocalToGlobalMapping rl2g,cl2g;
4145e3038f0Sstefano_zampini   MPI_Comm               comm;
4155b003df0Sstefano_zampini   PetscInt               *lr,*lc,*l2gidxs;
4165b003df0Sstefano_zampini   PetscInt               i,j,nr,nc,rbs,cbs;
4179e7b2b25Sstefano_zampini   PetscBool              convert,lreuse,*istrans;
4185e3038f0Sstefano_zampini   PetscErrorCode         ierr;
4195e3038f0Sstefano_zampini 
420ab4d48faSStefano Zampini   PetscFunctionBegin;
4215e3038f0Sstefano_zampini   ierr   = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr);
4225e3038f0Sstefano_zampini   lreuse = PETSC_FALSE;
4235e3038f0Sstefano_zampini   rnest  = NULL;
4245e3038f0Sstefano_zampini   if (reuse == MAT_REUSE_MATRIX) {
4255e3038f0Sstefano_zampini     PetscBool ismatis,isnest;
4265e3038f0Sstefano_zampini 
4275e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
4285e3038f0Sstefano_zampini     if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type);
4295e3038f0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
4305e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr);
4315e3038f0Sstefano_zampini     if (isnest) {
4325e3038f0Sstefano_zampini       ierr   = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr);
4335e3038f0Sstefano_zampini       lreuse = (PetscBool)(i == nr && j == nc);
4345e3038f0Sstefano_zampini       if (!lreuse) rnest = NULL;
4355e3038f0Sstefano_zampini     }
4365e3038f0Sstefano_zampini   }
4375e3038f0Sstefano_zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
4385b003df0Sstefano_zampini   ierr = PetscCalloc2(nr,&lr,nc,&lc);CHKERRQ(ierr);
4399e7b2b25Sstefano_zampini   ierr = PetscCalloc6(nr,&isrow,nc,&iscol,
4405e3038f0Sstefano_zampini                       nr,&islrow,nc,&islcol,
4419e7b2b25Sstefano_zampini                       nr*nc,&snest,nr*nc,&istrans);CHKERRQ(ierr);
4425e3038f0Sstefano_zampini   ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr);
4435e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
4445e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
4455e3038f0Sstefano_zampini       PetscBool ismatis;
4469e7b2b25Sstefano_zampini       PetscInt  l1,l2,lb1,lb2,ij=i*nc+j;
4475e3038f0Sstefano_zampini 
4485e3038f0Sstefano_zampini       /* Null matrix pointers are allowed in MATNEST */
4495e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
4505e3038f0Sstefano_zampini 
4515e3038f0Sstefano_zampini       /* Nested matrices should be of type MATIS */
4529e7b2b25Sstefano_zampini       ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij]);CHKERRQ(ierr);
4539e7b2b25Sstefano_zampini       if (istrans[ij]) {
4549e7b2b25Sstefano_zampini         Mat T,lT;
4559e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
4569e7b2b25Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis);CHKERRQ(ierr);
4579e7b2b25Sstefano_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);
4589e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(T,&lT);CHKERRQ(ierr);
4599e7b2b25Sstefano_zampini         ierr = MatCreateTranspose(lT,&snest[ij]);CHKERRQ(ierr);
4609e7b2b25Sstefano_zampini       } else {
4615e3038f0Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr);
4625e3038f0Sstefano_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);
4639e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr);
4649e7b2b25Sstefano_zampini       }
4655e3038f0Sstefano_zampini 
4665e3038f0Sstefano_zampini       /* Check compatibility of local sizes */
4675e3038f0Sstefano_zampini       ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr);
4689e7b2b25Sstefano_zampini       ierr = MatGetBlockSizes(snest[ij],&lb1,&lb2);CHKERRQ(ierr);
4695e3038f0Sstefano_zampini       if (!l1 || !l2) continue;
4705e3038f0Sstefano_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);
4715e3038f0Sstefano_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);
4725e3038f0Sstefano_zampini       lr[i] = l1;
4735e3038f0Sstefano_zampini       lc[j] = l2;
4745e3038f0Sstefano_zampini 
4755e3038f0Sstefano_zampini       /* check compatibilty for local matrix reusage */
4765e3038f0Sstefano_zampini       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
4775e3038f0Sstefano_zampini     }
4785e3038f0Sstefano_zampini   }
4795e3038f0Sstefano_zampini 
4805e3038f0Sstefano_zampini #if defined (PETSC_USE_DEBUG)
4815e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for rows */
4825e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
4835e3038f0Sstefano_zampini     rl2g = NULL;
4845e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
4855e3038f0Sstefano_zampini       PetscInt n1,n2;
4865e3038f0Sstefano_zampini 
4875e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
4889e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
4899e7b2b25Sstefano_zampini         Mat T;
4909e7b2b25Sstefano_zampini 
4919e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
4929e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,NULL,&cl2g);CHKERRQ(ierr);
4939e7b2b25Sstefano_zampini       } else {
4945e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr);
4959e7b2b25Sstefano_zampini       }
4965e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
4975e3038f0Sstefano_zampini       if (!n1) continue;
4985e3038f0Sstefano_zampini       if (!rl2g) {
4995e3038f0Sstefano_zampini         rl2g = cl2g;
5005e3038f0Sstefano_zampini       } else {
5015e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
5025e3038f0Sstefano_zampini         PetscBool      same;
5035e3038f0Sstefano_zampini 
5045e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
5055e3038f0Sstefano_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);
5065e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
5075e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
5085e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
5095e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
5105e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
5115e3038f0Sstefano_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);
5125e3038f0Sstefano_zampini       }
5135e3038f0Sstefano_zampini     }
5145e3038f0Sstefano_zampini   }
5155e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for columns */
5165e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
5175e3038f0Sstefano_zampini     rl2g = NULL;
5185e3038f0Sstefano_zampini     for (j=0;j<nr;j++) {
5195e3038f0Sstefano_zampini       PetscInt n1,n2;
5205e3038f0Sstefano_zampini 
5215e3038f0Sstefano_zampini       if (!nest[j][i]) continue;
5229e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
5239e7b2b25Sstefano_zampini         Mat T;
5249e7b2b25Sstefano_zampini 
5259e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[j][i],&T);CHKERRQ(ierr);
5269e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,&cl2g,NULL);CHKERRQ(ierr);
5279e7b2b25Sstefano_zampini       } else {
5285e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr);
5299e7b2b25Sstefano_zampini       }
5305e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
5315e3038f0Sstefano_zampini       if (!n1) continue;
5325e3038f0Sstefano_zampini       if (!rl2g) {
5335e3038f0Sstefano_zampini         rl2g = cl2g;
5345e3038f0Sstefano_zampini       } else {
5355e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
5365e3038f0Sstefano_zampini         PetscBool      same;
5375e3038f0Sstefano_zampini 
5385e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
5395e3038f0Sstefano_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);
5405e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
5415e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
5425e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
5435e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
5445e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
5455e3038f0Sstefano_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);
5465e3038f0Sstefano_zampini       }
5475e3038f0Sstefano_zampini     }
5485e3038f0Sstefano_zampini   }
5495e3038f0Sstefano_zampini #endif
5505e3038f0Sstefano_zampini 
5515e3038f0Sstefano_zampini   B = NULL;
5525e3038f0Sstefano_zampini   if (reuse != MAT_REUSE_MATRIX) {
5535b003df0Sstefano_zampini     PetscInt stl;
5545b003df0Sstefano_zampini 
5555e3038f0Sstefano_zampini     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
5565e3038f0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) stl += lr[i];
5575e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
5585b003df0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) {
5595e3038f0Sstefano_zampini       Mat            usedmat;
5605e3038f0Sstefano_zampini       Mat_IS         *matis;
5615e3038f0Sstefano_zampini       const PetscInt *idxs;
5625e3038f0Sstefano_zampini 
5635e3038f0Sstefano_zampini       /* local IS for local NEST */
5645b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
5655e3038f0Sstefano_zampini 
5665e3038f0Sstefano_zampini       /* l2gmap */
5675e3038f0Sstefano_zampini       j = 0;
5685e3038f0Sstefano_zampini       usedmat = nest[i][j];
5699e7b2b25Sstefano_zampini       while (!usedmat && j < nc-1) usedmat = nest[i][++j];
5709e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid row mat");
5719e7b2b25Sstefano_zampini 
5729e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
5739e7b2b25Sstefano_zampini         Mat T;
5749e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
5759e7b2b25Sstefano_zampini         usedmat = T;
5769e7b2b25Sstefano_zampini       }
57782d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
5785e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
5795e3038f0Sstefano_zampini       ierr  = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr);
5809e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
5819e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
5829e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
5839e7b2b25Sstefano_zampini       } else {
5845e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
5855e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
5869e7b2b25Sstefano_zampini       }
5875e3038f0Sstefano_zampini       ierr = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr);
5885e3038f0Sstefano_zampini       stl += lr[i];
5895e3038f0Sstefano_zampini     }
5905e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr);
5915e3038f0Sstefano_zampini 
5925e3038f0Sstefano_zampini     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
5935e3038f0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) stl += lc[i];
5945e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
5955b003df0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) {
5965e3038f0Sstefano_zampini       Mat            usedmat;
5975e3038f0Sstefano_zampini       Mat_IS         *matis;
5985e3038f0Sstefano_zampini       const PetscInt *idxs;
5995e3038f0Sstefano_zampini 
6005e3038f0Sstefano_zampini       /* local IS for local NEST */
6015b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
6025e3038f0Sstefano_zampini 
6035e3038f0Sstefano_zampini       /* l2gmap */
6045e3038f0Sstefano_zampini       j = 0;
6055e3038f0Sstefano_zampini       usedmat = nest[j][i];
6069e7b2b25Sstefano_zampini       while (!usedmat && j < nr-1) usedmat = nest[++j][i];
6079e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid column mat");
6089e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
6099e7b2b25Sstefano_zampini         Mat T;
6109e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
6119e7b2b25Sstefano_zampini         usedmat = T;
6129e7b2b25Sstefano_zampini       }
61382d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
6145e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
6155e3038f0Sstefano_zampini       ierr  = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr);
6169e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
6179e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
6189e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
6199e7b2b25Sstefano_zampini       } else {
6205e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
6215e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
6229e7b2b25Sstefano_zampini       }
6235e3038f0Sstefano_zampini       ierr = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr);
6245e3038f0Sstefano_zampini       stl += lc[i];
6255e3038f0Sstefano_zampini     }
6265e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr);
6275e3038f0Sstefano_zampini 
6285e3038f0Sstefano_zampini     /* Create MATIS */
6295e3038f0Sstefano_zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
6305e3038f0Sstefano_zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
6315e3038f0Sstefano_zampini     ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr);
6325e3038f0Sstefano_zampini     ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr);
6335e3038f0Sstefano_zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
6345e3038f0Sstefano_zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
6355e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
6365e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
6375e3038f0Sstefano_zampini     ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
6389e7b2b25Sstefano_zampini     for (i=0;i<nr*nc;i++) {
6399e7b2b25Sstefano_zampini       if (istrans[i]) {
6409e7b2b25Sstefano_zampini         ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
6419e7b2b25Sstefano_zampini       }
6429e7b2b25Sstefano_zampini     }
6435e3038f0Sstefano_zampini     ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
6445e3038f0Sstefano_zampini     ierr = MatDestroy(&lA);CHKERRQ(ierr);
6455e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6465e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6475e3038f0Sstefano_zampini     if (reuse == MAT_INPLACE_MATRIX) {
6485e3038f0Sstefano_zampini       ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
6495e3038f0Sstefano_zampini     } else {
6505e3038f0Sstefano_zampini       *newmat = B;
6515e3038f0Sstefano_zampini     }
6525e3038f0Sstefano_zampini   } else {
6535e3038f0Sstefano_zampini     if (lreuse) {
6545e3038f0Sstefano_zampini       ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
6555e3038f0Sstefano_zampini       for (i=0;i<nr;i++) {
6565e3038f0Sstefano_zampini         for (j=0;j<nc;j++) {
6575e3038f0Sstefano_zampini           if (snest[i*nc+j]) {
6585e3038f0Sstefano_zampini             ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr);
6599e7b2b25Sstefano_zampini             if (istrans[i*nc+j]) {
6609e7b2b25Sstefano_zampini               ierr = MatDestroy(&snest[i*nc+j]);CHKERRQ(ierr);
6619e7b2b25Sstefano_zampini             }
6625e3038f0Sstefano_zampini           }
6635e3038f0Sstefano_zampini         }
6645e3038f0Sstefano_zampini       }
6655e3038f0Sstefano_zampini     } else {
6665b003df0Sstefano_zampini       PetscInt stl;
6675b003df0Sstefano_zampini       for (i=0,stl=0;i<nr;i++) {
6685b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
6695b003df0Sstefano_zampini         stl  += lr[i];
6705e3038f0Sstefano_zampini       }
6715b003df0Sstefano_zampini       for (i=0,stl=0;i<nc;i++) {
6725b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
6735b003df0Sstefano_zampini         stl  += lc[i];
6745e3038f0Sstefano_zampini       }
6755e3038f0Sstefano_zampini       ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
676ab4d48faSStefano Zampini       for (i=0;i<nr*nc;i++) {
6779e7b2b25Sstefano_zampini         if (istrans[i]) {
6789e7b2b25Sstefano_zampini           ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
6799e7b2b25Sstefano_zampini         }
680ab4d48faSStefano Zampini       }
6815e3038f0Sstefano_zampini       ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
6825e3038f0Sstefano_zampini       ierr = MatDestroy(&lA);CHKERRQ(ierr);
6835e3038f0Sstefano_zampini     }
6845e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6855e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6865e3038f0Sstefano_zampini   }
6875e3038f0Sstefano_zampini 
6885b003df0Sstefano_zampini   /* Create local matrix in MATNEST format */
6895b003df0Sstefano_zampini   convert = PETSC_FALSE;
6905b003df0Sstefano_zampini   ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr);
6915b003df0Sstefano_zampini   if (convert) {
6925b003df0Sstefano_zampini     Mat              M;
6935b003df0Sstefano_zampini     MatISLocalFields lf;
6945b003df0Sstefano_zampini     PetscContainer   c;
6955b003df0Sstefano_zampini 
6965b003df0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
6975b003df0Sstefano_zampini     ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr);
6985b003df0Sstefano_zampini     ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr);
6995b003df0Sstefano_zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
7005b003df0Sstefano_zampini 
7015b003df0Sstefano_zampini     /* attach local fields to the matrix */
7025b003df0Sstefano_zampini     ierr = PetscNew(&lf);CHKERRQ(ierr);
7035b003df0Sstefano_zampini     ierr = PetscCalloc2(nr,&lf->rf,nc,&lf->cf);CHKERRQ(ierr);
7045b003df0Sstefano_zampini     for (i=0;i<nr;i++) {
7055b003df0Sstefano_zampini       PetscInt n,st;
7065b003df0Sstefano_zampini 
7075b003df0Sstefano_zampini       ierr = ISGetLocalSize(islrow[i],&n);CHKERRQ(ierr);
7085b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islrow[i],&st,NULL);CHKERRQ(ierr);
7095b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->rf[i]);CHKERRQ(ierr);
7105b003df0Sstefano_zampini     }
7115b003df0Sstefano_zampini     for (i=0;i<nc;i++) {
7125b003df0Sstefano_zampini       PetscInt n,st;
7135b003df0Sstefano_zampini 
7145b003df0Sstefano_zampini       ierr = ISGetLocalSize(islcol[i],&n);CHKERRQ(ierr);
7155b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islcol[i],&st,NULL);CHKERRQ(ierr);
7165b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->cf[i]);CHKERRQ(ierr);
7175b003df0Sstefano_zampini     }
7185b003df0Sstefano_zampini     lf->nr = nr;
7195b003df0Sstefano_zampini     lf->nc = nc;
7205b003df0Sstefano_zampini     ierr = PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c);CHKERRQ(ierr);
7215b003df0Sstefano_zampini     ierr = PetscContainerSetPointer(c,lf);CHKERRQ(ierr);
7225b003df0Sstefano_zampini     ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private);CHKERRQ(ierr);
7235b003df0Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c);CHKERRQ(ierr);
7245b003df0Sstefano_zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
7255b003df0Sstefano_zampini   }
7265b003df0Sstefano_zampini 
7275e3038f0Sstefano_zampini   /* Free workspace */
7285e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
7295e3038f0Sstefano_zampini     ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr);
7305e3038f0Sstefano_zampini   }
7315e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
7325e3038f0Sstefano_zampini     ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr);
7335e3038f0Sstefano_zampini   }
7349e7b2b25Sstefano_zampini   ierr = PetscFree6(isrow,iscol,islrow,islcol,snest,istrans);CHKERRQ(ierr);
7355b003df0Sstefano_zampini   ierr = PetscFree2(lr,lc);CHKERRQ(ierr);
7365e3038f0Sstefano_zampini   PetscFunctionReturn(0);
7375e3038f0Sstefano_zampini }
7385e3038f0Sstefano_zampini 
739ad219c80Sstefano_zampini static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r)
740ad219c80Sstefano_zampini {
741ad219c80Sstefano_zampini   Mat_IS            *matis = (Mat_IS*)A->data;
742ad219c80Sstefano_zampini   Vec               ll,rr;
743ad219c80Sstefano_zampini   const PetscScalar *Y,*X;
744ad219c80Sstefano_zampini   PetscScalar       *x,*y;
745ad219c80Sstefano_zampini   PetscErrorCode    ierr;
746ad219c80Sstefano_zampini 
747ad219c80Sstefano_zampini   PetscFunctionBegin;
748ad219c80Sstefano_zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
749ad219c80Sstefano_zampini   if (l) {
750ad219c80Sstefano_zampini     ll   = matis->y;
751ad219c80Sstefano_zampini     ierr = VecGetArrayRead(l,&Y);CHKERRQ(ierr);
752ad219c80Sstefano_zampini     ierr = VecGetArray(ll,&y);CHKERRQ(ierr);
753ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
754ad219c80Sstefano_zampini   } else {
755ad219c80Sstefano_zampini     ll = NULL;
756ad219c80Sstefano_zampini   }
757ad219c80Sstefano_zampini   if (r) {
758ad219c80Sstefano_zampini     rr   = matis->x;
759ad219c80Sstefano_zampini     ierr = VecGetArrayRead(r,&X);CHKERRQ(ierr);
760ad219c80Sstefano_zampini     ierr = VecGetArray(rr,&x);CHKERRQ(ierr);
761ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
762ad219c80Sstefano_zampini   } else {
763ad219c80Sstefano_zampini     rr = NULL;
764ad219c80Sstefano_zampini   }
765ad219c80Sstefano_zampini   if (ll) {
766ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
767ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(l,&Y);CHKERRQ(ierr);
768ad219c80Sstefano_zampini     ierr = VecRestoreArray(ll,&y);CHKERRQ(ierr);
769ad219c80Sstefano_zampini   }
770ad219c80Sstefano_zampini   if (rr) {
771ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
772ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(r,&X);CHKERRQ(ierr);
773ad219c80Sstefano_zampini     ierr = VecRestoreArray(rr,&x);CHKERRQ(ierr);
774ad219c80Sstefano_zampini   }
775ad219c80Sstefano_zampini   ierr = MatDiagonalScale(matis->A,ll,rr);CHKERRQ(ierr);
776ad219c80Sstefano_zampini   PetscFunctionReturn(0);
777ad219c80Sstefano_zampini }
778ad219c80Sstefano_zampini 
7797fa8f2d3SStefano Zampini static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo)
7807fa8f2d3SStefano Zampini {
7817fa8f2d3SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
7827fa8f2d3SStefano Zampini   MatInfo        info;
7837fa8f2d3SStefano Zampini   PetscReal      isend[6],irecv[6];
7847fa8f2d3SStefano Zampini   PetscInt       bs;
7857fa8f2d3SStefano Zampini   PetscErrorCode ierr;
7867fa8f2d3SStefano Zampini 
7877fa8f2d3SStefano Zampini   PetscFunctionBegin;
7887fa8f2d3SStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
7897fa8f2d3SStefano Zampini   if (matis->A->ops->getinfo) {
7907fa8f2d3SStefano Zampini     ierr     = MatGetInfo(matis->A,MAT_LOCAL,&info);CHKERRQ(ierr);
7917fa8f2d3SStefano Zampini     isend[0] = info.nz_used;
7927fa8f2d3SStefano Zampini     isend[1] = info.nz_allocated;
7937fa8f2d3SStefano Zampini     isend[2] = info.nz_unneeded;
7947fa8f2d3SStefano Zampini     isend[3] = info.memory;
7957fa8f2d3SStefano Zampini     isend[4] = info.mallocs;
7967fa8f2d3SStefano Zampini   } else {
7977fa8f2d3SStefano Zampini     isend[0] = 0.;
7987fa8f2d3SStefano Zampini     isend[1] = 0.;
7997fa8f2d3SStefano Zampini     isend[2] = 0.;
8007fa8f2d3SStefano Zampini     isend[3] = 0.;
8017fa8f2d3SStefano Zampini     isend[4] = 0.;
8027fa8f2d3SStefano Zampini   }
8037fa8f2d3SStefano Zampini   isend[5] = matis->A->num_ass;
8047fa8f2d3SStefano Zampini   if (flag == MAT_LOCAL) {
8057fa8f2d3SStefano Zampini     ginfo->nz_used      = isend[0];
8067fa8f2d3SStefano Zampini     ginfo->nz_allocated = isend[1];
8077fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = isend[2];
8087fa8f2d3SStefano Zampini     ginfo->memory       = isend[3];
8097fa8f2d3SStefano Zampini     ginfo->mallocs      = isend[4];
8107fa8f2d3SStefano Zampini     ginfo->assemblies   = isend[5];
8117fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_MAX) {
8127fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,6,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
8137fa8f2d3SStefano Zampini 
8147fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
8157fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
8167fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
8177fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
8187fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
8197fa8f2d3SStefano Zampini     ginfo->assemblies   = irecv[5];
8207fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_SUM) {
8217fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
8227fa8f2d3SStefano Zampini 
8237fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
8247fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
8257fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
8267fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
8277fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
8287fa8f2d3SStefano Zampini     ginfo->assemblies   = A->num_ass;
829d7f69cd0SStefano Zampini   }
830d7f69cd0SStefano Zampini   ginfo->block_size        = bs;
831d7f69cd0SStefano Zampini   ginfo->fill_ratio_given  = 0;
832d7f69cd0SStefano Zampini   ginfo->fill_ratio_needed = 0;
833d7f69cd0SStefano Zampini   ginfo->factor_mallocs    = 0;
8345e3038f0Sstefano_zampini   PetscFunctionReturn(0);
8355e3038f0Sstefano_zampini }
8365e3038f0Sstefano_zampini 
837d7f69cd0SStefano Zampini PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
838d7f69cd0SStefano Zampini {
839d7f69cd0SStefano Zampini   Mat                    C,lC,lA;
840d7f69cd0SStefano Zampini   PetscErrorCode         ierr;
841d7f69cd0SStefano Zampini 
842d7f69cd0SStefano Zampini   PetscFunctionBegin;
843cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) {
844cf37664fSBarry Smith     ISLocalToGlobalMapping rl2g,cl2g;
845d7f69cd0SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
846d7f69cd0SStefano Zampini     ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr);
847d7f69cd0SStefano Zampini     ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
848d7f69cd0SStefano Zampini     ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
849d7f69cd0SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
850d7f69cd0SStefano Zampini     ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr);
851cf37664fSBarry Smith   } else {
852cf37664fSBarry Smith     C = *B;
853d7f69cd0SStefano Zampini   }
854d7f69cd0SStefano Zampini 
855d7f69cd0SStefano Zampini   /* perform local transposition */
856d7f69cd0SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
857d7f69cd0SStefano Zampini   ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr);
858d7f69cd0SStefano Zampini   ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
859d7f69cd0SStefano Zampini   ierr = MatDestroy(&lC);CHKERRQ(ierr);
860d7f69cd0SStefano Zampini 
861cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) {
862d7f69cd0SStefano Zampini     *B = C;
863d7f69cd0SStefano Zampini   } else {
864d7f69cd0SStefano Zampini     ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr);
865d7f69cd0SStefano Zampini   }
8667aa7aec5Sstefano_zampini   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
8677aa7aec5Sstefano_zampini   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
868d7f69cd0SStefano Zampini   PetscFunctionReturn(0);
869d7f69cd0SStefano Zampini }
870d7f69cd0SStefano Zampini 
8713fd1c9e7SStefano Zampini PetscErrorCode  MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
8723fd1c9e7SStefano Zampini {
8733fd1c9e7SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
8743fd1c9e7SStefano Zampini   PetscErrorCode ierr;
8753fd1c9e7SStefano Zampini 
8763fd1c9e7SStefano Zampini   PetscFunctionBegin;
8774b89b9cdSStefano Zampini   if (D) { /* MatShift_IS pass D = NULL */
8783fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8793fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8803fd1c9e7SStefano Zampini   }
8813fd1c9e7SStefano Zampini   ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr);
8823fd1c9e7SStefano Zampini   ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr);
8833fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
8843fd1c9e7SStefano Zampini }
8853fd1c9e7SStefano Zampini 
8863fd1c9e7SStefano Zampini PetscErrorCode  MatShift_IS(Mat A,PetscScalar a)
8873fd1c9e7SStefano Zampini {
8884b89b9cdSStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
8893fd1c9e7SStefano Zampini   PetscErrorCode ierr;
8903fd1c9e7SStefano Zampini 
8913fd1c9e7SStefano Zampini   PetscFunctionBegin;
8924b89b9cdSStefano Zampini   ierr = VecSet(is->y,a);CHKERRQ(ierr);
8933fd1c9e7SStefano Zampini   ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr);
8943fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
8953fd1c9e7SStefano Zampini }
8963fd1c9e7SStefano Zampini 
897f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
898f26d0771SStefano Zampini {
899f26d0771SStefano Zampini   PetscErrorCode ierr;
900f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
901f26d0771SStefano Zampini 
902f26d0771SStefano Zampini   PetscFunctionBegin;
903f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
904f26d0771SStefano 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);
905f26d0771SStefano Zampini #endif
906f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
907f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
908b4f971dfSStefano Zampini   ierr = MatSetValuesLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
909f26d0771SStefano Zampini   PetscFunctionReturn(0);
910f26d0771SStefano Zampini }
911f26d0771SStefano Zampini 
912f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
913f26d0771SStefano Zampini {
914f26d0771SStefano Zampini   PetscErrorCode ierr;
915f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
916f26d0771SStefano Zampini 
917f26d0771SStefano Zampini   PetscFunctionBegin;
918f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
919f26d0771SStefano 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);
920f26d0771SStefano Zampini #endif
921f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
922f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
923b4f971dfSStefano Zampini   ierr = MatSetValuesBlockedLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
924f26d0771SStefano Zampini   PetscFunctionReturn(0);
925f26d0771SStefano Zampini }
926f26d0771SStefano Zampini 
927f0ae7da4SStefano Zampini static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
928a8116848SStefano Zampini {
929a8116848SStefano Zampini   PetscInt      *owners = map->range;
930a8116848SStefano Zampini   PetscInt       n      = map->n;
931a8116848SStefano Zampini   PetscSF        sf;
932a8116848SStefano Zampini   PetscInt      *lidxs,*work = NULL;
933a8116848SStefano Zampini   PetscSFNode   *ridxs;
934a8116848SStefano Zampini   PetscMPIInt    rank;
935a8116848SStefano Zampini   PetscInt       r, p = 0, len = 0;
936a8116848SStefano Zampini   PetscErrorCode ierr;
937a8116848SStefano Zampini 
938a8116848SStefano Zampini   PetscFunctionBegin;
939fd3a879cSJed Brown   if (on) *on = 0;              /* squelch -Wmaybe-uninitialized */
940a8116848SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */
941a8116848SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
942a8116848SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
943a8116848SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
944a8116848SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
945a8116848SStefano Zampini   for (r = 0; r < N; ++r) {
946a8116848SStefano Zampini     const PetscInt idx = idxs[r];
947a8116848SStefano 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);
948a8116848SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
949a8116848SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
950a8116848SStefano Zampini     }
951a8116848SStefano Zampini     ridxs[r].rank = p;
952a8116848SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
953a8116848SStefano Zampini   }
954a8116848SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
955a8116848SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
956a8116848SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
957a8116848SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
958f0ae7da4SStefano Zampini   if (ogidxs) { /* communicate global idxs */
959a8116848SStefano Zampini     PetscInt cum = 0,start,*work2;
960f0ae7da4SStefano Zampini 
961f0ae7da4SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
962a8116848SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
963a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
964a8116848SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
965a8116848SStefano Zampini     start -= cum;
966a8116848SStefano Zampini     cum = 0;
967a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
968a8116848SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
969a8116848SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
970a8116848SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
971a8116848SStefano Zampini   }
972a8116848SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
973a8116848SStefano Zampini   /* Compress and put in indices */
974a8116848SStefano Zampini   for (r = 0; r < n; ++r)
975a8116848SStefano Zampini     if (lidxs[r] >= 0) {
976a8116848SStefano Zampini       if (work) work[len] = work[r];
977a8116848SStefano Zampini       lidxs[len++] = r;
978a8116848SStefano Zampini     }
979a8116848SStefano Zampini   if (on) *on = len;
980a8116848SStefano Zampini   if (oidxs) *oidxs = lidxs;
981a8116848SStefano Zampini   if (ogidxs) *ogidxs = work;
982a8116848SStefano Zampini   PetscFunctionReturn(0);
983a8116848SStefano Zampini }
984a8116848SStefano Zampini 
9857dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
986a8116848SStefano Zampini {
987a8116848SStefano Zampini   Mat               locmat,newlocmat;
988a8116848SStefano Zampini   Mat_IS            *newmatis;
989a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
990a8116848SStefano Zampini   Vec               rtest,ltest;
991a8116848SStefano Zampini   const PetscScalar *array;
992a8116848SStefano Zampini #endif
993a8116848SStefano Zampini   const PetscInt    *idxs;
994a8116848SStefano Zampini   PetscInt          i,m,n;
995a8116848SStefano Zampini   PetscErrorCode    ierr;
996a8116848SStefano Zampini 
997a8116848SStefano Zampini   PetscFunctionBegin;
998a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
999a8116848SStefano Zampini     PetscBool ismatis;
1000a8116848SStefano Zampini 
1001a8116848SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
1002a8116848SStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
1003a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
1004a8116848SStefano Zampini     if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
1005a8116848SStefano Zampini     if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
1006a8116848SStefano Zampini   }
1007a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
1008a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
1009a8116848SStefano Zampini   ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
1010a8116848SStefano Zampini   ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
1011a8116848SStefano Zampini   ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
1012a8116848SStefano Zampini   for (i=0;i<n;i++) {
1013a8116848SStefano Zampini     ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
1014a8116848SStefano Zampini   }
1015a8116848SStefano Zampini   ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
1016a8116848SStefano Zampini   ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
1017a8116848SStefano Zampini   ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
1018a8116848SStefano Zampini   ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
1019a8116848SStefano Zampini   ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
1020fd479f66SMatthew 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]));
1021a8116848SStefano Zampini   ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
1022a8116848SStefano Zampini   ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
1023a8116848SStefano Zampini   ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
1024a8116848SStefano Zampini   ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
1025a8116848SStefano Zampini   for (i=0;i<n;i++) {
1026a8116848SStefano Zampini     ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
1027a8116848SStefano Zampini   }
1028a8116848SStefano Zampini   ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
1029a8116848SStefano Zampini   ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
1030a8116848SStefano Zampini   ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
1031a8116848SStefano Zampini   ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
1032a8116848SStefano Zampini   ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
1033fd479f66SMatthew 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]));
1034a8116848SStefano Zampini   ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
1035a8116848SStefano Zampini   ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
1036a8116848SStefano Zampini   ierr = VecDestroy(&rtest);CHKERRQ(ierr);
1037a8116848SStefano Zampini   ierr = VecDestroy(&ltest);CHKERRQ(ierr);
1038a8116848SStefano Zampini #endif
1039a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
1040a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
1041a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
1042a8116848SStefano Zampini     IS                     is;
1043a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
1044306cf5c7SStefano Zampini     PetscInt               ll,newloc,irbs,icbs,arbs,acbs,rbs,cbs;
104594342113SStefano Zampini     PetscBool              cong;
1046a8116848SStefano Zampini     MPI_Comm               comm;
1047a8116848SStefano Zampini 
1048a8116848SStefano Zampini     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
1049306cf5c7SStefano Zampini     ierr = MatGetBlockSizes(mat,&arbs,&acbs);CHKERRQ(ierr);
1050306cf5c7SStefano Zampini     ierr = ISGetBlockSize(irow,&irbs);CHKERRQ(ierr);
1051306cf5c7SStefano Zampini     ierr = ISGetBlockSize(icol,&icbs);CHKERRQ(ierr);
1052306cf5c7SStefano Zampini     rbs  = arbs == irbs ? irbs : 1;
1053306cf5c7SStefano Zampini     cbs  = acbs == icbs ? icbs : 1;
1054a8116848SStefano Zampini     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
1055a8116848SStefano Zampini     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
1056a8116848SStefano Zampini     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
1057a8116848SStefano Zampini     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
1058a8116848SStefano Zampini     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1059306cf5c7SStefano Zampini     ierr = MatSetBlockSizes(*newmat,rbs,cbs);CHKERRQ(ierr);
1060a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
1061a8116848SStefano Zampini     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
1062f0ae7da4SStefano Zampini     ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
1063a8116848SStefano Zampini     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
10643d996552SStefano Zampini     ierr = MatISSetUpSF(mat);CHKERRQ(ierr);
10653d996552SStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,matis->sf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
1066a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
1067a8116848SStefano Zampini     ierr = PetscFree(lidxs);CHKERRQ(ierr);
1068a8116848SStefano Zampini     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
1069a8116848SStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
1070a8116848SStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
10713d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
1072a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
1073a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
10743d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++)
1075a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
1076a8116848SStefano Zampini         lidxs[newloc] = i;
1077a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
1078a8116848SStefano Zampini       }
1079a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1080a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
1081306cf5c7SStefano Zampini     ierr = ISLocalToGlobalMappingSetBlockSize(rl2g,rbs);CHKERRQ(ierr);
1082a8116848SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
1083a8116848SStefano Zampini     /* local is to extract local submatrix */
1084a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
1085a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
108694342113SStefano Zampini     ierr = MatHasCongruentLayouts(mat,&cong);CHKERRQ(ierr);
108794342113SStefano Zampini     if (cong && irow == icol && matis->csf == matis->sf) {
1088a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
1089a8116848SStefano Zampini       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
1090a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
1091a8116848SStefano Zampini     } else {
1092a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
1093a8116848SStefano Zampini 
1094a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
1095a8116848SStefano Zampini       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
1096f0ae7da4SStefano Zampini       ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
1097a8116848SStefano Zampini       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
10983d996552SStefano Zampini       ierr = PetscMemzero(matis->csf_rootdata,matis->csf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
1099a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
1100a8116848SStefano Zampini       ierr = PetscFree(lidxs);CHKERRQ(ierr);
1101a8116848SStefano Zampini       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
1102a8116848SStefano Zampini       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
1103a8116848SStefano Zampini       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
11043d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
1105a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
1106a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
11073d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++)
1108a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
1109a8116848SStefano Zampini           lidxs[newloc] = i;
1110a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
1111a8116848SStefano Zampini         }
1112a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1113a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
1114306cf5c7SStefano Zampini       ierr = ISLocalToGlobalMappingSetBlockSize(cl2g,cbs);CHKERRQ(ierr);
1115a8116848SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
1116a8116848SStefano Zampini       /* local is to extract local submatrix */
1117a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
1118a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
1119a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
1120a8116848SStefano Zampini     }
1121a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
1122a8116848SStefano Zampini   } else {
1123a8116848SStefano Zampini     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
1124a8116848SStefano Zampini   }
1125a8116848SStefano Zampini   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
1126a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
11277dae84e0SHong Zhang   ierr = MatCreateSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
1128a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
1129a8116848SStefano Zampini     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
1130a8116848SStefano Zampini     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
1131a8116848SStefano Zampini   }
1132a8116848SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1133a8116848SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1134a8116848SStefano Zampini   PetscFunctionReturn(0);
1135a8116848SStefano Zampini }
1136a8116848SStefano Zampini 
1137a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
11382b404112SStefano Zampini {
11392b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
11402b404112SStefano Zampini   PetscBool      ismatis;
11412b404112SStefano Zampini   PetscErrorCode ierr;
11422b404112SStefano Zampini 
11432b404112SStefano Zampini   PetscFunctionBegin;
11442b404112SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
11452b404112SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
11462b404112SStefano Zampini   b = (Mat_IS*)B->data;
11472b404112SStefano Zampini   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
1148cdc753b6SBarry Smith   ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
11492b404112SStefano Zampini   PetscFunctionReturn(0);
11502b404112SStefano Zampini }
11512b404112SStefano Zampini 
1152a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
11536bd84002SStefano Zampini {
1154527b2640SStefano Zampini   Vec               v;
1155527b2640SStefano Zampini   const PetscScalar *array;
1156527b2640SStefano Zampini   PetscInt          i,n;
11576bd84002SStefano Zampini   PetscErrorCode    ierr;
11586bd84002SStefano Zampini 
11596bd84002SStefano Zampini   PetscFunctionBegin;
1160527b2640SStefano Zampini   *missing = PETSC_FALSE;
1161527b2640SStefano Zampini   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
1162527b2640SStefano Zampini   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
1163527b2640SStefano Zampini   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1164527b2640SStefano Zampini   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
1165527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
1166527b2640SStefano Zampini   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
1167527b2640SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
1168527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
1169527b2640SStefano Zampini   if (d) {
1170527b2640SStefano Zampini     *d = -1;
1171527b2640SStefano Zampini     if (*missing) {
1172527b2640SStefano Zampini       PetscInt rstart;
1173527b2640SStefano Zampini       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
1174527b2640SStefano Zampini       *d = i+rstart;
1175527b2640SStefano Zampini     }
1176527b2640SStefano Zampini   }
11776bd84002SStefano Zampini   PetscFunctionReturn(0);
11786bd84002SStefano Zampini }
11796bd84002SStefano Zampini 
1180cf0a3239SStefano Zampini static PetscErrorCode MatISSetUpSF_IS(Mat B)
118128f4e0baSStefano Zampini {
118228f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
118328f4e0baSStefano Zampini   const PetscInt *gidxs;
11844f2d7cafSStefano Zampini   PetscInt       nleaves;
118528f4e0baSStefano Zampini   PetscErrorCode ierr;
118628f4e0baSStefano Zampini 
118728f4e0baSStefano Zampini   PetscFunctionBegin;
11884f2d7cafSStefano Zampini   if (matis->sf) PetscFunctionReturn(0);
118975d48cdbSStefano Zampini   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
119075d48cdbSStefano Zampini   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
119128f4e0baSStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
11923bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
11934f2d7cafSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(B->rmap->mapping,&nleaves);CHKERRQ(ierr);
11944f2d7cafSStefano Zampini   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
11953bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
11964f2d7cafSStefano Zampini   ierr = PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
1197a8116848SStefano Zampini   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
11983d996552SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(B->cmap->mapping,&nleaves);CHKERRQ(ierr);
1199a8116848SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
1200a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
12013d996552SStefano Zampini     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
1202a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
12033d996552SStefano Zampini     ierr = PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
1204a8116848SStefano Zampini   } else {
1205a8116848SStefano Zampini     matis->csf = matis->sf;
1206a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
1207a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
1208a8116848SStefano Zampini   }
120928f4e0baSStefano Zampini   PetscFunctionReturn(0);
121028f4e0baSStefano Zampini }
12112e1947a5SStefano Zampini 
1212eb82efa4SStefano Zampini /*@
121375d48cdbSStefano Zampini    MatISStoreL2L - Store local-to-local operators during the Galerkin process of MatPtAP.
121475d48cdbSStefano Zampini 
121575d48cdbSStefano Zampini    Collective on MPI_Comm
121675d48cdbSStefano Zampini 
121775d48cdbSStefano Zampini    Input Parameters:
121875d48cdbSStefano Zampini +  A - the matrix
121975d48cdbSStefano Zampini -  store - the boolean flag
122075d48cdbSStefano Zampini 
122175d48cdbSStefano Zampini    Level: advanced
122275d48cdbSStefano Zampini 
122375d48cdbSStefano Zampini    Notes:
122475d48cdbSStefano Zampini 
122575d48cdbSStefano Zampini .keywords: matrix
122675d48cdbSStefano Zampini 
122775d48cdbSStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatPtAP()
122875d48cdbSStefano Zampini @*/
122975d48cdbSStefano Zampini PetscErrorCode  MatISStoreL2L(Mat A, PetscBool store)
123075d48cdbSStefano Zampini {
123175d48cdbSStefano Zampini   PetscErrorCode ierr;
123275d48cdbSStefano Zampini 
123375d48cdbSStefano Zampini   PetscFunctionBegin;
123475d48cdbSStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
123575d48cdbSStefano Zampini   PetscValidType(A,1);
123675d48cdbSStefano Zampini   PetscValidLogicalCollectiveBool(A,store,2);
123775d48cdbSStefano Zampini   ierr = PetscTryMethod(A,"MatISStoreL2L_C",(Mat,PetscBool),(A,store));CHKERRQ(ierr);
123875d48cdbSStefano Zampini   PetscFunctionReturn(0);
123975d48cdbSStefano Zampini }
124075d48cdbSStefano Zampini 
124175d48cdbSStefano Zampini static PetscErrorCode MatISStoreL2L_IS(Mat A, PetscBool store)
124275d48cdbSStefano Zampini {
124375d48cdbSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(A->data);
124475d48cdbSStefano Zampini   PetscErrorCode ierr;
124575d48cdbSStefano Zampini 
124675d48cdbSStefano Zampini   PetscFunctionBegin;
124775d48cdbSStefano Zampini   matis->storel2l = store;
124875d48cdbSStefano Zampini   if (!store) {
124975d48cdbSStefano Zampini     ierr = PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",NULL);CHKERRQ(ierr);
125075d48cdbSStefano Zampini   }
125175d48cdbSStefano Zampini   PetscFunctionReturn(0);
125275d48cdbSStefano Zampini }
125375d48cdbSStefano Zampini 
125475d48cdbSStefano Zampini /*@
1255a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
1256a88811baSStefano Zampini 
1257a88811baSStefano Zampini    Collective on MPI_Comm
1258a88811baSStefano Zampini 
1259a88811baSStefano Zampini    Input Parameters:
1260a88811baSStefano Zampini +  B - the matrix
1261a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1262a88811baSStefano Zampini            (same value is used for all local rows)
1263a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
1264a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
1265a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
1266a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
1267a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
1268a88811baSStefano Zampini            the diagonal entry even if it is zero.
1269a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1270a88811baSStefano Zampini            submatrix (same value is used for all local rows).
1271a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
1272a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
1273a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
1274a88811baSStefano Zampini            structure. The size of this array is equal to the number
1275a88811baSStefano Zampini            of local rows, i.e 'm'.
1276a88811baSStefano Zampini 
1277a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
1278a88811baSStefano Zampini 
1279a88811baSStefano Zampini    Level: intermediate
1280a88811baSStefano Zampini 
128195452b02SPatrick Sanan    Notes:
128295452b02SPatrick Sanan     This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
1283a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
1284a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
1285a88811baSStefano Zampini 
1286a88811baSStefano Zampini .keywords: matrix
1287a88811baSStefano Zampini 
12883c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
1289a88811baSStefano Zampini @*/
12902e1947a5SStefano Zampini PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
12912e1947a5SStefano Zampini {
12922e1947a5SStefano Zampini   PetscErrorCode ierr;
12932e1947a5SStefano Zampini 
12942e1947a5SStefano Zampini   PetscFunctionBegin;
12952e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
12962e1947a5SStefano Zampini   PetscValidType(B,1);
12972e1947a5SStefano Zampini   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
12982e1947a5SStefano Zampini   PetscFunctionReturn(0);
12992e1947a5SStefano Zampini }
13002e1947a5SStefano Zampini 
1301*844bd0d7SStefano Zampini /* this is used by DMDA */
1302*844bd0d7SStefano Zampini PETSC_EXTERN PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
13032e1947a5SStefano Zampini {
13042e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
130528f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
13062e1947a5SStefano Zampini   PetscErrorCode ierr;
13072e1947a5SStefano Zampini 
13082e1947a5SStefano Zampini   PetscFunctionBegin;
13096c4ed002SBarry Smith   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
1310cf0a3239SStefano Zampini   ierr = MatISSetUpSF(B);CHKERRQ(ierr);
13114f2d7cafSStefano Zampini 
13124f2d7cafSStefano Zampini   if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz;
13134f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
13144f2d7cafSStefano Zampini 
13154f2d7cafSStefano Zampini   if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz;
13164f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
13174f2d7cafSStefano Zampini 
131828f4e0baSStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
131928f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
132028f4e0baSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
132128f4e0baSStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
13224f2d7cafSStefano Zampini 
13234f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
132428f4e0baSStefano Zampini   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
13250f2f62c7SStefano Zampini #if defined(PETSC_HAVE_HYPRE)
13260f2f62c7SStefano Zampini   ierr = MatHYPRESetPreallocation(matis->A,0,matis->sf_leafdata,0,NULL);CHKERRQ(ierr);
13270f2f62c7SStefano Zampini #endif
13284f2d7cafSStefano Zampini 
13294f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
133028f4e0baSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
13314f2d7cafSStefano Zampini 
13324f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i]-i;
133328f4e0baSStefano Zampini   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
13340f2f62c7SStefano Zampini 
13350f2f62c7SStefano Zampini   /* for other matrix types */
13360f2f62c7SStefano Zampini   ierr = MatSetUp(matis->A);CHKERRQ(ierr);
13372e1947a5SStefano Zampini   PetscFunctionReturn(0);
13382e1947a5SStefano Zampini }
1339b4319ba4SBarry Smith 
13403927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
13413927de2eSStefano Zampini {
13423927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
13433927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
1344ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
13453927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
13463927de2eSStefano Zampini   PetscInt        lrows,lcols;
13473927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
13483927de2eSStefano Zampini   PetscMPIInt     nsubdomains;
13493927de2eSStefano Zampini   PetscBool       isdense,issbaij;
13503927de2eSStefano Zampini   PetscErrorCode  ierr;
13513927de2eSStefano Zampini 
13523927de2eSStefano Zampini   PetscFunctionBegin;
13533927de2eSStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&nsubdomains);CHKERRQ(ierr);
13543927de2eSStefano Zampini   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
13553927de2eSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
13563927de2eSStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
13573927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
13583927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1359ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1360ecf5a873SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
13617230de76SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1362ecf5a873SStefano Zampini   } else {
1363ecf5a873SStefano Zampini     global_indices_c = global_indices_r;
1364ecf5a873SStefano Zampini   }
1365ecf5a873SStefano Zampini 
13663927de2eSStefano Zampini   if (issbaij) {
13673927de2eSStefano Zampini     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
13683927de2eSStefano Zampini   }
13693927de2eSStefano Zampini   /*
1370ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
13713927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
13723927de2eSStefano Zampini   */
1373cf0a3239SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
13743927de2eSStefano Zampini   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
13753927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
13763927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
13773927de2eSStefano Zampini   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
13783927de2eSStefano Zampini   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
13793927de2eSStefano Zampini   for (i=0;i<nsubdomains;i++) {
13803927de2eSStefano Zampini     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
13813927de2eSStefano Zampini       row_ownership[j] = i;
13823927de2eSStefano Zampini     }
13833927de2eSStefano Zampini   }
13847230de76SStefano Zampini   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
13853927de2eSStefano Zampini 
13863927de2eSStefano Zampini   /*
13873927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
13883927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
13893927de2eSStefano Zampini   */
13903927de2eSStefano Zampini   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
13913927de2eSStefano Zampini   /* preallocation as a MATAIJ */
13923927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
13933927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
139412dfadf8SStefano Zampini       PetscInt owner = row_ownership[global_indices_r[i]];
139512dfadf8SStefano Zampini       for (j=0;j<local_cols;j++) {
1396ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
13973927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
13983927de2eSStefano Zampini           my_dnz[i] += 1;
13993927de2eSStefano Zampini         } else { /* offdiag block */
14003927de2eSStefano Zampini           my_onz[i] += 1;
14013927de2eSStefano Zampini         }
14023927de2eSStefano Zampini       }
14033927de2eSStefano Zampini     }
1404bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
1405bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
1406bb1015c3SStefano Zampini     PetscBool      done;
1407bb1015c3SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1408938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1409bb1015c3SStefano Zampini     jptr = jj;
1410bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
1411bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
1412bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
1413bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
1414bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
1415bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
1416bb1015c3SStefano Zampini           my_dnz[i] += 1;
1417bb1015c3SStefano Zampini         } else { /* offdiag block */
1418bb1015c3SStefano Zampini           my_onz[i] += 1;
1419bb1015c3SStefano Zampini         }
1420bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
1421bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
1422bb1015c3SStefano Zampini           owner = row_ownership[index_col];
1423bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1424bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
1425bb1015c3SStefano Zampini           } else {
1426bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
1427bb1015c3SStefano Zampini           }
1428bb1015c3SStefano Zampini         }
1429bb1015c3SStefano Zampini       }
1430bb1015c3SStefano Zampini     }
1431bb1015c3SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1432938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1433bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
14343927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
14353927de2eSStefano Zampini       const PetscInt *cols;
1436ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
14373927de2eSStefano Zampini       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
14383927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
14393927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
1440ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
14413927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
14423927de2eSStefano Zampini           my_dnz[i] += 1;
14433927de2eSStefano Zampini         } else { /* offdiag block */
14443927de2eSStefano Zampini           my_onz[i] += 1;
14453927de2eSStefano Zampini         }
14463927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
1447d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
14483927de2eSStefano Zampini           owner = row_ownership[index_col];
14493927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1450d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
14513927de2eSStefano Zampini           } else {
1452d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
14533927de2eSStefano Zampini           }
14543927de2eSStefano Zampini         }
14553927de2eSStefano Zampini       }
14563927de2eSStefano Zampini       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
14573927de2eSStefano Zampini     }
14583927de2eSStefano Zampini   }
1459ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
14607230de76SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1461ecf5a873SStefano Zampini   }
14624f619741Sstefano_zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
14633927de2eSStefano Zampini   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
1464ecf5a873SStefano Zampini 
1465ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
14663927de2eSStefano Zampini   if (maxreduce) {
14673927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
14683927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
1469bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
14703927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
14713927de2eSStefano Zampini   } else {
14723927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
14733927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
1474bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
14753927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
14763927de2eSStefano Zampini   }
14773927de2eSStefano Zampini   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
14783927de2eSStefano Zampini 
14793927de2eSStefano Zampini   /* Resize preallocation if overestimated */
14803927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
14813927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
14823927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
14833927de2eSStefano Zampini   }
14841670daf9Sstefano_zampini 
14851670daf9Sstefano_zampini   /* Set preallocation */
1486268753edSStefano Zampini   ierr = MatSeqAIJSetPreallocation(B,0,dnz);CHKERRQ(ierr);
14873927de2eSStefano Zampini   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
14883927de2eSStefano Zampini   for (i=0;i<lrows/bs;i++) {
14893927de2eSStefano Zampini     dnz[i] = dnz[i*bs]/bs;
14903927de2eSStefano Zampini     onz[i] = onz[i*bs]/bs;
14913927de2eSStefano Zampini   }
1492268753edSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(B,bs,0,dnz);CHKERRQ(ierr);
14933927de2eSStefano Zampini   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
14943927de2eSStefano Zampini   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
14953927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
14963927de2eSStefano Zampini   if (issbaij) {
14973927de2eSStefano Zampini     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
14983927de2eSStefano Zampini   }
14993927de2eSStefano Zampini   PetscFunctionReturn(0);
15003927de2eSStefano Zampini }
15013927de2eSStefano Zampini 
15027230de76SStefano Zampini static PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M)
1503b7ce53b6SStefano Zampini {
1504b7ce53b6SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1505d9a9e74cSStefano Zampini   Mat            local_mat;
1506b7ce53b6SStefano Zampini   /* info on mat */
15073cfa4ea4SStefano Zampini   PetscInt       bs,rows,cols,lrows,lcols;
1508b7ce53b6SStefano Zampini   PetscInt       local_rows,local_cols;
1509b9ed4604SStefano Zampini   PetscBool      isseqdense,isseqsbaij,isseqaij,isseqbaij;
1510b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1511b9ed4604SStefano Zampini   PetscBool      lb[4],bb[4];
1512b9ed4604SStefano Zampini #endif
15137c03b4e8SStefano Zampini   PetscMPIInt    nsubdomains;
1514b7ce53b6SStefano Zampini   /* values insertion */
1515b7ce53b6SStefano Zampini   PetscScalar    *array;
1516b7ce53b6SStefano Zampini   /* work */
1517b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1518b7ce53b6SStefano Zampini 
1519b7ce53b6SStefano Zampini   PetscFunctionBegin;
1520b7ce53b6SStefano Zampini   /* get info from mat */
15217c03b4e8SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr);
15227c03b4e8SStefano Zampini   if (nsubdomains == 1) {
15231670daf9Sstefano_zampini     Mat            B;
15241670daf9Sstefano_zampini     IS             rows,cols;
1525acdf38a7Sstefano_zampini     IS             irows,icols;
15261670daf9Sstefano_zampini     const PetscInt *ridxs,*cidxs;
15271670daf9Sstefano_zampini 
15281670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
15291670daf9Sstefano_zampini     ierr = ISLocalToGlobalMappingGetIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
15301670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->rmap->n,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
15311670daf9Sstefano_zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,mat->cmap->n,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
1532acdf38a7Sstefano_zampini     ierr = ISSetPermutation(rows);CHKERRQ(ierr);
1533acdf38a7Sstefano_zampini     ierr = ISSetPermutation(cols);CHKERRQ(ierr);
1534acdf38a7Sstefano_zampini     ierr = ISInvertPermutation(rows,mat->rmap->n,&irows);CHKERRQ(ierr);
1535acdf38a7Sstefano_zampini     ierr = ISInvertPermutation(cols,mat->cmap->n,&icols);CHKERRQ(ierr);
1536268753edSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
1537268753edSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
1538acdf38a7Sstefano_zampini     ierr = ISDestroy(&cols);CHKERRQ(ierr);
1539acdf38a7Sstefano_zampini     ierr = ISDestroy(&rows);CHKERRQ(ierr);
15406104e0f1Sstefano_zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
15417dae84e0SHong Zhang     ierr = MatCreateSubMatrix(B,irows,icols,reuse,M);CHKERRQ(ierr);
1542acdf38a7Sstefano_zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
1543acdf38a7Sstefano_zampini     ierr = ISDestroy(&icols);CHKERRQ(ierr);
1544acdf38a7Sstefano_zampini     ierr = ISDestroy(&irows);CHKERRQ(ierr);
15457c03b4e8SStefano Zampini     PetscFunctionReturn(0);
15467c03b4e8SStefano Zampini   }
1547b7ce53b6SStefano Zampini   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
1548b7ce53b6SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
15493cfa4ea4SStefano Zampini   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
1550b7ce53b6SStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
1551b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
15524099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
1553b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
1554b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij);CHKERRQ(ierr);
1555b9ed4604SStefano Zampini   if (!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name);
1556b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1557b9ed4604SStefano Zampini   lb[0] = isseqdense;
1558b9ed4604SStefano Zampini   lb[1] = isseqaij;
1559b9ed4604SStefano Zampini   lb[2] = isseqbaij;
1560b9ed4604SStefano Zampini   lb[3] = isseqsbaij;
1561b9ed4604SStefano Zampini   ierr = MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
1562b9ed4604SStefano Zampini   if (!bb[0] && !bb[1] && !bb[2] && !bb[3]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type");
1563b9ed4604SStefano Zampini #endif
1564b7ce53b6SStefano Zampini 
1565b7ce53b6SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
15663927de2eSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr);
15673cfa4ea4SStefano Zampini     ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr);
1568b9ed4604SStefano Zampini     if (!isseqsbaij) {
1569b9ed4604SStefano Zampini       ierr = MatSetType(*M,MATAIJ);CHKERRQ(ierr);
1570b9ed4604SStefano Zampini     } else {
1571b9ed4604SStefano Zampini       ierr = MatSetType(*M,MATSBAIJ);CHKERRQ(ierr);
1572b9ed4604SStefano Zampini     }
1573d59cf9ebSStefano Zampini     ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr);
15743927de2eSStefano Zampini     ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr);
1575b7ce53b6SStefano Zampini   } else {
15763cfa4ea4SStefano Zampini     PetscInt mbs,mrows,mcols,mlrows,mlcols;
1577b7ce53b6SStefano Zampini     /* some checks */
1578b7ce53b6SStefano Zampini     ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr);
1579b7ce53b6SStefano Zampini     ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr);
15803cfa4ea4SStefano Zampini     ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr);
15816c4ed002SBarry Smith     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
15826c4ed002SBarry Smith     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
15836c4ed002SBarry Smith     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
15846c4ed002SBarry Smith     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
15856c4ed002SBarry Smith     if (mbs != bs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs);
1586b7ce53b6SStefano Zampini     ierr = MatZeroEntries(*M);CHKERRQ(ierr);
1587b7ce53b6SStefano Zampini   }
1588d9a9e74cSStefano Zampini 
1589b9ed4604SStefano Zampini   if (isseqsbaij) {
1590d9a9e74cSStefano Zampini     ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
1591d9a9e74cSStefano Zampini   } else {
1592d9a9e74cSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
1593d9a9e74cSStefano Zampini     local_mat = matis->A;
1594d9a9e74cSStefano Zampini   }
1595686e3a49SStefano Zampini 
1596b7ce53b6SStefano Zampini   /* Set values */
1597ecf5a873SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*M,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
1598b9ed4604SStefano Zampini   if (isseqdense) { /* special case for dense local matrices */
159965066ba5SStefano Zampini     PetscInt i,*dummy;
1600ecf5a873SStefano Zampini 
160165066ba5SStefano Zampini     ierr = PetscMalloc1(PetscMax(local_rows,local_cols),&dummy);CHKERRQ(ierr);
160265066ba5SStefano Zampini     for (i=0;i<PetscMax(local_rows,local_cols);i++) dummy[i] = i;
1603b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
1604d9a9e74cSStefano Zampini     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
160565066ba5SStefano Zampini     ierr = MatSetValuesLocal(*M,local_rows,dummy,local_cols,dummy,array,ADD_VALUES);CHKERRQ(ierr);
1606d9a9e74cSStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
160765066ba5SStefano Zampini     ierr = PetscFree(dummy);CHKERRQ(ierr);
1608686e3a49SStefano Zampini   } else if (isseqaij) {
1609ecf5a873SStefano Zampini     PetscInt  i,nvtxs,*xadj,*adjncy;
1610686e3a49SStefano Zampini     PetscBool done;
1611686e3a49SStefano Zampini 
1612d9a9e74cSStefano Zampini     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1613938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1614d9a9e74cSStefano Zampini     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
1615686e3a49SStefano Zampini     for (i=0;i<nvtxs;i++) {
1616ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
1617686e3a49SStefano Zampini     }
1618d9a9e74cSStefano Zampini     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
1619938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1620d9a9e74cSStefano Zampini     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
1621686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
1622ecf5a873SStefano Zampini     PetscInt i;
1623c0962df8SStefano Zampini 
1624686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
1625686e3a49SStefano Zampini       PetscInt       j;
1626ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
1627686e3a49SStefano Zampini 
1628ecf5a873SStefano Zampini       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1629ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
1630ecf5a873SStefano Zampini       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
1631686e3a49SStefano Zampini     }
1632b7ce53b6SStefano Zampini   }
1633b7ce53b6SStefano Zampini   ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1634d9a9e74cSStefano Zampini   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
1635b7ce53b6SStefano Zampini   ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1636b9ed4604SStefano Zampini   if (isseqdense) {
1637b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
1638b7ce53b6SStefano Zampini   }
1639b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1640b7ce53b6SStefano Zampini }
1641b7ce53b6SStefano Zampini 
1642b7ce53b6SStefano Zampini /*@
1643b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
1644b7ce53b6SStefano Zampini 
1645b7ce53b6SStefano Zampini   Input Parameter:
1646b7ce53b6SStefano Zampini .  mat - the matrix (should be of type MATIS)
1647b7ce53b6SStefano Zampini .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
1648b7ce53b6SStefano Zampini 
1649b7ce53b6SStefano Zampini   Output Parameter:
1650b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
1651b7ce53b6SStefano Zampini 
1652b7ce53b6SStefano Zampini   Level: developer
1653b7ce53b6SStefano Zampini 
165495452b02SPatrick Sanan   Notes:
165595452b02SPatrick Sanan     mat and *newmat cannot be the same object when MAT_REUSE_MATRIX is requested.
1656b7ce53b6SStefano Zampini 
1657b7ce53b6SStefano Zampini .seealso: MATIS
1658b7ce53b6SStefano Zampini @*/
1659b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
1660b7ce53b6SStefano Zampini {
1661b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1662b7ce53b6SStefano Zampini 
1663b7ce53b6SStefano Zampini   PetscFunctionBegin;
1664b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
1665b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
1666b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
1667b7ce53b6SStefano Zampini   if (reuse != MAT_INITIAL_MATRIX) {
1668b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
1669b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
16706c4ed002SBarry Smith     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
1671b7ce53b6SStefano Zampini   }
1672b7ce53b6SStefano Zampini   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatReuse,Mat*),(mat,reuse,newmat));CHKERRQ(ierr);
1673b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
1674b7ce53b6SStefano Zampini }
1675b7ce53b6SStefano Zampini 
1676ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
1677ad6194a2SStefano Zampini {
1678ad6194a2SStefano Zampini   PetscErrorCode ierr;
1679ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1680ad6194a2SStefano Zampini   PetscInt       bs,m,n,M,N;
1681ad6194a2SStefano Zampini   Mat            B,localmat;
1682ad6194a2SStefano Zampini 
1683ad6194a2SStefano Zampini   PetscFunctionBegin;
1684ad6194a2SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
1685ad6194a2SStefano Zampini   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
1686ad6194a2SStefano Zampini   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
1687e176bc59SStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr);
1688ad6194a2SStefano Zampini   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
1689ad6194a2SStefano Zampini   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
1690b3317aa8SStefano Zampini   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
1691b0f2910eSStefano Zampini   if (matis->sf) {
1692b0f2910eSStefano Zampini     Mat_IS *bmatis = (Mat_IS*)(B->data);
1693b0f2910eSStefano Zampini 
1694b0f2910eSStefano Zampini     ierr       = PetscObjectReference((PetscObject)matis->sf);CHKERRQ(ierr);
1695b0f2910eSStefano Zampini     bmatis->sf = matis->sf;
1696b0f2910eSStefano Zampini     ierr       = PetscMalloc2(matis->sf->nroots,&bmatis->sf_rootdata,matis->sf->nleaves,&bmatis->sf_leafdata);CHKERRQ(ierr);
1697b0f2910eSStefano Zampini     if (matis->sf != matis->csf) {
1698b0f2910eSStefano Zampini       ierr        = PetscObjectReference((PetscObject)matis->csf);CHKERRQ(ierr);
1699b0f2910eSStefano Zampini       bmatis->csf = matis->csf;
1700b0f2910eSStefano Zampini       ierr        = PetscMalloc2(matis->csf->nroots,&bmatis->csf_rootdata,matis->csf->nleaves,&bmatis->csf_leafdata);CHKERRQ(ierr);
1701b0f2910eSStefano Zampini     } else {
1702b0f2910eSStefano Zampini       bmatis->csf          = bmatis->sf;
1703b0f2910eSStefano Zampini       bmatis->csf_leafdata = bmatis->sf_leafdata;
1704b0f2910eSStefano Zampini       bmatis->csf_rootdata = bmatis->sf_rootdata;
1705b0f2910eSStefano Zampini     }
1706b0f2910eSStefano Zampini   }
1707ad6194a2SStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1708ad6194a2SStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1709ad6194a2SStefano Zampini   *newmat = B;
1710ad6194a2SStefano Zampini   PetscFunctionReturn(0);
1711ad6194a2SStefano Zampini }
1712ad6194a2SStefano Zampini 
1713a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
171469796d55SStefano Zampini {
171569796d55SStefano Zampini   PetscErrorCode ierr;
171669796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
171769796d55SStefano Zampini   PetscBool      local_sym;
171869796d55SStefano Zampini 
171969796d55SStefano Zampini   PetscFunctionBegin;
172069796d55SStefano Zampini   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
1721b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
172269796d55SStefano Zampini   PetscFunctionReturn(0);
172369796d55SStefano Zampini }
172469796d55SStefano Zampini 
1725a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
172669796d55SStefano Zampini {
172769796d55SStefano Zampini   PetscErrorCode ierr;
172869796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
172969796d55SStefano Zampini   PetscBool      local_sym;
173069796d55SStefano Zampini 
173169796d55SStefano Zampini   PetscFunctionBegin;
173269796d55SStefano Zampini   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
1733b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
173469796d55SStefano Zampini   PetscFunctionReturn(0);
173569796d55SStefano Zampini }
173669796d55SStefano Zampini 
173745471136SStefano Zampini static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool  *flg)
173845471136SStefano Zampini {
173945471136SStefano Zampini   PetscErrorCode ierr;
174045471136SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
174145471136SStefano Zampini   PetscBool      local_sym;
174245471136SStefano Zampini 
174345471136SStefano Zampini   PetscFunctionBegin;
174445471136SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
174545471136SStefano Zampini     *flg = PETSC_FALSE;
174645471136SStefano Zampini     PetscFunctionReturn(0);
174745471136SStefano Zampini   }
174845471136SStefano Zampini   ierr = MatIsStructurallySymmetric(matis->A,&local_sym);CHKERRQ(ierr);
174945471136SStefano Zampini   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
175045471136SStefano Zampini   PetscFunctionReturn(0);
175145471136SStefano Zampini }
175245471136SStefano Zampini 
1753a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
1754b4319ba4SBarry Smith {
1755dfbe8321SBarry Smith   PetscErrorCode ierr;
1756b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
1757b4319ba4SBarry Smith 
1758b4319ba4SBarry Smith   PetscFunctionBegin;
17596bf464f9SBarry Smith   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
1760e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
1761e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
17626bf464f9SBarry Smith   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
17636bf464f9SBarry Smith   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
17643fd1c9e7SStefano Zampini   ierr = VecDestroy(&b->counter);CHKERRQ(ierr);
1765a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
1766a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
1767a8116848SStefano Zampini   if (b->sf != b->csf) {
1768a8116848SStefano Zampini     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
1769a8116848SStefano Zampini     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
1770a8116848SStefano Zampini   }
177128f4e0baSStefano Zampini   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
177228f4e0baSStefano Zampini   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
1773bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1774dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
1775bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
1776b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
1777b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
17782e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
1779cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",NULL);CHKERRQ(ierr);
178075d48cdbSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",NULL);CHKERRQ(ierr);
1781b4319ba4SBarry Smith   PetscFunctionReturn(0);
1782b4319ba4SBarry Smith }
1783b4319ba4SBarry Smith 
1784a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
1785b4319ba4SBarry Smith {
1786dfbe8321SBarry Smith   PetscErrorCode ierr;
1787b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
1788b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
1789b4319ba4SBarry Smith 
1790b4319ba4SBarry Smith   PetscFunctionBegin;
1791b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
1792e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1793e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1794b4319ba4SBarry Smith 
1795b4319ba4SBarry Smith   /* multiply the local matrix */
1796b4319ba4SBarry Smith   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
1797b4319ba4SBarry Smith 
1798b4319ba4SBarry Smith   /* scatter product back into global memory */
17992dcb1b2aSMatthew Knepley   ierr = VecSet(y,zero);CHKERRQ(ierr);
1800e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1801e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1802b4319ba4SBarry Smith   PetscFunctionReturn(0);
1803b4319ba4SBarry Smith }
1804b4319ba4SBarry Smith 
1805a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
18062e74eeadSLisandro Dalcin {
1807650997f4SStefano Zampini   Vec            temp_vec;
18082e74eeadSLisandro Dalcin   PetscErrorCode ierr;
18092e74eeadSLisandro Dalcin 
18102e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
1811650997f4SStefano Zampini   if (v3 != v2) {
1812650997f4SStefano Zampini     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
1813650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1814650997f4SStefano Zampini   } else {
1815650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1816650997f4SStefano Zampini     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
1817650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1818650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1819650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1820650997f4SStefano Zampini   }
18212e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
18222e74eeadSLisandro Dalcin }
18232e74eeadSLisandro Dalcin 
1824a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
18252e74eeadSLisandro Dalcin {
18262e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
18272e74eeadSLisandro Dalcin   PetscErrorCode ierr;
18282e74eeadSLisandro Dalcin 
1829e176bc59SStefano Zampini   PetscFunctionBegin;
18302e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
1831e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1832e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
18332e74eeadSLisandro Dalcin 
18342e74eeadSLisandro Dalcin   /* multiply the local matrix */
1835e176bc59SStefano Zampini   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
18362e74eeadSLisandro Dalcin 
18372e74eeadSLisandro Dalcin   /* scatter product back into global vector */
1838e176bc59SStefano Zampini   ierr = VecSet(x,0);CHKERRQ(ierr);
1839e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1840e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
18412e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
18422e74eeadSLisandro Dalcin }
18432e74eeadSLisandro Dalcin 
1844a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
18452e74eeadSLisandro Dalcin {
1846650997f4SStefano Zampini   Vec            temp_vec;
18472e74eeadSLisandro Dalcin   PetscErrorCode ierr;
18482e74eeadSLisandro Dalcin 
18492e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
1850650997f4SStefano Zampini   if (v3 != v2) {
1851650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
1852650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
1853650997f4SStefano Zampini   } else {
1854650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
1855650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
1856650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
1857650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
1858650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1859650997f4SStefano Zampini   }
18602e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
18612e74eeadSLisandro Dalcin }
18622e74eeadSLisandro Dalcin 
1863a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
1864b4319ba4SBarry Smith {
1865b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
1866dfbe8321SBarry Smith   PetscErrorCode ierr;
1867b4319ba4SBarry Smith   PetscViewer    sviewer;
1868ee2491ecSStefano Zampini   PetscBool      isascii,view = PETSC_TRUE;
1869b4319ba4SBarry Smith 
1870b4319ba4SBarry Smith   PetscFunctionBegin;
1871ee2491ecSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1872ee2491ecSStefano Zampini   if (isascii)  {
1873ee2491ecSStefano Zampini     PetscViewerFormat format;
1874ee2491ecSStefano Zampini 
1875ee2491ecSStefano Zampini     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1876ee2491ecSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE;
1877ee2491ecSStefano Zampini   }
1878ee2491ecSStefano Zampini   if (!view) PetscFunctionReturn(0);
18793f08860eSBarry Smith   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
1880b4319ba4SBarry Smith   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
18813f08860eSBarry Smith   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
18826e520ac8SStefano Zampini   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1883b4319ba4SBarry Smith   PetscFunctionReturn(0);
1884b4319ba4SBarry Smith }
1885b4319ba4SBarry Smith 
1886a8116848SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
1887b4319ba4SBarry Smith {
1888dfbe8321SBarry Smith   PetscErrorCode ierr;
1889e176bc59SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
1890b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
1891b4319ba4SBarry Smith   IS             from,to;
1892e176bc59SStefano Zampini   Vec            cglobal,rglobal;
1893b4319ba4SBarry Smith 
1894b4319ba4SBarry Smith   PetscFunctionBegin;
1895784ac674SJed Brown   PetscCheckSameComm(A,1,rmapping,2);
1896e176bc59SStefano Zampini   PetscCheckSameComm(A,1,cmapping,3);
18973bbff08aSStefano Zampini   /* Destroy any previous data */
189870cf5478SStefano Zampini   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
189970cf5478SStefano Zampini   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
19003fd1c9e7SStefano Zampini   ierr = VecDestroy(&is->counter);CHKERRQ(ierr);
1901e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
1902e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
19031c47cb0fSStefano Zampini   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
1904872cf891SStefano Zampini   if (is->csf != is->sf) {
1905872cf891SStefano Zampini     ierr = PetscSFDestroy(&is->csf);CHKERRQ(ierr);
1906872cf891SStefano Zampini     ierr = PetscFree2(is->csf_rootdata,is->csf_leafdata);CHKERRQ(ierr);
1907872cf891SStefano Zampini   }
190828f4e0baSStefano Zampini   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
190928f4e0baSStefano Zampini   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
19103bbff08aSStefano Zampini 
19113bbff08aSStefano Zampini   /* Setup Layout and set local to global maps */
1912fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1913fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1914e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
1915e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
1916e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
1917e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
19186625354bSStefano Zampini   /* check if the two mappings are actually the same for square matrices (DOLFIN passes 2 different objects) */
19196625354bSStefano Zampini   if (rmapping != cmapping && A->rmap->N == A->cmap->N) {
19206625354bSStefano Zampini     PetscBool same,gsame;
19216625354bSStefano Zampini 
19226625354bSStefano Zampini     same = PETSC_FALSE;
19236625354bSStefano Zampini     if (nr == nc && cbs == rbs) {
19246625354bSStefano Zampini       const PetscInt *idxs1,*idxs2;
19256625354bSStefano Zampini 
19266625354bSStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(rmapping,&idxs1);CHKERRQ(ierr);
19276625354bSStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(cmapping,&idxs2);CHKERRQ(ierr);
19286625354bSStefano Zampini       ierr = PetscMemcmp(idxs1,idxs2,(nr/rbs)*sizeof(PetscInt),&same);CHKERRQ(ierr);
19296625354bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(rmapping,&idxs1);CHKERRQ(ierr);
19306625354bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(cmapping,&idxs2);CHKERRQ(ierr);
19316625354bSStefano Zampini     }
19326625354bSStefano Zampini     ierr = MPIU_Allreduce(&same,&gsame,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
19336625354bSStefano Zampini     if (gsame) cmapping = rmapping;
19346625354bSStefano Zampini   }
19356625354bSStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
19366625354bSStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
19376625354bSStefano Zampini 
19386625354bSStefano Zampini   /* Create the local matrix A */
1939f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
1940e176bc59SStefano Zampini   ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr);
1941e176bc59SStefano Zampini   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
1942e176bc59SStefano Zampini   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
1943ff130e51SJed Brown   ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
1944ff130e51SJed Brown   ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
1945b4319ba4SBarry Smith   ierr = MatSetFromOptions(is->A);CHKERRQ(ierr);
1946c77832edSStefano Zampini   ierr = PetscLayoutSetUp(is->A->rmap);CHKERRQ(ierr);
1947c77832edSStefano Zampini   ierr = PetscLayoutSetUp(is->A->cmap);CHKERRQ(ierr);
1948b4319ba4SBarry Smith 
1949f26d0771SStefano Zampini   if (!is->islocalref) { /* setup scatters and local vectors for MatMult */
1950b4319ba4SBarry Smith     /* Create the local work vectors */
19513bbff08aSStefano Zampini     ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
1952b4319ba4SBarry Smith 
1953e176bc59SStefano Zampini     /* setup the global to local scatters */
1954e176bc59SStefano Zampini     ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
1955e176bc59SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,nr,0,1,&to);CHKERRQ(ierr);
1956784ac674SJed Brown     ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr);
1957e176bc59SStefano Zampini     ierr = VecScatterCreate(rglobal,from,is->y,to,&is->rctx);CHKERRQ(ierr);
1958e176bc59SStefano Zampini     if (rmapping != cmapping) {
1959e176bc59SStefano Zampini       ierr = ISDestroy(&to);CHKERRQ(ierr);
1960e176bc59SStefano Zampini       ierr = ISDestroy(&from);CHKERRQ(ierr);
1961e176bc59SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,nc,0,1,&to);CHKERRQ(ierr);
1962e176bc59SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(cmapping,to,&from);CHKERRQ(ierr);
1963e176bc59SStefano Zampini       ierr = VecScatterCreate(cglobal,from,is->x,to,&is->cctx);CHKERRQ(ierr);
1964e176bc59SStefano Zampini     } else {
1965e176bc59SStefano Zampini       ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
1966e176bc59SStefano Zampini       is->cctx = is->rctx;
1967e176bc59SStefano Zampini     }
19683fd1c9e7SStefano Zampini 
19693fd1c9e7SStefano Zampini     /* interface counter vector (local) */
19703fd1c9e7SStefano Zampini     ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr);
19713fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
19723fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
19733fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
19743fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19753fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19763fd1c9e7SStefano Zampini 
19773fd1c9e7SStefano Zampini     /* free workspace */
1978e176bc59SStefano Zampini     ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
1979e176bc59SStefano Zampini     ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
19806bf464f9SBarry Smith     ierr = ISDestroy(&to);CHKERRQ(ierr);
19816bf464f9SBarry Smith     ierr = ISDestroy(&from);CHKERRQ(ierr);
1982f26d0771SStefano Zampini   }
198348ff6bf3SStefano Zampini   ierr = MatSetUp(A);CHKERRQ(ierr);
1984b4319ba4SBarry Smith   PetscFunctionReturn(0);
1985b4319ba4SBarry Smith }
1986b4319ba4SBarry Smith 
1987a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
19882e74eeadSLisandro Dalcin {
19892e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
19902e74eeadSLisandro Dalcin   PetscErrorCode ierr;
199197563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
199297563a80SStefano Zampini   PetscInt       i,zm,zn;
199397563a80SStefano Zampini #endif
1994f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
19952e74eeadSLisandro Dalcin 
19962e74eeadSLisandro Dalcin   PetscFunctionBegin;
19972e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG)
1998f26d0771SStefano 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);
199997563a80SStefano Zampini   /* count negative indices */
200097563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
200197563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
20022e74eeadSLisandro Dalcin #endif
200397563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
200497563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
200597563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
200697563a80SStefano Zampini   /* count negative indices (should be the same as before) */
200797563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
200897563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
2009b4f971dfSStefano 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");
2010b4f971dfSStefano 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");
201197563a80SStefano Zampini #endif
20122e74eeadSLisandro Dalcin   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
20132e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
20142e74eeadSLisandro Dalcin }
20152e74eeadSLisandro Dalcin 
2016a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
201797563a80SStefano Zampini {
201897563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
201997563a80SStefano Zampini   PetscErrorCode ierr;
202097563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
202197563a80SStefano Zampini   PetscInt       i,zm,zn;
202297563a80SStefano Zampini #endif
2023f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
202497563a80SStefano Zampini 
202597563a80SStefano Zampini   PetscFunctionBegin;
202697563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
2027f26d0771SStefano 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);
202897563a80SStefano Zampini   /* count negative indices */
202997563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
203097563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
203197563a80SStefano Zampini #endif
203297563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
203397563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
203497563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
203597563a80SStefano Zampini   /* count negative indices (should be the same as before) */
203697563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
203797563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
2038b4f971dfSStefano 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");
2039b4f971dfSStefano 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");
204097563a80SStefano Zampini #endif
2041d59cf9ebSStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
204297563a80SStefano Zampini   PetscFunctionReturn(0);
204397563a80SStefano Zampini }
204497563a80SStefano Zampini 
2045a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
2046b4319ba4SBarry Smith {
2047dfbe8321SBarry Smith   PetscErrorCode ierr;
2048b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2049b4319ba4SBarry Smith 
2050b4319ba4SBarry Smith   PetscFunctionBegin;
2051b4f971dfSStefano Zampini   if (is->A->rmap->mapping) {
2052872cf891SStefano Zampini     ierr = MatSetValuesLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2053872cf891SStefano Zampini   } else {
2054b4319ba4SBarry Smith     ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2055872cf891SStefano Zampini   }
2056b4319ba4SBarry Smith   PetscFunctionReturn(0);
2057b4319ba4SBarry Smith }
2058b4319ba4SBarry Smith 
2059a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
2060f0006bf2SLisandro Dalcin {
2061f0006bf2SLisandro Dalcin   PetscErrorCode ierr;
2062f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
2063f0006bf2SLisandro Dalcin 
2064f0006bf2SLisandro Dalcin   PetscFunctionBegin;
2065b4f971dfSStefano Zampini   if (is->A->rmap->mapping) {
2066b4f971dfSStefano Zampini #if defined(PETSC_USE_DEBUG)
2067b4f971dfSStefano Zampini     PetscInt ibs,bs;
2068b4f971dfSStefano Zampini 
2069b4f971dfSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(is->A->rmap->mapping,&ibs);CHKERRQ(ierr);
2070b4f971dfSStefano Zampini     ierr = MatGetBlockSize(is->A,&bs);CHKERRQ(ierr);
2071b4f971dfSStefano Zampini     if (ibs != bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Different block sizes! local mat %D, local l2g map %D",bs,ibs);
2072b4f971dfSStefano Zampini #endif
2073b4f971dfSStefano Zampini     ierr = MatSetValuesBlockedLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2074b4f971dfSStefano Zampini   } else {
2075f0006bf2SLisandro Dalcin     ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2076b4f971dfSStefano Zampini   }
2077f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
2078f0006bf2SLisandro Dalcin }
2079f0006bf2SLisandro Dalcin 
2080f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
2081f0ae7da4SStefano Zampini {
2082f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
2083f0ae7da4SStefano Zampini   PetscErrorCode ierr;
2084f0ae7da4SStefano Zampini 
2085f0ae7da4SStefano Zampini   PetscFunctionBegin;
2086f0ae7da4SStefano Zampini   if (!n) {
2087f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
2088f0ae7da4SStefano Zampini   } else {
2089f0ae7da4SStefano Zampini     PetscInt i;
2090f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
2091f0ae7da4SStefano Zampini 
2092f0ae7da4SStefano Zampini     if (columns) {
2093f0ae7da4SStefano Zampini       ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
2094f0ae7da4SStefano Zampini     } else {
2095f0ae7da4SStefano Zampini       ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
2096f0ae7da4SStefano Zampini     }
2097f0ae7da4SStefano Zampini     if (diag != 0.) {
2098f0ae7da4SStefano Zampini       const PetscScalar *array;
2099f0ae7da4SStefano Zampini       ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr);
2100f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
2101f0ae7da4SStefano Zampini         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
2102f0ae7da4SStefano Zampini       }
2103f0ae7da4SStefano Zampini       ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr);
2104f0ae7da4SStefano Zampini     }
2105f0ae7da4SStefano Zampini     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2106f0ae7da4SStefano Zampini     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2107f0ae7da4SStefano Zampini   }
2108f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
2109f0ae7da4SStefano Zampini }
2110f0ae7da4SStefano Zampini 
2111f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
21122e74eeadSLisandro Dalcin {
21136e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
21146e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
21156e520ac8SStefano Zampini   PetscInt       *lrows;
21162e74eeadSLisandro Dalcin   PetscErrorCode ierr;
21172e74eeadSLisandro Dalcin 
21182e74eeadSLisandro Dalcin   PetscFunctionBegin;
2119f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG)
2120f0ae7da4SStefano Zampini   if (columns || diag != 0. || (x && b)) {
2121f0ae7da4SStefano Zampini     PetscBool cong;
212226b0207aSStefano Zampini 
2123f0ae7da4SStefano Zampini     ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr);
212426b0207aSStefano Zampini     cong = (PetscBool)(cong && matis->sf == matis->csf);
2125268753edSStefano 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");
2126268753edSStefano 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");
2127268753edSStefano 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");
2128f0ae7da4SStefano Zampini   }
2129f0ae7da4SStefano Zampini #endif
21306e520ac8SStefano Zampini   /* get locally owned rows */
2131f0ae7da4SStefano Zampini   ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr);
21326e520ac8SStefano Zampini   /* fix right hand side if needed */
21336e520ac8SStefano Zampini   if (x && b) {
21346e520ac8SStefano Zampini     const PetscScalar *xx;
21356e520ac8SStefano Zampini     PetscScalar       *bb;
21366e520ac8SStefano Zampini 
21376e520ac8SStefano Zampini     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
21386e520ac8SStefano Zampini     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
21396e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
21406e520ac8SStefano Zampini     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
21416e520ac8SStefano Zampini     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
21422e74eeadSLisandro Dalcin   }
21436e520ac8SStefano Zampini   /* get rows associated to the local matrices */
21443d996552SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
21456e520ac8SStefano Zampini   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
21466e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr);
21476e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
21486e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
21496e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
21506e520ac8SStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
21516e520ac8SStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
21526e520ac8SStefano Zampini   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
21536e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
2154f0ae7da4SStefano Zampini   ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr);
21556e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
21562e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
21572e74eeadSLisandro Dalcin }
21582e74eeadSLisandro Dalcin 
2159f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
2160b4319ba4SBarry Smith {
2161dfbe8321SBarry Smith   PetscErrorCode ierr;
2162b4319ba4SBarry Smith 
2163b4319ba4SBarry Smith   PetscFunctionBegin;
2164f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr);
2165f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
2166f0ae7da4SStefano Zampini }
21672205254eSKarl Rupp 
2168f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
2169f0ae7da4SStefano Zampini {
2170f0ae7da4SStefano Zampini   PetscErrorCode ierr;
2171f0ae7da4SStefano Zampini 
2172f0ae7da4SStefano Zampini   PetscFunctionBegin;
2173f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr);
2174b4319ba4SBarry Smith   PetscFunctionReturn(0);
2175b4319ba4SBarry Smith }
2176b4319ba4SBarry Smith 
2177a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
2178b4319ba4SBarry Smith {
2179b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2180dfbe8321SBarry Smith   PetscErrorCode ierr;
2181b4319ba4SBarry Smith 
2182b4319ba4SBarry Smith   PetscFunctionBegin;
2183b4319ba4SBarry Smith   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
2184b4319ba4SBarry Smith   PetscFunctionReturn(0);
2185b4319ba4SBarry Smith }
2186b4319ba4SBarry Smith 
2187a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
2188b4319ba4SBarry Smith {
2189b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2190dfbe8321SBarry Smith   PetscErrorCode ierr;
2191b4319ba4SBarry Smith 
2192b4319ba4SBarry Smith   PetscFunctionBegin;
2193b4319ba4SBarry Smith   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
2194872cf891SStefano Zampini   /* fix for local empty rows/cols */
2195872cf891SStefano Zampini   if (is->locempty && type == MAT_FINAL_ASSEMBLY) {
2196872cf891SStefano Zampini     Mat                    newlA;
2197872cf891SStefano Zampini     ISLocalToGlobalMapping l2g;
2198872cf891SStefano Zampini     IS                     tis;
2199872cf891SStefano Zampini     const PetscScalar      *v;
2200872cf891SStefano Zampini     PetscInt               i,n,cf,*loce,*locf;
2201872cf891SStefano Zampini     PetscBool              sym;
2202872cf891SStefano Zampini 
2203872cf891SStefano Zampini     ierr = MatGetRowMaxAbs(is->A,is->y,NULL);CHKERRQ(ierr);
2204872cf891SStefano Zampini     ierr = MatIsSymmetric(is->A,PETSC_SMALL,&sym);CHKERRQ(ierr);
2205872cf891SStefano Zampini     if (!sym) SETERRQ(PetscObjectComm((PetscObject)is->A),PETSC_ERR_SUP,"Not yet implemented for unsymmetric case");
2206872cf891SStefano Zampini     ierr = VecGetLocalSize(is->y,&n);CHKERRQ(ierr);
2207872cf891SStefano Zampini     ierr = PetscMalloc1(n,&loce);CHKERRQ(ierr);
2208872cf891SStefano Zampini     ierr = PetscMalloc1(n,&locf);CHKERRQ(ierr);
2209872cf891SStefano Zampini     ierr = VecGetArrayRead(is->y,&v);CHKERRQ(ierr);
2210872cf891SStefano Zampini     for (i=0,cf=0;i<n;i++) {
2211872cf891SStefano Zampini       if (v[i] == 0.0) {
2212872cf891SStefano Zampini         loce[i] = -1;
2213872cf891SStefano Zampini       } else {
2214872cf891SStefano Zampini         loce[i]    = cf;
2215872cf891SStefano Zampini         locf[cf++] = i;
2216872cf891SStefano Zampini       }
2217872cf891SStefano Zampini     }
2218872cf891SStefano Zampini     ierr = VecRestoreArrayRead(is->y,&v);CHKERRQ(ierr);
2219872cf891SStefano Zampini     /* extract valid submatrix */
2220872cf891SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is->A),cf,locf,PETSC_USE_POINTER,&tis);CHKERRQ(ierr);
2221e5b89577SStefano Zampini     ierr = MatCreateSubMatrix(is->A,tis,tis,MAT_INITIAL_MATRIX,&newlA);CHKERRQ(ierr);
2222872cf891SStefano Zampini     ierr = ISDestroy(&tis);CHKERRQ(ierr);
2223872cf891SStefano Zampini     /* attach local l2g map for successive calls of MatSetValues */
2224872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)is->A),1,n,loce,PETSC_OWN_POINTER,&l2g);CHKERRQ(ierr);
2225872cf891SStefano Zampini     ierr = MatSetLocalToGlobalMapping(newlA,l2g,l2g);CHKERRQ(ierr);
2226872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
2227872cf891SStefano Zampini     /* attach new global l2g map */
2228872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,cf,locf,locf);CHKERRQ(ierr);
2229872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,cf,locf,PETSC_OWN_POINTER,&l2g);CHKERRQ(ierr);
2230872cf891SStefano Zampini     ierr = MatSetLocalToGlobalMapping(A,l2g,l2g);CHKERRQ(ierr);
2231872cf891SStefano Zampini     ierr = MatISSetLocalMat(A,newlA);CHKERRQ(ierr);
2232872cf891SStefano Zampini     ierr = MatDestroy(&newlA);CHKERRQ(ierr);
2233872cf891SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
2234872cf891SStefano Zampini   }
2235872cf891SStefano Zampini   is->locempty = PETSC_FALSE;
2236b4319ba4SBarry Smith   PetscFunctionReturn(0);
2237b4319ba4SBarry Smith }
2238b4319ba4SBarry Smith 
2239a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
2240b4319ba4SBarry Smith {
2241b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
2242b4319ba4SBarry Smith 
2243b4319ba4SBarry Smith   PetscFunctionBegin;
2244b4319ba4SBarry Smith   *local = is->A;
2245b4319ba4SBarry Smith   PetscFunctionReturn(0);
2246b4319ba4SBarry Smith }
2247b4319ba4SBarry Smith 
22483b3b1effSJed Brown static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat,Mat *local)
22493b3b1effSJed Brown {
22503b3b1effSJed Brown   PetscFunctionBegin;
22513b3b1effSJed Brown   *local = NULL;
22523b3b1effSJed Brown   PetscFunctionReturn(0);
22533b3b1effSJed Brown }
22543b3b1effSJed Brown 
2255b4319ba4SBarry Smith /*@
2256b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
2257b4319ba4SBarry Smith 
2258b4319ba4SBarry Smith   Input Parameter:
2259b4319ba4SBarry Smith .  mat - the matrix
2260b4319ba4SBarry Smith 
2261b4319ba4SBarry Smith   Output Parameter:
2262eb82efa4SStefano Zampini .  local - the local matrix
2263b4319ba4SBarry Smith 
2264b4319ba4SBarry Smith   Level: advanced
2265b4319ba4SBarry Smith 
2266b4319ba4SBarry Smith   Notes:
2267b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
2268b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
2269b4319ba4SBarry Smith   of the MatSetValues() operation.
2270b4319ba4SBarry Smith 
22713b3b1effSJed Brown   Call MatISRestoreLocalMat() when finished with the local matrix.
227296a6f129SJed Brown 
2273b4319ba4SBarry Smith .seealso: MATIS
2274b4319ba4SBarry Smith @*/
22757087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
2276b4319ba4SBarry Smith {
22774ac538c5SBarry Smith   PetscErrorCode ierr;
2278b4319ba4SBarry Smith 
2279b4319ba4SBarry Smith   PetscFunctionBegin;
22800700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2281b4319ba4SBarry Smith   PetscValidPointer(local,2);
22824ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
2283b4319ba4SBarry Smith   PetscFunctionReturn(0);
2284b4319ba4SBarry Smith }
2285b4319ba4SBarry Smith 
22863b3b1effSJed Brown /*@
22873b3b1effSJed Brown     MatISRestoreLocalMat - Restores the local matrix obtained with MatISGetLocalMat()
22883b3b1effSJed Brown 
22893b3b1effSJed Brown   Input Parameter:
22903b3b1effSJed Brown .  mat - the matrix
22913b3b1effSJed Brown 
22923b3b1effSJed Brown   Output Parameter:
22933b3b1effSJed Brown .  local - the local matrix
22943b3b1effSJed Brown 
22953b3b1effSJed Brown   Level: advanced
22963b3b1effSJed Brown 
22973b3b1effSJed Brown .seealso: MATIS
22983b3b1effSJed Brown @*/
22993b3b1effSJed Brown PetscErrorCode MatISRestoreLocalMat(Mat mat,Mat *local)
23003b3b1effSJed Brown {
23013b3b1effSJed Brown   PetscErrorCode ierr;
23023b3b1effSJed Brown 
23033b3b1effSJed Brown   PetscFunctionBegin;
23043b3b1effSJed Brown   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
23053b3b1effSJed Brown   PetscValidPointer(local,2);
23063b3b1effSJed Brown   ierr = PetscUseMethod(mat,"MatISRestoreLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
23073b3b1effSJed Brown   PetscFunctionReturn(0);
23083b3b1effSJed Brown }
23093b3b1effSJed Brown 
2310a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
23113b03a366Sstefano_zampini {
23123b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
23133b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
23143b03a366Sstefano_zampini   PetscErrorCode ierr;
23153b03a366Sstefano_zampini 
23163b03a366Sstefano_zampini   PetscFunctionBegin;
23174e4c7dbeSStefano Zampini   if (is->A) {
23183b03a366Sstefano_zampini     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
23193b03a366Sstefano_zampini     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
2320f0ae7da4SStefano 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);
23214e4c7dbeSStefano Zampini   }
23223b03a366Sstefano_zampini   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
23233b03a366Sstefano_zampini   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
23243b03a366Sstefano_zampini   is->A = local;
23253b03a366Sstefano_zampini   PetscFunctionReturn(0);
23263b03a366Sstefano_zampini }
23273b03a366Sstefano_zampini 
23283b03a366Sstefano_zampini /*@
2329eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
23303b03a366Sstefano_zampini 
23313b03a366Sstefano_zampini   Input Parameter:
23323b03a366Sstefano_zampini .  mat - the matrix
2333eb82efa4SStefano Zampini .  local - the local matrix
23343b03a366Sstefano_zampini 
23353b03a366Sstefano_zampini   Output Parameter:
23363b03a366Sstefano_zampini 
23373b03a366Sstefano_zampini   Level: advanced
23383b03a366Sstefano_zampini 
23393b03a366Sstefano_zampini   Notes:
23403b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
23413b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
23423b03a366Sstefano_zampini 
23433b03a366Sstefano_zampini .seealso: MATIS
23443b03a366Sstefano_zampini @*/
23453b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
23463b03a366Sstefano_zampini {
23473b03a366Sstefano_zampini   PetscErrorCode ierr;
23483b03a366Sstefano_zampini 
23493b03a366Sstefano_zampini   PetscFunctionBegin;
23503b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2351b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
23523b03a366Sstefano_zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
23533b03a366Sstefano_zampini   PetscFunctionReturn(0);
23543b03a366Sstefano_zampini }
23553b03a366Sstefano_zampini 
2356a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
23576726f965SBarry Smith {
23586726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
23596726f965SBarry Smith   PetscErrorCode ierr;
23606726f965SBarry Smith 
23616726f965SBarry Smith   PetscFunctionBegin;
23626726f965SBarry Smith   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
23636726f965SBarry Smith   PetscFunctionReturn(0);
23646726f965SBarry Smith }
23656726f965SBarry Smith 
2366a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
23672e74eeadSLisandro Dalcin {
23682e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
23692e74eeadSLisandro Dalcin   PetscErrorCode ierr;
23702e74eeadSLisandro Dalcin 
23712e74eeadSLisandro Dalcin   PetscFunctionBegin;
23722e74eeadSLisandro Dalcin   ierr = MatScale(is->A,a);CHKERRQ(ierr);
23732e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
23742e74eeadSLisandro Dalcin }
23752e74eeadSLisandro Dalcin 
2376a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
23772e74eeadSLisandro Dalcin {
23782e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
23792e74eeadSLisandro Dalcin   PetscErrorCode ierr;
23802e74eeadSLisandro Dalcin 
23812e74eeadSLisandro Dalcin   PetscFunctionBegin;
23822e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
2383e176bc59SStefano Zampini   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
23842e74eeadSLisandro Dalcin 
23852e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
23862e74eeadSLisandro Dalcin   ierr = VecSet(v,0);CHKERRQ(ierr);
2387e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2388e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
23892e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
23902e74eeadSLisandro Dalcin }
23912e74eeadSLisandro Dalcin 
2392a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
23936726f965SBarry Smith {
23946726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
23956726f965SBarry Smith   PetscErrorCode ierr;
23966726f965SBarry Smith 
23976726f965SBarry Smith   PetscFunctionBegin;
23984e0d8c25SBarry Smith   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
23996726f965SBarry Smith   PetscFunctionReturn(0);
24006726f965SBarry Smith }
24016726f965SBarry Smith 
2402f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
2403f26d0771SStefano Zampini {
2404f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
2405f26d0771SStefano Zampini   Mat_IS         *x;
2406f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2407f26d0771SStefano Zampini   PetscBool      ismatis;
2408f26d0771SStefano Zampini #endif
2409f26d0771SStefano Zampini   PetscErrorCode ierr;
2410f26d0771SStefano Zampini 
2411f26d0771SStefano Zampini   PetscFunctionBegin;
2412f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2413f26d0771SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
2414f26d0771SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
2415f26d0771SStefano Zampini #endif
2416f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
2417f26d0771SStefano Zampini   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
2418f26d0771SStefano Zampini   PetscFunctionReturn(0);
2419f26d0771SStefano Zampini }
2420f26d0771SStefano Zampini 
2421f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
2422f26d0771SStefano Zampini {
2423f26d0771SStefano Zampini   Mat                    lA;
2424f26d0771SStefano Zampini   Mat_IS                 *matis;
2425f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
2426f26d0771SStefano Zampini   IS                     is;
2427f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
2428f26d0771SStefano Zampini   PetscInt               nrg;
2429f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
2430f26d0771SStefano Zampini   PetscErrorCode         ierr;
2431f26d0771SStefano Zampini 
2432f26d0771SStefano Zampini   PetscFunctionBegin;
2433f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
2434f26d0771SStefano Zampini   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
2435f26d0771SStefano Zampini   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
2436f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
2437f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2438f0ae7da4SStefano 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);
2439f26d0771SStefano Zampini #endif
2440f26d0771SStefano Zampini   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
2441f26d0771SStefano Zampini   /* map from [0,nrl) to row */
2442f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
2443f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2444f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = nrg;
2445f26d0771SStefano Zampini #else
2446f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
2447f26d0771SStefano Zampini #endif
2448f26d0771SStefano Zampini   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
2449f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
2450f26d0771SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2451f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
2452f26d0771SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
2453f26d0771SStefano Zampini   /* compute new l2g map for columns */
2454f26d0771SStefano Zampini   if (col != row || A->rmap->mapping != A->cmap->mapping) {
2455f26d0771SStefano Zampini     const PetscInt *cg,*cl;
2456f26d0771SStefano Zampini     PetscInt       ncg;
2457f26d0771SStefano Zampini     PetscInt       ncl;
2458f26d0771SStefano Zampini 
2459f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2460f26d0771SStefano Zampini     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
2461f26d0771SStefano Zampini     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
2462f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
2463f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2464f0ae7da4SStefano 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);
2465f26d0771SStefano Zampini #endif
2466f26d0771SStefano Zampini     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
2467f26d0771SStefano Zampini     /* map from [0,ncl) to col */
2468f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
2469f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
2470f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = ncg;
2471f26d0771SStefano Zampini #else
2472f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
2473f26d0771SStefano Zampini #endif
2474f26d0771SStefano Zampini     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
2475f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
2476f26d0771SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2477f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
2478f26d0771SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
2479f26d0771SStefano Zampini   } else {
2480f26d0771SStefano Zampini     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
2481f26d0771SStefano Zampini     cl2g = rl2g;
2482f26d0771SStefano Zampini   }
2483f26d0771SStefano Zampini   /* create the MATIS submatrix */
2484f26d0771SStefano Zampini   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
2485f26d0771SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
2486f26d0771SStefano Zampini   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2487f26d0771SStefano Zampini   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
2488b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
2489f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
2490f26d0771SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
2491f26d0771SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
2492f26d0771SStefano Zampini   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
2493f26d0771SStefano Zampini   ierr = MatSetUp(*submat);CHKERRQ(ierr);
2494f26d0771SStefano Zampini   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2495f26d0771SStefano Zampini   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2496f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2497f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2498f26d0771SStefano Zampini   /* remove unsupported ops */
2499f26d0771SStefano Zampini   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2500f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
2501f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
2502f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
2503f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
2504f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
2505f26d0771SStefano Zampini   PetscFunctionReturn(0);
2506f26d0771SStefano Zampini }
2507f26d0771SStefano Zampini 
2508872cf891SStefano Zampini static PetscErrorCode MatSetFromOptions_IS(PetscOptionItems *PetscOptionsObject, Mat A)
2509872cf891SStefano Zampini {
2510872cf891SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
2511872cf891SStefano Zampini   PetscErrorCode ierr;
2512872cf891SStefano Zampini 
2513872cf891SStefano Zampini   PetscFunctionBegin;
2514872cf891SStefano Zampini   ierr = PetscOptionsHead(PetscOptionsObject,"MATIS options");CHKERRQ(ierr);
2515872cf891SStefano Zampini   ierr = PetscObjectOptionsBegin((PetscObject)A);
2516872cf891SStefano Zampini   ierr = PetscOptionsBool("-matis_fixempty","Fix local matrices in case of empty local rows/columns",NULL,a->locempty,&a->locempty,NULL);CHKERRQ(ierr);
251775d48cdbSStefano Zampini   ierr = PetscOptionsBool("-matis_storel2l","Store local-to-local matrices generated from PtAP operations","MatISStoreL2L",a->storel2l,&a->storel2l,NULL);CHKERRQ(ierr);
2518872cf891SStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
2519872cf891SStefano Zampini   PetscFunctionReturn(0);
2520872cf891SStefano Zampini }
2521872cf891SStefano Zampini 
2522284134d9SBarry Smith /*@
25233c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
2524284134d9SBarry Smith        process but not across processes.
2525284134d9SBarry Smith 
2526284134d9SBarry Smith    Input Parameters:
2527284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
2528e176bc59SStefano Zampini .     bs      - block size of the matrix
2529df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
2530e176bc59SStefano Zampini .     rmap    - local to global map for rows
2531e176bc59SStefano Zampini -     cmap    - local to global map for cols
2532284134d9SBarry Smith 
2533284134d9SBarry Smith    Output Parameter:
2534284134d9SBarry Smith .    A - the resulting matrix
2535284134d9SBarry Smith 
25368e6c10adSSatish Balay    Level: advanced
25378e6c10adSSatish Balay 
253895452b02SPatrick Sanan    Notes:
253995452b02SPatrick Sanan     See MATIS for more details.
25406fdf41d1SStefano Zampini           m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors
25416fdf41d1SStefano Zampini           used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
25423c212e90SHong Zhang           If either rmap or cmap are NULL, then the matrix is assumed to be square.
2543284134d9SBarry Smith 
2544284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
2545284134d9SBarry Smith @*/
2546e176bc59SStefano Zampini PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
2547284134d9SBarry Smith {
2548284134d9SBarry Smith   PetscErrorCode ierr;
2549284134d9SBarry Smith 
2550284134d9SBarry Smith   PetscFunctionBegin;
25516fdf41d1SStefano Zampini   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings");
2552284134d9SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
2553284134d9SBarry Smith   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
25546fdf41d1SStefano Zampini   if (bs > 0) {
2555284134d9SBarry Smith     ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
25566fdf41d1SStefano Zampini   }
2557284134d9SBarry Smith   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
2558e176bc59SStefano Zampini   if (rmap && cmap) {
2559e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
2560e176bc59SStefano Zampini   } else if (!rmap) {
2561e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
2562e176bc59SStefano Zampini   } else {
2563e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
2564e176bc59SStefano Zampini   }
2565284134d9SBarry Smith   PetscFunctionReturn(0);
2566284134d9SBarry Smith }
2567284134d9SBarry Smith 
2568b4319ba4SBarry Smith /*MC
2569f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
2570b4319ba4SBarry Smith    This stores the matrices in globally unassembled form. Each processor
2571b4319ba4SBarry Smith    assembles only its local Neumann problem and the parallel matrix vector
2572b4319ba4SBarry Smith    product is handled "implicitly".
2573b4319ba4SBarry Smith 
2574b4319ba4SBarry Smith    Operations Provided:
25756726f965SBarry Smith +  MatMult()
25762e74eeadSLisandro Dalcin .  MatMultAdd()
25772e74eeadSLisandro Dalcin .  MatMultTranspose()
25782e74eeadSLisandro Dalcin .  MatMultTransposeAdd()
25796726f965SBarry Smith .  MatZeroEntries()
25806726f965SBarry Smith .  MatSetOption()
25812e74eeadSLisandro Dalcin .  MatZeroRows()
25822e74eeadSLisandro Dalcin .  MatSetValues()
258397563a80SStefano Zampini .  MatSetValuesBlocked()
25846726f965SBarry Smith .  MatSetValuesLocal()
258597563a80SStefano Zampini .  MatSetValuesBlockedLocal()
25862e74eeadSLisandro Dalcin .  MatScale()
25872e74eeadSLisandro Dalcin .  MatGetDiagonal()
25882b404112SStefano Zampini .  MatMissingDiagonal()
25892b404112SStefano Zampini .  MatDuplicate()
25902b404112SStefano Zampini .  MatCopy()
2591f26d0771SStefano Zampini .  MatAXPY()
25927dae84e0SHong Zhang .  MatCreateSubMatrix()
2593f26d0771SStefano Zampini .  MatGetLocalSubMatrix()
2594d7f69cd0SStefano Zampini .  MatTranspose()
259575d48cdbSStefano Zampini .  MatPtAP() (with P of AIJ type)
25966726f965SBarry Smith -  MatSetLocalToGlobalMapping()
2597b4319ba4SBarry Smith 
2598b4319ba4SBarry Smith    Options Database Keys:
259975d48cdbSStefano Zampini + -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
260075d48cdbSStefano Zampini . -matis_fixempty - Fixes local matrices in case of empty local rows/columns.
260175d48cdbSStefano Zampini - -matis_storel2l - stores the local-to-local operators generated by the Galerkin process of MatPtAP().
2602b4319ba4SBarry Smith 
260395452b02SPatrick Sanan    Notes:
260495452b02SPatrick Sanan     Options prefix for the inner matrix are given by -is_mat_xxx
2605b4319ba4SBarry Smith 
2606b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
2607b4319ba4SBarry Smith 
2608b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
2609eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
2610b4319ba4SBarry Smith 
2611b4319ba4SBarry Smith   Level: advanced
2612b4319ba4SBarry Smith 
2613f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
2614b4319ba4SBarry Smith 
2615b4319ba4SBarry Smith M*/
2616b4319ba4SBarry Smith 
26178cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
2618b4319ba4SBarry Smith {
2619dfbe8321SBarry Smith   PetscErrorCode ierr;
2620b4319ba4SBarry Smith   Mat_IS         *b;
2621b4319ba4SBarry Smith 
2622b4319ba4SBarry Smith   PetscFunctionBegin;
2623b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
2624b4319ba4SBarry Smith   A->data = (void*)b;
2625b4319ba4SBarry Smith 
2626e176bc59SStefano Zampini   /* matrix ops */
2627e176bc59SStefano Zampini   ierr = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
2628b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
26292e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
26302e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
26312e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
2632b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
2633b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
26342e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
263598921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
2636b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
2637f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
26382e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
2639f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
2640b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
2641b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
2642b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
26436726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
26442e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
26452e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
26466726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
264769796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
264869796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
264945471136SStefano Zampini   A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS;
2650ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
26516bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
26522b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
2653659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
26547dae84e0SHong Zhang   A->ops->createsubmatrix         = MatCreateSubMatrix_IS;
2655f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
26563fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
26573fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
2658d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
26597fa8f2d3SStefano Zampini   A->ops->getinfo                 = MatGetInfo_IS;
2660ad219c80Sstefano_zampini   A->ops->diagonalscale           = MatDiagonalScale_IS;
2661872cf891SStefano Zampini   A->ops->setfromoptions          = MatSetFromOptions_IS;
2662b4319ba4SBarry Smith 
2663b7ce53b6SStefano Zampini   /* special MATIS functions */
2664bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
26653b3b1effSJed Brown   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISRestoreLocalMat_C",MatISRestoreLocalMat_IS);CHKERRQ(ierr);
2666bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
2667b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatISGetMPIXAIJ_IS);CHKERRQ(ierr);
26682e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
2669cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",MatISSetUpSF_IS);CHKERRQ(ierr);
267075d48cdbSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",MatISStoreL2L_IS);CHKERRQ(ierr);
267117667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
2672b4319ba4SBarry Smith   PetscFunctionReturn(0);
2673b4319ba4SBarry Smith }
2674