xref: /petsc/src/mat/impls/is/matis.c (revision a72d46e8e7e5c1ca21e150f6c091a62358e50c50)
1b4319ba4SBarry Smith /*
2b4319ba4SBarry Smith     Creates a matrix class for using the Neumann-Neumann type preconditioners.
3b4319ba4SBarry Smith     This stores the matrices in globally unassembled form. Each processor
4b4319ba4SBarry Smith     assembles only its local Neumann problem and the parallel matrix vector
5b4319ba4SBarry Smith     product is handled "implicitly".
6b4319ba4SBarry Smith 
7b4319ba4SBarry Smith     Currently this allows for only one subdomain per processor.
8b4319ba4SBarry Smith */
9b4319ba4SBarry Smith 
10c6db04a5SJed Brown #include <../src/mat/impls/is/matis.h>      /*I "petscmat.h" I*/
114f2d7cafSStefano Zampini #include <petsc/private/sfimpl.h>
12*a72d46e8SStefano Zampini #include <petsc/private/vecimpl.h>
1328f4e0baSStefano Zampini 
14f26d0771SStefano Zampini #define MATIS_MAX_ENTRIES_INSERTION 2048
15b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat,PetscInt,const PetscInt*,PetscInt,const PetscInt*,const PetscScalar*,InsertMode);
16b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat,PetscInt,const PetscInt*,PetscInt,const PetscInt*,const PetscScalar*,InsertMode);
178546b261SStefano Zampini static PetscErrorCode MatISSetUpScatters_Private(Mat);
18f26d0771SStefano Zampini 
1975d48cdbSStefano Zampini static PetscErrorCode MatISContainerDestroyPtAP_Private(void *ptr)
2075d48cdbSStefano Zampini {
2175d48cdbSStefano Zampini   MatISPtAP      ptap = (MatISPtAP)ptr;
2275d48cdbSStefano Zampini   PetscErrorCode ierr;
2375d48cdbSStefano Zampini 
2475d48cdbSStefano Zampini   PetscFunctionBegin;
2575d48cdbSStefano Zampini   ierr = MatDestroySubMatrices(ptap->ris1 ? 2 : 1,&ptap->lP);CHKERRQ(ierr);
2675d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->cis0);CHKERRQ(ierr);
2775d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->cis1);CHKERRQ(ierr);
2875d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->ris0);CHKERRQ(ierr);
2975d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->ris1);CHKERRQ(ierr);
3075d48cdbSStefano Zampini   ierr = PetscFree(ptap);CHKERRQ(ierr);
3175d48cdbSStefano Zampini   PetscFunctionReturn(0);
3275d48cdbSStefano Zampini }
3375d48cdbSStefano Zampini 
3475d48cdbSStefano Zampini static PetscErrorCode MatPtAPNumeric_IS_XAIJ(Mat A, Mat P, Mat C)
3575d48cdbSStefano Zampini {
3675d48cdbSStefano Zampini   MatISPtAP      ptap;
3775d48cdbSStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
3875d48cdbSStefano Zampini   Mat            lA,lC;
3975d48cdbSStefano Zampini   MatReuse       reuse;
4075d48cdbSStefano Zampini   IS             ris[2],cis[2];
4175d48cdbSStefano Zampini   PetscContainer c;
4275d48cdbSStefano Zampini   PetscInt       n;
4375d48cdbSStefano Zampini   PetscErrorCode ierr;
4475d48cdbSStefano Zampini 
4575d48cdbSStefano Zampini   PetscFunctionBegin;
466afe12f5SStefano Zampini   ierr = PetscObjectQuery((PetscObject)C,"_MatIS_PtAP",(PetscObject*)&c);CHKERRQ(ierr);
4775d48cdbSStefano Zampini   if (!c) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing PtAP information");
4875d48cdbSStefano Zampini   ierr   = PetscContainerGetPointer(c,(void**)&ptap);CHKERRQ(ierr);
4975d48cdbSStefano Zampini   ris[0] = ptap->ris0;
5075d48cdbSStefano Zampini   ris[1] = ptap->ris1;
5175d48cdbSStefano Zampini   cis[0] = ptap->cis0;
5275d48cdbSStefano Zampini   cis[1] = ptap->cis1;
5375d48cdbSStefano Zampini   n      = ptap->ris1 ? 2 : 1;
5475d48cdbSStefano Zampini   reuse  = ptap->lP ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX;
5575d48cdbSStefano Zampini   ierr   = MatCreateSubMatrices(P,n,ris,cis,reuse,&ptap->lP);CHKERRQ(ierr);
5675d48cdbSStefano Zampini 
5775d48cdbSStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
5875d48cdbSStefano Zampini   ierr = MatISGetLocalMat(C,&lC);CHKERRQ(ierr);
5975d48cdbSStefano Zampini   if (ptap->ris1) { /* unsymmetric A mapping */
6075d48cdbSStefano Zampini     Mat lPt;
6175d48cdbSStefano Zampini 
6275d48cdbSStefano Zampini     ierr = MatTranspose(ptap->lP[1],MAT_INITIAL_MATRIX,&lPt);CHKERRQ(ierr);
6375d48cdbSStefano Zampini     ierr = MatMatMatMult(lPt,lA,ptap->lP[0],reuse,ptap->fill,&lC);CHKERRQ(ierr);
6475d48cdbSStefano Zampini     if (matis->storel2l) {
6575d48cdbSStefano Zampini       ierr = PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",(PetscObject)lPt);CHKERRQ(ierr);
6675d48cdbSStefano Zampini     }
6775d48cdbSStefano Zampini     ierr = MatDestroy(&lPt);CHKERRQ(ierr);
6875d48cdbSStefano Zampini   } else {
6975d48cdbSStefano Zampini     ierr = MatPtAP(lA,ptap->lP[0],reuse,ptap->fill,&lC);CHKERRQ(ierr);
7075d48cdbSStefano Zampini     if (matis->storel2l) {
7175d48cdbSStefano Zampini      ierr = PetscObjectCompose((PetscObject)(C),"_MatIS_PtAP_l2l",(PetscObject)ptap->lP[0]);CHKERRQ(ierr);
7275d48cdbSStefano Zampini     }
7375d48cdbSStefano Zampini   }
7475d48cdbSStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
7575d48cdbSStefano Zampini     ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
7675d48cdbSStefano Zampini     ierr = MatDestroy(&lC);CHKERRQ(ierr);
7775d48cdbSStefano Zampini   }
7875d48cdbSStefano Zampini   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7975d48cdbSStefano Zampini   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
8075d48cdbSStefano Zampini   PetscFunctionReturn(0);
8175d48cdbSStefano Zampini }
8275d48cdbSStefano Zampini 
8375d48cdbSStefano Zampini static PetscErrorCode MatGetNonzeroColumnsLocal_Private(Mat PT,IS *cis)
8475d48cdbSStefano Zampini {
8575d48cdbSStefano Zampini   Mat            Po,Pd;
8675d48cdbSStefano Zampini   IS             zd,zo;
8775d48cdbSStefano Zampini   const PetscInt *garray;
8875d48cdbSStefano Zampini   PetscInt       *aux,i,bs;
8975d48cdbSStefano Zampini   PetscInt       dc,stc,oc,ctd,cto;
9075d48cdbSStefano Zampini   PetscBool      ismpiaij,ismpibaij,isseqaij,isseqbaij;
9175d48cdbSStefano Zampini   MPI_Comm       comm;
9275d48cdbSStefano Zampini   PetscErrorCode ierr;
9375d48cdbSStefano Zampini 
9475d48cdbSStefano Zampini   PetscFunctionBegin;
9575d48cdbSStefano Zampini   PetscValidHeaderSpecific(PT,MAT_CLASSID,1);
9675d48cdbSStefano Zampini   PetscValidPointer(cis,2);
9775d48cdbSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)PT,&comm);CHKERRQ(ierr);
9875d48cdbSStefano Zampini   bs   = 1;
9975d48cdbSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)PT,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
10075d48cdbSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)PT,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr);
10104637862SRichard Tran Mills   ierr = PetscObjectBaseTypeCompare((PetscObject)PT,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
10275d48cdbSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)PT,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
10375d48cdbSStefano Zampini   if (isseqaij || isseqbaij) {
10475d48cdbSStefano Zampini     Pd = PT;
10575d48cdbSStefano Zampini     Po = NULL;
10675d48cdbSStefano Zampini     garray = NULL;
10775d48cdbSStefano Zampini   } else if (ismpiaij) {
10875d48cdbSStefano Zampini     ierr = MatMPIAIJGetSeqAIJ(PT,&Pd,&Po,&garray);CHKERRQ(ierr);
10975d48cdbSStefano Zampini   } else if (ismpibaij) {
11075d48cdbSStefano Zampini     ierr = MatMPIBAIJGetSeqBAIJ(PT,&Pd,&Po,&garray);CHKERRQ(ierr);
11175d48cdbSStefano Zampini     ierr = MatGetBlockSize(PT,&bs);CHKERRQ(ierr);
11275d48cdbSStefano Zampini   } else SETERRQ1(comm,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(PT))->type_name);
11375d48cdbSStefano Zampini 
11475d48cdbSStefano Zampini   /* identify any null columns in Pd or Po */
11522f7620eSStefano Zampini   /* We use a tolerance comparison since it may happen that, with geometric multigrid,
11622f7620eSStefano Zampini      some of the columns are not really zero, but very close to */
11775d48cdbSStefano Zampini   zo = zd = NULL;
11875d48cdbSStefano Zampini   if (Po) {
11922f7620eSStefano Zampini     ierr = MatFindNonzeroRowsOrCols_Basic(Po,PETSC_TRUE,PETSC_SMALL,&zo);CHKERRQ(ierr);
12075d48cdbSStefano Zampini   }
12122f7620eSStefano Zampini   ierr = MatFindNonzeroRowsOrCols_Basic(Pd,PETSC_TRUE,PETSC_SMALL,&zd);CHKERRQ(ierr);
12275d48cdbSStefano Zampini 
12375d48cdbSStefano Zampini   ierr = MatGetLocalSize(PT,NULL,&dc);CHKERRQ(ierr);
12475d48cdbSStefano Zampini   ierr = MatGetOwnershipRangeColumn(PT,&stc,NULL);CHKERRQ(ierr);
12575d48cdbSStefano Zampini   if (Po) { ierr = MatGetLocalSize(Po,NULL,&oc);CHKERRQ(ierr); }
12675d48cdbSStefano Zampini   else oc = 0;
12775d48cdbSStefano Zampini   ierr = PetscMalloc1((dc+oc)/bs,&aux);CHKERRQ(ierr);
12875d48cdbSStefano Zampini   if (zd) {
12975d48cdbSStefano Zampini     const PetscInt *idxs;
13075d48cdbSStefano Zampini     PetscInt       nz;
13175d48cdbSStefano Zampini 
13275d48cdbSStefano Zampini     /* this will throw an error if bs is not valid */
13375d48cdbSStefano Zampini     ierr = ISSetBlockSize(zd,bs);CHKERRQ(ierr);
13475d48cdbSStefano Zampini     ierr = ISGetLocalSize(zd,&nz);CHKERRQ(ierr);
13575d48cdbSStefano Zampini     ierr = ISGetIndices(zd,&idxs);CHKERRQ(ierr);
13675d48cdbSStefano Zampini     ctd  = nz/bs;
13775d48cdbSStefano Zampini     for (i=0; i<ctd; i++) aux[i] = (idxs[bs*i]+stc)/bs;
13875d48cdbSStefano Zampini     ierr = ISRestoreIndices(zd,&idxs);CHKERRQ(ierr);
13975d48cdbSStefano Zampini   } else {
14075d48cdbSStefano Zampini     ctd = dc/bs;
14175d48cdbSStefano Zampini     for (i=0; i<ctd; i++) aux[i] = i+stc/bs;
14275d48cdbSStefano Zampini   }
14375d48cdbSStefano Zampini   if (zo) {
14475d48cdbSStefano Zampini     const PetscInt *idxs;
14575d48cdbSStefano Zampini     PetscInt       nz;
14675d48cdbSStefano Zampini 
14775d48cdbSStefano Zampini     /* this will throw an error if bs is not valid */
14875d48cdbSStefano Zampini     ierr = ISSetBlockSize(zo,bs);CHKERRQ(ierr);
14975d48cdbSStefano Zampini     ierr = ISGetLocalSize(zo,&nz);CHKERRQ(ierr);
15075d48cdbSStefano Zampini     ierr = ISGetIndices(zo,&idxs);CHKERRQ(ierr);
15175d48cdbSStefano Zampini     cto  = nz/bs;
15275d48cdbSStefano Zampini     for (i=0; i<cto; i++) aux[i+ctd] = garray[idxs[bs*i]/bs];
15375d48cdbSStefano Zampini     ierr = ISRestoreIndices(zo,&idxs);CHKERRQ(ierr);
15475d48cdbSStefano Zampini   } else {
15575d48cdbSStefano Zampini     cto = oc/bs;
15675d48cdbSStefano Zampini     for (i=0; i<cto; i++) aux[i+ctd] = garray[i];
15775d48cdbSStefano Zampini   }
15875d48cdbSStefano Zampini   ierr = ISCreateBlock(comm,bs,ctd+cto,aux,PETSC_OWN_POINTER,cis);CHKERRQ(ierr);
15975d48cdbSStefano Zampini   ierr = ISDestroy(&zd);CHKERRQ(ierr);
16075d48cdbSStefano Zampini   ierr = ISDestroy(&zo);CHKERRQ(ierr);
16175d48cdbSStefano Zampini   PetscFunctionReturn(0);
16275d48cdbSStefano Zampini }
16375d48cdbSStefano Zampini 
16475d48cdbSStefano Zampini static PetscErrorCode MatPtAPSymbolic_IS_XAIJ(Mat A,Mat P,PetscReal fill,Mat *C)
16575d48cdbSStefano Zampini {
1668546b261SStefano Zampini   Mat                    PT,lA;
16775d48cdbSStefano Zampini   MatISPtAP              ptap;
16875d48cdbSStefano Zampini   ISLocalToGlobalMapping Crl2g,Ccl2g,rl2g,cl2g;
16975d48cdbSStefano Zampini   PetscContainer         c;
1708546b261SStefano Zampini   MatType                lmtype;
17175d48cdbSStefano Zampini   const PetscInt         *garray;
17275d48cdbSStefano Zampini   PetscInt               ibs,N,dc;
17375d48cdbSStefano Zampini   MPI_Comm               comm;
17475d48cdbSStefano Zampini   PetscErrorCode         ierr;
17575d48cdbSStefano Zampini 
17675d48cdbSStefano Zampini   PetscFunctionBegin;
17775d48cdbSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
17875d48cdbSStefano Zampini   ierr = MatCreate(comm,C);CHKERRQ(ierr);
17975d48cdbSStefano Zampini   ierr = MatSetType(*C,MATIS);CHKERRQ(ierr);
1808546b261SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
1818546b261SStefano Zampini   ierr = MatGetType(lA,&lmtype);CHKERRQ(ierr);
1828546b261SStefano Zampini   ierr = MatISSetLocalMatType(*C,lmtype);CHKERRQ(ierr);
18375d48cdbSStefano Zampini   ierr = MatGetSize(P,NULL,&N);CHKERRQ(ierr);
18475d48cdbSStefano Zampini   ierr = MatGetLocalSize(P,NULL,&dc);CHKERRQ(ierr);
18575d48cdbSStefano Zampini   ierr = MatSetSizes(*C,dc,dc,N,N);CHKERRQ(ierr);
18675d48cdbSStefano Zampini /* Not sure about this
18775d48cdbSStefano Zampini   ierr = MatGetBlockSizes(P,NULL,&ibs);CHKERRQ(ierr);
18875d48cdbSStefano Zampini   ierr = MatSetBlockSize(*C,ibs);CHKERRQ(ierr);
18975d48cdbSStefano Zampini */
19075d48cdbSStefano Zampini 
19175d48cdbSStefano Zampini   ierr = PetscNew(&ptap);CHKERRQ(ierr);
19275d48cdbSStefano Zampini   ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr);
19375d48cdbSStefano Zampini   ierr = PetscContainerSetPointer(c,ptap);CHKERRQ(ierr);
19475d48cdbSStefano Zampini   ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyPtAP_Private);CHKERRQ(ierr);
19575d48cdbSStefano Zampini   ierr = PetscObjectCompose((PetscObject)(*C),"_MatIS_PtAP",(PetscObject)c);CHKERRQ(ierr);
19675d48cdbSStefano Zampini   ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
19775d48cdbSStefano Zampini   ptap->fill = fill;
19875d48cdbSStefano Zampini 
19975d48cdbSStefano Zampini   ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
20075d48cdbSStefano Zampini 
20175d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cl2g,&ibs);CHKERRQ(ierr);
20275d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cl2g,&N);CHKERRQ(ierr);
20375d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockIndices(cl2g,&garray);CHKERRQ(ierr);
20475d48cdbSStefano Zampini   ierr = ISCreateBlock(comm,ibs,N/ibs,garray,PETSC_COPY_VALUES,&ptap->ris0);CHKERRQ(ierr);
20575d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreBlockIndices(cl2g,&garray);CHKERRQ(ierr);
20675d48cdbSStefano Zampini 
20775d48cdbSStefano Zampini   ierr = MatCreateSubMatrix(P,ptap->ris0,NULL,MAT_INITIAL_MATRIX,&PT);CHKERRQ(ierr);
20875d48cdbSStefano Zampini   ierr = MatGetNonzeroColumnsLocal_Private(PT,&ptap->cis0);CHKERRQ(ierr);
20975d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(ptap->cis0,&Ccl2g);CHKERRQ(ierr);
21075d48cdbSStefano Zampini   ierr = MatDestroy(&PT);CHKERRQ(ierr);
21175d48cdbSStefano Zampini 
21275d48cdbSStefano Zampini   Crl2g = NULL;
21375d48cdbSStefano Zampini   if (rl2g != cl2g) { /* unsymmetric A mapping */
21475d48cdbSStefano Zampini     PetscBool same,lsame = PETSC_FALSE;
21575d48cdbSStefano Zampini     PetscInt  N1,ibs1;
21675d48cdbSStefano Zampini 
21775d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(rl2g,&N1);CHKERRQ(ierr);
21875d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(rl2g,&ibs1);CHKERRQ(ierr);
21975d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockIndices(rl2g,&garray);CHKERRQ(ierr);
22075d48cdbSStefano Zampini     ierr = ISCreateBlock(comm,ibs,N/ibs,garray,PETSC_COPY_VALUES,&ptap->ris1);CHKERRQ(ierr);
22175d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreBlockIndices(rl2g,&garray);CHKERRQ(ierr);
22275d48cdbSStefano Zampini     if (ibs1 == ibs && N1 == N) { /* check if the l2gmaps are the same */
22375d48cdbSStefano Zampini       const PetscInt *i1,*i2;
22475d48cdbSStefano Zampini 
22575d48cdbSStefano Zampini       ierr = ISBlockGetIndices(ptap->ris0,&i1);CHKERRQ(ierr);
22675d48cdbSStefano Zampini       ierr = ISBlockGetIndices(ptap->ris1,&i2);CHKERRQ(ierr);
22775d48cdbSStefano Zampini       ierr = PetscMemcmp(i1,i2,N*sizeof(*i1),&lsame);CHKERRQ(ierr);
22875d48cdbSStefano Zampini     }
22975d48cdbSStefano Zampini     ierr = MPIU_Allreduce(&lsame,&same,1,MPIU_BOOL,MPI_LAND,comm);CHKERRQ(ierr);
23075d48cdbSStefano Zampini     if (same) {
23175d48cdbSStefano Zampini       ierr = ISDestroy(&ptap->ris1);CHKERRQ(ierr);
23275d48cdbSStefano Zampini     } else {
23375d48cdbSStefano Zampini       ierr = MatCreateSubMatrix(P,ptap->ris1,NULL,MAT_INITIAL_MATRIX,&PT);CHKERRQ(ierr);
23475d48cdbSStefano Zampini       ierr = MatGetNonzeroColumnsLocal_Private(PT,&ptap->cis1);CHKERRQ(ierr);
23575d48cdbSStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(ptap->cis1,&Crl2g);CHKERRQ(ierr);
23675d48cdbSStefano Zampini       ierr = MatDestroy(&PT);CHKERRQ(ierr);
23775d48cdbSStefano Zampini     }
23875d48cdbSStefano Zampini   }
23975d48cdbSStefano Zampini /* Not sure about this
24075d48cdbSStefano Zampini   if (!Crl2g) {
24175d48cdbSStefano Zampini     ierr = MatGetBlockSize(*C,&ibs);CHKERRQ(ierr);
24275d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingSetBlockSize(Ccl2g,ibs);CHKERRQ(ierr);
24375d48cdbSStefano Zampini   }
24475d48cdbSStefano Zampini */
24575d48cdbSStefano Zampini   ierr = MatSetLocalToGlobalMapping(*C,Crl2g ? Crl2g : Ccl2g,Ccl2g);CHKERRQ(ierr);
24675d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&Crl2g);CHKERRQ(ierr);
24775d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&Ccl2g);CHKERRQ(ierr);
24875d48cdbSStefano Zampini 
24975d48cdbSStefano Zampini   (*C)->ops->ptapnumeric = MatPtAPNumeric_IS_XAIJ;
25075d48cdbSStefano Zampini   PetscFunctionReturn(0);
25175d48cdbSStefano Zampini }
25275d48cdbSStefano Zampini 
25375d48cdbSStefano Zampini PETSC_INTERN PetscErrorCode MatPtAP_IS_XAIJ(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C)
25475d48cdbSStefano Zampini {
25575d48cdbSStefano Zampini   PetscErrorCode ierr;
25675d48cdbSStefano Zampini 
25775d48cdbSStefano Zampini   PetscFunctionBegin;
25875d48cdbSStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
25975d48cdbSStefano Zampini     ierr = PetscLogEventBegin(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr);
26075d48cdbSStefano Zampini     ierr = MatPtAPSymbolic_IS_XAIJ(A,P,fill,C);CHKERRQ(ierr);
26175d48cdbSStefano Zampini     ierr = PetscLogEventEnd(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr);
26275d48cdbSStefano Zampini   }
26375d48cdbSStefano Zampini   ierr = PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
26475d48cdbSStefano Zampini   ierr = ((*C)->ops->ptapnumeric)(A,P,*C);CHKERRQ(ierr);
26575d48cdbSStefano Zampini   ierr = PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
26675d48cdbSStefano Zampini   PetscFunctionReturn(0);
26775d48cdbSStefano Zampini }
26875d48cdbSStefano Zampini 
2695b003df0Sstefano_zampini static PetscErrorCode MatISContainerDestroyFields_Private(void *ptr)
2705b003df0Sstefano_zampini {
2715b003df0Sstefano_zampini   MatISLocalFields lf = (MatISLocalFields)ptr;
2725b003df0Sstefano_zampini   PetscInt         i;
2735b003df0Sstefano_zampini   PetscErrorCode   ierr;
2745b003df0Sstefano_zampini 
275ab4d48faSStefano Zampini   PetscFunctionBegin;
2765b003df0Sstefano_zampini   for (i=0;i<lf->nr;i++) {
2775b003df0Sstefano_zampini     ierr = ISDestroy(&lf->rf[i]);CHKERRQ(ierr);
2785b003df0Sstefano_zampini   }
2795b003df0Sstefano_zampini   for (i=0;i<lf->nc;i++) {
2805b003df0Sstefano_zampini     ierr = ISDestroy(&lf->cf[i]);CHKERRQ(ierr);
2815b003df0Sstefano_zampini   }
2825b003df0Sstefano_zampini   ierr = PetscFree2(lf->rf,lf->cf);CHKERRQ(ierr);
2835b003df0Sstefano_zampini   ierr = PetscFree(lf);CHKERRQ(ierr);
2845b003df0Sstefano_zampini   PetscFunctionReturn(0);
2855b003df0Sstefano_zampini }
286a72627d2SStefano Zampini 
287c9225affSStefano Zampini static PetscErrorCode MatConvert_SeqXAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
2886989cf23SStefano Zampini {
289c9225affSStefano Zampini   Mat            B,lB;
290c9225affSStefano Zampini   PetscErrorCode ierr;
291c9225affSStefano Zampini 
292c9225affSStefano Zampini   PetscFunctionBegin;
293c9225affSStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
294c9225affSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g;
295c9225affSStefano Zampini     PetscInt               bs;
296c9225affSStefano Zampini     IS                     is;
297c9225affSStefano Zampini 
298c9225affSStefano Zampini     ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
299c9225affSStefano Zampini     ierr = ISCreateStride(PetscObjectComm((PetscObject)A),A->rmap->n/bs,0,1,&is);CHKERRQ(ierr);
300c9225affSStefano Zampini     if (bs > 1) {
301c9225affSStefano Zampini       IS       is2;
302c9225affSStefano Zampini       PetscInt i,*aux;
303c9225affSStefano Zampini 
304c9225affSStefano Zampini       ierr = ISGetLocalSize(is,&i);CHKERRQ(ierr);
305c9225affSStefano Zampini       ierr = ISGetIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
306c9225affSStefano Zampini       ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),bs,i,aux,PETSC_COPY_VALUES,&is2);CHKERRQ(ierr);
307c9225affSStefano Zampini       ierr = ISRestoreIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
308c9225affSStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
309c9225affSStefano Zampini       is   = is2;
310c9225affSStefano Zampini     }
311c9225affSStefano Zampini     ierr = ISSetIdentity(is);CHKERRQ(ierr);
312c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
313c9225affSStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
314c9225affSStefano Zampini     ierr = ISCreateStride(PetscObjectComm((PetscObject)A),A->cmap->n/bs,0,1,&is);CHKERRQ(ierr);
315c9225affSStefano Zampini     if (bs > 1) {
316c9225affSStefano Zampini       IS       is2;
317c9225affSStefano Zampini       PetscInt i,*aux;
318c9225affSStefano Zampini 
319c9225affSStefano Zampini       ierr = ISGetLocalSize(is,&i);CHKERRQ(ierr);
320c9225affSStefano Zampini       ierr = ISGetIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
321c9225affSStefano Zampini       ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),bs,i,aux,PETSC_COPY_VALUES,&is2);CHKERRQ(ierr);
322c9225affSStefano Zampini       ierr = ISRestoreIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
323c9225affSStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
324c9225affSStefano Zampini       is   = is2;
325c9225affSStefano Zampini     }
326c9225affSStefano Zampini     ierr = ISSetIdentity(is);CHKERRQ(ierr);
327c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
328c9225affSStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
329c9225affSStefano Zampini     ierr = MatCreateIS(PetscObjectComm((PetscObject)A),bs,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N,rl2g,cl2g,&B);CHKERRQ(ierr);
330c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
331c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
332c9225affSStefano Zampini     ierr = MatDuplicate(A,MAT_COPY_VALUES,&lB);CHKERRQ(ierr);
333c9225affSStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) *newmat = B;
334c9225affSStefano Zampini   } else {
335c9225affSStefano Zampini     B    = *newmat;
336c9225affSStefano Zampini     ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
337c9225affSStefano Zampini     lB   = A;
338c9225affSStefano Zampini   }
339c9225affSStefano Zampini   ierr = MatISSetLocalMat(B,lB);CHKERRQ(ierr);
340c9225affSStefano Zampini   ierr = MatDestroy(&lB);CHKERRQ(ierr);
341c9225affSStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
342c9225affSStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
343c9225affSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
344c9225affSStefano Zampini     ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
345c9225affSStefano Zampini   }
346c9225affSStefano Zampini   PetscFunctionReturn(0);
347c9225affSStefano Zampini }
348c9225affSStefano Zampini 
349c9225affSStefano Zampini static PetscErrorCode MatISScaleDisassembling_Private(Mat A)
350c9225affSStefano Zampini {
351c9225affSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(A->data);
352c9225affSStefano Zampini   PetscScalar    *aa;
353c9225affSStefano Zampini   const PetscInt *ii,*jj;
354c9225affSStefano Zampini   PetscInt       i,n,m;
355fabe8965SStefano Zampini   PetscInt       *ecount,**eneighs;
356c9225affSStefano Zampini   PetscBool      flg;
357c9225affSStefano Zampini   PetscErrorCode ierr;
358c9225affSStefano Zampini 
359c9225affSStefano Zampini   PetscFunctionBegin;
360c9225affSStefano Zampini   ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&m,&ii,&jj,&flg);CHKERRQ(ierr);
361c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
362fabe8965SStefano Zampini   ierr = ISLocalToGlobalMappingGetNodeInfo(A->rmap->mapping,&n,&ecount,&eneighs);CHKERRQ(ierr);
363c9225affSStefano Zampini   if (m != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %D != %D",m,n);
364c9225affSStefano Zampini   ierr = MatSeqAIJGetArray(matis->A,&aa);CHKERRQ(ierr);
365c9225affSStefano Zampini   for (i=0;i<n;i++) {
366fabe8965SStefano Zampini     if (ecount[i] > 1) {
367c9225affSStefano Zampini       PetscInt j;
368c9225affSStefano Zampini 
369c9225affSStefano Zampini       for (j=ii[i];j<ii[i+1];j++) {
370c9225affSStefano Zampini         PetscInt    i2 = jj[j],p,p2;
371fabe8965SStefano Zampini         PetscReal   scal = 0.0;
372c9225affSStefano Zampini 
373c9225affSStefano Zampini         for (p=0;p<ecount[i];p++) {
374c9225affSStefano Zampini           for (p2=0;p2<ecount[i2];p2++) {
375c9225affSStefano Zampini             if (eneighs[i][p] == eneighs[i2][p2]) { scal += 1.0; break; }
376c9225affSStefano Zampini           }
377c9225affSStefano Zampini         }
378fabe8965SStefano Zampini         if (scal) aa[j] /= scal;
379c9225affSStefano Zampini       }
380c9225affSStefano Zampini     }
381c9225affSStefano Zampini   }
382fabe8965SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreNodeInfo(A->rmap->mapping,&n,&ecount,&eneighs);CHKERRQ(ierr);
383c9225affSStefano Zampini   ierr = MatSeqAIJRestoreArray(matis->A,&aa);CHKERRQ(ierr);
384c9225affSStefano Zampini   ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&m,&ii,&jj,&flg);CHKERRQ(ierr);
385c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
386c9225affSStefano Zampini   PetscFunctionReturn(0);
387c9225affSStefano Zampini }
388c9225affSStefano Zampini 
389fabe8965SStefano Zampini typedef enum {MAT_IS_DISASSEMBLE_L2G_NATURAL,MAT_IS_DISASSEMBLE_L2G_MAT, MAT_IS_DISASSEMBLE_L2G_ND} MatISDisassemblel2gType;
390fabe8965SStefano Zampini 
391c9225affSStefano Zampini static PetscErrorCode MatMPIXAIJComputeLocalToGlobalMapping_Private(Mat A, ISLocalToGlobalMapping *l2g)
392c9225affSStefano Zampini {
393fabe8965SStefano Zampini   Mat                     Ad,Ao;
394fabe8965SStefano Zampini   IS                      is,ndmap,ndsub;
395c9225affSStefano Zampini   MPI_Comm                comm;
396fabe8965SStefano Zampini   const PetscInt          *garray,*ndmapi;
397fabe8965SStefano Zampini   PetscInt                bs,i,cnt,nl,*ncount,*ndmapc;
398fabe8965SStefano Zampini   PetscBool               ismpiaij,ismpibaij;
399fabe8965SStefano Zampini   const char *const       MatISDisassemblel2gTypes[] = {"NATURAL","MAT","ND","MatISDisassemblel2gType","MAT_IS_DISASSEMBLE_L2G_",0};
400fabe8965SStefano Zampini   MatISDisassemblel2gType mode = MAT_IS_DISASSEMBLE_L2G_NATURAL;
401fabe8965SStefano Zampini   MatPartitioning         part;
402fabe8965SStefano Zampini   PetscSF                 sf;
403c9225affSStefano Zampini   PetscErrorCode          ierr;
404c9225affSStefano Zampini 
405c9225affSStefano Zampini   PetscFunctionBegin;
406fabe8965SStefano Zampini   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"MatIS l2g disassembling options","Mat");CHKERRQ(ierr);
407fabe8965SStefano Zampini   ierr = PetscOptionsEnum("-mat_is_disassemble_l2g_type","Type of local-to-global mapping to be used for disassembling","MatISDisassemblel2gType",MatISDisassemblel2gTypes,(PetscEnum)mode,(PetscEnum*)&mode,NULL);CHKERRQ(ierr);
408fabe8965SStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
409fabe8965SStefano Zampini   if (mode == MAT_IS_DISASSEMBLE_L2G_MAT) {
410c9225affSStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,l2g,NULL);CHKERRQ(ierr);
411c9225affSStefano Zampini     PetscFunctionReturn(0);
412c9225affSStefano Zampini   }
413c9225affSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
414c9225affSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij);CHKERRQ(ierr);
415c9225affSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr);
416c9225affSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
417fabe8965SStefano Zampini   switch (mode) {
418fabe8965SStefano Zampini   case MAT_IS_DISASSEMBLE_L2G_ND:
419fabe8965SStefano Zampini     ierr = MatPartitioningCreate(comm,&part);CHKERRQ(ierr);
420fabe8965SStefano Zampini     ierr = MatPartitioningSetAdjacency(part,A);CHKERRQ(ierr);
421fabe8965SStefano Zampini     ierr = PetscObjectSetOptionsPrefix((PetscObject)part,((PetscObject)A)->prefix);CHKERRQ(ierr);
422fabe8965SStefano Zampini     ierr = MatPartitioningSetFromOptions(part);CHKERRQ(ierr);
423fabe8965SStefano Zampini     ierr = MatPartitioningApplyND(part,&ndmap);CHKERRQ(ierr);
424fabe8965SStefano Zampini     ierr = MatPartitioningDestroy(&part);CHKERRQ(ierr);
425fabe8965SStefano Zampini     ierr = ISBuildTwoSided(ndmap,NULL,&ndsub);CHKERRQ(ierr);
426fabe8965SStefano Zampini     ierr = MatMPIAIJSetUseScalableIncreaseOverlap(A,PETSC_TRUE);CHKERRQ(ierr);
427fabe8965SStefano Zampini     ierr = MatIncreaseOverlap(A,1,&ndsub,1);CHKERRQ(ierr);
428fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(ndsub,l2g);CHKERRQ(ierr);
429fabe8965SStefano Zampini 
430fabe8965SStefano Zampini     /* it may happen that a separator node is not properly shared */
431fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingGetNodeInfo(*l2g,&nl,&ncount,NULL);CHKERRQ(ierr);
432fabe8965SStefano Zampini     ierr = PetscSFCreate(comm,&sf);CHKERRQ(ierr);
433fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(*l2g,&garray);CHKERRQ(ierr);
434fabe8965SStefano Zampini     ierr = PetscSFSetGraphLayout(sf,A->rmap,nl,NULL,PETSC_OWN_POINTER,garray);CHKERRQ(ierr);
435fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(*l2g,&garray);CHKERRQ(ierr);
436fabe8965SStefano Zampini     ierr = PetscCalloc1(A->rmap->n,&ndmapc);CHKERRQ(ierr);
437fabe8965SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,ncount,ndmapc,MPIU_REPLACE);CHKERRQ(ierr);
438fabe8965SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,ncount,ndmapc,MPIU_REPLACE);CHKERRQ(ierr);
439fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreNodeInfo(*l2g,NULL,&ncount,NULL);CHKERRQ(ierr);
440fabe8965SStefano Zampini     ierr = ISGetIndices(ndmap,&ndmapi);CHKERRQ(ierr);
441fabe8965SStefano Zampini     for (i = 0, cnt = 0; i < A->rmap->n; i++)
442fabe8965SStefano Zampini       if (ndmapi[i] < 0 && ndmapc[i] < 2)
443fabe8965SStefano Zampini         cnt++;
444fabe8965SStefano Zampini 
445fabe8965SStefano Zampini     ierr = MPIU_Allreduce(&cnt,&i,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
446fabe8965SStefano Zampini     if (i) { /* we detected isolated separator nodes */
447fabe8965SStefano Zampini       Mat                    A2,A3;
448fabe8965SStefano Zampini       IS                     *workis,is2;
449fabe8965SStefano Zampini       PetscScalar            *vals;
450fabe8965SStefano Zampini       PetscInt               gcnt = i,*dnz,*onz,j,*lndmapi;
451fabe8965SStefano Zampini       ISLocalToGlobalMapping ll2g;
452fabe8965SStefano Zampini       PetscBool              flg;
453fabe8965SStefano Zampini       const PetscInt         *ii,*jj;
454fabe8965SStefano Zampini 
455fabe8965SStefano Zampini       /* communicate global id of separators */
456fabe8965SStefano Zampini       ierr = MatPreallocateInitialize(comm,A->rmap->n,A->cmap->n,dnz,onz);CHKERRQ(ierr);
457fabe8965SStefano Zampini       for (i = 0, cnt = 0; i < A->rmap->n; i++)
458fabe8965SStefano Zampini         dnz[i] = ndmapi[i] < 0 ? i + A->rmap->rstart : -1;
459fabe8965SStefano Zampini 
460fabe8965SStefano Zampini       ierr = PetscMalloc1(nl,&lndmapi);CHKERRQ(ierr);
461fabe8965SStefano Zampini       ierr = PetscSFBcastBegin(sf,MPIU_INT,dnz,lndmapi);CHKERRQ(ierr);
462fabe8965SStefano Zampini 
463fabe8965SStefano Zampini       /* compute adjacency of isolated separators node */
464fabe8965SStefano Zampini       ierr = PetscMalloc1(gcnt,&workis);CHKERRQ(ierr);
465fabe8965SStefano Zampini       for (i = 0, cnt = 0; i < A->rmap->n; i++) {
466fabe8965SStefano Zampini         if (ndmapi[i] < 0 && ndmapc[i] < 2) {
467fabe8965SStefano Zampini           ierr = ISCreateStride(comm,1,i+A->rmap->rstart,1,&workis[cnt++]);CHKERRQ(ierr);
468fabe8965SStefano Zampini         }
469fabe8965SStefano Zampini       }
470fabe8965SStefano Zampini       for (i = cnt; i < gcnt; i++) {
471fabe8965SStefano Zampini         ierr = ISCreateStride(comm,0,0,1,&workis[i]);CHKERRQ(ierr);
472fabe8965SStefano Zampini       }
473fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
474fabe8965SStefano Zampini         ierr = PetscObjectSetName((PetscObject)workis[i],"ISOLATED");CHKERRQ(ierr);
475fabe8965SStefano Zampini         ierr = ISViewFromOptions(workis[i],NULL,"-view_isolated_separators");CHKERRQ(ierr);
476fabe8965SStefano Zampini       }
477fabe8965SStefano Zampini 
478fabe8965SStefano Zampini       /* no communications since all the ISes correspond to locally owned rows */
479fabe8965SStefano Zampini       ierr = MatIncreaseOverlap(A,gcnt,workis,1);CHKERRQ(ierr);
480fabe8965SStefano Zampini 
481fabe8965SStefano Zampini       /* end communicate global id of separators */
482fabe8965SStefano Zampini       ierr = PetscSFBcastEnd(sf,MPIU_INT,dnz,lndmapi);CHKERRQ(ierr);
483fabe8965SStefano Zampini 
484fabe8965SStefano Zampini       /* communicate new layers : create a matrix and transpose it */
485fabe8965SStefano Zampini       ierr = PetscMemzero(dnz,A->rmap->n*sizeof(*dnz));CHKERRQ(ierr);
486fabe8965SStefano Zampini       ierr = PetscMemzero(onz,A->rmap->n*sizeof(*onz));CHKERRQ(ierr);
487fabe8965SStefano Zampini       for (i = 0, j = 0; i < A->rmap->n; i++) {
488fabe8965SStefano Zampini         if (ndmapi[i] < 0 && ndmapc[i] < 2) {
489fabe8965SStefano Zampini           const PetscInt* idxs;
490fabe8965SStefano Zampini           PetscInt        s;
491fabe8965SStefano Zampini 
492fabe8965SStefano Zampini           ierr = ISGetLocalSize(workis[j],&s);CHKERRQ(ierr);
493fabe8965SStefano Zampini           ierr = ISGetIndices(workis[j],&idxs);CHKERRQ(ierr);
494fabe8965SStefano Zampini           ierr = MatPreallocateSet(i+A->rmap->rstart,s,idxs,dnz,onz);CHKERRQ(ierr);
495fabe8965SStefano Zampini           j++;
496fabe8965SStefano Zampini         }
497fabe8965SStefano Zampini       }
498fabe8965SStefano Zampini       if (j != cnt) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected local count %D != %D",j,cnt);
499fabe8965SStefano Zampini 
500fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
501fabe8965SStefano Zampini         ierr = PetscObjectSetName((PetscObject)workis[i],"EXTENDED");CHKERRQ(ierr);
502fabe8965SStefano Zampini         ierr = ISViewFromOptions(workis[i],NULL,"-view_isolated_separators");CHKERRQ(ierr);
503fabe8965SStefano Zampini       }
504fabe8965SStefano Zampini 
505fabe8965SStefano Zampini       for (i = 0, j = 0; i < A->rmap->n; i++) j = PetscMax(j,dnz[i]+onz[i]);
506fabe8965SStefano Zampini       ierr = PetscMalloc1(j,&vals);CHKERRQ(ierr);
507fabe8965SStefano Zampini       for (i = 0; i < j; i++) vals[i] = 1.0;
508fabe8965SStefano Zampini 
509fabe8965SStefano Zampini       ierr = MatCreate(comm,&A2);CHKERRQ(ierr);
510fabe8965SStefano Zampini       ierr = MatSetType(A2,MATMPIAIJ);CHKERRQ(ierr);
511fabe8965SStefano Zampini       ierr = MatSetSizes(A2,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
512fabe8965SStefano Zampini       ierr = MatMPIAIJSetPreallocation(A2,0,dnz,0,onz);CHKERRQ(ierr);
513fabe8965SStefano Zampini       ierr = MatSetOption(A2,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
514fabe8965SStefano Zampini       for (i = 0, j = 0; i < A2->rmap->n; i++) {
515fabe8965SStefano Zampini         PetscInt        row = i+A2->rmap->rstart,s = dnz[i] + onz[i];
516fabe8965SStefano Zampini         const PetscInt* idxs;
517fabe8965SStefano Zampini 
518fabe8965SStefano Zampini         if (s) {
519fabe8965SStefano Zampini           ierr = ISGetIndices(workis[j],&idxs);CHKERRQ(ierr);
520fabe8965SStefano Zampini           ierr = MatSetValues(A2,1,&row,s,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
521fabe8965SStefano Zampini           ierr = ISRestoreIndices(workis[j],&idxs);CHKERRQ(ierr);
522fabe8965SStefano Zampini           j++;
523fabe8965SStefano Zampini         }
524fabe8965SStefano Zampini       }
525fabe8965SStefano Zampini       if (j != cnt) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected local count %D != %D",j,cnt);
526fabe8965SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
527fabe8965SStefano Zampini       ierr = MatAssemblyBegin(A2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
528fabe8965SStefano Zampini       ierr = MatAssemblyEnd(A2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
529fabe8965SStefano Zampini       ierr = MatTranspose(A2,MAT_INPLACE_MATRIX,&A2);CHKERRQ(ierr);
530fabe8965SStefano Zampini 
531fabe8965SStefano Zampini       /* extract submatrix corresponding to the coupling "owned separators" x "isolated separators" */
532fabe8965SStefano Zampini       for (i = 0, j = 0; i < nl; i++)
533fabe8965SStefano Zampini         if (lndmapi[i] >= 0) lndmapi[j++] = lndmapi[i];
534fabe8965SStefano Zampini       ierr = ISCreateGeneral(comm,j,lndmapi,PETSC_USE_POINTER,&is);CHKERRQ(ierr);
535fabe8965SStefano Zampini       ierr = MatMPIAIJGetLocalMatCondensed(A2,MAT_INITIAL_MATRIX,&is,NULL,&A3);CHKERRQ(ierr);
536fabe8965SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
537fabe8965SStefano Zampini       ierr = MatDestroy(&A2);CHKERRQ(ierr);
538fabe8965SStefano Zampini 
539fabe8965SStefano Zampini       /* extend local to global map to include connected isolated separators */
540fabe8965SStefano Zampini       ierr = PetscObjectQuery((PetscObject)A3,"_petsc_GetLocalMatCondensed_iscol",(PetscObject*)&is);CHKERRQ(ierr);
541fabe8965SStefano Zampini       if (!is) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing column map");
542fabe8965SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&ll2g);CHKERRQ(ierr);
543fabe8965SStefano Zampini       ierr = MatGetRowIJ(A3,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&flg);CHKERRQ(ierr);
544fabe8965SStefano Zampini       if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
545fabe8965SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,ii[i],jj,PETSC_COPY_VALUES,&is);CHKERRQ(ierr);
546fabe8965SStefano Zampini       ierr = MatRestoreRowIJ(A3,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&flg);CHKERRQ(ierr);
547fabe8965SStefano Zampini       if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
548fabe8965SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(ll2g,is,&is2);CHKERRQ(ierr);
549fabe8965SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
550fabe8965SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&ll2g);CHKERRQ(ierr);
551fabe8965SStefano Zampini 
552fabe8965SStefano Zampini       /* add new nodes to the local-to-global map */
553fabe8965SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(l2g);CHKERRQ(ierr);
554fabe8965SStefano Zampini       ierr = ISExpand(ndsub,is2,&is);CHKERRQ(ierr);
555fabe8965SStefano Zampini       ierr = ISDestroy(&is2);CHKERRQ(ierr);
556fabe8965SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,l2g);CHKERRQ(ierr);
557fabe8965SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
558fabe8965SStefano Zampini 
559fabe8965SStefano Zampini       ierr = MatDestroy(&A3);CHKERRQ(ierr);
560fabe8965SStefano Zampini       ierr = PetscFree(lndmapi);CHKERRQ(ierr);
561fabe8965SStefano Zampini       ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
562fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
563fabe8965SStefano Zampini         ierr = ISDestroy(&workis[i]);CHKERRQ(ierr);
564fabe8965SStefano Zampini       }
565fabe8965SStefano Zampini       ierr = PetscFree(workis);CHKERRQ(ierr);
566fabe8965SStefano Zampini     }
567fabe8965SStefano Zampini     ierr = ISRestoreIndices(ndmap,&ndmapi);CHKERRQ(ierr);
568fabe8965SStefano Zampini     ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
569fabe8965SStefano Zampini     ierr = PetscFree(ndmapc);CHKERRQ(ierr);
570fabe8965SStefano Zampini     ierr = ISDestroy(&ndmap);CHKERRQ(ierr);
571fabe8965SStefano Zampini     ierr = ISDestroy(&ndsub);CHKERRQ(ierr);
572fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingSetBlockSize(*l2g,bs);CHKERRQ(ierr);
573fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingViewFromOptions(*l2g,NULL,"-matis_nd_l2g_view");CHKERRQ(ierr);
574fabe8965SStefano Zampini     break;
575fabe8965SStefano Zampini   case MAT_IS_DISASSEMBLE_L2G_NATURAL:
576fabe8965SStefano Zampini     if (ismpiaij) {
577fabe8965SStefano Zampini       ierr = MatMPIAIJGetSeqAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
578fabe8965SStefano Zampini     } else if (ismpibaij) {
579fabe8965SStefano Zampini       ierr = MatMPIBAIJGetSeqBAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
580c9225affSStefano Zampini     } else SETERRQ1(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name);
581c9225affSStefano Zampini     if (!garray) SETERRQ(comm,PETSC_ERR_ARG_WRONGSTATE,"garray not present");
582c9225affSStefano Zampini     if (A->rmap->n) {
583fabe8965SStefano Zampini       PetscInt dc,oc,stc,*aux;
584c9225affSStefano Zampini 
585c9225affSStefano Zampini       ierr = MatGetLocalSize(A,NULL,&dc);CHKERRQ(ierr);
586c9225affSStefano Zampini       ierr = MatGetLocalSize(Ao,NULL,&oc);CHKERRQ(ierr);
587c9225affSStefano Zampini       ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr);
588c9225affSStefano Zampini       ierr = PetscMalloc1((dc+oc)/bs,&aux);CHKERRQ(ierr);
589c9225affSStefano Zampini       for (i=0; i<dc/bs; i++) aux[i]       = i+stc/bs;
590c9225affSStefano Zampini       for (i=0; i<oc/bs; i++) aux[i+dc/bs] = garray[i];
591c9225affSStefano Zampini       ierr = ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
592c9225affSStefano Zampini     } else {
593c9225affSStefano Zampini       ierr = ISCreateBlock(comm,1,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
594c9225affSStefano Zampini     }
595c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,l2g);CHKERRQ(ierr);
596c9225affSStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
597fabe8965SStefano Zampini     break;
598fabe8965SStefano Zampini   default:
599fabe8965SStefano Zampini     SETERRQ1(comm,PETSC_ERR_ARG_WRONG,"Unsupported l2g disassembling type %D",mode);
600c9225affSStefano Zampini   }
601c9225affSStefano Zampini   PetscFunctionReturn(0);
602c9225affSStefano Zampini }
603c9225affSStefano Zampini 
604c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
605c9225affSStefano Zampini {
606c9225affSStefano Zampini   Mat                    lA,Ad,Ao,B = NULL;
6076989cf23SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
6086989cf23SStefano Zampini   IS                     is;
6096989cf23SStefano Zampini   MPI_Comm               comm;
6106989cf23SStefano Zampini   void                   *ptrs[2];
6116989cf23SStefano Zampini   const char             *names[2] = {"_convert_csr_aux","_convert_csr_data"};
612c9225affSStefano Zampini   const PetscInt         *garray;
6136989cf23SStefano Zampini   PetscScalar            *dd,*od,*aa,*data;
614c9225affSStefano Zampini   const PetscInt         *di,*dj,*oi,*oj;
615c9225affSStefano Zampini   const PetscInt         *odi,*odj,*ooi,*ooj;
6166989cf23SStefano Zampini   PetscInt               *aux,*ii,*jj;
617c9225affSStefano Zampini   PetscInt               bs,lc,dr,dc,oc,str,stc,nnz,i,jd,jo,cum;
618c9225affSStefano Zampini   PetscBool              flg,ismpiaij,ismpibaij,was_inplace = PETSC_FALSE;
619c9225affSStefano Zampini   PetscMPIInt            size;
6206989cf23SStefano Zampini   PetscErrorCode         ierr;
6216989cf23SStefano Zampini 
622ab4d48faSStefano Zampini   PetscFunctionBegin;
6236989cf23SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
624c9225affSStefano Zampini   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
625c9225affSStefano Zampini   if (size == 1) {
626c9225affSStefano Zampini     ierr = MatConvert_SeqXAIJ_IS(A,type,reuse,newmat);CHKERRQ(ierr);
627c9225affSStefano Zampini     PetscFunctionReturn(0);
628c9225affSStefano Zampini   }
629c9225affSStefano Zampini   if (reuse != MAT_REUSE_MATRIX && A->cmap->N == A->rmap->N) {
630c9225affSStefano Zampini     ierr = MatMPIXAIJComputeLocalToGlobalMapping_Private(A,&rl2g);CHKERRQ(ierr);
631c9225affSStefano Zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
632c9225affSStefano Zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
633c9225affSStefano Zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
634c9225affSStefano Zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,rl2g);CHKERRQ(ierr);
635c9225affSStefano Zampini     ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
636c9225affSStefano Zampini     ierr = MatSetBlockSize(B,bs);CHKERRQ(ierr);
637c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
638c9225affSStefano Zampini     if (reuse == MAT_INPLACE_MATRIX) was_inplace = PETSC_TRUE;
639c9225affSStefano Zampini     reuse = MAT_REUSE_MATRIX;
640c9225affSStefano Zampini   }
641c9225affSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
642c9225affSStefano Zampini     Mat            *newlA, lA;
643c9225affSStefano Zampini     IS             rows, cols;
644c9225affSStefano Zampini     const PetscInt *ridx, *cidx;
645c9225affSStefano Zampini     PetscInt       rbs, cbs, nr, nc;
646c9225affSStefano Zampini 
647c9225affSStefano Zampini     if (!B) B = *newmat;
648c9225affSStefano Zampini     ierr = MatGetLocalToGlobalMapping(B,&rl2g,&cl2g);CHKERRQ(ierr);
649c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockIndices(rl2g,&ridx);CHKERRQ(ierr);
650c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockIndices(cl2g,&cidx);CHKERRQ(ierr);
651c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(rl2g,&nr);CHKERRQ(ierr);
652c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(cl2g,&nc);CHKERRQ(ierr);
653c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(rl2g,&rbs);CHKERRQ(ierr);
654c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(cl2g,&cbs);CHKERRQ(ierr);
655c9225affSStefano Zampini     ierr = ISCreateBlock(comm,rbs,nr/rbs,ridx,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
656c9225affSStefano Zampini     if (rl2g != cl2g) {
657c9225affSStefano Zampini       ierr = ISCreateBlock(comm,cbs,nc/cbs,cidx,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
658c9225affSStefano Zampini     } else {
659c9225affSStefano Zampini       ierr = PetscObjectReference((PetscObject)rows);CHKERRQ(ierr);
660c9225affSStefano Zampini       cols = rows;
661c9225affSStefano Zampini     }
662c9225affSStefano Zampini     ierr = MatISGetLocalMat(B,&lA);CHKERRQ(ierr);
663c9225affSStefano Zampini     ierr = MatCreateSubMatrices(A,1,&rows,&cols,MAT_INITIAL_MATRIX,&newlA);CHKERRQ(ierr);
664c9225affSStefano Zampini     ierr = MatConvert(newlA[0],MATSEQAIJ,MAT_INPLACE_MATRIX,&newlA[0]);CHKERRQ(ierr);
665c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreBlockIndices(rl2g,&ridx);CHKERRQ(ierr);
666c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreBlockIndices(cl2g,&cidx);CHKERRQ(ierr);
667c9225affSStefano Zampini     ierr = ISDestroy(&rows);CHKERRQ(ierr);
668c9225affSStefano Zampini     ierr = ISDestroy(&cols);CHKERRQ(ierr);
669c9225affSStefano Zampini     if (!lA->preallocated) { /* first time */
670c9225affSStefano Zampini       ierr = MatDuplicate(newlA[0],MAT_COPY_VALUES,&lA);CHKERRQ(ierr);
671c9225affSStefano Zampini       ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
672c9225affSStefano Zampini       ierr = PetscObjectDereference((PetscObject)lA);CHKERRQ(ierr);
673c9225affSStefano Zampini     }
674c9225affSStefano Zampini     ierr = MatCopy(newlA[0],lA,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
675c9225affSStefano Zampini     ierr = MatDestroySubMatrices(1,&newlA);CHKERRQ(ierr);
676c9225affSStefano Zampini     ierr = MatISScaleDisassembling_Private(B);CHKERRQ(ierr);
677c9225affSStefano Zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
678c9225affSStefano Zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
679c9225affSStefano Zampini     if (was_inplace) { ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr); }
680c9225affSStefano Zampini     else *newmat = B;
681c9225affSStefano Zampini     PetscFunctionReturn(0);
682c9225affSStefano Zampini   }
683c9225affSStefano Zampini   /* rectangular case, just compress out the column space */
684c9225affSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij);CHKERRQ(ierr);
685c9225affSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr);
686c9225affSStefano Zampini   if (ismpiaij) {
687c9225affSStefano Zampini     bs   = 1;
688c9225affSStefano Zampini     ierr = MatMPIAIJGetSeqAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
689c9225affSStefano Zampini   } else if (ismpibaij) {
690c9225affSStefano Zampini     ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
691c9225affSStefano Zampini     ierr = MatMPIBAIJGetSeqBAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
692c9225affSStefano Zampini     ierr = MatConvert(Ad,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ad);CHKERRQ(ierr);
693c9225affSStefano Zampini     ierr = MatConvert(Ao,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ao);CHKERRQ(ierr);
694c9225affSStefano Zampini   } else SETERRQ1(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name);
695c9225affSStefano Zampini   ierr = MatSeqAIJGetArray(Ad,&dd);CHKERRQ(ierr);
696c9225affSStefano Zampini   ierr = MatSeqAIJGetArray(Ao,&od);CHKERRQ(ierr);
697c9225affSStefano Zampini   if (!garray) SETERRQ(comm,PETSC_ERR_ARG_WRONGSTATE,"garray not present");
6986989cf23SStefano Zampini 
6996989cf23SStefano Zampini   /* access relevant information from MPIAIJ */
7006989cf23SStefano Zampini   ierr = MatGetOwnershipRange(A,&str,NULL);CHKERRQ(ierr);
7016989cf23SStefano Zampini   ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr);
7026989cf23SStefano Zampini   ierr = MatGetLocalSize(A,&dr,&dc);CHKERRQ(ierr);
703c9225affSStefano Zampini   ierr = MatGetLocalSize(Ao,NULL,&oc);CHKERRQ(ierr);
704c9225affSStefano Zampini   ierr = MatGetRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&di,&dj,&flg);CHKERRQ(ierr);
705c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
706c9225affSStefano Zampini   ierr = MatGetRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&oi,&oj,&flg);CHKERRQ(ierr);
707c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
708c9225affSStefano Zampini   nnz = di[dr] + oi[dr];
709c9225affSStefano Zampini   /* store original pointers to be restored later */
710c9225affSStefano Zampini   odi = di; odj = dj; ooi = oi; ooj = oj;
7116989cf23SStefano Zampini 
7126989cf23SStefano Zampini   /* generate l2g maps for rows and cols */
713c9225affSStefano Zampini   ierr = ISCreateStride(comm,dr/bs,str/bs,1,&is);CHKERRQ(ierr);
714c9225affSStefano Zampini   if (bs > 1) {
715c9225affSStefano Zampini     IS is2;
716c9225affSStefano Zampini 
717c9225affSStefano Zampini     ierr = ISGetLocalSize(is,&i);CHKERRQ(ierr);
718c9225affSStefano Zampini     ierr = ISGetIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
719c9225affSStefano Zampini     ierr = ISCreateBlock(comm,bs,i,aux,PETSC_COPY_VALUES,&is2);CHKERRQ(ierr);
720c9225affSStefano Zampini     ierr = ISRestoreIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
721c9225affSStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
722c9225affSStefano Zampini     is   = is2;
723c9225affSStefano Zampini   }
7246989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
7256989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
726e363d98aSStefano Zampini   if (dr) {
727c9225affSStefano Zampini     ierr = PetscMalloc1((dc+oc)/bs,&aux);CHKERRQ(ierr);
728c9225affSStefano Zampini     for (i=0; i<dc/bs; i++) aux[i]       = i+stc/bs;
729c9225affSStefano Zampini     for (i=0; i<oc/bs; i++) aux[i+dc/bs] = garray[i];
730c9225affSStefano Zampini     ierr = ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
731e363d98aSStefano Zampini     lc   = dc+oc;
732e363d98aSStefano Zampini   } else {
733c9225affSStefano Zampini     ierr = ISCreateBlock(comm,bs,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
734e363d98aSStefano Zampini     lc   = 0;
735e363d98aSStefano Zampini   }
7366989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
7376989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
7386989cf23SStefano Zampini 
7396989cf23SStefano Zampini   /* create MATIS object */
740c9225affSStefano Zampini   ierr = MatCreate(comm,&B);CHKERRQ(ierr);
741c9225affSStefano Zampini   ierr = MatSetSizes(B,dr,dc,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
742c9225affSStefano Zampini   ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
743c9225affSStefano Zampini   ierr = MatSetBlockSize(B,bs);CHKERRQ(ierr);
744c9225affSStefano Zampini   ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
7456989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
7466989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
7476989cf23SStefano Zampini 
7486989cf23SStefano Zampini   /* merge local matrices */
7496989cf23SStefano Zampini   ierr = PetscMalloc1(nnz+dr+1,&aux);CHKERRQ(ierr);
7506989cf23SStefano Zampini   ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr);
7516989cf23SStefano Zampini   ii   = aux;
7526989cf23SStefano Zampini   jj   = aux+dr+1;
7536989cf23SStefano Zampini   aa   = data;
7546989cf23SStefano Zampini   *ii  = *(di++) + *(oi++);
7556989cf23SStefano Zampini   for (jd=0,jo=0,cum=0;*ii<nnz;cum++)
7566989cf23SStefano Zampini   {
7576989cf23SStefano Zampini      for (;jd<*di;jd++) { *jj++ = *dj++;      *aa++ = *dd++; }
7586989cf23SStefano Zampini      for (;jo<*oi;jo++) { *jj++ = *oj++ + dc; *aa++ = *od++; }
7596989cf23SStefano Zampini      *(++ii) = *(di++) + *(oi++);
7606989cf23SStefano Zampini   }
7616989cf23SStefano Zampini   for (;cum<dr;cum++) *(++ii) = nnz;
762c9225affSStefano Zampini 
763c9225affSStefano Zampini   ierr = MatRestoreRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&odi,&odj,&flg);CHKERRQ(ierr);
764c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
765c9225affSStefano Zampini   ierr = MatRestoreRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&ooi,&ooj,&flg);CHKERRQ(ierr);
766c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
767c9225affSStefano Zampini   ierr = MatSeqAIJRestoreArray(Ad,&dd);CHKERRQ(ierr);
768c9225affSStefano Zampini   ierr = MatSeqAIJRestoreArray(Ao,&od);CHKERRQ(ierr);
769c9225affSStefano Zampini 
7706989cf23SStefano Zampini   ii   = aux;
7716989cf23SStefano Zampini   jj   = aux+dr+1;
7726989cf23SStefano Zampini   aa   = data;
773e363d98aSStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,lc,ii,jj,aa,&lA);CHKERRQ(ierr);
7746989cf23SStefano Zampini 
7756989cf23SStefano Zampini   /* create containers to destroy the data */
7766989cf23SStefano Zampini   ptrs[0] = aux;
7776989cf23SStefano Zampini   ptrs[1] = data;
7786989cf23SStefano Zampini   for (i=0; i<2; i++) {
7796989cf23SStefano Zampini     PetscContainer c;
7806989cf23SStefano Zampini 
7816989cf23SStefano Zampini     ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr);
7826989cf23SStefano Zampini     ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr);
783b81c21eeSStefano Zampini     ierr = PetscContainerSetUserDestroy(c,PetscContainerUserDestroyDefault);CHKERRQ(ierr);
7846989cf23SStefano Zampini     ierr = PetscObjectCompose((PetscObject)lA,names[i],(PetscObject)c);CHKERRQ(ierr);
7856989cf23SStefano Zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
7866989cf23SStefano Zampini   }
787c9225affSStefano Zampini   if (ismpibaij) { /* destroy converted local matrices */
788c9225affSStefano Zampini     ierr = MatDestroy(&Ad);CHKERRQ(ierr);
789c9225affSStefano Zampini     ierr = MatDestroy(&Ao);CHKERRQ(ierr);
790c9225affSStefano Zampini   }
7916989cf23SStefano Zampini 
7926989cf23SStefano Zampini   /* finalize matrix */
793c9225affSStefano Zampini   ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
7946989cf23SStefano Zampini   ierr = MatDestroy(&lA);CHKERRQ(ierr);
795c9225affSStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
796c9225affSStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
797c9225affSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
798c9225affSStefano Zampini     ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
799c9225affSStefano Zampini   } else *newmat = B;
8006989cf23SStefano Zampini   PetscFunctionReturn(0);
8016989cf23SStefano Zampini }
8026989cf23SStefano Zampini 
8035e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
8045e3038f0Sstefano_zampini {
8055e3038f0Sstefano_zampini   Mat                    **nest,*snest,**rnest,lA,B;
8065e3038f0Sstefano_zampini   IS                     *iscol,*isrow,*islrow,*islcol;
8075e3038f0Sstefano_zampini   ISLocalToGlobalMapping rl2g,cl2g;
8085e3038f0Sstefano_zampini   MPI_Comm               comm;
8095b003df0Sstefano_zampini   PetscInt               *lr,*lc,*l2gidxs;
8105b003df0Sstefano_zampini   PetscInt               i,j,nr,nc,rbs,cbs;
8119e7b2b25Sstefano_zampini   PetscBool              convert,lreuse,*istrans;
8125e3038f0Sstefano_zampini   PetscErrorCode         ierr;
8135e3038f0Sstefano_zampini 
814ab4d48faSStefano Zampini   PetscFunctionBegin;
8155e3038f0Sstefano_zampini   ierr   = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr);
8165e3038f0Sstefano_zampini   lreuse = PETSC_FALSE;
8175e3038f0Sstefano_zampini   rnest  = NULL;
8185e3038f0Sstefano_zampini   if (reuse == MAT_REUSE_MATRIX) {
8195e3038f0Sstefano_zampini     PetscBool ismatis,isnest;
8205e3038f0Sstefano_zampini 
8215e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
8225e3038f0Sstefano_zampini     if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type);
8235e3038f0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
8245e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr);
8255e3038f0Sstefano_zampini     if (isnest) {
8265e3038f0Sstefano_zampini       ierr   = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr);
8275e3038f0Sstefano_zampini       lreuse = (PetscBool)(i == nr && j == nc);
8285e3038f0Sstefano_zampini       if (!lreuse) rnest = NULL;
8295e3038f0Sstefano_zampini     }
8305e3038f0Sstefano_zampini   }
8315e3038f0Sstefano_zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
8325b003df0Sstefano_zampini   ierr = PetscCalloc2(nr,&lr,nc,&lc);CHKERRQ(ierr);
8339e7b2b25Sstefano_zampini   ierr = PetscCalloc6(nr,&isrow,nc,&iscol,
8345e3038f0Sstefano_zampini                       nr,&islrow,nc,&islcol,
8359e7b2b25Sstefano_zampini                       nr*nc,&snest,nr*nc,&istrans);CHKERRQ(ierr);
8365e3038f0Sstefano_zampini   ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr);
8375e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
8385e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
8395e3038f0Sstefano_zampini       PetscBool ismatis;
8409e7b2b25Sstefano_zampini       PetscInt  l1,l2,lb1,lb2,ij=i*nc+j;
8415e3038f0Sstefano_zampini 
8425e3038f0Sstefano_zampini       /* Null matrix pointers are allowed in MATNEST */
8435e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
8445e3038f0Sstefano_zampini 
8455e3038f0Sstefano_zampini       /* Nested matrices should be of type MATIS */
8469e7b2b25Sstefano_zampini       ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij]);CHKERRQ(ierr);
8479e7b2b25Sstefano_zampini       if (istrans[ij]) {
8489e7b2b25Sstefano_zampini         Mat T,lT;
8499e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
8509e7b2b25Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis);CHKERRQ(ierr);
8519e7b2b25Sstefano_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);
8529e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(T,&lT);CHKERRQ(ierr);
8539e7b2b25Sstefano_zampini         ierr = MatCreateTranspose(lT,&snest[ij]);CHKERRQ(ierr);
8549e7b2b25Sstefano_zampini       } else {
8555e3038f0Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr);
8565e3038f0Sstefano_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);
8579e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr);
8589e7b2b25Sstefano_zampini       }
8595e3038f0Sstefano_zampini 
8605e3038f0Sstefano_zampini       /* Check compatibility of local sizes */
8615e3038f0Sstefano_zampini       ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr);
8629e7b2b25Sstefano_zampini       ierr = MatGetBlockSizes(snest[ij],&lb1,&lb2);CHKERRQ(ierr);
8635e3038f0Sstefano_zampini       if (!l1 || !l2) continue;
8645e3038f0Sstefano_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);
8655e3038f0Sstefano_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);
8665e3038f0Sstefano_zampini       lr[i] = l1;
8675e3038f0Sstefano_zampini       lc[j] = l2;
8685e3038f0Sstefano_zampini 
8695e3038f0Sstefano_zampini       /* check compatibilty for local matrix reusage */
8705e3038f0Sstefano_zampini       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
8715e3038f0Sstefano_zampini     }
8725e3038f0Sstefano_zampini   }
8735e3038f0Sstefano_zampini 
8745e3038f0Sstefano_zampini #if defined (PETSC_USE_DEBUG)
8755e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for rows */
8765e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
8775e3038f0Sstefano_zampini     rl2g = NULL;
8785e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
8795e3038f0Sstefano_zampini       PetscInt n1,n2;
8805e3038f0Sstefano_zampini 
8815e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
8829e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
8839e7b2b25Sstefano_zampini         Mat T;
8849e7b2b25Sstefano_zampini 
8859e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
8869e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,NULL,&cl2g);CHKERRQ(ierr);
8879e7b2b25Sstefano_zampini       } else {
8885e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr);
8899e7b2b25Sstefano_zampini       }
8905e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
8915e3038f0Sstefano_zampini       if (!n1) continue;
8925e3038f0Sstefano_zampini       if (!rl2g) {
8935e3038f0Sstefano_zampini         rl2g = cl2g;
8945e3038f0Sstefano_zampini       } else {
8955e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
8965e3038f0Sstefano_zampini         PetscBool      same;
8975e3038f0Sstefano_zampini 
8985e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
8995e3038f0Sstefano_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);
9005e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
9015e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
9025e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
9035e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
9045e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
9055e3038f0Sstefano_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);
9065e3038f0Sstefano_zampini       }
9075e3038f0Sstefano_zampini     }
9085e3038f0Sstefano_zampini   }
9095e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for columns */
9105e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
9115e3038f0Sstefano_zampini     rl2g = NULL;
9125e3038f0Sstefano_zampini     for (j=0;j<nr;j++) {
9135e3038f0Sstefano_zampini       PetscInt n1,n2;
9145e3038f0Sstefano_zampini 
9155e3038f0Sstefano_zampini       if (!nest[j][i]) continue;
9169e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
9179e7b2b25Sstefano_zampini         Mat T;
9189e7b2b25Sstefano_zampini 
9199e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[j][i],&T);CHKERRQ(ierr);
9209e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,&cl2g,NULL);CHKERRQ(ierr);
9219e7b2b25Sstefano_zampini       } else {
9225e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr);
9239e7b2b25Sstefano_zampini       }
9245e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
9255e3038f0Sstefano_zampini       if (!n1) continue;
9265e3038f0Sstefano_zampini       if (!rl2g) {
9275e3038f0Sstefano_zampini         rl2g = cl2g;
9285e3038f0Sstefano_zampini       } else {
9295e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
9305e3038f0Sstefano_zampini         PetscBool      same;
9315e3038f0Sstefano_zampini 
9325e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
9335e3038f0Sstefano_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);
9345e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
9355e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
9365e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
9375e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
9385e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
9395e3038f0Sstefano_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);
9405e3038f0Sstefano_zampini       }
9415e3038f0Sstefano_zampini     }
9425e3038f0Sstefano_zampini   }
9435e3038f0Sstefano_zampini #endif
9445e3038f0Sstefano_zampini 
9455e3038f0Sstefano_zampini   B = NULL;
9465e3038f0Sstefano_zampini   if (reuse != MAT_REUSE_MATRIX) {
9475b003df0Sstefano_zampini     PetscInt stl;
9485b003df0Sstefano_zampini 
9495e3038f0Sstefano_zampini     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
9505e3038f0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) stl += lr[i];
9515e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
9525b003df0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) {
9535e3038f0Sstefano_zampini       Mat            usedmat;
9545e3038f0Sstefano_zampini       Mat_IS         *matis;
9555e3038f0Sstefano_zampini       const PetscInt *idxs;
9565e3038f0Sstefano_zampini 
9575e3038f0Sstefano_zampini       /* local IS for local NEST */
9585b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
9595e3038f0Sstefano_zampini 
9605e3038f0Sstefano_zampini       /* l2gmap */
9615e3038f0Sstefano_zampini       j = 0;
9625e3038f0Sstefano_zampini       usedmat = nest[i][j];
9639e7b2b25Sstefano_zampini       while (!usedmat && j < nc-1) usedmat = nest[i][++j];
9649e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid row mat");
9659e7b2b25Sstefano_zampini 
9669e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
9679e7b2b25Sstefano_zampini         Mat T;
9689e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
9699e7b2b25Sstefano_zampini         usedmat = T;
9709e7b2b25Sstefano_zampini       }
9715e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
9725e3038f0Sstefano_zampini       ierr  = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr);
9739e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
9749e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
9759e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
9769e7b2b25Sstefano_zampini       } else {
9775e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
9785e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
9799e7b2b25Sstefano_zampini       }
9805e3038f0Sstefano_zampini       ierr = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr);
9815e3038f0Sstefano_zampini       stl += lr[i];
9825e3038f0Sstefano_zampini     }
9835e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr);
9845e3038f0Sstefano_zampini 
9855e3038f0Sstefano_zampini     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
9865e3038f0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) stl += lc[i];
9875e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
9885b003df0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) {
9895e3038f0Sstefano_zampini       Mat            usedmat;
9905e3038f0Sstefano_zampini       Mat_IS         *matis;
9915e3038f0Sstefano_zampini       const PetscInt *idxs;
9925e3038f0Sstefano_zampini 
9935e3038f0Sstefano_zampini       /* local IS for local NEST */
9945b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
9955e3038f0Sstefano_zampini 
9965e3038f0Sstefano_zampini       /* l2gmap */
9975e3038f0Sstefano_zampini       j = 0;
9985e3038f0Sstefano_zampini       usedmat = nest[j][i];
9999e7b2b25Sstefano_zampini       while (!usedmat && j < nr-1) usedmat = nest[++j][i];
10009e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid column mat");
10019e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
10029e7b2b25Sstefano_zampini         Mat T;
10039e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
10049e7b2b25Sstefano_zampini         usedmat = T;
10059e7b2b25Sstefano_zampini       }
10065e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
10075e3038f0Sstefano_zampini       ierr  = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr);
10089e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
10099e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
10109e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
10119e7b2b25Sstefano_zampini       } else {
10125e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
10135e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
10149e7b2b25Sstefano_zampini       }
10155e3038f0Sstefano_zampini       ierr = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr);
10165e3038f0Sstefano_zampini       stl += lc[i];
10175e3038f0Sstefano_zampini     }
10185e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr);
10195e3038f0Sstefano_zampini 
10205e3038f0Sstefano_zampini     /* Create MATIS */
10215e3038f0Sstefano_zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
10225e3038f0Sstefano_zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
10235e3038f0Sstefano_zampini     ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr);
10245e3038f0Sstefano_zampini     ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr);
10255e3038f0Sstefano_zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
10268546b261SStefano Zampini     ierr = MatISSetLocalMatType(B,MATNEST);CHKERRQ(ierr);
10278546b261SStefano Zampini     { /* hack : avoid setup of scatters */
10288546b261SStefano Zampini       Mat_IS *matis = (Mat_IS*)(B->data);
10298546b261SStefano Zampini       matis->islocalref = PETSC_TRUE;
10308546b261SStefano Zampini     }
10315e3038f0Sstefano_zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
10325e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
10335e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
10345e3038f0Sstefano_zampini     ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
10358546b261SStefano Zampini     ierr = MatNestSetVecType(lA,VECNEST);CHKERRQ(ierr);
10369e7b2b25Sstefano_zampini     for (i=0;i<nr*nc;i++) {
10379e7b2b25Sstefano_zampini       if (istrans[i]) {
10389e7b2b25Sstefano_zampini         ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
10399e7b2b25Sstefano_zampini       }
10409e7b2b25Sstefano_zampini     }
10415e3038f0Sstefano_zampini     ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
10425e3038f0Sstefano_zampini     ierr = MatDestroy(&lA);CHKERRQ(ierr);
10438546b261SStefano Zampini     { /* hack : setup of scatters done here */
10448546b261SStefano Zampini       Mat_IS *matis = (Mat_IS*)(B->data);
10458546b261SStefano Zampini 
10468546b261SStefano Zampini       matis->islocalref = PETSC_FALSE;
10478546b261SStefano Zampini       ierr = MatISSetUpScatters_Private(B);CHKERRQ(ierr);
10488546b261SStefano Zampini     }
10495e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10505e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10515e3038f0Sstefano_zampini     if (reuse == MAT_INPLACE_MATRIX) {
10525e3038f0Sstefano_zampini       ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
10535e3038f0Sstefano_zampini     } else {
10545e3038f0Sstefano_zampini       *newmat = B;
10555e3038f0Sstefano_zampini     }
10565e3038f0Sstefano_zampini   } else {
10575e3038f0Sstefano_zampini     if (lreuse) {
10585e3038f0Sstefano_zampini       ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
10595e3038f0Sstefano_zampini       for (i=0;i<nr;i++) {
10605e3038f0Sstefano_zampini         for (j=0;j<nc;j++) {
10615e3038f0Sstefano_zampini           if (snest[i*nc+j]) {
10625e3038f0Sstefano_zampini             ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr);
10639e7b2b25Sstefano_zampini             if (istrans[i*nc+j]) {
10649e7b2b25Sstefano_zampini               ierr = MatDestroy(&snest[i*nc+j]);CHKERRQ(ierr);
10659e7b2b25Sstefano_zampini             }
10665e3038f0Sstefano_zampini           }
10675e3038f0Sstefano_zampini         }
10685e3038f0Sstefano_zampini       }
10695e3038f0Sstefano_zampini     } else {
10705b003df0Sstefano_zampini       PetscInt stl;
10715b003df0Sstefano_zampini       for (i=0,stl=0;i<nr;i++) {
10725b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
10735b003df0Sstefano_zampini         stl  += lr[i];
10745e3038f0Sstefano_zampini       }
10755b003df0Sstefano_zampini       for (i=0,stl=0;i<nc;i++) {
10765b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
10775b003df0Sstefano_zampini         stl  += lc[i];
10785e3038f0Sstefano_zampini       }
10795e3038f0Sstefano_zampini       ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
1080ab4d48faSStefano Zampini       for (i=0;i<nr*nc;i++) {
10819e7b2b25Sstefano_zampini         if (istrans[i]) {
10829e7b2b25Sstefano_zampini           ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
10839e7b2b25Sstefano_zampini         }
1084ab4d48faSStefano Zampini       }
10855e3038f0Sstefano_zampini       ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
10865e3038f0Sstefano_zampini       ierr = MatDestroy(&lA);CHKERRQ(ierr);
10875e3038f0Sstefano_zampini     }
10885e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10895e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10905e3038f0Sstefano_zampini   }
10915e3038f0Sstefano_zampini 
10925b003df0Sstefano_zampini   /* Create local matrix in MATNEST format */
10935b003df0Sstefano_zampini   convert = PETSC_FALSE;
10945b003df0Sstefano_zampini   ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr);
10955b003df0Sstefano_zampini   if (convert) {
10965b003df0Sstefano_zampini     Mat              M;
10975b003df0Sstefano_zampini     MatISLocalFields lf;
10985b003df0Sstefano_zampini     PetscContainer   c;
10995b003df0Sstefano_zampini 
11005b003df0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
11015b003df0Sstefano_zampini     ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr);
11025b003df0Sstefano_zampini     ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr);
11035b003df0Sstefano_zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
11045b003df0Sstefano_zampini 
11055b003df0Sstefano_zampini     /* attach local fields to the matrix */
11065b003df0Sstefano_zampini     ierr = PetscNew(&lf);CHKERRQ(ierr);
11075b003df0Sstefano_zampini     ierr = PetscCalloc2(nr,&lf->rf,nc,&lf->cf);CHKERRQ(ierr);
11085b003df0Sstefano_zampini     for (i=0;i<nr;i++) {
11095b003df0Sstefano_zampini       PetscInt n,st;
11105b003df0Sstefano_zampini 
11115b003df0Sstefano_zampini       ierr = ISGetLocalSize(islrow[i],&n);CHKERRQ(ierr);
11125b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islrow[i],&st,NULL);CHKERRQ(ierr);
11135b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->rf[i]);CHKERRQ(ierr);
11145b003df0Sstefano_zampini     }
11155b003df0Sstefano_zampini     for (i=0;i<nc;i++) {
11165b003df0Sstefano_zampini       PetscInt n,st;
11175b003df0Sstefano_zampini 
11185b003df0Sstefano_zampini       ierr = ISGetLocalSize(islcol[i],&n);CHKERRQ(ierr);
11195b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islcol[i],&st,NULL);CHKERRQ(ierr);
11205b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->cf[i]);CHKERRQ(ierr);
11215b003df0Sstefano_zampini     }
11225b003df0Sstefano_zampini     lf->nr = nr;
11235b003df0Sstefano_zampini     lf->nc = nc;
11245b003df0Sstefano_zampini     ierr = PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c);CHKERRQ(ierr);
11255b003df0Sstefano_zampini     ierr = PetscContainerSetPointer(c,lf);CHKERRQ(ierr);
11265b003df0Sstefano_zampini     ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private);CHKERRQ(ierr);
11275b003df0Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c);CHKERRQ(ierr);
11285b003df0Sstefano_zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
11295b003df0Sstefano_zampini   }
11305b003df0Sstefano_zampini 
11315e3038f0Sstefano_zampini   /* Free workspace */
11325e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
11335e3038f0Sstefano_zampini     ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr);
11345e3038f0Sstefano_zampini   }
11355e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
11365e3038f0Sstefano_zampini     ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr);
11375e3038f0Sstefano_zampini   }
11389e7b2b25Sstefano_zampini   ierr = PetscFree6(isrow,iscol,islrow,islcol,snest,istrans);CHKERRQ(ierr);
11395b003df0Sstefano_zampini   ierr = PetscFree2(lr,lc);CHKERRQ(ierr);
11405e3038f0Sstefano_zampini   PetscFunctionReturn(0);
11415e3038f0Sstefano_zampini }
11425e3038f0Sstefano_zampini 
1143ad219c80Sstefano_zampini static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r)
1144ad219c80Sstefano_zampini {
1145ad219c80Sstefano_zampini   Mat_IS            *matis = (Mat_IS*)A->data;
1146ad219c80Sstefano_zampini   Vec               ll,rr;
1147ad219c80Sstefano_zampini   const PetscScalar *Y,*X;
1148ad219c80Sstefano_zampini   PetscScalar       *x,*y;
1149ad219c80Sstefano_zampini   PetscErrorCode    ierr;
1150ad219c80Sstefano_zampini 
1151ad219c80Sstefano_zampini   PetscFunctionBegin;
1152ad219c80Sstefano_zampini   if (l) {
1153ad219c80Sstefano_zampini     ll   = matis->y;
1154ad219c80Sstefano_zampini     ierr = VecGetArrayRead(l,&Y);CHKERRQ(ierr);
1155ad219c80Sstefano_zampini     ierr = VecGetArray(ll,&y);CHKERRQ(ierr);
1156ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
1157ad219c80Sstefano_zampini   } else {
1158ad219c80Sstefano_zampini     ll = NULL;
1159ad219c80Sstefano_zampini   }
1160ad219c80Sstefano_zampini   if (r) {
1161ad219c80Sstefano_zampini     rr   = matis->x;
1162ad219c80Sstefano_zampini     ierr = VecGetArrayRead(r,&X);CHKERRQ(ierr);
1163ad219c80Sstefano_zampini     ierr = VecGetArray(rr,&x);CHKERRQ(ierr);
1164ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
1165ad219c80Sstefano_zampini   } else {
1166ad219c80Sstefano_zampini     rr = NULL;
1167ad219c80Sstefano_zampini   }
1168ad219c80Sstefano_zampini   if (ll) {
1169ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
1170ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(l,&Y);CHKERRQ(ierr);
1171ad219c80Sstefano_zampini     ierr = VecRestoreArray(ll,&y);CHKERRQ(ierr);
1172ad219c80Sstefano_zampini   }
1173ad219c80Sstefano_zampini   if (rr) {
1174ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
1175ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(r,&X);CHKERRQ(ierr);
1176ad219c80Sstefano_zampini     ierr = VecRestoreArray(rr,&x);CHKERRQ(ierr);
1177ad219c80Sstefano_zampini   }
1178ad219c80Sstefano_zampini   ierr = MatDiagonalScale(matis->A,ll,rr);CHKERRQ(ierr);
1179ad219c80Sstefano_zampini   PetscFunctionReturn(0);
1180ad219c80Sstefano_zampini }
1181ad219c80Sstefano_zampini 
11827fa8f2d3SStefano Zampini static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo)
11837fa8f2d3SStefano Zampini {
11847fa8f2d3SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
11857fa8f2d3SStefano Zampini   MatInfo        info;
1186314ce898Sstefano_zampini   PetscReal      isend[6],irecv[6];
11877fa8f2d3SStefano Zampini   PetscInt       bs;
11887fa8f2d3SStefano Zampini   PetscErrorCode ierr;
11897fa8f2d3SStefano Zampini 
11907fa8f2d3SStefano Zampini   PetscFunctionBegin;
11917fa8f2d3SStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
1192a2ccb5f9Sstefano_zampini   if (matis->A->ops->getinfo) {
11937fa8f2d3SStefano Zampini     ierr     = MatGetInfo(matis->A,MAT_LOCAL,&info);CHKERRQ(ierr);
11947fa8f2d3SStefano Zampini     isend[0] = info.nz_used;
11957fa8f2d3SStefano Zampini     isend[1] = info.nz_allocated;
11967fa8f2d3SStefano Zampini     isend[2] = info.nz_unneeded;
11977fa8f2d3SStefano Zampini     isend[3] = info.memory;
11987fa8f2d3SStefano Zampini     isend[4] = info.mallocs;
1199a2ccb5f9Sstefano_zampini   } else {
1200a2ccb5f9Sstefano_zampini     isend[0] = 0.;
1201a2ccb5f9Sstefano_zampini     isend[1] = 0.;
1202a2ccb5f9Sstefano_zampini     isend[2] = 0.;
1203a2ccb5f9Sstefano_zampini     isend[3] = 0.;
1204a2ccb5f9Sstefano_zampini     isend[4] = 0.;
1205a2ccb5f9Sstefano_zampini   }
1206314ce898Sstefano_zampini   isend[5] = matis->A->num_ass;
12077fa8f2d3SStefano Zampini   if (flag == MAT_LOCAL) {
12087fa8f2d3SStefano Zampini     ginfo->nz_used      = isend[0];
12097fa8f2d3SStefano Zampini     ginfo->nz_allocated = isend[1];
12107fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = isend[2];
12117fa8f2d3SStefano Zampini     ginfo->memory       = isend[3];
12127fa8f2d3SStefano Zampini     ginfo->mallocs      = isend[4];
1213314ce898Sstefano_zampini     ginfo->assemblies   = isend[5];
12147fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_MAX) {
1215314ce898Sstefano_zampini     ierr = MPIU_Allreduce(isend,irecv,6,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
12167fa8f2d3SStefano Zampini 
12177fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
12187fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
12197fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
12207fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
12217fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
1222314ce898Sstefano_zampini     ginfo->assemblies   = irecv[5];
12237fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_SUM) {
12247fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
12257fa8f2d3SStefano Zampini 
12267fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
12277fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
12287fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
12297fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
12307fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
12317fa8f2d3SStefano Zampini     ginfo->assemblies   = A->num_ass;
12327fa8f2d3SStefano Zampini   }
12337fa8f2d3SStefano Zampini   ginfo->block_size        = bs;
12347fa8f2d3SStefano Zampini   ginfo->fill_ratio_given  = 0;
12357fa8f2d3SStefano Zampini   ginfo->fill_ratio_needed = 0;
12367fa8f2d3SStefano Zampini   ginfo->factor_mallocs    = 0;
12375e3038f0Sstefano_zampini   PetscFunctionReturn(0);
12385e3038f0Sstefano_zampini }
12395e3038f0Sstefano_zampini 
1240d7f69cd0SStefano Zampini PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
1241d7f69cd0SStefano Zampini {
1242d7f69cd0SStefano Zampini   Mat                    C,lC,lA;
1243d7f69cd0SStefano Zampini   PetscErrorCode         ierr;
1244d7f69cd0SStefano Zampini 
1245d7f69cd0SStefano Zampini   PetscFunctionBegin;
1246cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) {
1247cf37664fSBarry Smith     ISLocalToGlobalMapping rl2g,cl2g;
1248d7f69cd0SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
1249d7f69cd0SStefano Zampini     ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr);
1250d7f69cd0SStefano Zampini     ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
1251d7f69cd0SStefano Zampini     ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
1252d7f69cd0SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
1253d7f69cd0SStefano Zampini     ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr);
1254cf37664fSBarry Smith   } else {
1255cf37664fSBarry Smith     C = *B;
1256d7f69cd0SStefano Zampini   }
1257d7f69cd0SStefano Zampini 
1258d7f69cd0SStefano Zampini   /* perform local transposition */
1259d7f69cd0SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
1260d7f69cd0SStefano Zampini   ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr);
1261d7f69cd0SStefano Zampini   ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
1262d7f69cd0SStefano Zampini   ierr = MatDestroy(&lC);CHKERRQ(ierr);
1263d7f69cd0SStefano Zampini 
1264cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) {
1265d7f69cd0SStefano Zampini     *B = C;
1266d7f69cd0SStefano Zampini   } else {
1267d7f69cd0SStefano Zampini     ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr);
1268d7f69cd0SStefano Zampini   }
12697aa7aec5Sstefano_zampini   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
12707aa7aec5Sstefano_zampini   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1271d7f69cd0SStefano Zampini   PetscFunctionReturn(0);
1272d7f69cd0SStefano Zampini }
1273d7f69cd0SStefano Zampini 
12743fd1c9e7SStefano Zampini PetscErrorCode  MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
12753fd1c9e7SStefano Zampini {
12763fd1c9e7SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
12773fd1c9e7SStefano Zampini   PetscErrorCode ierr;
12783fd1c9e7SStefano Zampini 
12793fd1c9e7SStefano Zampini   PetscFunctionBegin;
12804b89b9cdSStefano Zampini   if (D) { /* MatShift_IS pass D = NULL */
12813fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12823fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12833fd1c9e7SStefano Zampini   }
12843fd1c9e7SStefano Zampini   ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr);
12853fd1c9e7SStefano Zampini   ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr);
12863fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
12873fd1c9e7SStefano Zampini }
12883fd1c9e7SStefano Zampini 
12893fd1c9e7SStefano Zampini PetscErrorCode  MatShift_IS(Mat A,PetscScalar a)
12903fd1c9e7SStefano Zampini {
12914b89b9cdSStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
12923fd1c9e7SStefano Zampini   PetscErrorCode ierr;
12933fd1c9e7SStefano Zampini 
12943fd1c9e7SStefano Zampini   PetscFunctionBegin;
12954b89b9cdSStefano Zampini   ierr = VecSet(is->y,a);CHKERRQ(ierr);
12963fd1c9e7SStefano Zampini   ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr);
12973fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
12983fd1c9e7SStefano Zampini }
12993fd1c9e7SStefano Zampini 
1300f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1301f26d0771SStefano Zampini {
1302f26d0771SStefano Zampini   PetscErrorCode ierr;
1303f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
1304f26d0771SStefano Zampini 
1305f26d0771SStefano Zampini   PetscFunctionBegin;
1306f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1307f26d0771SStefano 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);
1308f26d0771SStefano Zampini #endif
1309f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
1310f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
1311b4f971dfSStefano Zampini   ierr = MatSetValuesLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
1312f26d0771SStefano Zampini   PetscFunctionReturn(0);
1313f26d0771SStefano Zampini }
1314f26d0771SStefano Zampini 
1315f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1316f26d0771SStefano Zampini {
1317f26d0771SStefano Zampini   PetscErrorCode ierr;
1318f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
1319f26d0771SStefano Zampini 
1320f26d0771SStefano Zampini   PetscFunctionBegin;
1321f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1322f26d0771SStefano 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);
1323f26d0771SStefano Zampini #endif
1324f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
1325f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
1326b4f971dfSStefano Zampini   ierr = MatSetValuesBlockedLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
1327f26d0771SStefano Zampini   PetscFunctionReturn(0);
1328f26d0771SStefano Zampini }
1329f26d0771SStefano Zampini 
13307dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
1331a8116848SStefano Zampini {
1332a8116848SStefano Zampini   Mat               locmat,newlocmat;
1333a8116848SStefano Zampini   Mat_IS            *newmatis;
1334a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
1335a8116848SStefano Zampini   Vec               rtest,ltest;
1336a8116848SStefano Zampini   const PetscScalar *array;
1337a8116848SStefano Zampini #endif
1338a8116848SStefano Zampini   const PetscInt    *idxs;
1339a8116848SStefano Zampini   PetscInt          i,m,n;
1340a8116848SStefano Zampini   PetscErrorCode    ierr;
1341a8116848SStefano Zampini 
1342a8116848SStefano Zampini   PetscFunctionBegin;
1343a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
1344a8116848SStefano Zampini     PetscBool ismatis;
1345a8116848SStefano Zampini 
1346a8116848SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
1347a8116848SStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
1348a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
1349a8116848SStefano Zampini     if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
1350a8116848SStefano Zampini     if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
1351a8116848SStefano Zampini   }
1352a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
1353a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
1354a8116848SStefano Zampini   ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
1355a8116848SStefano Zampini   ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
1356a8116848SStefano Zampini   ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
1357a8116848SStefano Zampini   for (i=0;i<n;i++) {
1358a8116848SStefano Zampini     ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
1359a8116848SStefano Zampini   }
1360a8116848SStefano Zampini   ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
1361a8116848SStefano Zampini   ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
1362a8116848SStefano Zampini   ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
1363a8116848SStefano Zampini   ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
1364a8116848SStefano Zampini   ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
1365fd479f66SMatthew 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]));
1366a8116848SStefano Zampini   ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
1367a8116848SStefano Zampini   ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
1368a8116848SStefano Zampini   ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
1369a8116848SStefano Zampini   ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
1370a8116848SStefano Zampini   for (i=0;i<n;i++) {
1371a8116848SStefano Zampini     ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
1372a8116848SStefano Zampini   }
1373a8116848SStefano Zampini   ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
1374a8116848SStefano Zampini   ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
1375a8116848SStefano Zampini   ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
1376a8116848SStefano Zampini   ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
1377a8116848SStefano Zampini   ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
1378fd479f66SMatthew 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]));
1379a8116848SStefano Zampini   ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
1380a8116848SStefano Zampini   ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
1381a8116848SStefano Zampini   ierr = VecDestroy(&rtest);CHKERRQ(ierr);
1382a8116848SStefano Zampini   ierr = VecDestroy(&ltest);CHKERRQ(ierr);
1383a8116848SStefano Zampini #endif
1384a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
1385a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
1386a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
1387a8116848SStefano Zampini     IS                     is;
1388a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
1389306cf5c7SStefano Zampini     PetscInt               ll,newloc,irbs,icbs,arbs,acbs,rbs,cbs;
139094342113SStefano Zampini     PetscBool              cong;
1391a8116848SStefano Zampini     MPI_Comm               comm;
1392a8116848SStefano Zampini 
1393a8116848SStefano Zampini     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
1394306cf5c7SStefano Zampini     ierr = MatGetBlockSizes(mat,&arbs,&acbs);CHKERRQ(ierr);
1395306cf5c7SStefano Zampini     ierr = ISGetBlockSize(irow,&irbs);CHKERRQ(ierr);
1396306cf5c7SStefano Zampini     ierr = ISGetBlockSize(icol,&icbs);CHKERRQ(ierr);
1397306cf5c7SStefano Zampini     rbs  = arbs == irbs ? irbs : 1;
1398306cf5c7SStefano Zampini     cbs  = acbs == icbs ? icbs : 1;
1399a8116848SStefano Zampini     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
1400a8116848SStefano Zampini     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
1401a8116848SStefano Zampini     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
1402a8116848SStefano Zampini     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
1403a8116848SStefano Zampini     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1404306cf5c7SStefano Zampini     ierr = MatSetBlockSizes(*newmat,rbs,cbs);CHKERRQ(ierr);
1405a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
1406a8116848SStefano Zampini     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
1407*a72d46e8SStefano Zampini     ierr = PetscLayoutMapLocal(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
1408a8116848SStefano Zampini     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
14093d996552SStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,matis->sf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
1410a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
1411a8116848SStefano Zampini     ierr = PetscFree(lidxs);CHKERRQ(ierr);
1412a8116848SStefano Zampini     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
1413a8116848SStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
1414a8116848SStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
14153d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
1416a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
1417a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
14183d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++)
1419a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
1420a8116848SStefano Zampini         lidxs[newloc] = i;
1421a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
1422a8116848SStefano Zampini       }
1423a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1424a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
1425306cf5c7SStefano Zampini     ierr = ISLocalToGlobalMappingSetBlockSize(rl2g,rbs);CHKERRQ(ierr);
1426a8116848SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
1427a8116848SStefano Zampini     /* local is to extract local submatrix */
1428a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
1429a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
143094342113SStefano Zampini     ierr = MatHasCongruentLayouts(mat,&cong);CHKERRQ(ierr);
143194342113SStefano Zampini     if (cong && irow == icol && matis->csf == matis->sf) {
1432a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
1433a8116848SStefano Zampini       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
1434a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
1435a8116848SStefano Zampini     } else {
1436a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
1437a8116848SStefano Zampini 
1438a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
1439a8116848SStefano Zampini       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
1440*a72d46e8SStefano Zampini       ierr = PetscLayoutMapLocal(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
1441a8116848SStefano Zampini       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
14423d996552SStefano Zampini       ierr = PetscMemzero(matis->csf_rootdata,matis->csf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
1443a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
1444a8116848SStefano Zampini       ierr = PetscFree(lidxs);CHKERRQ(ierr);
1445a8116848SStefano Zampini       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
1446a8116848SStefano Zampini       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
1447a8116848SStefano Zampini       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
14483d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
1449a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
1450a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
14513d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++)
1452a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
1453a8116848SStefano Zampini           lidxs[newloc] = i;
1454a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
1455a8116848SStefano Zampini         }
1456a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1457a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
1458306cf5c7SStefano Zampini       ierr = ISLocalToGlobalMappingSetBlockSize(cl2g,cbs);CHKERRQ(ierr);
1459a8116848SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
1460a8116848SStefano Zampini       /* local is to extract local submatrix */
1461a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
1462a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
1463a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
1464a8116848SStefano Zampini     }
1465a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
1466a8116848SStefano Zampini   } else {
1467a8116848SStefano Zampini     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
1468a8116848SStefano Zampini   }
1469a8116848SStefano Zampini   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
1470a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
14717dae84e0SHong Zhang   ierr = MatCreateSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
1472a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
1473a8116848SStefano Zampini     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
1474a8116848SStefano Zampini     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
1475a8116848SStefano Zampini   }
1476a8116848SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1477a8116848SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1478a8116848SStefano Zampini   PetscFunctionReturn(0);
1479a8116848SStefano Zampini }
1480a8116848SStefano Zampini 
1481a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
14822b404112SStefano Zampini {
14832b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
14842b404112SStefano Zampini   PetscBool      ismatis;
14852b404112SStefano Zampini   PetscErrorCode ierr;
14862b404112SStefano Zampini 
14872b404112SStefano Zampini   PetscFunctionBegin;
14882b404112SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
14892b404112SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
14902b404112SStefano Zampini   b = (Mat_IS*)B->data;
14912b404112SStefano Zampini   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
1492cdc753b6SBarry Smith   ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
14932b404112SStefano Zampini   PetscFunctionReturn(0);
14942b404112SStefano Zampini }
14952b404112SStefano Zampini 
1496a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
14976bd84002SStefano Zampini {
1498527b2640SStefano Zampini   Vec               v;
1499527b2640SStefano Zampini   const PetscScalar *array;
1500527b2640SStefano Zampini   PetscInt          i,n;
15016bd84002SStefano Zampini   PetscErrorCode    ierr;
15026bd84002SStefano Zampini 
15036bd84002SStefano Zampini   PetscFunctionBegin;
1504527b2640SStefano Zampini   *missing = PETSC_FALSE;
1505527b2640SStefano Zampini   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
1506527b2640SStefano Zampini   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
1507527b2640SStefano Zampini   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1508527b2640SStefano Zampini   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
1509527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
1510527b2640SStefano Zampini   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
1511527b2640SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
1512527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
1513527b2640SStefano Zampini   if (d) {
1514527b2640SStefano Zampini     *d = -1;
1515527b2640SStefano Zampini     if (*missing) {
1516527b2640SStefano Zampini       PetscInt rstart;
1517527b2640SStefano Zampini       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
1518527b2640SStefano Zampini       *d = i+rstart;
1519527b2640SStefano Zampini     }
1520527b2640SStefano Zampini   }
15216bd84002SStefano Zampini   PetscFunctionReturn(0);
15226bd84002SStefano Zampini }
15236bd84002SStefano Zampini 
1524cf0a3239SStefano Zampini static PetscErrorCode MatISSetUpSF_IS(Mat B)
152528f4e0baSStefano Zampini {
152628f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
152728f4e0baSStefano Zampini   const PetscInt *gidxs;
15284f2d7cafSStefano Zampini   PetscInt       nleaves;
152928f4e0baSStefano Zampini   PetscErrorCode ierr;
153028f4e0baSStefano Zampini 
153128f4e0baSStefano Zampini   PetscFunctionBegin;
15324f2d7cafSStefano Zampini   if (matis->sf) PetscFunctionReturn(0);
153328f4e0baSStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
15343bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
15354f2d7cafSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(B->rmap->mapping,&nleaves);CHKERRQ(ierr);
15364f2d7cafSStefano Zampini   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
15373bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
15384f2d7cafSStefano Zampini   ierr = PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
1539a8116848SStefano Zampini   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
15403d996552SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(B->cmap->mapping,&nleaves);CHKERRQ(ierr);
1541a8116848SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
1542a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
15433d996552SStefano Zampini     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
1544a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
15453d996552SStefano Zampini     ierr = PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
1546a8116848SStefano Zampini   } else {
1547a8116848SStefano Zampini     matis->csf = matis->sf;
1548a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
1549a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
1550a8116848SStefano Zampini   }
155128f4e0baSStefano Zampini   PetscFunctionReturn(0);
155228f4e0baSStefano Zampini }
15532e1947a5SStefano Zampini 
1554eb82efa4SStefano Zampini /*@
155575d48cdbSStefano Zampini    MatISStoreL2L - Store local-to-local operators during the Galerkin process of MatPtAP.
155675d48cdbSStefano Zampini 
155775d48cdbSStefano Zampini    Collective on MPI_Comm
155875d48cdbSStefano Zampini 
155975d48cdbSStefano Zampini    Input Parameters:
156075d48cdbSStefano Zampini +  A - the matrix
156175d48cdbSStefano Zampini -  store - the boolean flag
156275d48cdbSStefano Zampini 
156375d48cdbSStefano Zampini    Level: advanced
156475d48cdbSStefano Zampini 
156575d48cdbSStefano Zampini    Notes:
156675d48cdbSStefano Zampini 
156775d48cdbSStefano Zampini .keywords: matrix
156875d48cdbSStefano Zampini 
156975d48cdbSStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatPtAP()
157075d48cdbSStefano Zampini @*/
157175d48cdbSStefano Zampini PetscErrorCode  MatISStoreL2L(Mat A, PetscBool store)
157275d48cdbSStefano Zampini {
157375d48cdbSStefano Zampini   PetscErrorCode ierr;
157475d48cdbSStefano Zampini 
157575d48cdbSStefano Zampini   PetscFunctionBegin;
157675d48cdbSStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
157775d48cdbSStefano Zampini   PetscValidType(A,1);
157875d48cdbSStefano Zampini   PetscValidLogicalCollectiveBool(A,store,2);
157975d48cdbSStefano Zampini   ierr = PetscTryMethod(A,"MatISStoreL2L_C",(Mat,PetscBool),(A,store));CHKERRQ(ierr);
158075d48cdbSStefano Zampini   PetscFunctionReturn(0);
158175d48cdbSStefano Zampini }
158275d48cdbSStefano Zampini 
158375d48cdbSStefano Zampini static PetscErrorCode MatISStoreL2L_IS(Mat A, PetscBool store)
158475d48cdbSStefano Zampini {
158575d48cdbSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(A->data);
158675d48cdbSStefano Zampini   PetscErrorCode ierr;
158775d48cdbSStefano Zampini 
158875d48cdbSStefano Zampini   PetscFunctionBegin;
158975d48cdbSStefano Zampini   matis->storel2l = store;
159075d48cdbSStefano Zampini   if (!store) {
159175d48cdbSStefano Zampini     ierr = PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",NULL);CHKERRQ(ierr);
159275d48cdbSStefano Zampini   }
159375d48cdbSStefano Zampini   PetscFunctionReturn(0);
159475d48cdbSStefano Zampini }
159575d48cdbSStefano Zampini 
159675d48cdbSStefano Zampini /*@
1597f03112d0SStefano Zampini    MatISFixLocalEmpty - Compress out zero local rows from the local matrices
1598f03112d0SStefano Zampini 
1599f03112d0SStefano Zampini    Collective on MPI_Comm
1600f03112d0SStefano Zampini 
1601f03112d0SStefano Zampini    Input Parameters:
1602f03112d0SStefano Zampini +  A - the matrix
1603f03112d0SStefano Zampini -  fix - the boolean flag
1604f03112d0SStefano Zampini 
1605f03112d0SStefano Zampini    Level: advanced
1606f03112d0SStefano Zampini 
1607f03112d0SStefano Zampini    Notes: When fix is true, new local matrices and l2g maps are generated during the final assembly process.
1608f03112d0SStefano Zampini 
1609f03112d0SStefano Zampini .keywords: matrix
1610f03112d0SStefano Zampini 
1611f03112d0SStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatAssemblyEnd(), MAT_FINAL_ASSEMBLY
1612f03112d0SStefano Zampini @*/
1613f03112d0SStefano Zampini PetscErrorCode  MatISFixLocalEmpty(Mat A, PetscBool fix)
1614f03112d0SStefano Zampini {
1615f03112d0SStefano Zampini   PetscErrorCode ierr;
1616f03112d0SStefano Zampini 
1617f03112d0SStefano Zampini   PetscFunctionBegin;
1618f03112d0SStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
1619f03112d0SStefano Zampini   PetscValidType(A,1);
1620f03112d0SStefano Zampini   PetscValidLogicalCollectiveBool(A,fix,2);
1621f03112d0SStefano Zampini   ierr = PetscTryMethod(A,"MatISFixLocalEmpty_C",(Mat,PetscBool),(A,fix));CHKERRQ(ierr);
1622f03112d0SStefano Zampini   PetscFunctionReturn(0);
1623f03112d0SStefano Zampini }
1624f03112d0SStefano Zampini 
1625f03112d0SStefano Zampini static PetscErrorCode MatISFixLocalEmpty_IS(Mat A, PetscBool fix)
1626f03112d0SStefano Zampini {
1627f03112d0SStefano Zampini   Mat_IS *matis = (Mat_IS*)(A->data);
1628f03112d0SStefano Zampini 
1629f03112d0SStefano Zampini   PetscFunctionBegin;
1630f03112d0SStefano Zampini   matis->locempty = fix;
1631f03112d0SStefano Zampini   PetscFunctionReturn(0);
1632f03112d0SStefano Zampini }
1633f03112d0SStefano Zampini 
1634f03112d0SStefano Zampini /*@
1635a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
1636a88811baSStefano Zampini 
1637a88811baSStefano Zampini    Collective on MPI_Comm
1638a88811baSStefano Zampini 
1639a88811baSStefano Zampini    Input Parameters:
1640a88811baSStefano Zampini +  B - the matrix
1641a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1642a88811baSStefano Zampini            (same value is used for all local rows)
1643a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
1644a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
1645a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
1646a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
1647a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
1648a88811baSStefano Zampini            the diagonal entry even if it is zero.
1649a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1650a88811baSStefano Zampini            submatrix (same value is used for all local rows).
1651a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
1652a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
1653a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
1654a88811baSStefano Zampini            structure. The size of this array is equal to the number
1655a88811baSStefano Zampini            of local rows, i.e 'm'.
1656a88811baSStefano Zampini 
1657a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
1658a88811baSStefano Zampini 
1659a88811baSStefano Zampini    Level: intermediate
1660a88811baSStefano Zampini 
166195452b02SPatrick Sanan    Notes:
166295452b02SPatrick Sanan     This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
1663a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
1664a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
1665a88811baSStefano Zampini 
1666a88811baSStefano Zampini .keywords: matrix
1667a88811baSStefano Zampini 
16683c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
1669a88811baSStefano Zampini @*/
16702e1947a5SStefano Zampini PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
16712e1947a5SStefano Zampini {
16722e1947a5SStefano Zampini   PetscErrorCode ierr;
16732e1947a5SStefano Zampini 
16742e1947a5SStefano Zampini   PetscFunctionBegin;
16752e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
16762e1947a5SStefano Zampini   PetscValidType(B,1);
16772e1947a5SStefano Zampini   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
16782e1947a5SStefano Zampini   PetscFunctionReturn(0);
16792e1947a5SStefano Zampini }
16802e1947a5SStefano Zampini 
1681844bd0d7SStefano Zampini /* this is used by DMDA */
1682844bd0d7SStefano Zampini PETSC_EXTERN PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
16832e1947a5SStefano Zampini {
16842e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
168528f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
16862e1947a5SStefano Zampini   PetscErrorCode ierr;
16872e1947a5SStefano Zampini 
16882e1947a5SStefano Zampini   PetscFunctionBegin;
16896c4ed002SBarry Smith   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
16904f2d7cafSStefano Zampini 
16914f2d7cafSStefano Zampini   if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz;
16924f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
16934f2d7cafSStefano Zampini 
16944f2d7cafSStefano Zampini   if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz;
16954f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
16964f2d7cafSStefano Zampini 
169728f4e0baSStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
169828f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
169928f4e0baSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
170028f4e0baSStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
17014f2d7cafSStefano Zampini 
17024f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
170328f4e0baSStefano Zampini   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
17040f2f62c7SStefano Zampini #if defined(PETSC_HAVE_HYPRE)
17050f2f62c7SStefano Zampini   ierr = MatHYPRESetPreallocation(matis->A,0,matis->sf_leafdata,0,NULL);CHKERRQ(ierr);
17060f2f62c7SStefano Zampini #endif
17074f2d7cafSStefano Zampini 
17084f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
170928f4e0baSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
17104f2d7cafSStefano Zampini 
171100a59248SStefano Zampini   nlocalcols /= bs;
171200a59248SStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols - i);
171328f4e0baSStefano Zampini   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
17140f2f62c7SStefano Zampini 
17150f2f62c7SStefano Zampini   /* for other matrix types */
17160f2f62c7SStefano Zampini   ierr = MatSetUp(matis->A);CHKERRQ(ierr);
17172e1947a5SStefano Zampini   PetscFunctionReturn(0);
17182e1947a5SStefano Zampini }
1719b4319ba4SBarry Smith 
17203927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
17213927de2eSStefano Zampini {
17223927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
17233927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
1724ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
17253927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
17263927de2eSStefano Zampini   PetscInt        lrows,lcols;
17273927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
1728f03112d0SStefano Zampini   PetscMPIInt     size;
17293927de2eSStefano Zampini   PetscBool       isdense,issbaij;
17303927de2eSStefano Zampini   PetscErrorCode  ierr;
17313927de2eSStefano Zampini 
17323927de2eSStefano Zampini   PetscFunctionBegin;
1733f03112d0SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRQ(ierr);
17343927de2eSStefano Zampini   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
17353927de2eSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
17363927de2eSStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
17373927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
17383927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1739ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1740ecf5a873SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
17417230de76SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1742ecf5a873SStefano Zampini   } else {
1743ecf5a873SStefano Zampini     global_indices_c = global_indices_r;
1744ecf5a873SStefano Zampini   }
1745ecf5a873SStefano Zampini 
17463927de2eSStefano Zampini   if (issbaij) {
17473927de2eSStefano Zampini     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
17483927de2eSStefano Zampini   }
17493927de2eSStefano Zampini   /*
1750ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
17513927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
17523927de2eSStefano Zampini   */
17533927de2eSStefano Zampini   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
17543927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
17553927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
17563927de2eSStefano Zampini   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
17573927de2eSStefano Zampini   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
1758f03112d0SStefano Zampini   for (i=0;i<size;i++) {
17593927de2eSStefano Zampini     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
17603927de2eSStefano Zampini       row_ownership[j] = i;
17613927de2eSStefano Zampini     }
17623927de2eSStefano Zampini   }
17637230de76SStefano Zampini   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
17643927de2eSStefano Zampini 
17653927de2eSStefano Zampini   /*
17663927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
17673927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
17683927de2eSStefano Zampini   */
17693927de2eSStefano Zampini   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
17703927de2eSStefano Zampini   /* preallocation as a MATAIJ */
17713927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
17723927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
177312dfadf8SStefano Zampini       PetscInt owner = row_ownership[global_indices_r[i]];
177412dfadf8SStefano Zampini       for (j=0;j<local_cols;j++) {
1775ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
17763927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
17773927de2eSStefano Zampini           my_dnz[i] += 1;
17783927de2eSStefano Zampini         } else { /* offdiag block */
17793927de2eSStefano Zampini           my_onz[i] += 1;
17803927de2eSStefano Zampini         }
17813927de2eSStefano Zampini       }
17823927de2eSStefano Zampini     }
1783bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
1784bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
1785bb1015c3SStefano Zampini     PetscBool      done;
1786bb1015c3SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1787938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1788bb1015c3SStefano Zampini     jptr = jj;
1789bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
1790bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
1791bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
1792bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
1793bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
1794bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
1795bb1015c3SStefano Zampini           my_dnz[i] += 1;
1796bb1015c3SStefano Zampini         } else { /* offdiag block */
1797bb1015c3SStefano Zampini           my_onz[i] += 1;
1798bb1015c3SStefano Zampini         }
1799bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
1800bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
1801bb1015c3SStefano Zampini           owner = row_ownership[index_col];
1802bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1803bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
1804bb1015c3SStefano Zampini           } else {
1805bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
1806bb1015c3SStefano Zampini           }
1807bb1015c3SStefano Zampini         }
1808bb1015c3SStefano Zampini       }
1809bb1015c3SStefano Zampini     }
1810bb1015c3SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1811938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1812bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
18133927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
18143927de2eSStefano Zampini       const PetscInt *cols;
1815ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
18163927de2eSStefano Zampini       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
18173927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
18183927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
1819ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
18203927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
18213927de2eSStefano Zampini           my_dnz[i] += 1;
18223927de2eSStefano Zampini         } else { /* offdiag block */
18233927de2eSStefano Zampini           my_onz[i] += 1;
18243927de2eSStefano Zampini         }
18253927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
1826d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
18273927de2eSStefano Zampini           owner = row_ownership[index_col];
18283927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1829d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
18303927de2eSStefano Zampini           } else {
1831d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
18323927de2eSStefano Zampini           }
18333927de2eSStefano Zampini         }
18343927de2eSStefano Zampini       }
18353927de2eSStefano Zampini       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
18363927de2eSStefano Zampini     }
18373927de2eSStefano Zampini   }
1838ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
18397230de76SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1840ecf5a873SStefano Zampini   }
18414f619741Sstefano_zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
18423927de2eSStefano Zampini   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
1843ecf5a873SStefano Zampini 
1844ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
18453927de2eSStefano Zampini   if (maxreduce) {
18463927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
18473927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
1848bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
18493927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
18503927de2eSStefano Zampini   } else {
18513927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
18523927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
1853bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
18543927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
18553927de2eSStefano Zampini   }
18563927de2eSStefano Zampini   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
18573927de2eSStefano Zampini 
18583927de2eSStefano Zampini   /* Resize preallocation if overestimated */
18593927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
18603927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
18613927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
18623927de2eSStefano Zampini   }
18631670daf9Sstefano_zampini 
18641670daf9Sstefano_zampini   /* Set preallocation */
1865268753edSStefano Zampini   ierr = MatSeqAIJSetPreallocation(B,0,dnz);CHKERRQ(ierr);
18663927de2eSStefano Zampini   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
186753b44cf5SStefano Zampini   for (i=0;i<lrows;i+=bs) {
186853b44cf5SStefano Zampini     PetscInt b, d = dnz[i],o = onz[i];
186953b44cf5SStefano Zampini 
187053b44cf5SStefano Zampini     for (b=1;b<bs;b++) {
187153b44cf5SStefano Zampini       d = PetscMax(d,dnz[i+b]);
187253b44cf5SStefano Zampini       o = PetscMax(o,onz[i+b]);
187353b44cf5SStefano Zampini     }
187453b44cf5SStefano Zampini     dnz[i/bs] = PetscMin(d/bs + d%bs,lcols/bs);
187553b44cf5SStefano Zampini     onz[i/bs] = PetscMin(o/bs + o%bs,(cols-lcols)/bs);
18763927de2eSStefano Zampini   }
1877268753edSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(B,bs,0,dnz);CHKERRQ(ierr);
18783927de2eSStefano Zampini   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
18793927de2eSStefano Zampini   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
18803927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
18813927de2eSStefano Zampini   if (issbaij) {
18823927de2eSStefano Zampini     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
18833927de2eSStefano Zampini   }
18849be90c3fSStefano Zampini   ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
18853927de2eSStefano Zampini   PetscFunctionReturn(0);
18863927de2eSStefano Zampini }
18873927de2eSStefano Zampini 
1888487b449aSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_IS_XAIJ(Mat mat, MatType mtype, MatReuse reuse, Mat *M)
1889b7ce53b6SStefano Zampini {
1890b7ce53b6SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1891487b449aSStefano Zampini   Mat            local_mat,MT;
189253b44cf5SStefano Zampini   PetscInt       rbs,cbs,rows,cols,lrows,lcols;
1893b7ce53b6SStefano Zampini   PetscInt       local_rows,local_cols;
1894b9ed4604SStefano Zampini   PetscBool      isseqdense,isseqsbaij,isseqaij,isseqbaij;
1895b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1896b9ed4604SStefano Zampini   PetscBool      lb[4],bb[4];
1897b9ed4604SStefano Zampini #endif
1898f03112d0SStefano Zampini   PetscMPIInt    size;
1899b7ce53b6SStefano Zampini   PetscScalar    *array;
1900b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1901b7ce53b6SStefano Zampini 
1902b7ce53b6SStefano Zampini   PetscFunctionBegin;
1903f03112d0SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
1904f03112d0SStefano Zampini   if (size == 1 && mat->rmap->N == matis->A->rmap->N && mat->cmap->N == matis->A->cmap->N) {
19051670daf9Sstefano_zampini     Mat      B;
190653b44cf5SStefano Zampini     IS       irows = NULL,icols = NULL;
1907487b449aSStefano Zampini     PetscInt rbs,cbs;
19081670daf9Sstefano_zampini 
1909487b449aSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr);
1910487b449aSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr);
191153b44cf5SStefano Zampini     if (reuse != MAT_REUSE_MATRIX) { /* check if l2g maps are one-to-one */
191253b44cf5SStefano Zampini       IS             rows,cols;
191353b44cf5SStefano Zampini       const PetscInt *ridxs,*cidxs;
191453b44cf5SStefano Zampini       PetscInt       i,nw,*work;
191553b44cf5SStefano Zampini 
191653b44cf5SStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
191753b44cf5SStefano Zampini       ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&nw);CHKERRQ(ierr);
191853b44cf5SStefano Zampini       nw   = nw/rbs;
191953b44cf5SStefano Zampini       ierr = PetscCalloc1(nw,&work);CHKERRQ(ierr);
192053b44cf5SStefano Zampini       for (i=0;i<nw;i++) work[ridxs[i]] += 1;
192153b44cf5SStefano Zampini       for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break;
192253b44cf5SStefano Zampini       if (i == nw) {
192353b44cf5SStefano Zampini         ierr = ISCreateBlock(PETSC_COMM_SELF,rbs,nw,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
1924acdf38a7Sstefano_zampini         ierr = ISSetPermutation(rows);CHKERRQ(ierr);
192553b44cf5SStefano Zampini         ierr = ISInvertPermutation(rows,PETSC_DECIDE,&irows);CHKERRQ(ierr);
1926acdf38a7Sstefano_zampini         ierr = ISDestroy(&rows);CHKERRQ(ierr);
192753b44cf5SStefano Zampini       }
192853b44cf5SStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
192953b44cf5SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
193053b44cf5SStefano Zampini       if (irows && mat->rmap->mapping != mat->cmap->mapping) {
193153b44cf5SStefano Zampini         ierr = ISLocalToGlobalMappingGetBlockIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
193253b44cf5SStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(mat->cmap->mapping,&nw);CHKERRQ(ierr);
193353b44cf5SStefano Zampini         nw   = nw/cbs;
193453b44cf5SStefano Zampini         ierr = PetscCalloc1(nw,&work);CHKERRQ(ierr);
193553b44cf5SStefano Zampini         for (i=0;i<nw;i++) work[cidxs[i]] += 1;
193653b44cf5SStefano Zampini         for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break;
193753b44cf5SStefano Zampini         if (i == nw) {
193853b44cf5SStefano Zampini           ierr = ISCreateBlock(PETSC_COMM_SELF,cbs,nw,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
193953b44cf5SStefano Zampini           ierr = ISSetPermutation(cols);CHKERRQ(ierr);
194053b44cf5SStefano Zampini           ierr = ISInvertPermutation(cols,PETSC_DECIDE,&icols);CHKERRQ(ierr);
194153b44cf5SStefano Zampini           ierr = ISDestroy(&cols);CHKERRQ(ierr);
194253b44cf5SStefano Zampini         }
194353b44cf5SStefano Zampini         ierr = ISLocalToGlobalMappingRestoreBlockIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
194453b44cf5SStefano Zampini         ierr = PetscFree(work);CHKERRQ(ierr);
194553b44cf5SStefano Zampini       } else if (irows) {
194653b44cf5SStefano Zampini         ierr  = PetscObjectReference((PetscObject)irows);CHKERRQ(ierr);
194753b44cf5SStefano Zampini         icols = irows;
194853b44cf5SStefano Zampini       }
194953b44cf5SStefano Zampini     } else {
195053b44cf5SStefano Zampini       ierr = PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject*)&irows);CHKERRQ(ierr);
195153b44cf5SStefano Zampini       ierr = PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject*)&icols);CHKERRQ(ierr);
195253b44cf5SStefano Zampini       if (irows) { ierr = PetscObjectReference((PetscObject)irows);CHKERRQ(ierr); }
195353b44cf5SStefano Zampini       if (icols) { ierr = PetscObjectReference((PetscObject)icols);CHKERRQ(ierr); }
195453b44cf5SStefano Zampini     }
195553b44cf5SStefano Zampini     if (!irows || !icols) {
195653b44cf5SStefano Zampini       ierr = ISDestroy(&icols);CHKERRQ(ierr);
195753b44cf5SStefano Zampini       ierr = ISDestroy(&irows);CHKERRQ(ierr);
195853b44cf5SStefano Zampini       goto general_assembly;
195953b44cf5SStefano Zampini     }
1960487b449aSStefano Zampini     ierr = MatConvert(matis->A,(rbs == cbs && rbs > 1) ? MATSEQBAIJ : MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
1961487b449aSStefano Zampini     if (reuse != MAT_INPLACE_MATRIX) {
19627dae84e0SHong Zhang       ierr = MatCreateSubMatrix(B,irows,icols,reuse,M);CHKERRQ(ierr);
196353b44cf5SStefano Zampini       ierr = PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject)irows);CHKERRQ(ierr);
196453b44cf5SStefano Zampini       ierr = PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject)icols);CHKERRQ(ierr);
1965487b449aSStefano Zampini     } else {
1966487b449aSStefano Zampini       Mat C;
1967487b449aSStefano Zampini 
1968487b449aSStefano Zampini       ierr = MatCreateSubMatrix(B,irows,icols,MAT_INITIAL_MATRIX,&C);CHKERRQ(ierr);
1969487b449aSStefano Zampini       ierr = MatHeaderReplace(mat,&C);CHKERRQ(ierr);
1970487b449aSStefano Zampini     }
1971acdf38a7Sstefano_zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
1972acdf38a7Sstefano_zampini     ierr = ISDestroy(&icols);CHKERRQ(ierr);
1973acdf38a7Sstefano_zampini     ierr = ISDestroy(&irows);CHKERRQ(ierr);
19747c03b4e8SStefano Zampini     PetscFunctionReturn(0);
19757c03b4e8SStefano Zampini   }
197653b44cf5SStefano Zampini general_assembly:
1977b7ce53b6SStefano Zampini   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
197853b44cf5SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr);
197953b44cf5SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr);
19803cfa4ea4SStefano Zampini   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
1981b7ce53b6SStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
1982b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
19834099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
1984b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
1985b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij);CHKERRQ(ierr);
1986b9ed4604SStefano Zampini   if (!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name);
1987b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1988b9ed4604SStefano Zampini   lb[0] = isseqdense;
1989b9ed4604SStefano Zampini   lb[1] = isseqaij;
1990b9ed4604SStefano Zampini   lb[2] = isseqbaij;
1991b9ed4604SStefano Zampini   lb[3] = isseqsbaij;
1992b9ed4604SStefano Zampini   ierr = MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
1993b9ed4604SStefano Zampini   if (!bb[0] && !bb[1] && !bb[2] && !bb[3]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type");
1994b9ed4604SStefano Zampini #endif
1995b7ce53b6SStefano Zampini 
1996487b449aSStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
1997487b449aSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)mat),&MT);CHKERRQ(ierr);
1998487b449aSStefano Zampini     ierr = MatSetSizes(MT,lrows,lcols,rows,cols);CHKERRQ(ierr);
1999487b449aSStefano Zampini     ierr = MatSetType(MT,mtype);CHKERRQ(ierr);
200053b44cf5SStefano Zampini     ierr = MatSetBlockSizes(MT,rbs,cbs);CHKERRQ(ierr);
2001487b449aSStefano Zampini     ierr = MatISSetMPIXAIJPreallocation_Private(mat,MT,PETSC_FALSE);CHKERRQ(ierr);
2002b7ce53b6SStefano Zampini   } else {
200353b44cf5SStefano Zampini     PetscInt mrbs,mcbs,mrows,mcols,mlrows,mlcols;
2004487b449aSStefano Zampini 
2005b7ce53b6SStefano Zampini     /* some checks */
2006487b449aSStefano Zampini     MT   = *M;
200753b44cf5SStefano Zampini     ierr = MatGetBlockSizes(MT,&mrbs,&mcbs);CHKERRQ(ierr);
2008487b449aSStefano Zampini     ierr = MatGetSize(MT,&mrows,&mcols);CHKERRQ(ierr);
2009487b449aSStefano Zampini     ierr = MatGetLocalSize(MT,&mlrows,&mlcols);CHKERRQ(ierr);
20106c4ed002SBarry Smith     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
20116c4ed002SBarry Smith     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
20126c4ed002SBarry Smith     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
20136c4ed002SBarry Smith     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
201453b44cf5SStefano Zampini     if (mrbs != rbs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong row block size (%d != %d)",rbs,mrbs);
201553b44cf5SStefano Zampini     if (mcbs != cbs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong col block size (%d != %d)",cbs,mcbs);
2016487b449aSStefano Zampini     ierr = MatZeroEntries(MT);CHKERRQ(ierr);
2017b7ce53b6SStefano Zampini   }
2018d9a9e74cSStefano Zampini 
20198546b261SStefano Zampini   if (isseqsbaij || isseqbaij) {
20208546b261SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
20218546b261SStefano Zampini     isseqaij = PETSC_TRUE;
2022d9a9e74cSStefano Zampini   } else {
2023d9a9e74cSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
2024d9a9e74cSStefano Zampini     local_mat = matis->A;
2025d9a9e74cSStefano Zampini   }
2026686e3a49SStefano Zampini 
2027b7ce53b6SStefano Zampini   /* Set values */
2028487b449aSStefano Zampini   ierr = MatSetLocalToGlobalMapping(MT,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
2029b9ed4604SStefano Zampini   if (isseqdense) { /* special case for dense local matrices */
203065066ba5SStefano Zampini     PetscInt i,*dummy;
2031ecf5a873SStefano Zampini 
203265066ba5SStefano Zampini     ierr = PetscMalloc1(PetscMax(local_rows,local_cols),&dummy);CHKERRQ(ierr);
203365066ba5SStefano Zampini     for (i=0;i<PetscMax(local_rows,local_cols);i++) dummy[i] = i;
2034487b449aSStefano Zampini     ierr = MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
2035d9a9e74cSStefano Zampini     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
2036487b449aSStefano Zampini     ierr = MatSetValuesLocal(MT,local_rows,dummy,local_cols,dummy,array,ADD_VALUES);CHKERRQ(ierr);
2037d9a9e74cSStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
203865066ba5SStefano Zampini     ierr = PetscFree(dummy);CHKERRQ(ierr);
2039686e3a49SStefano Zampini   } else if (isseqaij) {
20406afe12f5SStefano Zampini     const PetscInt *blocks;
20416afe12f5SStefano Zampini     PetscInt       i,nvtxs,*xadj,*adjncy, nb;
2042686e3a49SStefano Zampini     PetscBool      done;
2043686e3a49SStefano Zampini 
2044d9a9e74cSStefano Zampini     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
2045938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
2046d9a9e74cSStefano Zampini     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
20476afe12f5SStefano Zampini     ierr = MatGetVariableBlockSizes(local_mat,&nb,&blocks);CHKERRQ(ierr);
20486afe12f5SStefano Zampini     if (nb) { /* speed up assembly for special blocked matrices (used by BDDC) */
20496afe12f5SStefano Zampini       PetscInt sum;
20506afe12f5SStefano Zampini 
20516afe12f5SStefano Zampini       for (i=0,sum=0;i<nb;i++) sum += blocks[i];
20526afe12f5SStefano Zampini       if (sum == nvtxs) {
20536afe12f5SStefano Zampini         PetscInt r;
20546afe12f5SStefano Zampini 
20556afe12f5SStefano Zampini         for (i=0,r=0;i<nb;i++) {
20566afe12f5SStefano Zampini           if (blocks[i] != xadj[r+1] - xadj[r]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid block sizes prescribed for block %D: expected %D, got %D",i,blocks[i],xadj[r+1] - xadj[r]);
20576afe12f5SStefano Zampini           ierr = MatSetValuesLocal(MT,blocks[i],adjncy+xadj[r],blocks[i],adjncy+xadj[r],array+xadj[r],ADD_VALUES);CHKERRQ(ierr);
20586afe12f5SStefano Zampini           r   += blocks[i];
20596afe12f5SStefano Zampini         }
20606afe12f5SStefano Zampini       } else {
2061686e3a49SStefano Zampini         for (i=0;i<nvtxs;i++) {
2062487b449aSStefano Zampini           ierr = MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
2063686e3a49SStefano Zampini         }
20646afe12f5SStefano Zampini       }
20656afe12f5SStefano Zampini     } else {
20666afe12f5SStefano Zampini       for (i=0;i<nvtxs;i++) {
20676afe12f5SStefano Zampini         ierr = MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
20686afe12f5SStefano Zampini       }
20696afe12f5SStefano Zampini     }
2070d9a9e74cSStefano Zampini     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
2071938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
2072d9a9e74cSStefano Zampini     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
2073686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
2074ecf5a873SStefano Zampini     PetscInt i;
2075c0962df8SStefano Zampini 
2076686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
2077686e3a49SStefano Zampini       PetscInt       j;
2078ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
2079686e3a49SStefano Zampini 
2080ecf5a873SStefano Zampini       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
2081487b449aSStefano Zampini       ierr = MatSetValuesLocal(MT,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
2082ecf5a873SStefano Zampini       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
2083686e3a49SStefano Zampini     }
2084b7ce53b6SStefano Zampini   }
2085487b449aSStefano Zampini   ierr = MatAssemblyBegin(MT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2086d9a9e74cSStefano Zampini   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
2087487b449aSStefano Zampini   ierr = MatAssemblyEnd(MT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2088b9ed4604SStefano Zampini   if (isseqdense) {
2089487b449aSStefano Zampini     ierr = MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
2090487b449aSStefano Zampini   }
2091487b449aSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
2092487b449aSStefano Zampini     ierr = MatHeaderReplace(mat,&MT);CHKERRQ(ierr);
2093487b449aSStefano Zampini   } else if (reuse == MAT_INITIAL_MATRIX) {
2094487b449aSStefano Zampini     *M = MT;
2095b7ce53b6SStefano Zampini   }
2096b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
2097b7ce53b6SStefano Zampini }
2098b7ce53b6SStefano Zampini 
2099b7ce53b6SStefano Zampini /*@
2100b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
2101b7ce53b6SStefano Zampini 
2102b7ce53b6SStefano Zampini   Input Parameter:
2103b7ce53b6SStefano Zampini .  mat - the matrix (should be of type MATIS)
2104b7ce53b6SStefano Zampini .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
2105b7ce53b6SStefano Zampini 
2106b7ce53b6SStefano Zampini   Output Parameter:
2107b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
2108b7ce53b6SStefano Zampini 
2109b7ce53b6SStefano Zampini   Level: developer
2110b7ce53b6SStefano Zampini 
211195452b02SPatrick Sanan   Notes:
2112487b449aSStefano Zampini     This function has been deprecated and it will be removed in future releases. Update your code to use the MatConvert() interface.
2113b7ce53b6SStefano Zampini 
2114487b449aSStefano Zampini .seealso: MATIS, MatConvert()
2115b7ce53b6SStefano Zampini @*/
2116b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
2117b7ce53b6SStefano Zampini {
2118b7ce53b6SStefano Zampini   PetscErrorCode ierr;
2119b7ce53b6SStefano Zampini 
2120b7ce53b6SStefano Zampini   PetscFunctionBegin;
2121b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2122b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
2123b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
2124487b449aSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
2125b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
2126b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
21276c4ed002SBarry Smith     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
2128b7ce53b6SStefano Zampini   }
2129487b449aSStefano Zampini   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatType,MatReuse,Mat*),(mat,MATAIJ,reuse,newmat));CHKERRQ(ierr);
2130b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
2131b7ce53b6SStefano Zampini }
2132b7ce53b6SStefano Zampini 
2133ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
2134ad6194a2SStefano Zampini {
2135ad6194a2SStefano Zampini   PetscErrorCode ierr;
2136ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
2137c9225affSStefano Zampini   PetscInt       rbs,cbs,m,n,M,N;
2138ad6194a2SStefano Zampini   Mat            B,localmat;
2139ad6194a2SStefano Zampini 
2140ad6194a2SStefano Zampini   PetscFunctionBegin;
2141c9225affSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr);
2142c9225affSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr);
2143ad6194a2SStefano Zampini   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
2144ad6194a2SStefano Zampini   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
21458546b261SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)mat),&B);CHKERRQ(ierr);
21468546b261SStefano Zampini   ierr = MatSetSizes(B,m,n,M,N);CHKERRQ(ierr);
21478546b261SStefano Zampini   ierr = MatSetBlockSize(B,rbs == cbs ? rbs : 1);CHKERRQ(ierr);
21488546b261SStefano Zampini   ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
21498546b261SStefano Zampini   ierr = MatISSetLocalMatType(B,matis->lmattype);CHKERRQ(ierr);
21508546b261SStefano Zampini   ierr = MatSetLocalToGlobalMapping(B,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
2151ad6194a2SStefano Zampini   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
2152ad6194a2SStefano Zampini   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
2153b3317aa8SStefano Zampini   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
2154ad6194a2SStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2155ad6194a2SStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2156ad6194a2SStefano Zampini   *newmat = B;
2157ad6194a2SStefano Zampini   PetscFunctionReturn(0);
2158ad6194a2SStefano Zampini }
2159ad6194a2SStefano Zampini 
2160a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
216169796d55SStefano Zampini {
216269796d55SStefano Zampini   PetscErrorCode ierr;
216369796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
216469796d55SStefano Zampini   PetscBool      local_sym;
216569796d55SStefano Zampini 
216669796d55SStefano Zampini   PetscFunctionBegin;
216769796d55SStefano Zampini   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
2168b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
216969796d55SStefano Zampini   PetscFunctionReturn(0);
217069796d55SStefano Zampini }
217169796d55SStefano Zampini 
2172a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
217369796d55SStefano Zampini {
217469796d55SStefano Zampini   PetscErrorCode ierr;
217569796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
217669796d55SStefano Zampini   PetscBool      local_sym;
217769796d55SStefano Zampini 
217869796d55SStefano Zampini   PetscFunctionBegin;
217969796d55SStefano Zampini   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
2180b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
218169796d55SStefano Zampini   PetscFunctionReturn(0);
218269796d55SStefano Zampini }
218369796d55SStefano Zampini 
218445471136SStefano Zampini static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool  *flg)
218545471136SStefano Zampini {
218645471136SStefano Zampini   PetscErrorCode ierr;
218745471136SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
218845471136SStefano Zampini   PetscBool      local_sym;
218945471136SStefano Zampini 
219045471136SStefano Zampini   PetscFunctionBegin;
219145471136SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
219245471136SStefano Zampini     *flg = PETSC_FALSE;
219345471136SStefano Zampini     PetscFunctionReturn(0);
219445471136SStefano Zampini   }
219545471136SStefano Zampini   ierr = MatIsStructurallySymmetric(matis->A,&local_sym);CHKERRQ(ierr);
219645471136SStefano Zampini   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
219745471136SStefano Zampini   PetscFunctionReturn(0);
219845471136SStefano Zampini }
219945471136SStefano Zampini 
2200a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
2201b4319ba4SBarry Smith {
2202dfbe8321SBarry Smith   PetscErrorCode ierr;
2203b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
2204b4319ba4SBarry Smith 
2205b4319ba4SBarry Smith   PetscFunctionBegin;
2206b89f26deSStefano Zampini   ierr = PetscFree(b->bdiag);CHKERRQ(ierr);
22078546b261SStefano Zampini   ierr = PetscFree(b->lmattype);CHKERRQ(ierr);
22086bf464f9SBarry Smith   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
2209e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
2210e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
22116bf464f9SBarry Smith   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
22126bf464f9SBarry Smith   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
22133fd1c9e7SStefano Zampini   ierr = VecDestroy(&b->counter);CHKERRQ(ierr);
2214a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
2215a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
2216a8116848SStefano Zampini   if (b->sf != b->csf) {
2217a8116848SStefano Zampini     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
2218a8116848SStefano Zampini     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
2219f03112d0SStefano Zampini   } else b->csf = NULL;
222028f4e0baSStefano Zampini   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
222128f4e0baSStefano Zampini   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
2222bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
2223dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
22248546b261SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMatType_C",NULL);CHKERRQ(ierr);
2225bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
2226b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
2227b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
22282e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
222975d48cdbSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",NULL);CHKERRQ(ierr);
2230f03112d0SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",NULL);CHKERRQ(ierr);
2231487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",NULL);CHKERRQ(ierr);
2232487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",NULL);CHKERRQ(ierr);
2233487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",NULL);CHKERRQ(ierr);
2234487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",NULL);CHKERRQ(ierr);
2235487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",NULL);CHKERRQ(ierr);
2236487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",NULL);CHKERRQ(ierr);
2237487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",NULL);CHKERRQ(ierr);
2238b4319ba4SBarry Smith   PetscFunctionReturn(0);
2239b4319ba4SBarry Smith }
2240b4319ba4SBarry Smith 
2241a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
2242b4319ba4SBarry Smith {
2243dfbe8321SBarry Smith   PetscErrorCode ierr;
2244b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
2245b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
2246b4319ba4SBarry Smith 
2247b4319ba4SBarry Smith   PetscFunctionBegin;
2248b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
2249e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2250e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2251b4319ba4SBarry Smith 
2252b4319ba4SBarry Smith   /* multiply the local matrix */
2253b4319ba4SBarry Smith   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
2254b4319ba4SBarry Smith 
2255b4319ba4SBarry Smith   /* scatter product back into global memory */
22562dcb1b2aSMatthew Knepley   ierr = VecSet(y,zero);CHKERRQ(ierr);
2257e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2258e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2259b4319ba4SBarry Smith   PetscFunctionReturn(0);
2260b4319ba4SBarry Smith }
2261b4319ba4SBarry Smith 
2262a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
22632e74eeadSLisandro Dalcin {
2264650997f4SStefano Zampini   Vec            temp_vec;
22652e74eeadSLisandro Dalcin   PetscErrorCode ierr;
22662e74eeadSLisandro Dalcin 
22672e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
2268650997f4SStefano Zampini   if (v3 != v2) {
2269650997f4SStefano Zampini     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
2270650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
2271650997f4SStefano Zampini   } else {
2272650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
2273650997f4SStefano Zampini     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
2274650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
2275650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
2276650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
2277650997f4SStefano Zampini   }
22782e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
22792e74eeadSLisandro Dalcin }
22802e74eeadSLisandro Dalcin 
2281a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
22822e74eeadSLisandro Dalcin {
22832e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
22842e74eeadSLisandro Dalcin   PetscErrorCode ierr;
22852e74eeadSLisandro Dalcin 
2286e176bc59SStefano Zampini   PetscFunctionBegin;
22872e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
2288e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2289e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
22902e74eeadSLisandro Dalcin 
22912e74eeadSLisandro Dalcin   /* multiply the local matrix */
2292e176bc59SStefano Zampini   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
22932e74eeadSLisandro Dalcin 
22942e74eeadSLisandro Dalcin   /* scatter product back into global vector */
2295e176bc59SStefano Zampini   ierr = VecSet(x,0);CHKERRQ(ierr);
2296e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2297e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
22982e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
22992e74eeadSLisandro Dalcin }
23002e74eeadSLisandro Dalcin 
2301a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
23022e74eeadSLisandro Dalcin {
2303650997f4SStefano Zampini   Vec            temp_vec;
23042e74eeadSLisandro Dalcin   PetscErrorCode ierr;
23052e74eeadSLisandro Dalcin 
23062e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
2307650997f4SStefano Zampini   if (v3 != v2) {
2308650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
2309650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
2310650997f4SStefano Zampini   } else {
2311650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
2312650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
2313650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
2314650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
2315650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
2316650997f4SStefano Zampini   }
23172e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
23182e74eeadSLisandro Dalcin }
23192e74eeadSLisandro Dalcin 
2320a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
2321b4319ba4SBarry Smith {
2322b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
2323dfbe8321SBarry Smith   PetscErrorCode ierr;
2324b4319ba4SBarry Smith   PetscViewer    sviewer;
2325ee2491ecSStefano Zampini   PetscBool      isascii,view = PETSC_TRUE;
2326b4319ba4SBarry Smith 
2327b4319ba4SBarry Smith   PetscFunctionBegin;
2328ee2491ecSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
2329ee2491ecSStefano Zampini   if (isascii)  {
2330ee2491ecSStefano Zampini     PetscViewerFormat format;
2331ee2491ecSStefano Zampini 
2332ee2491ecSStefano Zampini     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
2333ee2491ecSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE;
2334ee2491ecSStefano Zampini   }
2335ee2491ecSStefano Zampini   if (!view) PetscFunctionReturn(0);
23363f08860eSBarry Smith   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
2337b4319ba4SBarry Smith   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
23383f08860eSBarry Smith   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
23396e520ac8SStefano Zampini   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2340b4319ba4SBarry Smith   PetscFunctionReturn(0);
2341b4319ba4SBarry Smith }
2342b4319ba4SBarry Smith 
2343b89f26deSStefano Zampini static PetscErrorCode MatInvertBlockDiagonal_IS(Mat mat,const PetscScalar **values)
2344b89f26deSStefano Zampini {
2345b89f26deSStefano Zampini   Mat_IS            *is = (Mat_IS*)mat->data;
2346b89f26deSStefano Zampini   MPI_Datatype      nodeType;
2347b89f26deSStefano Zampini   const PetscScalar *lv;
2348b89f26deSStefano Zampini   PetscInt          bs;
2349b89f26deSStefano Zampini   PetscErrorCode    ierr;
2350b89f26deSStefano Zampini 
2351b89f26deSStefano Zampini   PetscFunctionBegin;
2352b89f26deSStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
2353b89f26deSStefano Zampini   ierr = MatSetBlockSize(is->A,bs);CHKERRQ(ierr);
2354b89f26deSStefano Zampini   ierr = MatInvertBlockDiagonal(is->A,&lv);CHKERRQ(ierr);
2355b89f26deSStefano Zampini   if (!is->bdiag) {
2356b89f26deSStefano Zampini     ierr = PetscMalloc1(bs*mat->rmap->n,&is->bdiag);CHKERRQ(ierr);
2357b89f26deSStefano Zampini   }
2358b89f26deSStefano Zampini   ierr = MPI_Type_contiguous(bs,MPIU_SCALAR,&nodeType);CHKERRQ(ierr);
2359b89f26deSStefano Zampini   ierr = MPI_Type_commit(&nodeType);CHKERRQ(ierr);
2360b89f26deSStefano Zampini   ierr = PetscSFReduceBegin(is->sf,nodeType,lv,is->bdiag,MPIU_REPLACE);CHKERRQ(ierr);
2361b89f26deSStefano Zampini   ierr = PetscSFReduceEnd(is->sf,nodeType,lv,is->bdiag,MPIU_REPLACE);CHKERRQ(ierr);
2362b89f26deSStefano Zampini   ierr = MPI_Type_free(&nodeType);CHKERRQ(ierr);
2363b89f26deSStefano Zampini   if (values) *values = is->bdiag;
2364b89f26deSStefano Zampini   PetscFunctionReturn(0);
2365b89f26deSStefano Zampini }
2366b89f26deSStefano Zampini 
23678546b261SStefano Zampini static PetscErrorCode MatISSetUpScatters_Private(Mat A)
2368b4319ba4SBarry Smith {
2369e176bc59SStefano Zampini   Vec            cglobal,rglobal;
23708546b261SStefano Zampini   IS             from;
23718546b261SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
2372b89f26deSStefano Zampini   PetscScalar    sum;
23738546b261SStefano Zampini   const PetscInt *garray;
23748546b261SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
23758546b261SStefano Zampini   PetscBool      iscuda;
23768546b261SStefano Zampini   PetscErrorCode ierr;
2377b4319ba4SBarry Smith 
2378b4319ba4SBarry Smith   PetscFunctionBegin;
23798546b261SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nr);CHKERRQ(ierr);
23808546b261SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(A->rmap->mapping,&rbs);CHKERRQ(ierr);
23818546b261SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&nc);CHKERRQ(ierr);
23828546b261SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(A->cmap->mapping,&cbs);CHKERRQ(ierr);
238370cf5478SStefano Zampini   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
238470cf5478SStefano Zampini   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
23853fd1c9e7SStefano Zampini   ierr = VecDestroy(&is->counter);CHKERRQ(ierr);
2386e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
2387e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
23888546b261SStefano Zampini   ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
23898546b261SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)is->y,VECSEQCUDA,&iscuda);CHKERRQ(ierr);
23908546b261SStefano Zampini   if (iscuda) {
23918546b261SStefano Zampini     ierr = PetscFree(A->defaultvectype);CHKERRQ(ierr);
23928546b261SStefano Zampini     ierr = PetscStrallocpy(VECCUDA,&A->defaultvectype);CHKERRQ(ierr);
23938546b261SStefano Zampini   }
23948546b261SStefano Zampini   ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
23958546b261SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockIndices(A->rmap->mapping,&garray);CHKERRQ(ierr);
23968546b261SStefano Zampini   ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),rbs,nr/rbs,garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
23979448b7f1SJunchao Zhang   ierr = VecScatterCreate(rglobal,from,is->y,NULL,&is->rctx);CHKERRQ(ierr);
23988546b261SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreBlockIndices(A->rmap->mapping,&garray);CHKERRQ(ierr);
23998546b261SStefano Zampini   ierr = ISDestroy(&from);CHKERRQ(ierr);
24008546b261SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
24018546b261SStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockIndices(A->cmap->mapping,&garray);CHKERRQ(ierr);
24028546b261SStefano Zampini     ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),cbs,nc/cbs,garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
24039448b7f1SJunchao Zhang     ierr = VecScatterCreate(cglobal,from,is->x,NULL,&is->cctx);CHKERRQ(ierr);
24048546b261SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreBlockIndices(A->cmap->mapping,&garray);CHKERRQ(ierr);
24058546b261SStefano Zampini     ierr = ISDestroy(&from);CHKERRQ(ierr);
24068546b261SStefano Zampini   } else {
24078546b261SStefano Zampini     ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
24088546b261SStefano Zampini     is->cctx = is->rctx;
24098546b261SStefano Zampini   }
2410b89f26deSStefano Zampini   ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
2411b89f26deSStefano Zampini 
24128546b261SStefano Zampini   /* interface counter vector (local) */
24138546b261SStefano Zampini   ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr);
24148546b261SStefano Zampini   ierr = VecSet(is->y,1.);CHKERRQ(ierr);
24158546b261SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
24168546b261SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
24178546b261SStefano Zampini   ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
24188546b261SStefano Zampini   ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2419b89f26deSStefano Zampini 
2420b89f26deSStefano Zampini   /* special functions for block-diagonal matrices */
2421b89f26deSStefano Zampini   ierr = VecSum(rglobal,&sum);CHKERRQ(ierr);
2422b89f26deSStefano Zampini   if ((PetscInt)(PetscRealPart(sum)) == A->rmap->N && A->rmap->N == A->cmap->N && A->rmap->mapping == A->cmap->mapping) {
2423b89f26deSStefano Zampini     A->ops->invertblockdiagonal = MatInvertBlockDiagonal_IS;
2424b89f26deSStefano Zampini   } else {
2425b89f26deSStefano Zampini     A->ops->invertblockdiagonal = NULL;
2426b89f26deSStefano Zampini   }
24278546b261SStefano Zampini   ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
2428b0cc1f67SStefano Zampini 
2429b0cc1f67SStefano Zampini   /* setup SF for general purpose shared indices based communications */
2430b0cc1f67SStefano Zampini   ierr = MatISSetUpSF_IS(A);CHKERRQ(ierr);
24318546b261SStefano Zampini   PetscFunctionReturn(0);
24328546b261SStefano Zampini }
24338546b261SStefano Zampini 
24348546b261SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
24358546b261SStefano Zampini {
24368546b261SStefano Zampini   PetscErrorCode ierr;
24378546b261SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
24388546b261SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
24398546b261SStefano Zampini 
24408546b261SStefano Zampini   PetscFunctionBegin;
24418546b261SStefano Zampini   PetscCheckSameComm(A,1,rmapping,2);
24428546b261SStefano Zampini   PetscCheckSameComm(A,1,cmapping,3);
24431c47cb0fSStefano Zampini   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
2444872cf891SStefano Zampini   if (is->csf != is->sf) {
2445872cf891SStefano Zampini     ierr = PetscSFDestroy(&is->csf);CHKERRQ(ierr);
2446872cf891SStefano Zampini     ierr = PetscFree2(is->csf_rootdata,is->csf_leafdata);CHKERRQ(ierr);
2447f03112d0SStefano Zampini   } else is->csf = NULL;
244828f4e0baSStefano Zampini   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
244928f4e0baSStefano Zampini   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
2450b89f26deSStefano Zampini   ierr = PetscFree(is->bdiag);CHKERRQ(ierr);
24513bbff08aSStefano Zampini 
24523bbff08aSStefano Zampini   /* Setup Layout and set local to global maps */
2453fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
2454fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
2455e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
2456e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
2457e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
2458e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
24596625354bSStefano Zampini   /* check if the two mappings are actually the same for square matrices (DOLFIN passes 2 different objects) */
24606625354bSStefano Zampini   if (rmapping != cmapping && A->rmap->N == A->cmap->N) {
24616625354bSStefano Zampini     PetscBool same,gsame;
24626625354bSStefano Zampini 
24636625354bSStefano Zampini     same = PETSC_FALSE;
24646625354bSStefano Zampini     if (nr == nc && cbs == rbs) {
24656625354bSStefano Zampini       const PetscInt *idxs1,*idxs2;
24666625354bSStefano Zampini 
24676625354bSStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(rmapping,&idxs1);CHKERRQ(ierr);
24686625354bSStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(cmapping,&idxs2);CHKERRQ(ierr);
24696625354bSStefano Zampini       ierr = PetscMemcmp(idxs1,idxs2,(nr/rbs)*sizeof(PetscInt),&same);CHKERRQ(ierr);
24706625354bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(rmapping,&idxs1);CHKERRQ(ierr);
24716625354bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(cmapping,&idxs2);CHKERRQ(ierr);
24726625354bSStefano Zampini     }
24736625354bSStefano Zampini     ierr = MPIU_Allreduce(&same,&gsame,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
24746625354bSStefano Zampini     if (gsame) cmapping = rmapping;
24756625354bSStefano Zampini   }
247653b44cf5SStefano Zampini   ierr = PetscLayoutSetBlockSize(A->rmap,rbs);CHKERRQ(ierr);
247753b44cf5SStefano Zampini   ierr = PetscLayoutSetBlockSize(A->cmap,cbs);CHKERRQ(ierr);
24786625354bSStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
24796625354bSStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
24806625354bSStefano Zampini 
24816625354bSStefano Zampini   /* Create the local matrix A */
2482f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
24838546b261SStefano Zampini   ierr = MatSetType(is->A,is->lmattype);CHKERRQ(ierr);
2484e176bc59SStefano Zampini   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
2485e176bc59SStefano Zampini   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
24868546b261SStefano Zampini   ierr = MatSetOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
24878546b261SStefano Zampini   ierr = MatAppendOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
2488c77832edSStefano Zampini   ierr = PetscLayoutSetUp(is->A->rmap);CHKERRQ(ierr);
2489c77832edSStefano Zampini   ierr = PetscLayoutSetUp(is->A->cmap);CHKERRQ(ierr);
2490b4319ba4SBarry Smith 
2491f26d0771SStefano Zampini   if (!is->islocalref) { /* setup scatters and local vectors for MatMult */
24928546b261SStefano Zampini     ierr = MatISSetUpScatters_Private(A);CHKERRQ(ierr);
2493f26d0771SStefano Zampini   }
249448ff6bf3SStefano Zampini   ierr = MatSetUp(A);CHKERRQ(ierr);
2495b4319ba4SBarry Smith   PetscFunctionReturn(0);
2496b4319ba4SBarry Smith }
2497b4319ba4SBarry Smith 
2498a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
24992e74eeadSLisandro Dalcin {
25002e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
25012e74eeadSLisandro Dalcin   PetscErrorCode ierr;
250297563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
250397563a80SStefano Zampini   PetscInt       i,zm,zn;
250497563a80SStefano Zampini #endif
2505f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
25062e74eeadSLisandro Dalcin 
25072e74eeadSLisandro Dalcin   PetscFunctionBegin;
25082e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG)
2509f26d0771SStefano 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);
251097563a80SStefano Zampini   /* count negative indices */
251197563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
251297563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
25132e74eeadSLisandro Dalcin #endif
251497563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
251597563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
251697563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
251797563a80SStefano Zampini   /* count negative indices (should be the same as before) */
251897563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
251997563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
2520b4f971dfSStefano 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");
2521b4f971dfSStefano 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");
252297563a80SStefano Zampini #endif
25232e74eeadSLisandro Dalcin   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
25242e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
25252e74eeadSLisandro Dalcin }
25262e74eeadSLisandro Dalcin 
2527a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
252897563a80SStefano Zampini {
252997563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
253097563a80SStefano Zampini   PetscErrorCode ierr;
253197563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
253297563a80SStefano Zampini   PetscInt       i,zm,zn;
253397563a80SStefano Zampini #endif
2534f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
253597563a80SStefano Zampini 
253697563a80SStefano Zampini   PetscFunctionBegin;
253797563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
2538f26d0771SStefano 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);
253997563a80SStefano Zampini   /* count negative indices */
254097563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
254197563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
254297563a80SStefano Zampini #endif
254397563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
254497563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
254597563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
254697563a80SStefano Zampini   /* count negative indices (should be the same as before) */
254797563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
254897563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
2549b4f971dfSStefano 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");
2550b4f971dfSStefano 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");
255197563a80SStefano Zampini #endif
2552d59cf9ebSStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
255397563a80SStefano Zampini   PetscFunctionReturn(0);
255497563a80SStefano Zampini }
255597563a80SStefano Zampini 
2556a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
2557b4319ba4SBarry Smith {
2558dfbe8321SBarry Smith   PetscErrorCode ierr;
2559b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2560b4319ba4SBarry Smith 
2561b4319ba4SBarry Smith   PetscFunctionBegin;
2562b4f971dfSStefano Zampini   if (is->A->rmap->mapping) {
2563872cf891SStefano Zampini     ierr = MatSetValuesLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2564872cf891SStefano Zampini   } else {
2565b4319ba4SBarry Smith     ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2566872cf891SStefano Zampini   }
2567b4319ba4SBarry Smith   PetscFunctionReturn(0);
2568b4319ba4SBarry Smith }
2569b4319ba4SBarry Smith 
2570a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
2571f0006bf2SLisandro Dalcin {
2572f0006bf2SLisandro Dalcin   PetscErrorCode ierr;
2573f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
2574f0006bf2SLisandro Dalcin 
2575f0006bf2SLisandro Dalcin   PetscFunctionBegin;
2576b4f971dfSStefano Zampini   if (is->A->rmap->mapping) {
2577b4f971dfSStefano Zampini #if defined(PETSC_USE_DEBUG)
2578b4f971dfSStefano Zampini     PetscInt ibs,bs;
2579b4f971dfSStefano Zampini 
2580b4f971dfSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(is->A->rmap->mapping,&ibs);CHKERRQ(ierr);
2581b4f971dfSStefano Zampini     ierr = MatGetBlockSize(is->A,&bs);CHKERRQ(ierr);
2582b4f971dfSStefano Zampini     if (ibs != bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Different block sizes! local mat %D, local l2g map %D",bs,ibs);
2583b4f971dfSStefano Zampini #endif
2584b4f971dfSStefano Zampini     ierr = MatSetValuesBlockedLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2585b4f971dfSStefano Zampini   } else {
2586f0006bf2SLisandro Dalcin     ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2587b4f971dfSStefano Zampini   }
2588f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
2589f0006bf2SLisandro Dalcin }
2590f0006bf2SLisandro Dalcin 
2591f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
2592f0ae7da4SStefano Zampini {
2593f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
2594f0ae7da4SStefano Zampini   PetscErrorCode ierr;
2595f0ae7da4SStefano Zampini 
2596f0ae7da4SStefano Zampini   PetscFunctionBegin;
2597f0ae7da4SStefano Zampini   if (!n) {
2598f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
2599f0ae7da4SStefano Zampini   } else {
2600f0ae7da4SStefano Zampini     PetscInt i;
2601f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
2602f0ae7da4SStefano Zampini 
2603f0ae7da4SStefano Zampini     if (columns) {
2604f0ae7da4SStefano Zampini       ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
2605f0ae7da4SStefano Zampini     } else {
2606f0ae7da4SStefano Zampini       ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
2607f0ae7da4SStefano Zampini     }
2608f0ae7da4SStefano Zampini     if (diag != 0.) {
2609f0ae7da4SStefano Zampini       const PetscScalar *array;
2610f0ae7da4SStefano Zampini       ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr);
2611f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
2612f0ae7da4SStefano Zampini         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
2613f0ae7da4SStefano Zampini       }
2614f0ae7da4SStefano Zampini       ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr);
2615f0ae7da4SStefano Zampini     }
2616f0ae7da4SStefano Zampini     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2617f0ae7da4SStefano Zampini     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2618f0ae7da4SStefano Zampini   }
2619f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
2620f0ae7da4SStefano Zampini }
2621f0ae7da4SStefano Zampini 
2622f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
26232e74eeadSLisandro Dalcin {
26246e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
26256e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
26266e520ac8SStefano Zampini   PetscInt       *lrows;
26272e74eeadSLisandro Dalcin   PetscErrorCode ierr;
26282e74eeadSLisandro Dalcin 
26292e74eeadSLisandro Dalcin   PetscFunctionBegin;
2630f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG)
2631f0ae7da4SStefano Zampini   if (columns || diag != 0. || (x && b)) {
2632f0ae7da4SStefano Zampini     PetscBool cong;
263326b0207aSStefano Zampini 
2634f0ae7da4SStefano Zampini     ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr);
263526b0207aSStefano Zampini     cong = (PetscBool)(cong && matis->sf == matis->csf);
2636268753edSStefano 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");
2637268753edSStefano 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");
2638268753edSStefano 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");
2639f0ae7da4SStefano Zampini   }
2640f0ae7da4SStefano Zampini #endif
26416e520ac8SStefano Zampini   /* get locally owned rows */
2642*a72d46e8SStefano Zampini   ierr = PetscLayoutMapLocal(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr);
26436e520ac8SStefano Zampini   /* fix right hand side if needed */
26446e520ac8SStefano Zampini   if (x && b) {
26456e520ac8SStefano Zampini     const PetscScalar *xx;
26466e520ac8SStefano Zampini     PetscScalar       *bb;
26476e520ac8SStefano Zampini 
26486e520ac8SStefano Zampini     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
26496e520ac8SStefano Zampini     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
26506e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
26516e520ac8SStefano Zampini     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
26526e520ac8SStefano Zampini     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
26532e74eeadSLisandro Dalcin   }
26546e520ac8SStefano Zampini   /* get rows associated to the local matrices */
26556e520ac8SStefano Zampini   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
26566e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr);
26576e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
26586e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
26596e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
26606e520ac8SStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
26616e520ac8SStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
26626e520ac8SStefano Zampini   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
26636e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
2664f0ae7da4SStefano Zampini   ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr);
26656e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
26662e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
26672e74eeadSLisandro Dalcin }
26682e74eeadSLisandro Dalcin 
2669f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
2670b4319ba4SBarry Smith {
2671dfbe8321SBarry Smith   PetscErrorCode ierr;
2672b4319ba4SBarry Smith 
2673b4319ba4SBarry Smith   PetscFunctionBegin;
2674f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr);
2675f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
2676f0ae7da4SStefano Zampini }
26772205254eSKarl Rupp 
2678f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
2679f0ae7da4SStefano Zampini {
2680f0ae7da4SStefano Zampini   PetscErrorCode ierr;
2681f0ae7da4SStefano Zampini 
2682f0ae7da4SStefano Zampini   PetscFunctionBegin;
2683f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr);
2684b4319ba4SBarry Smith   PetscFunctionReturn(0);
2685b4319ba4SBarry Smith }
2686b4319ba4SBarry Smith 
2687a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
2688b4319ba4SBarry Smith {
2689b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2690dfbe8321SBarry Smith   PetscErrorCode ierr;
2691b4319ba4SBarry Smith 
2692b4319ba4SBarry Smith   PetscFunctionBegin;
2693b4319ba4SBarry Smith   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
2694b4319ba4SBarry Smith   PetscFunctionReturn(0);
2695b4319ba4SBarry Smith }
2696b4319ba4SBarry Smith 
2697a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
2698b4319ba4SBarry Smith {
2699b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2700dfbe8321SBarry Smith   PetscErrorCode ierr;
2701b4319ba4SBarry Smith 
2702b4319ba4SBarry Smith   PetscFunctionBegin;
2703b4319ba4SBarry Smith   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
2704872cf891SStefano Zampini   /* fix for local empty rows/cols */
2705872cf891SStefano Zampini   if (is->locempty && type == MAT_FINAL_ASSEMBLY) {
2706872cf891SStefano Zampini     Mat                    newlA;
2707f03112d0SStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g;
2708f03112d0SStefano Zampini     IS                     nzr,nzc;
2709f03112d0SStefano Zampini     PetscInt               nr,nc,nnzr,nnzc;
2710f03112d0SStefano Zampini     PetscBool              lnewl2g,newl2g;
2711872cf891SStefano Zampini 
2712f03112d0SStefano Zampini     ierr = MatGetSize(is->A,&nr,&nc);CHKERRQ(ierr);
2713f03112d0SStefano Zampini     ierr = MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_FALSE,PETSC_SMALL,&nzr);CHKERRQ(ierr);
2714f03112d0SStefano Zampini     if (!nzr) {
2715f03112d0SStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nr,0,1,&nzr);CHKERRQ(ierr);
2716872cf891SStefano Zampini     }
2717f03112d0SStefano Zampini     ierr = MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_TRUE,PETSC_SMALL,&nzc);CHKERRQ(ierr);
2718f03112d0SStefano Zampini     if (!nzc) {
2719f03112d0SStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nc,0,1,&nzc);CHKERRQ(ierr);
2720872cf891SStefano Zampini     }
2721f03112d0SStefano Zampini     ierr = ISGetSize(nzr,&nnzr);CHKERRQ(ierr);
2722f03112d0SStefano Zampini     ierr = ISGetSize(nzc,&nnzc);CHKERRQ(ierr);
2723f03112d0SStefano Zampini     if (nnzr != nr || nnzc != nc) {
2724f03112d0SStefano Zampini       ISLocalToGlobalMapping l2g;
2725f03112d0SStefano Zampini       IS                     is1,is2;
2726f03112d0SStefano Zampini 
2727f03112d0SStefano Zampini       /* need new global l2g map */
2728f03112d0SStefano Zampini       lnewl2g = PETSC_TRUE;
2729f03112d0SStefano Zampini       ierr    = MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
2730f03112d0SStefano Zampini 
2731872cf891SStefano Zampini       /* extract valid submatrix */
2732f03112d0SStefano Zampini       ierr = MatCreateSubMatrix(is->A,nzr,nzc,MAT_INITIAL_MATRIX,&newlA);CHKERRQ(ierr);
2733f03112d0SStefano Zampini 
2734f03112d0SStefano Zampini       /* attach local l2g maps for successive calls of MatSetValues on the local matrix */
2735f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(nzr,&l2g);CHKERRQ(ierr);
2736f03112d0SStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nr,0,1,&is1);CHKERRQ(ierr);
2737f03112d0SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_MASK,is1,&is2);CHKERRQ(ierr);
2738872cf891SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
273972ed36d8SStefano Zampini       if (is->A->rmap->mapping) { /* the matrix has a local-to-local map already attached (probably DMDA generated) */
274072ed36d8SStefano Zampini         const PetscInt *idxs1,*idxs2;
274172ed36d8SStefano Zampini         PetscInt       j,i,nl,*tidxs;
274272ed36d8SStefano Zampini 
274372ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(is->A->rmap->mapping,&nl);CHKERRQ(ierr);
274472ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(is->A->rmap->mapping,&idxs1);CHKERRQ(ierr);
274572ed36d8SStefano Zampini         ierr = PetscMalloc1(nl,&tidxs);CHKERRQ(ierr);
274672ed36d8SStefano Zampini         ierr = ISGetIndices(is2,&idxs2);CHKERRQ(ierr);
274772ed36d8SStefano Zampini         for (i=0,j=0;i<nl;i++) tidxs[i] = idxs1[i] < 0 ? -1 : idxs2[j++];
274872ed36d8SStefano Zampini         if (j != nr) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected count %D != %D",j,nr);
274972ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(is->A->rmap->mapping,&idxs1);CHKERRQ(ierr);
275072ed36d8SStefano Zampini         ierr = ISRestoreIndices(is2,&idxs2);CHKERRQ(ierr);
275172ed36d8SStefano Zampini         ierr = ISDestroy(&is2);CHKERRQ(ierr);
275272ed36d8SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is->A->rmap->mapping),nl,tidxs,PETSC_OWN_POINTER,&is2);CHKERRQ(ierr);
275372ed36d8SStefano Zampini       }
2754f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is2,&rl2g);CHKERRQ(ierr);
2755f03112d0SStefano Zampini       ierr = ISDestroy(&is1);CHKERRQ(ierr);
2756f03112d0SStefano Zampini       ierr = ISDestroy(&is2);CHKERRQ(ierr);
275772ed36d8SStefano Zampini 
2758f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(nzc,&l2g);CHKERRQ(ierr);
2759f03112d0SStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nc,0,1,&is1);CHKERRQ(ierr);
2760f03112d0SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_MASK,is1,&is2);CHKERRQ(ierr);
2761f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
276272ed36d8SStefano Zampini       if (is->A->cmap->mapping) { /* the matrix has a local-to-local map already attached (probably DMDA generated) */
276372ed36d8SStefano Zampini         const PetscInt *idxs1,*idxs2;
276472ed36d8SStefano Zampini         PetscInt       j,i,nl,*tidxs;
276572ed36d8SStefano Zampini 
276672ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(is->A->cmap->mapping,&nl);CHKERRQ(ierr);
276772ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(is->A->cmap->mapping,&idxs1);CHKERRQ(ierr);
276872ed36d8SStefano Zampini         ierr = PetscMalloc1(nl,&tidxs);CHKERRQ(ierr);
276972ed36d8SStefano Zampini         ierr = ISGetIndices(is2,&idxs2);CHKERRQ(ierr);
277072ed36d8SStefano Zampini         for (i=0,j=0;i<nl;i++) tidxs[i] = idxs1[i] < 0 ? -1 : idxs2[j++];
277172ed36d8SStefano Zampini         if (j != nc) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected count %D != %D",j,nc);
277272ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(is->A->cmap->mapping,&idxs1);CHKERRQ(ierr);
277372ed36d8SStefano Zampini         ierr = ISRestoreIndices(is2,&idxs2);CHKERRQ(ierr);
277472ed36d8SStefano Zampini         ierr = ISDestroy(&is2);CHKERRQ(ierr);
277572ed36d8SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is->A->cmap->mapping),nl,tidxs,PETSC_OWN_POINTER,&is2);CHKERRQ(ierr);
277672ed36d8SStefano Zampini       }
2777f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is2,&cl2g);CHKERRQ(ierr);
2778f03112d0SStefano Zampini       ierr = ISDestroy(&is1);CHKERRQ(ierr);
2779f03112d0SStefano Zampini       ierr = ISDestroy(&is2);CHKERRQ(ierr);
278072ed36d8SStefano Zampini 
2781f03112d0SStefano Zampini       ierr = MatSetLocalToGlobalMapping(newlA,rl2g,cl2g);CHKERRQ(ierr);
278272ed36d8SStefano Zampini 
2783f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2784f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2785f03112d0SStefano Zampini     } else { /* local matrix fully populated */
2786f03112d0SStefano Zampini       lnewl2g = PETSC_FALSE;
2787f03112d0SStefano Zampini       ierr    = MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
2788f03112d0SStefano Zampini       ierr    = PetscObjectReference((PetscObject)is->A);CHKERRQ(ierr);
2789f03112d0SStefano Zampini       newlA   = is->A;
2790f03112d0SStefano Zampini     }
2791f03112d0SStefano Zampini     /* attach new global l2g map if needed */
2792f03112d0SStefano Zampini     if (newl2g) {
2793f03112d0SStefano Zampini       IS             gnzr,gnzc;
2794f03112d0SStefano Zampini       const PetscInt *grid,*gcid;
2795f03112d0SStefano Zampini 
2796f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(A->rmap->mapping,nzr,&gnzr);CHKERRQ(ierr);
2797f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(A->cmap->mapping,nzc,&gnzc);CHKERRQ(ierr);
2798f03112d0SStefano Zampini       ierr = ISGetIndices(gnzr,&grid);CHKERRQ(ierr);
2799f03112d0SStefano Zampini       ierr = ISGetIndices(gnzc,&gcid);CHKERRQ(ierr);
2800f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nnzr,grid,PETSC_COPY_VALUES,&rl2g);CHKERRQ(ierr);
2801f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nnzc,gcid,PETSC_COPY_VALUES,&cl2g);CHKERRQ(ierr);
2802f03112d0SStefano Zampini       ierr = ISRestoreIndices(gnzr,&grid);CHKERRQ(ierr);
2803f03112d0SStefano Zampini       ierr = ISRestoreIndices(gnzc,&gcid);CHKERRQ(ierr);
2804f03112d0SStefano Zampini       ierr = ISDestroy(&gnzr);CHKERRQ(ierr);
2805f03112d0SStefano Zampini       ierr = ISDestroy(&gnzc);CHKERRQ(ierr);
2806f03112d0SStefano Zampini       ierr = MatSetLocalToGlobalMapping(A,rl2g,cl2g);CHKERRQ(ierr);
2807f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2808f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2809f03112d0SStefano Zampini     }
2810872cf891SStefano Zampini     ierr = MatISSetLocalMat(A,newlA);CHKERRQ(ierr);
2811872cf891SStefano Zampini     ierr = MatDestroy(&newlA);CHKERRQ(ierr);
2812f03112d0SStefano Zampini     ierr = ISDestroy(&nzr);CHKERRQ(ierr);
2813f03112d0SStefano Zampini     ierr = ISDestroy(&nzc);CHKERRQ(ierr);
2814872cf891SStefano Zampini     is->locempty = PETSC_FALSE;
2815f03112d0SStefano Zampini   }
2816b4319ba4SBarry Smith   PetscFunctionReturn(0);
2817b4319ba4SBarry Smith }
2818b4319ba4SBarry Smith 
2819a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
2820b4319ba4SBarry Smith {
2821b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
2822b4319ba4SBarry Smith 
2823b4319ba4SBarry Smith   PetscFunctionBegin;
2824b4319ba4SBarry Smith   *local = is->A;
2825b4319ba4SBarry Smith   PetscFunctionReturn(0);
2826b4319ba4SBarry Smith }
2827b4319ba4SBarry Smith 
28283b3b1effSJed Brown static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat,Mat *local)
28293b3b1effSJed Brown {
28303b3b1effSJed Brown   PetscFunctionBegin;
28313b3b1effSJed Brown   *local = NULL;
28323b3b1effSJed Brown   PetscFunctionReturn(0);
28333b3b1effSJed Brown }
28343b3b1effSJed Brown 
2835b4319ba4SBarry Smith /*@
2836b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
2837b4319ba4SBarry Smith 
2838b4319ba4SBarry Smith   Input Parameter:
2839b4319ba4SBarry Smith .  mat - the matrix
2840b4319ba4SBarry Smith 
2841b4319ba4SBarry Smith   Output Parameter:
2842eb82efa4SStefano Zampini .  local - the local matrix
2843b4319ba4SBarry Smith 
2844b4319ba4SBarry Smith   Level: advanced
2845b4319ba4SBarry Smith 
2846b4319ba4SBarry Smith   Notes:
2847b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
2848b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
2849b4319ba4SBarry Smith   of the MatSetValues() operation.
2850b4319ba4SBarry Smith 
28513b3b1effSJed Brown   Call MatISRestoreLocalMat() when finished with the local matrix.
285296a6f129SJed Brown 
2853b4319ba4SBarry Smith .seealso: MATIS
2854b4319ba4SBarry Smith @*/
28557087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
2856b4319ba4SBarry Smith {
28574ac538c5SBarry Smith   PetscErrorCode ierr;
2858b4319ba4SBarry Smith 
2859b4319ba4SBarry Smith   PetscFunctionBegin;
28600700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2861b4319ba4SBarry Smith   PetscValidPointer(local,2);
28624ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
2863b4319ba4SBarry Smith   PetscFunctionReturn(0);
2864b4319ba4SBarry Smith }
2865b4319ba4SBarry Smith 
28663b3b1effSJed Brown /*@
28673b3b1effSJed Brown     MatISRestoreLocalMat - Restores the local matrix obtained with MatISGetLocalMat()
28683b3b1effSJed Brown 
28693b3b1effSJed Brown   Input Parameter:
28703b3b1effSJed Brown .  mat - the matrix
28713b3b1effSJed Brown 
28723b3b1effSJed Brown   Output Parameter:
28733b3b1effSJed Brown .  local - the local matrix
28743b3b1effSJed Brown 
28753b3b1effSJed Brown   Level: advanced
28763b3b1effSJed Brown 
28773b3b1effSJed Brown .seealso: MATIS
28783b3b1effSJed Brown @*/
28793b3b1effSJed Brown PetscErrorCode MatISRestoreLocalMat(Mat mat,Mat *local)
28803b3b1effSJed Brown {
28813b3b1effSJed Brown   PetscErrorCode ierr;
28823b3b1effSJed Brown 
28833b3b1effSJed Brown   PetscFunctionBegin;
28843b3b1effSJed Brown   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
28853b3b1effSJed Brown   PetscValidPointer(local,2);
28863b3b1effSJed Brown   ierr = PetscUseMethod(mat,"MatISRestoreLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
28873b3b1effSJed Brown   PetscFunctionReturn(0);
28883b3b1effSJed Brown }
28893b3b1effSJed Brown 
28908546b261SStefano Zampini static PetscErrorCode MatISSetLocalMatType_IS(Mat mat,MatType mtype)
28918546b261SStefano Zampini {
28928546b261SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
28938546b261SStefano Zampini   PetscErrorCode ierr;
28948546b261SStefano Zampini 
28958546b261SStefano Zampini   PetscFunctionBegin;
28968546b261SStefano Zampini   if (is->A) {
28978546b261SStefano Zampini     ierr = MatSetType(is->A,mtype);CHKERRQ(ierr);
28988546b261SStefano Zampini   }
28998546b261SStefano Zampini   ierr = PetscFree(is->lmattype);CHKERRQ(ierr);
29008546b261SStefano Zampini   ierr = PetscStrallocpy(mtype,&is->lmattype);CHKERRQ(ierr);
29018546b261SStefano Zampini   PetscFunctionReturn(0);
29028546b261SStefano Zampini }
29038546b261SStefano Zampini 
29048546b261SStefano Zampini /*@
29058546b261SStefano Zampini     MatISSetLocalMatType - Specifies the type of local matrix
29068546b261SStefano Zampini 
29078546b261SStefano Zampini   Input Parameter:
29088546b261SStefano Zampini .  mat - the matrix
29098546b261SStefano Zampini .  mtype - the local matrix type
29108546b261SStefano Zampini 
29118546b261SStefano Zampini   Output Parameter:
29128546b261SStefano Zampini 
29138546b261SStefano Zampini   Level: advanced
29148546b261SStefano Zampini 
29158546b261SStefano Zampini .seealso: MATIS, MatSetType(), MatType
29168546b261SStefano Zampini @*/
29178546b261SStefano Zampini PetscErrorCode MatISSetLocalMatType(Mat mat,MatType mtype)
29188546b261SStefano Zampini {
29198546b261SStefano Zampini   PetscErrorCode ierr;
29208546b261SStefano Zampini 
29218546b261SStefano Zampini   PetscFunctionBegin;
29228546b261SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
29238546b261SStefano Zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMatType_C",(Mat,MatType),(mat,mtype));CHKERRQ(ierr);
29248546b261SStefano Zampini   PetscFunctionReturn(0);
29258546b261SStefano Zampini }
29268546b261SStefano Zampini 
2927a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
29283b03a366Sstefano_zampini {
29293b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
29303b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
29313b03a366Sstefano_zampini   PetscErrorCode ierr;
29328546b261SStefano Zampini   MatType        mtype,otype;
29338546b261SStefano Zampini   PetscBool      sametype = PETSC_TRUE;
29343b03a366Sstefano_zampini 
29353b03a366Sstefano_zampini   PetscFunctionBegin;
29364e4c7dbeSStefano Zampini   if (is->A) {
29373b03a366Sstefano_zampini     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
29383b03a366Sstefano_zampini     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
2939f0ae7da4SStefano Zampini     if (orows != nrows || ocols != ncols) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local MATIS matrix should be of size %Dx%D (you passed a %Dx%D matrix)",orows,ocols,nrows,ncols);
29408546b261SStefano Zampini     ierr = MatGetType(local,&mtype);CHKERRQ(ierr);
29418546b261SStefano Zampini     ierr = MatGetType(is->A,&otype);CHKERRQ(ierr);
29428546b261SStefano Zampini     ierr = PetscStrcmp(mtype,otype,&sametype);CHKERRQ(ierr);
29434e4c7dbeSStefano Zampini   }
29443b03a366Sstefano_zampini   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
29453b03a366Sstefano_zampini   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
29463b03a366Sstefano_zampini   is->A = local;
29478546b261SStefano Zampini   ierr  = MatGetType(is->A,&mtype);CHKERRQ(ierr);
29488546b261SStefano Zampini   ierr  = MatISSetLocalMatType(mat,mtype);CHKERRQ(ierr);
29498546b261SStefano Zampini   if (!sametype && !is->islocalref) {
29508546b261SStefano Zampini     ierr = MatISSetUpScatters_Private(mat);CHKERRQ(ierr);
29518546b261SStefano Zampini   }
29523b03a366Sstefano_zampini   PetscFunctionReturn(0);
29533b03a366Sstefano_zampini }
29543b03a366Sstefano_zampini 
29553b03a366Sstefano_zampini /*@
2956eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
29573b03a366Sstefano_zampini 
29588546b261SStefano Zampini   Collective on Mat
29598546b261SStefano Zampini 
29603b03a366Sstefano_zampini   Input Parameter:
29613b03a366Sstefano_zampini .  mat - the matrix
2962eb82efa4SStefano Zampini .  local - the local matrix
29633b03a366Sstefano_zampini 
29643b03a366Sstefano_zampini   Output Parameter:
29653b03a366Sstefano_zampini 
29663b03a366Sstefano_zampini   Level: advanced
29673b03a366Sstefano_zampini 
29683b03a366Sstefano_zampini   Notes:
29693b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
29703b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
29713b03a366Sstefano_zampini 
29723b03a366Sstefano_zampini .seealso: MATIS
29733b03a366Sstefano_zampini @*/
29743b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
29753b03a366Sstefano_zampini {
29763b03a366Sstefano_zampini   PetscErrorCode ierr;
29773b03a366Sstefano_zampini 
29783b03a366Sstefano_zampini   PetscFunctionBegin;
29793b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2980b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
29813b03a366Sstefano_zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
29823b03a366Sstefano_zampini   PetscFunctionReturn(0);
29833b03a366Sstefano_zampini }
29843b03a366Sstefano_zampini 
2985a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
29866726f965SBarry Smith {
29876726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
29886726f965SBarry Smith   PetscErrorCode ierr;
29896726f965SBarry Smith 
29906726f965SBarry Smith   PetscFunctionBegin;
29916726f965SBarry Smith   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
29926726f965SBarry Smith   PetscFunctionReturn(0);
29936726f965SBarry Smith }
29946726f965SBarry Smith 
2995a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
29962e74eeadSLisandro Dalcin {
29972e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
29982e74eeadSLisandro Dalcin   PetscErrorCode ierr;
29992e74eeadSLisandro Dalcin 
30002e74eeadSLisandro Dalcin   PetscFunctionBegin;
30012e74eeadSLisandro Dalcin   ierr = MatScale(is->A,a);CHKERRQ(ierr);
30022e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
30032e74eeadSLisandro Dalcin }
30042e74eeadSLisandro Dalcin 
3005a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
30062e74eeadSLisandro Dalcin {
30072e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
30082e74eeadSLisandro Dalcin   PetscErrorCode ierr;
30092e74eeadSLisandro Dalcin 
30102e74eeadSLisandro Dalcin   PetscFunctionBegin;
30112e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
3012e176bc59SStefano Zampini   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
30132e74eeadSLisandro Dalcin 
30142e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
30152e74eeadSLisandro Dalcin   ierr = VecSet(v,0);CHKERRQ(ierr);
3016e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3017e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
30182e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
30192e74eeadSLisandro Dalcin }
30202e74eeadSLisandro Dalcin 
3021a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
30226726f965SBarry Smith {
30236726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
30246726f965SBarry Smith   PetscErrorCode ierr;
30256726f965SBarry Smith 
30266726f965SBarry Smith   PetscFunctionBegin;
30274e0d8c25SBarry Smith   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
30286726f965SBarry Smith   PetscFunctionReturn(0);
30296726f965SBarry Smith }
30306726f965SBarry Smith 
3031f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
3032f26d0771SStefano Zampini {
3033f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
3034f26d0771SStefano Zampini   Mat_IS         *x;
3035f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
3036f26d0771SStefano Zampini   PetscBool      ismatis;
3037f26d0771SStefano Zampini #endif
3038f26d0771SStefano Zampini   PetscErrorCode ierr;
3039f26d0771SStefano Zampini 
3040f26d0771SStefano Zampini   PetscFunctionBegin;
3041f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
3042f26d0771SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
3043f26d0771SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
3044f26d0771SStefano Zampini #endif
3045f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
3046f26d0771SStefano Zampini   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
3047f26d0771SStefano Zampini   PetscFunctionReturn(0);
3048f26d0771SStefano Zampini }
3049f26d0771SStefano Zampini 
3050f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
3051f26d0771SStefano Zampini {
3052f26d0771SStefano Zampini   Mat                    lA;
3053f26d0771SStefano Zampini   Mat_IS                 *matis;
3054f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
3055f26d0771SStefano Zampini   IS                     is;
3056f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
3057f26d0771SStefano Zampini   PetscInt               nrg;
3058f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
3059f26d0771SStefano Zampini   PetscErrorCode         ierr;
3060f26d0771SStefano Zampini 
3061f26d0771SStefano Zampini   PetscFunctionBegin;
3062f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
3063f26d0771SStefano Zampini   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
3064f26d0771SStefano Zampini   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
3065f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
3066f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
3067249c8a71SStefano Zampini   for (i=0;i<nrl;i++) if (rl[i]>=nrg) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row index %D -> %D greater then maximum possible %D",i,rl[i],nrg);
3068f26d0771SStefano Zampini #endif
3069f26d0771SStefano Zampini   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
3070f26d0771SStefano Zampini   /* map from [0,nrl) to row */
3071f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
3072f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
3073f26d0771SStefano Zampini   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
3074f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
3075f26d0771SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
3076f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
3077f26d0771SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
3078f26d0771SStefano Zampini   /* compute new l2g map for columns */
3079f26d0771SStefano Zampini   if (col != row || A->rmap->mapping != A->cmap->mapping) {
3080f26d0771SStefano Zampini     const PetscInt *cg,*cl;
3081f26d0771SStefano Zampini     PetscInt       ncg;
3082f26d0771SStefano Zampini     PetscInt       ncl;
3083f26d0771SStefano Zampini 
3084f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
3085f26d0771SStefano Zampini     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
3086f26d0771SStefano Zampini     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
3087f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
3088f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
3089249c8a71SStefano Zampini     for (i=0;i<ncl;i++) if (cl[i]>=ncg) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local column index %D -> %D greater then maximum possible %D",i,cl[i],ncg);
3090f26d0771SStefano Zampini #endif
3091f26d0771SStefano Zampini     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
3092f26d0771SStefano Zampini     /* map from [0,ncl) to col */
3093f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
3094f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
3095f26d0771SStefano Zampini     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
3096f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
3097f26d0771SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
3098f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
3099f26d0771SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
3100f26d0771SStefano Zampini   } else {
3101f26d0771SStefano Zampini     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
3102f26d0771SStefano Zampini     cl2g = rl2g;
3103f26d0771SStefano Zampini   }
3104f26d0771SStefano Zampini   /* create the MATIS submatrix */
3105f26d0771SStefano Zampini   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
3106f26d0771SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
3107f26d0771SStefano Zampini   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
3108f26d0771SStefano Zampini   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
3109b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
3110f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
3111f26d0771SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
3112f26d0771SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
3113f26d0771SStefano Zampini   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
3114f26d0771SStefano Zampini   ierr = MatSetUp(*submat);CHKERRQ(ierr);
3115f26d0771SStefano Zampini   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3116f26d0771SStefano Zampini   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3117f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
3118f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
3119f26d0771SStefano Zampini   /* remove unsupported ops */
3120f26d0771SStefano Zampini   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
3121f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
3122f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
3123f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
3124f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
3125f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
3126f26d0771SStefano Zampini   PetscFunctionReturn(0);
3127f26d0771SStefano Zampini }
3128f26d0771SStefano Zampini 
3129872cf891SStefano Zampini static PetscErrorCode MatSetFromOptions_IS(PetscOptionItems *PetscOptionsObject, Mat A)
3130872cf891SStefano Zampini {
3131872cf891SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
31328546b261SStefano Zampini   char           type[256];
31338546b261SStefano Zampini   PetscBool      flg;
3134872cf891SStefano Zampini   PetscErrorCode ierr;
3135872cf891SStefano Zampini 
3136872cf891SStefano Zampini   PetscFunctionBegin;
3137872cf891SStefano Zampini   ierr = PetscOptionsHead(PetscOptionsObject,"MATIS options");CHKERRQ(ierr);
3138f03112d0SStefano Zampini   ierr = PetscOptionsBool("-matis_fixempty","Fix local matrices in case of empty local rows/columns","MatISFixLocalEmpty",a->locempty,&a->locempty,NULL);CHKERRQ(ierr);
313975d48cdbSStefano Zampini   ierr = PetscOptionsBool("-matis_storel2l","Store local-to-local matrices generated from PtAP operations","MatISStoreL2L",a->storel2l,&a->storel2l,NULL);CHKERRQ(ierr);
31408546b261SStefano Zampini   ierr = PetscOptionsFList("-matis_localmat_type","Matrix type","MatISSetLocalMatType",MatList,a->lmattype,type,256,&flg);CHKERRQ(ierr);
31418546b261SStefano Zampini   if (flg) {
31428546b261SStefano Zampini     ierr = MatISSetLocalMatType(A,type);CHKERRQ(ierr);
31438546b261SStefano Zampini   }
31448546b261SStefano Zampini   if (a->A) {
31458546b261SStefano Zampini     ierr = MatSetFromOptions(a->A);CHKERRQ(ierr);
31468546b261SStefano Zampini   }
31470af67c1bSStefano Zampini   ierr = PetscOptionsTail();CHKERRQ(ierr);
3148872cf891SStefano Zampini   PetscFunctionReturn(0);
3149872cf891SStefano Zampini }
3150872cf891SStefano Zampini 
3151284134d9SBarry Smith /*@
31523c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
3153284134d9SBarry Smith        process but not across processes.
3154284134d9SBarry Smith 
3155284134d9SBarry Smith    Input Parameters:
3156284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
3157e176bc59SStefano Zampini .     bs      - block size of the matrix
3158df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
3159e176bc59SStefano Zampini .     rmap    - local to global map for rows
3160e176bc59SStefano Zampini -     cmap    - local to global map for cols
3161284134d9SBarry Smith 
3162284134d9SBarry Smith    Output Parameter:
3163284134d9SBarry Smith .    A - the resulting matrix
3164284134d9SBarry Smith 
31658e6c10adSSatish Balay    Level: advanced
31668e6c10adSSatish Balay 
316795452b02SPatrick Sanan    Notes:
316895452b02SPatrick Sanan     See MATIS for more details.
31696fdf41d1SStefano Zampini           m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors
31706fdf41d1SStefano Zampini           used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
31713c212e90SHong Zhang           If either rmap or cmap are NULL, then the matrix is assumed to be square.
3172284134d9SBarry Smith 
3173284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
3174284134d9SBarry Smith @*/
3175e176bc59SStefano Zampini PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
3176284134d9SBarry Smith {
3177284134d9SBarry Smith   PetscErrorCode ierr;
3178284134d9SBarry Smith 
3179284134d9SBarry Smith   PetscFunctionBegin;
31806fdf41d1SStefano Zampini   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings");
3181284134d9SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
3182284134d9SBarry Smith   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
31836fdf41d1SStefano Zampini   if (bs > 0) {
3184284134d9SBarry Smith     ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
31856fdf41d1SStefano Zampini   }
3186284134d9SBarry Smith   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
3187e176bc59SStefano Zampini   if (rmap && cmap) {
3188e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
3189e176bc59SStefano Zampini   } else if (!rmap) {
3190e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
3191e176bc59SStefano Zampini   } else {
3192e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
3193e176bc59SStefano Zampini   }
3194284134d9SBarry Smith   PetscFunctionReturn(0);
3195284134d9SBarry Smith }
3196284134d9SBarry Smith 
3197b4319ba4SBarry Smith /*MC
3198f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
3199b89f26deSStefano Zampini    This stores the matrices in globally unassembled form. Each processor assembles only its local Neumann problem and the parallel matrix vector
3200b4319ba4SBarry Smith    product is handled "implicitly".
3201b4319ba4SBarry Smith 
3202b4319ba4SBarry Smith    Options Database Keys:
320375d48cdbSStefano Zampini + -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
320475d48cdbSStefano Zampini . -matis_fixempty - Fixes local matrices in case of empty local rows/columns.
320575d48cdbSStefano Zampini - -matis_storel2l - stores the local-to-local operators generated by the Galerkin process of MatPtAP().
3206b4319ba4SBarry Smith 
320795452b02SPatrick Sanan    Notes:
320895452b02SPatrick Sanan     Options prefix for the inner matrix are given by -is_mat_xxx
3209b4319ba4SBarry Smith 
3210b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
3211b4319ba4SBarry Smith 
3212b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
3213eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
3214b4319ba4SBarry Smith 
3215b4319ba4SBarry Smith   Level: advanced
3216b4319ba4SBarry Smith 
3217f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
3218b4319ba4SBarry Smith 
3219b4319ba4SBarry Smith M*/
3220b4319ba4SBarry Smith 
32218cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
3222b4319ba4SBarry Smith {
3223dfbe8321SBarry Smith   PetscErrorCode ierr;
3224b4319ba4SBarry Smith   Mat_IS         *b;
3225b4319ba4SBarry Smith 
3226b4319ba4SBarry Smith   PetscFunctionBegin;
3227b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
32288546b261SStefano Zampini   ierr    = PetscStrallocpy(MATAIJ,&b->lmattype);CHKERRQ(ierr);
3229b4319ba4SBarry Smith   A->data = (void*)b;
3230b4319ba4SBarry Smith 
3231e176bc59SStefano Zampini   /* matrix ops */
3232e176bc59SStefano Zampini   ierr = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
3233b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
32342e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
32352e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
32362e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
3237b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
3238b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
32392e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
324098921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
3241b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
3242f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
32432e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
3244f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
3245b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
3246b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
3247b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
32486726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
32492e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
32502e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
32516726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
325269796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
325369796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
325445471136SStefano Zampini   A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS;
3255ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
32566bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
32572b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
3258659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
32597dae84e0SHong Zhang   A->ops->createsubmatrix         = MatCreateSubMatrix_IS;
3260f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
32613fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
32623fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
3263d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
32647fa8f2d3SStefano Zampini   A->ops->getinfo                 = MatGetInfo_IS;
3265ad219c80Sstefano_zampini   A->ops->diagonalscale           = MatDiagonalScale_IS;
3266872cf891SStefano Zampini   A->ops->setfromoptions          = MatSetFromOptions_IS;
3267b4319ba4SBarry Smith 
3268b7ce53b6SStefano Zampini   /* special MATIS functions */
32698546b261SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMatType_C",MatISSetLocalMatType_IS);CHKERRQ(ierr);
3270bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
32713b3b1effSJed Brown   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISRestoreLocalMat_C",MatISRestoreLocalMat_IS);CHKERRQ(ierr);
3272bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
3273487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
32742e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
327575d48cdbSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",MatISStoreL2L_IS);CHKERRQ(ierr);
3276f03112d0SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",MatISFixLocalEmpty_IS);CHKERRQ(ierr);
3277487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3278487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3279487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3280487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3281487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3282487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3283487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
328417667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
3285b4319ba4SBarry Smith   PetscFunctionReturn(0);
3286b4319ba4SBarry Smith }
3287