xref: /petsc/src/mat/impls/is/matis.c (revision 28b400f66ebc7ae0049166a2294dfcd3df27e64b)
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>
12a72d46e8SStefano Zampini #include <petsc/private/vecimpl.h>
13e432b41dSStefano Zampini #include <petsc/private/hashseti.h>
1428f4e0baSStefano Zampini 
15f26d0771SStefano Zampini #define MATIS_MAX_ENTRIES_INSERTION 2048
16b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat,PetscInt,const PetscInt*,PetscInt,const PetscInt*,const PetscScalar*,InsertMode);
17b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat,PetscInt,const PetscInt*,PetscInt,const PetscInt*,const PetscScalar*,InsertMode);
188546b261SStefano Zampini static PetscErrorCode MatISSetUpScatters_Private(Mat);
19f26d0771SStefano Zampini 
2075d48cdbSStefano Zampini static PetscErrorCode MatISContainerDestroyPtAP_Private(void *ptr)
2175d48cdbSStefano Zampini {
2275d48cdbSStefano Zampini   MatISPtAP      ptap = (MatISPtAP)ptr;
2375d48cdbSStefano Zampini 
2475d48cdbSStefano Zampini   PetscFunctionBegin;
255f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroySubMatrices(ptap->ris1 ? 2 : 1,&ptap->lP));
265f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&ptap->cis0));
275f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&ptap->cis1));
285f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&ptap->ris0));
295f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&ptap->ris1));
305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(ptap));
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 
4475d48cdbSStefano Zampini   PetscFunctionBegin;
455f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectQuery((PetscObject)C,"_MatIS_PtAP",(PetscObject*)&c));
46*28b400f6SJacob Faibussowitsch   PetscCheck(c,PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing PtAP information");
475f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscContainerGetPointer(c,(void**)&ptap));
4875d48cdbSStefano Zampini   ris[0] = ptap->ris0;
4975d48cdbSStefano Zampini   ris[1] = ptap->ris1;
5075d48cdbSStefano Zampini   cis[0] = ptap->cis0;
5175d48cdbSStefano Zampini   cis[1] = ptap->cis1;
5275d48cdbSStefano Zampini   n      = ptap->ris1 ? 2 : 1;
5375d48cdbSStefano Zampini   reuse  = ptap->lP ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX;
545f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreateSubMatrices(P,n,ris,cis,reuse,&ptap->lP));
5575d48cdbSStefano Zampini 
565f80ce2aSJacob Faibussowitsch   CHKERRQ(MatISGetLocalMat(A,&lA));
575f80ce2aSJacob Faibussowitsch   CHKERRQ(MatISGetLocalMat(C,&lC));
5875d48cdbSStefano Zampini   if (ptap->ris1) { /* unsymmetric A mapping */
5975d48cdbSStefano Zampini     Mat lPt;
6075d48cdbSStefano Zampini 
615f80ce2aSJacob Faibussowitsch     CHKERRQ(MatTranspose(ptap->lP[1],MAT_INITIAL_MATRIX,&lPt));
625f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMatMatMult(lPt,lA,ptap->lP[0],reuse,ptap->fill,&lC));
6375d48cdbSStefano Zampini     if (matis->storel2l) {
645f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",(PetscObject)lPt));
6575d48cdbSStefano Zampini     }
665f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroy(&lPt));
6775d48cdbSStefano Zampini   } else {
685f80ce2aSJacob Faibussowitsch     CHKERRQ(MatPtAP(lA,ptap->lP[0],reuse,ptap->fill,&lC));
6975d48cdbSStefano Zampini     if (matis->storel2l) {
705f80ce2aSJacob Faibussowitsch      CHKERRQ(PetscObjectCompose((PetscObject)C,"_MatIS_PtAP_l2l",(PetscObject)ptap->lP[0]));
7175d48cdbSStefano Zampini     }
7275d48cdbSStefano Zampini   }
7375d48cdbSStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
745f80ce2aSJacob Faibussowitsch     CHKERRQ(MatISSetLocalMat(C,lC));
755f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroy(&lC));
7675d48cdbSStefano Zampini   }
775f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY));
785f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY));
7975d48cdbSStefano Zampini   PetscFunctionReturn(0);
8075d48cdbSStefano Zampini }
8175d48cdbSStefano Zampini 
8275d48cdbSStefano Zampini static PetscErrorCode MatGetNonzeroColumnsLocal_Private(Mat PT,IS *cis)
8375d48cdbSStefano Zampini {
8475d48cdbSStefano Zampini   Mat            Po,Pd;
8575d48cdbSStefano Zampini   IS             zd,zo;
8675d48cdbSStefano Zampini   const PetscInt *garray;
8775d48cdbSStefano Zampini   PetscInt       *aux,i,bs;
8875d48cdbSStefano Zampini   PetscInt       dc,stc,oc,ctd,cto;
8975d48cdbSStefano Zampini   PetscBool      ismpiaij,ismpibaij,isseqaij,isseqbaij;
9075d48cdbSStefano Zampini   MPI_Comm       comm;
9175d48cdbSStefano Zampini 
9275d48cdbSStefano Zampini   PetscFunctionBegin;
9375d48cdbSStefano Zampini   PetscValidHeaderSpecific(PT,MAT_CLASSID,1);
9475d48cdbSStefano Zampini   PetscValidPointer(cis,2);
955f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)PT,&comm));
9675d48cdbSStefano Zampini   bs   = 1;
975f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectBaseTypeCompare((PetscObject)PT,MATMPIAIJ,&ismpiaij));
985f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectBaseTypeCompare((PetscObject)PT,MATMPIBAIJ,&ismpibaij));
995f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectBaseTypeCompare((PetscObject)PT,MATSEQAIJ,&isseqaij));
1005f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)PT,MATSEQBAIJ,&isseqbaij));
10175d48cdbSStefano Zampini   if (isseqaij || isseqbaij) {
10275d48cdbSStefano Zampini     Pd = PT;
10375d48cdbSStefano Zampini     Po = NULL;
10475d48cdbSStefano Zampini     garray = NULL;
10575d48cdbSStefano Zampini   } else if (ismpiaij) {
1065f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMPIAIJGetSeqAIJ(PT,&Pd,&Po,&garray));
10775d48cdbSStefano Zampini   } else if (ismpibaij) {
1085f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMPIBAIJGetSeqBAIJ(PT,&Pd,&Po,&garray));
1095f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetBlockSize(PT,&bs));
11098921bdaSJacob Faibussowitsch   } else SETERRQ(comm,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(PT))->type_name);
11175d48cdbSStefano Zampini 
11275d48cdbSStefano Zampini   /* identify any null columns in Pd or Po */
11322f7620eSStefano Zampini   /* We use a tolerance comparison since it may happen that, with geometric multigrid,
11422f7620eSStefano Zampini      some of the columns are not really zero, but very close to */
11575d48cdbSStefano Zampini   zo = zd = NULL;
11675d48cdbSStefano Zampini   if (Po) {
1175f80ce2aSJacob Faibussowitsch     CHKERRQ(MatFindNonzeroRowsOrCols_Basic(Po,PETSC_TRUE,PETSC_SMALL,&zo));
11875d48cdbSStefano Zampini   }
1195f80ce2aSJacob Faibussowitsch   CHKERRQ(MatFindNonzeroRowsOrCols_Basic(Pd,PETSC_TRUE,PETSC_SMALL,&zd));
12075d48cdbSStefano Zampini 
1215f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetLocalSize(PT,NULL,&dc));
1225f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetOwnershipRangeColumn(PT,&stc,NULL));
1235f80ce2aSJacob Faibussowitsch   if (Po) CHKERRQ(MatGetLocalSize(Po,NULL,&oc));
12475d48cdbSStefano Zampini   else oc = 0;
1255f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1((dc+oc)/bs,&aux));
12675d48cdbSStefano Zampini   if (zd) {
12775d48cdbSStefano Zampini     const PetscInt *idxs;
12875d48cdbSStefano Zampini     PetscInt       nz;
12975d48cdbSStefano Zampini 
13075d48cdbSStefano Zampini     /* this will throw an error if bs is not valid */
1315f80ce2aSJacob Faibussowitsch     CHKERRQ(ISSetBlockSize(zd,bs));
1325f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetLocalSize(zd,&nz));
1335f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(zd,&idxs));
13475d48cdbSStefano Zampini     ctd  = nz/bs;
13575d48cdbSStefano Zampini     for (i=0; i<ctd; i++) aux[i] = (idxs[bs*i]+stc)/bs;
1365f80ce2aSJacob Faibussowitsch     CHKERRQ(ISRestoreIndices(zd,&idxs));
13775d48cdbSStefano Zampini   } else {
13875d48cdbSStefano Zampini     ctd = dc/bs;
13975d48cdbSStefano Zampini     for (i=0; i<ctd; i++) aux[i] = i+stc/bs;
14075d48cdbSStefano Zampini   }
14175d48cdbSStefano Zampini   if (zo) {
14275d48cdbSStefano Zampini     const PetscInt *idxs;
14375d48cdbSStefano Zampini     PetscInt       nz;
14475d48cdbSStefano Zampini 
14575d48cdbSStefano Zampini     /* this will throw an error if bs is not valid */
1465f80ce2aSJacob Faibussowitsch     CHKERRQ(ISSetBlockSize(zo,bs));
1475f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetLocalSize(zo,&nz));
1485f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(zo,&idxs));
14975d48cdbSStefano Zampini     cto  = nz/bs;
15075d48cdbSStefano Zampini     for (i=0; i<cto; i++) aux[i+ctd] = garray[idxs[bs*i]/bs];
1515f80ce2aSJacob Faibussowitsch     CHKERRQ(ISRestoreIndices(zo,&idxs));
15275d48cdbSStefano Zampini   } else {
15375d48cdbSStefano Zampini     cto = oc/bs;
15475d48cdbSStefano Zampini     for (i=0; i<cto; i++) aux[i+ctd] = garray[i];
15575d48cdbSStefano Zampini   }
1565f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateBlock(comm,bs,ctd+cto,aux,PETSC_OWN_POINTER,cis));
1575f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&zd));
1585f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&zo));
15975d48cdbSStefano Zampini   PetscFunctionReturn(0);
16075d48cdbSStefano Zampini }
16175d48cdbSStefano Zampini 
1624222ddf1SHong Zhang static PetscErrorCode MatPtAPSymbolic_IS_XAIJ(Mat A,Mat P,PetscReal fill,Mat C)
16375d48cdbSStefano Zampini {
1648546b261SStefano Zampini   Mat                    PT,lA;
16575d48cdbSStefano Zampini   MatISPtAP              ptap;
16675d48cdbSStefano Zampini   ISLocalToGlobalMapping Crl2g,Ccl2g,rl2g,cl2g;
16775d48cdbSStefano Zampini   PetscContainer         c;
1688546b261SStefano Zampini   MatType                lmtype;
16975d48cdbSStefano Zampini   const PetscInt         *garray;
17075d48cdbSStefano Zampini   PetscInt               ibs,N,dc;
17175d48cdbSStefano Zampini   MPI_Comm               comm;
17275d48cdbSStefano Zampini 
17375d48cdbSStefano Zampini   PetscFunctionBegin;
1745f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)A,&comm));
1755f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetType(C,MATIS));
1765f80ce2aSJacob Faibussowitsch   CHKERRQ(MatISGetLocalMat(A,&lA));
1775f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetType(lA,&lmtype));
1785f80ce2aSJacob Faibussowitsch   CHKERRQ(MatISSetLocalMatType(C,lmtype));
1795f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetSize(P,NULL,&N));
1805f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetLocalSize(P,NULL,&dc));
1815f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSizes(C,dc,dc,N,N));
18275d48cdbSStefano Zampini /* Not sure about this
1835f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetBlockSizes(P,NULL,&ibs));
1845f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetBlockSize(*C,ibs));
18575d48cdbSStefano Zampini */
18675d48cdbSStefano Zampini 
1875f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscNew(&ptap));
1885f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscContainerCreate(PETSC_COMM_SELF,&c));
1895f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscContainerSetPointer(c,ptap));
1905f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscContainerSetUserDestroy(c,MatISContainerDestroyPtAP_Private));
1915f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectCompose((PetscObject)C,"_MatIS_PtAP",(PetscObject)c));
1925f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscContainerDestroy(&c));
19375d48cdbSStefano Zampini   ptap->fill = fill;
19475d48cdbSStefano Zampini 
1955f80ce2aSJacob Faibussowitsch   CHKERRQ(MatISGetLocalToGlobalMapping(A,&rl2g,&cl2g));
19675d48cdbSStefano Zampini 
1975f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetBlockSize(cl2g,&ibs));
1985f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetSize(cl2g,&N));
1995f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetBlockIndices(cl2g,&garray));
2005f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateBlock(comm,ibs,N/ibs,garray,PETSC_COPY_VALUES,&ptap->ris0));
2015f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingRestoreBlockIndices(cl2g,&garray));
20275d48cdbSStefano Zampini 
2035f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreateSubMatrix(P,ptap->ris0,NULL,MAT_INITIAL_MATRIX,&PT));
2045f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetNonzeroColumnsLocal_Private(PT,&ptap->cis0));
2055f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingCreateIS(ptap->cis0,&Ccl2g));
2065f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&PT));
20775d48cdbSStefano Zampini 
20875d48cdbSStefano Zampini   Crl2g = NULL;
20975d48cdbSStefano Zampini   if (rl2g != cl2g) { /* unsymmetric A mapping */
21075d48cdbSStefano Zampini     PetscBool same,lsame = PETSC_FALSE;
21175d48cdbSStefano Zampini     PetscInt  N1,ibs1;
21275d48cdbSStefano Zampini 
2135f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingGetSize(rl2g,&N1));
2145f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingGetBlockSize(rl2g,&ibs1));
2155f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingGetBlockIndices(rl2g,&garray));
2165f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateBlock(comm,ibs,N/ibs,garray,PETSC_COPY_VALUES,&ptap->ris1));
2175f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingRestoreBlockIndices(rl2g,&garray));
21875d48cdbSStefano Zampini     if (ibs1 == ibs && N1 == N) { /* check if the l2gmaps are the same */
21975d48cdbSStefano Zampini       const PetscInt *i1,*i2;
22075d48cdbSStefano Zampini 
2215f80ce2aSJacob Faibussowitsch       CHKERRQ(ISBlockGetIndices(ptap->ris0,&i1));
2225f80ce2aSJacob Faibussowitsch       CHKERRQ(ISBlockGetIndices(ptap->ris1,&i2));
2235f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArraycmp(i1,i2,N,&lsame));
22475d48cdbSStefano Zampini     }
2255f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPIU_Allreduce(&lsame,&same,1,MPIU_BOOL,MPI_LAND,comm));
22675d48cdbSStefano Zampini     if (same) {
2275f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&ptap->ris1));
22875d48cdbSStefano Zampini     } else {
2295f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreateSubMatrix(P,ptap->ris1,NULL,MAT_INITIAL_MATRIX,&PT));
2305f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetNonzeroColumnsLocal_Private(PT,&ptap->cis1));
2315f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingCreateIS(ptap->cis1,&Crl2g));
2325f80ce2aSJacob Faibussowitsch       CHKERRQ(MatDestroy(&PT));
23375d48cdbSStefano Zampini     }
23475d48cdbSStefano Zampini   }
23575d48cdbSStefano Zampini /* Not sure about this
23675d48cdbSStefano Zampini   if (!Crl2g) {
2375f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetBlockSize(C,&ibs));
2385f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingSetBlockSize(Ccl2g,ibs));
23975d48cdbSStefano Zampini   }
24075d48cdbSStefano Zampini */
2415f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetLocalToGlobalMapping(C,Crl2g ? Crl2g : Ccl2g,Ccl2g));
2425f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingDestroy(&Crl2g));
2435f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingDestroy(&Ccl2g));
24475d48cdbSStefano Zampini 
2454222ddf1SHong Zhang   C->ops->ptapnumeric = MatPtAPNumeric_IS_XAIJ;
24675d48cdbSStefano Zampini   PetscFunctionReturn(0);
24775d48cdbSStefano Zampini }
24875d48cdbSStefano Zampini 
2494222ddf1SHong Zhang /* ----------------------------------------- */
2504222ddf1SHong Zhang static PetscErrorCode MatProductSymbolic_PtAP_IS_XAIJ(Mat C)
25175d48cdbSStefano Zampini {
2524222ddf1SHong Zhang   Mat_Product    *product = C->product;
2534222ddf1SHong Zhang   Mat            A=product->A,P=product->B;
2544222ddf1SHong Zhang   PetscReal      fill=product->fill;
25575d48cdbSStefano Zampini 
25675d48cdbSStefano Zampini   PetscFunctionBegin;
2575f80ce2aSJacob Faibussowitsch   CHKERRQ(MatPtAPSymbolic_IS_XAIJ(A,P,fill,C));
2584222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
25975d48cdbSStefano Zampini   PetscFunctionReturn(0);
26075d48cdbSStefano Zampini }
26175d48cdbSStefano Zampini 
2624222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_IS_XAIJ_PtAP(Mat C)
2634222ddf1SHong Zhang {
2644222ddf1SHong Zhang   PetscFunctionBegin;
2654222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_PtAP_IS_XAIJ;
2664222ddf1SHong Zhang   PetscFunctionReturn(0);
2674222ddf1SHong Zhang }
2684222ddf1SHong Zhang 
2694222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat C)
2704222ddf1SHong Zhang {
2714222ddf1SHong Zhang   Mat_Product    *product = C->product;
2724222ddf1SHong Zhang 
2734222ddf1SHong Zhang   PetscFunctionBegin;
2744222ddf1SHong Zhang   if (product->type == MATPRODUCT_PtAP) {
2755f80ce2aSJacob Faibussowitsch     CHKERRQ(MatProductSetFromOptions_IS_XAIJ_PtAP(C));
2766718818eSStefano Zampini   }
2774222ddf1SHong Zhang   PetscFunctionReturn(0);
2784222ddf1SHong Zhang }
2794222ddf1SHong Zhang 
2804222ddf1SHong Zhang /* ----------------------------------------- */
2815b003df0Sstefano_zampini static PetscErrorCode MatISContainerDestroyFields_Private(void *ptr)
2825b003df0Sstefano_zampini {
2835b003df0Sstefano_zampini   MatISLocalFields lf = (MatISLocalFields)ptr;
2845b003df0Sstefano_zampini   PetscInt         i;
2855b003df0Sstefano_zampini 
286ab4d48faSStefano Zampini   PetscFunctionBegin;
2875b003df0Sstefano_zampini   for (i=0;i<lf->nr;i++) {
2885f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&lf->rf[i]));
2895b003df0Sstefano_zampini   }
2905b003df0Sstefano_zampini   for (i=0;i<lf->nc;i++) {
2915f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&lf->cf[i]));
2925b003df0Sstefano_zampini   }
2935f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree2(lf->rf,lf->cf));
2945f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(lf));
2955b003df0Sstefano_zampini   PetscFunctionReturn(0);
2965b003df0Sstefano_zampini }
297a72627d2SStefano Zampini 
298c9225affSStefano Zampini static PetscErrorCode MatConvert_SeqXAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
2996989cf23SStefano Zampini {
300c9225affSStefano Zampini   Mat            B,lB;
301c9225affSStefano Zampini 
302c9225affSStefano Zampini   PetscFunctionBegin;
303c9225affSStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
304c9225affSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g;
305c9225affSStefano Zampini     PetscInt               bs;
306c9225affSStefano Zampini     IS                     is;
307c9225affSStefano Zampini 
3085f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetBlockSize(A,&bs));
3095f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateStride(PetscObjectComm((PetscObject)A),A->rmap->n/bs,0,1,&is));
310c9225affSStefano Zampini     if (bs > 1) {
311c9225affSStefano Zampini       IS       is2;
312c9225affSStefano Zampini       PetscInt i,*aux;
313c9225affSStefano Zampini 
3145f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetLocalSize(is,&i));
3155f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetIndices(is,(const PetscInt**)&aux));
3165f80ce2aSJacob Faibussowitsch       CHKERRQ(ISCreateBlock(PetscObjectComm((PetscObject)A),bs,i,aux,PETSC_COPY_VALUES,&is2));
3175f80ce2aSJacob Faibussowitsch       CHKERRQ(ISRestoreIndices(is,(const PetscInt**)&aux));
3185f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&is));
319c9225affSStefano Zampini       is   = is2;
320c9225affSStefano Zampini     }
3215f80ce2aSJacob Faibussowitsch     CHKERRQ(ISSetIdentity(is));
3225f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingCreateIS(is,&rl2g));
3235f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&is));
3245f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateStride(PetscObjectComm((PetscObject)A),A->cmap->n/bs,0,1,&is));
325c9225affSStefano Zampini     if (bs > 1) {
326c9225affSStefano Zampini       IS       is2;
327c9225affSStefano Zampini       PetscInt i,*aux;
328c9225affSStefano Zampini 
3295f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetLocalSize(is,&i));
3305f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetIndices(is,(const PetscInt**)&aux));
3315f80ce2aSJacob Faibussowitsch       CHKERRQ(ISCreateBlock(PetscObjectComm((PetscObject)A),bs,i,aux,PETSC_COPY_VALUES,&is2));
3325f80ce2aSJacob Faibussowitsch       CHKERRQ(ISRestoreIndices(is,(const PetscInt**)&aux));
3335f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&is));
334c9225affSStefano Zampini       is   = is2;
335c9225affSStefano Zampini     }
3365f80ce2aSJacob Faibussowitsch     CHKERRQ(ISSetIdentity(is));
3375f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingCreateIS(is,&cl2g));
3385f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&is));
3395f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreateIS(PetscObjectComm((PetscObject)A),bs,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N,rl2g,cl2g,&B));
3405f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingDestroy(&rl2g));
3415f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingDestroy(&cl2g));
3425f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDuplicate(A,MAT_COPY_VALUES,&lB));
343c9225affSStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) *newmat = B;
344c9225affSStefano Zampini   } else {
345c9225affSStefano Zampini     B    = *newmat;
3465f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectReference((PetscObject)A));
347c9225affSStefano Zampini     lB   = A;
348c9225affSStefano Zampini   }
3495f80ce2aSJacob Faibussowitsch   CHKERRQ(MatISSetLocalMat(B,lB));
3505f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&lB));
3515f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
3525f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
353c9225affSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
3545f80ce2aSJacob Faibussowitsch     CHKERRQ(MatHeaderReplace(A,&B));
355c9225affSStefano Zampini   }
356c9225affSStefano Zampini   PetscFunctionReturn(0);
357c9225affSStefano Zampini }
358c9225affSStefano Zampini 
359c9225affSStefano Zampini static PetscErrorCode MatISScaleDisassembling_Private(Mat A)
360c9225affSStefano Zampini {
361c9225affSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(A->data);
362c9225affSStefano Zampini   PetscScalar    *aa;
363c9225affSStefano Zampini   const PetscInt *ii,*jj;
364c9225affSStefano Zampini   PetscInt       i,n,m;
365fabe8965SStefano Zampini   PetscInt       *ecount,**eneighs;
366c9225affSStefano Zampini   PetscBool      flg;
367c9225affSStefano Zampini 
368c9225affSStefano Zampini   PetscFunctionBegin;
3695f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&m,&ii,&jj,&flg));
3702c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
3715f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetNodeInfo(matis->rmapping,&n,&ecount,&eneighs));
3722c71b3e2SJacob Faibussowitsch   PetscCheckFalse(m != n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %" PetscInt_FMT " != %" PetscInt_FMT,m,n);
3735f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArray(matis->A,&aa));
374c9225affSStefano Zampini   for (i=0;i<n;i++) {
375fabe8965SStefano Zampini     if (ecount[i] > 1) {
376c9225affSStefano Zampini       PetscInt j;
377c9225affSStefano Zampini 
378c9225affSStefano Zampini       for (j=ii[i];j<ii[i+1];j++) {
379c9225affSStefano Zampini         PetscInt    i2 = jj[j],p,p2;
380fabe8965SStefano Zampini         PetscReal   scal = 0.0;
381c9225affSStefano Zampini 
382c9225affSStefano Zampini         for (p=0;p<ecount[i];p++) {
383c9225affSStefano Zampini           for (p2=0;p2<ecount[i2];p2++) {
384c9225affSStefano Zampini             if (eneighs[i][p] == eneighs[i2][p2]) { scal += 1.0; break; }
385c9225affSStefano Zampini           }
386c9225affSStefano Zampini         }
387fabe8965SStefano Zampini         if (scal) aa[j] /= scal;
388c9225affSStefano Zampini       }
389c9225affSStefano Zampini     }
390c9225affSStefano Zampini   }
3915f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingRestoreNodeInfo(matis->rmapping,&n,&ecount,&eneighs));
3925f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArray(matis->A,&aa));
3935f80ce2aSJacob Faibussowitsch   CHKERRQ(MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&m,&ii,&jj,&flg));
3942c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
395c9225affSStefano Zampini   PetscFunctionReturn(0);
396c9225affSStefano Zampini }
397c9225affSStefano Zampini 
398fabe8965SStefano Zampini typedef enum {MAT_IS_DISASSEMBLE_L2G_NATURAL,MAT_IS_DISASSEMBLE_L2G_MAT, MAT_IS_DISASSEMBLE_L2G_ND} MatISDisassemblel2gType;
399fabe8965SStefano Zampini 
400c9225affSStefano Zampini static PetscErrorCode MatMPIXAIJComputeLocalToGlobalMapping_Private(Mat A, ISLocalToGlobalMapping *l2g)
401c9225affSStefano Zampini {
402fabe8965SStefano Zampini   Mat                     Ad,Ao;
403fabe8965SStefano Zampini   IS                      is,ndmap,ndsub;
404c9225affSStefano Zampini   MPI_Comm                comm;
405fabe8965SStefano Zampini   const PetscInt          *garray,*ndmapi;
406fabe8965SStefano Zampini   PetscInt                bs,i,cnt,nl,*ncount,*ndmapc;
407fabe8965SStefano Zampini   PetscBool               ismpiaij,ismpibaij;
408f4259b30SLisandro Dalcin   const char *const       MatISDisassemblel2gTypes[] = {"NATURAL","MAT","ND","MatISDisassemblel2gType","MAT_IS_DISASSEMBLE_L2G_",NULL};
409fabe8965SStefano Zampini   MatISDisassemblel2gType mode = MAT_IS_DISASSEMBLE_L2G_NATURAL;
410fabe8965SStefano Zampini   MatPartitioning         part;
411fabe8965SStefano Zampini   PetscSF                 sf;
412c9225affSStefano Zampini   PetscErrorCode          ierr;
413c9225affSStefano Zampini 
414c9225affSStefano Zampini   PetscFunctionBegin;
415fabe8965SStefano Zampini   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"MatIS l2g disassembling options","Mat");CHKERRQ(ierr);
4165f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsEnum("-mat_is_disassemble_l2g_type","Type of local-to-global mapping to be used for disassembling","MatISDisassemblel2gType",MatISDisassemblel2gTypes,(PetscEnum)mode,(PetscEnum*)&mode,NULL));
417fabe8965SStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
418fabe8965SStefano Zampini   if (mode == MAT_IS_DISASSEMBLE_L2G_MAT) {
4195f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetLocalToGlobalMapping(A,l2g,NULL));
420c9225affSStefano Zampini     PetscFunctionReturn(0);
421c9225affSStefano Zampini   }
4225f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)A,&comm));
4235f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectBaseTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij));
4245f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectBaseTypeCompare((PetscObject)A,MATMPIBAIJ,&ismpibaij));
4255f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetBlockSize(A,&bs));
426fabe8965SStefano Zampini   switch (mode) {
427fabe8965SStefano Zampini   case MAT_IS_DISASSEMBLE_L2G_ND:
4285f80ce2aSJacob Faibussowitsch     CHKERRQ(MatPartitioningCreate(comm,&part));
4295f80ce2aSJacob Faibussowitsch     CHKERRQ(MatPartitioningSetAdjacency(part,A));
4305f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject)part,((PetscObject)A)->prefix));
4315f80ce2aSJacob Faibussowitsch     CHKERRQ(MatPartitioningSetFromOptions(part));
4325f80ce2aSJacob Faibussowitsch     CHKERRQ(MatPartitioningApplyND(part,&ndmap));
4335f80ce2aSJacob Faibussowitsch     CHKERRQ(MatPartitioningDestroy(&part));
4345f80ce2aSJacob Faibussowitsch     CHKERRQ(ISBuildTwoSided(ndmap,NULL,&ndsub));
4355f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMPIAIJSetUseScalableIncreaseOverlap(A,PETSC_TRUE));
4365f80ce2aSJacob Faibussowitsch     CHKERRQ(MatIncreaseOverlap(A,1,&ndsub,1));
4375f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingCreateIS(ndsub,l2g));
438fabe8965SStefano Zampini 
439fabe8965SStefano Zampini     /* it may happen that a separator node is not properly shared */
4405f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingGetNodeInfo(*l2g,&nl,&ncount,NULL));
4415f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFCreate(comm,&sf));
4425f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingGetIndices(*l2g,&garray));
4435f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFSetGraphLayout(sf,A->rmap,nl,NULL,PETSC_OWN_POINTER,garray));
4445f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingRestoreIndices(*l2g,&garray));
4455f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscCalloc1(A->rmap->n,&ndmapc));
4465f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFReduceBegin(sf,MPIU_INT,ncount,ndmapc,MPI_REPLACE));
4475f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFReduceEnd(sf,MPIU_INT,ncount,ndmapc,MPI_REPLACE));
4485f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingRestoreNodeInfo(*l2g,NULL,&ncount,NULL));
4495f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(ndmap,&ndmapi));
450fabe8965SStefano Zampini     for (i = 0, cnt = 0; i < A->rmap->n; i++)
451fabe8965SStefano Zampini       if (ndmapi[i] < 0 && ndmapc[i] < 2)
452fabe8965SStefano Zampini         cnt++;
453fabe8965SStefano Zampini 
4545f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPIU_Allreduce(&cnt,&i,1,MPIU_INT,MPI_MAX,comm));
455fabe8965SStefano Zampini     if (i) { /* we detected isolated separator nodes */
456fabe8965SStefano Zampini       Mat                    A2,A3;
457fabe8965SStefano Zampini       IS                     *workis,is2;
458fabe8965SStefano Zampini       PetscScalar            *vals;
459fabe8965SStefano Zampini       PetscInt               gcnt = i,*dnz,*onz,j,*lndmapi;
460fabe8965SStefano Zampini       ISLocalToGlobalMapping ll2g;
461fabe8965SStefano Zampini       PetscBool              flg;
462fabe8965SStefano Zampini       const PetscInt         *ii,*jj;
463fabe8965SStefano Zampini 
464fabe8965SStefano Zampini       /* communicate global id of separators */
465fabe8965SStefano Zampini       ierr = MatPreallocateInitialize(comm,A->rmap->n,A->cmap->n,dnz,onz);CHKERRQ(ierr);
466fabe8965SStefano Zampini       for (i = 0, cnt = 0; i < A->rmap->n; i++)
467fabe8965SStefano Zampini         dnz[i] = ndmapi[i] < 0 ? i + A->rmap->rstart : -1;
468fabe8965SStefano Zampini 
4695f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(nl,&lndmapi));
4705f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSFBcastBegin(sf,MPIU_INT,dnz,lndmapi,MPI_REPLACE));
471fabe8965SStefano Zampini 
472fabe8965SStefano Zampini       /* compute adjacency of isolated separators node */
4735f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(gcnt,&workis));
474fabe8965SStefano Zampini       for (i = 0, cnt = 0; i < A->rmap->n; i++) {
475fabe8965SStefano Zampini         if (ndmapi[i] < 0 && ndmapc[i] < 2) {
4765f80ce2aSJacob Faibussowitsch           CHKERRQ(ISCreateStride(comm,1,i+A->rmap->rstart,1,&workis[cnt++]));
477fabe8965SStefano Zampini         }
478fabe8965SStefano Zampini       }
479fabe8965SStefano Zampini       for (i = cnt; i < gcnt; i++) {
4805f80ce2aSJacob Faibussowitsch         CHKERRQ(ISCreateStride(comm,0,0,1,&workis[i]));
481fabe8965SStefano Zampini       }
482fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
4835f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscObjectSetName((PetscObject)workis[i],"ISOLATED"));
4845f80ce2aSJacob Faibussowitsch         CHKERRQ(ISViewFromOptions(workis[i],NULL,"-view_isolated_separators"));
485fabe8965SStefano Zampini       }
486fabe8965SStefano Zampini 
487fabe8965SStefano Zampini       /* no communications since all the ISes correspond to locally owned rows */
4885f80ce2aSJacob Faibussowitsch       CHKERRQ(MatIncreaseOverlap(A,gcnt,workis,1));
489fabe8965SStefano Zampini 
490fabe8965SStefano Zampini       /* end communicate global id of separators */
4915f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSFBcastEnd(sf,MPIU_INT,dnz,lndmapi,MPI_REPLACE));
492fabe8965SStefano Zampini 
493fabe8965SStefano Zampini       /* communicate new layers : create a matrix and transpose it */
4945f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArrayzero(dnz,A->rmap->n));
4955f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArrayzero(onz,A->rmap->n));
496fabe8965SStefano Zampini       for (i = 0, j = 0; i < A->rmap->n; i++) {
497fabe8965SStefano Zampini         if (ndmapi[i] < 0 && ndmapc[i] < 2) {
498fabe8965SStefano Zampini           const PetscInt* idxs;
499fabe8965SStefano Zampini           PetscInt        s;
500fabe8965SStefano Zampini 
5015f80ce2aSJacob Faibussowitsch           CHKERRQ(ISGetLocalSize(workis[j],&s));
5025f80ce2aSJacob Faibussowitsch           CHKERRQ(ISGetIndices(workis[j],&idxs));
5035f80ce2aSJacob Faibussowitsch           CHKERRQ(MatPreallocateSet(i+A->rmap->rstart,s,idxs,dnz,onz));
504fabe8965SStefano Zampini           j++;
505fabe8965SStefano Zampini         }
506fabe8965SStefano Zampini       }
5072c71b3e2SJacob Faibussowitsch       PetscCheckFalse(j != cnt,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected local count %" PetscInt_FMT " != %" PetscInt_FMT,j,cnt);
508fabe8965SStefano Zampini 
509fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
5105f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscObjectSetName((PetscObject)workis[i],"EXTENDED"));
5115f80ce2aSJacob Faibussowitsch         CHKERRQ(ISViewFromOptions(workis[i],NULL,"-view_isolated_separators"));
512fabe8965SStefano Zampini       }
513fabe8965SStefano Zampini 
514fabe8965SStefano Zampini       for (i = 0, j = 0; i < A->rmap->n; i++) j = PetscMax(j,dnz[i]+onz[i]);
5155f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(j,&vals));
516fabe8965SStefano Zampini       for (i = 0; i < j; i++) vals[i] = 1.0;
517fabe8965SStefano Zampini 
5185f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreate(comm,&A2));
5195f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetType(A2,MATMPIAIJ));
5205f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetSizes(A2,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N));
5215f80ce2aSJacob Faibussowitsch       CHKERRQ(MatMPIAIJSetPreallocation(A2,0,dnz,0,onz));
5225f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetOption(A2,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE));
523fabe8965SStefano Zampini       for (i = 0, j = 0; i < A2->rmap->n; i++) {
524fabe8965SStefano Zampini         PetscInt        row = i+A2->rmap->rstart,s = dnz[i] + onz[i];
525fabe8965SStefano Zampini         const PetscInt* idxs;
526fabe8965SStefano Zampini 
527fabe8965SStefano Zampini         if (s) {
5285f80ce2aSJacob Faibussowitsch           CHKERRQ(ISGetIndices(workis[j],&idxs));
5295f80ce2aSJacob Faibussowitsch           CHKERRQ(MatSetValues(A2,1,&row,s,idxs,vals,INSERT_VALUES));
5305f80ce2aSJacob Faibussowitsch           CHKERRQ(ISRestoreIndices(workis[j],&idxs));
531fabe8965SStefano Zampini           j++;
532fabe8965SStefano Zampini         }
533fabe8965SStefano Zampini       }
5342c71b3e2SJacob Faibussowitsch       PetscCheckFalse(j != cnt,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected local count %" PetscInt_FMT " != %" PetscInt_FMT,j,cnt);
5355f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(vals));
5365f80ce2aSJacob Faibussowitsch       CHKERRQ(MatAssemblyBegin(A2,MAT_FINAL_ASSEMBLY));
5375f80ce2aSJacob Faibussowitsch       CHKERRQ(MatAssemblyEnd(A2,MAT_FINAL_ASSEMBLY));
5385f80ce2aSJacob Faibussowitsch       CHKERRQ(MatTranspose(A2,MAT_INPLACE_MATRIX,&A2));
539fabe8965SStefano Zampini 
540fabe8965SStefano Zampini       /* extract submatrix corresponding to the coupling "owned separators" x "isolated separators" */
541fabe8965SStefano Zampini       for (i = 0, j = 0; i < nl; i++)
542fabe8965SStefano Zampini         if (lndmapi[i] >= 0) lndmapi[j++] = lndmapi[i];
5435f80ce2aSJacob Faibussowitsch       CHKERRQ(ISCreateGeneral(comm,j,lndmapi,PETSC_USE_POINTER,&is));
5445f80ce2aSJacob Faibussowitsch       CHKERRQ(MatMPIAIJGetLocalMatCondensed(A2,MAT_INITIAL_MATRIX,&is,NULL,&A3));
5455f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&is));
5465f80ce2aSJacob Faibussowitsch       CHKERRQ(MatDestroy(&A2));
547fabe8965SStefano Zampini 
548fabe8965SStefano Zampini       /* extend local to global map to include connected isolated separators */
5495f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectQuery((PetscObject)A3,"_petsc_GetLocalMatCondensed_iscol",(PetscObject*)&is));
550*28b400f6SJacob Faibussowitsch       PetscCheck(is,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing column map");
5515f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingCreateIS(is,&ll2g));
5525f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetRowIJ(A3,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&flg));
553*28b400f6SJacob Faibussowitsch       PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
5545f80ce2aSJacob Faibussowitsch       CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,ii[i],jj,PETSC_COPY_VALUES,&is));
5555f80ce2aSJacob Faibussowitsch       CHKERRQ(MatRestoreRowIJ(A3,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&flg));
556*28b400f6SJacob Faibussowitsch       PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
5575f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingApplyIS(ll2g,is,&is2));
5585f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&is));
5595f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingDestroy(&ll2g));
560fabe8965SStefano Zampini 
561fabe8965SStefano Zampini       /* add new nodes to the local-to-global map */
5625f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingDestroy(l2g));
5635f80ce2aSJacob Faibussowitsch       CHKERRQ(ISExpand(ndsub,is2,&is));
5645f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&is2));
5655f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingCreateIS(is,l2g));
5665f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&is));
567fabe8965SStefano Zampini 
5685f80ce2aSJacob Faibussowitsch       CHKERRQ(MatDestroy(&A3));
5695f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(lndmapi));
570fabe8965SStefano Zampini       ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
571fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
5725f80ce2aSJacob Faibussowitsch         CHKERRQ(ISDestroy(&workis[i]));
573fabe8965SStefano Zampini       }
5745f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(workis));
575fabe8965SStefano Zampini     }
5765f80ce2aSJacob Faibussowitsch     CHKERRQ(ISRestoreIndices(ndmap,&ndmapi));
5775f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFDestroy(&sf));
5785f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(ndmapc));
5795f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&ndmap));
5805f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&ndsub));
5815f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingSetBlockSize(*l2g,bs));
5825f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingViewFromOptions(*l2g,NULL,"-matis_nd_l2g_view"));
583fabe8965SStefano Zampini     break;
584fabe8965SStefano Zampini   case MAT_IS_DISASSEMBLE_L2G_NATURAL:
585fabe8965SStefano Zampini     if (ismpiaij) {
5865f80ce2aSJacob Faibussowitsch       CHKERRQ(MatMPIAIJGetSeqAIJ(A,&Ad,&Ao,&garray));
587fabe8965SStefano Zampini     } else if (ismpibaij) {
5885f80ce2aSJacob Faibussowitsch       CHKERRQ(MatMPIBAIJGetSeqBAIJ(A,&Ad,&Ao,&garray));
58998921bdaSJacob Faibussowitsch     } else SETERRQ(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name);
590*28b400f6SJacob Faibussowitsch     PetscCheck(garray,comm,PETSC_ERR_ARG_WRONGSTATE,"garray not present");
591c9225affSStefano Zampini     if (A->rmap->n) {
592fabe8965SStefano Zampini       PetscInt dc,oc,stc,*aux;
593c9225affSStefano Zampini 
5945f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetLocalSize(A,NULL,&dc));
5955f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetLocalSize(Ao,NULL,&oc));
5965f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetOwnershipRangeColumn(A,&stc,NULL));
5975f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1((dc+oc)/bs,&aux));
598c9225affSStefano Zampini       for (i=0; i<dc/bs; i++) aux[i]       = i+stc/bs;
599c9225affSStefano Zampini       for (i=0; i<oc/bs; i++) aux[i+dc/bs] = garray[i];
6005f80ce2aSJacob Faibussowitsch       CHKERRQ(ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is));
601c9225affSStefano Zampini     } else {
6025f80ce2aSJacob Faibussowitsch       CHKERRQ(ISCreateBlock(comm,1,0,NULL,PETSC_OWN_POINTER,&is));
603c9225affSStefano Zampini     }
6045f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingCreateIS(is,l2g));
6055f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&is));
606fabe8965SStefano Zampini     break;
607fabe8965SStefano Zampini   default:
60898921bdaSJacob Faibussowitsch     SETERRQ(comm,PETSC_ERR_ARG_WRONG,"Unsupported l2g disassembling type %d",mode);
609c9225affSStefano Zampini   }
610c9225affSStefano Zampini   PetscFunctionReturn(0);
611c9225affSStefano Zampini }
612c9225affSStefano Zampini 
613c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
614c9225affSStefano Zampini {
615c9225affSStefano Zampini   Mat                    lA,Ad,Ao,B = NULL;
6166989cf23SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
6176989cf23SStefano Zampini   IS                     is;
6186989cf23SStefano Zampini   MPI_Comm               comm;
6196989cf23SStefano Zampini   void                   *ptrs[2];
6206989cf23SStefano Zampini   const char             *names[2] = {"_convert_csr_aux","_convert_csr_data"};
621c9225affSStefano Zampini   const PetscInt         *garray;
6226989cf23SStefano Zampini   PetscScalar            *dd,*od,*aa,*data;
623c9225affSStefano Zampini   const PetscInt         *di,*dj,*oi,*oj;
624c9225affSStefano Zampini   const PetscInt         *odi,*odj,*ooi,*ooj;
6256989cf23SStefano Zampini   PetscInt               *aux,*ii,*jj;
626c9225affSStefano Zampini   PetscInt               bs,lc,dr,dc,oc,str,stc,nnz,i,jd,jo,cum;
627c9225affSStefano Zampini   PetscBool              flg,ismpiaij,ismpibaij,was_inplace = PETSC_FALSE;
628c9225affSStefano Zampini   PetscMPIInt            size;
6296989cf23SStefano Zampini 
630ab4d48faSStefano Zampini   PetscFunctionBegin;
6315f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)A,&comm));
6325f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm,&size));
633c9225affSStefano Zampini   if (size == 1) {
6345f80ce2aSJacob Faibussowitsch     CHKERRQ(MatConvert_SeqXAIJ_IS(A,type,reuse,newmat));
635c9225affSStefano Zampini     PetscFunctionReturn(0);
636c9225affSStefano Zampini   }
637c9225affSStefano Zampini   if (reuse != MAT_REUSE_MATRIX && A->cmap->N == A->rmap->N) {
6385f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMPIXAIJComputeLocalToGlobalMapping_Private(A,&rl2g));
6395f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreate(comm,&B));
6405f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetType(B,MATIS));
6415f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N));
6425f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetLocalToGlobalMapping(B,rl2g,rl2g));
6435f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetBlockSize(A,&bs));
6445f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetBlockSize(B,bs));
6455f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingDestroy(&rl2g));
646c9225affSStefano Zampini     if (reuse == MAT_INPLACE_MATRIX) was_inplace = PETSC_TRUE;
647c9225affSStefano Zampini     reuse = MAT_REUSE_MATRIX;
648c9225affSStefano Zampini   }
649c9225affSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
650c9225affSStefano Zampini     Mat            *newlA, lA;
651c9225affSStefano Zampini     IS             rows, cols;
652c9225affSStefano Zampini     const PetscInt *ridx, *cidx;
653c9225affSStefano Zampini     PetscInt       rbs, cbs, nr, nc;
654c9225affSStefano Zampini 
655c9225affSStefano Zampini     if (!B) B = *newmat;
6565f80ce2aSJacob Faibussowitsch     CHKERRQ(MatISGetLocalToGlobalMapping(B,&rl2g,&cl2g));
6575f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingGetBlockIndices(rl2g,&ridx));
6585f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingGetBlockIndices(cl2g,&cidx));
6595f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingGetSize(rl2g,&nr));
6605f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingGetSize(cl2g,&nc));
6615f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingGetBlockSize(rl2g,&rbs));
6625f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingGetBlockSize(cl2g,&cbs));
6635f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateBlock(comm,rbs,nr/rbs,ridx,PETSC_USE_POINTER,&rows));
664c9225affSStefano Zampini     if (rl2g != cl2g) {
6655f80ce2aSJacob Faibussowitsch       CHKERRQ(ISCreateBlock(comm,cbs,nc/cbs,cidx,PETSC_USE_POINTER,&cols));
666c9225affSStefano Zampini     } else {
6675f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectReference((PetscObject)rows));
668c9225affSStefano Zampini       cols = rows;
669c9225affSStefano Zampini     }
6705f80ce2aSJacob Faibussowitsch     CHKERRQ(MatISGetLocalMat(B,&lA));
6715f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreateSubMatrices(A,1,&rows,&cols,MAT_INITIAL_MATRIX,&newlA));
6725f80ce2aSJacob Faibussowitsch     CHKERRQ(MatConvert(newlA[0],MATSEQAIJ,MAT_INPLACE_MATRIX,&newlA[0]));
6735f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingRestoreBlockIndices(rl2g,&ridx));
6745f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingRestoreBlockIndices(cl2g,&cidx));
6755f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&rows));
6765f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&cols));
677c9225affSStefano Zampini     if (!lA->preallocated) { /* first time */
6785f80ce2aSJacob Faibussowitsch       CHKERRQ(MatDuplicate(newlA[0],MAT_COPY_VALUES,&lA));
6795f80ce2aSJacob Faibussowitsch       CHKERRQ(MatISSetLocalMat(B,lA));
6805f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectDereference((PetscObject)lA));
681c9225affSStefano Zampini     }
6825f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCopy(newlA[0],lA,SAME_NONZERO_PATTERN));
6835f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroySubMatrices(1,&newlA));
6845f80ce2aSJacob Faibussowitsch     CHKERRQ(MatISScaleDisassembling_Private(B));
6855f80ce2aSJacob Faibussowitsch     CHKERRQ(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
6865f80ce2aSJacob Faibussowitsch     CHKERRQ(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
6875f80ce2aSJacob Faibussowitsch     if (was_inplace) CHKERRQ(MatHeaderReplace(A,&B));
688c9225affSStefano Zampini     else *newmat = B;
689c9225affSStefano Zampini     PetscFunctionReturn(0);
690c9225affSStefano Zampini   }
691c9225affSStefano Zampini   /* rectangular case, just compress out the column space */
6925f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectBaseTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij));
6935f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectBaseTypeCompare((PetscObject)A,MATMPIBAIJ,&ismpibaij));
694c9225affSStefano Zampini   if (ismpiaij) {
695c9225affSStefano Zampini     bs   = 1;
6965f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMPIAIJGetSeqAIJ(A,&Ad,&Ao,&garray));
697c9225affSStefano Zampini   } else if (ismpibaij) {
6985f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetBlockSize(A,&bs));
6995f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMPIBAIJGetSeqBAIJ(A,&Ad,&Ao,&garray));
7005f80ce2aSJacob Faibussowitsch     CHKERRQ(MatConvert(Ad,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ad));
7015f80ce2aSJacob Faibussowitsch     CHKERRQ(MatConvert(Ao,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ao));
70298921bdaSJacob Faibussowitsch   } else SETERRQ(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name);
7035f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArray(Ad,&dd));
7045f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArray(Ao,&od));
705*28b400f6SJacob Faibussowitsch   PetscCheck(garray,comm,PETSC_ERR_ARG_WRONGSTATE,"garray not present");
7066989cf23SStefano Zampini 
7076989cf23SStefano Zampini   /* access relevant information from MPIAIJ */
7085f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetOwnershipRange(A,&str,NULL));
7095f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetOwnershipRangeColumn(A,&stc,NULL));
7105f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetLocalSize(A,&dr,&dc));
7115f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetLocalSize(Ao,NULL,&oc));
7125f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&di,&dj,&flg));
713*28b400f6SJacob Faibussowitsch   PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
7145f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&oi,&oj,&flg));
715*28b400f6SJacob Faibussowitsch   PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
716c9225affSStefano Zampini   nnz = di[dr] + oi[dr];
717c9225affSStefano Zampini   /* store original pointers to be restored later */
718c9225affSStefano Zampini   odi = di; odj = dj; ooi = oi; ooj = oj;
7196989cf23SStefano Zampini 
7206989cf23SStefano Zampini   /* generate l2g maps for rows and cols */
7215f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateStride(comm,dr/bs,str/bs,1,&is));
722c9225affSStefano Zampini   if (bs > 1) {
723c9225affSStefano Zampini     IS is2;
724c9225affSStefano Zampini 
7255f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetLocalSize(is,&i));
7265f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(is,(const PetscInt**)&aux));
7275f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateBlock(comm,bs,i,aux,PETSC_COPY_VALUES,&is2));
7285f80ce2aSJacob Faibussowitsch     CHKERRQ(ISRestoreIndices(is,(const PetscInt**)&aux));
7295f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&is));
730c9225affSStefano Zampini     is   = is2;
731c9225affSStefano Zampini   }
7325f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingCreateIS(is,&rl2g));
7335f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&is));
734e363d98aSStefano Zampini   if (dr) {
7355f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1((dc+oc)/bs,&aux));
736c9225affSStefano Zampini     for (i=0; i<dc/bs; i++) aux[i]       = i+stc/bs;
737c9225affSStefano Zampini     for (i=0; i<oc/bs; i++) aux[i+dc/bs] = garray[i];
7385f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is));
739e363d98aSStefano Zampini     lc   = dc+oc;
740e363d98aSStefano Zampini   } else {
7415f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateBlock(comm,bs,0,NULL,PETSC_OWN_POINTER,&is));
742e363d98aSStefano Zampini     lc   = 0;
743e363d98aSStefano Zampini   }
7445f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingCreateIS(is,&cl2g));
7455f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&is));
7466989cf23SStefano Zampini 
7476989cf23SStefano Zampini   /* create MATIS object */
7485f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreate(comm,&B));
7495f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSizes(B,dr,dc,PETSC_DECIDE,PETSC_DECIDE));
7505f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetType(B,MATIS));
7515f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetBlockSize(B,bs));
7525f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetLocalToGlobalMapping(B,rl2g,cl2g));
7535f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingDestroy(&rl2g));
7545f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingDestroy(&cl2g));
7556989cf23SStefano Zampini 
7566989cf23SStefano Zampini   /* merge local matrices */
7575f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(nnz+dr+1,&aux));
7585f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(nnz,&data));
7596989cf23SStefano Zampini   ii   = aux;
7606989cf23SStefano Zampini   jj   = aux+dr+1;
7616989cf23SStefano Zampini   aa   = data;
7626989cf23SStefano Zampini   *ii  = *(di++) + *(oi++);
7636989cf23SStefano Zampini   for (jd=0,jo=0,cum=0;*ii<nnz;cum++)
7646989cf23SStefano Zampini   {
7656989cf23SStefano Zampini      for (;jd<*di;jd++) { *jj++ = *dj++;      *aa++ = *dd++; }
7666989cf23SStefano Zampini      for (;jo<*oi;jo++) { *jj++ = *oj++ + dc; *aa++ = *od++; }
7676989cf23SStefano Zampini      *(++ii) = *(di++) + *(oi++);
7686989cf23SStefano Zampini   }
7696989cf23SStefano Zampini   for (;cum<dr;cum++) *(++ii) = nnz;
770c9225affSStefano Zampini 
7715f80ce2aSJacob Faibussowitsch   CHKERRQ(MatRestoreRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&odi,&odj,&flg));
772*28b400f6SJacob Faibussowitsch   PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
7735f80ce2aSJacob Faibussowitsch   CHKERRQ(MatRestoreRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&ooi,&ooj,&flg));
774*28b400f6SJacob Faibussowitsch   PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
7755f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArray(Ad,&dd));
7765f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArray(Ao,&od));
777c9225affSStefano Zampini 
7786989cf23SStefano Zampini   ii   = aux;
7796989cf23SStefano Zampini   jj   = aux+dr+1;
7806989cf23SStefano Zampini   aa   = data;
7815f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,lc,ii,jj,aa,&lA));
7826989cf23SStefano Zampini 
7836989cf23SStefano Zampini   /* create containers to destroy the data */
7846989cf23SStefano Zampini   ptrs[0] = aux;
7856989cf23SStefano Zampini   ptrs[1] = data;
7866989cf23SStefano Zampini   for (i=0; i<2; i++) {
7876989cf23SStefano Zampini     PetscContainer c;
7886989cf23SStefano Zampini 
7895f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscContainerCreate(PETSC_COMM_SELF,&c));
7905f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscContainerSetPointer(c,ptrs[i]));
7915f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscContainerSetUserDestroy(c,PetscContainerUserDestroyDefault));
7925f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectCompose((PetscObject)lA,names[i],(PetscObject)c));
7935f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscContainerDestroy(&c));
7946989cf23SStefano Zampini   }
795c9225affSStefano Zampini   if (ismpibaij) { /* destroy converted local matrices */
7965f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroy(&Ad));
7975f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroy(&Ao));
798c9225affSStefano Zampini   }
7996989cf23SStefano Zampini 
8006989cf23SStefano Zampini   /* finalize matrix */
8015f80ce2aSJacob Faibussowitsch   CHKERRQ(MatISSetLocalMat(B,lA));
8025f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&lA));
8035f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
8045f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
805c9225affSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
8065f80ce2aSJacob Faibussowitsch     CHKERRQ(MatHeaderReplace(A,&B));
807c9225affSStefano Zampini   } else *newmat = B;
8086989cf23SStefano Zampini   PetscFunctionReturn(0);
8096989cf23SStefano Zampini }
8106989cf23SStefano Zampini 
8115e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
8125e3038f0Sstefano_zampini {
8135e3038f0Sstefano_zampini   Mat                    **nest,*snest,**rnest,lA,B;
8145e3038f0Sstefano_zampini   IS                     *iscol,*isrow,*islrow,*islcol;
8155e3038f0Sstefano_zampini   ISLocalToGlobalMapping rl2g,cl2g;
8165e3038f0Sstefano_zampini   MPI_Comm               comm;
8175b003df0Sstefano_zampini   PetscInt               *lr,*lc,*l2gidxs;
8185b003df0Sstefano_zampini   PetscInt               i,j,nr,nc,rbs,cbs;
8199e7b2b25Sstefano_zampini   PetscBool              convert,lreuse,*istrans;
8205e3038f0Sstefano_zampini 
821ab4d48faSStefano Zampini   PetscFunctionBegin;
8225f80ce2aSJacob Faibussowitsch   CHKERRQ(MatNestGetSubMats(A,&nr,&nc,&nest));
8235e3038f0Sstefano_zampini   lreuse = PETSC_FALSE;
8245e3038f0Sstefano_zampini   rnest  = NULL;
8255e3038f0Sstefano_zampini   if (reuse == MAT_REUSE_MATRIX) {
8265e3038f0Sstefano_zampini     PetscBool ismatis,isnest;
8275e3038f0Sstefano_zampini 
8285f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis));
829*28b400f6SJacob Faibussowitsch     PetscCheck(ismatis,PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type_name);
8305f80ce2aSJacob Faibussowitsch     CHKERRQ(MatISGetLocalMat(*newmat,&lA));
8315f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest));
8325e3038f0Sstefano_zampini     if (isnest) {
8335f80ce2aSJacob Faibussowitsch       CHKERRQ(MatNestGetSubMats(lA,&i,&j,&rnest));
8345e3038f0Sstefano_zampini       lreuse = (PetscBool)(i == nr && j == nc);
8355e3038f0Sstefano_zampini       if (!lreuse) rnest = NULL;
8365e3038f0Sstefano_zampini     }
8375e3038f0Sstefano_zampini   }
8385f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)A,&comm));
8395f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc2(nr,&lr,nc,&lc));
8405f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc6(nr,&isrow,nc,&iscol,nr,&islrow,nc,&islcol,nr*nc,&snest,nr*nc,&istrans));
8415f80ce2aSJacob Faibussowitsch   CHKERRQ(MatNestGetISs(A,isrow,iscol));
8425e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
8435e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
8445e3038f0Sstefano_zampini       PetscBool ismatis;
8459e7b2b25Sstefano_zampini       PetscInt  l1,l2,lb1,lb2,ij=i*nc+j;
8465e3038f0Sstefano_zampini 
8475e3038f0Sstefano_zampini       /* Null matrix pointers are allowed in MATNEST */
8485e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
8495e3038f0Sstefano_zampini 
8505e3038f0Sstefano_zampini       /* Nested matrices should be of type MATIS */
8515f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij]));
8529e7b2b25Sstefano_zampini       if (istrans[ij]) {
8539e7b2b25Sstefano_zampini         Mat T,lT;
8545f80ce2aSJacob Faibussowitsch         CHKERRQ(MatTransposeGetMat(nest[i][j],&T));
8555f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis));
856*28b400f6SJacob Faibussowitsch         PetscCheck(ismatis,comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") (transposed) is not of type MATIS",i,j);
8575f80ce2aSJacob Faibussowitsch         CHKERRQ(MatISGetLocalMat(T,&lT));
8585f80ce2aSJacob Faibussowitsch         CHKERRQ(MatCreateTranspose(lT,&snest[ij]));
8599e7b2b25Sstefano_zampini       } else {
8605f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis));
861*28b400f6SJacob Faibussowitsch         PetscCheck(ismatis,comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") is not of type MATIS",i,j);
8625f80ce2aSJacob Faibussowitsch         CHKERRQ(MatISGetLocalMat(nest[i][j],&snest[ij]));
8639e7b2b25Sstefano_zampini       }
8645e3038f0Sstefano_zampini 
8655e3038f0Sstefano_zampini       /* Check compatibility of local sizes */
8665f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetSize(snest[ij],&l1,&l2));
8675f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetBlockSizes(snest[ij],&lb1,&lb2));
8685e3038f0Sstefano_zampini       if (!l1 || !l2) continue;
8692c71b3e2SJacob Faibussowitsch       PetscCheckFalse(lr[i] && l1 != lr[i],PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") has invalid local size %" PetscInt_FMT " != %" PetscInt_FMT,i,j,lr[i],l1);
8702c71b3e2SJacob Faibussowitsch       PetscCheckFalse(lc[j] && l2 != lc[j],PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") has invalid local size %" PetscInt_FMT " != %" PetscInt_FMT,i,j,lc[j],l2);
8715e3038f0Sstefano_zampini       lr[i] = l1;
8725e3038f0Sstefano_zampini       lc[j] = l2;
8735e3038f0Sstefano_zampini 
8745e3038f0Sstefano_zampini       /* check compatibilty for local matrix reusage */
8755e3038f0Sstefano_zampini       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
8765e3038f0Sstefano_zampini     }
8775e3038f0Sstefano_zampini   }
8785e3038f0Sstefano_zampini 
87976bd3646SJed Brown   if (PetscDefined (USE_DEBUG)) {
8805e3038f0Sstefano_zampini     /* Check compatibility of l2g maps for rows */
8815e3038f0Sstefano_zampini     for (i=0;i<nr;i++) {
8825e3038f0Sstefano_zampini       rl2g = NULL;
8835e3038f0Sstefano_zampini       for (j=0;j<nc;j++) {
8845e3038f0Sstefano_zampini         PetscInt n1,n2;
8855e3038f0Sstefano_zampini 
8865e3038f0Sstefano_zampini         if (!nest[i][j]) continue;
8879e7b2b25Sstefano_zampini         if (istrans[i*nc+j]) {
8889e7b2b25Sstefano_zampini           Mat T;
8899e7b2b25Sstefano_zampini 
8905f80ce2aSJacob Faibussowitsch           CHKERRQ(MatTransposeGetMat(nest[i][j],&T));
8915f80ce2aSJacob Faibussowitsch           CHKERRQ(MatISGetLocalToGlobalMapping(T,NULL,&cl2g));
8929e7b2b25Sstefano_zampini         } else {
8935f80ce2aSJacob Faibussowitsch           CHKERRQ(MatISGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL));
8949e7b2b25Sstefano_zampini         }
8955f80ce2aSJacob Faibussowitsch         CHKERRQ(ISLocalToGlobalMappingGetSize(cl2g,&n1));
8965e3038f0Sstefano_zampini         if (!n1) continue;
8975e3038f0Sstefano_zampini         if (!rl2g) {
8985e3038f0Sstefano_zampini           rl2g = cl2g;
8995e3038f0Sstefano_zampini         } else {
9005e3038f0Sstefano_zampini           const PetscInt *idxs1,*idxs2;
9015e3038f0Sstefano_zampini           PetscBool      same;
9025e3038f0Sstefano_zampini 
9035f80ce2aSJacob Faibussowitsch           CHKERRQ(ISLocalToGlobalMappingGetSize(rl2g,&n2));
9042c71b3e2SJacob Faibussowitsch           PetscCheckFalse(n1 != n2,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") has invalid row l2gmap size %" PetscInt_FMT " != %" PetscInt_FMT,i,j,n1,n2);
9055f80ce2aSJacob Faibussowitsch           CHKERRQ(ISLocalToGlobalMappingGetIndices(cl2g,&idxs1));
9065f80ce2aSJacob Faibussowitsch           CHKERRQ(ISLocalToGlobalMappingGetIndices(rl2g,&idxs2));
9075f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscArraycmp(idxs1,idxs2,n1,&same));
9085f80ce2aSJacob Faibussowitsch           CHKERRQ(ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1));
9095f80ce2aSJacob Faibussowitsch           CHKERRQ(ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2));
910*28b400f6SJacob Faibussowitsch           PetscCheck(same,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") has invalid row l2gmap",i,j);
9115e3038f0Sstefano_zampini         }
9125e3038f0Sstefano_zampini       }
9135e3038f0Sstefano_zampini     }
9145e3038f0Sstefano_zampini     /* Check compatibility of l2g maps for columns */
9155e3038f0Sstefano_zampini     for (i=0;i<nc;i++) {
9165e3038f0Sstefano_zampini       rl2g = NULL;
9175e3038f0Sstefano_zampini       for (j=0;j<nr;j++) {
9185e3038f0Sstefano_zampini         PetscInt n1,n2;
9195e3038f0Sstefano_zampini 
9205e3038f0Sstefano_zampini         if (!nest[j][i]) continue;
9219e7b2b25Sstefano_zampini         if (istrans[j*nc+i]) {
9229e7b2b25Sstefano_zampini           Mat T;
9239e7b2b25Sstefano_zampini 
9245f80ce2aSJacob Faibussowitsch           CHKERRQ(MatTransposeGetMat(nest[j][i],&T));
9255f80ce2aSJacob Faibussowitsch           CHKERRQ(MatISGetLocalToGlobalMapping(T,&cl2g,NULL));
9269e7b2b25Sstefano_zampini         } else {
9275f80ce2aSJacob Faibussowitsch           CHKERRQ(MatISGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g));
9289e7b2b25Sstefano_zampini         }
9295f80ce2aSJacob Faibussowitsch         CHKERRQ(ISLocalToGlobalMappingGetSize(cl2g,&n1));
9305e3038f0Sstefano_zampini         if (!n1) continue;
9315e3038f0Sstefano_zampini         if (!rl2g) {
9325e3038f0Sstefano_zampini           rl2g = cl2g;
9335e3038f0Sstefano_zampini         } else {
9345e3038f0Sstefano_zampini           const PetscInt *idxs1,*idxs2;
9355e3038f0Sstefano_zampini           PetscBool      same;
9365e3038f0Sstefano_zampini 
9375f80ce2aSJacob Faibussowitsch           CHKERRQ(ISLocalToGlobalMappingGetSize(rl2g,&n2));
9382c71b3e2SJacob Faibussowitsch           PetscCheckFalse(n1 != n2,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") has invalid column l2gmap size %" PetscInt_FMT " != %" PetscInt_FMT,j,i,n1,n2);
9395f80ce2aSJacob Faibussowitsch           CHKERRQ(ISLocalToGlobalMappingGetIndices(cl2g,&idxs1));
9405f80ce2aSJacob Faibussowitsch           CHKERRQ(ISLocalToGlobalMappingGetIndices(rl2g,&idxs2));
9415f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscArraycmp(idxs1,idxs2,n1,&same));
9425f80ce2aSJacob Faibussowitsch           CHKERRQ(ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1));
9435f80ce2aSJacob Faibussowitsch           CHKERRQ(ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2));
944*28b400f6SJacob Faibussowitsch           PetscCheck(same,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") has invalid column l2gmap",j,i);
9455e3038f0Sstefano_zampini         }
9465e3038f0Sstefano_zampini       }
9475e3038f0Sstefano_zampini     }
94876bd3646SJed Brown   }
9495e3038f0Sstefano_zampini 
9505e3038f0Sstefano_zampini   B = NULL;
9515e3038f0Sstefano_zampini   if (reuse != MAT_REUSE_MATRIX) {
9525b003df0Sstefano_zampini     PetscInt stl;
9535b003df0Sstefano_zampini 
9545e3038f0Sstefano_zampini     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
9555e3038f0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) stl += lr[i];
9565f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(stl,&l2gidxs));
9575b003df0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) {
9585e3038f0Sstefano_zampini       Mat            usedmat;
9595e3038f0Sstefano_zampini       Mat_IS         *matis;
9605e3038f0Sstefano_zampini       const PetscInt *idxs;
9615e3038f0Sstefano_zampini 
9625e3038f0Sstefano_zampini       /* local IS for local NEST */
9635f80ce2aSJacob Faibussowitsch       CHKERRQ(ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]));
9645e3038f0Sstefano_zampini 
9655e3038f0Sstefano_zampini       /* l2gmap */
9665e3038f0Sstefano_zampini       j = 0;
9675e3038f0Sstefano_zampini       usedmat = nest[i][j];
9689e7b2b25Sstefano_zampini       while (!usedmat && j < nc-1) usedmat = nest[i][++j];
969*28b400f6SJacob Faibussowitsch       PetscCheck(usedmat,comm,PETSC_ERR_SUP,"Cannot find valid row mat");
9709e7b2b25Sstefano_zampini 
9719e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
9729e7b2b25Sstefano_zampini         Mat T;
9735f80ce2aSJacob Faibussowitsch         CHKERRQ(MatTransposeGetMat(usedmat,&T));
9749e7b2b25Sstefano_zampini         usedmat = T;
9759e7b2b25Sstefano_zampini       }
9765e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
9775f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetIndices(isrow[i],&idxs));
9789e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
9795f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE));
9805f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE));
9819e7b2b25Sstefano_zampini       } else {
9825f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE));
9835f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE));
9849e7b2b25Sstefano_zampini       }
9855f80ce2aSJacob Faibussowitsch       CHKERRQ(ISRestoreIndices(isrow[i],&idxs));
9865e3038f0Sstefano_zampini       stl += lr[i];
9875e3038f0Sstefano_zampini     }
9885f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g));
9895e3038f0Sstefano_zampini 
9905e3038f0Sstefano_zampini     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
9915e3038f0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) stl += lc[i];
9925f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(stl,&l2gidxs));
9935b003df0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) {
9945e3038f0Sstefano_zampini       Mat            usedmat;
9955e3038f0Sstefano_zampini       Mat_IS         *matis;
9965e3038f0Sstefano_zampini       const PetscInt *idxs;
9975e3038f0Sstefano_zampini 
9985e3038f0Sstefano_zampini       /* local IS for local NEST */
9995f80ce2aSJacob Faibussowitsch       CHKERRQ(ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]));
10005e3038f0Sstefano_zampini 
10015e3038f0Sstefano_zampini       /* l2gmap */
10025e3038f0Sstefano_zampini       j = 0;
10035e3038f0Sstefano_zampini       usedmat = nest[j][i];
10049e7b2b25Sstefano_zampini       while (!usedmat && j < nr-1) usedmat = nest[++j][i];
1005*28b400f6SJacob Faibussowitsch       PetscCheck(usedmat,comm,PETSC_ERR_SUP,"Cannot find valid column mat");
10069e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
10079e7b2b25Sstefano_zampini         Mat T;
10085f80ce2aSJacob Faibussowitsch         CHKERRQ(MatTransposeGetMat(usedmat,&T));
10099e7b2b25Sstefano_zampini         usedmat = T;
10109e7b2b25Sstefano_zampini       }
10115e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
10125f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetIndices(iscol[i],&idxs));
10139e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
10145f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE));
10155f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE));
10169e7b2b25Sstefano_zampini       } else {
10175f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE));
10185f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE));
10199e7b2b25Sstefano_zampini       }
10205f80ce2aSJacob Faibussowitsch       CHKERRQ(ISRestoreIndices(iscol[i],&idxs));
10215e3038f0Sstefano_zampini       stl += lc[i];
10225e3038f0Sstefano_zampini     }
10235f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g));
10245e3038f0Sstefano_zampini 
10255e3038f0Sstefano_zampini     /* Create MATIS */
10265f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreate(comm,&B));
10275f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N));
10285f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetBlockSizes(A,&rbs,&cbs));
10295f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetBlockSizes(B,rbs,cbs));
10305f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetType(B,MATIS));
10315f80ce2aSJacob Faibussowitsch     CHKERRQ(MatISSetLocalMatType(B,MATNEST));
10328546b261SStefano Zampini     { /* hack : avoid setup of scatters */
10338546b261SStefano Zampini       Mat_IS *matis = (Mat_IS*)(B->data);
10348546b261SStefano Zampini       matis->islocalref = PETSC_TRUE;
10358546b261SStefano Zampini     }
10365f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetLocalToGlobalMapping(B,rl2g,cl2g));
10375f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingDestroy(&rl2g));
10385f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingDestroy(&cl2g));
10395f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA));
10405f80ce2aSJacob Faibussowitsch     CHKERRQ(MatNestSetVecType(lA,VECNEST));
10419e7b2b25Sstefano_zampini     for (i=0;i<nr*nc;i++) {
10429e7b2b25Sstefano_zampini       if (istrans[i]) {
10435f80ce2aSJacob Faibussowitsch         CHKERRQ(MatDestroy(&snest[i]));
10449e7b2b25Sstefano_zampini       }
10459e7b2b25Sstefano_zampini     }
10465f80ce2aSJacob Faibussowitsch     CHKERRQ(MatISSetLocalMat(B,lA));
10475f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroy(&lA));
10488546b261SStefano Zampini     { /* hack : setup of scatters done here */
10498546b261SStefano Zampini       Mat_IS *matis = (Mat_IS*)(B->data);
10508546b261SStefano Zampini 
10518546b261SStefano Zampini       matis->islocalref = PETSC_FALSE;
10525f80ce2aSJacob Faibussowitsch       CHKERRQ(MatISSetUpScatters_Private(B));
10538546b261SStefano Zampini     }
10545f80ce2aSJacob Faibussowitsch     CHKERRQ(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
10555f80ce2aSJacob Faibussowitsch     CHKERRQ(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
10565e3038f0Sstefano_zampini     if (reuse == MAT_INPLACE_MATRIX) {
10575f80ce2aSJacob Faibussowitsch       CHKERRQ(MatHeaderReplace(A,&B));
10585e3038f0Sstefano_zampini     } else {
10595e3038f0Sstefano_zampini       *newmat = B;
10605e3038f0Sstefano_zampini     }
10615e3038f0Sstefano_zampini   } else {
10625e3038f0Sstefano_zampini     if (lreuse) {
10635f80ce2aSJacob Faibussowitsch       CHKERRQ(MatISGetLocalMat(*newmat,&lA));
10645e3038f0Sstefano_zampini       for (i=0;i<nr;i++) {
10655e3038f0Sstefano_zampini         for (j=0;j<nc;j++) {
10665e3038f0Sstefano_zampini           if (snest[i*nc+j]) {
10675f80ce2aSJacob Faibussowitsch             CHKERRQ(MatNestSetSubMat(lA,i,j,snest[i*nc+j]));
10689e7b2b25Sstefano_zampini             if (istrans[i*nc+j]) {
10695f80ce2aSJacob Faibussowitsch               CHKERRQ(MatDestroy(&snest[i*nc+j]));
10709e7b2b25Sstefano_zampini             }
10715e3038f0Sstefano_zampini           }
10725e3038f0Sstefano_zampini         }
10735e3038f0Sstefano_zampini       }
10745e3038f0Sstefano_zampini     } else {
10755b003df0Sstefano_zampini       PetscInt stl;
10765b003df0Sstefano_zampini       for (i=0,stl=0;i<nr;i++) {
10775f80ce2aSJacob Faibussowitsch         CHKERRQ(ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]));
10785b003df0Sstefano_zampini         stl  += lr[i];
10795e3038f0Sstefano_zampini       }
10805b003df0Sstefano_zampini       for (i=0,stl=0;i<nc;i++) {
10815f80ce2aSJacob Faibussowitsch         CHKERRQ(ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]));
10825b003df0Sstefano_zampini         stl  += lc[i];
10835e3038f0Sstefano_zampini       }
10845f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA));
1085ab4d48faSStefano Zampini       for (i=0;i<nr*nc;i++) {
10869e7b2b25Sstefano_zampini         if (istrans[i]) {
10875f80ce2aSJacob Faibussowitsch           CHKERRQ(MatDestroy(&snest[i]));
10889e7b2b25Sstefano_zampini         }
1089ab4d48faSStefano Zampini       }
10905f80ce2aSJacob Faibussowitsch       CHKERRQ(MatISSetLocalMat(*newmat,lA));
10915f80ce2aSJacob Faibussowitsch       CHKERRQ(MatDestroy(&lA));
10925e3038f0Sstefano_zampini     }
10935f80ce2aSJacob Faibussowitsch     CHKERRQ(MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY));
10945f80ce2aSJacob Faibussowitsch     CHKERRQ(MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY));
10955e3038f0Sstefano_zampini   }
10965e3038f0Sstefano_zampini 
10975b003df0Sstefano_zampini   /* Create local matrix in MATNEST format */
10985b003df0Sstefano_zampini   convert = PETSC_FALSE;
10995f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL));
11005b003df0Sstefano_zampini   if (convert) {
11015b003df0Sstefano_zampini     Mat              M;
11025b003df0Sstefano_zampini     MatISLocalFields lf;
11035b003df0Sstefano_zampini     PetscContainer   c;
11045b003df0Sstefano_zampini 
11055f80ce2aSJacob Faibussowitsch     CHKERRQ(MatISGetLocalMat(*newmat,&lA));
11065f80ce2aSJacob Faibussowitsch     CHKERRQ(MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M));
11075f80ce2aSJacob Faibussowitsch     CHKERRQ(MatISSetLocalMat(*newmat,M));
11085f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroy(&M));
11095b003df0Sstefano_zampini 
11105b003df0Sstefano_zampini     /* attach local fields to the matrix */
11115f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscNew(&lf));
11125f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc2(nr,&lf->rf,nc,&lf->cf));
11135b003df0Sstefano_zampini     for (i=0;i<nr;i++) {
11145b003df0Sstefano_zampini       PetscInt n,st;
11155b003df0Sstefano_zampini 
11165f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetLocalSize(islrow[i],&n));
11175f80ce2aSJacob Faibussowitsch       CHKERRQ(ISStrideGetInfo(islrow[i],&st,NULL));
11185f80ce2aSJacob Faibussowitsch       CHKERRQ(ISCreateStride(comm,n,st,1,&lf->rf[i]));
11195b003df0Sstefano_zampini     }
11205b003df0Sstefano_zampini     for (i=0;i<nc;i++) {
11215b003df0Sstefano_zampini       PetscInt n,st;
11225b003df0Sstefano_zampini 
11235f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetLocalSize(islcol[i],&n));
11245f80ce2aSJacob Faibussowitsch       CHKERRQ(ISStrideGetInfo(islcol[i],&st,NULL));
11255f80ce2aSJacob Faibussowitsch       CHKERRQ(ISCreateStride(comm,n,st,1,&lf->cf[i]));
11265b003df0Sstefano_zampini     }
11275b003df0Sstefano_zampini     lf->nr = nr;
11285b003df0Sstefano_zampini     lf->nc = nc;
11295f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c));
11305f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscContainerSetPointer(c,lf));
11315f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private));
11325f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c));
11335f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscContainerDestroy(&c));
11345b003df0Sstefano_zampini   }
11355b003df0Sstefano_zampini 
11365e3038f0Sstefano_zampini   /* Free workspace */
11375e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
11385f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&islrow[i]));
11395e3038f0Sstefano_zampini   }
11405e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
11415f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&islcol[i]));
11425e3038f0Sstefano_zampini   }
11435f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree6(isrow,iscol,islrow,islcol,snest,istrans));
11445f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree2(lr,lc));
11455e3038f0Sstefano_zampini   PetscFunctionReturn(0);
11465e3038f0Sstefano_zampini }
11475e3038f0Sstefano_zampini 
1148ad219c80Sstefano_zampini static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r)
1149ad219c80Sstefano_zampini {
1150ad219c80Sstefano_zampini   Mat_IS            *matis = (Mat_IS*)A->data;
1151ad219c80Sstefano_zampini   Vec               ll,rr;
1152ad219c80Sstefano_zampini   const PetscScalar *Y,*X;
1153ad219c80Sstefano_zampini   PetscScalar       *x,*y;
1154ad219c80Sstefano_zampini 
1155ad219c80Sstefano_zampini   PetscFunctionBegin;
1156ad219c80Sstefano_zampini   if (l) {
1157ad219c80Sstefano_zampini     ll   = matis->y;
11585f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArrayRead(l,&Y));
11595f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(ll,&y));
11605f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastBegin(matis->sf,MPIU_SCALAR,Y,y,MPI_REPLACE));
1161ad219c80Sstefano_zampini   } else {
1162ad219c80Sstefano_zampini     ll = NULL;
1163ad219c80Sstefano_zampini   }
1164ad219c80Sstefano_zampini   if (r) {
1165ad219c80Sstefano_zampini     rr   = matis->x;
11665f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArrayRead(r,&X));
11675f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(rr,&x));
11685f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastBegin(matis->csf,MPIU_SCALAR,X,x,MPI_REPLACE));
1169ad219c80Sstefano_zampini   } else {
1170ad219c80Sstefano_zampini     rr = NULL;
1171ad219c80Sstefano_zampini   }
1172ad219c80Sstefano_zampini   if (ll) {
11735f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastEnd(matis->sf,MPIU_SCALAR,Y,y,MPI_REPLACE));
11745f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(l,&Y));
11755f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(ll,&y));
1176ad219c80Sstefano_zampini   }
1177ad219c80Sstefano_zampini   if (rr) {
11785f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastEnd(matis->csf,MPIU_SCALAR,X,x,MPI_REPLACE));
11795f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(r,&X));
11805f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(rr,&x));
1181ad219c80Sstefano_zampini   }
11825f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDiagonalScale(matis->A,ll,rr));
1183ad219c80Sstefano_zampini   PetscFunctionReturn(0);
1184ad219c80Sstefano_zampini }
1185ad219c80Sstefano_zampini 
11867fa8f2d3SStefano Zampini static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo)
11877fa8f2d3SStefano Zampini {
11887fa8f2d3SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
11897fa8f2d3SStefano Zampini   MatInfo        info;
11903966268fSBarry Smith   PetscLogDouble isend[6],irecv[6];
11917fa8f2d3SStefano Zampini   PetscInt       bs;
11927fa8f2d3SStefano Zampini 
11937fa8f2d3SStefano Zampini   PetscFunctionBegin;
11945f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetBlockSize(A,&bs));
1195a2ccb5f9Sstefano_zampini   if (matis->A->ops->getinfo) {
11965f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetInfo(matis->A,MAT_LOCAL,&info));
11977fa8f2d3SStefano Zampini     isend[0] = info.nz_used;
11987fa8f2d3SStefano Zampini     isend[1] = info.nz_allocated;
11997fa8f2d3SStefano Zampini     isend[2] = info.nz_unneeded;
12007fa8f2d3SStefano Zampini     isend[3] = info.memory;
12017fa8f2d3SStefano Zampini     isend[4] = info.mallocs;
1202a2ccb5f9Sstefano_zampini   } else {
1203a2ccb5f9Sstefano_zampini     isend[0] = 0.;
1204a2ccb5f9Sstefano_zampini     isend[1] = 0.;
1205a2ccb5f9Sstefano_zampini     isend[2] = 0.;
1206a2ccb5f9Sstefano_zampini     isend[3] = 0.;
1207a2ccb5f9Sstefano_zampini     isend[4] = 0.;
1208a2ccb5f9Sstefano_zampini   }
1209314ce898Sstefano_zampini   isend[5] = matis->A->num_ass;
12107fa8f2d3SStefano Zampini   if (flag == MAT_LOCAL) {
12117fa8f2d3SStefano Zampini     ginfo->nz_used      = isend[0];
12127fa8f2d3SStefano Zampini     ginfo->nz_allocated = isend[1];
12137fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = isend[2];
12147fa8f2d3SStefano Zampini     ginfo->memory       = isend[3];
12157fa8f2d3SStefano Zampini     ginfo->mallocs      = isend[4];
1216314ce898Sstefano_zampini     ginfo->assemblies   = isend[5];
12177fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_MAX) {
12185f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPIU_Allreduce(isend,irecv,6,MPIU_PETSCLOGDOUBLE,MPI_MAX,PetscObjectComm((PetscObject)A)));
12197fa8f2d3SStefano Zampini 
12207fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
12217fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
12227fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
12237fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
12247fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
1225314ce898Sstefano_zampini     ginfo->assemblies   = irecv[5];
12267fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_SUM) {
12275f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPIU_Allreduce(isend,irecv,5,MPIU_PETSCLOGDOUBLE,MPI_SUM,PetscObjectComm((PetscObject)A)));
12287fa8f2d3SStefano Zampini 
12297fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
12307fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
12317fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
12327fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
12337fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
12347fa8f2d3SStefano Zampini     ginfo->assemblies   = A->num_ass;
12357fa8f2d3SStefano Zampini   }
12367fa8f2d3SStefano Zampini   ginfo->block_size        = bs;
12377fa8f2d3SStefano Zampini   ginfo->fill_ratio_given  = 0;
12387fa8f2d3SStefano Zampini   ginfo->fill_ratio_needed = 0;
12397fa8f2d3SStefano Zampini   ginfo->factor_mallocs    = 0;
12405e3038f0Sstefano_zampini   PetscFunctionReturn(0);
12415e3038f0Sstefano_zampini }
12425e3038f0Sstefano_zampini 
12438b9382cfSStefano Zampini static PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
1244d7f69cd0SStefano Zampini {
1245d7f69cd0SStefano Zampini   Mat                    C,lC,lA;
1246d7f69cd0SStefano Zampini 
1247d7f69cd0SStefano Zampini   PetscFunctionBegin;
1248cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) {
1249cf37664fSBarry Smith     ISLocalToGlobalMapping rl2g,cl2g;
12505f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreate(PetscObjectComm((PetscObject)A),&C));
12515f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N));
12525f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs)));
12535f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetType(C,MATIS));
12545f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetLocalToGlobalMapping(A,&rl2g,&cl2g));
12555f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetLocalToGlobalMapping(C,cl2g,rl2g));
1256e432b41dSStefano Zampini   } else C = *B;
1257d7f69cd0SStefano Zampini 
1258d7f69cd0SStefano Zampini   /* perform local transposition */
12595f80ce2aSJacob Faibussowitsch   CHKERRQ(MatISGetLocalMat(A,&lA));
12605f80ce2aSJacob Faibussowitsch   CHKERRQ(MatTranspose(lA,MAT_INITIAL_MATRIX,&lC));
12615f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetLocalToGlobalMapping(lC,lA->cmap->mapping,lA->rmap->mapping));
12625f80ce2aSJacob Faibussowitsch   CHKERRQ(MatISSetLocalMat(C,lC));
12635f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&lC));
1264d7f69cd0SStefano Zampini 
1265cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) {
1266d7f69cd0SStefano Zampini     *B = C;
1267d7f69cd0SStefano Zampini   } else {
12685f80ce2aSJacob Faibussowitsch     CHKERRQ(MatHeaderMerge(A,&C));
1269d7f69cd0SStefano Zampini   }
12705f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY));
12715f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY));
1272d7f69cd0SStefano Zampini   PetscFunctionReturn(0);
1273d7f69cd0SStefano Zampini }
1274d7f69cd0SStefano Zampini 
12758b9382cfSStefano Zampini static PetscErrorCode MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
12763fd1c9e7SStefano Zampini {
12773fd1c9e7SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
12783fd1c9e7SStefano Zampini 
12793fd1c9e7SStefano Zampini   PetscFunctionBegin;
12804b89b9cdSStefano Zampini   if (D) { /* MatShift_IS pass D = NULL */
12815f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD));
12825f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD));
12833fd1c9e7SStefano Zampini   }
12845f80ce2aSJacob Faibussowitsch   CHKERRQ(VecPointwiseDivide(is->y,is->y,is->counter));
12855f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDiagonalSet(is->A,is->y,insmode));
12863fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
12873fd1c9e7SStefano Zampini }
12883fd1c9e7SStefano Zampini 
12898b9382cfSStefano Zampini static PetscErrorCode MatShift_IS(Mat A,PetscScalar a)
12903fd1c9e7SStefano Zampini {
12914b89b9cdSStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
12923fd1c9e7SStefano Zampini 
12933fd1c9e7SStefano Zampini   PetscFunctionBegin;
12945f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSet(is->y,a));
12955f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDiagonalSet_IS(A,NULL,ADD_VALUES));
12963fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
12973fd1c9e7SStefano Zampini }
12983fd1c9e7SStefano Zampini 
1299f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1300f26d0771SStefano Zampini {
1301f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
1302f26d0771SStefano Zampini 
1303f26d0771SStefano Zampini   PetscFunctionBegin;
13042c71b3e2SJacob Faibussowitsch   PetscCheckFalse(m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION,PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column indices must be <= %d: they are %" PetscInt_FMT " %" PetscInt_FMT,MATIS_MAX_ENTRIES_INSERTION,m,n);
13055f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l));
13065f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l));
13075f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetValuesLocal_IS(A,m,rows_l,n,cols_l,values,addv));
1308f26d0771SStefano Zampini   PetscFunctionReturn(0);
1309f26d0771SStefano Zampini }
1310f26d0771SStefano Zampini 
1311f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1312f26d0771SStefano Zampini {
1313f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
1314f26d0771SStefano Zampini 
1315f26d0771SStefano Zampini   PetscFunctionBegin;
13162c71b3e2SJacob Faibussowitsch   PetscCheckFalse(m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION,PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column block indices must be <= %d: they are %" PetscInt_FMT " %" PetscInt_FMT,MATIS_MAX_ENTRIES_INSERTION,m,n);
13175f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l));
13185f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l));
13195f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetValuesBlockedLocal_IS(A,m,rows_l,n,cols_l,values,addv));
1320f26d0771SStefano Zampini   PetscFunctionReturn(0);
1321f26d0771SStefano Zampini }
1322f26d0771SStefano Zampini 
13237dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
1324a8116848SStefano Zampini {
1325a8116848SStefano Zampini   Mat               locmat,newlocmat;
1326a8116848SStefano Zampini   Mat_IS            *newmatis;
1327a8116848SStefano Zampini   const PetscInt    *idxs;
1328a8116848SStefano Zampini   PetscInt          i,m,n;
1329a8116848SStefano Zampini 
1330a8116848SStefano Zampini   PetscFunctionBegin;
1331a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
1332a8116848SStefano Zampini     PetscBool ismatis;
1333a8116848SStefano Zampini 
13345f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis));
1335*28b400f6SJacob Faibussowitsch     PetscCheck(ismatis,PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
1336a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
1337*28b400f6SJacob Faibussowitsch     PetscCheck(newmatis->getsub_ris,PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
1338*28b400f6SJacob Faibussowitsch     PetscCheck(newmatis->getsub_cis,PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
1339a8116848SStefano Zampini   }
1340a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
134176bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
134276bd3646SJed Brown     Vec               rtest,ltest;
134376bd3646SJed Brown     const PetscScalar *array;
134476bd3646SJed Brown 
13455f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreateVecs(mat,&ltest,&rtest));
13465f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetLocalSize(irow,&n));
13475f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(irow,&idxs));
1348a8116848SStefano Zampini     for (i=0;i<n;i++) {
13495f80ce2aSJacob Faibussowitsch       CHKERRQ(VecSetValue(rtest,idxs[i],1.0,ADD_VALUES));
1350a8116848SStefano Zampini     }
13515f80ce2aSJacob Faibussowitsch     CHKERRQ(VecAssemblyBegin(rtest));
13525f80ce2aSJacob Faibussowitsch     CHKERRQ(VecAssemblyEnd(rtest));
13535f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetLocalSize(rtest,&n));
13545f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetOwnershipRange(rtest,&m,NULL));
13555f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArrayRead(rtest,&array));
13562c71b3e2SJacob Faibussowitsch     for (i=0;i<n;i++) PetscCheckFalse(array[i] != 0. && array[i] != 1.,PETSC_COMM_SELF,PETSC_ERR_SUP,"Index %" PetscInt_FMT " counted %" PetscInt_FMT " times! Irow may not have duplicate entries",i+m,(PetscInt)PetscRealPart(array[i]));
13575f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(rtest,&array));
13585f80ce2aSJacob Faibussowitsch     CHKERRQ(ISRestoreIndices(irow,&idxs));
13595f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetLocalSize(icol,&n));
13605f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(icol,&idxs));
1361a8116848SStefano Zampini     for (i=0;i<n;i++) {
13625f80ce2aSJacob Faibussowitsch       CHKERRQ(VecSetValue(ltest,idxs[i],1.0,ADD_VALUES));
1363a8116848SStefano Zampini     }
13645f80ce2aSJacob Faibussowitsch     CHKERRQ(VecAssemblyBegin(ltest));
13655f80ce2aSJacob Faibussowitsch     CHKERRQ(VecAssemblyEnd(ltest));
13665f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetLocalSize(ltest,&n));
13675f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetOwnershipRange(ltest,&m,NULL));
13685f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArrayRead(ltest,&array));
13692c71b3e2SJacob Faibussowitsch     for (i=0;i<n;i++) PetscCheckFalse(array[i] != 0. && array[i] != 1.,PETSC_COMM_SELF,PETSC_ERR_SUP,"Index %" PetscInt_FMT " counted %" PetscInt_FMT " times! Icol may not have duplicate entries",i+m,(PetscInt)PetscRealPart(array[i]));
13705f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(ltest,&array));
13715f80ce2aSJacob Faibussowitsch     CHKERRQ(ISRestoreIndices(icol,&idxs));
13725f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDestroy(&rtest));
13735f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDestroy(&ltest));
137476bd3646SJed Brown   }
1375a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
1376a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
1377a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
1378a8116848SStefano Zampini     IS                     is;
1379a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
1380306cf5c7SStefano Zampini     PetscInt               ll,newloc,irbs,icbs,arbs,acbs,rbs,cbs;
138194342113SStefano Zampini     PetscBool              cong;
1382a8116848SStefano Zampini     MPI_Comm               comm;
1383a8116848SStefano Zampini 
13845f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectGetComm((PetscObject)mat,&comm));
13855f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetBlockSizes(mat,&arbs,&acbs));
13865f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetBlockSize(irow,&irbs));
13875f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetBlockSize(icol,&icbs));
1388306cf5c7SStefano Zampini     rbs  = arbs == irbs ? irbs : 1;
1389306cf5c7SStefano Zampini     cbs  = acbs == icbs ? icbs : 1;
13905f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetLocalSize(irow,&m));
13915f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetLocalSize(icol,&n));
13925f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreate(comm,newmat));
13935f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetType(*newmat,MATIS));
13945f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE));
13955f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetBlockSizes(*newmat,rbs,cbs));
1396a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
13975f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(irow,&idxs));
13985f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLayoutMapLocal(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs));
13995f80ce2aSJacob Faibussowitsch     CHKERRQ(ISRestoreIndices(irow,&idxs));
14005f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArrayzero(matis->sf_rootdata,matis->sf->nroots));
1401a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
14025f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(lidxs));
14035f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(lgidxs));
14045f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
14055f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
14063d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
14075f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(newloc,&newgidxs));
14085f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(newloc,&lidxs));
14093d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++)
1410a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
1411a8116848SStefano Zampini         lidxs[newloc] = i;
1412a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
1413a8116848SStefano Zampini       }
14145f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is));
14155f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingCreateIS(is,&rl2g));
14165f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingSetBlockSize(rl2g,rbs));
14175f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&is));
1418a8116848SStefano Zampini     /* local is to extract local submatrix */
1419a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
14205f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris));
14215f80ce2aSJacob Faibussowitsch     CHKERRQ(MatHasCongruentLayouts(mat,&cong));
142294342113SStefano Zampini     if (cong && irow == icol && matis->csf == matis->sf) {
14235f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g));
14245f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectReference((PetscObject)newmatis->getsub_ris));
1425a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
1426a8116848SStefano Zampini     } else {
1427a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
1428a8116848SStefano Zampini 
1429a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
14305f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetIndices(icol,&idxs));
14315f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLayoutMapLocal(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs));
14325f80ce2aSJacob Faibussowitsch       CHKERRQ(ISRestoreIndices(icol,&idxs));
14335f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArrayzero(matis->csf_rootdata,matis->csf->nroots));
1434a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
14355f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(lidxs));
14365f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(lgidxs));
14375f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata,MPI_REPLACE));
14385f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata,MPI_REPLACE));
14393d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
14405f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(newloc,&newgidxs));
14415f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(newloc,&lidxs));
14423d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++)
1443a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
1444a8116848SStefano Zampini           lidxs[newloc] = i;
1445a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
1446a8116848SStefano Zampini         }
14475f80ce2aSJacob Faibussowitsch       CHKERRQ(ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is));
14485f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingCreateIS(is,&cl2g));
14495f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingSetBlockSize(cl2g,cbs));
14505f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&is));
1451a8116848SStefano Zampini       /* local is to extract local submatrix */
14525f80ce2aSJacob Faibussowitsch       CHKERRQ(ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis));
14535f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g));
14545f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingDestroy(&cl2g));
1455a8116848SStefano Zampini     }
14565f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingDestroy(&rl2g));
1457a8116848SStefano Zampini   } else {
14585f80ce2aSJacob Faibussowitsch     CHKERRQ(MatISGetLocalMat(*newmat,&newlocmat));
1459a8116848SStefano Zampini   }
14605f80ce2aSJacob Faibussowitsch   CHKERRQ(MatISGetLocalMat(mat,&locmat));
1461a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
14625f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreateSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat));
1463a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
14645f80ce2aSJacob Faibussowitsch     CHKERRQ(MatISSetLocalMat(*newmat,newlocmat));
14655f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroy(&newlocmat));
1466a8116848SStefano Zampini   }
14675f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY));
14685f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY));
1469a8116848SStefano Zampini   PetscFunctionReturn(0);
1470a8116848SStefano Zampini }
1471a8116848SStefano Zampini 
1472a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
14732b404112SStefano Zampini {
14742b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
14752b404112SStefano Zampini   PetscBool      ismatis;
14762b404112SStefano Zampini 
14772b404112SStefano Zampini   PetscFunctionBegin;
14785f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis));
1479*28b400f6SJacob Faibussowitsch   PetscCheck(ismatis,PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
14802b404112SStefano Zampini   b = (Mat_IS*)B->data;
14815f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCopy(a->A,b->A,str));
14825f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectStateIncrease((PetscObject)B));
14832b404112SStefano Zampini   PetscFunctionReturn(0);
14842b404112SStefano Zampini }
14852b404112SStefano Zampini 
1486a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
14876bd84002SStefano Zampini {
1488527b2640SStefano Zampini   Vec               v;
1489527b2640SStefano Zampini   const PetscScalar *array;
1490527b2640SStefano Zampini   PetscInt          i,n;
14916bd84002SStefano Zampini 
14926bd84002SStefano Zampini   PetscFunctionBegin;
1493527b2640SStefano Zampini   *missing = PETSC_FALSE;
14945f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreateVecs(A,NULL,&v));
14955f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetDiagonal(A,v));
14965f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetLocalSize(v,&n));
14975f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(v,&array));
1498527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
14995f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(v,&array));
15005f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&v));
1501527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
1502527b2640SStefano Zampini   if (d) {
1503527b2640SStefano Zampini     *d = -1;
1504527b2640SStefano Zampini     if (*missing) {
1505527b2640SStefano Zampini       PetscInt rstart;
15065f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetOwnershipRange(A,&rstart,NULL));
1507527b2640SStefano Zampini       *d = i+rstart;
1508527b2640SStefano Zampini     }
1509527b2640SStefano Zampini   }
15106bd84002SStefano Zampini   PetscFunctionReturn(0);
15116bd84002SStefano Zampini }
15126bd84002SStefano Zampini 
1513cf0a3239SStefano Zampini static PetscErrorCode MatISSetUpSF_IS(Mat B)
151428f4e0baSStefano Zampini {
151528f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
151628f4e0baSStefano Zampini   const PetscInt *gidxs;
15174f2d7cafSStefano Zampini   PetscInt       nleaves;
151828f4e0baSStefano Zampini 
151928f4e0baSStefano Zampini   PetscFunctionBegin;
15204f2d7cafSStefano Zampini   if (matis->sf) PetscFunctionReturn(0);
15215f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf));
15225f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetIndices(matis->rmapping,&gidxs));
15235f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetSize(matis->rmapping,&nleaves));
15245f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs));
15255f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingRestoreIndices(matis->rmapping,&gidxs));
15265f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata));
1527e432b41dSStefano Zampini   if (matis->rmapping != matis->cmapping) { /* setup SF for columns */
15285f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingGetSize(matis->cmapping,&nleaves));
15295f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf));
15305f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingGetIndices(matis->cmapping,&gidxs));
15315f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs));
15325f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingRestoreIndices(matis->cmapping,&gidxs));
15335f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata));
1534a8116848SStefano Zampini   } else {
1535a8116848SStefano Zampini     matis->csf = matis->sf;
1536a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
1537a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
1538a8116848SStefano Zampini   }
153928f4e0baSStefano Zampini   PetscFunctionReturn(0);
154028f4e0baSStefano Zampini }
15412e1947a5SStefano Zampini 
1542eb82efa4SStefano Zampini /*@
154375d48cdbSStefano Zampini    MatISStoreL2L - Store local-to-local operators during the Galerkin process of MatPtAP.
154475d48cdbSStefano Zampini 
1545d083f849SBarry Smith    Collective
154675d48cdbSStefano Zampini 
154775d48cdbSStefano Zampini    Input Parameters:
154875d48cdbSStefano Zampini +  A - the matrix
154975d48cdbSStefano Zampini -  store - the boolean flag
155075d48cdbSStefano Zampini 
155175d48cdbSStefano Zampini    Level: advanced
155275d48cdbSStefano Zampini 
155375d48cdbSStefano Zampini    Notes:
155475d48cdbSStefano Zampini 
155575d48cdbSStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatPtAP()
155675d48cdbSStefano Zampini @*/
155775d48cdbSStefano Zampini PetscErrorCode MatISStoreL2L(Mat A, PetscBool store)
155875d48cdbSStefano Zampini {
155975d48cdbSStefano Zampini   PetscFunctionBegin;
156075d48cdbSStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
156175d48cdbSStefano Zampini   PetscValidType(A,1);
156275d48cdbSStefano Zampini   PetscValidLogicalCollectiveBool(A,store,2);
15635f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(A,"MatISStoreL2L_C",(Mat,PetscBool),(A,store)));
156475d48cdbSStefano Zampini   PetscFunctionReturn(0);
156575d48cdbSStefano Zampini }
156675d48cdbSStefano Zampini 
156775d48cdbSStefano Zampini static PetscErrorCode MatISStoreL2L_IS(Mat A, PetscBool store)
156875d48cdbSStefano Zampini {
156975d48cdbSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(A->data);
157075d48cdbSStefano Zampini 
157175d48cdbSStefano Zampini   PetscFunctionBegin;
157275d48cdbSStefano Zampini   matis->storel2l = store;
157375d48cdbSStefano Zampini   if (!store) {
15745f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",NULL));
157575d48cdbSStefano Zampini   }
157675d48cdbSStefano Zampini   PetscFunctionReturn(0);
157775d48cdbSStefano Zampini }
157875d48cdbSStefano Zampini 
157975d48cdbSStefano Zampini /*@
1580f03112d0SStefano Zampini    MatISFixLocalEmpty - Compress out zero local rows from the local matrices
1581f03112d0SStefano Zampini 
1582d083f849SBarry Smith    Collective
1583f03112d0SStefano Zampini 
1584f03112d0SStefano Zampini    Input Parameters:
1585f03112d0SStefano Zampini +  A - the matrix
1586f03112d0SStefano Zampini -  fix - the boolean flag
1587f03112d0SStefano Zampini 
1588f03112d0SStefano Zampini    Level: advanced
1589f03112d0SStefano Zampini 
1590f03112d0SStefano Zampini    Notes: When fix is true, new local matrices and l2g maps are generated during the final assembly process.
1591f03112d0SStefano Zampini 
1592f03112d0SStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatAssemblyEnd(), MAT_FINAL_ASSEMBLY
1593f03112d0SStefano Zampini @*/
1594f03112d0SStefano Zampini PetscErrorCode MatISFixLocalEmpty(Mat A, PetscBool fix)
1595f03112d0SStefano Zampini {
1596f03112d0SStefano Zampini   PetscFunctionBegin;
1597f03112d0SStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
1598f03112d0SStefano Zampini   PetscValidType(A,1);
1599f03112d0SStefano Zampini   PetscValidLogicalCollectiveBool(A,fix,2);
16005f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(A,"MatISFixLocalEmpty_C",(Mat,PetscBool),(A,fix)));
1601f03112d0SStefano Zampini   PetscFunctionReturn(0);
1602f03112d0SStefano Zampini }
1603f03112d0SStefano Zampini 
1604f03112d0SStefano Zampini static PetscErrorCode MatISFixLocalEmpty_IS(Mat A, PetscBool fix)
1605f03112d0SStefano Zampini {
1606f03112d0SStefano Zampini   Mat_IS *matis = (Mat_IS*)(A->data);
1607f03112d0SStefano Zampini 
1608f03112d0SStefano Zampini   PetscFunctionBegin;
1609f03112d0SStefano Zampini   matis->locempty = fix;
1610f03112d0SStefano Zampini   PetscFunctionReturn(0);
1611f03112d0SStefano Zampini }
1612f03112d0SStefano Zampini 
1613f03112d0SStefano Zampini /*@
1614a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
1615a88811baSStefano Zampini 
1616d083f849SBarry Smith    Collective
1617a88811baSStefano Zampini 
1618a88811baSStefano Zampini    Input Parameters:
1619a88811baSStefano Zampini +  B - the matrix
1620a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1621a88811baSStefano Zampini            (same value is used for all local rows)
1622a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
1623a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
1624a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
1625a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
1626a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
1627a88811baSStefano Zampini            the diagonal entry even if it is zero.
1628a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1629a88811baSStefano Zampini            submatrix (same value is used for all local rows).
1630a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
1631a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
1632a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
1633a88811baSStefano Zampini            structure. The size of this array is equal to the number
1634a88811baSStefano Zampini            of local rows, i.e 'm'.
1635a88811baSStefano Zampini 
1636a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
1637a88811baSStefano Zampini 
1638a88811baSStefano Zampini    Level: intermediate
1639a88811baSStefano Zampini 
164095452b02SPatrick Sanan    Notes:
164195452b02SPatrick Sanan     This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
1642a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
1643a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
1644a88811baSStefano Zampini 
16453c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
1646a88811baSStefano Zampini @*/
16472e1947a5SStefano Zampini PetscErrorCode MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
16482e1947a5SStefano Zampini {
16492e1947a5SStefano Zampini   PetscFunctionBegin;
16502e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
16512e1947a5SStefano Zampini   PetscValidType(B,1);
16525f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz)));
16532e1947a5SStefano Zampini   PetscFunctionReturn(0);
16542e1947a5SStefano Zampini }
16552e1947a5SStefano Zampini 
1656844bd0d7SStefano Zampini /* this is used by DMDA */
1657844bd0d7SStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
16582e1947a5SStefano Zampini {
16592e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
166028f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
16612e1947a5SStefano Zampini 
16622e1947a5SStefano Zampini   PetscFunctionBegin;
16635f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetUp(B));
16644f2d7cafSStefano Zampini   if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz;
16654f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
16664f2d7cafSStefano Zampini 
16674f2d7cafSStefano Zampini   if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz;
16684f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
16694f2d7cafSStefano Zampini 
16705f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
16715f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetSize(matis->A,NULL,&nlocalcols));
16725f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetBlockSize(matis->A,&bs));
16735f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
16744f2d7cafSStefano Zampini 
16754f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
16765f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata));
16770f2f62c7SStefano Zampini #if defined(PETSC_HAVE_HYPRE)
16785f80ce2aSJacob Faibussowitsch   CHKERRQ(MatHYPRESetPreallocation(matis->A,0,matis->sf_leafdata,0,NULL));
16790f2f62c7SStefano Zampini #endif
16804f2d7cafSStefano Zampini 
1681fc989267SStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) {
1682fc989267SStefano Zampini     PetscInt b;
1683fc989267SStefano Zampini 
1684fc989267SStefano Zampini     matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
1685fc989267SStefano Zampini     for (b=1;b<bs;b++) {
1686fc989267SStefano Zampini       matis->sf_leafdata[i] = PetscMax(matis->sf_leafdata[i],matis->sf_leafdata[i*bs+b]/bs);
1687fc989267SStefano Zampini     }
1688fc989267SStefano Zampini   }
16895f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata));
16904f2d7cafSStefano Zampini 
169100a59248SStefano Zampini   nlocalcols /= bs;
169200a59248SStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols - i);
16935f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata));
16940f2f62c7SStefano Zampini 
16950f2f62c7SStefano Zampini   /* for other matrix types */
16965f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetUp(matis->A));
16972e1947a5SStefano Zampini   PetscFunctionReturn(0);
16982e1947a5SStefano Zampini }
1699b4319ba4SBarry Smith 
17003927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
17013927de2eSStefano Zampini {
17023927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
17033927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
1704ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
17053927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
17063927de2eSStefano Zampini   PetscInt        lrows,lcols;
17073927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
1708f03112d0SStefano Zampini   PetscMPIInt     size;
17093927de2eSStefano Zampini   PetscBool       isdense,issbaij;
17103927de2eSStefano Zampini   PetscErrorCode  ierr;
17113927de2eSStefano Zampini 
17123927de2eSStefano Zampini   PetscFunctionBegin;
17135f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A),&size));
17145f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetSize(A,&rows,&cols));
17155f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetBlockSize(A,&bs));
17165f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetSize(matis->A,&local_rows,&local_cols));
17175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense));
17185f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij));
17195f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetIndices(matis->rmapping,&global_indices_r));
1720e432b41dSStefano Zampini   if (matis->rmapping != matis->cmapping) {
17215f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingGetIndices(matis->cmapping,&global_indices_c));
17220dfc91b7SStefano Zampini   } else global_indices_c = global_indices_r;
1723ecf5a873SStefano Zampini 
17245f80ce2aSJacob Faibussowitsch   if (issbaij) CHKERRQ(MatGetRowUpperTriangular(matis->A));
17253927de2eSStefano Zampini   /*
1726ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
17273927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
17283927de2eSStefano Zampini   */
17295f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetLocalSize(A,&lrows,&lcols));
17303927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
17313927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
17325f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(rows,&row_ownership));
17335f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges));
1734f03112d0SStefano Zampini   for (i=0;i<size;i++) {
17355f80ce2aSJacob Faibussowitsch     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) row_ownership[j] = i;
17363927de2eSStefano Zampini   }
17375f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges));
17383927de2eSStefano Zampini 
17393927de2eSStefano Zampini   /*
17403927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
17413927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
17423927de2eSStefano Zampini   */
17435f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz));
17443927de2eSStefano Zampini   /* preallocation as a MATAIJ */
17453927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
17463927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
174712dfadf8SStefano Zampini       PetscInt owner = row_ownership[global_indices_r[i]];
174812dfadf8SStefano Zampini       for (j=0;j<local_cols;j++) {
1749ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
17503927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1]) { /* diag block */
17513927de2eSStefano Zampini           my_dnz[i] += 1;
17523927de2eSStefano Zampini         } else { /* offdiag block */
17533927de2eSStefano Zampini           my_onz[i] += 1;
17543927de2eSStefano Zampini         }
17553927de2eSStefano Zampini       }
17563927de2eSStefano Zampini     }
1757bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
1758bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
1759bb1015c3SStefano Zampini     PetscBool      done;
17605f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done));
17615f80ce2aSJacob Faibussowitsch     PetscCheck(done,PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1762bb1015c3SStefano Zampini     jptr = jj;
1763bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
1764bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
1765bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
1766bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
1767bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
1768bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1]) { /* diag block */
1769bb1015c3SStefano Zampini           my_dnz[i] += 1;
1770bb1015c3SStefano Zampini         } else { /* offdiag block */
1771bb1015c3SStefano Zampini           my_onz[i] += 1;
1772bb1015c3SStefano Zampini         }
1773bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
1774bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
1775bb1015c3SStefano Zampini           owner = row_ownership[index_col];
1776bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1]) {
1777bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
1778bb1015c3SStefano Zampini           } else {
1779bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
1780bb1015c3SStefano Zampini           }
1781bb1015c3SStefano Zampini         }
1782bb1015c3SStefano Zampini       }
1783bb1015c3SStefano Zampini     }
17845f80ce2aSJacob Faibussowitsch     CHKERRQ(MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done));
17855f80ce2aSJacob Faibussowitsch     PetscCheck(done,PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1786bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
17873927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
17883927de2eSStefano Zampini       const PetscInt *cols;
1789ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
17905f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetRow(matis->A,i,&ncols,&cols,NULL));
17913927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
17923927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
1793ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
17943927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1]) { /* diag block */
17953927de2eSStefano Zampini           my_dnz[i] += 1;
17963927de2eSStefano Zampini         } else { /* offdiag block */
17973927de2eSStefano Zampini           my_onz[i] += 1;
17983927de2eSStefano Zampini         }
17993927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
1800d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
18013927de2eSStefano Zampini           owner = row_ownership[index_col];
18023927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1]) {
1803d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
18043927de2eSStefano Zampini           } else {
1805d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
18063927de2eSStefano Zampini           }
18073927de2eSStefano Zampini         }
18083927de2eSStefano Zampini       }
18095f80ce2aSJacob Faibussowitsch       CHKERRQ(MatRestoreRow(matis->A,i,&ncols,&cols,NULL));
18103927de2eSStefano Zampini     }
18113927de2eSStefano Zampini   }
1812ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
18135f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingRestoreIndices(matis->cmapping,&global_indices_c));
1814ecf5a873SStefano Zampini   }
18155f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingRestoreIndices(matis->rmapping,&global_indices_r));
18165f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(row_ownership));
1817ecf5a873SStefano Zampini 
1818ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
18193927de2eSStefano Zampini   if (maxreduce) {
18205f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX));
18215f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX));
18225f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX));
18235f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX));
18243927de2eSStefano Zampini   } else {
18255f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM));
18265f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM));
18275f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM));
18285f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM));
18293927de2eSStefano Zampini   }
18305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree2(my_dnz,my_onz));
18313927de2eSStefano Zampini 
18323927de2eSStefano Zampini   /* Resize preallocation if overestimated */
18333927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
18343927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
18353927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
18363927de2eSStefano Zampini   }
18371670daf9Sstefano_zampini 
18381670daf9Sstefano_zampini   /* Set preallocation */
18395f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetBlockSizesFromMats(B,A,A));
18405f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJSetPreallocation(B,0,dnz));
18415f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMPIAIJSetPreallocation(B,0,dnz,0,onz));
184253b44cf5SStefano Zampini   for (i=0;i<lrows;i+=bs) {
184353b44cf5SStefano Zampini     PetscInt b, d = dnz[i],o = onz[i];
184453b44cf5SStefano Zampini 
184553b44cf5SStefano Zampini     for (b=1;b<bs;b++) {
184653b44cf5SStefano Zampini       d = PetscMax(d,dnz[i+b]);
184753b44cf5SStefano Zampini       o = PetscMax(o,onz[i+b]);
184853b44cf5SStefano Zampini     }
184953b44cf5SStefano Zampini     dnz[i/bs] = PetscMin(d/bs + d%bs,lcols/bs);
185053b44cf5SStefano Zampini     onz[i/bs] = PetscMin(o/bs + o%bs,(cols-lcols)/bs);
18513927de2eSStefano Zampini   }
18525f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqBAIJSetPreallocation(B,bs,0,dnz));
18535f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz));
18545f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz));
18553927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
18565f80ce2aSJacob Faibussowitsch   if (issbaij) CHKERRQ(MatRestoreRowUpperTriangular(matis->A));
18575f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE));
18583927de2eSStefano Zampini   PetscFunctionReturn(0);
18593927de2eSStefano Zampini }
18603927de2eSStefano Zampini 
1861487b449aSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_IS_XAIJ(Mat mat, MatType mtype, MatReuse reuse, Mat *M)
1862b7ce53b6SStefano Zampini {
1863b7ce53b6SStefano Zampini   Mat_IS            *matis = (Mat_IS*)(mat->data);
1864487b449aSStefano Zampini   Mat               local_mat,MT;
186553b44cf5SStefano Zampini   PetscInt          rbs,cbs,rows,cols,lrows,lcols;
1866b7ce53b6SStefano Zampini   PetscInt          local_rows,local_cols;
1867b9ed4604SStefano Zampini   PetscBool         isseqdense,isseqsbaij,isseqaij,isseqbaij;
1868f03112d0SStefano Zampini   PetscMPIInt       size;
18691683a169SBarry Smith   const PetscScalar *array;
1870b7ce53b6SStefano Zampini 
1871b7ce53b6SStefano Zampini   PetscFunctionBegin;
18725f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
1873f03112d0SStefano Zampini   if (size == 1 && mat->rmap->N == matis->A->rmap->N && mat->cmap->N == matis->A->cmap->N) {
18741670daf9Sstefano_zampini     Mat      B;
187553b44cf5SStefano Zampini     IS       irows = NULL,icols = NULL;
1876487b449aSStefano Zampini     PetscInt rbs,cbs;
18771670daf9Sstefano_zampini 
18785f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingGetBlockSize(matis->rmapping,&rbs));
18795f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingGetBlockSize(matis->cmapping,&cbs));
188053b44cf5SStefano Zampini     if (reuse != MAT_REUSE_MATRIX) { /* check if l2g maps are one-to-one */
188153b44cf5SStefano Zampini       IS             rows,cols;
188253b44cf5SStefano Zampini       const PetscInt *ridxs,*cidxs;
188353b44cf5SStefano Zampini       PetscInt       i,nw,*work;
188453b44cf5SStefano Zampini 
18855f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingGetBlockIndices(matis->rmapping,&ridxs));
18865f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingGetSize(matis->rmapping,&nw));
188753b44cf5SStefano Zampini       nw   = nw/rbs;
18885f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscCalloc1(nw,&work));
188953b44cf5SStefano Zampini       for (i=0;i<nw;i++) work[ridxs[i]] += 1;
189053b44cf5SStefano Zampini       for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break;
189153b44cf5SStefano Zampini       if (i == nw) {
18925f80ce2aSJacob Faibussowitsch         CHKERRQ(ISCreateBlock(PETSC_COMM_SELF,rbs,nw,ridxs,PETSC_USE_POINTER,&rows));
18935f80ce2aSJacob Faibussowitsch         CHKERRQ(ISSetPermutation(rows));
18945f80ce2aSJacob Faibussowitsch         CHKERRQ(ISInvertPermutation(rows,PETSC_DECIDE,&irows));
18955f80ce2aSJacob Faibussowitsch         CHKERRQ(ISDestroy(&rows));
189653b44cf5SStefano Zampini       }
18975f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingRestoreBlockIndices(matis->rmapping,&ridxs));
18985f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(work));
1899e432b41dSStefano Zampini       if (irows && matis->rmapping != matis->cmapping) {
19005f80ce2aSJacob Faibussowitsch         CHKERRQ(ISLocalToGlobalMappingGetBlockIndices(matis->cmapping,&cidxs));
19015f80ce2aSJacob Faibussowitsch         CHKERRQ(ISLocalToGlobalMappingGetSize(matis->cmapping,&nw));
190253b44cf5SStefano Zampini         nw   = nw/cbs;
19035f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscCalloc1(nw,&work));
190453b44cf5SStefano Zampini         for (i=0;i<nw;i++) work[cidxs[i]] += 1;
190553b44cf5SStefano Zampini         for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break;
190653b44cf5SStefano Zampini         if (i == nw) {
19075f80ce2aSJacob Faibussowitsch           CHKERRQ(ISCreateBlock(PETSC_COMM_SELF,cbs,nw,cidxs,PETSC_USE_POINTER,&cols));
19085f80ce2aSJacob Faibussowitsch           CHKERRQ(ISSetPermutation(cols));
19095f80ce2aSJacob Faibussowitsch           CHKERRQ(ISInvertPermutation(cols,PETSC_DECIDE,&icols));
19105f80ce2aSJacob Faibussowitsch           CHKERRQ(ISDestroy(&cols));
191153b44cf5SStefano Zampini         }
19125f80ce2aSJacob Faibussowitsch         CHKERRQ(ISLocalToGlobalMappingRestoreBlockIndices(matis->cmapping,&cidxs));
19135f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscFree(work));
191453b44cf5SStefano Zampini       } else if (irows) {
19155f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscObjectReference((PetscObject)irows));
191653b44cf5SStefano Zampini         icols = irows;
191753b44cf5SStefano Zampini       }
191853b44cf5SStefano Zampini     } else {
19195f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject*)&irows));
19205f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject*)&icols));
19215f80ce2aSJacob Faibussowitsch       if (irows) CHKERRQ(PetscObjectReference((PetscObject)irows));
19225f80ce2aSJacob Faibussowitsch       if (icols) CHKERRQ(PetscObjectReference((PetscObject)icols));
192353b44cf5SStefano Zampini     }
192453b44cf5SStefano Zampini     if (!irows || !icols) {
19255f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&icols));
19265f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&irows));
192753b44cf5SStefano Zampini       goto general_assembly;
192853b44cf5SStefano Zampini     }
19295f80ce2aSJacob Faibussowitsch     CHKERRQ(MatConvert(matis->A,mtype,MAT_INITIAL_MATRIX,&B));
1930487b449aSStefano Zampini     if (reuse != MAT_INPLACE_MATRIX) {
19315f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreateSubMatrix(B,irows,icols,reuse,M));
19325f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject)irows));
19335f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject)icols));
1934487b449aSStefano Zampini     } else {
1935487b449aSStefano Zampini       Mat C;
1936487b449aSStefano Zampini 
19375f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreateSubMatrix(B,irows,icols,MAT_INITIAL_MATRIX,&C));
19385f80ce2aSJacob Faibussowitsch       CHKERRQ(MatHeaderReplace(mat,&C));
1939487b449aSStefano Zampini     }
19405f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroy(&B));
19415f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&icols));
19425f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&irows));
19437c03b4e8SStefano Zampini     PetscFunctionReturn(0);
19447c03b4e8SStefano Zampini   }
194553b44cf5SStefano Zampini general_assembly:
19465f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetSize(mat,&rows,&cols));
19475f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetBlockSize(matis->rmapping,&rbs));
19485f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetBlockSize(matis->cmapping,&cbs));
19495f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetLocalSize(mat,&lrows,&lcols));
19505f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetSize(matis->A,&local_rows,&local_cols));
19515f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense));
19525f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij));
19535f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij));
19545f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij));
19552c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name);
195676bd3646SJed Brown   if (PetscDefined (USE_DEBUG)) {
195776bd3646SJed Brown     PetscBool         lb[4],bb[4];
195876bd3646SJed Brown 
1959b9ed4604SStefano Zampini     lb[0] = isseqdense;
1960b9ed4604SStefano Zampini     lb[1] = isseqaij;
1961b9ed4604SStefano Zampini     lb[2] = isseqbaij;
1962b9ed4604SStefano Zampini     lb[3] = isseqsbaij;
19635f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat)));
19642c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!bb[0] && !bb[1] && !bb[2] && !bb[3],PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type");
196576bd3646SJed Brown   }
1966b7ce53b6SStefano Zampini 
1967487b449aSStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
19685f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreate(PetscObjectComm((PetscObject)mat),&MT));
19695f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetSizes(MT,lrows,lcols,rows,cols));
19705f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetType(MT,mtype));
19715f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetBlockSizes(MT,rbs,cbs));
19725f80ce2aSJacob Faibussowitsch     CHKERRQ(MatISSetMPIXAIJPreallocation_Private(mat,MT,PETSC_FALSE));
1973b7ce53b6SStefano Zampini   } else {
197453b44cf5SStefano Zampini     PetscInt mrbs,mcbs,mrows,mcols,mlrows,mlcols;
1975487b449aSStefano Zampini 
1976b7ce53b6SStefano Zampini     /* some checks */
1977487b449aSStefano Zampini     MT   = *M;
19785f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetBlockSizes(MT,&mrbs,&mcbs));
19795f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetSize(MT,&mrows,&mcols));
19805f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetLocalSize(MT,&mlrows,&mlcols));
19812c71b3e2SJacob Faibussowitsch     PetscCheckFalse(mrows != rows,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%" PetscInt_FMT " != %" PetscInt_FMT ")",rows,mrows);
19822c71b3e2SJacob Faibussowitsch     PetscCheckFalse(mcols != cols,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%" PetscInt_FMT " != %" PetscInt_FMT ")",cols,mcols);
19832c71b3e2SJacob Faibussowitsch     PetscCheckFalse(mlrows != lrows,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%" PetscInt_FMT " != %" PetscInt_FMT ")",lrows,mlrows);
19842c71b3e2SJacob Faibussowitsch     PetscCheckFalse(mlcols != lcols,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%" PetscInt_FMT " != %" PetscInt_FMT ")",lcols,mlcols);
19852c71b3e2SJacob Faibussowitsch     PetscCheckFalse(mrbs != rbs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong row block size (%" PetscInt_FMT " != %" PetscInt_FMT ")",rbs,mrbs);
19862c71b3e2SJacob Faibussowitsch     PetscCheckFalse(mcbs != cbs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong col block size (%" PetscInt_FMT " != %" PetscInt_FMT ")",cbs,mcbs);
19875f80ce2aSJacob Faibussowitsch     CHKERRQ(MatZeroEntries(MT));
1988b7ce53b6SStefano Zampini   }
1989d9a9e74cSStefano Zampini 
19908546b261SStefano Zampini   if (isseqsbaij || isseqbaij) {
19915f80ce2aSJacob Faibussowitsch     CHKERRQ(MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&local_mat));
19928546b261SStefano Zampini     isseqaij = PETSC_TRUE;
1993d9a9e74cSStefano Zampini   } else {
19945f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectReference((PetscObject)matis->A));
1995d9a9e74cSStefano Zampini     local_mat = matis->A;
1996d9a9e74cSStefano Zampini   }
1997686e3a49SStefano Zampini 
1998b7ce53b6SStefano Zampini   /* Set values */
19995f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetLocalToGlobalMapping(MT,matis->rmapping,matis->cmapping));
2000b9ed4604SStefano Zampini   if (isseqdense) { /* special case for dense local matrices */
200165066ba5SStefano Zampini     PetscInt          i,*dummy;
2002ecf5a873SStefano Zampini 
20035f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(PetscMax(local_rows,local_cols),&dummy));
200465066ba5SStefano Zampini     for (i=0;i<PetscMax(local_rows,local_cols);i++) dummy[i] = i;
20055f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_FALSE));
20065f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDenseGetArrayRead(local_mat,&array));
20075f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetValuesLocal(MT,local_rows,dummy,local_cols,dummy,array,ADD_VALUES));
20085f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDenseRestoreArrayRead(local_mat,&array));
20095f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(dummy));
2010686e3a49SStefano Zampini   } else if (isseqaij) {
20116afe12f5SStefano Zampini     const PetscInt *blocks;
20126afe12f5SStefano Zampini     PetscInt       i,nvtxs,*xadj,*adjncy, nb;
2013686e3a49SStefano Zampini     PetscBool      done;
20141683a169SBarry Smith     PetscScalar    *sarray;
2015686e3a49SStefano Zampini 
20165f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done));
2017*28b400f6SJacob Faibussowitsch     PetscCheck(done,PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
20185f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJGetArray(local_mat,&sarray));
20195f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetVariableBlockSizes(local_mat,&nb,&blocks));
20206afe12f5SStefano Zampini     if (nb) { /* speed up assembly for special blocked matrices (used by BDDC) */
20216afe12f5SStefano Zampini       PetscInt sum;
20226afe12f5SStefano Zampini 
20236afe12f5SStefano Zampini       for (i=0,sum=0;i<nb;i++) sum += blocks[i];
20246afe12f5SStefano Zampini       if (sum == nvtxs) {
20256afe12f5SStefano Zampini         PetscInt r;
20266afe12f5SStefano Zampini 
20276afe12f5SStefano Zampini         for (i=0,r=0;i<nb;i++) {
20286bdcaf15SBarry Smith           PetscAssert(blocks[i] == xadj[r+1] - xadj[r],PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid block sizes prescribed for block %" PetscInt_FMT ": expected %" PetscInt_FMT ", got %" PetscInt_FMT,i,blocks[i],xadj[r+1] - xadj[r]);
20295f80ce2aSJacob Faibussowitsch           CHKERRQ(MatSetValuesLocal(MT,blocks[i],adjncy+xadj[r],blocks[i],adjncy+xadj[r],sarray+xadj[r],ADD_VALUES));
20306afe12f5SStefano Zampini           r   += blocks[i];
20316afe12f5SStefano Zampini         }
20326afe12f5SStefano Zampini       } else {
2033686e3a49SStefano Zampini         for (i=0;i<nvtxs;i++) {
20345f80ce2aSJacob Faibussowitsch           CHKERRQ(MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],sarray+xadj[i],ADD_VALUES));
2035686e3a49SStefano Zampini         }
20366afe12f5SStefano Zampini       }
20376afe12f5SStefano Zampini     } else {
20386afe12f5SStefano Zampini       for (i=0;i<nvtxs;i++) {
20395f80ce2aSJacob Faibussowitsch         CHKERRQ(MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],sarray+xadj[i],ADD_VALUES));
20406afe12f5SStefano Zampini       }
20416afe12f5SStefano Zampini     }
20425f80ce2aSJacob Faibussowitsch     CHKERRQ(MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done));
2043*28b400f6SJacob Faibussowitsch     PetscCheck(done,PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
20445f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJRestoreArray(local_mat,&sarray));
2045686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
2046ecf5a873SStefano Zampini     PetscInt i;
2047c0962df8SStefano Zampini 
2048686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
2049686e3a49SStefano Zampini       PetscInt       j;
2050ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
2051686e3a49SStefano Zampini 
20525f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetRow(local_mat,i,&j,&local_indices_cols,&array));
20535f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetValuesLocal(MT,1,&i,j,local_indices_cols,array,ADD_VALUES));
20545f80ce2aSJacob Faibussowitsch       CHKERRQ(MatRestoreRow(local_mat,i,&j,&local_indices_cols,&array));
2055686e3a49SStefano Zampini     }
2056b7ce53b6SStefano Zampini   }
20575f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(MT,MAT_FINAL_ASSEMBLY));
20585f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&local_mat));
20595f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(MT,MAT_FINAL_ASSEMBLY));
2060b9ed4604SStefano Zampini   if (isseqdense) {
20615f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_TRUE));
2062487b449aSStefano Zampini   }
2063487b449aSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
20645f80ce2aSJacob Faibussowitsch     CHKERRQ(MatHeaderReplace(mat,&MT));
2065487b449aSStefano Zampini   } else if (reuse == MAT_INITIAL_MATRIX) {
2066487b449aSStefano Zampini     *M = MT;
2067b7ce53b6SStefano Zampini   }
2068b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
2069b7ce53b6SStefano Zampini }
2070b7ce53b6SStefano Zampini 
2071b7ce53b6SStefano Zampini /*@
2072b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
2073b7ce53b6SStefano Zampini 
2074d8d19677SJose E. Roman   Input Parameters:
2075a2b725a8SWilliam Gropp +  mat - the matrix (should be of type MATIS)
2076a2b725a8SWilliam Gropp -  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
2077b7ce53b6SStefano Zampini 
2078b7ce53b6SStefano Zampini   Output Parameter:
2079b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
2080b7ce53b6SStefano Zampini 
2081b7ce53b6SStefano Zampini   Level: developer
2082b7ce53b6SStefano Zampini 
208395452b02SPatrick Sanan   Notes:
2084487b449aSStefano Zampini     This function has been deprecated and it will be removed in future releases. Update your code to use the MatConvert() interface.
2085b7ce53b6SStefano Zampini 
2086487b449aSStefano Zampini .seealso: MATIS, MatConvert()
2087b7ce53b6SStefano Zampini @*/
2088b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
2089b7ce53b6SStefano Zampini {
2090b7ce53b6SStefano Zampini   PetscFunctionBegin;
2091b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2092b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
2093b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
2094487b449aSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
2095b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
2096b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
20972c71b3e2SJacob Faibussowitsch     PetscCheckFalse(mat == *newmat,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
2098b7ce53b6SStefano Zampini   }
20995f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatType,MatReuse,Mat*),(mat,MATAIJ,reuse,newmat)));
2100b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
2101b7ce53b6SStefano Zampini }
2102b7ce53b6SStefano Zampini 
21038b9382cfSStefano Zampini static PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
2104ad6194a2SStefano Zampini {
2105ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
2106c9225affSStefano Zampini   PetscInt       rbs,cbs,m,n,M,N;
2107ad6194a2SStefano Zampini   Mat            B,localmat;
2108ad6194a2SStefano Zampini 
2109ad6194a2SStefano Zampini   PetscFunctionBegin;
21105f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs));
21115f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs));
21125f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetSize(mat,&M,&N));
21135f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetLocalSize(mat,&m,&n));
21145f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreate(PetscObjectComm((PetscObject)mat),&B));
21155f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSizes(B,m,n,M,N));
21165f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetBlockSize(B,rbs == cbs ? rbs : 1));
21175f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetType(B,MATIS));
21185f80ce2aSJacob Faibussowitsch   CHKERRQ(MatISSetLocalMatType(B,matis->lmattype));
21195f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetLocalToGlobalMapping(B,mat->rmap->mapping,mat->cmap->mapping));
21205f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDuplicate(matis->A,op,&localmat));
21215f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetLocalToGlobalMapping(localmat,matis->A->rmap->mapping,matis->A->cmap->mapping));
21225f80ce2aSJacob Faibussowitsch   CHKERRQ(MatISSetLocalMat(B,localmat));
21235f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&localmat));
21245f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
21255f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
2126ad6194a2SStefano Zampini   *newmat = B;
2127ad6194a2SStefano Zampini   PetscFunctionReturn(0);
2128ad6194a2SStefano Zampini }
2129ad6194a2SStefano Zampini 
2130a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
213169796d55SStefano Zampini {
213269796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
213369796d55SStefano Zampini   PetscBool      local_sym;
213469796d55SStefano Zampini 
213569796d55SStefano Zampini   PetscFunctionBegin;
21365f80ce2aSJacob Faibussowitsch   CHKERRQ(MatIsHermitian(matis->A,tol,&local_sym));
21375f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A)));
213869796d55SStefano Zampini   PetscFunctionReturn(0);
213969796d55SStefano Zampini }
214069796d55SStefano Zampini 
2141a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool *flg)
214269796d55SStefano Zampini {
214369796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
214469796d55SStefano Zampini   PetscBool      local_sym;
214569796d55SStefano Zampini 
214669796d55SStefano Zampini   PetscFunctionBegin;
2147e432b41dSStefano Zampini   if (matis->rmapping != matis->cmapping) {
2148e432b41dSStefano Zampini     *flg = PETSC_FALSE;
2149e432b41dSStefano Zampini     PetscFunctionReturn(0);
2150e432b41dSStefano Zampini   }
21515f80ce2aSJacob Faibussowitsch   CHKERRQ(MatIsSymmetric(matis->A,tol,&local_sym));
21525f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A)));
215369796d55SStefano Zampini   PetscFunctionReturn(0);
215469796d55SStefano Zampini }
215569796d55SStefano Zampini 
215645471136SStefano Zampini static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool *flg)
215745471136SStefano Zampini {
215845471136SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
215945471136SStefano Zampini   PetscBool      local_sym;
216045471136SStefano Zampini 
216145471136SStefano Zampini   PetscFunctionBegin;
2162e432b41dSStefano Zampini   if (matis->rmapping != matis->cmapping) {
216345471136SStefano Zampini     *flg = PETSC_FALSE;
216445471136SStefano Zampini     PetscFunctionReturn(0);
216545471136SStefano Zampini   }
21665f80ce2aSJacob Faibussowitsch   CHKERRQ(MatIsStructurallySymmetric(matis->A,&local_sym));
21675f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A)));
216845471136SStefano Zampini   PetscFunctionReturn(0);
216945471136SStefano Zampini }
217045471136SStefano Zampini 
2171a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
2172b4319ba4SBarry Smith {
2173b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
2174b4319ba4SBarry Smith 
2175b4319ba4SBarry Smith   PetscFunctionBegin;
21765f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(b->bdiag));
21775f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(b->lmattype));
21785f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&b->A));
21795f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterDestroy(&b->cctx));
21805f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterDestroy(&b->rctx));
21815f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&b->x));
21825f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&b->y));
21835f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&b->counter));
21845f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&b->getsub_ris));
21855f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&b->getsub_cis));
2186a8116848SStefano Zampini   if (b->sf != b->csf) {
21875f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFDestroy(&b->csf));
21885f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree2(b->csf_rootdata,b->csf_leafdata));
2189f03112d0SStefano Zampini   } else b->csf = NULL;
21905f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDestroy(&b->sf));
21915f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree2(b->sf_rootdata,b->sf_leafdata));
21925f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingDestroy(&b->rmapping));
21935f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingDestroy(&b->cmapping));
21945f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(A->data));
21955f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectChangeTypeName((PetscObject)A,NULL));
21965f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMatType_C",NULL));
21975f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL));
21985f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL));
21995f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL));
22005f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL));
22015f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",NULL));
22025f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",NULL));
22035f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalToGlobalMapping_C",NULL));
22045f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",NULL));
22055f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",NULL));
22065f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",NULL));
22075f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",NULL));
22085f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",NULL));
22095f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",NULL));
22105f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",NULL));
22115f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOOLocal_C",NULL));
22125f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOO_C",NULL));
22135f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatSetValuesCOO_C",NULL));
2214b4319ba4SBarry Smith   PetscFunctionReturn(0);
2215b4319ba4SBarry Smith }
2216b4319ba4SBarry Smith 
2217a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
2218b4319ba4SBarry Smith {
2219b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
2220b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
2221b4319ba4SBarry Smith 
2222b4319ba4SBarry Smith   PetscFunctionBegin;
2223b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
22245f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD));
22255f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD));
2226b4319ba4SBarry Smith 
2227b4319ba4SBarry Smith   /* multiply the local matrix */
22285f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMult(is->A,is->x,is->y));
2229b4319ba4SBarry Smith 
2230b4319ba4SBarry Smith   /* scatter product back into global memory */
22315f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSet(y,zero));
22325f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE));
22335f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE));
2234b4319ba4SBarry Smith   PetscFunctionReturn(0);
2235b4319ba4SBarry Smith }
2236b4319ba4SBarry Smith 
2237a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
22382e74eeadSLisandro Dalcin {
2239650997f4SStefano Zampini   Vec            temp_vec;
22402e74eeadSLisandro Dalcin 
22412e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
2242650997f4SStefano Zampini   if (v3 != v2) {
22435f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMult(A,v1,v3));
22445f80ce2aSJacob Faibussowitsch     CHKERRQ(VecAXPY(v3,1.0,v2));
2245650997f4SStefano Zampini   } else {
22465f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDuplicate(v2,&temp_vec));
22475f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMult(A,v1,temp_vec));
22485f80ce2aSJacob Faibussowitsch     CHKERRQ(VecAXPY(temp_vec,1.0,v2));
22495f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCopy(temp_vec,v3));
22505f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDestroy(&temp_vec));
2251650997f4SStefano Zampini   }
22522e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
22532e74eeadSLisandro Dalcin }
22542e74eeadSLisandro Dalcin 
2255a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
22562e74eeadSLisandro Dalcin {
22572e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
22582e74eeadSLisandro Dalcin 
2259e176bc59SStefano Zampini   PetscFunctionBegin;
22602e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
22615f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD));
22625f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD));
22632e74eeadSLisandro Dalcin 
22642e74eeadSLisandro Dalcin   /* multiply the local matrix */
22655f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMultTranspose(is->A,is->y,is->x));
22662e74eeadSLisandro Dalcin 
22672e74eeadSLisandro Dalcin   /* scatter product back into global vector */
22685f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSet(x,0));
22695f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE));
22705f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE));
22712e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
22722e74eeadSLisandro Dalcin }
22732e74eeadSLisandro Dalcin 
2274a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
22752e74eeadSLisandro Dalcin {
2276650997f4SStefano Zampini   Vec            temp_vec;
22772e74eeadSLisandro Dalcin 
22782e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
2279650997f4SStefano Zampini   if (v3 != v2) {
22805f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMultTranspose(A,v1,v3));
22815f80ce2aSJacob Faibussowitsch     CHKERRQ(VecAXPY(v3,1.0,v2));
2282650997f4SStefano Zampini   } else {
22835f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDuplicate(v2,&temp_vec));
22845f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMultTranspose(A,v1,temp_vec));
22855f80ce2aSJacob Faibussowitsch     CHKERRQ(VecAXPY(temp_vec,1.0,v2));
22865f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCopy(temp_vec,v3));
22875f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDestroy(&temp_vec));
2288650997f4SStefano Zampini   }
22892e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
22902e74eeadSLisandro Dalcin }
22912e74eeadSLisandro Dalcin 
2292a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
2293b4319ba4SBarry Smith {
2294b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
2295b4319ba4SBarry Smith   PetscViewer    sviewer;
2296ee2491ecSStefano Zampini   PetscBool      isascii,view = PETSC_TRUE;
2297b4319ba4SBarry Smith 
2298b4319ba4SBarry Smith   PetscFunctionBegin;
22995f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
2300ee2491ecSStefano Zampini   if (isascii)  {
2301ee2491ecSStefano Zampini     PetscViewerFormat format;
2302ee2491ecSStefano Zampini 
23035f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerGetFormat(viewer,&format));
2304ee2491ecSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE;
2305ee2491ecSStefano Zampini   }
2306ee2491ecSStefano Zampini   if (!view) PetscFunctionReturn(0);
23075f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer));
23085f80ce2aSJacob Faibussowitsch   CHKERRQ(MatView(a->A,sviewer));
23095f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer));
23105f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerFlush(viewer));
2311b4319ba4SBarry Smith   PetscFunctionReturn(0);
2312b4319ba4SBarry Smith }
2313b4319ba4SBarry Smith 
2314b89f26deSStefano Zampini static PetscErrorCode MatInvertBlockDiagonal_IS(Mat mat,const PetscScalar **values)
2315b89f26deSStefano Zampini {
2316b89f26deSStefano Zampini   Mat_IS            *is = (Mat_IS*)mat->data;
2317b89f26deSStefano Zampini   MPI_Datatype      nodeType;
2318b89f26deSStefano Zampini   const PetscScalar *lv;
2319b89f26deSStefano Zampini   PetscInt          bs;
2320b89f26deSStefano Zampini 
2321b89f26deSStefano Zampini   PetscFunctionBegin;
23225f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetBlockSize(mat,&bs));
23235f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetBlockSize(is->A,bs));
23245f80ce2aSJacob Faibussowitsch   CHKERRQ(MatInvertBlockDiagonal(is->A,&lv));
2325b89f26deSStefano Zampini   if (!is->bdiag) {
23265f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(bs*mat->rmap->n,&is->bdiag));
2327b89f26deSStefano Zampini   }
23285f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Type_contiguous(bs,MPIU_SCALAR,&nodeType));
23295f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Type_commit(&nodeType));
23305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFReduceBegin(is->sf,nodeType,lv,is->bdiag,MPI_REPLACE));
23315f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFReduceEnd(is->sf,nodeType,lv,is->bdiag,MPI_REPLACE));
23325f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Type_free(&nodeType));
2333b89f26deSStefano Zampini   if (values) *values = is->bdiag;
2334b89f26deSStefano Zampini   PetscFunctionReturn(0);
2335b89f26deSStefano Zampini }
2336b89f26deSStefano Zampini 
23378546b261SStefano Zampini static PetscErrorCode MatISSetUpScatters_Private(Mat A)
2338b4319ba4SBarry Smith {
2339e176bc59SStefano Zampini   Vec            cglobal,rglobal;
23408546b261SStefano Zampini   IS             from;
23418546b261SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
2342b89f26deSStefano Zampini   PetscScalar    sum;
23438546b261SStefano Zampini   const PetscInt *garray;
23448546b261SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
2345e432b41dSStefano Zampini   VecType        rtype;
2346b4319ba4SBarry Smith 
2347b4319ba4SBarry Smith   PetscFunctionBegin;
23485f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetSize(is->rmapping,&nr));
23495f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetBlockSize(is->rmapping,&rbs));
23505f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetSize(is->cmapping,&nc));
23515f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetBlockSize(is->cmapping,&cbs));
23525f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&is->x));
23535f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&is->y));
23545f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&is->counter));
23555f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterDestroy(&is->rctx));
23565f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterDestroy(&is->cctx));
23575f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreateVecs(is->A,&is->x,&is->y));
23585f80ce2aSJacob Faibussowitsch   CHKERRQ(VecBindToCPU(is->y,PETSC_TRUE));
23595f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetRootType_Private(is->y,&rtype));
23605f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(A->defaultvectype));
23615f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrallocpy(rtype,&A->defaultvectype));
23625f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreateVecs(A,&cglobal,&rglobal));
23635f80ce2aSJacob Faibussowitsch   CHKERRQ(VecBindToCPU(rglobal,PETSC_TRUE));
23645f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetBlockIndices(is->rmapping,&garray));
23655f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateBlock(PetscObjectComm((PetscObject)A),rbs,nr/rbs,garray,PETSC_USE_POINTER,&from));
23665f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterCreate(rglobal,from,is->y,NULL,&is->rctx));
23675f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingRestoreBlockIndices(is->rmapping,&garray));
23685f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&from));
2369e432b41dSStefano Zampini   if (is->rmapping != is->cmapping) {
23705f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingGetBlockIndices(is->cmapping,&garray));
23715f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateBlock(PetscObjectComm((PetscObject)A),cbs,nc/cbs,garray,PETSC_USE_POINTER,&from));
23725f80ce2aSJacob Faibussowitsch     CHKERRQ(VecScatterCreate(cglobal,from,is->x,NULL,&is->cctx));
23735f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingRestoreBlockIndices(is->cmapping,&garray));
23745f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&from));
23758546b261SStefano Zampini   } else {
23765f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectReference((PetscObject)is->rctx));
23778546b261SStefano Zampini     is->cctx = is->rctx;
23788546b261SStefano Zampini   }
23795f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&cglobal));
2380b89f26deSStefano Zampini 
23818546b261SStefano Zampini   /* interface counter vector (local) */
23825f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDuplicate(is->y,&is->counter));
23835f80ce2aSJacob Faibussowitsch   CHKERRQ(VecBindToCPU(is->counter,PETSC_TRUE));
23845f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSet(is->y,1.));
23855f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE));
23865f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE));
23875f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD));
23885f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD));
23895f80ce2aSJacob Faibussowitsch   CHKERRQ(VecBindToCPU(is->y,PETSC_FALSE));
23905f80ce2aSJacob Faibussowitsch   CHKERRQ(VecBindToCPU(is->counter,PETSC_FALSE));
2391b89f26deSStefano Zampini 
2392b89f26deSStefano Zampini   /* special functions for block-diagonal matrices */
23935f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSum(rglobal,&sum));
2394b89f26deSStefano Zampini   A->ops->invertblockdiagonal = NULL;
2395e432b41dSStefano Zampini   if ((PetscInt)(PetscRealPart(sum)) == A->rmap->N && A->rmap->N == A->cmap->N && is->rmapping == is->cmapping) A->ops->invertblockdiagonal = MatInvertBlockDiagonal_IS;
23965f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&rglobal));
2397b0cc1f67SStefano Zampini 
2398b0cc1f67SStefano Zampini   /* setup SF for general purpose shared indices based communications */
23995f80ce2aSJacob Faibussowitsch   CHKERRQ(MatISSetUpSF_IS(A));
24008546b261SStefano Zampini   PetscFunctionReturn(0);
24018546b261SStefano Zampini }
24028546b261SStefano Zampini 
2403e432b41dSStefano Zampini static PetscErrorCode MatISFilterL2GMap(Mat A, ISLocalToGlobalMapping map, ISLocalToGlobalMapping *nmap, ISLocalToGlobalMapping *lmap)
2404e432b41dSStefano Zampini {
2405e432b41dSStefano Zampini   IS                         is;
2406e432b41dSStefano Zampini   ISLocalToGlobalMappingType l2gtype;
2407e432b41dSStefano Zampini   const PetscInt             *idxs;
2408e432b41dSStefano Zampini   PetscHSetI                 ht;
2409e432b41dSStefano Zampini   PetscInt                   *nidxs;
2410e432b41dSStefano Zampini   PetscInt                   i,n,bs,c;
2411e432b41dSStefano Zampini   PetscBool                  flg[] = {PETSC_FALSE,PETSC_FALSE};
2412e432b41dSStefano Zampini 
2413e432b41dSStefano Zampini   PetscFunctionBegin;
24145f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetSize(map,&n));
24155f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetBlockSize(map,&bs));
24165f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetBlockIndices(map,&idxs));
24175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHSetICreate(&ht));
24185f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(n/bs,&nidxs));
2419e432b41dSStefano Zampini   for (i=0,c=0;i<n/bs;i++) {
2420e432b41dSStefano Zampini     PetscBool missing;
2421e432b41dSStefano Zampini     if (idxs[i] < 0) { flg[0] = PETSC_TRUE; continue; }
24225f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscHSetIQueryAdd(ht,idxs[i],&missing));
2423e432b41dSStefano Zampini     if (!missing) flg[1] = PETSC_TRUE;
2424e432b41dSStefano Zampini     else nidxs[c++] = idxs[i];
2425e432b41dSStefano Zampini   }
24265f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscHSetIDestroy(&ht));
24275f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPIU_Allreduce(MPI_IN_PLACE,flg,2,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A)));
2428e432b41dSStefano Zampini   if (!flg[0] && !flg[1]) { /* Entries are all non negative and unique */
2429e432b41dSStefano Zampini     *nmap = NULL;
2430e432b41dSStefano Zampini     *lmap = NULL;
24315f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(nidxs));
24325f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingRestoreBlockIndices(map,&idxs));
2433e432b41dSStefano Zampini     PetscFunctionReturn(0);
2434e432b41dSStefano Zampini   }
2435e432b41dSStefano Zampini 
2436e432b41dSStefano Zampini   /* New l2g map without negative or repeated indices */
24375f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateBlock(PetscObjectComm((PetscObject)A),bs,c,nidxs,PETSC_USE_POINTER,&is));
24385f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingCreateIS(is,nmap));
24395f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&is));
24405f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetType(map,&l2gtype));
24415f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingSetType(*nmap,l2gtype));
2442e432b41dSStefano Zampini 
2443e432b41dSStefano Zampini   /* New local l2g map for repeated indices */
24445f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGlobalToLocalMappingApplyBlock(*nmap,IS_GTOLM_MASK,n/bs,idxs,NULL,nidxs));
24455f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateBlock(PETSC_COMM_SELF,bs,n/bs,nidxs,PETSC_USE_POINTER,&is));
24465f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingCreateIS(is,lmap));
24475f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&is));
2448e432b41dSStefano Zampini 
24495f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(nidxs));
24505f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingRestoreBlockIndices(map,&idxs));
2451e432b41dSStefano Zampini   PetscFunctionReturn(0);
2452e432b41dSStefano Zampini }
2453e432b41dSStefano Zampini 
24548546b261SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
24558546b261SStefano Zampini {
24568546b261SStefano Zampini   Mat_IS                 *is = (Mat_IS*)A->data;
2457e432b41dSStefano Zampini   ISLocalToGlobalMapping localrmapping = NULL, localcmapping = NULL;
2458e432b41dSStefano Zampini   PetscBool              cong, freem[] = { PETSC_FALSE, PETSC_FALSE };
2459e432b41dSStefano Zampini   PetscInt               nr,rbs,nc,cbs;
24608546b261SStefano Zampini 
24618546b261SStefano Zampini   PetscFunctionBegin;
2462fc989267SStefano Zampini   if (rmapping) PetscCheckSameComm(A,1,rmapping,2);
2463fc989267SStefano Zampini   if (cmapping) PetscCheckSameComm(A,1,cmapping,3);
2464e432b41dSStefano Zampini 
24655f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingDestroy(&is->rmapping));
24665f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingDestroy(&is->cmapping));
24675f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutSetUp(A->rmap));
24685f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutSetUp(A->cmap));
24695f80ce2aSJacob Faibussowitsch   CHKERRQ(MatHasCongruentLayouts(A,&cong));
2470e432b41dSStefano Zampini 
2471fc989267SStefano Zampini   /* If NULL, local space matches global space */
2472fc989267SStefano Zampini   if (!rmapping) {
2473fc989267SStefano Zampini     IS is;
2474fc989267SStefano Zampini 
24755f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateStride(PetscObjectComm((PetscObject)A),A->rmap->N,0,1,&is));
24765f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingCreateIS(is,&rmapping));
24775f80ce2aSJacob Faibussowitsch     if (A->rmap->bs > 0) CHKERRQ(ISLocalToGlobalMappingSetBlockSize(rmapping,A->rmap->bs));
24785f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&is));
2479e432b41dSStefano Zampini     freem[0] = PETSC_TRUE;
2480e432b41dSStefano Zampini     if (!cmapping && cong && A->rmap->bs == A->cmap->bs) cmapping = rmapping;
2481e432b41dSStefano Zampini   } else if (!is->islocalref) { /* check if the l2g map has negative or repeated entries */
24825f80ce2aSJacob Faibussowitsch     CHKERRQ(MatISFilterL2GMap(A,rmapping,&is->rmapping,&localrmapping));
2483e432b41dSStefano Zampini     if (rmapping == cmapping) {
24845f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectReference((PetscObject)is->rmapping));
2485e432b41dSStefano Zampini       is->cmapping = is->rmapping;
24865f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectReference((PetscObject)localrmapping));
2487e432b41dSStefano Zampini       localcmapping = localrmapping;
2488fc989267SStefano Zampini     }
2489fc989267SStefano Zampini   }
2490fc989267SStefano Zampini   if (!cmapping) {
2491fc989267SStefano Zampini     IS is;
2492fc989267SStefano Zampini 
24935f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateStride(PetscObjectComm((PetscObject)A),A->cmap->N,0,1,&is));
24945f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingCreateIS(is,&cmapping));
24955f80ce2aSJacob Faibussowitsch     if (A->cmap->bs > 0) CHKERRQ(ISLocalToGlobalMappingSetBlockSize(cmapping,A->cmap->bs));
24965f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&is));
2497e432b41dSStefano Zampini     freem[1] = PETSC_TRUE;
2498e432b41dSStefano Zampini   } else if (cmapping != rmapping && !is->islocalref) { /* check if the l2g map has negative or repeated entries */
24995f80ce2aSJacob Faibussowitsch     CHKERRQ(MatISFilterL2GMap(A,cmapping,&is->cmapping,&localcmapping));
2500e432b41dSStefano Zampini   }
2501e432b41dSStefano Zampini   if (!is->rmapping) {
25025f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectReference((PetscObject)rmapping));
2503e432b41dSStefano Zampini     is->rmapping = rmapping;
2504e432b41dSStefano Zampini   }
2505e432b41dSStefano Zampini   if (!is->cmapping) {
25065f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectReference((PetscObject)cmapping));
2507e432b41dSStefano Zampini     is->cmapping = cmapping;
2508fc989267SStefano Zampini   }
2509fc989267SStefano Zampini 
2510fc989267SStefano Zampini   /* Clean up */
25115f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&is->A));
2512872cf891SStefano Zampini   if (is->csf != is->sf) {
25135f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSFDestroy(&is->csf));
25145f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree2(is->csf_rootdata,is->csf_leafdata));
2515f03112d0SStefano Zampini   } else is->csf = NULL;
25165f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFDestroy(&is->sf));
25175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree2(is->sf_rootdata,is->sf_leafdata));
25185f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(is->bdiag));
25193bbff08aSStefano Zampini 
2520fc989267SStefano Zampini   /* check if the two mappings are actually the same for square matrices since MATIS has some optimization for this case
2521fc989267SStefano Zampini      (DOLFIN passes 2 different objects) */
25225f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetSize(is->rmapping,&nr));
25235f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetBlockSize(is->rmapping,&rbs));
25245f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetSize(is->cmapping,&nc));
25255f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetBlockSize(is->cmapping,&cbs));
2526e432b41dSStefano Zampini   if (is->rmapping != is->cmapping && cong) {
2527e432b41dSStefano Zampini     PetscBool same = PETSC_FALSE;
25286625354bSStefano Zampini     if (nr == nc && cbs == rbs) {
25296625354bSStefano Zampini       const PetscInt *idxs1,*idxs2;
25306625354bSStefano Zampini 
25315f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingGetBlockIndices(is->rmapping,&idxs1));
25325f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingGetBlockIndices(is->cmapping,&idxs2));
25335f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArraycmp(idxs1,idxs2,nr/rbs,&same));
25345f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingRestoreBlockIndices(is->rmapping,&idxs1));
25355f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingRestoreBlockIndices(is->cmapping,&idxs2));
25366625354bSStefano Zampini     }
25375f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPIU_Allreduce(MPI_IN_PLACE,&same,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A)));
2538e432b41dSStefano Zampini     if (same) {
25395f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingDestroy(&is->cmapping));
25405f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectReference((PetscObject)is->rmapping));
2541e432b41dSStefano Zampini       is->cmapping = is->rmapping;
2542e432b41dSStefano Zampini     }
25436625354bSStefano Zampini   }
25445f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutSetBlockSize(A->rmap,rbs));
25455f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutSetBlockSize(A->cmap,cbs));
2546e432b41dSStefano Zampini   /* Pass the user defined maps to the layout */
25475f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping));
25485f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping));
25495f80ce2aSJacob Faibussowitsch   if (freem[0]) CHKERRQ(ISLocalToGlobalMappingDestroy(&rmapping));
25505f80ce2aSJacob Faibussowitsch   if (freem[1]) CHKERRQ(ISLocalToGlobalMappingDestroy(&cmapping));
25516625354bSStefano Zampini 
25526625354bSStefano Zampini   /* Create the local matrix A */
25535f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreate(PETSC_COMM_SELF,&is->A));
25545f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetType(is->A,is->lmattype));
25555f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSizes(is->A,nr,nc,nr,nc));
25565f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetBlockSizes(is->A,rbs,cbs));
25575f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetOptionsPrefix(is->A,"is_"));
25585f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAppendOptionsPrefix(is->A,((PetscObject)A)->prefix));
25595f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutSetUp(is->A->rmap));
25605f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutSetUp(is->A->cmap));
25615f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetLocalToGlobalMapping(is->A,localrmapping,localcmapping));
25625f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingDestroy(&localrmapping));
25635f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingDestroy(&localcmapping));
2564b4319ba4SBarry Smith 
2565fc989267SStefano Zampini   /* setup scatters and local vectors for MatMult */
25665f80ce2aSJacob Faibussowitsch   if (!is->islocalref) CHKERRQ(MatISSetUpScatters_Private(A));
2567fc989267SStefano Zampini   A->preallocated = PETSC_TRUE;
2568fc989267SStefano Zampini   PetscFunctionReturn(0);
2569fc989267SStefano Zampini }
2570fc989267SStefano Zampini 
2571fc989267SStefano Zampini static PetscErrorCode MatSetUp_IS(Mat A)
2572fc989267SStefano Zampini {
2573fc989267SStefano Zampini   ISLocalToGlobalMapping rmap, cmap;
2574fc989267SStefano Zampini 
2575fc989267SStefano Zampini   PetscFunctionBegin;
25765f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetLocalToGlobalMapping(A,&rmap,&cmap));
2577fc989267SStefano Zampini   if (!rmap && !cmap) {
25785f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetLocalToGlobalMapping(A,NULL,NULL));
2579fc989267SStefano Zampini   }
2580b4319ba4SBarry Smith   PetscFunctionReturn(0);
2581b4319ba4SBarry Smith }
2582b4319ba4SBarry Smith 
2583a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
25842e74eeadSLisandro Dalcin {
25852e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
2586f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
25872e74eeadSLisandro Dalcin 
25882e74eeadSLisandro Dalcin   PetscFunctionBegin;
25895f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGlobalToLocalMappingApply(is->rmapping,IS_GTOLM_MASK,m,rows,&m,rows_l));
2590e432b41dSStefano Zampini   if (m != n || rows != cols || is->cmapping != is->rmapping) {
25915f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGlobalToLocalMappingApply(is->cmapping,IS_GTOLM_MASK,n,cols,&n,cols_l));
25925f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetValues(is->A,m,rows_l,n,cols_l,values,addv));
2593e432b41dSStefano Zampini   } else {
25945f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetValues(is->A,m,rows_l,m,rows_l,values,addv));
2595e432b41dSStefano Zampini   }
25962e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
25972e74eeadSLisandro Dalcin }
25982e74eeadSLisandro Dalcin 
2599a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
260097563a80SStefano Zampini {
260197563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
2602f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
260397563a80SStefano Zampini 
260497563a80SStefano Zampini   PetscFunctionBegin;
26055f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGlobalToLocalMappingApplyBlock(is->rmapping,IS_GTOLM_MASK,m,rows,&m,rows_l));
2606e432b41dSStefano Zampini   if (m != n || rows != cols || is->cmapping != is->rmapping) {
26075f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGlobalToLocalMappingApply(is->cmapping,IS_GTOLM_MASK,n,cols,&n,cols_l));
26085f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv));
2609e432b41dSStefano Zampini   } else {
26105f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetValuesBlocked(is->A,m,rows_l,n,rows_l,values,addv));
2611e432b41dSStefano Zampini   }
261297563a80SStefano Zampini   PetscFunctionReturn(0);
261397563a80SStefano Zampini }
261497563a80SStefano Zampini 
2615a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
2616b4319ba4SBarry Smith {
2617b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2618b4319ba4SBarry Smith 
2619b4319ba4SBarry Smith   PetscFunctionBegin;
2620e432b41dSStefano Zampini   if (is->A->rmap->mapping || is->A->cmap->mapping) {
26215f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetValuesLocal(is->A,m,rows,n,cols,values,addv));
2622872cf891SStefano Zampini   } else {
26235f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetValues(is->A,m,rows,n,cols,values,addv));
2624872cf891SStefano Zampini   }
2625b4319ba4SBarry Smith   PetscFunctionReturn(0);
2626b4319ba4SBarry Smith }
2627b4319ba4SBarry Smith 
2628a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
2629f0006bf2SLisandro Dalcin {
2630f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
2631f0006bf2SLisandro Dalcin 
2632f0006bf2SLisandro Dalcin   PetscFunctionBegin;
2633e432b41dSStefano Zampini   if (is->A->rmap->mapping || is->A->cmap->mapping) {
26345f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetValuesBlockedLocal(is->A,m,rows,n,cols,values,addv));
2635b4f971dfSStefano Zampini   } else {
26365f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv));
2637b4f971dfSStefano Zampini   }
2638f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
2639f0006bf2SLisandro Dalcin }
2640f0006bf2SLisandro Dalcin 
2641f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
2642f0ae7da4SStefano Zampini {
2643f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
2644f0ae7da4SStefano Zampini 
2645f0ae7da4SStefano Zampini   PetscFunctionBegin;
2646f0ae7da4SStefano Zampini   if (!n) {
2647f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
2648f0ae7da4SStefano Zampini   } else {
2649f0ae7da4SStefano Zampini     PetscInt i;
2650f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
2651f0ae7da4SStefano Zampini 
2652f0ae7da4SStefano Zampini     if (columns) {
26535f80ce2aSJacob Faibussowitsch       CHKERRQ(MatZeroRowsColumns(is->A,n,rows,diag,NULL,NULL));
2654f0ae7da4SStefano Zampini     } else {
26555f80ce2aSJacob Faibussowitsch       CHKERRQ(MatZeroRows(is->A,n,rows,diag,NULL,NULL));
2656f0ae7da4SStefano Zampini     }
2657f0ae7da4SStefano Zampini     if (diag != 0.) {
2658f0ae7da4SStefano Zampini       const PetscScalar *array;
26595f80ce2aSJacob Faibussowitsch       CHKERRQ(VecGetArrayRead(is->counter,&array));
2660f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
26615f80ce2aSJacob Faibussowitsch         CHKERRQ(MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES));
2662f0ae7da4SStefano Zampini       }
26635f80ce2aSJacob Faibussowitsch       CHKERRQ(VecRestoreArrayRead(is->counter,&array));
2664f0ae7da4SStefano Zampini     }
26655f80ce2aSJacob Faibussowitsch     CHKERRQ(MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY));
26665f80ce2aSJacob Faibussowitsch     CHKERRQ(MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY));
2667f0ae7da4SStefano Zampini   }
2668f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
2669f0ae7da4SStefano Zampini }
2670f0ae7da4SStefano Zampini 
2671f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
26722e74eeadSLisandro Dalcin {
26736e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
26746e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
26756e520ac8SStefano Zampini   PetscInt       *lrows;
26762e74eeadSLisandro Dalcin 
26772e74eeadSLisandro Dalcin   PetscFunctionBegin;
2678cf9c20a2SJed Brown   if (PetscUnlikelyDebug(columns || diag != 0. || (x && b))) {
2679f0ae7da4SStefano Zampini     PetscBool cong;
268026b0207aSStefano Zampini 
26815f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLayoutCompare(A->rmap,A->cmap,&cong));
268226b0207aSStefano Zampini     cong = (PetscBool)(cong && matis->sf == matis->csf);
26832c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!cong && columns,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");
26842c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!cong && diag != 0.,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");
26852c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!cong && x && b,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"A->rmap and A->cmap need to be congruent, and the l2g maps be the same");
2686f0ae7da4SStefano Zampini   }
26876e520ac8SStefano Zampini   /* get locally owned rows */
26885f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutMapLocal(A->rmap,n,rows,&len,&lrows,NULL));
26896e520ac8SStefano Zampini   /* fix right hand side if needed */
26906e520ac8SStefano Zampini   if (x && b) {
26916e520ac8SStefano Zampini     const PetscScalar *xx;
26926e520ac8SStefano Zampini     PetscScalar       *bb;
26936e520ac8SStefano Zampini 
26945f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArrayRead(x, &xx));
26955f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(b, &bb));
26966e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
26975f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(x, &xx));
26985f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(b, &bb));
26992e74eeadSLisandro Dalcin   }
27006e520ac8SStefano Zampini   /* get rows associated to the local matrices */
27015f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetSize(matis->A,&nl,NULL));
27025f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArrayzero(matis->sf_leafdata,nl));
27035f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArrayzero(matis->sf_rootdata,A->rmap->n));
27046e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
27055f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(lrows));
27065f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
27075f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
27085f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(nl,&lrows));
27096e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
27105f80ce2aSJacob Faibussowitsch   CHKERRQ(MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns));
27115f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(lrows));
27122e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
27132e74eeadSLisandro Dalcin }
27142e74eeadSLisandro Dalcin 
2715f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
2716b4319ba4SBarry Smith {
2717b4319ba4SBarry Smith   PetscFunctionBegin;
27185f80ce2aSJacob Faibussowitsch   CHKERRQ(MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE));
2719f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
2720f0ae7da4SStefano Zampini }
27212205254eSKarl Rupp 
2722f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
2723f0ae7da4SStefano Zampini {
2724f0ae7da4SStefano Zampini   PetscFunctionBegin;
27255f80ce2aSJacob Faibussowitsch   CHKERRQ(MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE));
2726b4319ba4SBarry Smith   PetscFunctionReturn(0);
2727b4319ba4SBarry Smith }
2728b4319ba4SBarry Smith 
2729a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
2730b4319ba4SBarry Smith {
2731b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2732b4319ba4SBarry Smith 
2733b4319ba4SBarry Smith   PetscFunctionBegin;
27345f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(is->A,type));
2735b4319ba4SBarry Smith   PetscFunctionReturn(0);
2736b4319ba4SBarry Smith }
2737b4319ba4SBarry Smith 
2738a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
2739b4319ba4SBarry Smith {
2740b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2741b4319ba4SBarry Smith 
2742b4319ba4SBarry Smith   PetscFunctionBegin;
27435f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(is->A,type));
2744872cf891SStefano Zampini   /* fix for local empty rows/cols */
2745872cf891SStefano Zampini   if (is->locempty && type == MAT_FINAL_ASSEMBLY) {
2746872cf891SStefano Zampini     Mat                    newlA;
2747f03112d0SStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g;
2748f03112d0SStefano Zampini     IS                     nzr,nzc;
2749f03112d0SStefano Zampini     PetscInt               nr,nc,nnzr,nnzc;
2750f03112d0SStefano Zampini     PetscBool              lnewl2g,newl2g;
2751872cf891SStefano Zampini 
27525f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetSize(is->A,&nr,&nc));
27535f80ce2aSJacob Faibussowitsch     CHKERRQ(MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_FALSE,PETSC_SMALL,&nzr));
2754f03112d0SStefano Zampini     if (!nzr) {
27555f80ce2aSJacob Faibussowitsch       CHKERRQ(ISCreateStride(PetscObjectComm((PetscObject)is->A),nr,0,1,&nzr));
2756872cf891SStefano Zampini     }
27575f80ce2aSJacob Faibussowitsch     CHKERRQ(MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_TRUE,PETSC_SMALL,&nzc));
2758f03112d0SStefano Zampini     if (!nzc) {
27595f80ce2aSJacob Faibussowitsch       CHKERRQ(ISCreateStride(PetscObjectComm((PetscObject)is->A),nc,0,1,&nzc));
2760872cf891SStefano Zampini     }
27615f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetSize(nzr,&nnzr));
27625f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetSize(nzc,&nnzc));
2763e432b41dSStefano Zampini     if (nnzr != nr || nnzc != nc) { /* need new global l2g map */
2764f03112d0SStefano Zampini       lnewl2g = PETSC_TRUE;
27655f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A)));
2766f03112d0SStefano Zampini 
2767872cf891SStefano Zampini       /* extract valid submatrix */
27685f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreateSubMatrix(is->A,nzr,nzc,MAT_INITIAL_MATRIX,&newlA));
2769f03112d0SStefano Zampini     } else { /* local matrix fully populated */
2770f03112d0SStefano Zampini       lnewl2g = PETSC_FALSE;
27715f80ce2aSJacob Faibussowitsch       CHKERRMPI(MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A)));
27725f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscObjectReference((PetscObject)is->A));
2773f03112d0SStefano Zampini       newlA   = is->A;
2774f03112d0SStefano Zampini     }
2775e432b41dSStefano Zampini 
2776f03112d0SStefano Zampini     /* attach new global l2g map if needed */
2777f03112d0SStefano Zampini     if (newl2g) {
2778e432b41dSStefano Zampini       IS              zr,zc;
2779e432b41dSStefano Zampini       const  PetscInt *ridxs,*cidxs,*zridxs,*zcidxs;
2780e432b41dSStefano Zampini       PetscInt        *nidxs,i;
2781f03112d0SStefano Zampini 
27825f80ce2aSJacob Faibussowitsch       CHKERRQ(ISComplement(nzr,0,nr,&zr));
27835f80ce2aSJacob Faibussowitsch       CHKERRQ(ISComplement(nzc,0,nc,&zc));
27845f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(PetscMax(nr,nc),&nidxs));
27855f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingGetIndices(is->rmapping,&ridxs));
27865f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingGetIndices(is->cmapping,&cidxs));
27875f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetIndices(zr,&zridxs));
27885f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetIndices(zc,&zcidxs));
27895f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetLocalSize(zr,&nnzr));
27905f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetLocalSize(zc,&nnzc));
2791e432b41dSStefano Zampini 
27925f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArraycpy(nidxs,ridxs,nr));
2793e432b41dSStefano Zampini       for (i = 0; i < nnzr; i++) nidxs[zridxs[i]] = -1;
27945f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nr,nidxs,PETSC_COPY_VALUES,&rl2g));
27955f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArraycpy(nidxs,cidxs,nc));
2796e432b41dSStefano Zampini       for (i = 0; i < nnzc; i++) nidxs[zcidxs[i]] = -1;
27975f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nc,nidxs,PETSC_COPY_VALUES,&cl2g));
2798e432b41dSStefano Zampini 
27995f80ce2aSJacob Faibussowitsch       CHKERRQ(ISRestoreIndices(zr,&zridxs));
28005f80ce2aSJacob Faibussowitsch       CHKERRQ(ISRestoreIndices(zc,&zcidxs));
28015f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingRestoreIndices(is->rmapping,&ridxs));
28025f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingRestoreIndices(is->cmapping,&cidxs));
28035f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&nzr));
28045f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&nzc));
28055f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&zr));
28065f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&zc));
28075f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(nidxs));
28085f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetLocalToGlobalMapping(A,rl2g,cl2g));
28095f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingDestroy(&rl2g));
28105f80ce2aSJacob Faibussowitsch       CHKERRQ(ISLocalToGlobalMappingDestroy(&cl2g));
2811f03112d0SStefano Zampini     }
28125f80ce2aSJacob Faibussowitsch     CHKERRQ(MatISSetLocalMat(A,newlA));
28135f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroy(&newlA));
28145f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&nzr));
28155f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&nzc));
2816872cf891SStefano Zampini     is->locempty = PETSC_FALSE;
2817f03112d0SStefano Zampini   }
2818b4319ba4SBarry Smith   PetscFunctionReturn(0);
2819b4319ba4SBarry Smith }
2820b4319ba4SBarry Smith 
2821a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
2822b4319ba4SBarry Smith {
2823b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
2824b4319ba4SBarry Smith 
2825b4319ba4SBarry Smith   PetscFunctionBegin;
2826b4319ba4SBarry Smith   *local = is->A;
2827b4319ba4SBarry Smith   PetscFunctionReturn(0);
2828b4319ba4SBarry Smith }
2829b4319ba4SBarry Smith 
28303b3b1effSJed Brown static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat,Mat *local)
28313b3b1effSJed Brown {
28323b3b1effSJed Brown   PetscFunctionBegin;
28333b3b1effSJed Brown   *local = NULL;
28343b3b1effSJed Brown   PetscFunctionReturn(0);
28353b3b1effSJed Brown }
28363b3b1effSJed Brown 
2837b4319ba4SBarry Smith /*@
2838b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
2839b4319ba4SBarry Smith 
2840b4319ba4SBarry Smith   Input Parameter:
2841b4319ba4SBarry Smith .  mat - the matrix
2842b4319ba4SBarry Smith 
2843b4319ba4SBarry Smith   Output Parameter:
2844eb82efa4SStefano Zampini .  local - the local matrix
2845b4319ba4SBarry Smith 
2846b4319ba4SBarry Smith   Level: advanced
2847b4319ba4SBarry Smith 
2848b4319ba4SBarry Smith   Notes:
2849b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
2850b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
2851b4319ba4SBarry Smith   of the MatSetValues() operation.
2852b4319ba4SBarry Smith 
28533b3b1effSJed Brown   Call MatISRestoreLocalMat() when finished with the local matrix.
285496a6f129SJed Brown 
2855b4319ba4SBarry Smith .seealso: MATIS
2856b4319ba4SBarry Smith @*/
28577087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
2858b4319ba4SBarry Smith {
2859b4319ba4SBarry Smith   PetscFunctionBegin;
28600700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2861b4319ba4SBarry Smith   PetscValidPointer(local,2);
28625f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local)));
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   PetscFunctionBegin;
28823b3b1effSJed Brown   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
28833b3b1effSJed Brown   PetscValidPointer(local,2);
28845f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscUseMethod(mat,"MatISRestoreLocalMat_C",(Mat,Mat*),(mat,local)));
28853b3b1effSJed Brown   PetscFunctionReturn(0);
28863b3b1effSJed Brown }
28873b3b1effSJed Brown 
28888546b261SStefano Zampini static PetscErrorCode MatISSetLocalMatType_IS(Mat mat,MatType mtype)
28898546b261SStefano Zampini {
28908546b261SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
28918546b261SStefano Zampini 
28928546b261SStefano Zampini   PetscFunctionBegin;
28938546b261SStefano Zampini   if (is->A) {
28945f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetType(is->A,mtype));
28958546b261SStefano Zampini   }
28965f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(is->lmattype));
28975f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrallocpy(mtype,&is->lmattype));
28988546b261SStefano Zampini   PetscFunctionReturn(0);
28998546b261SStefano Zampini }
29008546b261SStefano Zampini 
29018546b261SStefano Zampini /*@
29028546b261SStefano Zampini     MatISSetLocalMatType - Specifies the type of local matrix
29038546b261SStefano Zampini 
2904d8d19677SJose E. Roman   Input Parameters:
2905a2b725a8SWilliam Gropp +  mat - the matrix
2906a2b725a8SWilliam Gropp -  mtype - the local matrix type
29078546b261SStefano Zampini 
29088546b261SStefano Zampini   Output Parameter:
29098546b261SStefano Zampini 
29108546b261SStefano Zampini   Level: advanced
29118546b261SStefano Zampini 
29128546b261SStefano Zampini .seealso: MATIS, MatSetType(), MatType
29138546b261SStefano Zampini @*/
29148546b261SStefano Zampini PetscErrorCode MatISSetLocalMatType(Mat mat,MatType mtype)
29158546b261SStefano Zampini {
29168546b261SStefano Zampini   PetscFunctionBegin;
29178546b261SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
29185f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscUseMethod(mat,"MatISSetLocalMatType_C",(Mat,MatType),(mat,mtype)));
29198546b261SStefano Zampini   PetscFunctionReturn(0);
29208546b261SStefano Zampini }
29218546b261SStefano Zampini 
2922a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
29233b03a366Sstefano_zampini {
29243b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
29253b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
29268546b261SStefano Zampini   MatType        mtype,otype;
29278546b261SStefano Zampini   PetscBool      sametype = PETSC_TRUE;
29283b03a366Sstefano_zampini 
29293b03a366Sstefano_zampini   PetscFunctionBegin;
2930e432b41dSStefano Zampini   if (is->A && !is->islocalref) {
29315f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetSize(is->A,&orows,&ocols));
29325f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetSize(local,&nrows,&ncols));
29332c71b3e2SJacob Faibussowitsch     PetscCheckFalse(orows != nrows || ocols != ncols,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local MATIS matrix should be of size %" PetscInt_FMT "x%" PetscInt_FMT " (you passed a %" PetscInt_FMT "x%" PetscInt_FMT " matrix)",orows,ocols,nrows,ncols);
29345f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetType(local,&mtype));
29355f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetType(is->A,&otype));
29365f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcmp(mtype,otype,&sametype));
29374e4c7dbeSStefano Zampini   }
29385f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectReference((PetscObject)local));
29395f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&is->A));
29403b03a366Sstefano_zampini   is->A = local;
29415f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetType(is->A,&mtype));
29425f80ce2aSJacob Faibussowitsch   CHKERRQ(MatISSetLocalMatType(mat,mtype));
29438546b261SStefano Zampini   if (!sametype && !is->islocalref) {
29445f80ce2aSJacob Faibussowitsch     CHKERRQ(MatISSetUpScatters_Private(mat));
29458546b261SStefano Zampini   }
29463b03a366Sstefano_zampini   PetscFunctionReturn(0);
29473b03a366Sstefano_zampini }
29483b03a366Sstefano_zampini 
29493b03a366Sstefano_zampini /*@
2950eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
29513b03a366Sstefano_zampini 
29528546b261SStefano Zampini   Collective on Mat
29538546b261SStefano Zampini 
2954d8d19677SJose E. Roman   Input Parameters:
2955a2b725a8SWilliam Gropp +  mat - the matrix
2956a2b725a8SWilliam Gropp -  local - the local matrix
29573b03a366Sstefano_zampini 
29583b03a366Sstefano_zampini   Output Parameter:
29593b03a366Sstefano_zampini 
29603b03a366Sstefano_zampini   Level: advanced
29613b03a366Sstefano_zampini 
29623b03a366Sstefano_zampini   Notes:
29633b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
29643b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
29653b03a366Sstefano_zampini 
29663b03a366Sstefano_zampini .seealso: MATIS
29673b03a366Sstefano_zampini @*/
29683b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
29693b03a366Sstefano_zampini {
29703b03a366Sstefano_zampini   PetscFunctionBegin;
29713b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2972b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
29735f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local)));
29743b03a366Sstefano_zampini   PetscFunctionReturn(0);
29753b03a366Sstefano_zampini }
29763b03a366Sstefano_zampini 
2977a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
29786726f965SBarry Smith {
29796726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
29806726f965SBarry Smith 
29816726f965SBarry Smith   PetscFunctionBegin;
29825f80ce2aSJacob Faibussowitsch   CHKERRQ(MatZeroEntries(a->A));
29836726f965SBarry Smith   PetscFunctionReturn(0);
29846726f965SBarry Smith }
29856726f965SBarry Smith 
2986a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
29872e74eeadSLisandro Dalcin {
29882e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
29892e74eeadSLisandro Dalcin 
29902e74eeadSLisandro Dalcin   PetscFunctionBegin;
29915f80ce2aSJacob Faibussowitsch   CHKERRQ(MatScale(is->A,a));
29922e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
29932e74eeadSLisandro Dalcin }
29942e74eeadSLisandro Dalcin 
2995a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
29962e74eeadSLisandro Dalcin {
29972e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
29982e74eeadSLisandro Dalcin 
29992e74eeadSLisandro Dalcin   PetscFunctionBegin;
30002e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
30015f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetDiagonal(is->A,is->y));
30022e74eeadSLisandro Dalcin 
30032e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
30045f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSet(v,0));
30055f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE));
30065f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE));
30072e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
30082e74eeadSLisandro Dalcin }
30092e74eeadSLisandro Dalcin 
3010a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
30116726f965SBarry Smith {
30126726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
30136726f965SBarry Smith 
30146726f965SBarry Smith   PetscFunctionBegin;
30155f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetOption(a->A,op,flg));
30166726f965SBarry Smith   PetscFunctionReturn(0);
30176726f965SBarry Smith }
30186726f965SBarry Smith 
3019f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
3020f26d0771SStefano Zampini {
3021f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
3022f26d0771SStefano Zampini   Mat_IS         *x;
3023f26d0771SStefano Zampini 
3024f26d0771SStefano Zampini   PetscFunctionBegin;
302576bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
302676bd3646SJed Brown     PetscBool      ismatis;
30275f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis));
3028*28b400f6SJacob Faibussowitsch     PetscCheck(ismatis,PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
302976bd3646SJed Brown   }
3030f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
30315f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAXPY(y->A,a,x->A,str));
3032f26d0771SStefano Zampini   PetscFunctionReturn(0);
3033f26d0771SStefano Zampini }
3034f26d0771SStefano Zampini 
3035f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
3036f26d0771SStefano Zampini {
3037f26d0771SStefano Zampini   Mat                    lA;
3038e432b41dSStefano Zampini   Mat_IS                 *matis = (Mat_IS*)(A->data);
3039f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
3040f26d0771SStefano Zampini   IS                     is;
3041f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
3042f26d0771SStefano Zampini   PetscInt               nrg;
3043f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
3044f26d0771SStefano Zampini 
3045f26d0771SStefano Zampini   PetscFunctionBegin;
30465f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg));
30475f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetLocalSize(row,&nrl));
30485f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetIndices(row,&rl));
30495f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg));
305076bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
30512c71b3e2SJacob Faibussowitsch     for (i=0; i<nrl; i++) PetscCheckFalse(rl[i]>=nrg,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row index %" PetscInt_FMT " -> %" PetscInt_FMT " greater then maximum possible %" PetscInt_FMT,i,rl[i],nrg);
305276bd3646SJed Brown   }
30535f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(nrg,&idxs));
3054f26d0771SStefano Zampini   /* map from [0,nrl) to row */
3055f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
3056f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
30575f80ce2aSJacob Faibussowitsch   CHKERRQ(ISRestoreIndices(row,&rl));
30585f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg));
30595f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is));
30605f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingCreateIS(is,&rl2g));
30615f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&is));
3062f26d0771SStefano Zampini   /* compute new l2g map for columns */
3063e432b41dSStefano Zampini   if (col != row || matis->rmapping != matis->cmapping || matis->A->rmap->mapping != matis->A->cmap->mapping) {
3064f26d0771SStefano Zampini     const PetscInt *cg,*cl;
3065f26d0771SStefano Zampini     PetscInt       ncg;
3066f26d0771SStefano Zampini     PetscInt       ncl;
3067f26d0771SStefano Zampini 
30685f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg));
30695f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetLocalSize(col,&ncl));
30705f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(col,&cl));
30715f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg));
307276bd3646SJed Brown     if (PetscDefined(USE_DEBUG)) {
30732c71b3e2SJacob Faibussowitsch       for (i=0; i<ncl; i++) PetscCheckFalse(cl[i]>=ncg,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local column index %" PetscInt_FMT " -> %" PetscInt_FMT " greater then maximum possible %" PetscInt_FMT,i,cl[i],ncg);
307476bd3646SJed Brown     }
30755f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(ncg,&idxs));
3076f26d0771SStefano Zampini     /* map from [0,ncl) to col */
3077f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
3078f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
30795f80ce2aSJacob Faibussowitsch     CHKERRQ(ISRestoreIndices(col,&cl));
30805f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg));
30815f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is));
30825f80ce2aSJacob Faibussowitsch     CHKERRQ(ISLocalToGlobalMappingCreateIS(is,&cl2g));
30835f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&is));
3084f26d0771SStefano Zampini   } else {
30855f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectReference((PetscObject)rl2g));
3086f26d0771SStefano Zampini     cl2g = rl2g;
3087f26d0771SStefano Zampini   }
3088f26d0771SStefano Zampini   /* create the MATIS submatrix */
30895f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetSize(A,&M,&N));
30905f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreate(PetscObjectComm((PetscObject)A),submat));
30915f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N));
30925f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetType(*submat,MATIS));
3093b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
3094f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
30955f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetLocalToGlobalMapping(*submat,rl2g,cl2g));
30965f80ce2aSJacob Faibussowitsch   CHKERRQ(MatISGetLocalMat(A,&lA));
30975f80ce2aSJacob Faibussowitsch   CHKERRQ(MatISSetLocalMat(*submat,lA));
30985f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetUp(*submat));
30995f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY));
31005f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY));
31015f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingDestroy(&rl2g));
31025f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingDestroy(&cl2g));
3103e432b41dSStefano Zampini 
3104f26d0771SStefano Zampini   /* remove unsupported ops */
31055f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMemzero((*submat)->ops,sizeof(struct _MatOps)));
3106f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
3107f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
3108f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
3109f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
3110f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
3111f26d0771SStefano Zampini   PetscFunctionReturn(0);
3112f26d0771SStefano Zampini }
3113f26d0771SStefano Zampini 
3114872cf891SStefano Zampini static PetscErrorCode MatSetFromOptions_IS(PetscOptionItems *PetscOptionsObject, Mat A)
3115872cf891SStefano Zampini {
3116872cf891SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
31178546b261SStefano Zampini   char           type[256];
31188546b261SStefano Zampini   PetscBool      flg;
3119872cf891SStefano Zampini 
3120872cf891SStefano Zampini   PetscFunctionBegin;
31215f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsHead(PetscOptionsObject,"MATIS options"));
31225f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-matis_fixempty","Fix local matrices in case of empty local rows/columns","MatISFixLocalEmpty",a->locempty,&a->locempty,NULL));
31235f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsBool("-matis_storel2l","Store local-to-local matrices generated from PtAP operations","MatISStoreL2L",a->storel2l,&a->storel2l,NULL));
31245f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsFList("-matis_localmat_type","Matrix type","MatISSetLocalMatType",MatList,a->lmattype,type,256,&flg));
31258546b261SStefano Zampini   if (flg) {
31265f80ce2aSJacob Faibussowitsch     CHKERRQ(MatISSetLocalMatType(A,type));
31278546b261SStefano Zampini   }
31288546b261SStefano Zampini   if (a->A) {
31295f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetFromOptions(a->A));
31308546b261SStefano Zampini   }
31315f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsTail());
3132872cf891SStefano Zampini   PetscFunctionReturn(0);
3133872cf891SStefano Zampini }
3134872cf891SStefano Zampini 
3135284134d9SBarry Smith /*@
31363c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
3137284134d9SBarry Smith        process but not across processes.
3138284134d9SBarry Smith 
3139284134d9SBarry Smith    Input Parameters:
3140284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
3141e176bc59SStefano Zampini .     bs      - block size of the matrix
3142df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
3143e176bc59SStefano Zampini .     rmap    - local to global map for rows
3144e176bc59SStefano Zampini -     cmap    - local to global map for cols
3145284134d9SBarry Smith 
3146284134d9SBarry Smith    Output Parameter:
3147284134d9SBarry Smith .    A - the resulting matrix
3148284134d9SBarry Smith 
31498e6c10adSSatish Balay    Level: advanced
31508e6c10adSSatish Balay 
315195452b02SPatrick Sanan    Notes:
315295452b02SPatrick Sanan     See MATIS for more details.
3153fc989267SStefano Zampini     m and n are NOT related to the size of the map; they represent the size of the local parts of the distributed vectors
31546fdf41d1SStefano Zampini     used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
3155fc989267SStefano Zampini     If rmap (cmap) is NULL, then the local row (column) spaces matches the global space.
3156284134d9SBarry Smith 
3157284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
3158284134d9SBarry Smith @*/
3159e176bc59SStefano Zampini PetscErrorCode MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
3160284134d9SBarry Smith {
3161284134d9SBarry Smith   PetscFunctionBegin;
31625f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreate(comm,A));
31635f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSizes(*A,m,n,M,N));
31646fdf41d1SStefano Zampini   if (bs > 0) {
31655f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetBlockSize(*A,bs));
31666fdf41d1SStefano Zampini   }
31675f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetType(*A,MATIS));
31685f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetLocalToGlobalMapping(*A,rmap,cmap));
3169284134d9SBarry Smith   PetscFunctionReturn(0);
3170284134d9SBarry Smith }
3171284134d9SBarry Smith 
31728b9382cfSStefano Zampini static PetscErrorCode MatHasOperation_IS(Mat A, MatOperation op, PetscBool *has)
31738b9382cfSStefano Zampini {
31748b9382cfSStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
31758b9382cfSStefano Zampini 
31768b9382cfSStefano Zampini   PetscFunctionBegin;
31778b9382cfSStefano Zampini   *has = PETSC_FALSE;
31788b9382cfSStefano Zampini   if (!((void**)A->ops)[op]) PetscFunctionReturn(0);
31795f80ce2aSJacob Faibussowitsch   CHKERRQ(MatHasOperation(a->A,op,has));
31808b9382cfSStefano Zampini   PetscFunctionReturn(0);
31818b9382cfSStefano Zampini }
31828b9382cfSStefano Zampini 
3183e432b41dSStefano Zampini static PetscErrorCode MatSetValuesCOO_IS(Mat A,const PetscScalar v[],InsertMode imode)
3184e432b41dSStefano Zampini {
3185e432b41dSStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
3186e432b41dSStefano Zampini 
3187e432b41dSStefano Zampini   PetscFunctionBegin;
31885f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetValuesCOO(a->A,v,imode));
31895f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY));
31905f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY));
3191e432b41dSStefano Zampini   PetscFunctionReturn(0);
3192e432b41dSStefano Zampini }
3193e432b41dSStefano Zampini 
3194e432b41dSStefano Zampini static PetscErrorCode MatSetPreallocationCOOLocal_IS(Mat A,PetscCount ncoo,PetscInt coo_i[],PetscInt coo_j[])
3195e432b41dSStefano Zampini {
3196e432b41dSStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
3197e432b41dSStefano Zampini 
3198e432b41dSStefano Zampini   PetscFunctionBegin;
3199e432b41dSStefano Zampini   PetscCheck(a->A,PetscObjectComm((PetscObject)A),PETSC_ERR_ORDER,"Need to provide l2g map first via MatSetLocalToGlobalMapping");
3200e432b41dSStefano Zampini   if (a->A->rmap->mapping || a->A->cmap->mapping) {
32015f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetPreallocationCOOLocal(a->A,ncoo,coo_i,coo_j));
3202e432b41dSStefano Zampini   } else {
32035f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetPreallocationCOO(a->A,ncoo,coo_i,coo_j));
3204e432b41dSStefano Zampini   }
32055f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatSetValuesCOO_C",MatSetValuesCOO_IS));
3206e432b41dSStefano Zampini   A->preallocated = PETSC_TRUE;
3207e432b41dSStefano Zampini   PetscFunctionReturn(0);
3208e432b41dSStefano Zampini }
3209e432b41dSStefano Zampini 
3210e432b41dSStefano Zampini static PetscErrorCode MatSetPreallocationCOO_IS(Mat A,PetscCount ncoo,const PetscInt coo_i[],const PetscInt coo_j[])
3211e432b41dSStefano Zampini {
3212e432b41dSStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
3213e432b41dSStefano Zampini   PetscInt       *coo_il, *coo_jl, incoo;
3214e432b41dSStefano Zampini 
3215e432b41dSStefano Zampini   PetscFunctionBegin;
3216e432b41dSStefano Zampini   PetscCheck(a->A,PetscObjectComm((PetscObject)A),PETSC_ERR_ORDER,"Need to provide l2g map first via MatSetLocalToGlobalMapping");
3217e432b41dSStefano Zampini   PetscCheck(ncoo <= PETSC_MAX_INT,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"ncoo %" PetscCount_FMT " overflowed PetscInt; configure --with-64-bit-indices or request support",ncoo);
32185f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc2(ncoo,&coo_il,ncoo,&coo_jl));
32195f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGlobalToLocalMappingApply(a->rmapping,IS_GTOLM_MASK,ncoo,coo_i,&incoo,coo_il));
32205f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGlobalToLocalMappingApply(a->cmapping,IS_GTOLM_MASK,ncoo,coo_j,&incoo,coo_jl));
32215f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetPreallocationCOO(a->A,ncoo,coo_il,coo_jl));
32225f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree2(coo_il,coo_jl));
32235f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatSetValuesCOO_C",MatSetValuesCOO_IS));
3224e432b41dSStefano Zampini   A->preallocated = PETSC_TRUE;
3225e432b41dSStefano Zampini   PetscFunctionReturn(0);
3226e432b41dSStefano Zampini }
3227e432b41dSStefano Zampini 
3228e432b41dSStefano Zampini /*@
3229e432b41dSStefano Zampini    MatISGetLocalToGlobalMapping - Gets the local-to-global numbering of the MATIS object
3230e432b41dSStefano Zampini 
3231e432b41dSStefano Zampini    Not Collective
3232e432b41dSStefano Zampini 
3233e432b41dSStefano Zampini    Input Parameter:
3234e432b41dSStefano Zampini .  A - the matrix
3235e432b41dSStefano Zampini 
3236e432b41dSStefano Zampini    Output Parameters:
3237e432b41dSStefano Zampini +  rmapping - row mapping
3238e432b41dSStefano Zampini -  cmapping - column mapping
3239e432b41dSStefano Zampini 
3240e432b41dSStefano Zampini    Notes: The returned map can be different from the one used to construct the MATIS object, since it will not contain negative or repeated indices.
3241e432b41dSStefano Zampini 
3242e432b41dSStefano Zampini    Level: advanced
3243e432b41dSStefano Zampini 
3244e432b41dSStefano Zampini .seealso:  MatSetLocalToGlobalMapping()
3245e432b41dSStefano Zampini @*/
3246e432b41dSStefano Zampini PetscErrorCode MatISGetLocalToGlobalMapping(Mat A,ISLocalToGlobalMapping *rmapping,ISLocalToGlobalMapping *cmapping)
3247e432b41dSStefano Zampini {
3248e432b41dSStefano Zampini   PetscFunctionBegin;
3249e432b41dSStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3250e432b41dSStefano Zampini   PetscValidType(A,1);
3251e432b41dSStefano Zampini   if (rmapping) PetscValidPointer(rmapping,2);
3252e432b41dSStefano Zampini   if (cmapping) PetscValidPointer(cmapping,3);
32535f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscUseMethod(A,"MatISGetLocalToGlobalMapping_C",(Mat,ISLocalToGlobalMapping*,ISLocalToGlobalMapping*),(A,rmapping,cmapping)));
3254e432b41dSStefano Zampini   PetscFunctionReturn(0);
3255e432b41dSStefano Zampini }
3256e432b41dSStefano Zampini 
3257e432b41dSStefano Zampini static PetscErrorCode MatISGetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping *r, ISLocalToGlobalMapping *c)
3258e432b41dSStefano Zampini {
3259e432b41dSStefano Zampini   Mat_IS *a = (Mat_IS*)A->data;
3260e432b41dSStefano Zampini 
3261e432b41dSStefano Zampini   PetscFunctionBegin;
3262e432b41dSStefano Zampini   if (r) *r = a->rmapping;
3263e432b41dSStefano Zampini   if (c) *c = a->cmapping;
3264e432b41dSStefano Zampini   PetscFunctionReturn(0);
3265e432b41dSStefano Zampini }
3266e432b41dSStefano Zampini 
3267b4319ba4SBarry Smith /*MC
3268f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
3269b89f26deSStefano Zampini    This stores the matrices in globally unassembled form. Each processor assembles only its local Neumann problem and the parallel matrix vector
3270b4319ba4SBarry Smith    product is handled "implicitly".
3271b4319ba4SBarry Smith 
3272b4319ba4SBarry Smith    Options Database Keys:
327375d48cdbSStefano Zampini + -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
327475d48cdbSStefano Zampini . -matis_fixempty - Fixes local matrices in case of empty local rows/columns.
327575d48cdbSStefano Zampini - -matis_storel2l - stores the local-to-local operators generated by the Galerkin process of MatPtAP().
3276b4319ba4SBarry Smith 
327795452b02SPatrick Sanan    Notes:
327895452b02SPatrick Sanan     Options prefix for the inner matrix are given by -is_mat_xxx
3279b4319ba4SBarry Smith 
3280b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
3281b4319ba4SBarry Smith 
3282b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
3283eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
3284b4319ba4SBarry Smith 
3285b4319ba4SBarry Smith   Level: advanced
3286b4319ba4SBarry Smith 
3287f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
3288b4319ba4SBarry Smith 
3289b4319ba4SBarry Smith M*/
32908cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
3291b4319ba4SBarry Smith {
3292e432b41dSStefano Zampini   Mat_IS         *a;
3293b4319ba4SBarry Smith 
3294b4319ba4SBarry Smith   PetscFunctionBegin;
32955f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscNewLog(A,&a));
32965f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrallocpy(MATAIJ,&a->lmattype));
3297e432b41dSStefano Zampini   A->data = (void*)a;
3298b4319ba4SBarry Smith 
3299e176bc59SStefano Zampini   /* matrix ops */
33005f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMemzero(A->ops,sizeof(struct _MatOps)));
3301b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
33022e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
33032e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
33042e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
3305b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
3306b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
33072e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
330898921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
3309b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
3310f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
33112e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
3312f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
3313b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
3314b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
3315b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
33166726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
33172e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
33182e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
33196726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
332069796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
332169796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
332245471136SStefano Zampini   A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS;
3323ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
33246bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
33252b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
3326659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
33277dae84e0SHong Zhang   A->ops->createsubmatrix         = MatCreateSubMatrix_IS;
3328f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
33293fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
33303fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
3331d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
33327fa8f2d3SStefano Zampini   A->ops->getinfo                 = MatGetInfo_IS;
3333ad219c80Sstefano_zampini   A->ops->diagonalscale           = MatDiagonalScale_IS;
3334872cf891SStefano Zampini   A->ops->setfromoptions          = MatSetFromOptions_IS;
3335fc989267SStefano Zampini   A->ops->setup                   = MatSetUp_IS;
33368b9382cfSStefano Zampini   A->ops->hasoperation            = MatHasOperation_IS;
3337b4319ba4SBarry Smith 
3338b7ce53b6SStefano Zampini   /* special MATIS functions */
33395f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMatType_C",MatISSetLocalMatType_IS));
33405f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS));
33415f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatISRestoreLocalMat_C",MatISRestoreLocalMat_IS));
33425f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS));
33435f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatConvert_IS_XAIJ));
33445f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS));
33455f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",MatISStoreL2L_IS));
33465f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",MatISFixLocalEmpty_IS));
33475f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalToGlobalMapping_C",MatISGetLocalToGlobalMapping_IS));
33485f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",MatConvert_IS_XAIJ));
33495f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",MatConvert_IS_XAIJ));
33505f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",MatConvert_IS_XAIJ));
33515f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",MatConvert_IS_XAIJ));
33525f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",MatConvert_IS_XAIJ));
33535f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",MatConvert_IS_XAIJ));
33545f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",MatConvert_IS_XAIJ));
33555f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOOLocal_C",MatSetPreallocationCOOLocal_IS));
33565f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOO_C",MatSetPreallocationCOO_IS));
33575f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectChangeTypeName((PetscObject)A,MATIS));
3358b4319ba4SBarry Smith   PetscFunctionReturn(0);
3359b4319ba4SBarry Smith }
3360