xref: /petsc/src/mat/impls/is/matis.c (revision aed4548f7b57b3f3898d52ba71a524e0765402ff)
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;
259566063dSJacob Faibussowitsch   PetscCall(MatDestroySubMatrices(ptap->ris1 ? 2 : 1,&ptap->lP));
269566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&ptap->cis0));
279566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&ptap->cis1));
289566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&ptap->ris0));
299566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&ptap->ris1));
309566063dSJacob Faibussowitsch   PetscCall(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;
459566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)C,"_MatIS_PtAP",(PetscObject*)&c));
4628b400f6SJacob Faibussowitsch   PetscCheck(c,PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing PtAP information");
479566063dSJacob Faibussowitsch   PetscCall(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;
549566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrices(P,n,ris,cis,reuse,&ptap->lP));
5575d48cdbSStefano Zampini 
569566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(A,&lA));
579566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(C,&lC));
5875d48cdbSStefano Zampini   if (ptap->ris1) { /* unsymmetric A mapping */
5975d48cdbSStefano Zampini     Mat lPt;
6075d48cdbSStefano Zampini 
619566063dSJacob Faibussowitsch     PetscCall(MatTranspose(ptap->lP[1],MAT_INITIAL_MATRIX,&lPt));
629566063dSJacob Faibussowitsch     PetscCall(MatMatMatMult(lPt,lA,ptap->lP[0],reuse,ptap->fill,&lC));
6375d48cdbSStefano Zampini     if (matis->storel2l) {
649566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",(PetscObject)lPt));
6575d48cdbSStefano Zampini     }
669566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&lPt));
6775d48cdbSStefano Zampini   } else {
689566063dSJacob Faibussowitsch     PetscCall(MatPtAP(lA,ptap->lP[0],reuse,ptap->fill,&lC));
6975d48cdbSStefano Zampini     if (matis->storel2l) {
709566063dSJacob Faibussowitsch      PetscCall(PetscObjectCompose((PetscObject)C,"_MatIS_PtAP_l2l",(PetscObject)ptap->lP[0]));
7175d48cdbSStefano Zampini     }
7275d48cdbSStefano Zampini   }
7375d48cdbSStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
749566063dSJacob Faibussowitsch     PetscCall(MatISSetLocalMat(C,lC));
759566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&lC));
7675d48cdbSStefano Zampini   }
779566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY));
789566063dSJacob Faibussowitsch   PetscCall(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);
959566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)PT,&comm));
9675d48cdbSStefano Zampini   bs   = 1;
979566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)PT,MATMPIAIJ,&ismpiaij));
989566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)PT,MATMPIBAIJ,&ismpibaij));
999566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)PT,MATSEQAIJ,&isseqaij));
1009566063dSJacob Faibussowitsch   PetscCall(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) {
1069566063dSJacob Faibussowitsch     PetscCall(MatMPIAIJGetSeqAIJ(PT,&Pd,&Po,&garray));
10775d48cdbSStefano Zampini   } else if (ismpibaij) {
1089566063dSJacob Faibussowitsch     PetscCall(MatMPIBAIJGetSeqBAIJ(PT,&Pd,&Po,&garray));
1099566063dSJacob Faibussowitsch     PetscCall(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) {
1179566063dSJacob Faibussowitsch     PetscCall(MatFindNonzeroRowsOrCols_Basic(Po,PETSC_TRUE,PETSC_SMALL,&zo));
11875d48cdbSStefano Zampini   }
1199566063dSJacob Faibussowitsch   PetscCall(MatFindNonzeroRowsOrCols_Basic(Pd,PETSC_TRUE,PETSC_SMALL,&zd));
12075d48cdbSStefano Zampini 
1219566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(PT,NULL,&dc));
1229566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRangeColumn(PT,&stc,NULL));
1239566063dSJacob Faibussowitsch   if (Po) PetscCall(MatGetLocalSize(Po,NULL,&oc));
12475d48cdbSStefano Zampini   else oc = 0;
1259566063dSJacob Faibussowitsch   PetscCall(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 */
1319566063dSJacob Faibussowitsch     PetscCall(ISSetBlockSize(zd,bs));
1329566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(zd,&nz));
1339566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(zd,&idxs));
13475d48cdbSStefano Zampini     ctd  = nz/bs;
13575d48cdbSStefano Zampini     for (i=0; i<ctd; i++) aux[i] = (idxs[bs*i]+stc)/bs;
1369566063dSJacob Faibussowitsch     PetscCall(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 */
1469566063dSJacob Faibussowitsch     PetscCall(ISSetBlockSize(zo,bs));
1479566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(zo,&nz));
1489566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(zo,&idxs));
14975d48cdbSStefano Zampini     cto  = nz/bs;
15075d48cdbSStefano Zampini     for (i=0; i<cto; i++) aux[i+ctd] = garray[idxs[bs*i]/bs];
1519566063dSJacob Faibussowitsch     PetscCall(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   }
1569566063dSJacob Faibussowitsch   PetscCall(ISCreateBlock(comm,bs,ctd+cto,aux,PETSC_OWN_POINTER,cis));
1579566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&zd));
1589566063dSJacob Faibussowitsch   PetscCall(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;
1749566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)A,&comm));
1759566063dSJacob Faibussowitsch   PetscCall(MatSetType(C,MATIS));
1769566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(A,&lA));
1779566063dSJacob Faibussowitsch   PetscCall(MatGetType(lA,&lmtype));
1789566063dSJacob Faibussowitsch   PetscCall(MatISSetLocalMatType(C,lmtype));
1799566063dSJacob Faibussowitsch   PetscCall(MatGetSize(P,NULL,&N));
1809566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(P,NULL,&dc));
1819566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C,dc,dc,N,N));
18275d48cdbSStefano Zampini /* Not sure about this
1839566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSizes(P,NULL,&ibs));
1849566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(*C,ibs));
18575d48cdbSStefano Zampini */
18675d48cdbSStefano Zampini 
1879566063dSJacob Faibussowitsch   PetscCall(PetscNew(&ptap));
1889566063dSJacob Faibussowitsch   PetscCall(PetscContainerCreate(PETSC_COMM_SELF,&c));
1899566063dSJacob Faibussowitsch   PetscCall(PetscContainerSetPointer(c,ptap));
1909566063dSJacob Faibussowitsch   PetscCall(PetscContainerSetUserDestroy(c,MatISContainerDestroyPtAP_Private));
1919566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)C,"_MatIS_PtAP",(PetscObject)c));
1929566063dSJacob Faibussowitsch   PetscCall(PetscContainerDestroy(&c));
19375d48cdbSStefano Zampini   ptap->fill = fill;
19475d48cdbSStefano Zampini 
1959566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalToGlobalMapping(A,&rl2g,&cl2g));
19675d48cdbSStefano Zampini 
1979566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(cl2g,&ibs));
1989566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(cl2g,&N));
1999566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockIndices(cl2g,&garray));
2009566063dSJacob Faibussowitsch   PetscCall(ISCreateBlock(comm,ibs,N/ibs,garray,PETSC_COPY_VALUES,&ptap->ris0));
2019566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(cl2g,&garray));
20275d48cdbSStefano Zampini 
2039566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrix(P,ptap->ris0,NULL,MAT_INITIAL_MATRIX,&PT));
2049566063dSJacob Faibussowitsch   PetscCall(MatGetNonzeroColumnsLocal_Private(PT,&ptap->cis0));
2059566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(ptap->cis0,&Ccl2g));
2069566063dSJacob Faibussowitsch   PetscCall(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 
2139566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetSize(rl2g,&N1));
2149566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockSize(rl2g,&ibs1));
2159566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockIndices(rl2g,&garray));
2169566063dSJacob Faibussowitsch     PetscCall(ISCreateBlock(comm,ibs,N/ibs,garray,PETSC_COPY_VALUES,&ptap->ris1));
2179566063dSJacob Faibussowitsch     PetscCall(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 
2219566063dSJacob Faibussowitsch       PetscCall(ISBlockGetIndices(ptap->ris0,&i1));
2229566063dSJacob Faibussowitsch       PetscCall(ISBlockGetIndices(ptap->ris1,&i2));
2239566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(i1,i2,N,&lsame));
22475d48cdbSStefano Zampini     }
2251c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&lsame,&same,1,MPIU_BOOL,MPI_LAND,comm));
22675d48cdbSStefano Zampini     if (same) {
2279566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&ptap->ris1));
22875d48cdbSStefano Zampini     } else {
2299566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(P,ptap->ris1,NULL,MAT_INITIAL_MATRIX,&PT));
2309566063dSJacob Faibussowitsch       PetscCall(MatGetNonzeroColumnsLocal_Private(PT,&ptap->cis1));
2319566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreateIS(ptap->cis1,&Crl2g));
2329566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&PT));
23375d48cdbSStefano Zampini     }
23475d48cdbSStefano Zampini   }
23575d48cdbSStefano Zampini /* Not sure about this
23675d48cdbSStefano Zampini   if (!Crl2g) {
2379566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(C,&ibs));
2389566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingSetBlockSize(Ccl2g,ibs));
23975d48cdbSStefano Zampini   }
24075d48cdbSStefano Zampini */
2419566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(C,Crl2g ? Crl2g : Ccl2g,Ccl2g));
2429566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&Crl2g));
2439566063dSJacob Faibussowitsch   PetscCall(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;
2579566063dSJacob Faibussowitsch   PetscCall(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) {
2759566063dSJacob Faibussowitsch     PetscCall(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++) {
2889566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&lf->rf[i]));
2895b003df0Sstefano_zampini   }
2905b003df0Sstefano_zampini   for (i=0;i<lf->nc;i++) {
2919566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&lf->cf[i]));
2925b003df0Sstefano_zampini   }
2939566063dSJacob Faibussowitsch   PetscCall(PetscFree2(lf->rf,lf->cf));
2949566063dSJacob Faibussowitsch   PetscCall(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 
3089566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(A,&bs));
3099566063dSJacob Faibussowitsch     PetscCall(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 
3149566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(is,&i));
3159566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(is,(const PetscInt**)&aux));
3169566063dSJacob Faibussowitsch       PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A),bs,i,aux,PETSC_COPY_VALUES,&is2));
3179566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(is,(const PetscInt**)&aux));
3189566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is));
319c9225affSStefano Zampini       is   = is2;
320c9225affSStefano Zampini     }
3219566063dSJacob Faibussowitsch     PetscCall(ISSetIdentity(is));
3229566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is,&rl2g));
3239566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
3249566063dSJacob Faibussowitsch     PetscCall(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 
3299566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(is,&i));
3309566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(is,(const PetscInt**)&aux));
3319566063dSJacob Faibussowitsch       PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A),bs,i,aux,PETSC_COPY_VALUES,&is2));
3329566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(is,(const PetscInt**)&aux));
3339566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is));
334c9225affSStefano Zampini       is   = is2;
335c9225affSStefano Zampini     }
3369566063dSJacob Faibussowitsch     PetscCall(ISSetIdentity(is));
3379566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is,&cl2g));
3389566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
3399566063dSJacob Faibussowitsch     PetscCall(MatCreateIS(PetscObjectComm((PetscObject)A),bs,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N,rl2g,cl2g,&B));
3409566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
3419566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
3429566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(A,MAT_COPY_VALUES,&lB));
343c9225affSStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) *newmat = B;
344c9225affSStefano Zampini   } else {
345c9225affSStefano Zampini     B    = *newmat;
3469566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)A));
347c9225affSStefano Zampini     lB   = A;
348c9225affSStefano Zampini   }
3499566063dSJacob Faibussowitsch   PetscCall(MatISSetLocalMat(B,lB));
3509566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&lB));
3519566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
3529566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
353c9225affSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
3549566063dSJacob Faibussowitsch     PetscCall(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;
3699566063dSJacob Faibussowitsch   PetscCall(MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&m,&ii,&jj,&flg));
37008401ef6SPierre Jolivet   PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
3719566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetNodeInfo(matis->rmapping,&n,&ecount,&eneighs));
37208401ef6SPierre Jolivet   PetscCheck(m == n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %" PetscInt_FMT " != %" PetscInt_FMT,m,n);
3739566063dSJacob Faibussowitsch   PetscCall(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   }
3919566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(matis->rmapping,&n,&ecount,&eneighs));
3929566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(matis->A,&aa));
3939566063dSJacob Faibussowitsch   PetscCall(MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&m,&ii,&jj,&flg));
39408401ef6SPierre Jolivet   PetscCheck(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 
413c9225affSStefano Zampini   PetscFunctionBegin;
414d0609cedSBarry Smith   PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"MatIS l2g disassembling options","Mat");
4159566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-mat_is_disassemble_l2g_type","Type of local-to-global mapping to be used for disassembling","MatISDisassemblel2gType",MatISDisassemblel2gTypes,(PetscEnum)mode,(PetscEnum*)&mode,NULL));
416d0609cedSBarry Smith   PetscOptionsEnd();
417fabe8965SStefano Zampini   if (mode == MAT_IS_DISASSEMBLE_L2G_MAT) {
4189566063dSJacob Faibussowitsch     PetscCall(MatGetLocalToGlobalMapping(A,l2g,NULL));
419c9225affSStefano Zampini     PetscFunctionReturn(0);
420c9225affSStefano Zampini   }
4219566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)A,&comm));
4229566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij));
4239566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A,MATMPIBAIJ,&ismpibaij));
4249566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(A,&bs));
425fabe8965SStefano Zampini   switch (mode) {
426fabe8965SStefano Zampini   case MAT_IS_DISASSEMBLE_L2G_ND:
4279566063dSJacob Faibussowitsch     PetscCall(MatPartitioningCreate(comm,&part));
4289566063dSJacob Faibussowitsch     PetscCall(MatPartitioningSetAdjacency(part,A));
4299566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)part,((PetscObject)A)->prefix));
4309566063dSJacob Faibussowitsch     PetscCall(MatPartitioningSetFromOptions(part));
4319566063dSJacob Faibussowitsch     PetscCall(MatPartitioningApplyND(part,&ndmap));
4329566063dSJacob Faibussowitsch     PetscCall(MatPartitioningDestroy(&part));
4339566063dSJacob Faibussowitsch     PetscCall(ISBuildTwoSided(ndmap,NULL,&ndsub));
4349566063dSJacob Faibussowitsch     PetscCall(MatMPIAIJSetUseScalableIncreaseOverlap(A,PETSC_TRUE));
4359566063dSJacob Faibussowitsch     PetscCall(MatIncreaseOverlap(A,1,&ndsub,1));
4369566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(ndsub,l2g));
437fabe8965SStefano Zampini 
438fabe8965SStefano Zampini     /* it may happen that a separator node is not properly shared */
4399566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetNodeInfo(*l2g,&nl,&ncount,NULL));
4409566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(comm,&sf));
4419566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetIndices(*l2g,&garray));
4429566063dSJacob Faibussowitsch     PetscCall(PetscSFSetGraphLayout(sf,A->rmap,nl,NULL,PETSC_OWN_POINTER,garray));
4439566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreIndices(*l2g,&garray));
4449566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(A->rmap->n,&ndmapc));
4459566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceBegin(sf,MPIU_INT,ncount,ndmapc,MPI_REPLACE));
4469566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceEnd(sf,MPIU_INT,ncount,ndmapc,MPI_REPLACE));
4479566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(*l2g,NULL,&ncount,NULL));
4489566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(ndmap,&ndmapi));
449fabe8965SStefano Zampini     for (i = 0, cnt = 0; i < A->rmap->n; i++)
450fabe8965SStefano Zampini       if (ndmapi[i] < 0 && ndmapc[i] < 2)
451fabe8965SStefano Zampini         cnt++;
452fabe8965SStefano Zampini 
4531c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&cnt,&i,1,MPIU_INT,MPI_MAX,comm));
454fabe8965SStefano Zampini     if (i) { /* we detected isolated separator nodes */
455fabe8965SStefano Zampini       Mat                    A2,A3;
456fabe8965SStefano Zampini       IS                     *workis,is2;
457fabe8965SStefano Zampini       PetscScalar            *vals;
458fabe8965SStefano Zampini       PetscInt               gcnt = i,*dnz,*onz,j,*lndmapi;
459fabe8965SStefano Zampini       ISLocalToGlobalMapping ll2g;
460fabe8965SStefano Zampini       PetscBool              flg;
461fabe8965SStefano Zampini       const PetscInt         *ii,*jj;
462fabe8965SStefano Zampini 
463fabe8965SStefano Zampini       /* communicate global id of separators */
464d0609cedSBarry Smith       MatPreallocateBegin(comm,A->rmap->n,A->cmap->n,dnz,onz);
465fabe8965SStefano Zampini       for (i = 0, cnt = 0; i < A->rmap->n; i++)
466fabe8965SStefano Zampini         dnz[i] = ndmapi[i] < 0 ? i + A->rmap->rstart : -1;
467fabe8965SStefano Zampini 
4689566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nl,&lndmapi));
4699566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastBegin(sf,MPIU_INT,dnz,lndmapi,MPI_REPLACE));
470fabe8965SStefano Zampini 
471fabe8965SStefano Zampini       /* compute adjacency of isolated separators node */
4729566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(gcnt,&workis));
473fabe8965SStefano Zampini       for (i = 0, cnt = 0; i < A->rmap->n; i++) {
474fabe8965SStefano Zampini         if (ndmapi[i] < 0 && ndmapc[i] < 2) {
4759566063dSJacob Faibussowitsch           PetscCall(ISCreateStride(comm,1,i+A->rmap->rstart,1,&workis[cnt++]));
476fabe8965SStefano Zampini         }
477fabe8965SStefano Zampini       }
478fabe8965SStefano Zampini       for (i = cnt; i < gcnt; i++) {
4799566063dSJacob Faibussowitsch         PetscCall(ISCreateStride(comm,0,0,1,&workis[i]));
480fabe8965SStefano Zampini       }
481fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
4829566063dSJacob Faibussowitsch         PetscCall(PetscObjectSetName((PetscObject)workis[i],"ISOLATED"));
4839566063dSJacob Faibussowitsch         PetscCall(ISViewFromOptions(workis[i],NULL,"-view_isolated_separators"));
484fabe8965SStefano Zampini       }
485fabe8965SStefano Zampini 
486fabe8965SStefano Zampini       /* no communications since all the ISes correspond to locally owned rows */
4879566063dSJacob Faibussowitsch       PetscCall(MatIncreaseOverlap(A,gcnt,workis,1));
488fabe8965SStefano Zampini 
489fabe8965SStefano Zampini       /* end communicate global id of separators */
4909566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastEnd(sf,MPIU_INT,dnz,lndmapi,MPI_REPLACE));
491fabe8965SStefano Zampini 
492fabe8965SStefano Zampini       /* communicate new layers : create a matrix and transpose it */
4939566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(dnz,A->rmap->n));
4949566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(onz,A->rmap->n));
495fabe8965SStefano Zampini       for (i = 0, j = 0; i < A->rmap->n; i++) {
496fabe8965SStefano Zampini         if (ndmapi[i] < 0 && ndmapc[i] < 2) {
497fabe8965SStefano Zampini           const PetscInt* idxs;
498fabe8965SStefano Zampini           PetscInt        s;
499fabe8965SStefano Zampini 
5009566063dSJacob Faibussowitsch           PetscCall(ISGetLocalSize(workis[j],&s));
5019566063dSJacob Faibussowitsch           PetscCall(ISGetIndices(workis[j],&idxs));
5029566063dSJacob Faibussowitsch           PetscCall(MatPreallocateSet(i+A->rmap->rstart,s,idxs,dnz,onz));
503fabe8965SStefano Zampini           j++;
504fabe8965SStefano Zampini         }
505fabe8965SStefano Zampini       }
50608401ef6SPierre Jolivet       PetscCheck(j == cnt,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected local count %" PetscInt_FMT " != %" PetscInt_FMT,j,cnt);
507fabe8965SStefano Zampini 
508fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
5099566063dSJacob Faibussowitsch         PetscCall(PetscObjectSetName((PetscObject)workis[i],"EXTENDED"));
5109566063dSJacob Faibussowitsch         PetscCall(ISViewFromOptions(workis[i],NULL,"-view_isolated_separators"));
511fabe8965SStefano Zampini       }
512fabe8965SStefano Zampini 
513fabe8965SStefano Zampini       for (i = 0, j = 0; i < A->rmap->n; i++) j = PetscMax(j,dnz[i]+onz[i]);
5149566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(j,&vals));
515fabe8965SStefano Zampini       for (i = 0; i < j; i++) vals[i] = 1.0;
516fabe8965SStefano Zampini 
5179566063dSJacob Faibussowitsch       PetscCall(MatCreate(comm,&A2));
5189566063dSJacob Faibussowitsch       PetscCall(MatSetType(A2,MATMPIAIJ));
5199566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(A2,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N));
5209566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJSetPreallocation(A2,0,dnz,0,onz));
5219566063dSJacob Faibussowitsch       PetscCall(MatSetOption(A2,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE));
522fabe8965SStefano Zampini       for (i = 0, j = 0; i < A2->rmap->n; i++) {
523fabe8965SStefano Zampini         PetscInt        row = i+A2->rmap->rstart,s = dnz[i] + onz[i];
524fabe8965SStefano Zampini         const PetscInt* idxs;
525fabe8965SStefano Zampini 
526fabe8965SStefano Zampini         if (s) {
5279566063dSJacob Faibussowitsch           PetscCall(ISGetIndices(workis[j],&idxs));
5289566063dSJacob Faibussowitsch           PetscCall(MatSetValues(A2,1,&row,s,idxs,vals,INSERT_VALUES));
5299566063dSJacob Faibussowitsch           PetscCall(ISRestoreIndices(workis[j],&idxs));
530fabe8965SStefano Zampini           j++;
531fabe8965SStefano Zampini         }
532fabe8965SStefano Zampini       }
53308401ef6SPierre Jolivet       PetscCheck(j == cnt,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected local count %" PetscInt_FMT " != %" PetscInt_FMT,j,cnt);
5349566063dSJacob Faibussowitsch       PetscCall(PetscFree(vals));
5359566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A2,MAT_FINAL_ASSEMBLY));
5369566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A2,MAT_FINAL_ASSEMBLY));
5379566063dSJacob Faibussowitsch       PetscCall(MatTranspose(A2,MAT_INPLACE_MATRIX,&A2));
538fabe8965SStefano Zampini 
539fabe8965SStefano Zampini       /* extract submatrix corresponding to the coupling "owned separators" x "isolated separators" */
540fabe8965SStefano Zampini       for (i = 0, j = 0; i < nl; i++)
541fabe8965SStefano Zampini         if (lndmapi[i] >= 0) lndmapi[j++] = lndmapi[i];
5429566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(comm,j,lndmapi,PETSC_USE_POINTER,&is));
5439566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJGetLocalMatCondensed(A2,MAT_INITIAL_MATRIX,&is,NULL,&A3));
5449566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is));
5459566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&A2));
546fabe8965SStefano Zampini 
547fabe8965SStefano Zampini       /* extend local to global map to include connected isolated separators */
5489566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)A3,"_petsc_GetLocalMatCondensed_iscol",(PetscObject*)&is));
54928b400f6SJacob Faibussowitsch       PetscCheck(is,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing column map");
5509566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreateIS(is,&ll2g));
5519566063dSJacob Faibussowitsch       PetscCall(MatGetRowIJ(A3,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&flg));
55228b400f6SJacob Faibussowitsch       PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
5539566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF,ii[i],jj,PETSC_COPY_VALUES,&is));
5549566063dSJacob Faibussowitsch       PetscCall(MatRestoreRowIJ(A3,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&flg));
55528b400f6SJacob Faibussowitsch       PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
5569566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingApplyIS(ll2g,is,&is2));
5579566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is));
5589566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingDestroy(&ll2g));
559fabe8965SStefano Zampini 
560fabe8965SStefano Zampini       /* add new nodes to the local-to-global map */
5619566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingDestroy(l2g));
5629566063dSJacob Faibussowitsch       PetscCall(ISExpand(ndsub,is2,&is));
5639566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is2));
5649566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreateIS(is,l2g));
5659566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is));
566fabe8965SStefano Zampini 
5679566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&A3));
5689566063dSJacob Faibussowitsch       PetscCall(PetscFree(lndmapi));
569d0609cedSBarry Smith       MatPreallocateEnd(dnz,onz);
570fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
5719566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&workis[i]));
572fabe8965SStefano Zampini       }
5739566063dSJacob Faibussowitsch       PetscCall(PetscFree(workis));
574fabe8965SStefano Zampini     }
5759566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(ndmap,&ndmapi));
5769566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sf));
5779566063dSJacob Faibussowitsch     PetscCall(PetscFree(ndmapc));
5789566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&ndmap));
5799566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&ndsub));
5809566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingSetBlockSize(*l2g,bs));
5819566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingViewFromOptions(*l2g,NULL,"-matis_nd_l2g_view"));
582fabe8965SStefano Zampini     break;
583fabe8965SStefano Zampini   case MAT_IS_DISASSEMBLE_L2G_NATURAL:
584fabe8965SStefano Zampini     if (ismpiaij) {
5859566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJGetSeqAIJ(A,&Ad,&Ao,&garray));
586fabe8965SStefano Zampini     } else if (ismpibaij) {
5879566063dSJacob Faibussowitsch       PetscCall(MatMPIBAIJGetSeqBAIJ(A,&Ad,&Ao,&garray));
58898921bdaSJacob Faibussowitsch     } else SETERRQ(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name);
58928b400f6SJacob Faibussowitsch     PetscCheck(garray,comm,PETSC_ERR_ARG_WRONGSTATE,"garray not present");
590c9225affSStefano Zampini     if (A->rmap->n) {
591fabe8965SStefano Zampini       PetscInt dc,oc,stc,*aux;
592c9225affSStefano Zampini 
593ebf8cefbSJunchao Zhang       PetscCall(MatGetLocalSize(Ad,NULL,&dc));
5949566063dSJacob Faibussowitsch       PetscCall(MatGetLocalSize(Ao,NULL,&oc));
5959566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRangeColumn(A,&stc,NULL));
5969566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1((dc+oc)/bs,&aux));
597c9225affSStefano Zampini       for (i=0; i<dc/bs; i++) aux[i]       = i+stc/bs;
598ebf8cefbSJunchao Zhang       for (i=0; i<oc/bs; i++) aux[i+dc/bs] = (ismpiaij ? garray[i*bs]/bs : garray[i]);
5999566063dSJacob Faibussowitsch       PetscCall(ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is));
600c9225affSStefano Zampini     } else {
6019566063dSJacob Faibussowitsch       PetscCall(ISCreateBlock(comm,1,0,NULL,PETSC_OWN_POINTER,&is));
602c9225affSStefano Zampini     }
6039566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is,l2g));
6049566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
605fabe8965SStefano Zampini     break;
606fabe8965SStefano Zampini   default:
60798921bdaSJacob Faibussowitsch     SETERRQ(comm,PETSC_ERR_ARG_WRONG,"Unsupported l2g disassembling type %d",mode);
608c9225affSStefano Zampini   }
609c9225affSStefano Zampini   PetscFunctionReturn(0);
610c9225affSStefano Zampini }
611c9225affSStefano Zampini 
612c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
613c9225affSStefano Zampini {
614c9225affSStefano Zampini   Mat                    lA,Ad,Ao,B = NULL;
6156989cf23SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
6166989cf23SStefano Zampini   IS                     is;
6176989cf23SStefano Zampini   MPI_Comm               comm;
6186989cf23SStefano Zampini   void                   *ptrs[2];
6196989cf23SStefano Zampini   const char             *names[2] = {"_convert_csr_aux","_convert_csr_data"};
620c9225affSStefano Zampini   const PetscInt         *garray;
6216989cf23SStefano Zampini   PetscScalar            *dd,*od,*aa,*data;
622c9225affSStefano Zampini   const PetscInt         *di,*dj,*oi,*oj;
623c9225affSStefano Zampini   const PetscInt         *odi,*odj,*ooi,*ooj;
6246989cf23SStefano Zampini   PetscInt               *aux,*ii,*jj;
625c9225affSStefano Zampini   PetscInt               bs,lc,dr,dc,oc,str,stc,nnz,i,jd,jo,cum;
626c9225affSStefano Zampini   PetscBool              flg,ismpiaij,ismpibaij,was_inplace = PETSC_FALSE;
627c9225affSStefano Zampini   PetscMPIInt            size;
6286989cf23SStefano Zampini 
629ab4d48faSStefano Zampini   PetscFunctionBegin;
6309566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)A,&comm));
6319566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm,&size));
632c9225affSStefano Zampini   if (size == 1) {
6339566063dSJacob Faibussowitsch     PetscCall(MatConvert_SeqXAIJ_IS(A,type,reuse,newmat));
634c9225affSStefano Zampini     PetscFunctionReturn(0);
635c9225affSStefano Zampini   }
636c9225affSStefano Zampini   if (reuse != MAT_REUSE_MATRIX && A->cmap->N == A->rmap->N) {
6379566063dSJacob Faibussowitsch     PetscCall(MatMPIXAIJComputeLocalToGlobalMapping_Private(A,&rl2g));
6389566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm,&B));
6399566063dSJacob Faibussowitsch     PetscCall(MatSetType(B,MATIS));
6409566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N));
6419566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(B,rl2g,rl2g));
6429566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(A,&bs));
6439566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSize(B,bs));
6449566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
645c9225affSStefano Zampini     if (reuse == MAT_INPLACE_MATRIX) was_inplace = PETSC_TRUE;
646c9225affSStefano Zampini     reuse = MAT_REUSE_MATRIX;
647c9225affSStefano Zampini   }
648c9225affSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
649c9225affSStefano Zampini     Mat            *newlA, lA;
650c9225affSStefano Zampini     IS             rows, cols;
651c9225affSStefano Zampini     const PetscInt *ridx, *cidx;
652c9225affSStefano Zampini     PetscInt       rbs, cbs, nr, nc;
653c9225affSStefano Zampini 
654c9225affSStefano Zampini     if (!B) B = *newmat;
6559566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalToGlobalMapping(B,&rl2g,&cl2g));
6569566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockIndices(rl2g,&ridx));
6579566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockIndices(cl2g,&cidx));
6589566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetSize(rl2g,&nr));
6599566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetSize(cl2g,&nc));
6609566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockSize(rl2g,&rbs));
6619566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockSize(cl2g,&cbs));
6629566063dSJacob Faibussowitsch     PetscCall(ISCreateBlock(comm,rbs,nr/rbs,ridx,PETSC_USE_POINTER,&rows));
663c9225affSStefano Zampini     if (rl2g != cl2g) {
6649566063dSJacob Faibussowitsch       PetscCall(ISCreateBlock(comm,cbs,nc/cbs,cidx,PETSC_USE_POINTER,&cols));
665c9225affSStefano Zampini     } else {
6669566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)rows));
667c9225affSStefano Zampini       cols = rows;
668c9225affSStefano Zampini     }
6699566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(B,&lA));
6709566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrices(A,1,&rows,&cols,MAT_INITIAL_MATRIX,&newlA));
6719566063dSJacob Faibussowitsch     PetscCall(MatConvert(newlA[0],MATSEQAIJ,MAT_INPLACE_MATRIX,&newlA[0]));
6729566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(rl2g,&ridx));
6739566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(cl2g,&cidx));
6749566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&rows));
6759566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&cols));
676c9225affSStefano Zampini     if (!lA->preallocated) { /* first time */
6779566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(newlA[0],MAT_COPY_VALUES,&lA));
6789566063dSJacob Faibussowitsch       PetscCall(MatISSetLocalMat(B,lA));
6799566063dSJacob Faibussowitsch       PetscCall(PetscObjectDereference((PetscObject)lA));
680c9225affSStefano Zampini     }
6819566063dSJacob Faibussowitsch     PetscCall(MatCopy(newlA[0],lA,SAME_NONZERO_PATTERN));
6829566063dSJacob Faibussowitsch     PetscCall(MatDestroySubMatrices(1,&newlA));
6839566063dSJacob Faibussowitsch     PetscCall(MatISScaleDisassembling_Private(B));
6849566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
6859566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
6869566063dSJacob Faibussowitsch     if (was_inplace) PetscCall(MatHeaderReplace(A,&B));
687c9225affSStefano Zampini     else *newmat = B;
688c9225affSStefano Zampini     PetscFunctionReturn(0);
689c9225affSStefano Zampini   }
690c9225affSStefano Zampini   /* rectangular case, just compress out the column space */
6919566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij));
6929566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A,MATMPIBAIJ,&ismpibaij));
693c9225affSStefano Zampini   if (ismpiaij) {
694c9225affSStefano Zampini     bs   = 1;
6959566063dSJacob Faibussowitsch     PetscCall(MatMPIAIJGetSeqAIJ(A,&Ad,&Ao,&garray));
696c9225affSStefano Zampini   } else if (ismpibaij) {
6979566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(A,&bs));
6989566063dSJacob Faibussowitsch     PetscCall(MatMPIBAIJGetSeqBAIJ(A,&Ad,&Ao,&garray));
6999566063dSJacob Faibussowitsch     PetscCall(MatConvert(Ad,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ad));
7009566063dSJacob Faibussowitsch     PetscCall(MatConvert(Ao,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ao));
70198921bdaSJacob Faibussowitsch   } else SETERRQ(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name);
7029566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(Ad,&dd));
7039566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(Ao,&od));
70428b400f6SJacob Faibussowitsch   PetscCheck(garray,comm,PETSC_ERR_ARG_WRONGSTATE,"garray not present");
7056989cf23SStefano Zampini 
7066989cf23SStefano Zampini   /* access relevant information from MPIAIJ */
7079566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A,&str,NULL));
7089566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRangeColumn(A,&stc,NULL));
7099566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A,&dr,&dc));
7109566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(Ao,NULL,&oc));
7119566063dSJacob Faibussowitsch   PetscCall(MatGetRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&di,&dj,&flg));
71228b400f6SJacob Faibussowitsch   PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
7139566063dSJacob Faibussowitsch   PetscCall(MatGetRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&oi,&oj,&flg));
71428b400f6SJacob Faibussowitsch   PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
715c9225affSStefano Zampini   nnz = di[dr] + oi[dr];
716c9225affSStefano Zampini   /* store original pointers to be restored later */
717c9225affSStefano Zampini   odi = di; odj = dj; ooi = oi; ooj = oj;
7186989cf23SStefano Zampini 
7196989cf23SStefano Zampini   /* generate l2g maps for rows and cols */
7209566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(comm,dr/bs,str/bs,1,&is));
721c9225affSStefano Zampini   if (bs > 1) {
722c9225affSStefano Zampini     IS is2;
723c9225affSStefano Zampini 
7249566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(is,&i));
7259566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is,(const PetscInt**)&aux));
7269566063dSJacob Faibussowitsch     PetscCall(ISCreateBlock(comm,bs,i,aux,PETSC_COPY_VALUES,&is2));
7279566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(is,(const PetscInt**)&aux));
7289566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
729c9225affSStefano Zampini     is   = is2;
730c9225affSStefano Zampini   }
7319566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(is,&rl2g));
7329566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
733e363d98aSStefano Zampini   if (dr) {
7349566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1((dc+oc)/bs,&aux));
735c9225affSStefano Zampini     for (i=0; i<dc/bs; i++) aux[i]       = i+stc/bs;
736c9225affSStefano Zampini     for (i=0; i<oc/bs; i++) aux[i+dc/bs] = garray[i];
7379566063dSJacob Faibussowitsch     PetscCall(ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is));
738e363d98aSStefano Zampini     lc   = dc+oc;
739e363d98aSStefano Zampini   } else {
7409566063dSJacob Faibussowitsch     PetscCall(ISCreateBlock(comm,bs,0,NULL,PETSC_OWN_POINTER,&is));
741e363d98aSStefano Zampini     lc   = 0;
742e363d98aSStefano Zampini   }
7439566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(is,&cl2g));
7449566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
7456989cf23SStefano Zampini 
7466989cf23SStefano Zampini   /* create MATIS object */
7479566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm,&B));
7489566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(B,dr,dc,PETSC_DECIDE,PETSC_DECIDE));
7499566063dSJacob Faibussowitsch   PetscCall(MatSetType(B,MATIS));
7509566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(B,bs));
7519566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(B,rl2g,cl2g));
7529566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
7539566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
7546989cf23SStefano Zampini 
7556989cf23SStefano Zampini   /* merge local matrices */
7569566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nnz+dr+1,&aux));
7579566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nnz,&data));
7586989cf23SStefano Zampini   ii   = aux;
7596989cf23SStefano Zampini   jj   = aux+dr+1;
7606989cf23SStefano Zampini   aa   = data;
7616989cf23SStefano Zampini   *ii  = *(di++) + *(oi++);
7626989cf23SStefano Zampini   for (jd=0,jo=0,cum=0;*ii<nnz;cum++)
7636989cf23SStefano Zampini   {
7646989cf23SStefano Zampini      for (;jd<*di;jd++) { *jj++ = *dj++;      *aa++ = *dd++; }
7656989cf23SStefano Zampini      for (;jo<*oi;jo++) { *jj++ = *oj++ + dc; *aa++ = *od++; }
7666989cf23SStefano Zampini      *(++ii) = *(di++) + *(oi++);
7676989cf23SStefano Zampini   }
7686989cf23SStefano Zampini   for (;cum<dr;cum++) *(++ii) = nnz;
769c9225affSStefano Zampini 
7709566063dSJacob Faibussowitsch   PetscCall(MatRestoreRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&odi,&odj,&flg));
77128b400f6SJacob Faibussowitsch   PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
7729566063dSJacob Faibussowitsch   PetscCall(MatRestoreRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&ooi,&ooj,&flg));
77328b400f6SJacob Faibussowitsch   PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
7749566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(Ad,&dd));
7759566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(Ao,&od));
776c9225affSStefano Zampini 
7776989cf23SStefano Zampini   ii   = aux;
7786989cf23SStefano Zampini   jj   = aux+dr+1;
7796989cf23SStefano Zampini   aa   = data;
7809566063dSJacob Faibussowitsch   PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,lc,ii,jj,aa,&lA));
7816989cf23SStefano Zampini 
7826989cf23SStefano Zampini   /* create containers to destroy the data */
7836989cf23SStefano Zampini   ptrs[0] = aux;
7846989cf23SStefano Zampini   ptrs[1] = data;
7856989cf23SStefano Zampini   for (i=0; i<2; i++) {
7866989cf23SStefano Zampini     PetscContainer c;
7876989cf23SStefano Zampini 
7889566063dSJacob Faibussowitsch     PetscCall(PetscContainerCreate(PETSC_COMM_SELF,&c));
7899566063dSJacob Faibussowitsch     PetscCall(PetscContainerSetPointer(c,ptrs[i]));
7909566063dSJacob Faibussowitsch     PetscCall(PetscContainerSetUserDestroy(c,PetscContainerUserDestroyDefault));
7919566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)lA,names[i],(PetscObject)c));
7929566063dSJacob Faibussowitsch     PetscCall(PetscContainerDestroy(&c));
7936989cf23SStefano Zampini   }
794c9225affSStefano Zampini   if (ismpibaij) { /* destroy converted local matrices */
7959566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Ad));
7969566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Ao));
797c9225affSStefano Zampini   }
7986989cf23SStefano Zampini 
7996989cf23SStefano Zampini   /* finalize matrix */
8009566063dSJacob Faibussowitsch   PetscCall(MatISSetLocalMat(B,lA));
8019566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&lA));
8029566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
8039566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
804c9225affSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
8059566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A,&B));
806c9225affSStefano Zampini   } else *newmat = B;
8076989cf23SStefano Zampini   PetscFunctionReturn(0);
8086989cf23SStefano Zampini }
8096989cf23SStefano Zampini 
8105e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
8115e3038f0Sstefano_zampini {
8125e3038f0Sstefano_zampini   Mat                    **nest,*snest,**rnest,lA,B;
8135e3038f0Sstefano_zampini   IS                     *iscol,*isrow,*islrow,*islcol;
8145e3038f0Sstefano_zampini   ISLocalToGlobalMapping rl2g,cl2g;
8155e3038f0Sstefano_zampini   MPI_Comm               comm;
8165b003df0Sstefano_zampini   PetscInt               *lr,*lc,*l2gidxs;
8175b003df0Sstefano_zampini   PetscInt               i,j,nr,nc,rbs,cbs;
8189e7b2b25Sstefano_zampini   PetscBool              convert,lreuse,*istrans;
8195e3038f0Sstefano_zampini 
820ab4d48faSStefano Zampini   PetscFunctionBegin;
8219566063dSJacob Faibussowitsch   PetscCall(MatNestGetSubMats(A,&nr,&nc,&nest));
8225e3038f0Sstefano_zampini   lreuse = PETSC_FALSE;
8235e3038f0Sstefano_zampini   rnest  = NULL;
8245e3038f0Sstefano_zampini   if (reuse == MAT_REUSE_MATRIX) {
8255e3038f0Sstefano_zampini     PetscBool ismatis,isnest;
8265e3038f0Sstefano_zampini 
8279566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis));
82828b400f6SJacob Faibussowitsch     PetscCheck(ismatis,PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type_name);
8299566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(*newmat,&lA));
8309566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest));
8315e3038f0Sstefano_zampini     if (isnest) {
8329566063dSJacob Faibussowitsch       PetscCall(MatNestGetSubMats(lA,&i,&j,&rnest));
8335e3038f0Sstefano_zampini       lreuse = (PetscBool)(i == nr && j == nc);
8345e3038f0Sstefano_zampini       if (!lreuse) rnest = NULL;
8355e3038f0Sstefano_zampini     }
8365e3038f0Sstefano_zampini   }
8379566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)A,&comm));
8389566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(nr,&lr,nc,&lc));
8399566063dSJacob Faibussowitsch   PetscCall(PetscCalloc6(nr,&isrow,nc,&iscol,nr,&islrow,nc,&islcol,nr*nc,&snest,nr*nc,&istrans));
8409566063dSJacob Faibussowitsch   PetscCall(MatNestGetISs(A,isrow,iscol));
8415e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
8425e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
8435e3038f0Sstefano_zampini       PetscBool ismatis;
8449e7b2b25Sstefano_zampini       PetscInt  l1,l2,lb1,lb2,ij=i*nc+j;
8455e3038f0Sstefano_zampini 
8465e3038f0Sstefano_zampini       /* Null matrix pointers are allowed in MATNEST */
8475e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
8485e3038f0Sstefano_zampini 
8495e3038f0Sstefano_zampini       /* Nested matrices should be of type MATIS */
8509566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij]));
8519e7b2b25Sstefano_zampini       if (istrans[ij]) {
8529e7b2b25Sstefano_zampini         Mat T,lT;
8539566063dSJacob Faibussowitsch         PetscCall(MatTransposeGetMat(nest[i][j],&T));
8549566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis));
85528b400f6SJacob 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);
8569566063dSJacob Faibussowitsch         PetscCall(MatISGetLocalMat(T,&lT));
8579566063dSJacob Faibussowitsch         PetscCall(MatCreateTranspose(lT,&snest[ij]));
8589e7b2b25Sstefano_zampini       } else {
8599566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis));
86028b400f6SJacob 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);
8619566063dSJacob Faibussowitsch         PetscCall(MatISGetLocalMat(nest[i][j],&snest[ij]));
8629e7b2b25Sstefano_zampini       }
8635e3038f0Sstefano_zampini 
8645e3038f0Sstefano_zampini       /* Check compatibility of local sizes */
8659566063dSJacob Faibussowitsch       PetscCall(MatGetSize(snest[ij],&l1,&l2));
8669566063dSJacob Faibussowitsch       PetscCall(MatGetBlockSizes(snest[ij],&lb1,&lb2));
8675e3038f0Sstefano_zampini       if (!l1 || !l2) continue;
868*aed4548fSBarry Smith       PetscCheck(!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);
869*aed4548fSBarry Smith       PetscCheck(!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);
8705e3038f0Sstefano_zampini       lr[i] = l1;
8715e3038f0Sstefano_zampini       lc[j] = l2;
8725e3038f0Sstefano_zampini 
8735e3038f0Sstefano_zampini       /* check compatibilty for local matrix reusage */
8745e3038f0Sstefano_zampini       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
8755e3038f0Sstefano_zampini     }
8765e3038f0Sstefano_zampini   }
8775e3038f0Sstefano_zampini 
87876bd3646SJed Brown   if (PetscDefined (USE_DEBUG)) {
8795e3038f0Sstefano_zampini     /* Check compatibility of l2g maps for rows */
8805e3038f0Sstefano_zampini     for (i=0;i<nr;i++) {
8815e3038f0Sstefano_zampini       rl2g = NULL;
8825e3038f0Sstefano_zampini       for (j=0;j<nc;j++) {
8835e3038f0Sstefano_zampini         PetscInt n1,n2;
8845e3038f0Sstefano_zampini 
8855e3038f0Sstefano_zampini         if (!nest[i][j]) continue;
8869e7b2b25Sstefano_zampini         if (istrans[i*nc+j]) {
8879e7b2b25Sstefano_zampini           Mat T;
8889e7b2b25Sstefano_zampini 
8899566063dSJacob Faibussowitsch           PetscCall(MatTransposeGetMat(nest[i][j],&T));
8909566063dSJacob Faibussowitsch           PetscCall(MatISGetLocalToGlobalMapping(T,NULL,&cl2g));
8919e7b2b25Sstefano_zampini         } else {
8929566063dSJacob Faibussowitsch           PetscCall(MatISGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL));
8939e7b2b25Sstefano_zampini         }
8949566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingGetSize(cl2g,&n1));
8955e3038f0Sstefano_zampini         if (!n1) continue;
8965e3038f0Sstefano_zampini         if (!rl2g) {
8975e3038f0Sstefano_zampini           rl2g = cl2g;
8985e3038f0Sstefano_zampini         } else {
8995e3038f0Sstefano_zampini           const PetscInt *idxs1,*idxs2;
9005e3038f0Sstefano_zampini           PetscBool      same;
9015e3038f0Sstefano_zampini 
9029566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingGetSize(rl2g,&n2));
90308401ef6SPierre Jolivet           PetscCheck(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);
9049566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingGetIndices(cl2g,&idxs1));
9059566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingGetIndices(rl2g,&idxs2));
9069566063dSJacob Faibussowitsch           PetscCall(PetscArraycmp(idxs1,idxs2,n1,&same));
9079566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1));
9089566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2));
90928b400f6SJacob 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);
9105e3038f0Sstefano_zampini         }
9115e3038f0Sstefano_zampini       }
9125e3038f0Sstefano_zampini     }
9135e3038f0Sstefano_zampini     /* Check compatibility of l2g maps for columns */
9145e3038f0Sstefano_zampini     for (i=0;i<nc;i++) {
9155e3038f0Sstefano_zampini       rl2g = NULL;
9165e3038f0Sstefano_zampini       for (j=0;j<nr;j++) {
9175e3038f0Sstefano_zampini         PetscInt n1,n2;
9185e3038f0Sstefano_zampini 
9195e3038f0Sstefano_zampini         if (!nest[j][i]) continue;
9209e7b2b25Sstefano_zampini         if (istrans[j*nc+i]) {
9219e7b2b25Sstefano_zampini           Mat T;
9229e7b2b25Sstefano_zampini 
9239566063dSJacob Faibussowitsch           PetscCall(MatTransposeGetMat(nest[j][i],&T));
9249566063dSJacob Faibussowitsch           PetscCall(MatISGetLocalToGlobalMapping(T,&cl2g,NULL));
9259e7b2b25Sstefano_zampini         } else {
9269566063dSJacob Faibussowitsch           PetscCall(MatISGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g));
9279e7b2b25Sstefano_zampini         }
9289566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingGetSize(cl2g,&n1));
9295e3038f0Sstefano_zampini         if (!n1) continue;
9305e3038f0Sstefano_zampini         if (!rl2g) {
9315e3038f0Sstefano_zampini           rl2g = cl2g;
9325e3038f0Sstefano_zampini         } else {
9335e3038f0Sstefano_zampini           const PetscInt *idxs1,*idxs2;
9345e3038f0Sstefano_zampini           PetscBool      same;
9355e3038f0Sstefano_zampini 
9369566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingGetSize(rl2g,&n2));
93708401ef6SPierre Jolivet           PetscCheck(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);
9389566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingGetIndices(cl2g,&idxs1));
9399566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingGetIndices(rl2g,&idxs2));
9409566063dSJacob Faibussowitsch           PetscCall(PetscArraycmp(idxs1,idxs2,n1,&same));
9419566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1));
9429566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2));
94328b400f6SJacob 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);
9445e3038f0Sstefano_zampini         }
9455e3038f0Sstefano_zampini       }
9465e3038f0Sstefano_zampini     }
94776bd3646SJed Brown   }
9485e3038f0Sstefano_zampini 
9495e3038f0Sstefano_zampini   B = NULL;
9505e3038f0Sstefano_zampini   if (reuse != MAT_REUSE_MATRIX) {
9515b003df0Sstefano_zampini     PetscInt stl;
9525b003df0Sstefano_zampini 
9535e3038f0Sstefano_zampini     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
9545e3038f0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) stl += lr[i];
9559566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(stl,&l2gidxs));
9565b003df0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) {
9575e3038f0Sstefano_zampini       Mat            usedmat;
9585e3038f0Sstefano_zampini       Mat_IS         *matis;
9595e3038f0Sstefano_zampini       const PetscInt *idxs;
9605e3038f0Sstefano_zampini 
9615e3038f0Sstefano_zampini       /* local IS for local NEST */
9629566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]));
9635e3038f0Sstefano_zampini 
9645e3038f0Sstefano_zampini       /* l2gmap */
9655e3038f0Sstefano_zampini       j = 0;
9665e3038f0Sstefano_zampini       usedmat = nest[i][j];
9679e7b2b25Sstefano_zampini       while (!usedmat && j < nc-1) usedmat = nest[i][++j];
96828b400f6SJacob Faibussowitsch       PetscCheck(usedmat,comm,PETSC_ERR_SUP,"Cannot find valid row mat");
9699e7b2b25Sstefano_zampini 
9709e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
9719e7b2b25Sstefano_zampini         Mat T;
9729566063dSJacob Faibussowitsch         PetscCall(MatTransposeGetMat(usedmat,&T));
9739e7b2b25Sstefano_zampini         usedmat = T;
9749e7b2b25Sstefano_zampini       }
9755e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
9769566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(isrow[i],&idxs));
9779e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
9789566063dSJacob Faibussowitsch         PetscCall(PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE));
9799566063dSJacob Faibussowitsch         PetscCall(PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE));
9809e7b2b25Sstefano_zampini       } else {
9819566063dSJacob Faibussowitsch         PetscCall(PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE));
9829566063dSJacob Faibussowitsch         PetscCall(PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE));
9839e7b2b25Sstefano_zampini       }
9849566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(isrow[i],&idxs));
9855e3038f0Sstefano_zampini       stl += lr[i];
9865e3038f0Sstefano_zampini     }
9879566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g));
9885e3038f0Sstefano_zampini 
9895e3038f0Sstefano_zampini     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
9905e3038f0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) stl += lc[i];
9919566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(stl,&l2gidxs));
9925b003df0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) {
9935e3038f0Sstefano_zampini       Mat            usedmat;
9945e3038f0Sstefano_zampini       Mat_IS         *matis;
9955e3038f0Sstefano_zampini       const PetscInt *idxs;
9965e3038f0Sstefano_zampini 
9975e3038f0Sstefano_zampini       /* local IS for local NEST */
9989566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]));
9995e3038f0Sstefano_zampini 
10005e3038f0Sstefano_zampini       /* l2gmap */
10015e3038f0Sstefano_zampini       j = 0;
10025e3038f0Sstefano_zampini       usedmat = nest[j][i];
10039e7b2b25Sstefano_zampini       while (!usedmat && j < nr-1) usedmat = nest[++j][i];
100428b400f6SJacob Faibussowitsch       PetscCheck(usedmat,comm,PETSC_ERR_SUP,"Cannot find valid column mat");
10059e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
10069e7b2b25Sstefano_zampini         Mat T;
10079566063dSJacob Faibussowitsch         PetscCall(MatTransposeGetMat(usedmat,&T));
10089e7b2b25Sstefano_zampini         usedmat = T;
10099e7b2b25Sstefano_zampini       }
10105e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
10119566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(iscol[i],&idxs));
10129e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
10139566063dSJacob Faibussowitsch         PetscCall(PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE));
10149566063dSJacob Faibussowitsch         PetscCall(PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE));
10159e7b2b25Sstefano_zampini       } else {
10169566063dSJacob Faibussowitsch         PetscCall(PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE));
10179566063dSJacob Faibussowitsch         PetscCall(PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE));
10189e7b2b25Sstefano_zampini       }
10199566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(iscol[i],&idxs));
10205e3038f0Sstefano_zampini       stl += lc[i];
10215e3038f0Sstefano_zampini     }
10229566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g));
10235e3038f0Sstefano_zampini 
10245e3038f0Sstefano_zampini     /* Create MATIS */
10259566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm,&B));
10269566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N));
10279566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSizes(A,&rbs,&cbs));
10289566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizes(B,rbs,cbs));
10299566063dSJacob Faibussowitsch     PetscCall(MatSetType(B,MATIS));
10309566063dSJacob Faibussowitsch     PetscCall(MatISSetLocalMatType(B,MATNEST));
10318546b261SStefano Zampini     { /* hack : avoid setup of scatters */
10328546b261SStefano Zampini       Mat_IS *matis = (Mat_IS*)(B->data);
10338546b261SStefano Zampini       matis->islocalref = PETSC_TRUE;
10348546b261SStefano Zampini     }
10359566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(B,rl2g,cl2g));
10369566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
10379566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
10389566063dSJacob Faibussowitsch     PetscCall(MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA));
10399566063dSJacob Faibussowitsch     PetscCall(MatNestSetVecType(lA,VECNEST));
10409e7b2b25Sstefano_zampini     for (i=0;i<nr*nc;i++) {
10419e7b2b25Sstefano_zampini       if (istrans[i]) {
10429566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&snest[i]));
10439e7b2b25Sstefano_zampini       }
10449e7b2b25Sstefano_zampini     }
10459566063dSJacob Faibussowitsch     PetscCall(MatISSetLocalMat(B,lA));
10469566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&lA));
10478546b261SStefano Zampini     { /* hack : setup of scatters done here */
10488546b261SStefano Zampini       Mat_IS *matis = (Mat_IS*)(B->data);
10498546b261SStefano Zampini 
10508546b261SStefano Zampini       matis->islocalref = PETSC_FALSE;
10519566063dSJacob Faibussowitsch       PetscCall(MatISSetUpScatters_Private(B));
10528546b261SStefano Zampini     }
10539566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
10549566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
10555e3038f0Sstefano_zampini     if (reuse == MAT_INPLACE_MATRIX) {
10569566063dSJacob Faibussowitsch       PetscCall(MatHeaderReplace(A,&B));
10575e3038f0Sstefano_zampini     } else {
10585e3038f0Sstefano_zampini       *newmat = B;
10595e3038f0Sstefano_zampini     }
10605e3038f0Sstefano_zampini   } else {
10615e3038f0Sstefano_zampini     if (lreuse) {
10629566063dSJacob Faibussowitsch       PetscCall(MatISGetLocalMat(*newmat,&lA));
10635e3038f0Sstefano_zampini       for (i=0;i<nr;i++) {
10645e3038f0Sstefano_zampini         for (j=0;j<nc;j++) {
10655e3038f0Sstefano_zampini           if (snest[i*nc+j]) {
10669566063dSJacob Faibussowitsch             PetscCall(MatNestSetSubMat(lA,i,j,snest[i*nc+j]));
10679e7b2b25Sstefano_zampini             if (istrans[i*nc+j]) {
10689566063dSJacob Faibussowitsch               PetscCall(MatDestroy(&snest[i*nc+j]));
10699e7b2b25Sstefano_zampini             }
10705e3038f0Sstefano_zampini           }
10715e3038f0Sstefano_zampini         }
10725e3038f0Sstefano_zampini       }
10735e3038f0Sstefano_zampini     } else {
10745b003df0Sstefano_zampini       PetscInt stl;
10755b003df0Sstefano_zampini       for (i=0,stl=0;i<nr;i++) {
10769566063dSJacob Faibussowitsch         PetscCall(ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]));
10775b003df0Sstefano_zampini         stl  += lr[i];
10785e3038f0Sstefano_zampini       }
10795b003df0Sstefano_zampini       for (i=0,stl=0;i<nc;i++) {
10809566063dSJacob Faibussowitsch         PetscCall(ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]));
10815b003df0Sstefano_zampini         stl  += lc[i];
10825e3038f0Sstefano_zampini       }
10839566063dSJacob Faibussowitsch       PetscCall(MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA));
1084ab4d48faSStefano Zampini       for (i=0;i<nr*nc;i++) {
10859e7b2b25Sstefano_zampini         if (istrans[i]) {
10869566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&snest[i]));
10879e7b2b25Sstefano_zampini         }
1088ab4d48faSStefano Zampini       }
10899566063dSJacob Faibussowitsch       PetscCall(MatISSetLocalMat(*newmat,lA));
10909566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&lA));
10915e3038f0Sstefano_zampini     }
10929566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY));
10939566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY));
10945e3038f0Sstefano_zampini   }
10955e3038f0Sstefano_zampini 
10965b003df0Sstefano_zampini   /* Create local matrix in MATNEST format */
10975b003df0Sstefano_zampini   convert = PETSC_FALSE;
10989566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL));
10995b003df0Sstefano_zampini   if (convert) {
11005b003df0Sstefano_zampini     Mat              M;
11015b003df0Sstefano_zampini     MatISLocalFields lf;
11025b003df0Sstefano_zampini     PetscContainer   c;
11035b003df0Sstefano_zampini 
11049566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(*newmat,&lA));
11059566063dSJacob Faibussowitsch     PetscCall(MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M));
11069566063dSJacob Faibussowitsch     PetscCall(MatISSetLocalMat(*newmat,M));
11079566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&M));
11085b003df0Sstefano_zampini 
11095b003df0Sstefano_zampini     /* attach local fields to the matrix */
11109566063dSJacob Faibussowitsch     PetscCall(PetscNew(&lf));
11119566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nr,&lf->rf,nc,&lf->cf));
11125b003df0Sstefano_zampini     for (i=0;i<nr;i++) {
11135b003df0Sstefano_zampini       PetscInt n,st;
11145b003df0Sstefano_zampini 
11159566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(islrow[i],&n));
11169566063dSJacob Faibussowitsch       PetscCall(ISStrideGetInfo(islrow[i],&st,NULL));
11179566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(comm,n,st,1,&lf->rf[i]));
11185b003df0Sstefano_zampini     }
11195b003df0Sstefano_zampini     for (i=0;i<nc;i++) {
11205b003df0Sstefano_zampini       PetscInt n,st;
11215b003df0Sstefano_zampini 
11229566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(islcol[i],&n));
11239566063dSJacob Faibussowitsch       PetscCall(ISStrideGetInfo(islcol[i],&st,NULL));
11249566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(comm,n,st,1,&lf->cf[i]));
11255b003df0Sstefano_zampini     }
11265b003df0Sstefano_zampini     lf->nr = nr;
11275b003df0Sstefano_zampini     lf->nc = nc;
11289566063dSJacob Faibussowitsch     PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c));
11299566063dSJacob Faibussowitsch     PetscCall(PetscContainerSetPointer(c,lf));
11309566063dSJacob Faibussowitsch     PetscCall(PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private));
11319566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c));
11329566063dSJacob Faibussowitsch     PetscCall(PetscContainerDestroy(&c));
11335b003df0Sstefano_zampini   }
11345b003df0Sstefano_zampini 
11355e3038f0Sstefano_zampini   /* Free workspace */
11365e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
11379566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&islrow[i]));
11385e3038f0Sstefano_zampini   }
11395e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
11409566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&islcol[i]));
11415e3038f0Sstefano_zampini   }
11429566063dSJacob Faibussowitsch   PetscCall(PetscFree6(isrow,iscol,islrow,islcol,snest,istrans));
11439566063dSJacob Faibussowitsch   PetscCall(PetscFree2(lr,lc));
11445e3038f0Sstefano_zampini   PetscFunctionReturn(0);
11455e3038f0Sstefano_zampini }
11465e3038f0Sstefano_zampini 
1147ad219c80Sstefano_zampini static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r)
1148ad219c80Sstefano_zampini {
1149ad219c80Sstefano_zampini   Mat_IS            *matis = (Mat_IS*)A->data;
1150ad219c80Sstefano_zampini   Vec               ll,rr;
1151ad219c80Sstefano_zampini   const PetscScalar *Y,*X;
1152ad219c80Sstefano_zampini   PetscScalar       *x,*y;
1153ad219c80Sstefano_zampini 
1154ad219c80Sstefano_zampini   PetscFunctionBegin;
1155ad219c80Sstefano_zampini   if (l) {
1156ad219c80Sstefano_zampini     ll   = matis->y;
11579566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(l,&Y));
11589566063dSJacob Faibussowitsch     PetscCall(VecGetArray(ll,&y));
11599566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(matis->sf,MPIU_SCALAR,Y,y,MPI_REPLACE));
1160ad219c80Sstefano_zampini   } else {
1161ad219c80Sstefano_zampini     ll = NULL;
1162ad219c80Sstefano_zampini   }
1163ad219c80Sstefano_zampini   if (r) {
1164ad219c80Sstefano_zampini     rr   = matis->x;
11659566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(r,&X));
11669566063dSJacob Faibussowitsch     PetscCall(VecGetArray(rr,&x));
11679566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(matis->csf,MPIU_SCALAR,X,x,MPI_REPLACE));
1168ad219c80Sstefano_zampini   } else {
1169ad219c80Sstefano_zampini     rr = NULL;
1170ad219c80Sstefano_zampini   }
1171ad219c80Sstefano_zampini   if (ll) {
11729566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(matis->sf,MPIU_SCALAR,Y,y,MPI_REPLACE));
11739566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(l,&Y));
11749566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(ll,&y));
1175ad219c80Sstefano_zampini   }
1176ad219c80Sstefano_zampini   if (rr) {
11779566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(matis->csf,MPIU_SCALAR,X,x,MPI_REPLACE));
11789566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(r,&X));
11799566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(rr,&x));
1180ad219c80Sstefano_zampini   }
11819566063dSJacob Faibussowitsch   PetscCall(MatDiagonalScale(matis->A,ll,rr));
1182ad219c80Sstefano_zampini   PetscFunctionReturn(0);
1183ad219c80Sstefano_zampini }
1184ad219c80Sstefano_zampini 
11857fa8f2d3SStefano Zampini static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo)
11867fa8f2d3SStefano Zampini {
11877fa8f2d3SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
11887fa8f2d3SStefano Zampini   MatInfo        info;
11893966268fSBarry Smith   PetscLogDouble isend[6],irecv[6];
11907fa8f2d3SStefano Zampini   PetscInt       bs;
11917fa8f2d3SStefano Zampini 
11927fa8f2d3SStefano Zampini   PetscFunctionBegin;
11939566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(A,&bs));
1194a2ccb5f9Sstefano_zampini   if (matis->A->ops->getinfo) {
11959566063dSJacob Faibussowitsch     PetscCall(MatGetInfo(matis->A,MAT_LOCAL,&info));
11967fa8f2d3SStefano Zampini     isend[0] = info.nz_used;
11977fa8f2d3SStefano Zampini     isend[1] = info.nz_allocated;
11987fa8f2d3SStefano Zampini     isend[2] = info.nz_unneeded;
11997fa8f2d3SStefano Zampini     isend[3] = info.memory;
12007fa8f2d3SStefano Zampini     isend[4] = info.mallocs;
1201a2ccb5f9Sstefano_zampini   } else {
1202a2ccb5f9Sstefano_zampini     isend[0] = 0.;
1203a2ccb5f9Sstefano_zampini     isend[1] = 0.;
1204a2ccb5f9Sstefano_zampini     isend[2] = 0.;
1205a2ccb5f9Sstefano_zampini     isend[3] = 0.;
1206a2ccb5f9Sstefano_zampini     isend[4] = 0.;
1207a2ccb5f9Sstefano_zampini   }
1208314ce898Sstefano_zampini   isend[5] = matis->A->num_ass;
12097fa8f2d3SStefano Zampini   if (flag == MAT_LOCAL) {
12107fa8f2d3SStefano Zampini     ginfo->nz_used      = isend[0];
12117fa8f2d3SStefano Zampini     ginfo->nz_allocated = isend[1];
12127fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = isend[2];
12137fa8f2d3SStefano Zampini     ginfo->memory       = isend[3];
12147fa8f2d3SStefano Zampini     ginfo->mallocs      = isend[4];
1215314ce898Sstefano_zampini     ginfo->assemblies   = isend[5];
12167fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_MAX) {
12171c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(isend,irecv,6,MPIU_PETSCLOGDOUBLE,MPI_MAX,PetscObjectComm((PetscObject)A)));
12187fa8f2d3SStefano Zampini 
12197fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
12207fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
12217fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
12227fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
12237fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
1224314ce898Sstefano_zampini     ginfo->assemblies   = irecv[5];
12257fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_SUM) {
12261c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(isend,irecv,5,MPIU_PETSCLOGDOUBLE,MPI_SUM,PetscObjectComm((PetscObject)A)));
12277fa8f2d3SStefano Zampini 
12287fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
12297fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
12307fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
12317fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
12327fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
12337fa8f2d3SStefano Zampini     ginfo->assemblies   = A->num_ass;
12347fa8f2d3SStefano Zampini   }
12357fa8f2d3SStefano Zampini   ginfo->block_size        = bs;
12367fa8f2d3SStefano Zampini   ginfo->fill_ratio_given  = 0;
12377fa8f2d3SStefano Zampini   ginfo->fill_ratio_needed = 0;
12387fa8f2d3SStefano Zampini   ginfo->factor_mallocs    = 0;
12395e3038f0Sstefano_zampini   PetscFunctionReturn(0);
12405e3038f0Sstefano_zampini }
12415e3038f0Sstefano_zampini 
12428b9382cfSStefano Zampini static PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
1243d7f69cd0SStefano Zampini {
1244d7f69cd0SStefano Zampini   Mat                    C,lC,lA;
1245d7f69cd0SStefano Zampini 
1246d7f69cd0SStefano Zampini   PetscFunctionBegin;
1247cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) {
1248cf37664fSBarry Smith     ISLocalToGlobalMapping rl2g,cl2g;
12499566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A),&C));
12509566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N));
12519566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs)));
12529566063dSJacob Faibussowitsch     PetscCall(MatSetType(C,MATIS));
12539566063dSJacob Faibussowitsch     PetscCall(MatGetLocalToGlobalMapping(A,&rl2g,&cl2g));
12549566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(C,cl2g,rl2g));
1255e432b41dSStefano Zampini   } else C = *B;
1256d7f69cd0SStefano Zampini 
1257d7f69cd0SStefano Zampini   /* perform local transposition */
12589566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(A,&lA));
12599566063dSJacob Faibussowitsch   PetscCall(MatTranspose(lA,MAT_INITIAL_MATRIX,&lC));
12609566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(lC,lA->cmap->mapping,lA->rmap->mapping));
12619566063dSJacob Faibussowitsch   PetscCall(MatISSetLocalMat(C,lC));
12629566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&lC));
1263d7f69cd0SStefano Zampini 
1264cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) {
1265d7f69cd0SStefano Zampini     *B = C;
1266d7f69cd0SStefano Zampini   } else {
12679566063dSJacob Faibussowitsch     PetscCall(MatHeaderMerge(A,&C));
1268d7f69cd0SStefano Zampini   }
12699566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY));
12709566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY));
1271d7f69cd0SStefano Zampini   PetscFunctionReturn(0);
1272d7f69cd0SStefano Zampini }
1273d7f69cd0SStefano Zampini 
12748b9382cfSStefano Zampini static PetscErrorCode MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
12753fd1c9e7SStefano Zampini {
12763fd1c9e7SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
12773fd1c9e7SStefano Zampini 
12783fd1c9e7SStefano Zampini   PetscFunctionBegin;
12794b89b9cdSStefano Zampini   if (D) { /* MatShift_IS pass D = NULL */
12809566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD));
12819566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD));
12823fd1c9e7SStefano Zampini   }
12839566063dSJacob Faibussowitsch   PetscCall(VecPointwiseDivide(is->y,is->y,is->counter));
12849566063dSJacob Faibussowitsch   PetscCall(MatDiagonalSet(is->A,is->y,insmode));
12853fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
12863fd1c9e7SStefano Zampini }
12873fd1c9e7SStefano Zampini 
12888b9382cfSStefano Zampini static PetscErrorCode MatShift_IS(Mat A,PetscScalar a)
12893fd1c9e7SStefano Zampini {
12904b89b9cdSStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
12913fd1c9e7SStefano Zampini 
12923fd1c9e7SStefano Zampini   PetscFunctionBegin;
12939566063dSJacob Faibussowitsch   PetscCall(VecSet(is->y,a));
12949566063dSJacob Faibussowitsch   PetscCall(MatDiagonalSet_IS(A,NULL,ADD_VALUES));
12953fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
12963fd1c9e7SStefano Zampini }
12973fd1c9e7SStefano Zampini 
1298f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1299f26d0771SStefano Zampini {
1300f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
1301f26d0771SStefano Zampini 
1302f26d0771SStefano Zampini   PetscFunctionBegin;
1303*aed4548fSBarry Smith   PetscCheck(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);
13049566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l));
13059566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l));
13069566063dSJacob Faibussowitsch   PetscCall(MatSetValuesLocal_IS(A,m,rows_l,n,cols_l,values,addv));
1307f26d0771SStefano Zampini   PetscFunctionReturn(0);
1308f26d0771SStefano Zampini }
1309f26d0771SStefano Zampini 
1310f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1311f26d0771SStefano Zampini {
1312f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
1313f26d0771SStefano Zampini 
1314f26d0771SStefano Zampini   PetscFunctionBegin;
1315*aed4548fSBarry Smith   PetscCheck(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);
13169566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l));
13179566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l));
13189566063dSJacob Faibussowitsch   PetscCall(MatSetValuesBlockedLocal_IS(A,m,rows_l,n,cols_l,values,addv));
1319f26d0771SStefano Zampini   PetscFunctionReturn(0);
1320f26d0771SStefano Zampini }
1321f26d0771SStefano Zampini 
13227dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
1323a8116848SStefano Zampini {
1324a8116848SStefano Zampini   Mat               locmat,newlocmat;
1325a8116848SStefano Zampini   Mat_IS            *newmatis;
1326a8116848SStefano Zampini   const PetscInt    *idxs;
1327a8116848SStefano Zampini   PetscInt          i,m,n;
1328a8116848SStefano Zampini 
1329a8116848SStefano Zampini   PetscFunctionBegin;
1330a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
1331a8116848SStefano Zampini     PetscBool ismatis;
1332a8116848SStefano Zampini 
13339566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis));
133428b400f6SJacob Faibussowitsch     PetscCheck(ismatis,PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
1335a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
133628b400f6SJacob Faibussowitsch     PetscCheck(newmatis->getsub_ris,PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
133728b400f6SJacob Faibussowitsch     PetscCheck(newmatis->getsub_cis,PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
1338a8116848SStefano Zampini   }
1339a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
134076bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
134176bd3646SJed Brown     Vec               rtest,ltest;
134276bd3646SJed Brown     const PetscScalar *array;
134376bd3646SJed Brown 
13449566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(mat,&ltest,&rtest));
13459566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(irow,&n));
13469566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(irow,&idxs));
1347a8116848SStefano Zampini     for (i=0;i<n;i++) {
13489566063dSJacob Faibussowitsch       PetscCall(VecSetValue(rtest,idxs[i],1.0,ADD_VALUES));
1349a8116848SStefano Zampini     }
13509566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(rtest));
13519566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(rtest));
13529566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(rtest,&n));
13539566063dSJacob Faibussowitsch     PetscCall(VecGetOwnershipRange(rtest,&m,NULL));
13549566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(rtest,&array));
1355*aed4548fSBarry Smith     for (i=0;i<n;i++) PetscCheck(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]));
13569566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(rtest,&array));
13579566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(irow,&idxs));
13589566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(icol,&n));
13599566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(icol,&idxs));
1360a8116848SStefano Zampini     for (i=0;i<n;i++) {
13619566063dSJacob Faibussowitsch       PetscCall(VecSetValue(ltest,idxs[i],1.0,ADD_VALUES));
1362a8116848SStefano Zampini     }
13639566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(ltest));
13649566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(ltest));
13659566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(ltest,&n));
13669566063dSJacob Faibussowitsch     PetscCall(VecGetOwnershipRange(ltest,&m,NULL));
13679566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(ltest,&array));
1368*aed4548fSBarry Smith     for (i=0;i<n;i++) PetscCheck(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]));
13699566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(ltest,&array));
13709566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(icol,&idxs));
13719566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&rtest));
13729566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&ltest));
137376bd3646SJed Brown   }
1374a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
1375a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
1376a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
1377a8116848SStefano Zampini     IS                     is;
1378a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
1379306cf5c7SStefano Zampini     PetscInt               ll,newloc,irbs,icbs,arbs,acbs,rbs,cbs;
138094342113SStefano Zampini     PetscBool              cong;
1381a8116848SStefano Zampini     MPI_Comm               comm;
1382a8116848SStefano Zampini 
13839566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)mat,&comm));
13849566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSizes(mat,&arbs,&acbs));
13859566063dSJacob Faibussowitsch     PetscCall(ISGetBlockSize(irow,&irbs));
13869566063dSJacob Faibussowitsch     PetscCall(ISGetBlockSize(icol,&icbs));
1387306cf5c7SStefano Zampini     rbs  = arbs == irbs ? irbs : 1;
1388306cf5c7SStefano Zampini     cbs  = acbs == icbs ? icbs : 1;
13899566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(irow,&m));
13909566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(icol,&n));
13919566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm,newmat));
13929566063dSJacob Faibussowitsch     PetscCall(MatSetType(*newmat,MATIS));
13939566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE));
13949566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizes(*newmat,rbs,cbs));
1395a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
13969566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(irow,&idxs));
13979566063dSJacob Faibussowitsch     PetscCall(PetscLayoutMapLocal(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs));
13989566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(irow,&idxs));
13999566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(matis->sf_rootdata,matis->sf->nroots));
1400a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
14019566063dSJacob Faibussowitsch     PetscCall(PetscFree(lidxs));
14029566063dSJacob Faibussowitsch     PetscCall(PetscFree(lgidxs));
14039566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
14049566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
14053d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
14069566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newloc,&newgidxs));
14079566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newloc,&lidxs));
14083d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++)
1409a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
1410a8116848SStefano Zampini         lidxs[newloc] = i;
1411a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
1412a8116848SStefano Zampini       }
14139566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is));
14149566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is,&rl2g));
14159566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingSetBlockSize(rl2g,rbs));
14169566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
1417a8116848SStefano Zampini     /* local is to extract local submatrix */
1418a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
14199566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris));
14209566063dSJacob Faibussowitsch     PetscCall(MatHasCongruentLayouts(mat,&cong));
142194342113SStefano Zampini     if (cong && irow == icol && matis->csf == matis->sf) {
14229566063dSJacob Faibussowitsch       PetscCall(MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g));
14239566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)newmatis->getsub_ris));
1424a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
1425a8116848SStefano Zampini     } else {
1426a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
1427a8116848SStefano Zampini 
1428a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
14299566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(icol,&idxs));
14309566063dSJacob Faibussowitsch       PetscCall(PetscLayoutMapLocal(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs));
14319566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(icol,&idxs));
14329566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(matis->csf_rootdata,matis->csf->nroots));
1433a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
14349566063dSJacob Faibussowitsch       PetscCall(PetscFree(lidxs));
14359566063dSJacob Faibussowitsch       PetscCall(PetscFree(lgidxs));
14369566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata,MPI_REPLACE));
14379566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata,MPI_REPLACE));
14383d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
14399566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(newloc,&newgidxs));
14409566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(newloc,&lidxs));
14413d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++)
1442a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
1443a8116848SStefano Zampini           lidxs[newloc] = i;
1444a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
1445a8116848SStefano Zampini         }
14469566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is));
14479566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreateIS(is,&cl2g));
14489566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingSetBlockSize(cl2g,cbs));
14499566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is));
1450a8116848SStefano Zampini       /* local is to extract local submatrix */
14519566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis));
14529566063dSJacob Faibussowitsch       PetscCall(MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g));
14539566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
1454a8116848SStefano Zampini     }
14559566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
1456a8116848SStefano Zampini   } else {
14579566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(*newmat,&newlocmat));
1458a8116848SStefano Zampini   }
14599566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(mat,&locmat));
1460a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
14619566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat));
1462a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
14639566063dSJacob Faibussowitsch     PetscCall(MatISSetLocalMat(*newmat,newlocmat));
14649566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&newlocmat));
1465a8116848SStefano Zampini   }
14669566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY));
14679566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY));
1468a8116848SStefano Zampini   PetscFunctionReturn(0);
1469a8116848SStefano Zampini }
1470a8116848SStefano Zampini 
1471a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
14722b404112SStefano Zampini {
14732b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
14742b404112SStefano Zampini   PetscBool      ismatis;
14752b404112SStefano Zampini 
14762b404112SStefano Zampini   PetscFunctionBegin;
14779566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis));
147828b400f6SJacob Faibussowitsch   PetscCheck(ismatis,PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
14792b404112SStefano Zampini   b = (Mat_IS*)B->data;
14809566063dSJacob Faibussowitsch   PetscCall(MatCopy(a->A,b->A,str));
14819566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)B));
14822b404112SStefano Zampini   PetscFunctionReturn(0);
14832b404112SStefano Zampini }
14842b404112SStefano Zampini 
1485a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
14866bd84002SStefano Zampini {
1487527b2640SStefano Zampini   Vec               v;
1488527b2640SStefano Zampini   const PetscScalar *array;
1489527b2640SStefano Zampini   PetscInt          i,n;
14906bd84002SStefano Zampini 
14916bd84002SStefano Zampini   PetscFunctionBegin;
1492527b2640SStefano Zampini   *missing = PETSC_FALSE;
14939566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(A,NULL,&v));
14949566063dSJacob Faibussowitsch   PetscCall(MatGetDiagonal(A,v));
14959566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v,&n));
14969566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(v,&array));
1497527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
14989566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(v,&array));
14999566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&v));
1500527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
1501527b2640SStefano Zampini   if (d) {
1502527b2640SStefano Zampini     *d = -1;
1503527b2640SStefano Zampini     if (*missing) {
1504527b2640SStefano Zampini       PetscInt rstart;
15059566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(A,&rstart,NULL));
1506527b2640SStefano Zampini       *d = i+rstart;
1507527b2640SStefano Zampini     }
1508527b2640SStefano Zampini   }
15096bd84002SStefano Zampini   PetscFunctionReturn(0);
15106bd84002SStefano Zampini }
15116bd84002SStefano Zampini 
1512cf0a3239SStefano Zampini static PetscErrorCode MatISSetUpSF_IS(Mat B)
151328f4e0baSStefano Zampini {
151428f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
151528f4e0baSStefano Zampini   const PetscInt *gidxs;
15164f2d7cafSStefano Zampini   PetscInt       nleaves;
151728f4e0baSStefano Zampini 
151828f4e0baSStefano Zampini   PetscFunctionBegin;
15194f2d7cafSStefano Zampini   if (matis->sf) PetscFunctionReturn(0);
15209566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf));
15219566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(matis->rmapping,&gidxs));
15229566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(matis->rmapping,&nleaves));
15239566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs));
15249566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->rmapping,&gidxs));
15259566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata));
1526e432b41dSStefano Zampini   if (matis->rmapping != matis->cmapping) { /* setup SF for columns */
15279566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetSize(matis->cmapping,&nleaves));
15289566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf));
15299566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetIndices(matis->cmapping,&gidxs));
15309566063dSJacob Faibussowitsch     PetscCall(PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs));
15319566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->cmapping,&gidxs));
15329566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata));
1533a8116848SStefano Zampini   } else {
1534a8116848SStefano Zampini     matis->csf = matis->sf;
1535a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
1536a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
1537a8116848SStefano Zampini   }
153828f4e0baSStefano Zampini   PetscFunctionReturn(0);
153928f4e0baSStefano Zampini }
15402e1947a5SStefano Zampini 
1541eb82efa4SStefano Zampini /*@
154275d48cdbSStefano Zampini    MatISStoreL2L - Store local-to-local operators during the Galerkin process of MatPtAP.
154375d48cdbSStefano Zampini 
1544d083f849SBarry Smith    Collective
154575d48cdbSStefano Zampini 
154675d48cdbSStefano Zampini    Input Parameters:
154775d48cdbSStefano Zampini +  A - the matrix
154875d48cdbSStefano Zampini -  store - the boolean flag
154975d48cdbSStefano Zampini 
155075d48cdbSStefano Zampini    Level: advanced
155175d48cdbSStefano Zampini 
155275d48cdbSStefano Zampini    Notes:
155375d48cdbSStefano Zampini 
155475d48cdbSStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatPtAP()
155575d48cdbSStefano Zampini @*/
155675d48cdbSStefano Zampini PetscErrorCode MatISStoreL2L(Mat A, PetscBool store)
155775d48cdbSStefano Zampini {
155875d48cdbSStefano Zampini   PetscFunctionBegin;
155975d48cdbSStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
156075d48cdbSStefano Zampini   PetscValidType(A,1);
156175d48cdbSStefano Zampini   PetscValidLogicalCollectiveBool(A,store,2);
1562cac4c232SBarry Smith   PetscTryMethod(A,"MatISStoreL2L_C",(Mat,PetscBool),(A,store));
156375d48cdbSStefano Zampini   PetscFunctionReturn(0);
156475d48cdbSStefano Zampini }
156575d48cdbSStefano Zampini 
156675d48cdbSStefano Zampini static PetscErrorCode MatISStoreL2L_IS(Mat A, PetscBool store)
156775d48cdbSStefano Zampini {
156875d48cdbSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(A->data);
156975d48cdbSStefano Zampini 
157075d48cdbSStefano Zampini   PetscFunctionBegin;
157175d48cdbSStefano Zampini   matis->storel2l = store;
157275d48cdbSStefano Zampini   if (!store) {
15739566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",NULL));
157475d48cdbSStefano Zampini   }
157575d48cdbSStefano Zampini   PetscFunctionReturn(0);
157675d48cdbSStefano Zampini }
157775d48cdbSStefano Zampini 
157875d48cdbSStefano Zampini /*@
1579f03112d0SStefano Zampini    MatISFixLocalEmpty - Compress out zero local rows from the local matrices
1580f03112d0SStefano Zampini 
1581d083f849SBarry Smith    Collective
1582f03112d0SStefano Zampini 
1583f03112d0SStefano Zampini    Input Parameters:
1584f03112d0SStefano Zampini +  A - the matrix
1585f03112d0SStefano Zampini -  fix - the boolean flag
1586f03112d0SStefano Zampini 
1587f03112d0SStefano Zampini    Level: advanced
1588f03112d0SStefano Zampini 
1589f03112d0SStefano Zampini    Notes: When fix is true, new local matrices and l2g maps are generated during the final assembly process.
1590f03112d0SStefano Zampini 
1591f03112d0SStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatAssemblyEnd(), MAT_FINAL_ASSEMBLY
1592f03112d0SStefano Zampini @*/
1593f03112d0SStefano Zampini PetscErrorCode MatISFixLocalEmpty(Mat A, PetscBool fix)
1594f03112d0SStefano Zampini {
1595f03112d0SStefano Zampini   PetscFunctionBegin;
1596f03112d0SStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
1597f03112d0SStefano Zampini   PetscValidType(A,1);
1598f03112d0SStefano Zampini   PetscValidLogicalCollectiveBool(A,fix,2);
1599cac4c232SBarry Smith   PetscTryMethod(A,"MatISFixLocalEmpty_C",(Mat,PetscBool),(A,fix));
1600f03112d0SStefano Zampini   PetscFunctionReturn(0);
1601f03112d0SStefano Zampini }
1602f03112d0SStefano Zampini 
1603f03112d0SStefano Zampini static PetscErrorCode MatISFixLocalEmpty_IS(Mat A, PetscBool fix)
1604f03112d0SStefano Zampini {
1605f03112d0SStefano Zampini   Mat_IS *matis = (Mat_IS*)(A->data);
1606f03112d0SStefano Zampini 
1607f03112d0SStefano Zampini   PetscFunctionBegin;
1608f03112d0SStefano Zampini   matis->locempty = fix;
1609f03112d0SStefano Zampini   PetscFunctionReturn(0);
1610f03112d0SStefano Zampini }
1611f03112d0SStefano Zampini 
1612f03112d0SStefano Zampini /*@
1613a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
1614a88811baSStefano Zampini 
1615d083f849SBarry Smith    Collective
1616a88811baSStefano Zampini 
1617a88811baSStefano Zampini    Input Parameters:
1618a88811baSStefano Zampini +  B - the matrix
1619a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1620a88811baSStefano Zampini            (same value is used for all local rows)
1621a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
1622a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
1623a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
1624a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
1625a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
1626a88811baSStefano Zampini            the diagonal entry even if it is zero.
1627a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1628a88811baSStefano Zampini            submatrix (same value is used for all local rows).
1629a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
1630a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
1631a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
1632a88811baSStefano Zampini            structure. The size of this array is equal to the number
1633a88811baSStefano Zampini            of local rows, i.e 'm'.
1634a88811baSStefano Zampini 
1635a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
1636a88811baSStefano Zampini 
1637a88811baSStefano Zampini    Level: intermediate
1638a88811baSStefano Zampini 
163995452b02SPatrick Sanan    Notes:
164095452b02SPatrick Sanan     This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
1641a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
1642a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
1643a88811baSStefano Zampini 
16443c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
1645a88811baSStefano Zampini @*/
16462e1947a5SStefano Zampini PetscErrorCode MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
16472e1947a5SStefano Zampini {
16482e1947a5SStefano Zampini   PetscFunctionBegin;
16492e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
16502e1947a5SStefano Zampini   PetscValidType(B,1);
1651cac4c232SBarry Smith   PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));
16522e1947a5SStefano Zampini   PetscFunctionReturn(0);
16532e1947a5SStefano Zampini }
16542e1947a5SStefano Zampini 
1655844bd0d7SStefano Zampini /* this is used by DMDA */
1656844bd0d7SStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
16572e1947a5SStefano Zampini {
16582e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
165928f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
16602e1947a5SStefano Zampini 
16612e1947a5SStefano Zampini   PetscFunctionBegin;
16629566063dSJacob Faibussowitsch   PetscCall(MatSetUp(B));
16634f2d7cafSStefano Zampini   if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz;
16644f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
16654f2d7cafSStefano Zampini 
16664f2d7cafSStefano Zampini   if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz;
16674f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
16684f2d7cafSStefano Zampini 
16699566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
16709566063dSJacob Faibussowitsch   PetscCall(MatGetSize(matis->A,NULL,&nlocalcols));
16719566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(matis->A,&bs));
16729566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
16734f2d7cafSStefano Zampini 
16744f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
16759566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata));
16760f2f62c7SStefano Zampini #if defined(PETSC_HAVE_HYPRE)
16779566063dSJacob Faibussowitsch   PetscCall(MatHYPRESetPreallocation(matis->A,0,matis->sf_leafdata,0,NULL));
16780f2f62c7SStefano Zampini #endif
16794f2d7cafSStefano Zampini 
1680fc989267SStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) {
1681fc989267SStefano Zampini     PetscInt b;
1682fc989267SStefano Zampini 
1683fc989267SStefano Zampini     matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
1684fc989267SStefano Zampini     for (b=1;b<bs;b++) {
1685fc989267SStefano Zampini       matis->sf_leafdata[i] = PetscMax(matis->sf_leafdata[i],matis->sf_leafdata[i*bs+b]/bs);
1686fc989267SStefano Zampini     }
1687fc989267SStefano Zampini   }
16889566063dSJacob Faibussowitsch   PetscCall(MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata));
16894f2d7cafSStefano Zampini 
169000a59248SStefano Zampini   nlocalcols /= bs;
169100a59248SStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols - i);
16929566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata));
16930f2f62c7SStefano Zampini 
16940f2f62c7SStefano Zampini   /* for other matrix types */
16959566063dSJacob Faibussowitsch   PetscCall(MatSetUp(matis->A));
16962e1947a5SStefano Zampini   PetscFunctionReturn(0);
16972e1947a5SStefano Zampini }
1698b4319ba4SBarry Smith 
16993927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
17003927de2eSStefano Zampini {
17013927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
17023927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
1703ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
17043927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
17053927de2eSStefano Zampini   PetscInt        lrows,lcols;
17063927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
1707f03112d0SStefano Zampini   PetscMPIInt     size;
17083927de2eSStefano Zampini   PetscBool       isdense,issbaij;
17093927de2eSStefano Zampini 
17103927de2eSStefano Zampini   PetscFunctionBegin;
17119566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A),&size));
17129566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A,&rows,&cols));
17139566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(A,&bs));
17149566063dSJacob Faibussowitsch   PetscCall(MatGetSize(matis->A,&local_rows,&local_cols));
17159566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense));
17169566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij));
17179566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(matis->rmapping,&global_indices_r));
1718e432b41dSStefano Zampini   if (matis->rmapping != matis->cmapping) {
17199566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetIndices(matis->cmapping,&global_indices_c));
17200dfc91b7SStefano Zampini   } else global_indices_c = global_indices_r;
1721ecf5a873SStefano Zampini 
17229566063dSJacob Faibussowitsch   if (issbaij) PetscCall(MatGetRowUpperTriangular(matis->A));
17233927de2eSStefano Zampini   /*
1724ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
17253927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
17263927de2eSStefano Zampini   */
17279566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A,&lrows,&lcols));
1728d0609cedSBarry Smith   MatPreallocateBegin(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);
17293927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
17309566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(rows,&row_ownership));
17319566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges));
1732f03112d0SStefano Zampini   for (i=0;i<size;i++) {
17335f80ce2aSJacob Faibussowitsch     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) row_ownership[j] = i;
17343927de2eSStefano Zampini   }
17359566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges));
17363927de2eSStefano Zampini 
17373927de2eSStefano Zampini   /*
17383927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
17393927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
17403927de2eSStefano Zampini   */
17419566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz));
17423927de2eSStefano Zampini   /* preallocation as a MATAIJ */
17433927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
17443927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
174512dfadf8SStefano Zampini       PetscInt owner = row_ownership[global_indices_r[i]];
174612dfadf8SStefano Zampini       for (j=0;j<local_cols;j++) {
1747ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
17483927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1]) { /* diag block */
17493927de2eSStefano Zampini           my_dnz[i] += 1;
17503927de2eSStefano Zampini         } else { /* offdiag block */
17513927de2eSStefano Zampini           my_onz[i] += 1;
17523927de2eSStefano Zampini         }
17533927de2eSStefano Zampini       }
17543927de2eSStefano Zampini     }
1755bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
1756bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
1757bb1015c3SStefano Zampini     PetscBool      done;
17589566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done));
17595f80ce2aSJacob Faibussowitsch     PetscCheck(done,PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1760bb1015c3SStefano Zampini     jptr = jj;
1761bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
1762bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
1763bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
1764bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
1765bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
1766bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1]) { /* diag block */
1767bb1015c3SStefano Zampini           my_dnz[i] += 1;
1768bb1015c3SStefano Zampini         } else { /* offdiag block */
1769bb1015c3SStefano Zampini           my_onz[i] += 1;
1770bb1015c3SStefano Zampini         }
1771bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
1772bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
1773bb1015c3SStefano Zampini           owner = row_ownership[index_col];
1774bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1]) {
1775bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
1776bb1015c3SStefano Zampini           } else {
1777bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
1778bb1015c3SStefano Zampini           }
1779bb1015c3SStefano Zampini         }
1780bb1015c3SStefano Zampini       }
1781bb1015c3SStefano Zampini     }
17829566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done));
17835f80ce2aSJacob Faibussowitsch     PetscCheck(done,PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1784bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
17853927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
17863927de2eSStefano Zampini       const PetscInt *cols;
1787ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
17889566063dSJacob Faibussowitsch       PetscCall(MatGetRow(matis->A,i,&ncols,&cols,NULL));
17893927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
17903927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
1791ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
17923927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1]) { /* diag block */
17933927de2eSStefano Zampini           my_dnz[i] += 1;
17943927de2eSStefano Zampini         } else { /* offdiag block */
17953927de2eSStefano Zampini           my_onz[i] += 1;
17963927de2eSStefano Zampini         }
17973927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
1798d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
17993927de2eSStefano Zampini           owner = row_ownership[index_col];
18003927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1]) {
1801d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
18023927de2eSStefano Zampini           } else {
1803d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
18043927de2eSStefano Zampini           }
18053927de2eSStefano Zampini         }
18063927de2eSStefano Zampini       }
18079566063dSJacob Faibussowitsch       PetscCall(MatRestoreRow(matis->A,i,&ncols,&cols,NULL));
18083927de2eSStefano Zampini     }
18093927de2eSStefano Zampini   }
1810ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
18119566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->cmapping,&global_indices_c));
1812ecf5a873SStefano Zampini   }
18139566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->rmapping,&global_indices_r));
18149566063dSJacob Faibussowitsch   PetscCall(PetscFree(row_ownership));
1815ecf5a873SStefano Zampini 
1816ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
18173927de2eSStefano Zampini   if (maxreduce) {
18189566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX));
18199566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX));
18209566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX));
18219566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX));
18223927de2eSStefano Zampini   } else {
18239566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM));
18249566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM));
18259566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM));
18269566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM));
18273927de2eSStefano Zampini   }
18289566063dSJacob Faibussowitsch   PetscCall(PetscFree2(my_dnz,my_onz));
18293927de2eSStefano Zampini 
18303927de2eSStefano Zampini   /* Resize preallocation if overestimated */
18313927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
18323927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
18333927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
18343927de2eSStefano Zampini   }
18351670daf9Sstefano_zampini 
18361670daf9Sstefano_zampini   /* Set preallocation */
18379566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSizesFromMats(B,A,A));
18389566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(B,0,dnz));
18399566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(B,0,dnz,0,onz));
184053b44cf5SStefano Zampini   for (i=0;i<lrows;i+=bs) {
184153b44cf5SStefano Zampini     PetscInt b, d = dnz[i],o = onz[i];
184253b44cf5SStefano Zampini 
184353b44cf5SStefano Zampini     for (b=1;b<bs;b++) {
184453b44cf5SStefano Zampini       d = PetscMax(d,dnz[i+b]);
184553b44cf5SStefano Zampini       o = PetscMax(o,onz[i+b]);
184653b44cf5SStefano Zampini     }
184753b44cf5SStefano Zampini     dnz[i/bs] = PetscMin(d/bs + d%bs,lcols/bs);
184853b44cf5SStefano Zampini     onz[i/bs] = PetscMin(o/bs + o%bs,(cols-lcols)/bs);
18493927de2eSStefano Zampini   }
18509566063dSJacob Faibussowitsch   PetscCall(MatSeqBAIJSetPreallocation(B,bs,0,dnz));
18519566063dSJacob Faibussowitsch   PetscCall(MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz));
18529566063dSJacob Faibussowitsch   PetscCall(MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz));
1853d0609cedSBarry Smith   MatPreallocateEnd(dnz,onz);
18549566063dSJacob Faibussowitsch   if (issbaij) PetscCall(MatRestoreRowUpperTriangular(matis->A));
18559566063dSJacob Faibussowitsch   PetscCall(MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE));
18563927de2eSStefano Zampini   PetscFunctionReturn(0);
18573927de2eSStefano Zampini }
18583927de2eSStefano Zampini 
1859487b449aSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_IS_XAIJ(Mat mat, MatType mtype, MatReuse reuse, Mat *M)
1860b7ce53b6SStefano Zampini {
1861b7ce53b6SStefano Zampini   Mat_IS            *matis = (Mat_IS*)(mat->data);
1862487b449aSStefano Zampini   Mat               local_mat,MT;
186353b44cf5SStefano Zampini   PetscInt          rbs,cbs,rows,cols,lrows,lcols;
1864b7ce53b6SStefano Zampini   PetscInt          local_rows,local_cols;
1865b9ed4604SStefano Zampini   PetscBool         isseqdense,isseqsbaij,isseqaij,isseqbaij;
1866f03112d0SStefano Zampini   PetscMPIInt       size;
18671683a169SBarry Smith   const PetscScalar *array;
1868b7ce53b6SStefano Zampini 
1869b7ce53b6SStefano Zampini   PetscFunctionBegin;
18709566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
1871f03112d0SStefano Zampini   if (size == 1 && mat->rmap->N == matis->A->rmap->N && mat->cmap->N == matis->A->cmap->N) {
18721670daf9Sstefano_zampini     Mat      B;
187353b44cf5SStefano Zampini     IS       irows = NULL,icols = NULL;
1874487b449aSStefano Zampini     PetscInt rbs,cbs;
18751670daf9Sstefano_zampini 
18769566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->rmapping,&rbs));
18779566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->cmapping,&cbs));
187853b44cf5SStefano Zampini     if (reuse != MAT_REUSE_MATRIX) { /* check if l2g maps are one-to-one */
187953b44cf5SStefano Zampini       IS             rows,cols;
188053b44cf5SStefano Zampini       const PetscInt *ridxs,*cidxs;
188153b44cf5SStefano Zampini       PetscInt       i,nw,*work;
188253b44cf5SStefano Zampini 
18839566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingGetBlockIndices(matis->rmapping,&ridxs));
18849566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingGetSize(matis->rmapping,&nw));
188553b44cf5SStefano Zampini       nw   = nw/rbs;
18869566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(nw,&work));
188753b44cf5SStefano Zampini       for (i=0;i<nw;i++) work[ridxs[i]] += 1;
188853b44cf5SStefano Zampini       for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break;
188953b44cf5SStefano Zampini       if (i == nw) {
18909566063dSJacob Faibussowitsch         PetscCall(ISCreateBlock(PETSC_COMM_SELF,rbs,nw,ridxs,PETSC_USE_POINTER,&rows));
18919566063dSJacob Faibussowitsch         PetscCall(ISSetPermutation(rows));
18929566063dSJacob Faibussowitsch         PetscCall(ISInvertPermutation(rows,PETSC_DECIDE,&irows));
18939566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&rows));
189453b44cf5SStefano Zampini       }
18959566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(matis->rmapping,&ridxs));
18969566063dSJacob Faibussowitsch       PetscCall(PetscFree(work));
1897e432b41dSStefano Zampini       if (irows && matis->rmapping != matis->cmapping) {
18989566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingGetBlockIndices(matis->cmapping,&cidxs));
18999566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingGetSize(matis->cmapping,&nw));
190053b44cf5SStefano Zampini         nw   = nw/cbs;
19019566063dSJacob Faibussowitsch         PetscCall(PetscCalloc1(nw,&work));
190253b44cf5SStefano Zampini         for (i=0;i<nw;i++) work[cidxs[i]] += 1;
190353b44cf5SStefano Zampini         for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break;
190453b44cf5SStefano Zampini         if (i == nw) {
19059566063dSJacob Faibussowitsch           PetscCall(ISCreateBlock(PETSC_COMM_SELF,cbs,nw,cidxs,PETSC_USE_POINTER,&cols));
19069566063dSJacob Faibussowitsch           PetscCall(ISSetPermutation(cols));
19079566063dSJacob Faibussowitsch           PetscCall(ISInvertPermutation(cols,PETSC_DECIDE,&icols));
19089566063dSJacob Faibussowitsch           PetscCall(ISDestroy(&cols));
190953b44cf5SStefano Zampini         }
19109566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(matis->cmapping,&cidxs));
19119566063dSJacob Faibussowitsch         PetscCall(PetscFree(work));
191253b44cf5SStefano Zampini       } else if (irows) {
19139566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)irows));
191453b44cf5SStefano Zampini         icols = irows;
191553b44cf5SStefano Zampini       }
191653b44cf5SStefano Zampini     } else {
19179566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject*)&irows));
19189566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject*)&icols));
19199566063dSJacob Faibussowitsch       if (irows) PetscCall(PetscObjectReference((PetscObject)irows));
19209566063dSJacob Faibussowitsch       if (icols) PetscCall(PetscObjectReference((PetscObject)icols));
192153b44cf5SStefano Zampini     }
192253b44cf5SStefano Zampini     if (!irows || !icols) {
19239566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&icols));
19249566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&irows));
192553b44cf5SStefano Zampini       goto general_assembly;
192653b44cf5SStefano Zampini     }
19279566063dSJacob Faibussowitsch     PetscCall(MatConvert(matis->A,mtype,MAT_INITIAL_MATRIX,&B));
1928487b449aSStefano Zampini     if (reuse != MAT_INPLACE_MATRIX) {
19299566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(B,irows,icols,reuse,M));
19309566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject)irows));
19319566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject)icols));
1932487b449aSStefano Zampini     } else {
1933487b449aSStefano Zampini       Mat C;
1934487b449aSStefano Zampini 
19359566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(B,irows,icols,MAT_INITIAL_MATRIX,&C));
19369566063dSJacob Faibussowitsch       PetscCall(MatHeaderReplace(mat,&C));
1937487b449aSStefano Zampini     }
19389566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
19399566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&icols));
19409566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&irows));
19417c03b4e8SStefano Zampini     PetscFunctionReturn(0);
19427c03b4e8SStefano Zampini   }
194353b44cf5SStefano Zampini general_assembly:
19449566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat,&rows,&cols));
19459566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->rmapping,&rbs));
19469566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->cmapping,&cbs));
19479566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mat,&lrows,&lcols));
19489566063dSJacob Faibussowitsch   PetscCall(MatGetSize(matis->A,&local_rows,&local_cols));
19499566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense));
19509566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij));
19519566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij));
19529566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij));
1953*aed4548fSBarry Smith   PetscCheck(isseqdense || isseqaij || isseqbaij || isseqsbaij,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name);
195476bd3646SJed Brown   if (PetscDefined (USE_DEBUG)) {
195576bd3646SJed Brown     PetscBool         lb[4],bb[4];
195676bd3646SJed Brown 
1957b9ed4604SStefano Zampini     lb[0] = isseqdense;
1958b9ed4604SStefano Zampini     lb[1] = isseqaij;
1959b9ed4604SStefano Zampini     lb[2] = isseqbaij;
1960b9ed4604SStefano Zampini     lb[3] = isseqsbaij;
19611c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat)));
1962*aed4548fSBarry Smith     PetscCheck(bb[0] || bb[1] || bb[2] || bb[3],PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type");
196376bd3646SJed Brown   }
1964b7ce53b6SStefano Zampini 
1965487b449aSStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
19669566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat),&MT));
19679566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(MT,lrows,lcols,rows,cols));
19689566063dSJacob Faibussowitsch     PetscCall(MatSetType(MT,mtype));
19699566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizes(MT,rbs,cbs));
19709566063dSJacob Faibussowitsch     PetscCall(MatISSetMPIXAIJPreallocation_Private(mat,MT,PETSC_FALSE));
1971b7ce53b6SStefano Zampini   } else {
197253b44cf5SStefano Zampini     PetscInt mrbs,mcbs,mrows,mcols,mlrows,mlcols;
1973487b449aSStefano Zampini 
1974b7ce53b6SStefano Zampini     /* some checks */
1975487b449aSStefano Zampini     MT   = *M;
19769566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSizes(MT,&mrbs,&mcbs));
19779566063dSJacob Faibussowitsch     PetscCall(MatGetSize(MT,&mrows,&mcols));
19789566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(MT,&mlrows,&mlcols));
197908401ef6SPierre Jolivet     PetscCheck(mrows == rows,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%" PetscInt_FMT " != %" PetscInt_FMT ")",rows,mrows);
198008401ef6SPierre Jolivet     PetscCheck(mcols == cols,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%" PetscInt_FMT " != %" PetscInt_FMT ")",cols,mcols);
198108401ef6SPierre Jolivet     PetscCheck(mlrows == lrows,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%" PetscInt_FMT " != %" PetscInt_FMT ")",lrows,mlrows);
198208401ef6SPierre Jolivet     PetscCheck(mlcols == lcols,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%" PetscInt_FMT " != %" PetscInt_FMT ")",lcols,mlcols);
198308401ef6SPierre Jolivet     PetscCheck(mrbs == rbs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong row block size (%" PetscInt_FMT " != %" PetscInt_FMT ")",rbs,mrbs);
198408401ef6SPierre Jolivet     PetscCheck(mcbs == cbs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong col block size (%" PetscInt_FMT " != %" PetscInt_FMT ")",cbs,mcbs);
19859566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries(MT));
1986b7ce53b6SStefano Zampini   }
1987d9a9e74cSStefano Zampini 
19888546b261SStefano Zampini   if (isseqsbaij || isseqbaij) {
19899566063dSJacob Faibussowitsch     PetscCall(MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&local_mat));
19908546b261SStefano Zampini     isseqaij = PETSC_TRUE;
1991d9a9e74cSStefano Zampini   } else {
19929566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)matis->A));
1993d9a9e74cSStefano Zampini     local_mat = matis->A;
1994d9a9e74cSStefano Zampini   }
1995686e3a49SStefano Zampini 
1996b7ce53b6SStefano Zampini   /* Set values */
19979566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(MT,matis->rmapping,matis->cmapping));
1998b9ed4604SStefano Zampini   if (isseqdense) { /* special case for dense local matrices */
199965066ba5SStefano Zampini     PetscInt          i,*dummy;
2000ecf5a873SStefano Zampini 
20019566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(PetscMax(local_rows,local_cols),&dummy));
200265066ba5SStefano Zampini     for (i=0;i<PetscMax(local_rows,local_cols);i++) dummy[i] = i;
20039566063dSJacob Faibussowitsch     PetscCall(MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_FALSE));
20049566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(local_mat,&array));
20059566063dSJacob Faibussowitsch     PetscCall(MatSetValuesLocal(MT,local_rows,dummy,local_cols,dummy,array,ADD_VALUES));
20069566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(local_mat,&array));
20079566063dSJacob Faibussowitsch     PetscCall(PetscFree(dummy));
2008686e3a49SStefano Zampini   } else if (isseqaij) {
20096afe12f5SStefano Zampini     const PetscInt *blocks;
20106afe12f5SStefano Zampini     PetscInt       i,nvtxs,*xadj,*adjncy, nb;
2011686e3a49SStefano Zampini     PetscBool      done;
20121683a169SBarry Smith     PetscScalar    *sarray;
2013686e3a49SStefano Zampini 
20149566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done));
201528b400f6SJacob Faibussowitsch     PetscCheck(done,PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
20169566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArray(local_mat,&sarray));
20179566063dSJacob Faibussowitsch     PetscCall(MatGetVariableBlockSizes(local_mat,&nb,&blocks));
20186afe12f5SStefano Zampini     if (nb) { /* speed up assembly for special blocked matrices (used by BDDC) */
20196afe12f5SStefano Zampini       PetscInt sum;
20206afe12f5SStefano Zampini 
20216afe12f5SStefano Zampini       for (i=0,sum=0;i<nb;i++) sum += blocks[i];
20226afe12f5SStefano Zampini       if (sum == nvtxs) {
20236afe12f5SStefano Zampini         PetscInt r;
20246afe12f5SStefano Zampini 
20256afe12f5SStefano Zampini         for (i=0,r=0;i<nb;i++) {
20266bdcaf15SBarry 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]);
20279566063dSJacob Faibussowitsch           PetscCall(MatSetValuesLocal(MT,blocks[i],adjncy+xadj[r],blocks[i],adjncy+xadj[r],sarray+xadj[r],ADD_VALUES));
20286afe12f5SStefano Zampini           r   += blocks[i];
20296afe12f5SStefano Zampini         }
20306afe12f5SStefano Zampini       } else {
2031686e3a49SStefano Zampini         for (i=0;i<nvtxs;i++) {
20329566063dSJacob Faibussowitsch           PetscCall(MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],sarray+xadj[i],ADD_VALUES));
2033686e3a49SStefano Zampini         }
20346afe12f5SStefano Zampini       }
20356afe12f5SStefano Zampini     } else {
20366afe12f5SStefano Zampini       for (i=0;i<nvtxs;i++) {
20379566063dSJacob Faibussowitsch         PetscCall(MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],sarray+xadj[i],ADD_VALUES));
20386afe12f5SStefano Zampini       }
20396afe12f5SStefano Zampini     }
20409566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done));
204128b400f6SJacob Faibussowitsch     PetscCheck(done,PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
20429566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArray(local_mat,&sarray));
2043686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
2044ecf5a873SStefano Zampini     PetscInt i;
2045c0962df8SStefano Zampini 
2046686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
2047686e3a49SStefano Zampini       PetscInt       j;
2048ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
2049686e3a49SStefano Zampini 
20509566063dSJacob Faibussowitsch       PetscCall(MatGetRow(local_mat,i,&j,&local_indices_cols,&array));
20519566063dSJacob Faibussowitsch       PetscCall(MatSetValuesLocal(MT,1,&i,j,local_indices_cols,array,ADD_VALUES));
20529566063dSJacob Faibussowitsch       PetscCall(MatRestoreRow(local_mat,i,&j,&local_indices_cols,&array));
2053686e3a49SStefano Zampini     }
2054b7ce53b6SStefano Zampini   }
20559566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(MT,MAT_FINAL_ASSEMBLY));
20569566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&local_mat));
20579566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(MT,MAT_FINAL_ASSEMBLY));
2058b9ed4604SStefano Zampini   if (isseqdense) {
20599566063dSJacob Faibussowitsch     PetscCall(MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_TRUE));
2060487b449aSStefano Zampini   }
2061487b449aSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
20629566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(mat,&MT));
2063487b449aSStefano Zampini   } else if (reuse == MAT_INITIAL_MATRIX) {
2064487b449aSStefano Zampini     *M = MT;
2065b7ce53b6SStefano Zampini   }
2066b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
2067b7ce53b6SStefano Zampini }
2068b7ce53b6SStefano Zampini 
2069b7ce53b6SStefano Zampini /*@
2070b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
2071b7ce53b6SStefano Zampini 
2072d8d19677SJose E. Roman   Input Parameters:
2073a2b725a8SWilliam Gropp +  mat - the matrix (should be of type MATIS)
2074a2b725a8SWilliam Gropp -  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
2075b7ce53b6SStefano Zampini 
2076b7ce53b6SStefano Zampini   Output Parameter:
2077b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
2078b7ce53b6SStefano Zampini 
2079b7ce53b6SStefano Zampini   Level: developer
2080b7ce53b6SStefano Zampini 
208195452b02SPatrick Sanan   Notes:
2082487b449aSStefano Zampini     This function has been deprecated and it will be removed in future releases. Update your code to use the MatConvert() interface.
2083b7ce53b6SStefano Zampini 
2084487b449aSStefano Zampini .seealso: MATIS, MatConvert()
2085b7ce53b6SStefano Zampini @*/
2086b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
2087b7ce53b6SStefano Zampini {
2088b7ce53b6SStefano Zampini   PetscFunctionBegin;
2089b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2090b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
2091b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
2092487b449aSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
2093b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
2094b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
209508401ef6SPierre Jolivet     PetscCheck(mat != *newmat,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
2096b7ce53b6SStefano Zampini   }
2097cac4c232SBarry Smith   PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatType,MatReuse,Mat*),(mat,MATAIJ,reuse,newmat));
2098b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
2099b7ce53b6SStefano Zampini }
2100b7ce53b6SStefano Zampini 
21018b9382cfSStefano Zampini static PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
2102ad6194a2SStefano Zampini {
2103ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
2104c9225affSStefano Zampini   PetscInt       rbs,cbs,m,n,M,N;
2105ad6194a2SStefano Zampini   Mat            B,localmat;
2106ad6194a2SStefano Zampini 
2107ad6194a2SStefano Zampini   PetscFunctionBegin;
21089566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs));
21099566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs));
21109566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat,&M,&N));
21119566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mat,&m,&n));
21129566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat),&B));
21139566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(B,m,n,M,N));
21149566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(B,rbs == cbs ? rbs : 1));
21159566063dSJacob Faibussowitsch   PetscCall(MatSetType(B,MATIS));
21169566063dSJacob Faibussowitsch   PetscCall(MatISSetLocalMatType(B,matis->lmattype));
21179566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(B,mat->rmap->mapping,mat->cmap->mapping));
21189566063dSJacob Faibussowitsch   PetscCall(MatDuplicate(matis->A,op,&localmat));
21199566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(localmat,matis->A->rmap->mapping,matis->A->cmap->mapping));
21209566063dSJacob Faibussowitsch   PetscCall(MatISSetLocalMat(B,localmat));
21219566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&localmat));
21229566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
21239566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
2124ad6194a2SStefano Zampini   *newmat = B;
2125ad6194a2SStefano Zampini   PetscFunctionReturn(0);
2126ad6194a2SStefano Zampini }
2127ad6194a2SStefano Zampini 
2128a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
212969796d55SStefano Zampini {
213069796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
213169796d55SStefano Zampini   PetscBool      local_sym;
213269796d55SStefano Zampini 
213369796d55SStefano Zampini   PetscFunctionBegin;
21349566063dSJacob Faibussowitsch   PetscCall(MatIsHermitian(matis->A,tol,&local_sym));
21351c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A)));
213669796d55SStefano Zampini   PetscFunctionReturn(0);
213769796d55SStefano Zampini }
213869796d55SStefano Zampini 
2139a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool *flg)
214069796d55SStefano Zampini {
214169796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
214269796d55SStefano Zampini   PetscBool      local_sym;
214369796d55SStefano Zampini 
214469796d55SStefano Zampini   PetscFunctionBegin;
2145e432b41dSStefano Zampini   if (matis->rmapping != matis->cmapping) {
2146e432b41dSStefano Zampini     *flg = PETSC_FALSE;
2147e432b41dSStefano Zampini     PetscFunctionReturn(0);
2148e432b41dSStefano Zampini   }
21499566063dSJacob Faibussowitsch   PetscCall(MatIsSymmetric(matis->A,tol,&local_sym));
21501c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A)));
215169796d55SStefano Zampini   PetscFunctionReturn(0);
215269796d55SStefano Zampini }
215369796d55SStefano Zampini 
215445471136SStefano Zampini static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool *flg)
215545471136SStefano Zampini {
215645471136SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
215745471136SStefano Zampini   PetscBool      local_sym;
215845471136SStefano Zampini 
215945471136SStefano Zampini   PetscFunctionBegin;
2160e432b41dSStefano Zampini   if (matis->rmapping != matis->cmapping) {
216145471136SStefano Zampini     *flg = PETSC_FALSE;
216245471136SStefano Zampini     PetscFunctionReturn(0);
216345471136SStefano Zampini   }
21649566063dSJacob Faibussowitsch   PetscCall(MatIsStructurallySymmetric(matis->A,&local_sym));
21651c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A)));
216645471136SStefano Zampini   PetscFunctionReturn(0);
216745471136SStefano Zampini }
216845471136SStefano Zampini 
2169a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
2170b4319ba4SBarry Smith {
2171b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
2172b4319ba4SBarry Smith 
2173b4319ba4SBarry Smith   PetscFunctionBegin;
21749566063dSJacob Faibussowitsch   PetscCall(PetscFree(b->bdiag));
21759566063dSJacob Faibussowitsch   PetscCall(PetscFree(b->lmattype));
21769566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&b->A));
21779566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&b->cctx));
21789566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&b->rctx));
21799566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&b->x));
21809566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&b->y));
21819566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&b->counter));
21829566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&b->getsub_ris));
21839566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&b->getsub_cis));
2184a8116848SStefano Zampini   if (b->sf != b->csf) {
21859566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&b->csf));
21869566063dSJacob Faibussowitsch     PetscCall(PetscFree2(b->csf_rootdata,b->csf_leafdata));
2187f03112d0SStefano Zampini   } else b->csf = NULL;
21889566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&b->sf));
21899566063dSJacob Faibussowitsch   PetscCall(PetscFree2(b->sf_rootdata,b->sf_leafdata));
21909566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&b->rmapping));
21919566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&b->cmapping));
21929566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->data));
21939566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)A,NULL));
21949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMatType_C",NULL));
21959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL));
21969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL));
21979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL));
21989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL));
21999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",NULL));
22009566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",NULL));
22019566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalToGlobalMapping_C",NULL));
22029566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",NULL));
22039566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",NULL));
22049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",NULL));
22059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",NULL));
22069566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",NULL));
22079566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",NULL));
22089566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",NULL));
22099566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOOLocal_C",NULL));
22109566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOO_C",NULL));
22119566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetValuesCOO_C",NULL));
2212b4319ba4SBarry Smith   PetscFunctionReturn(0);
2213b4319ba4SBarry Smith }
2214b4319ba4SBarry Smith 
2215a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
2216b4319ba4SBarry Smith {
2217b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
2218b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
2219b4319ba4SBarry Smith 
2220b4319ba4SBarry Smith   PetscFunctionBegin;
2221b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
22229566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD));
22239566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD));
2224b4319ba4SBarry Smith 
2225b4319ba4SBarry Smith   /* multiply the local matrix */
22269566063dSJacob Faibussowitsch   PetscCall(MatMult(is->A,is->x,is->y));
2227b4319ba4SBarry Smith 
2228b4319ba4SBarry Smith   /* scatter product back into global memory */
22299566063dSJacob Faibussowitsch   PetscCall(VecSet(y,zero));
22309566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE));
22319566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE));
2232b4319ba4SBarry Smith   PetscFunctionReturn(0);
2233b4319ba4SBarry Smith }
2234b4319ba4SBarry Smith 
2235a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
22362e74eeadSLisandro Dalcin {
2237650997f4SStefano Zampini   Vec            temp_vec;
22382e74eeadSLisandro Dalcin 
22392e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
2240650997f4SStefano Zampini   if (v3 != v2) {
22419566063dSJacob Faibussowitsch     PetscCall(MatMult(A,v1,v3));
22429566063dSJacob Faibussowitsch     PetscCall(VecAXPY(v3,1.0,v2));
2243650997f4SStefano Zampini   } else {
22449566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(v2,&temp_vec));
22459566063dSJacob Faibussowitsch     PetscCall(MatMult(A,v1,temp_vec));
22469566063dSJacob Faibussowitsch     PetscCall(VecAXPY(temp_vec,1.0,v2));
22479566063dSJacob Faibussowitsch     PetscCall(VecCopy(temp_vec,v3));
22489566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&temp_vec));
2249650997f4SStefano Zampini   }
22502e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
22512e74eeadSLisandro Dalcin }
22522e74eeadSLisandro Dalcin 
2253a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
22542e74eeadSLisandro Dalcin {
22552e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
22562e74eeadSLisandro Dalcin 
2257e176bc59SStefano Zampini   PetscFunctionBegin;
22582e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
22599566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD));
22609566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD));
22612e74eeadSLisandro Dalcin 
22622e74eeadSLisandro Dalcin   /* multiply the local matrix */
22639566063dSJacob Faibussowitsch   PetscCall(MatMultTranspose(is->A,is->y,is->x));
22642e74eeadSLisandro Dalcin 
22652e74eeadSLisandro Dalcin   /* scatter product back into global vector */
22669566063dSJacob Faibussowitsch   PetscCall(VecSet(x,0));
22679566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE));
22689566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE));
22692e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
22702e74eeadSLisandro Dalcin }
22712e74eeadSLisandro Dalcin 
2272a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
22732e74eeadSLisandro Dalcin {
2274650997f4SStefano Zampini   Vec            temp_vec;
22752e74eeadSLisandro Dalcin 
22762e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
2277650997f4SStefano Zampini   if (v3 != v2) {
22789566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(A,v1,v3));
22799566063dSJacob Faibussowitsch     PetscCall(VecAXPY(v3,1.0,v2));
2280650997f4SStefano Zampini   } else {
22819566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(v2,&temp_vec));
22829566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(A,v1,temp_vec));
22839566063dSJacob Faibussowitsch     PetscCall(VecAXPY(temp_vec,1.0,v2));
22849566063dSJacob Faibussowitsch     PetscCall(VecCopy(temp_vec,v3));
22859566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&temp_vec));
2286650997f4SStefano Zampini   }
22872e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
22882e74eeadSLisandro Dalcin }
22892e74eeadSLisandro Dalcin 
2290a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
2291b4319ba4SBarry Smith {
2292b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
2293b4319ba4SBarry Smith   PetscViewer    sviewer;
2294ee2491ecSStefano Zampini   PetscBool      isascii,view = PETSC_TRUE;
2295b4319ba4SBarry Smith 
2296b4319ba4SBarry Smith   PetscFunctionBegin;
22979566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
2298ee2491ecSStefano Zampini   if (isascii)  {
2299ee2491ecSStefano Zampini     PetscViewerFormat format;
2300ee2491ecSStefano Zampini 
23019566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer,&format));
2302ee2491ecSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE;
2303ee2491ecSStefano Zampini   }
2304ee2491ecSStefano Zampini   if (!view) PetscFunctionReturn(0);
23059566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer));
23069566063dSJacob Faibussowitsch   PetscCall(MatView(a->A,sviewer));
23079566063dSJacob Faibussowitsch   PetscCall(PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer));
23089566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
2309b4319ba4SBarry Smith   PetscFunctionReturn(0);
2310b4319ba4SBarry Smith }
2311b4319ba4SBarry Smith 
2312b89f26deSStefano Zampini static PetscErrorCode MatInvertBlockDiagonal_IS(Mat mat,const PetscScalar **values)
2313b89f26deSStefano Zampini {
2314b89f26deSStefano Zampini   Mat_IS            *is = (Mat_IS*)mat->data;
2315b89f26deSStefano Zampini   MPI_Datatype      nodeType;
2316b89f26deSStefano Zampini   const PetscScalar *lv;
2317b89f26deSStefano Zampini   PetscInt          bs;
2318b89f26deSStefano Zampini 
2319b89f26deSStefano Zampini   PetscFunctionBegin;
23209566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(mat,&bs));
23219566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(is->A,bs));
23229566063dSJacob Faibussowitsch   PetscCall(MatInvertBlockDiagonal(is->A,&lv));
2323b89f26deSStefano Zampini   if (!is->bdiag) {
23249566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(bs*mat->rmap->n,&is->bdiag));
2325b89f26deSStefano Zampini   }
23269566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Type_contiguous(bs,MPIU_SCALAR,&nodeType));
23279566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Type_commit(&nodeType));
23289566063dSJacob Faibussowitsch   PetscCall(PetscSFReduceBegin(is->sf,nodeType,lv,is->bdiag,MPI_REPLACE));
23299566063dSJacob Faibussowitsch   PetscCall(PetscSFReduceEnd(is->sf,nodeType,lv,is->bdiag,MPI_REPLACE));
23309566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Type_free(&nodeType));
2331b89f26deSStefano Zampini   if (values) *values = is->bdiag;
2332b89f26deSStefano Zampini   PetscFunctionReturn(0);
2333b89f26deSStefano Zampini }
2334b89f26deSStefano Zampini 
23358546b261SStefano Zampini static PetscErrorCode MatISSetUpScatters_Private(Mat A)
2336b4319ba4SBarry Smith {
2337e176bc59SStefano Zampini   Vec            cglobal,rglobal;
23388546b261SStefano Zampini   IS             from;
23398546b261SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
2340b89f26deSStefano Zampini   PetscScalar    sum;
23418546b261SStefano Zampini   const PetscInt *garray;
23428546b261SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
2343e432b41dSStefano Zampini   VecType        rtype;
2344b4319ba4SBarry Smith 
2345b4319ba4SBarry Smith   PetscFunctionBegin;
23469566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(is->rmapping,&nr));
23479566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(is->rmapping,&rbs));
23489566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(is->cmapping,&nc));
23499566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(is->cmapping,&cbs));
23509566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&is->x));
23519566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&is->y));
23529566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&is->counter));
23539566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&is->rctx));
23549566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&is->cctx));
23559566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(is->A,&is->x,&is->y));
23569566063dSJacob Faibussowitsch   PetscCall(VecBindToCPU(is->y,PETSC_TRUE));
23579566063dSJacob Faibussowitsch   PetscCall(VecGetRootType_Private(is->y,&rtype));
23589566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->defaultvectype));
23599566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(rtype,&A->defaultvectype));
23609566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(A,&cglobal,&rglobal));
23619566063dSJacob Faibussowitsch   PetscCall(VecBindToCPU(rglobal,PETSC_TRUE));
23629566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->rmapping,&garray));
23639566063dSJacob Faibussowitsch   PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A),rbs,nr/rbs,garray,PETSC_USE_POINTER,&from));
23649566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(rglobal,from,is->y,NULL,&is->rctx));
23659566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->rmapping,&garray));
23669566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&from));
2367e432b41dSStefano Zampini   if (is->rmapping != is->cmapping) {
23689566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->cmapping,&garray));
23699566063dSJacob Faibussowitsch     PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A),cbs,nc/cbs,garray,PETSC_USE_POINTER,&from));
23709566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(cglobal,from,is->x,NULL,&is->cctx));
23719566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->cmapping,&garray));
23729566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&from));
23738546b261SStefano Zampini   } else {
23749566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)is->rctx));
23758546b261SStefano Zampini     is->cctx = is->rctx;
23768546b261SStefano Zampini   }
23779566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&cglobal));
2378b89f26deSStefano Zampini 
23798546b261SStefano Zampini   /* interface counter vector (local) */
23809566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(is->y,&is->counter));
23819566063dSJacob Faibussowitsch   PetscCall(VecBindToCPU(is->counter,PETSC_TRUE));
23829566063dSJacob Faibussowitsch   PetscCall(VecSet(is->y,1.));
23839566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE));
23849566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE));
23859566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD));
23869566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD));
23879566063dSJacob Faibussowitsch   PetscCall(VecBindToCPU(is->y,PETSC_FALSE));
23889566063dSJacob Faibussowitsch   PetscCall(VecBindToCPU(is->counter,PETSC_FALSE));
2389b89f26deSStefano Zampini 
2390b89f26deSStefano Zampini   /* special functions for block-diagonal matrices */
23919566063dSJacob Faibussowitsch   PetscCall(VecSum(rglobal,&sum));
2392b89f26deSStefano Zampini   A->ops->invertblockdiagonal = NULL;
2393e432b41dSStefano Zampini   if ((PetscInt)(PetscRealPart(sum)) == A->rmap->N && A->rmap->N == A->cmap->N && is->rmapping == is->cmapping) A->ops->invertblockdiagonal = MatInvertBlockDiagonal_IS;
23949566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&rglobal));
2395b0cc1f67SStefano Zampini 
2396b0cc1f67SStefano Zampini   /* setup SF for general purpose shared indices based communications */
23979566063dSJacob Faibussowitsch   PetscCall(MatISSetUpSF_IS(A));
23988546b261SStefano Zampini   PetscFunctionReturn(0);
23998546b261SStefano Zampini }
24008546b261SStefano Zampini 
2401e432b41dSStefano Zampini static PetscErrorCode MatISFilterL2GMap(Mat A, ISLocalToGlobalMapping map, ISLocalToGlobalMapping *nmap, ISLocalToGlobalMapping *lmap)
2402e432b41dSStefano Zampini {
2403e432b41dSStefano Zampini   IS                         is;
2404e432b41dSStefano Zampini   ISLocalToGlobalMappingType l2gtype;
2405e432b41dSStefano Zampini   const PetscInt             *idxs;
2406e432b41dSStefano Zampini   PetscHSetI                 ht;
2407e432b41dSStefano Zampini   PetscInt                   *nidxs;
2408e432b41dSStefano Zampini   PetscInt                   i,n,bs,c;
2409e432b41dSStefano Zampini   PetscBool                  flg[] = {PETSC_FALSE,PETSC_FALSE};
2410e432b41dSStefano Zampini 
2411e432b41dSStefano Zampini   PetscFunctionBegin;
24129566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(map,&n));
24139566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(map,&bs));
24149566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockIndices(map,&idxs));
24159566063dSJacob Faibussowitsch   PetscCall(PetscHSetICreate(&ht));
24169566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n/bs,&nidxs));
2417e432b41dSStefano Zampini   for (i=0,c=0;i<n/bs;i++) {
2418e432b41dSStefano Zampini     PetscBool missing;
2419e432b41dSStefano Zampini     if (idxs[i] < 0) { flg[0] = PETSC_TRUE; continue; }
24209566063dSJacob Faibussowitsch     PetscCall(PetscHSetIQueryAdd(ht,idxs[i],&missing));
2421e432b41dSStefano Zampini     if (!missing) flg[1] = PETSC_TRUE;
2422e432b41dSStefano Zampini     else nidxs[c++] = idxs[i];
2423e432b41dSStefano Zampini   }
24249566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDestroy(&ht));
24251c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(MPI_IN_PLACE,flg,2,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A)));
2426e432b41dSStefano Zampini   if (!flg[0] && !flg[1]) { /* Entries are all non negative and unique */
2427e432b41dSStefano Zampini     *nmap = NULL;
2428e432b41dSStefano Zampini     *lmap = NULL;
24299566063dSJacob Faibussowitsch     PetscCall(PetscFree(nidxs));
24309566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(map,&idxs));
2431e432b41dSStefano Zampini     PetscFunctionReturn(0);
2432e432b41dSStefano Zampini   }
2433e432b41dSStefano Zampini 
2434e432b41dSStefano Zampini   /* New l2g map without negative or repeated indices */
24359566063dSJacob Faibussowitsch   PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A),bs,c,nidxs,PETSC_USE_POINTER,&is));
24369566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(is,nmap));
24379566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
24389566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetType(map,&l2gtype));
24399566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingSetType(*nmap,l2gtype));
2440e432b41dSStefano Zampini 
2441e432b41dSStefano Zampini   /* New local l2g map for repeated indices */
24429566063dSJacob Faibussowitsch   PetscCall(ISGlobalToLocalMappingApplyBlock(*nmap,IS_GTOLM_MASK,n/bs,idxs,NULL,nidxs));
24439566063dSJacob Faibussowitsch   PetscCall(ISCreateBlock(PETSC_COMM_SELF,bs,n/bs,nidxs,PETSC_USE_POINTER,&is));
24449566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(is,lmap));
24459566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
2446e432b41dSStefano Zampini 
24479566063dSJacob Faibussowitsch   PetscCall(PetscFree(nidxs));
24489566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(map,&idxs));
2449e432b41dSStefano Zampini   PetscFunctionReturn(0);
2450e432b41dSStefano Zampini }
2451e432b41dSStefano Zampini 
24528546b261SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
24538546b261SStefano Zampini {
24548546b261SStefano Zampini   Mat_IS                 *is = (Mat_IS*)A->data;
2455e432b41dSStefano Zampini   ISLocalToGlobalMapping localrmapping = NULL, localcmapping = NULL;
2456e432b41dSStefano Zampini   PetscBool              cong, freem[] = { PETSC_FALSE, PETSC_FALSE };
2457e432b41dSStefano Zampini   PetscInt               nr,rbs,nc,cbs;
24588546b261SStefano Zampini 
24598546b261SStefano Zampini   PetscFunctionBegin;
2460fc989267SStefano Zampini   if (rmapping) PetscCheckSameComm(A,1,rmapping,2);
2461fc989267SStefano Zampini   if (cmapping) PetscCheckSameComm(A,1,cmapping,3);
2462e432b41dSStefano Zampini 
24639566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&is->rmapping));
24649566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&is->cmapping));
24659566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
24669566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
24679566063dSJacob Faibussowitsch   PetscCall(MatHasCongruentLayouts(A,&cong));
2468e432b41dSStefano Zampini 
2469fc989267SStefano Zampini   /* If NULL, local space matches global space */
2470fc989267SStefano Zampini   if (!rmapping) {
2471fc989267SStefano Zampini     IS is;
2472fc989267SStefano Zampini 
24739566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A),A->rmap->N,0,1,&is));
24749566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is,&rmapping));
24759566063dSJacob Faibussowitsch     if (A->rmap->bs > 0) PetscCall(ISLocalToGlobalMappingSetBlockSize(rmapping,A->rmap->bs));
24769566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
2477e432b41dSStefano Zampini     freem[0] = PETSC_TRUE;
2478e432b41dSStefano Zampini     if (!cmapping && cong && A->rmap->bs == A->cmap->bs) cmapping = rmapping;
2479e432b41dSStefano Zampini   } else if (!is->islocalref) { /* check if the l2g map has negative or repeated entries */
24809566063dSJacob Faibussowitsch     PetscCall(MatISFilterL2GMap(A,rmapping,&is->rmapping,&localrmapping));
2481e432b41dSStefano Zampini     if (rmapping == cmapping) {
24829566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)is->rmapping));
2483e432b41dSStefano Zampini       is->cmapping = is->rmapping;
24849566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)localrmapping));
2485e432b41dSStefano Zampini       localcmapping = localrmapping;
2486fc989267SStefano Zampini     }
2487fc989267SStefano Zampini   }
2488fc989267SStefano Zampini   if (!cmapping) {
2489fc989267SStefano Zampini     IS is;
2490fc989267SStefano Zampini 
24919566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A),A->cmap->N,0,1,&is));
24929566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is,&cmapping));
24939566063dSJacob Faibussowitsch     if (A->cmap->bs > 0) PetscCall(ISLocalToGlobalMappingSetBlockSize(cmapping,A->cmap->bs));
24949566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
2495e432b41dSStefano Zampini     freem[1] = PETSC_TRUE;
2496e432b41dSStefano Zampini   } else if (cmapping != rmapping && !is->islocalref) { /* check if the l2g map has negative or repeated entries */
24979566063dSJacob Faibussowitsch     PetscCall(MatISFilterL2GMap(A,cmapping,&is->cmapping,&localcmapping));
2498e432b41dSStefano Zampini   }
2499e432b41dSStefano Zampini   if (!is->rmapping) {
25009566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)rmapping));
2501e432b41dSStefano Zampini     is->rmapping = rmapping;
2502e432b41dSStefano Zampini   }
2503e432b41dSStefano Zampini   if (!is->cmapping) {
25049566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)cmapping));
2505e432b41dSStefano Zampini     is->cmapping = cmapping;
2506fc989267SStefano Zampini   }
2507fc989267SStefano Zampini 
2508fc989267SStefano Zampini   /* Clean up */
25099566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&is->A));
2510872cf891SStefano Zampini   if (is->csf != is->sf) {
25119566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&is->csf));
25129566063dSJacob Faibussowitsch     PetscCall(PetscFree2(is->csf_rootdata,is->csf_leafdata));
2513f03112d0SStefano Zampini   } else is->csf = NULL;
25149566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&is->sf));
25159566063dSJacob Faibussowitsch   PetscCall(PetscFree2(is->sf_rootdata,is->sf_leafdata));
25169566063dSJacob Faibussowitsch   PetscCall(PetscFree(is->bdiag));
25173bbff08aSStefano Zampini 
2518fc989267SStefano Zampini   /* check if the two mappings are actually the same for square matrices since MATIS has some optimization for this case
2519fc989267SStefano Zampini      (DOLFIN passes 2 different objects) */
25209566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(is->rmapping,&nr));
25219566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(is->rmapping,&rbs));
25229566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(is->cmapping,&nc));
25239566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(is->cmapping,&cbs));
2524e432b41dSStefano Zampini   if (is->rmapping != is->cmapping && cong) {
2525e432b41dSStefano Zampini     PetscBool same = PETSC_FALSE;
25266625354bSStefano Zampini     if (nr == nc && cbs == rbs) {
25276625354bSStefano Zampini       const PetscInt *idxs1,*idxs2;
25286625354bSStefano Zampini 
25299566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->rmapping,&idxs1));
25309566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->cmapping,&idxs2));
25319566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(idxs1,idxs2,nr/rbs,&same));
25329566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->rmapping,&idxs1));
25339566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->cmapping,&idxs2));
25346625354bSStefano Zampini     }
25351c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(MPI_IN_PLACE,&same,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A)));
2536e432b41dSStefano Zampini     if (same) {
25379566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingDestroy(&is->cmapping));
25389566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)is->rmapping));
2539e432b41dSStefano Zampini       is->cmapping = is->rmapping;
2540e432b41dSStefano Zampini     }
25416625354bSStefano Zampini   }
25429566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(A->rmap,rbs));
25439566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(A->cmap,cbs));
2544e432b41dSStefano Zampini   /* Pass the user defined maps to the layout */
25459566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping));
25469566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping));
25479566063dSJacob Faibussowitsch   if (freem[0]) PetscCall(ISLocalToGlobalMappingDestroy(&rmapping));
25489566063dSJacob Faibussowitsch   if (freem[1]) PetscCall(ISLocalToGlobalMappingDestroy(&cmapping));
25496625354bSStefano Zampini 
25506625354bSStefano Zampini   /* Create the local matrix A */
25519566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF,&is->A));
25529566063dSJacob Faibussowitsch   PetscCall(MatSetType(is->A,is->lmattype));
25539566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(is->A,nr,nc,nr,nc));
25549566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSizes(is->A,rbs,cbs));
25559566063dSJacob Faibussowitsch   PetscCall(MatSetOptionsPrefix(is->A,"is_"));
25569566063dSJacob Faibussowitsch   PetscCall(MatAppendOptionsPrefix(is->A,((PetscObject)A)->prefix));
25579566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(is->A->rmap));
25589566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(is->A->cmap));
25599566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(is->A,localrmapping,localcmapping));
25609566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&localrmapping));
25619566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&localcmapping));
2562b4319ba4SBarry Smith 
2563fc989267SStefano Zampini   /* setup scatters and local vectors for MatMult */
25649566063dSJacob Faibussowitsch   if (!is->islocalref) PetscCall(MatISSetUpScatters_Private(A));
2565fc989267SStefano Zampini   A->preallocated = PETSC_TRUE;
2566fc989267SStefano Zampini   PetscFunctionReturn(0);
2567fc989267SStefano Zampini }
2568fc989267SStefano Zampini 
2569fc989267SStefano Zampini static PetscErrorCode MatSetUp_IS(Mat A)
2570fc989267SStefano Zampini {
2571fc989267SStefano Zampini   ISLocalToGlobalMapping rmap, cmap;
2572fc989267SStefano Zampini 
2573fc989267SStefano Zampini   PetscFunctionBegin;
25749566063dSJacob Faibussowitsch   PetscCall(MatGetLocalToGlobalMapping(A,&rmap,&cmap));
2575fc989267SStefano Zampini   if (!rmap && !cmap) {
25769566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(A,NULL,NULL));
2577fc989267SStefano Zampini   }
2578b4319ba4SBarry Smith   PetscFunctionReturn(0);
2579b4319ba4SBarry Smith }
2580b4319ba4SBarry Smith 
2581a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
25822e74eeadSLisandro Dalcin {
25832e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
2584f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
25852e74eeadSLisandro Dalcin 
25862e74eeadSLisandro Dalcin   PetscFunctionBegin;
25879566063dSJacob Faibussowitsch   PetscCall(ISGlobalToLocalMappingApply(is->rmapping,IS_GTOLM_MASK,m,rows,&m,rows_l));
2588e432b41dSStefano Zampini   if (m != n || rows != cols || is->cmapping != is->rmapping) {
25899566063dSJacob Faibussowitsch     PetscCall(ISGlobalToLocalMappingApply(is->cmapping,IS_GTOLM_MASK,n,cols,&n,cols_l));
25909566063dSJacob Faibussowitsch     PetscCall(MatSetValues(is->A,m,rows_l,n,cols_l,values,addv));
2591e432b41dSStefano Zampini   } else {
25929566063dSJacob Faibussowitsch     PetscCall(MatSetValues(is->A,m,rows_l,m,rows_l,values,addv));
2593e432b41dSStefano Zampini   }
25942e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
25952e74eeadSLisandro Dalcin }
25962e74eeadSLisandro Dalcin 
2597a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
259897563a80SStefano Zampini {
259997563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
2600f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
260197563a80SStefano Zampini 
260297563a80SStefano Zampini   PetscFunctionBegin;
26039566063dSJacob Faibussowitsch   PetscCall(ISGlobalToLocalMappingApplyBlock(is->rmapping,IS_GTOLM_MASK,m,rows,&m,rows_l));
2604e432b41dSStefano Zampini   if (m != n || rows != cols || is->cmapping != is->rmapping) {
26059566063dSJacob Faibussowitsch     PetscCall(ISGlobalToLocalMappingApply(is->cmapping,IS_GTOLM_MASK,n,cols,&n,cols_l));
26069566063dSJacob Faibussowitsch     PetscCall(MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv));
2607e432b41dSStefano Zampini   } else {
26089566063dSJacob Faibussowitsch     PetscCall(MatSetValuesBlocked(is->A,m,rows_l,n,rows_l,values,addv));
2609e432b41dSStefano Zampini   }
261097563a80SStefano Zampini   PetscFunctionReturn(0);
261197563a80SStefano Zampini }
261297563a80SStefano Zampini 
2613a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
2614b4319ba4SBarry Smith {
2615b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2616b4319ba4SBarry Smith 
2617b4319ba4SBarry Smith   PetscFunctionBegin;
2618e432b41dSStefano Zampini   if (is->A->rmap->mapping || is->A->cmap->mapping) {
26199566063dSJacob Faibussowitsch     PetscCall(MatSetValuesLocal(is->A,m,rows,n,cols,values,addv));
2620872cf891SStefano Zampini   } else {
26219566063dSJacob Faibussowitsch     PetscCall(MatSetValues(is->A,m,rows,n,cols,values,addv));
2622872cf891SStefano Zampini   }
2623b4319ba4SBarry Smith   PetscFunctionReturn(0);
2624b4319ba4SBarry Smith }
2625b4319ba4SBarry Smith 
2626a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
2627f0006bf2SLisandro Dalcin {
2628f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
2629f0006bf2SLisandro Dalcin 
2630f0006bf2SLisandro Dalcin   PetscFunctionBegin;
2631e432b41dSStefano Zampini   if (is->A->rmap->mapping || is->A->cmap->mapping) {
26329566063dSJacob Faibussowitsch     PetscCall(MatSetValuesBlockedLocal(is->A,m,rows,n,cols,values,addv));
2633b4f971dfSStefano Zampini   } else {
26349566063dSJacob Faibussowitsch     PetscCall(MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv));
2635b4f971dfSStefano Zampini   }
2636f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
2637f0006bf2SLisandro Dalcin }
2638f0006bf2SLisandro Dalcin 
2639f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
2640f0ae7da4SStefano Zampini {
2641f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
2642f0ae7da4SStefano Zampini 
2643f0ae7da4SStefano Zampini   PetscFunctionBegin;
2644f0ae7da4SStefano Zampini   if (!n) {
2645f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
2646f0ae7da4SStefano Zampini   } else {
2647f0ae7da4SStefano Zampini     PetscInt i;
2648f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
2649f0ae7da4SStefano Zampini 
2650f0ae7da4SStefano Zampini     if (columns) {
26519566063dSJacob Faibussowitsch       PetscCall(MatZeroRowsColumns(is->A,n,rows,diag,NULL,NULL));
2652f0ae7da4SStefano Zampini     } else {
26539566063dSJacob Faibussowitsch       PetscCall(MatZeroRows(is->A,n,rows,diag,NULL,NULL));
2654f0ae7da4SStefano Zampini     }
2655f0ae7da4SStefano Zampini     if (diag != 0.) {
2656f0ae7da4SStefano Zampini       const PetscScalar *array;
26579566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(is->counter,&array));
2658f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
26599566063dSJacob Faibussowitsch         PetscCall(MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES));
2660f0ae7da4SStefano Zampini       }
26619566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(is->counter,&array));
2662f0ae7da4SStefano Zampini     }
26639566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY));
26649566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY));
2665f0ae7da4SStefano Zampini   }
2666f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
2667f0ae7da4SStefano Zampini }
2668f0ae7da4SStefano Zampini 
2669f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
26702e74eeadSLisandro Dalcin {
26716e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
26726e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
26736e520ac8SStefano Zampini   PetscInt       *lrows;
26742e74eeadSLisandro Dalcin 
26752e74eeadSLisandro Dalcin   PetscFunctionBegin;
2676cf9c20a2SJed Brown   if (PetscUnlikelyDebug(columns || diag != 0. || (x && b))) {
2677f0ae7da4SStefano Zampini     PetscBool cong;
267826b0207aSStefano Zampini 
26799566063dSJacob Faibussowitsch     PetscCall(PetscLayoutCompare(A->rmap,A->cmap,&cong));
268026b0207aSStefano Zampini     cong = (PetscBool)(cong && matis->sf == matis->csf);
268108401ef6SPierre Jolivet     PetscCheck(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");
2682*aed4548fSBarry Smith     PetscCheck(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");
2683*aed4548fSBarry Smith     PetscCheck(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");
2684f0ae7da4SStefano Zampini   }
26856e520ac8SStefano Zampini   /* get locally owned rows */
26869566063dSJacob Faibussowitsch   PetscCall(PetscLayoutMapLocal(A->rmap,n,rows,&len,&lrows,NULL));
26876e520ac8SStefano Zampini   /* fix right hand side if needed */
26886e520ac8SStefano Zampini   if (x && b) {
26896e520ac8SStefano Zampini     const PetscScalar *xx;
26906e520ac8SStefano Zampini     PetscScalar       *bb;
26916e520ac8SStefano Zampini 
26929566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
26939566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
26946e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
26959566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
26969566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
26972e74eeadSLisandro Dalcin   }
26986e520ac8SStefano Zampini   /* get rows associated to the local matrices */
26999566063dSJacob Faibussowitsch   PetscCall(MatGetSize(matis->A,&nl,NULL));
27009566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(matis->sf_leafdata,nl));
27019566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(matis->sf_rootdata,A->rmap->n));
27026e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
27039566063dSJacob Faibussowitsch   PetscCall(PetscFree(lrows));
27049566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
27059566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
27069566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nl,&lrows));
27076e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
27089566063dSJacob Faibussowitsch   PetscCall(MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns));
27099566063dSJacob Faibussowitsch   PetscCall(PetscFree(lrows));
27102e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
27112e74eeadSLisandro Dalcin }
27122e74eeadSLisandro Dalcin 
2713f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
2714b4319ba4SBarry Smith {
2715b4319ba4SBarry Smith   PetscFunctionBegin;
27169566063dSJacob Faibussowitsch   PetscCall(MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE));
2717f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
2718f0ae7da4SStefano Zampini }
27192205254eSKarl Rupp 
2720f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
2721f0ae7da4SStefano Zampini {
2722f0ae7da4SStefano Zampini   PetscFunctionBegin;
27239566063dSJacob Faibussowitsch   PetscCall(MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE));
2724b4319ba4SBarry Smith   PetscFunctionReturn(0);
2725b4319ba4SBarry Smith }
2726b4319ba4SBarry Smith 
2727a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
2728b4319ba4SBarry Smith {
2729b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2730b4319ba4SBarry Smith 
2731b4319ba4SBarry Smith   PetscFunctionBegin;
27329566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(is->A,type));
2733b4319ba4SBarry Smith   PetscFunctionReturn(0);
2734b4319ba4SBarry Smith }
2735b4319ba4SBarry Smith 
2736a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
2737b4319ba4SBarry Smith {
2738b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2739b4319ba4SBarry Smith 
2740b4319ba4SBarry Smith   PetscFunctionBegin;
27419566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(is->A,type));
2742872cf891SStefano Zampini   /* fix for local empty rows/cols */
2743872cf891SStefano Zampini   if (is->locempty && type == MAT_FINAL_ASSEMBLY) {
2744872cf891SStefano Zampini     Mat                    newlA;
2745f03112d0SStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g;
2746f03112d0SStefano Zampini     IS                     nzr,nzc;
2747f03112d0SStefano Zampini     PetscInt               nr,nc,nnzr,nnzc;
2748f03112d0SStefano Zampini     PetscBool              lnewl2g,newl2g;
2749872cf891SStefano Zampini 
27509566063dSJacob Faibussowitsch     PetscCall(MatGetSize(is->A,&nr,&nc));
27519566063dSJacob Faibussowitsch     PetscCall(MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_FALSE,PETSC_SMALL,&nzr));
2752f03112d0SStefano Zampini     if (!nzr) {
27539566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PetscObjectComm((PetscObject)is->A),nr,0,1,&nzr));
2754872cf891SStefano Zampini     }
27559566063dSJacob Faibussowitsch     PetscCall(MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_TRUE,PETSC_SMALL,&nzc));
2756f03112d0SStefano Zampini     if (!nzc) {
27579566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PetscObjectComm((PetscObject)is->A),nc,0,1,&nzc));
2758872cf891SStefano Zampini     }
27599566063dSJacob Faibussowitsch     PetscCall(ISGetSize(nzr,&nnzr));
27609566063dSJacob Faibussowitsch     PetscCall(ISGetSize(nzc,&nnzc));
2761e432b41dSStefano Zampini     if (nnzr != nr || nnzc != nc) { /* need new global l2g map */
2762f03112d0SStefano Zampini       lnewl2g = PETSC_TRUE;
27639566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A)));
2764f03112d0SStefano Zampini 
2765872cf891SStefano Zampini       /* extract valid submatrix */
27669566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(is->A,nzr,nzc,MAT_INITIAL_MATRIX,&newlA));
2767f03112d0SStefano Zampini     } else { /* local matrix fully populated */
2768f03112d0SStefano Zampini       lnewl2g = PETSC_FALSE;
27699566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A)));
27709566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)is->A));
2771f03112d0SStefano Zampini       newlA   = is->A;
2772f03112d0SStefano Zampini     }
2773e432b41dSStefano Zampini 
2774f03112d0SStefano Zampini     /* attach new global l2g map if needed */
2775f03112d0SStefano Zampini     if (newl2g) {
2776e432b41dSStefano Zampini       IS              zr,zc;
2777e432b41dSStefano Zampini       const  PetscInt *ridxs,*cidxs,*zridxs,*zcidxs;
2778e432b41dSStefano Zampini       PetscInt        *nidxs,i;
2779f03112d0SStefano Zampini 
27809566063dSJacob Faibussowitsch       PetscCall(ISComplement(nzr,0,nr,&zr));
27819566063dSJacob Faibussowitsch       PetscCall(ISComplement(nzc,0,nc,&zc));
27829566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(PetscMax(nr,nc),&nidxs));
27839566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingGetIndices(is->rmapping,&ridxs));
27849566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingGetIndices(is->cmapping,&cidxs));
27859566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(zr,&zridxs));
27869566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(zc,&zcidxs));
27879566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(zr,&nnzr));
27889566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(zc,&nnzc));
2789e432b41dSStefano Zampini 
27909566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(nidxs,ridxs,nr));
2791e432b41dSStefano Zampini       for (i = 0; i < nnzr; i++) nidxs[zridxs[i]] = -1;
27929566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nr,nidxs,PETSC_COPY_VALUES,&rl2g));
27939566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(nidxs,cidxs,nc));
2794e432b41dSStefano Zampini       for (i = 0; i < nnzc; i++) nidxs[zcidxs[i]] = -1;
27959566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nc,nidxs,PETSC_COPY_VALUES,&cl2g));
2796e432b41dSStefano Zampini 
27979566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(zr,&zridxs));
27989566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(zc,&zcidxs));
27999566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingRestoreIndices(is->rmapping,&ridxs));
28009566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingRestoreIndices(is->cmapping,&cidxs));
28019566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&nzr));
28029566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&nzc));
28039566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&zr));
28049566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&zc));
28059566063dSJacob Faibussowitsch       PetscCall(PetscFree(nidxs));
28069566063dSJacob Faibussowitsch       PetscCall(MatSetLocalToGlobalMapping(A,rl2g,cl2g));
28079566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
28089566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
2809f03112d0SStefano Zampini     }
28109566063dSJacob Faibussowitsch     PetscCall(MatISSetLocalMat(A,newlA));
28119566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&newlA));
28129566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&nzr));
28139566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&nzc));
2814872cf891SStefano Zampini     is->locempty = PETSC_FALSE;
2815f03112d0SStefano Zampini   }
2816b4319ba4SBarry Smith   PetscFunctionReturn(0);
2817b4319ba4SBarry Smith }
2818b4319ba4SBarry Smith 
2819a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
2820b4319ba4SBarry Smith {
2821b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
2822b4319ba4SBarry Smith 
2823b4319ba4SBarry Smith   PetscFunctionBegin;
2824b4319ba4SBarry Smith   *local = is->A;
2825b4319ba4SBarry Smith   PetscFunctionReturn(0);
2826b4319ba4SBarry Smith }
2827b4319ba4SBarry Smith 
28283b3b1effSJed Brown static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat,Mat *local)
28293b3b1effSJed Brown {
28303b3b1effSJed Brown   PetscFunctionBegin;
28313b3b1effSJed Brown   *local = NULL;
28323b3b1effSJed Brown   PetscFunctionReturn(0);
28333b3b1effSJed Brown }
28343b3b1effSJed Brown 
2835b4319ba4SBarry Smith /*@
2836b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
2837b4319ba4SBarry Smith 
2838b4319ba4SBarry Smith   Input Parameter:
2839b4319ba4SBarry Smith .  mat - the matrix
2840b4319ba4SBarry Smith 
2841b4319ba4SBarry Smith   Output Parameter:
2842eb82efa4SStefano Zampini .  local - the local matrix
2843b4319ba4SBarry Smith 
2844b4319ba4SBarry Smith   Level: advanced
2845b4319ba4SBarry Smith 
2846b4319ba4SBarry Smith   Notes:
2847b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
2848b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
2849b4319ba4SBarry Smith   of the MatSetValues() operation.
2850b4319ba4SBarry Smith 
28513b3b1effSJed Brown   Call MatISRestoreLocalMat() when finished with the local matrix.
285296a6f129SJed Brown 
2853b4319ba4SBarry Smith .seealso: MATIS
2854b4319ba4SBarry Smith @*/
28557087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
2856b4319ba4SBarry Smith {
2857b4319ba4SBarry Smith   PetscFunctionBegin;
28580700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2859b4319ba4SBarry Smith   PetscValidPointer(local,2);
2860cac4c232SBarry Smith   PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));
2861b4319ba4SBarry Smith   PetscFunctionReturn(0);
2862b4319ba4SBarry Smith }
2863b4319ba4SBarry Smith 
28643b3b1effSJed Brown /*@
28653b3b1effSJed Brown     MatISRestoreLocalMat - Restores the local matrix obtained with MatISGetLocalMat()
28663b3b1effSJed Brown 
28673b3b1effSJed Brown   Input Parameter:
28683b3b1effSJed Brown .  mat - the matrix
28693b3b1effSJed Brown 
28703b3b1effSJed Brown   Output Parameter:
28713b3b1effSJed Brown .  local - the local matrix
28723b3b1effSJed Brown 
28733b3b1effSJed Brown   Level: advanced
28743b3b1effSJed Brown 
28753b3b1effSJed Brown .seealso: MATIS
28763b3b1effSJed Brown @*/
28773b3b1effSJed Brown PetscErrorCode MatISRestoreLocalMat(Mat mat,Mat *local)
28783b3b1effSJed Brown {
28793b3b1effSJed Brown   PetscFunctionBegin;
28803b3b1effSJed Brown   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
28813b3b1effSJed Brown   PetscValidPointer(local,2);
2882cac4c232SBarry Smith   PetscUseMethod(mat,"MatISRestoreLocalMat_C",(Mat,Mat*),(mat,local));
28833b3b1effSJed Brown   PetscFunctionReturn(0);
28843b3b1effSJed Brown }
28853b3b1effSJed Brown 
28868546b261SStefano Zampini static PetscErrorCode MatISSetLocalMatType_IS(Mat mat,MatType mtype)
28878546b261SStefano Zampini {
28888546b261SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
28898546b261SStefano Zampini 
28908546b261SStefano Zampini   PetscFunctionBegin;
28918546b261SStefano Zampini   if (is->A) {
28929566063dSJacob Faibussowitsch     PetscCall(MatSetType(is->A,mtype));
28938546b261SStefano Zampini   }
28949566063dSJacob Faibussowitsch   PetscCall(PetscFree(is->lmattype));
28959566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(mtype,&is->lmattype));
28968546b261SStefano Zampini   PetscFunctionReturn(0);
28978546b261SStefano Zampini }
28988546b261SStefano Zampini 
28998546b261SStefano Zampini /*@
29008546b261SStefano Zampini     MatISSetLocalMatType - Specifies the type of local matrix
29018546b261SStefano Zampini 
2902d8d19677SJose E. Roman   Input Parameters:
2903a2b725a8SWilliam Gropp +  mat - the matrix
2904a2b725a8SWilliam Gropp -  mtype - the local matrix type
29058546b261SStefano Zampini 
29068546b261SStefano Zampini   Output Parameter:
29078546b261SStefano Zampini 
29088546b261SStefano Zampini   Level: advanced
29098546b261SStefano Zampini 
29108546b261SStefano Zampini .seealso: MATIS, MatSetType(), MatType
29118546b261SStefano Zampini @*/
29128546b261SStefano Zampini PetscErrorCode MatISSetLocalMatType(Mat mat,MatType mtype)
29138546b261SStefano Zampini {
29148546b261SStefano Zampini   PetscFunctionBegin;
29158546b261SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2916cac4c232SBarry Smith   PetscUseMethod(mat,"MatISSetLocalMatType_C",(Mat,MatType),(mat,mtype));
29178546b261SStefano Zampini   PetscFunctionReturn(0);
29188546b261SStefano Zampini }
29198546b261SStefano Zampini 
2920a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
29213b03a366Sstefano_zampini {
29223b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
29233b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
29248546b261SStefano Zampini   MatType        mtype,otype;
29258546b261SStefano Zampini   PetscBool      sametype = PETSC_TRUE;
29263b03a366Sstefano_zampini 
29273b03a366Sstefano_zampini   PetscFunctionBegin;
2928e432b41dSStefano Zampini   if (is->A && !is->islocalref) {
29299566063dSJacob Faibussowitsch     PetscCall(MatGetSize(is->A,&orows,&ocols));
29309566063dSJacob Faibussowitsch     PetscCall(MatGetSize(local,&nrows,&ncols));
2931*aed4548fSBarry Smith     PetscCheck(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);
29329566063dSJacob Faibussowitsch     PetscCall(MatGetType(local,&mtype));
29339566063dSJacob Faibussowitsch     PetscCall(MatGetType(is->A,&otype));
29349566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(mtype,otype,&sametype));
29354e4c7dbeSStefano Zampini   }
29369566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)local));
29379566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&is->A));
29383b03a366Sstefano_zampini   is->A = local;
29399566063dSJacob Faibussowitsch   PetscCall(MatGetType(is->A,&mtype));
29409566063dSJacob Faibussowitsch   PetscCall(MatISSetLocalMatType(mat,mtype));
29418546b261SStefano Zampini   if (!sametype && !is->islocalref) {
29429566063dSJacob Faibussowitsch     PetscCall(MatISSetUpScatters_Private(mat));
29438546b261SStefano Zampini   }
29443b03a366Sstefano_zampini   PetscFunctionReturn(0);
29453b03a366Sstefano_zampini }
29463b03a366Sstefano_zampini 
29473b03a366Sstefano_zampini /*@
2948eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
29493b03a366Sstefano_zampini 
29508546b261SStefano Zampini   Collective on Mat
29518546b261SStefano Zampini 
2952d8d19677SJose E. Roman   Input Parameters:
2953a2b725a8SWilliam Gropp +  mat - the matrix
2954a2b725a8SWilliam Gropp -  local - the local matrix
29553b03a366Sstefano_zampini 
29563b03a366Sstefano_zampini   Output Parameter:
29573b03a366Sstefano_zampini 
29583b03a366Sstefano_zampini   Level: advanced
29593b03a366Sstefano_zampini 
29603b03a366Sstefano_zampini   Notes:
29613b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
29623b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
29633b03a366Sstefano_zampini 
29643b03a366Sstefano_zampini .seealso: MATIS
29653b03a366Sstefano_zampini @*/
29663b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
29673b03a366Sstefano_zampini {
29683b03a366Sstefano_zampini   PetscFunctionBegin;
29693b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2970b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
2971cac4c232SBarry Smith   PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));
29723b03a366Sstefano_zampini   PetscFunctionReturn(0);
29733b03a366Sstefano_zampini }
29743b03a366Sstefano_zampini 
2975a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
29766726f965SBarry Smith {
29776726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
29786726f965SBarry Smith 
29796726f965SBarry Smith   PetscFunctionBegin;
29809566063dSJacob Faibussowitsch   PetscCall(MatZeroEntries(a->A));
29816726f965SBarry Smith   PetscFunctionReturn(0);
29826726f965SBarry Smith }
29836726f965SBarry Smith 
2984a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
29852e74eeadSLisandro Dalcin {
29862e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
29872e74eeadSLisandro Dalcin 
29882e74eeadSLisandro Dalcin   PetscFunctionBegin;
29899566063dSJacob Faibussowitsch   PetscCall(MatScale(is->A,a));
29902e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
29912e74eeadSLisandro Dalcin }
29922e74eeadSLisandro Dalcin 
2993a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
29942e74eeadSLisandro Dalcin {
29952e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
29962e74eeadSLisandro Dalcin 
29972e74eeadSLisandro Dalcin   PetscFunctionBegin;
29982e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
29999566063dSJacob Faibussowitsch   PetscCall(MatGetDiagonal(is->A,is->y));
30002e74eeadSLisandro Dalcin 
30012e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
30029566063dSJacob Faibussowitsch   PetscCall(VecSet(v,0));
30039566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE));
30049566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE));
30052e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
30062e74eeadSLisandro Dalcin }
30072e74eeadSLisandro Dalcin 
3008a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
30096726f965SBarry Smith {
30106726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
30116726f965SBarry Smith 
30126726f965SBarry Smith   PetscFunctionBegin;
30139566063dSJacob Faibussowitsch   PetscCall(MatSetOption(a->A,op,flg));
30146726f965SBarry Smith   PetscFunctionReturn(0);
30156726f965SBarry Smith }
30166726f965SBarry Smith 
3017f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
3018f26d0771SStefano Zampini {
3019f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
3020f26d0771SStefano Zampini   Mat_IS         *x;
3021f26d0771SStefano Zampini 
3022f26d0771SStefano Zampini   PetscFunctionBegin;
302376bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
302476bd3646SJed Brown     PetscBool      ismatis;
30259566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis));
302628b400f6SJacob Faibussowitsch     PetscCheck(ismatis,PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
302776bd3646SJed Brown   }
3028f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
30299566063dSJacob Faibussowitsch   PetscCall(MatAXPY(y->A,a,x->A,str));
3030f26d0771SStefano Zampini   PetscFunctionReturn(0);
3031f26d0771SStefano Zampini }
3032f26d0771SStefano Zampini 
3033f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
3034f26d0771SStefano Zampini {
3035f26d0771SStefano Zampini   Mat                    lA;
3036e432b41dSStefano Zampini   Mat_IS                 *matis = (Mat_IS*)(A->data);
3037f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
3038f26d0771SStefano Zampini   IS                     is;
3039f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
3040f26d0771SStefano Zampini   PetscInt               nrg;
3041f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
3042f26d0771SStefano Zampini 
3043f26d0771SStefano Zampini   PetscFunctionBegin;
30449566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg));
30459566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(row,&nrl));
30469566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(row,&rl));
30479566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg));
304876bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
304908401ef6SPierre Jolivet     for (i=0; i<nrl; i++) PetscCheck(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);
305076bd3646SJed Brown   }
30519566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrg,&idxs));
3052f26d0771SStefano Zampini   /* map from [0,nrl) to row */
3053f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
3054f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
30559566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(row,&rl));
30569566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg));
30579566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is));
30589566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(is,&rl2g));
30599566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
3060f26d0771SStefano Zampini   /* compute new l2g map for columns */
3061e432b41dSStefano Zampini   if (col != row || matis->rmapping != matis->cmapping || matis->A->rmap->mapping != matis->A->cmap->mapping) {
3062f26d0771SStefano Zampini     const PetscInt *cg,*cl;
3063f26d0771SStefano Zampini     PetscInt       ncg;
3064f26d0771SStefano Zampini     PetscInt       ncl;
3065f26d0771SStefano Zampini 
30669566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg));
30679566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(col,&ncl));
30689566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(col,&cl));
30699566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg));
307076bd3646SJed Brown     if (PetscDefined(USE_DEBUG)) {
307108401ef6SPierre Jolivet       for (i=0; i<ncl; i++) PetscCheck(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);
307276bd3646SJed Brown     }
30739566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(ncg,&idxs));
3074f26d0771SStefano Zampini     /* map from [0,ncl) to col */
3075f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
3076f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
30779566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(col,&cl));
30789566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg));
30799566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is));
30809566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is,&cl2g));
30819566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
3082f26d0771SStefano Zampini   } else {
30839566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)rl2g));
3084f26d0771SStefano Zampini     cl2g = rl2g;
3085f26d0771SStefano Zampini   }
3086f26d0771SStefano Zampini   /* create the MATIS submatrix */
30879566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A,&M,&N));
30889566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A),submat));
30899566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N));
30909566063dSJacob Faibussowitsch   PetscCall(MatSetType(*submat,MATIS));
3091b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
3092f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
30939566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(*submat,rl2g,cl2g));
30949566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(A,&lA));
30959566063dSJacob Faibussowitsch   PetscCall(MatISSetLocalMat(*submat,lA));
30969566063dSJacob Faibussowitsch   PetscCall(MatSetUp(*submat));
30979566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY));
30989566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY));
30999566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
31009566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
3101e432b41dSStefano Zampini 
3102f26d0771SStefano Zampini   /* remove unsupported ops */
31039566063dSJacob Faibussowitsch   PetscCall(PetscMemzero((*submat)->ops,sizeof(struct _MatOps)));
3104f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
3105f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
3106f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
3107f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
3108f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
3109f26d0771SStefano Zampini   PetscFunctionReturn(0);
3110f26d0771SStefano Zampini }
3111f26d0771SStefano Zampini 
3112872cf891SStefano Zampini static PetscErrorCode MatSetFromOptions_IS(PetscOptionItems *PetscOptionsObject, Mat A)
3113872cf891SStefano Zampini {
3114872cf891SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
31158546b261SStefano Zampini   char           type[256];
31168546b261SStefano Zampini   PetscBool      flg;
3117872cf891SStefano Zampini 
3118872cf891SStefano Zampini   PetscFunctionBegin;
3119d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject,"MATIS options");
31209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-matis_fixempty","Fix local matrices in case of empty local rows/columns","MatISFixLocalEmpty",a->locempty,&a->locempty,NULL));
31219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-matis_storel2l","Store local-to-local matrices generated from PtAP operations","MatISStoreL2L",a->storel2l,&a->storel2l,NULL));
31229566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-matis_localmat_type","Matrix type","MatISSetLocalMatType",MatList,a->lmattype,type,256,&flg));
31238546b261SStefano Zampini   if (flg) {
31249566063dSJacob Faibussowitsch     PetscCall(MatISSetLocalMatType(A,type));
31258546b261SStefano Zampini   }
31268546b261SStefano Zampini   if (a->A) {
31279566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(a->A));
31288546b261SStefano Zampini   }
3129d0609cedSBarry Smith   PetscOptionsHeadEnd();
3130872cf891SStefano Zampini   PetscFunctionReturn(0);
3131872cf891SStefano Zampini }
3132872cf891SStefano Zampini 
3133284134d9SBarry Smith /*@
31343c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
3135284134d9SBarry Smith        process but not across processes.
3136284134d9SBarry Smith 
3137284134d9SBarry Smith    Input Parameters:
3138284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
3139e176bc59SStefano Zampini .     bs      - block size of the matrix
3140df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
3141e176bc59SStefano Zampini .     rmap    - local to global map for rows
3142e176bc59SStefano Zampini -     cmap    - local to global map for cols
3143284134d9SBarry Smith 
3144284134d9SBarry Smith    Output Parameter:
3145284134d9SBarry Smith .    A - the resulting matrix
3146284134d9SBarry Smith 
31478e6c10adSSatish Balay    Level: advanced
31488e6c10adSSatish Balay 
314995452b02SPatrick Sanan    Notes:
315095452b02SPatrick Sanan     See MATIS for more details.
3151fc989267SStefano 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
31526fdf41d1SStefano Zampini     used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
3153fc989267SStefano Zampini     If rmap (cmap) is NULL, then the local row (column) spaces matches the global space.
3154284134d9SBarry Smith 
3155284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
3156284134d9SBarry Smith @*/
3157e176bc59SStefano Zampini PetscErrorCode MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
3158284134d9SBarry Smith {
3159284134d9SBarry Smith   PetscFunctionBegin;
31609566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm,A));
31619566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A,m,n,M,N));
31626fdf41d1SStefano Zampini   if (bs > 0) {
31639566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSize(*A,bs));
31646fdf41d1SStefano Zampini   }
31659566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A,MATIS));
31669566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(*A,rmap,cmap));
3167284134d9SBarry Smith   PetscFunctionReturn(0);
3168284134d9SBarry Smith }
3169284134d9SBarry Smith 
31708b9382cfSStefano Zampini static PetscErrorCode MatHasOperation_IS(Mat A, MatOperation op, PetscBool *has)
31718b9382cfSStefano Zampini {
31728b9382cfSStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
31738b9382cfSStefano Zampini 
31748b9382cfSStefano Zampini   PetscFunctionBegin;
31758b9382cfSStefano Zampini   *has = PETSC_FALSE;
31768b9382cfSStefano Zampini   if (!((void**)A->ops)[op]) PetscFunctionReturn(0);
31779566063dSJacob Faibussowitsch   PetscCall(MatHasOperation(a->A,op,has));
31788b9382cfSStefano Zampini   PetscFunctionReturn(0);
31798b9382cfSStefano Zampini }
31808b9382cfSStefano Zampini 
3181e432b41dSStefano Zampini static PetscErrorCode MatSetValuesCOO_IS(Mat A,const PetscScalar v[],InsertMode imode)
3182e432b41dSStefano Zampini {
3183e432b41dSStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
3184e432b41dSStefano Zampini 
3185e432b41dSStefano Zampini   PetscFunctionBegin;
31869566063dSJacob Faibussowitsch   PetscCall(MatSetValuesCOO(a->A,v,imode));
31879566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY));
31889566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY));
3189e432b41dSStefano Zampini   PetscFunctionReturn(0);
3190e432b41dSStefano Zampini }
3191e432b41dSStefano Zampini 
3192e432b41dSStefano Zampini static PetscErrorCode MatSetPreallocationCOOLocal_IS(Mat A,PetscCount ncoo,PetscInt coo_i[],PetscInt coo_j[])
3193e432b41dSStefano Zampini {
3194e432b41dSStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
3195e432b41dSStefano Zampini 
3196e432b41dSStefano Zampini   PetscFunctionBegin;
3197e432b41dSStefano Zampini   PetscCheck(a->A,PetscObjectComm((PetscObject)A),PETSC_ERR_ORDER,"Need to provide l2g map first via MatSetLocalToGlobalMapping");
3198e432b41dSStefano Zampini   if (a->A->rmap->mapping || a->A->cmap->mapping) {
31999566063dSJacob Faibussowitsch     PetscCall(MatSetPreallocationCOOLocal(a->A,ncoo,coo_i,coo_j));
3200e432b41dSStefano Zampini   } else {
32019566063dSJacob Faibussowitsch     PetscCall(MatSetPreallocationCOO(a->A,ncoo,coo_i,coo_j));
3202e432b41dSStefano Zampini   }
32039566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetValuesCOO_C",MatSetValuesCOO_IS));
3204e432b41dSStefano Zampini   A->preallocated = PETSC_TRUE;
3205e432b41dSStefano Zampini   PetscFunctionReturn(0);
3206e432b41dSStefano Zampini }
3207e432b41dSStefano Zampini 
3208e432b41dSStefano Zampini static PetscErrorCode MatSetPreallocationCOO_IS(Mat A,PetscCount ncoo,const PetscInt coo_i[],const PetscInt coo_j[])
3209e432b41dSStefano Zampini {
3210e432b41dSStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
3211e432b41dSStefano Zampini   PetscInt       *coo_il, *coo_jl, incoo;
3212e432b41dSStefano Zampini 
3213e432b41dSStefano Zampini   PetscFunctionBegin;
3214e432b41dSStefano Zampini   PetscCheck(a->A,PetscObjectComm((PetscObject)A),PETSC_ERR_ORDER,"Need to provide l2g map first via MatSetLocalToGlobalMapping");
3215e432b41dSStefano 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);
32169566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(ncoo,&coo_il,ncoo,&coo_jl));
32179566063dSJacob Faibussowitsch   PetscCall(ISGlobalToLocalMappingApply(a->rmapping,IS_GTOLM_MASK,ncoo,coo_i,&incoo,coo_il));
32189566063dSJacob Faibussowitsch   PetscCall(ISGlobalToLocalMappingApply(a->cmapping,IS_GTOLM_MASK,ncoo,coo_j,&incoo,coo_jl));
32199566063dSJacob Faibussowitsch   PetscCall(MatSetPreallocationCOO(a->A,ncoo,coo_il,coo_jl));
32209566063dSJacob Faibussowitsch   PetscCall(PetscFree2(coo_il,coo_jl));
32219566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetValuesCOO_C",MatSetValuesCOO_IS));
3222e432b41dSStefano Zampini   A->preallocated = PETSC_TRUE;
3223e432b41dSStefano Zampini   PetscFunctionReturn(0);
3224e432b41dSStefano Zampini }
3225e432b41dSStefano Zampini 
3226e432b41dSStefano Zampini /*@
3227e432b41dSStefano Zampini    MatISGetLocalToGlobalMapping - Gets the local-to-global numbering of the MATIS object
3228e432b41dSStefano Zampini 
3229e432b41dSStefano Zampini    Not Collective
3230e432b41dSStefano Zampini 
3231e432b41dSStefano Zampini    Input Parameter:
3232e432b41dSStefano Zampini .  A - the matrix
3233e432b41dSStefano Zampini 
3234e432b41dSStefano Zampini    Output Parameters:
3235e432b41dSStefano Zampini +  rmapping - row mapping
3236e432b41dSStefano Zampini -  cmapping - column mapping
3237e432b41dSStefano Zampini 
3238e432b41dSStefano 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.
3239e432b41dSStefano Zampini 
3240e432b41dSStefano Zampini    Level: advanced
3241e432b41dSStefano Zampini 
3242e432b41dSStefano Zampini .seealso:  MatSetLocalToGlobalMapping()
3243e432b41dSStefano Zampini @*/
3244e432b41dSStefano Zampini PetscErrorCode MatISGetLocalToGlobalMapping(Mat A,ISLocalToGlobalMapping *rmapping,ISLocalToGlobalMapping *cmapping)
3245e432b41dSStefano Zampini {
3246e432b41dSStefano Zampini   PetscFunctionBegin;
3247e432b41dSStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3248e432b41dSStefano Zampini   PetscValidType(A,1);
3249e432b41dSStefano Zampini   if (rmapping) PetscValidPointer(rmapping,2);
3250e432b41dSStefano Zampini   if (cmapping) PetscValidPointer(cmapping,3);
3251cac4c232SBarry Smith   PetscUseMethod(A,"MatISGetLocalToGlobalMapping_C",(Mat,ISLocalToGlobalMapping*,ISLocalToGlobalMapping*),(A,rmapping,cmapping));
3252e432b41dSStefano Zampini   PetscFunctionReturn(0);
3253e432b41dSStefano Zampini }
3254e432b41dSStefano Zampini 
3255e432b41dSStefano Zampini static PetscErrorCode MatISGetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping *r, ISLocalToGlobalMapping *c)
3256e432b41dSStefano Zampini {
3257e432b41dSStefano Zampini   Mat_IS *a = (Mat_IS*)A->data;
3258e432b41dSStefano Zampini 
3259e432b41dSStefano Zampini   PetscFunctionBegin;
3260e432b41dSStefano Zampini   if (r) *r = a->rmapping;
3261e432b41dSStefano Zampini   if (c) *c = a->cmapping;
3262e432b41dSStefano Zampini   PetscFunctionReturn(0);
3263e432b41dSStefano Zampini }
3264e432b41dSStefano Zampini 
3265b4319ba4SBarry Smith /*MC
3266f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
3267b89f26deSStefano Zampini    This stores the matrices in globally unassembled form. Each processor assembles only its local Neumann problem and the parallel matrix vector
3268b4319ba4SBarry Smith    product is handled "implicitly".
3269b4319ba4SBarry Smith 
3270b4319ba4SBarry Smith    Options Database Keys:
327175d48cdbSStefano Zampini + -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
327275d48cdbSStefano Zampini . -matis_fixempty - Fixes local matrices in case of empty local rows/columns.
327375d48cdbSStefano Zampini - -matis_storel2l - stores the local-to-local operators generated by the Galerkin process of MatPtAP().
3274b4319ba4SBarry Smith 
327595452b02SPatrick Sanan    Notes:
327695452b02SPatrick Sanan     Options prefix for the inner matrix are given by -is_mat_xxx
3277b4319ba4SBarry Smith 
3278b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
3279b4319ba4SBarry Smith 
3280b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
3281eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
3282b4319ba4SBarry Smith 
3283b4319ba4SBarry Smith   Level: advanced
3284b4319ba4SBarry Smith 
3285f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
3286b4319ba4SBarry Smith 
3287b4319ba4SBarry Smith M*/
32888cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
3289b4319ba4SBarry Smith {
3290e432b41dSStefano Zampini   Mat_IS         *a;
3291b4319ba4SBarry Smith 
3292b4319ba4SBarry Smith   PetscFunctionBegin;
32939566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(A,&a));
32949566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATAIJ,&a->lmattype));
3295e432b41dSStefano Zampini   A->data = (void*)a;
3296b4319ba4SBarry Smith 
3297e176bc59SStefano Zampini   /* matrix ops */
32989566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(A->ops,sizeof(struct _MatOps)));
3299b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
33002e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
33012e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
33022e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
3303b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
3304b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
33052e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
330698921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
3307b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
3308f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
33092e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
3310f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
3311b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
3312b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
3313b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
33146726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
33152e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
33162e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
33176726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
331869796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
331969796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
332045471136SStefano Zampini   A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS;
3321ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
33226bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
33232b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
3324659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
33257dae84e0SHong Zhang   A->ops->createsubmatrix         = MatCreateSubMatrix_IS;
3326f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
33273fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
33283fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
3329d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
33307fa8f2d3SStefano Zampini   A->ops->getinfo                 = MatGetInfo_IS;
3331ad219c80Sstefano_zampini   A->ops->diagonalscale           = MatDiagonalScale_IS;
3332872cf891SStefano Zampini   A->ops->setfromoptions          = MatSetFromOptions_IS;
3333fc989267SStefano Zampini   A->ops->setup                   = MatSetUp_IS;
33348b9382cfSStefano Zampini   A->ops->hasoperation            = MatHasOperation_IS;
3335b4319ba4SBarry Smith 
3336b7ce53b6SStefano Zampini   /* special MATIS functions */
33379566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMatType_C",MatISSetLocalMatType_IS));
33389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS));
33399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISRestoreLocalMat_C",MatISRestoreLocalMat_IS));
33409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS));
33419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatConvert_IS_XAIJ));
33429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS));
33439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",MatISStoreL2L_IS));
33449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",MatISFixLocalEmpty_IS));
33459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalToGlobalMapping_C",MatISGetLocalToGlobalMapping_IS));
33469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",MatConvert_IS_XAIJ));
33479566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",MatConvert_IS_XAIJ));
33489566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",MatConvert_IS_XAIJ));
33499566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",MatConvert_IS_XAIJ));
33509566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",MatConvert_IS_XAIJ));
33519566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",MatConvert_IS_XAIJ));
33529566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",MatConvert_IS_XAIJ));
33539566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOOLocal_C",MatSetPreallocationCOOLocal_IS));
33549566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOO_C",MatSetPreallocationCOO_IS));
33559566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)A,MATIS));
3356b4319ba4SBarry Smith   PetscFunctionReturn(0);
3357b4319ba4SBarry Smith }
3358