xref: /petsc/src/mat/impls/is/matis.c (revision 7fb60732ccf1806988e9909cd147cdb09c395756)
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 
10d0dbe9f7SStefano Zampini #include <petsc/private/matisimpl.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;
41291d376acSStefano Zampini   PetscObject             dm;
413c9225affSStefano Zampini 
414c9225affSStefano Zampini   PetscFunctionBegin;
415d0609cedSBarry Smith   PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"MatIS l2g disassembling options","Mat");
4169566063dSJacob 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));
417d0609cedSBarry Smith   PetscOptionsEnd();
418fabe8965SStefano Zampini   if (mode == MAT_IS_DISASSEMBLE_L2G_MAT) {
4199566063dSJacob Faibussowitsch     PetscCall(MatGetLocalToGlobalMapping(A,l2g,NULL));
420c9225affSStefano Zampini     PetscFunctionReturn(0);
421c9225affSStefano Zampini   }
4229566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)A,&comm));
4239566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij));
4249566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A,MATMPIBAIJ,&ismpibaij));
4259566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(A,&bs));
426fabe8965SStefano Zampini   switch (mode) {
427fabe8965SStefano Zampini   case MAT_IS_DISASSEMBLE_L2G_ND:
4289566063dSJacob Faibussowitsch     PetscCall(MatPartitioningCreate(comm,&part));
4299566063dSJacob Faibussowitsch     PetscCall(MatPartitioningSetAdjacency(part,A));
4309566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)part,((PetscObject)A)->prefix));
4319566063dSJacob Faibussowitsch     PetscCall(MatPartitioningSetFromOptions(part));
4329566063dSJacob Faibussowitsch     PetscCall(MatPartitioningApplyND(part,&ndmap));
4339566063dSJacob Faibussowitsch     PetscCall(MatPartitioningDestroy(&part));
4349566063dSJacob Faibussowitsch     PetscCall(ISBuildTwoSided(ndmap,NULL,&ndsub));
4359566063dSJacob Faibussowitsch     PetscCall(MatMPIAIJSetUseScalableIncreaseOverlap(A,PETSC_TRUE));
4369566063dSJacob Faibussowitsch     PetscCall(MatIncreaseOverlap(A,1,&ndsub,1));
4379566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(ndsub,l2g));
438fabe8965SStefano Zampini 
439fabe8965SStefano Zampini     /* it may happen that a separator node is not properly shared */
4409566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetNodeInfo(*l2g,&nl,&ncount,NULL));
4419566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(comm,&sf));
4429566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetIndices(*l2g,&garray));
4439566063dSJacob Faibussowitsch     PetscCall(PetscSFSetGraphLayout(sf,A->rmap,nl,NULL,PETSC_OWN_POINTER,garray));
4449566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreIndices(*l2g,&garray));
4459566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(A->rmap->n,&ndmapc));
4469566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceBegin(sf,MPIU_INT,ncount,ndmapc,MPI_REPLACE));
4479566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceEnd(sf,MPIU_INT,ncount,ndmapc,MPI_REPLACE));
4489566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(*l2g,NULL,&ncount,NULL));
4499566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(ndmap,&ndmapi));
450fabe8965SStefano Zampini     for (i = 0, cnt = 0; i < A->rmap->n; i++)
451fabe8965SStefano Zampini       if (ndmapi[i] < 0 && ndmapc[i] < 2)
452fabe8965SStefano Zampini         cnt++;
453fabe8965SStefano Zampini 
4541c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&cnt,&i,1,MPIU_INT,MPI_MAX,comm));
455fabe8965SStefano Zampini     if (i) { /* we detected isolated separator nodes */
456fabe8965SStefano Zampini       Mat                    A2,A3;
457fabe8965SStefano Zampini       IS                     *workis,is2;
458fabe8965SStefano Zampini       PetscScalar            *vals;
459fabe8965SStefano Zampini       PetscInt               gcnt = i,*dnz,*onz,j,*lndmapi;
460fabe8965SStefano Zampini       ISLocalToGlobalMapping ll2g;
461fabe8965SStefano Zampini       PetscBool              flg;
462fabe8965SStefano Zampini       const PetscInt         *ii,*jj;
463fabe8965SStefano Zampini 
464fabe8965SStefano Zampini       /* communicate global id of separators */
465d0609cedSBarry Smith       MatPreallocateBegin(comm,A->rmap->n,A->cmap->n,dnz,onz);
466fabe8965SStefano Zampini       for (i = 0, cnt = 0; i < A->rmap->n; i++)
467fabe8965SStefano Zampini         dnz[i] = ndmapi[i] < 0 ? i + A->rmap->rstart : -1;
468fabe8965SStefano Zampini 
4699566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nl,&lndmapi));
4709566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastBegin(sf,MPIU_INT,dnz,lndmapi,MPI_REPLACE));
471fabe8965SStefano Zampini 
472fabe8965SStefano Zampini       /* compute adjacency of isolated separators node */
4739566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(gcnt,&workis));
474fabe8965SStefano Zampini       for (i = 0, cnt = 0; i < A->rmap->n; i++) {
475fabe8965SStefano Zampini         if (ndmapi[i] < 0 && ndmapc[i] < 2) {
4769566063dSJacob Faibussowitsch           PetscCall(ISCreateStride(comm,1,i+A->rmap->rstart,1,&workis[cnt++]));
477fabe8965SStefano Zampini         }
478fabe8965SStefano Zampini       }
479fabe8965SStefano Zampini       for (i = cnt; i < gcnt; i++) {
4809566063dSJacob Faibussowitsch         PetscCall(ISCreateStride(comm,0,0,1,&workis[i]));
481fabe8965SStefano Zampini       }
482fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
4839566063dSJacob Faibussowitsch         PetscCall(PetscObjectSetName((PetscObject)workis[i],"ISOLATED"));
4849566063dSJacob Faibussowitsch         PetscCall(ISViewFromOptions(workis[i],NULL,"-view_isolated_separators"));
485fabe8965SStefano Zampini       }
486fabe8965SStefano Zampini 
487fabe8965SStefano Zampini       /* no communications since all the ISes correspond to locally owned rows */
4889566063dSJacob Faibussowitsch       PetscCall(MatIncreaseOverlap(A,gcnt,workis,1));
489fabe8965SStefano Zampini 
490fabe8965SStefano Zampini       /* end communicate global id of separators */
4919566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastEnd(sf,MPIU_INT,dnz,lndmapi,MPI_REPLACE));
492fabe8965SStefano Zampini 
493fabe8965SStefano Zampini       /* communicate new layers : create a matrix and transpose it */
4949566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(dnz,A->rmap->n));
4959566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(onz,A->rmap->n));
496fabe8965SStefano Zampini       for (i = 0, j = 0; i < A->rmap->n; i++) {
497fabe8965SStefano Zampini         if (ndmapi[i] < 0 && ndmapc[i] < 2) {
498fabe8965SStefano Zampini           const PetscInt* idxs;
499fabe8965SStefano Zampini           PetscInt        s;
500fabe8965SStefano Zampini 
5019566063dSJacob Faibussowitsch           PetscCall(ISGetLocalSize(workis[j],&s));
5029566063dSJacob Faibussowitsch           PetscCall(ISGetIndices(workis[j],&idxs));
5039566063dSJacob Faibussowitsch           PetscCall(MatPreallocateSet(i+A->rmap->rstart,s,idxs,dnz,onz));
504fabe8965SStefano Zampini           j++;
505fabe8965SStefano Zampini         }
506fabe8965SStefano Zampini       }
50708401ef6SPierre Jolivet       PetscCheck(j == cnt,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected local count %" PetscInt_FMT " != %" PetscInt_FMT,j,cnt);
508fabe8965SStefano Zampini 
509fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
5109566063dSJacob Faibussowitsch         PetscCall(PetscObjectSetName((PetscObject)workis[i],"EXTENDED"));
5119566063dSJacob Faibussowitsch         PetscCall(ISViewFromOptions(workis[i],NULL,"-view_isolated_separators"));
512fabe8965SStefano Zampini       }
513fabe8965SStefano Zampini 
514fabe8965SStefano Zampini       for (i = 0, j = 0; i < A->rmap->n; i++) j = PetscMax(j,dnz[i]+onz[i]);
5159566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(j,&vals));
516fabe8965SStefano Zampini       for (i = 0; i < j; i++) vals[i] = 1.0;
517fabe8965SStefano Zampini 
5189566063dSJacob Faibussowitsch       PetscCall(MatCreate(comm,&A2));
5199566063dSJacob Faibussowitsch       PetscCall(MatSetType(A2,MATMPIAIJ));
5209566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(A2,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N));
5219566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJSetPreallocation(A2,0,dnz,0,onz));
5229566063dSJacob Faibussowitsch       PetscCall(MatSetOption(A2,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE));
523fabe8965SStefano Zampini       for (i = 0, j = 0; i < A2->rmap->n; i++) {
524fabe8965SStefano Zampini         PetscInt        row = i+A2->rmap->rstart,s = dnz[i] + onz[i];
525fabe8965SStefano Zampini         const PetscInt* idxs;
526fabe8965SStefano Zampini 
527fabe8965SStefano Zampini         if (s) {
5289566063dSJacob Faibussowitsch           PetscCall(ISGetIndices(workis[j],&idxs));
5299566063dSJacob Faibussowitsch           PetscCall(MatSetValues(A2,1,&row,s,idxs,vals,INSERT_VALUES));
5309566063dSJacob Faibussowitsch           PetscCall(ISRestoreIndices(workis[j],&idxs));
531fabe8965SStefano Zampini           j++;
532fabe8965SStefano Zampini         }
533fabe8965SStefano Zampini       }
53408401ef6SPierre Jolivet       PetscCheck(j == cnt,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected local count %" PetscInt_FMT " != %" PetscInt_FMT,j,cnt);
5359566063dSJacob Faibussowitsch       PetscCall(PetscFree(vals));
5369566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A2,MAT_FINAL_ASSEMBLY));
5379566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A2,MAT_FINAL_ASSEMBLY));
5389566063dSJacob Faibussowitsch       PetscCall(MatTranspose(A2,MAT_INPLACE_MATRIX,&A2));
539fabe8965SStefano Zampini 
540fabe8965SStefano Zampini       /* extract submatrix corresponding to the coupling "owned separators" x "isolated separators" */
541fabe8965SStefano Zampini       for (i = 0, j = 0; i < nl; i++)
542fabe8965SStefano Zampini         if (lndmapi[i] >= 0) lndmapi[j++] = lndmapi[i];
5439566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(comm,j,lndmapi,PETSC_USE_POINTER,&is));
5449566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJGetLocalMatCondensed(A2,MAT_INITIAL_MATRIX,&is,NULL,&A3));
5459566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is));
5469566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&A2));
547fabe8965SStefano Zampini 
548fabe8965SStefano Zampini       /* extend local to global map to include connected isolated separators */
5499566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)A3,"_petsc_GetLocalMatCondensed_iscol",(PetscObject*)&is));
55028b400f6SJacob Faibussowitsch       PetscCheck(is,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing column map");
5519566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreateIS(is,&ll2g));
5529566063dSJacob Faibussowitsch       PetscCall(MatGetRowIJ(A3,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&flg));
55328b400f6SJacob Faibussowitsch       PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
5549566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF,ii[i],jj,PETSC_COPY_VALUES,&is));
5559566063dSJacob Faibussowitsch       PetscCall(MatRestoreRowIJ(A3,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&flg));
55628b400f6SJacob Faibussowitsch       PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
5579566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingApplyIS(ll2g,is,&is2));
5589566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is));
5599566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingDestroy(&ll2g));
560fabe8965SStefano Zampini 
561fabe8965SStefano Zampini       /* add new nodes to the local-to-global map */
5629566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingDestroy(l2g));
5639566063dSJacob Faibussowitsch       PetscCall(ISExpand(ndsub,is2,&is));
5649566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is2));
5659566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreateIS(is,l2g));
5669566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is));
567fabe8965SStefano Zampini 
5689566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&A3));
5699566063dSJacob Faibussowitsch       PetscCall(PetscFree(lndmapi));
570d0609cedSBarry Smith       MatPreallocateEnd(dnz,onz);
571fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
5729566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&workis[i]));
573fabe8965SStefano Zampini       }
5749566063dSJacob Faibussowitsch       PetscCall(PetscFree(workis));
575fabe8965SStefano Zampini     }
5769566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(ndmap,&ndmapi));
5779566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sf));
5789566063dSJacob Faibussowitsch     PetscCall(PetscFree(ndmapc));
5799566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&ndmap));
5809566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&ndsub));
5819566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingSetBlockSize(*l2g,bs));
5829566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingViewFromOptions(*l2g,NULL,"-matis_nd_l2g_view"));
583fabe8965SStefano Zampini     break;
584fabe8965SStefano Zampini   case MAT_IS_DISASSEMBLE_L2G_NATURAL:
58591d376acSStefano Zampini     PetscCall(PetscObjectQuery((PetscObject)A,"__PETSc_dm",(PetscObject*)&dm));
58691d376acSStefano Zampini     if (dm) { /* if a matrix comes from a DM, most likely we can use the l2gmap if any */
58791d376acSStefano Zampini       PetscCall(MatGetLocalToGlobalMapping(A,l2g,NULL));
58891d376acSStefano Zampini       PetscCall(PetscObjectReference((PetscObject)*l2g));
58991d376acSStefano Zampini       if (*l2g) PetscFunctionReturn(0);
59091d376acSStefano Zampini     }
591fabe8965SStefano Zampini     if (ismpiaij) {
5929566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJGetSeqAIJ(A,&Ad,&Ao,&garray));
593fabe8965SStefano Zampini     } else if (ismpibaij) {
5949566063dSJacob Faibussowitsch       PetscCall(MatMPIBAIJGetSeqBAIJ(A,&Ad,&Ao,&garray));
59598921bdaSJacob Faibussowitsch     } else SETERRQ(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name);
596c9225affSStefano Zampini     if (A->rmap->n) {
597fabe8965SStefano Zampini       PetscInt dc,oc,stc,*aux;
598c9225affSStefano Zampini 
599ebf8cefbSJunchao Zhang       PetscCall(MatGetLocalSize(Ad,NULL,&dc));
6009566063dSJacob Faibussowitsch       PetscCall(MatGetLocalSize(Ao,NULL,&oc));
601d0dbe9f7SStefano Zampini       PetscCheck(!oc || garray,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"garray not present");
6029566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRangeColumn(A,&stc,NULL));
6039566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1((dc+oc)/bs,&aux));
604c9225affSStefano Zampini       for (i=0; i<dc/bs; i++) aux[i]       = i+stc/bs;
605ebf8cefbSJunchao Zhang       for (i=0; i<oc/bs; i++) aux[i+dc/bs] = (ismpiaij ? garray[i*bs]/bs : garray[i]);
6069566063dSJacob Faibussowitsch       PetscCall(ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is));
607c9225affSStefano Zampini     } else {
6089566063dSJacob Faibussowitsch       PetscCall(ISCreateBlock(comm,1,0,NULL,PETSC_OWN_POINTER,&is));
609c9225affSStefano Zampini     }
6109566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is,l2g));
6119566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
612fabe8965SStefano Zampini     break;
613fabe8965SStefano Zampini   default:
61498921bdaSJacob Faibussowitsch     SETERRQ(comm,PETSC_ERR_ARG_WRONG,"Unsupported l2g disassembling type %d",mode);
615c9225affSStefano Zampini   }
616c9225affSStefano Zampini   PetscFunctionReturn(0);
617c9225affSStefano Zampini }
618c9225affSStefano Zampini 
619c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
620c9225affSStefano Zampini {
621c9225affSStefano Zampini   Mat                    lA,Ad,Ao,B = NULL;
6226989cf23SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
6236989cf23SStefano Zampini   IS                     is;
6246989cf23SStefano Zampini   MPI_Comm               comm;
6256989cf23SStefano Zampini   void                   *ptrs[2];
6266989cf23SStefano Zampini   const char             *names[2] = {"_convert_csr_aux","_convert_csr_data"};
627c9225affSStefano Zampini   const PetscInt         *garray;
6286989cf23SStefano Zampini   PetscScalar            *dd,*od,*aa,*data;
629c9225affSStefano Zampini   const PetscInt         *di,*dj,*oi,*oj;
630c9225affSStefano Zampini   const PetscInt         *odi,*odj,*ooi,*ooj;
6316989cf23SStefano Zampini   PetscInt               *aux,*ii,*jj;
632c9225affSStefano Zampini   PetscInt               bs,lc,dr,dc,oc,str,stc,nnz,i,jd,jo,cum;
633c9225affSStefano Zampini   PetscBool              flg,ismpiaij,ismpibaij,was_inplace = PETSC_FALSE;
634c9225affSStefano Zampini   PetscMPIInt            size;
6356989cf23SStefano Zampini 
636ab4d48faSStefano Zampini   PetscFunctionBegin;
6379566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)A,&comm));
6389566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm,&size));
639c9225affSStefano Zampini   if (size == 1) {
6409566063dSJacob Faibussowitsch     PetscCall(MatConvert_SeqXAIJ_IS(A,type,reuse,newmat));
641c9225affSStefano Zampini     PetscFunctionReturn(0);
642c9225affSStefano Zampini   }
643c9225affSStefano Zampini   if (reuse != MAT_REUSE_MATRIX && A->cmap->N == A->rmap->N) {
6449566063dSJacob Faibussowitsch     PetscCall(MatMPIXAIJComputeLocalToGlobalMapping_Private(A,&rl2g));
6459566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm,&B));
6469566063dSJacob Faibussowitsch     PetscCall(MatSetType(B,MATIS));
6479566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N));
6489566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(B,rl2g,rl2g));
6499566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(A,&bs));
6509566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSize(B,bs));
6519566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
652c9225affSStefano Zampini     if (reuse == MAT_INPLACE_MATRIX) was_inplace = PETSC_TRUE;
653c9225affSStefano Zampini     reuse = MAT_REUSE_MATRIX;
654c9225affSStefano Zampini   }
655c9225affSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
656c9225affSStefano Zampini     Mat            *newlA, lA;
657c9225affSStefano Zampini     IS             rows, cols;
658c9225affSStefano Zampini     const PetscInt *ridx, *cidx;
659c9225affSStefano Zampini     PetscInt       rbs, cbs, nr, nc;
660c9225affSStefano Zampini 
661c9225affSStefano Zampini     if (!B) B = *newmat;
6629566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalToGlobalMapping(B,&rl2g,&cl2g));
6639566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockIndices(rl2g,&ridx));
6649566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockIndices(cl2g,&cidx));
6659566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetSize(rl2g,&nr));
6669566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetSize(cl2g,&nc));
6679566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockSize(rl2g,&rbs));
6689566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockSize(cl2g,&cbs));
6699566063dSJacob Faibussowitsch     PetscCall(ISCreateBlock(comm,rbs,nr/rbs,ridx,PETSC_USE_POINTER,&rows));
670c9225affSStefano Zampini     if (rl2g != cl2g) {
6719566063dSJacob Faibussowitsch       PetscCall(ISCreateBlock(comm,cbs,nc/cbs,cidx,PETSC_USE_POINTER,&cols));
672c9225affSStefano Zampini     } else {
6739566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)rows));
674c9225affSStefano Zampini       cols = rows;
675c9225affSStefano Zampini     }
6769566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(B,&lA));
6779566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrices(A,1,&rows,&cols,MAT_INITIAL_MATRIX,&newlA));
6789566063dSJacob Faibussowitsch     PetscCall(MatConvert(newlA[0],MATSEQAIJ,MAT_INPLACE_MATRIX,&newlA[0]));
6799566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(rl2g,&ridx));
6809566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(cl2g,&cidx));
6819566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&rows));
6829566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&cols));
683c9225affSStefano Zampini     if (!lA->preallocated) { /* first time */
6849566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(newlA[0],MAT_COPY_VALUES,&lA));
6859566063dSJacob Faibussowitsch       PetscCall(MatISSetLocalMat(B,lA));
6869566063dSJacob Faibussowitsch       PetscCall(PetscObjectDereference((PetscObject)lA));
687c9225affSStefano Zampini     }
6889566063dSJacob Faibussowitsch     PetscCall(MatCopy(newlA[0],lA,SAME_NONZERO_PATTERN));
6899566063dSJacob Faibussowitsch     PetscCall(MatDestroySubMatrices(1,&newlA));
6909566063dSJacob Faibussowitsch     PetscCall(MatISScaleDisassembling_Private(B));
6919566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
6929566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
6939566063dSJacob Faibussowitsch     if (was_inplace) PetscCall(MatHeaderReplace(A,&B));
694c9225affSStefano Zampini     else *newmat = B;
695c9225affSStefano Zampini     PetscFunctionReturn(0);
696c9225affSStefano Zampini   }
697c9225affSStefano Zampini   /* rectangular case, just compress out the column space */
6989566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij));
6999566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A,MATMPIBAIJ,&ismpibaij));
700c9225affSStefano Zampini   if (ismpiaij) {
701c9225affSStefano Zampini     bs   = 1;
7029566063dSJacob Faibussowitsch     PetscCall(MatMPIAIJGetSeqAIJ(A,&Ad,&Ao,&garray));
703c9225affSStefano Zampini   } else if (ismpibaij) {
7049566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(A,&bs));
7059566063dSJacob Faibussowitsch     PetscCall(MatMPIBAIJGetSeqBAIJ(A,&Ad,&Ao,&garray));
7069566063dSJacob Faibussowitsch     PetscCall(MatConvert(Ad,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ad));
7079566063dSJacob Faibussowitsch     PetscCall(MatConvert(Ao,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ao));
70898921bdaSJacob Faibussowitsch   } else SETERRQ(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name);
7099566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(Ad,&dd));
7109566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(Ao,&od));
71128b400f6SJacob Faibussowitsch   PetscCheck(garray,comm,PETSC_ERR_ARG_WRONGSTATE,"garray not present");
7126989cf23SStefano Zampini 
7136989cf23SStefano Zampini   /* access relevant information from MPIAIJ */
7149566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A,&str,NULL));
7159566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRangeColumn(A,&stc,NULL));
7169566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A,&dr,&dc));
7179566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(Ao,NULL,&oc));
7189566063dSJacob Faibussowitsch   PetscCall(MatGetRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&di,&dj,&flg));
71928b400f6SJacob Faibussowitsch   PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
7209566063dSJacob Faibussowitsch   PetscCall(MatGetRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&oi,&oj,&flg));
72128b400f6SJacob Faibussowitsch   PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
722c9225affSStefano Zampini   nnz = di[dr] + oi[dr];
723c9225affSStefano Zampini   /* store original pointers to be restored later */
724c9225affSStefano Zampini   odi = di; odj = dj; ooi = oi; ooj = oj;
7256989cf23SStefano Zampini 
7266989cf23SStefano Zampini   /* generate l2g maps for rows and cols */
7279566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(comm,dr/bs,str/bs,1,&is));
728c9225affSStefano Zampini   if (bs > 1) {
729c9225affSStefano Zampini     IS is2;
730c9225affSStefano Zampini 
7319566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(is,&i));
7329566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is,(const PetscInt**)&aux));
7339566063dSJacob Faibussowitsch     PetscCall(ISCreateBlock(comm,bs,i,aux,PETSC_COPY_VALUES,&is2));
7349566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(is,(const PetscInt**)&aux));
7359566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
736c9225affSStefano Zampini     is   = is2;
737c9225affSStefano Zampini   }
7389566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(is,&rl2g));
7399566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
740e363d98aSStefano Zampini   if (dr) {
7419566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1((dc+oc)/bs,&aux));
742c9225affSStefano Zampini     for (i=0; i<dc/bs; i++) aux[i]       = i+stc/bs;
743c9225affSStefano Zampini     for (i=0; i<oc/bs; i++) aux[i+dc/bs] = garray[i];
7449566063dSJacob Faibussowitsch     PetscCall(ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is));
745e363d98aSStefano Zampini     lc   = dc+oc;
746e363d98aSStefano Zampini   } else {
7479566063dSJacob Faibussowitsch     PetscCall(ISCreateBlock(comm,bs,0,NULL,PETSC_OWN_POINTER,&is));
748e363d98aSStefano Zampini     lc   = 0;
749e363d98aSStefano Zampini   }
7509566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(is,&cl2g));
7519566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
7526989cf23SStefano Zampini 
7536989cf23SStefano Zampini   /* create MATIS object */
7549566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm,&B));
7559566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(B,dr,dc,PETSC_DECIDE,PETSC_DECIDE));
7569566063dSJacob Faibussowitsch   PetscCall(MatSetType(B,MATIS));
7579566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(B,bs));
7589566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(B,rl2g,cl2g));
7599566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
7609566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
7616989cf23SStefano Zampini 
7626989cf23SStefano Zampini   /* merge local matrices */
7639566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nnz+dr+1,&aux));
7649566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nnz,&data));
7656989cf23SStefano Zampini   ii   = aux;
7666989cf23SStefano Zampini   jj   = aux+dr+1;
7676989cf23SStefano Zampini   aa   = data;
7686989cf23SStefano Zampini   *ii  = *(di++) + *(oi++);
7696989cf23SStefano Zampini   for (jd=0,jo=0,cum=0;*ii<nnz;cum++)
7706989cf23SStefano Zampini   {
7716989cf23SStefano Zampini      for (;jd<*di;jd++) { *jj++ = *dj++;      *aa++ = *dd++; }
7726989cf23SStefano Zampini      for (;jo<*oi;jo++) { *jj++ = *oj++ + dc; *aa++ = *od++; }
7736989cf23SStefano Zampini      *(++ii) = *(di++) + *(oi++);
7746989cf23SStefano Zampini   }
7756989cf23SStefano Zampini   for (;cum<dr;cum++) *(++ii) = nnz;
776c9225affSStefano Zampini 
7779566063dSJacob Faibussowitsch   PetscCall(MatRestoreRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&odi,&odj,&flg));
77828b400f6SJacob Faibussowitsch   PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
7799566063dSJacob Faibussowitsch   PetscCall(MatRestoreRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&ooi,&ooj,&flg));
78028b400f6SJacob Faibussowitsch   PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
7819566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(Ad,&dd));
7829566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(Ao,&od));
783c9225affSStefano Zampini 
7846989cf23SStefano Zampini   ii   = aux;
7856989cf23SStefano Zampini   jj   = aux+dr+1;
7866989cf23SStefano Zampini   aa   = data;
7879566063dSJacob Faibussowitsch   PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,lc,ii,jj,aa,&lA));
7886989cf23SStefano Zampini 
7896989cf23SStefano Zampini   /* create containers to destroy the data */
7906989cf23SStefano Zampini   ptrs[0] = aux;
7916989cf23SStefano Zampini   ptrs[1] = data;
7926989cf23SStefano Zampini   for (i=0; i<2; i++) {
7936989cf23SStefano Zampini     PetscContainer c;
7946989cf23SStefano Zampini 
7959566063dSJacob Faibussowitsch     PetscCall(PetscContainerCreate(PETSC_COMM_SELF,&c));
7969566063dSJacob Faibussowitsch     PetscCall(PetscContainerSetPointer(c,ptrs[i]));
7979566063dSJacob Faibussowitsch     PetscCall(PetscContainerSetUserDestroy(c,PetscContainerUserDestroyDefault));
7989566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)lA,names[i],(PetscObject)c));
7999566063dSJacob Faibussowitsch     PetscCall(PetscContainerDestroy(&c));
8006989cf23SStefano Zampini   }
801c9225affSStefano Zampini   if (ismpibaij) { /* destroy converted local matrices */
8029566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Ad));
8039566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Ao));
804c9225affSStefano Zampini   }
8056989cf23SStefano Zampini 
8066989cf23SStefano Zampini   /* finalize matrix */
8079566063dSJacob Faibussowitsch   PetscCall(MatISSetLocalMat(B,lA));
8089566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&lA));
8099566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
8109566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
811c9225affSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
8129566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(A,&B));
813c9225affSStefano Zampini   } else *newmat = B;
8146989cf23SStefano Zampini   PetscFunctionReturn(0);
8156989cf23SStefano Zampini }
8166989cf23SStefano Zampini 
8175e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
8185e3038f0Sstefano_zampini {
8195e3038f0Sstefano_zampini   Mat                    **nest,*snest,**rnest,lA,B;
8205e3038f0Sstefano_zampini   IS                     *iscol,*isrow,*islrow,*islcol;
8215e3038f0Sstefano_zampini   ISLocalToGlobalMapping rl2g,cl2g;
8225e3038f0Sstefano_zampini   MPI_Comm               comm;
8235b003df0Sstefano_zampini   PetscInt               *lr,*lc,*l2gidxs;
8245b003df0Sstefano_zampini   PetscInt               i,j,nr,nc,rbs,cbs;
8259e7b2b25Sstefano_zampini   PetscBool              convert,lreuse,*istrans;
8265e3038f0Sstefano_zampini 
827ab4d48faSStefano Zampini   PetscFunctionBegin;
8289566063dSJacob Faibussowitsch   PetscCall(MatNestGetSubMats(A,&nr,&nc,&nest));
8295e3038f0Sstefano_zampini   lreuse = PETSC_FALSE;
8305e3038f0Sstefano_zampini   rnest  = NULL;
8315e3038f0Sstefano_zampini   if (reuse == MAT_REUSE_MATRIX) {
8325e3038f0Sstefano_zampini     PetscBool ismatis,isnest;
8335e3038f0Sstefano_zampini 
8349566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis));
83528b400f6SJacob Faibussowitsch     PetscCheck(ismatis,PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type_name);
8369566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(*newmat,&lA));
8379566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest));
8385e3038f0Sstefano_zampini     if (isnest) {
8399566063dSJacob Faibussowitsch       PetscCall(MatNestGetSubMats(lA,&i,&j,&rnest));
8405e3038f0Sstefano_zampini       lreuse = (PetscBool)(i == nr && j == nc);
8415e3038f0Sstefano_zampini       if (!lreuse) rnest = NULL;
8425e3038f0Sstefano_zampini     }
8435e3038f0Sstefano_zampini   }
8449566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)A,&comm));
8459566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(nr,&lr,nc,&lc));
8469566063dSJacob Faibussowitsch   PetscCall(PetscCalloc6(nr,&isrow,nc,&iscol,nr,&islrow,nc,&islcol,nr*nc,&snest,nr*nc,&istrans));
8479566063dSJacob Faibussowitsch   PetscCall(MatNestGetISs(A,isrow,iscol));
8485e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
8495e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
8505e3038f0Sstefano_zampini       PetscBool ismatis;
8519e7b2b25Sstefano_zampini       PetscInt  l1,l2,lb1,lb2,ij=i*nc+j;
8525e3038f0Sstefano_zampini 
8535e3038f0Sstefano_zampini       /* Null matrix pointers are allowed in MATNEST */
8545e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
8555e3038f0Sstefano_zampini 
8565e3038f0Sstefano_zampini       /* Nested matrices should be of type MATIS */
8579566063dSJacob Faibussowitsch       PetscCall(PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij]));
8589e7b2b25Sstefano_zampini       if (istrans[ij]) {
8599e7b2b25Sstefano_zampini         Mat T,lT;
8609566063dSJacob Faibussowitsch         PetscCall(MatTransposeGetMat(nest[i][j],&T));
8619566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis));
86228b400f6SJacob 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);
8639566063dSJacob Faibussowitsch         PetscCall(MatISGetLocalMat(T,&lT));
8649566063dSJacob Faibussowitsch         PetscCall(MatCreateTranspose(lT,&snest[ij]));
8659e7b2b25Sstefano_zampini       } else {
8669566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis));
86728b400f6SJacob 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);
8689566063dSJacob Faibussowitsch         PetscCall(MatISGetLocalMat(nest[i][j],&snest[ij]));
8699e7b2b25Sstefano_zampini       }
8705e3038f0Sstefano_zampini 
8715e3038f0Sstefano_zampini       /* Check compatibility of local sizes */
8729566063dSJacob Faibussowitsch       PetscCall(MatGetSize(snest[ij],&l1,&l2));
8739566063dSJacob Faibussowitsch       PetscCall(MatGetBlockSizes(snest[ij],&lb1,&lb2));
8745e3038f0Sstefano_zampini       if (!l1 || !l2) continue;
875aed4548fSBarry 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);
876aed4548fSBarry 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);
8775e3038f0Sstefano_zampini       lr[i] = l1;
8785e3038f0Sstefano_zampini       lc[j] = l2;
8795e3038f0Sstefano_zampini 
8805e3038f0Sstefano_zampini       /* check compatibilty for local matrix reusage */
8815e3038f0Sstefano_zampini       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
8825e3038f0Sstefano_zampini     }
8835e3038f0Sstefano_zampini   }
8845e3038f0Sstefano_zampini 
88576bd3646SJed Brown   if (PetscDefined (USE_DEBUG)) {
8865e3038f0Sstefano_zampini     /* Check compatibility of l2g maps for rows */
8875e3038f0Sstefano_zampini     for (i=0;i<nr;i++) {
8885e3038f0Sstefano_zampini       rl2g = NULL;
8895e3038f0Sstefano_zampini       for (j=0;j<nc;j++) {
8905e3038f0Sstefano_zampini         PetscInt n1,n2;
8915e3038f0Sstefano_zampini 
8925e3038f0Sstefano_zampini         if (!nest[i][j]) continue;
8939e7b2b25Sstefano_zampini         if (istrans[i*nc+j]) {
8949e7b2b25Sstefano_zampini           Mat T;
8959e7b2b25Sstefano_zampini 
8969566063dSJacob Faibussowitsch           PetscCall(MatTransposeGetMat(nest[i][j],&T));
8979566063dSJacob Faibussowitsch           PetscCall(MatISGetLocalToGlobalMapping(T,NULL,&cl2g));
8989e7b2b25Sstefano_zampini         } else {
8999566063dSJacob Faibussowitsch           PetscCall(MatISGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL));
9009e7b2b25Sstefano_zampini         }
9019566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingGetSize(cl2g,&n1));
9025e3038f0Sstefano_zampini         if (!n1) continue;
9035e3038f0Sstefano_zampini         if (!rl2g) {
9045e3038f0Sstefano_zampini           rl2g = cl2g;
9055e3038f0Sstefano_zampini         } else {
9065e3038f0Sstefano_zampini           const PetscInt *idxs1,*idxs2;
9075e3038f0Sstefano_zampini           PetscBool      same;
9085e3038f0Sstefano_zampini 
9099566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingGetSize(rl2g,&n2));
91008401ef6SPierre 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);
9119566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingGetIndices(cl2g,&idxs1));
9129566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingGetIndices(rl2g,&idxs2));
9139566063dSJacob Faibussowitsch           PetscCall(PetscArraycmp(idxs1,idxs2,n1,&same));
9149566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1));
9159566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2));
91628b400f6SJacob 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);
9175e3038f0Sstefano_zampini         }
9185e3038f0Sstefano_zampini       }
9195e3038f0Sstefano_zampini     }
9205e3038f0Sstefano_zampini     /* Check compatibility of l2g maps for columns */
9215e3038f0Sstefano_zampini     for (i=0;i<nc;i++) {
9225e3038f0Sstefano_zampini       rl2g = NULL;
9235e3038f0Sstefano_zampini       for (j=0;j<nr;j++) {
9245e3038f0Sstefano_zampini         PetscInt n1,n2;
9255e3038f0Sstefano_zampini 
9265e3038f0Sstefano_zampini         if (!nest[j][i]) continue;
9279e7b2b25Sstefano_zampini         if (istrans[j*nc+i]) {
9289e7b2b25Sstefano_zampini           Mat T;
9299e7b2b25Sstefano_zampini 
9309566063dSJacob Faibussowitsch           PetscCall(MatTransposeGetMat(nest[j][i],&T));
9319566063dSJacob Faibussowitsch           PetscCall(MatISGetLocalToGlobalMapping(T,&cl2g,NULL));
9329e7b2b25Sstefano_zampini         } else {
9339566063dSJacob Faibussowitsch           PetscCall(MatISGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g));
9349e7b2b25Sstefano_zampini         }
9359566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingGetSize(cl2g,&n1));
9365e3038f0Sstefano_zampini         if (!n1) continue;
9375e3038f0Sstefano_zampini         if (!rl2g) {
9385e3038f0Sstefano_zampini           rl2g = cl2g;
9395e3038f0Sstefano_zampini         } else {
9405e3038f0Sstefano_zampini           const PetscInt *idxs1,*idxs2;
9415e3038f0Sstefano_zampini           PetscBool      same;
9425e3038f0Sstefano_zampini 
9439566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingGetSize(rl2g,&n2));
94408401ef6SPierre 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);
9459566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingGetIndices(cl2g,&idxs1));
9469566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingGetIndices(rl2g,&idxs2));
9479566063dSJacob Faibussowitsch           PetscCall(PetscArraycmp(idxs1,idxs2,n1,&same));
9489566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1));
9499566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2));
95028b400f6SJacob 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);
9515e3038f0Sstefano_zampini         }
9525e3038f0Sstefano_zampini       }
9535e3038f0Sstefano_zampini     }
95476bd3646SJed Brown   }
9555e3038f0Sstefano_zampini 
9565e3038f0Sstefano_zampini   B = NULL;
9575e3038f0Sstefano_zampini   if (reuse != MAT_REUSE_MATRIX) {
9585b003df0Sstefano_zampini     PetscInt stl;
9595b003df0Sstefano_zampini 
9605e3038f0Sstefano_zampini     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
9615e3038f0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) stl += lr[i];
9629566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(stl,&l2gidxs));
9635b003df0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) {
9645e3038f0Sstefano_zampini       Mat            usedmat;
9655e3038f0Sstefano_zampini       Mat_IS         *matis;
9665e3038f0Sstefano_zampini       const PetscInt *idxs;
9675e3038f0Sstefano_zampini 
9685e3038f0Sstefano_zampini       /* local IS for local NEST */
9699566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]));
9705e3038f0Sstefano_zampini 
9715e3038f0Sstefano_zampini       /* l2gmap */
9725e3038f0Sstefano_zampini       j = 0;
9735e3038f0Sstefano_zampini       usedmat = nest[i][j];
9749e7b2b25Sstefano_zampini       while (!usedmat && j < nc-1) usedmat = nest[i][++j];
97528b400f6SJacob Faibussowitsch       PetscCheck(usedmat,comm,PETSC_ERR_SUP,"Cannot find valid row mat");
9769e7b2b25Sstefano_zampini 
9779e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
9789e7b2b25Sstefano_zampini         Mat T;
9799566063dSJacob Faibussowitsch         PetscCall(MatTransposeGetMat(usedmat,&T));
9809e7b2b25Sstefano_zampini         usedmat = T;
9819e7b2b25Sstefano_zampini       }
9825e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
9839566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(isrow[i],&idxs));
9849e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
9859566063dSJacob Faibussowitsch         PetscCall(PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE));
9869566063dSJacob Faibussowitsch         PetscCall(PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE));
9879e7b2b25Sstefano_zampini       } else {
9889566063dSJacob Faibussowitsch         PetscCall(PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE));
9899566063dSJacob Faibussowitsch         PetscCall(PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE));
9909e7b2b25Sstefano_zampini       }
9919566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(isrow[i],&idxs));
9925e3038f0Sstefano_zampini       stl += lr[i];
9935e3038f0Sstefano_zampini     }
9949566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g));
9955e3038f0Sstefano_zampini 
9965e3038f0Sstefano_zampini     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
9975e3038f0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) stl += lc[i];
9989566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(stl,&l2gidxs));
9995b003df0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) {
10005e3038f0Sstefano_zampini       Mat            usedmat;
10015e3038f0Sstefano_zampini       Mat_IS         *matis;
10025e3038f0Sstefano_zampini       const PetscInt *idxs;
10035e3038f0Sstefano_zampini 
10045e3038f0Sstefano_zampini       /* local IS for local NEST */
10059566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]));
10065e3038f0Sstefano_zampini 
10075e3038f0Sstefano_zampini       /* l2gmap */
10085e3038f0Sstefano_zampini       j = 0;
10095e3038f0Sstefano_zampini       usedmat = nest[j][i];
10109e7b2b25Sstefano_zampini       while (!usedmat && j < nr-1) usedmat = nest[++j][i];
101128b400f6SJacob Faibussowitsch       PetscCheck(usedmat,comm,PETSC_ERR_SUP,"Cannot find valid column mat");
10129e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
10139e7b2b25Sstefano_zampini         Mat T;
10149566063dSJacob Faibussowitsch         PetscCall(MatTransposeGetMat(usedmat,&T));
10159e7b2b25Sstefano_zampini         usedmat = T;
10169e7b2b25Sstefano_zampini       }
10175e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
10189566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(iscol[i],&idxs));
10199e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
10209566063dSJacob Faibussowitsch         PetscCall(PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE));
10219566063dSJacob Faibussowitsch         PetscCall(PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE));
10229e7b2b25Sstefano_zampini       } else {
10239566063dSJacob Faibussowitsch         PetscCall(PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE));
10249566063dSJacob Faibussowitsch         PetscCall(PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE));
10259e7b2b25Sstefano_zampini       }
10269566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(iscol[i],&idxs));
10275e3038f0Sstefano_zampini       stl += lc[i];
10285e3038f0Sstefano_zampini     }
10299566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g));
10305e3038f0Sstefano_zampini 
10315e3038f0Sstefano_zampini     /* Create MATIS */
10329566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm,&B));
10339566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N));
10349566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSizes(A,&rbs,&cbs));
10359566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizes(B,rbs,cbs));
10369566063dSJacob Faibussowitsch     PetscCall(MatSetType(B,MATIS));
10379566063dSJacob Faibussowitsch     PetscCall(MatISSetLocalMatType(B,MATNEST));
10388546b261SStefano Zampini     { /* hack : avoid setup of scatters */
10398546b261SStefano Zampini       Mat_IS *matis = (Mat_IS*)(B->data);
10408546b261SStefano Zampini       matis->islocalref = PETSC_TRUE;
10418546b261SStefano Zampini     }
10429566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(B,rl2g,cl2g));
10439566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
10449566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
10459566063dSJacob Faibussowitsch     PetscCall(MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA));
10469566063dSJacob Faibussowitsch     PetscCall(MatNestSetVecType(lA,VECNEST));
10479e7b2b25Sstefano_zampini     for (i=0;i<nr*nc;i++) {
10489e7b2b25Sstefano_zampini       if (istrans[i]) {
10499566063dSJacob Faibussowitsch         PetscCall(MatDestroy(&snest[i]));
10509e7b2b25Sstefano_zampini       }
10519e7b2b25Sstefano_zampini     }
10529566063dSJacob Faibussowitsch     PetscCall(MatISSetLocalMat(B,lA));
10539566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&lA));
10548546b261SStefano Zampini     { /* hack : setup of scatters done here */
10558546b261SStefano Zampini       Mat_IS *matis = (Mat_IS*)(B->data);
10568546b261SStefano Zampini 
10578546b261SStefano Zampini       matis->islocalref = PETSC_FALSE;
10589566063dSJacob Faibussowitsch       PetscCall(MatISSetUpScatters_Private(B));
10598546b261SStefano Zampini     }
10609566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
10619566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
10625e3038f0Sstefano_zampini     if (reuse == MAT_INPLACE_MATRIX) {
10639566063dSJacob Faibussowitsch       PetscCall(MatHeaderReplace(A,&B));
10645e3038f0Sstefano_zampini     } else {
10655e3038f0Sstefano_zampini       *newmat = B;
10665e3038f0Sstefano_zampini     }
10675e3038f0Sstefano_zampini   } else {
10685e3038f0Sstefano_zampini     if (lreuse) {
10699566063dSJacob Faibussowitsch       PetscCall(MatISGetLocalMat(*newmat,&lA));
10705e3038f0Sstefano_zampini       for (i=0;i<nr;i++) {
10715e3038f0Sstefano_zampini         for (j=0;j<nc;j++) {
10725e3038f0Sstefano_zampini           if (snest[i*nc+j]) {
10739566063dSJacob Faibussowitsch             PetscCall(MatNestSetSubMat(lA,i,j,snest[i*nc+j]));
10749e7b2b25Sstefano_zampini             if (istrans[i*nc+j]) {
10759566063dSJacob Faibussowitsch               PetscCall(MatDestroy(&snest[i*nc+j]));
10769e7b2b25Sstefano_zampini             }
10775e3038f0Sstefano_zampini           }
10785e3038f0Sstefano_zampini         }
10795e3038f0Sstefano_zampini       }
10805e3038f0Sstefano_zampini     } else {
10815b003df0Sstefano_zampini       PetscInt stl;
10825b003df0Sstefano_zampini       for (i=0,stl=0;i<nr;i++) {
10839566063dSJacob Faibussowitsch         PetscCall(ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]));
10845b003df0Sstefano_zampini         stl  += lr[i];
10855e3038f0Sstefano_zampini       }
10865b003df0Sstefano_zampini       for (i=0,stl=0;i<nc;i++) {
10879566063dSJacob Faibussowitsch         PetscCall(ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]));
10885b003df0Sstefano_zampini         stl  += lc[i];
10895e3038f0Sstefano_zampini       }
10909566063dSJacob Faibussowitsch       PetscCall(MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA));
1091ab4d48faSStefano Zampini       for (i=0;i<nr*nc;i++) {
10929e7b2b25Sstefano_zampini         if (istrans[i]) {
10939566063dSJacob Faibussowitsch           PetscCall(MatDestroy(&snest[i]));
10949e7b2b25Sstefano_zampini         }
1095ab4d48faSStefano Zampini       }
10969566063dSJacob Faibussowitsch       PetscCall(MatISSetLocalMat(*newmat,lA));
10979566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&lA));
10985e3038f0Sstefano_zampini     }
10999566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY));
11009566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY));
11015e3038f0Sstefano_zampini   }
11025e3038f0Sstefano_zampini 
11035b003df0Sstefano_zampini   /* Create local matrix in MATNEST format */
11045b003df0Sstefano_zampini   convert = PETSC_FALSE;
11059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL));
11065b003df0Sstefano_zampini   if (convert) {
11075b003df0Sstefano_zampini     Mat              M;
11085b003df0Sstefano_zampini     MatISLocalFields lf;
11095b003df0Sstefano_zampini     PetscContainer   c;
11105b003df0Sstefano_zampini 
11119566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(*newmat,&lA));
11129566063dSJacob Faibussowitsch     PetscCall(MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M));
11139566063dSJacob Faibussowitsch     PetscCall(MatISSetLocalMat(*newmat,M));
11149566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&M));
11155b003df0Sstefano_zampini 
11165b003df0Sstefano_zampini     /* attach local fields to the matrix */
11179566063dSJacob Faibussowitsch     PetscCall(PetscNew(&lf));
11189566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nr,&lf->rf,nc,&lf->cf));
11195b003df0Sstefano_zampini     for (i=0;i<nr;i++) {
11205b003df0Sstefano_zampini       PetscInt n,st;
11215b003df0Sstefano_zampini 
11229566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(islrow[i],&n));
11239566063dSJacob Faibussowitsch       PetscCall(ISStrideGetInfo(islrow[i],&st,NULL));
11249566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(comm,n,st,1,&lf->rf[i]));
11255b003df0Sstefano_zampini     }
11265b003df0Sstefano_zampini     for (i=0;i<nc;i++) {
11275b003df0Sstefano_zampini       PetscInt n,st;
11285b003df0Sstefano_zampini 
11299566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(islcol[i],&n));
11309566063dSJacob Faibussowitsch       PetscCall(ISStrideGetInfo(islcol[i],&st,NULL));
11319566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(comm,n,st,1,&lf->cf[i]));
11325b003df0Sstefano_zampini     }
11335b003df0Sstefano_zampini     lf->nr = nr;
11345b003df0Sstefano_zampini     lf->nc = nc;
11359566063dSJacob Faibussowitsch     PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c));
11369566063dSJacob Faibussowitsch     PetscCall(PetscContainerSetPointer(c,lf));
11379566063dSJacob Faibussowitsch     PetscCall(PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private));
11389566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c));
11399566063dSJacob Faibussowitsch     PetscCall(PetscContainerDestroy(&c));
11405b003df0Sstefano_zampini   }
11415b003df0Sstefano_zampini 
11425e3038f0Sstefano_zampini   /* Free workspace */
11435e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
11449566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&islrow[i]));
11455e3038f0Sstefano_zampini   }
11465e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
11479566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&islcol[i]));
11485e3038f0Sstefano_zampini   }
11499566063dSJacob Faibussowitsch   PetscCall(PetscFree6(isrow,iscol,islrow,islcol,snest,istrans));
11509566063dSJacob Faibussowitsch   PetscCall(PetscFree2(lr,lc));
11515e3038f0Sstefano_zampini   PetscFunctionReturn(0);
11525e3038f0Sstefano_zampini }
11535e3038f0Sstefano_zampini 
1154ad219c80Sstefano_zampini static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r)
1155ad219c80Sstefano_zampini {
1156ad219c80Sstefano_zampini   Mat_IS            *matis = (Mat_IS*)A->data;
1157ad219c80Sstefano_zampini   Vec               ll,rr;
1158ad219c80Sstefano_zampini   const PetscScalar *Y,*X;
1159ad219c80Sstefano_zampini   PetscScalar       *x,*y;
1160ad219c80Sstefano_zampini 
1161ad219c80Sstefano_zampini   PetscFunctionBegin;
1162ad219c80Sstefano_zampini   if (l) {
1163ad219c80Sstefano_zampini     ll   = matis->y;
11649566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(l,&Y));
11659566063dSJacob Faibussowitsch     PetscCall(VecGetArray(ll,&y));
11669566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(matis->sf,MPIU_SCALAR,Y,y,MPI_REPLACE));
1167ad219c80Sstefano_zampini   } else {
1168ad219c80Sstefano_zampini     ll = NULL;
1169ad219c80Sstefano_zampini   }
1170ad219c80Sstefano_zampini   if (r) {
1171ad219c80Sstefano_zampini     rr   = matis->x;
11729566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(r,&X));
11739566063dSJacob Faibussowitsch     PetscCall(VecGetArray(rr,&x));
11749566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(matis->csf,MPIU_SCALAR,X,x,MPI_REPLACE));
1175ad219c80Sstefano_zampini   } else {
1176ad219c80Sstefano_zampini     rr = NULL;
1177ad219c80Sstefano_zampini   }
1178ad219c80Sstefano_zampini   if (ll) {
11799566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(matis->sf,MPIU_SCALAR,Y,y,MPI_REPLACE));
11809566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(l,&Y));
11819566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(ll,&y));
1182ad219c80Sstefano_zampini   }
1183ad219c80Sstefano_zampini   if (rr) {
11849566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(matis->csf,MPIU_SCALAR,X,x,MPI_REPLACE));
11859566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(r,&X));
11869566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(rr,&x));
1187ad219c80Sstefano_zampini   }
11889566063dSJacob Faibussowitsch   PetscCall(MatDiagonalScale(matis->A,ll,rr));
1189ad219c80Sstefano_zampini   PetscFunctionReturn(0);
1190ad219c80Sstefano_zampini }
1191ad219c80Sstefano_zampini 
11927fa8f2d3SStefano Zampini static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo)
11937fa8f2d3SStefano Zampini {
11947fa8f2d3SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
11957fa8f2d3SStefano Zampini   MatInfo        info;
11963966268fSBarry Smith   PetscLogDouble isend[6],irecv[6];
11977fa8f2d3SStefano Zampini   PetscInt       bs;
11987fa8f2d3SStefano Zampini 
11997fa8f2d3SStefano Zampini   PetscFunctionBegin;
12009566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(A,&bs));
1201a2ccb5f9Sstefano_zampini   if (matis->A->ops->getinfo) {
12029566063dSJacob Faibussowitsch     PetscCall(MatGetInfo(matis->A,MAT_LOCAL,&info));
12037fa8f2d3SStefano Zampini     isend[0] = info.nz_used;
12047fa8f2d3SStefano Zampini     isend[1] = info.nz_allocated;
12057fa8f2d3SStefano Zampini     isend[2] = info.nz_unneeded;
12067fa8f2d3SStefano Zampini     isend[3] = info.memory;
12077fa8f2d3SStefano Zampini     isend[4] = info.mallocs;
1208a2ccb5f9Sstefano_zampini   } else {
1209a2ccb5f9Sstefano_zampini     isend[0] = 0.;
1210a2ccb5f9Sstefano_zampini     isend[1] = 0.;
1211a2ccb5f9Sstefano_zampini     isend[2] = 0.;
1212a2ccb5f9Sstefano_zampini     isend[3] = 0.;
1213a2ccb5f9Sstefano_zampini     isend[4] = 0.;
1214a2ccb5f9Sstefano_zampini   }
1215314ce898Sstefano_zampini   isend[5] = matis->A->num_ass;
12167fa8f2d3SStefano Zampini   if (flag == MAT_LOCAL) {
12177fa8f2d3SStefano Zampini     ginfo->nz_used      = isend[0];
12187fa8f2d3SStefano Zampini     ginfo->nz_allocated = isend[1];
12197fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = isend[2];
12207fa8f2d3SStefano Zampini     ginfo->memory       = isend[3];
12217fa8f2d3SStefano Zampini     ginfo->mallocs      = isend[4];
1222314ce898Sstefano_zampini     ginfo->assemblies   = isend[5];
12237fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_MAX) {
12241c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(isend,irecv,6,MPIU_PETSCLOGDOUBLE,MPI_MAX,PetscObjectComm((PetscObject)A)));
12257fa8f2d3SStefano Zampini 
12267fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
12277fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
12287fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
12297fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
12307fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
1231314ce898Sstefano_zampini     ginfo->assemblies   = irecv[5];
12327fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_SUM) {
12331c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(isend,irecv,5,MPIU_PETSCLOGDOUBLE,MPI_SUM,PetscObjectComm((PetscObject)A)));
12347fa8f2d3SStefano Zampini 
12357fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
12367fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
12377fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
12387fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
12397fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
12407fa8f2d3SStefano Zampini     ginfo->assemblies   = A->num_ass;
12417fa8f2d3SStefano Zampini   }
12427fa8f2d3SStefano Zampini   ginfo->block_size        = bs;
12437fa8f2d3SStefano Zampini   ginfo->fill_ratio_given  = 0;
12447fa8f2d3SStefano Zampini   ginfo->fill_ratio_needed = 0;
12457fa8f2d3SStefano Zampini   ginfo->factor_mallocs    = 0;
12465e3038f0Sstefano_zampini   PetscFunctionReturn(0);
12475e3038f0Sstefano_zampini }
12485e3038f0Sstefano_zampini 
12498b9382cfSStefano Zampini static PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
1250d7f69cd0SStefano Zampini {
1251d7f69cd0SStefano Zampini   Mat                    C,lC,lA;
1252d7f69cd0SStefano Zampini 
1253d7f69cd0SStefano Zampini   PetscFunctionBegin;
1254*7fb60732SBarry Smith   if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A,*B));
1255cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) {
1256cf37664fSBarry Smith     ISLocalToGlobalMapping rl2g,cl2g;
12579566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A),&C));
12589566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N));
12599566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs)));
12609566063dSJacob Faibussowitsch     PetscCall(MatSetType(C,MATIS));
12619566063dSJacob Faibussowitsch     PetscCall(MatGetLocalToGlobalMapping(A,&rl2g,&cl2g));
12629566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(C,cl2g,rl2g));
1263e432b41dSStefano Zampini   } else C = *B;
1264d7f69cd0SStefano Zampini 
1265d7f69cd0SStefano Zampini   /* perform local transposition */
12669566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(A,&lA));
12679566063dSJacob Faibussowitsch   PetscCall(MatTranspose(lA,MAT_INITIAL_MATRIX,&lC));
12689566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(lC,lA->cmap->mapping,lA->rmap->mapping));
12699566063dSJacob Faibussowitsch   PetscCall(MatISSetLocalMat(C,lC));
12709566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&lC));
1271d7f69cd0SStefano Zampini 
1272cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) {
1273d7f69cd0SStefano Zampini     *B = C;
1274d7f69cd0SStefano Zampini   } else {
12759566063dSJacob Faibussowitsch     PetscCall(MatHeaderMerge(A,&C));
1276d7f69cd0SStefano Zampini   }
12779566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY));
12789566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY));
1279d7f69cd0SStefano Zampini   PetscFunctionReturn(0);
1280d7f69cd0SStefano Zampini }
1281d7f69cd0SStefano Zampini 
12828b9382cfSStefano Zampini static PetscErrorCode MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
12833fd1c9e7SStefano Zampini {
12843fd1c9e7SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
12853fd1c9e7SStefano Zampini 
12863fd1c9e7SStefano Zampini   PetscFunctionBegin;
12874b89b9cdSStefano Zampini   if (D) { /* MatShift_IS pass D = NULL */
12889566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD));
12899566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD));
12903fd1c9e7SStefano Zampini   }
12919566063dSJacob Faibussowitsch   PetscCall(VecPointwiseDivide(is->y,is->y,is->counter));
12929566063dSJacob Faibussowitsch   PetscCall(MatDiagonalSet(is->A,is->y,insmode));
12933fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
12943fd1c9e7SStefano Zampini }
12953fd1c9e7SStefano Zampini 
12968b9382cfSStefano Zampini static PetscErrorCode MatShift_IS(Mat A,PetscScalar a)
12973fd1c9e7SStefano Zampini {
12984b89b9cdSStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
12993fd1c9e7SStefano Zampini 
13003fd1c9e7SStefano Zampini   PetscFunctionBegin;
13019566063dSJacob Faibussowitsch   PetscCall(VecSet(is->y,a));
13029566063dSJacob Faibussowitsch   PetscCall(MatDiagonalSet_IS(A,NULL,ADD_VALUES));
13033fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
13043fd1c9e7SStefano Zampini }
13053fd1c9e7SStefano Zampini 
1306f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1307f26d0771SStefano Zampini {
1308f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
1309f26d0771SStefano Zampini 
1310f26d0771SStefano Zampini   PetscFunctionBegin;
1311aed4548fSBarry 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);
13129566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l));
13139566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l));
13149566063dSJacob Faibussowitsch   PetscCall(MatSetValuesLocal_IS(A,m,rows_l,n,cols_l,values,addv));
1315f26d0771SStefano Zampini   PetscFunctionReturn(0);
1316f26d0771SStefano Zampini }
1317f26d0771SStefano Zampini 
1318f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1319f26d0771SStefano Zampini {
1320f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
1321f26d0771SStefano Zampini 
1322f26d0771SStefano Zampini   PetscFunctionBegin;
1323aed4548fSBarry 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);
13249566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l));
13259566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l));
13269566063dSJacob Faibussowitsch   PetscCall(MatSetValuesBlockedLocal_IS(A,m,rows_l,n,cols_l,values,addv));
1327f26d0771SStefano Zampini   PetscFunctionReturn(0);
1328f26d0771SStefano Zampini }
1329f26d0771SStefano Zampini 
13307dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
1331a8116848SStefano Zampini {
1332a8116848SStefano Zampini   Mat               locmat,newlocmat;
1333a8116848SStefano Zampini   Mat_IS            *newmatis;
1334a8116848SStefano Zampini   const PetscInt    *idxs;
1335a8116848SStefano Zampini   PetscInt          i,m,n;
1336a8116848SStefano Zampini 
1337a8116848SStefano Zampini   PetscFunctionBegin;
1338a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
1339a8116848SStefano Zampini     PetscBool ismatis;
1340a8116848SStefano Zampini 
13419566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis));
134228b400f6SJacob Faibussowitsch     PetscCheck(ismatis,PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
1343a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
134428b400f6SJacob Faibussowitsch     PetscCheck(newmatis->getsub_ris,PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
134528b400f6SJacob Faibussowitsch     PetscCheck(newmatis->getsub_cis,PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
1346a8116848SStefano Zampini   }
1347a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
134876bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
134976bd3646SJed Brown     Vec               rtest,ltest;
135076bd3646SJed Brown     const PetscScalar *array;
135176bd3646SJed Brown 
13529566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(mat,&ltest,&rtest));
13539566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(irow,&n));
13549566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(irow,&idxs));
1355a8116848SStefano Zampini     for (i=0;i<n;i++) {
13569566063dSJacob Faibussowitsch       PetscCall(VecSetValue(rtest,idxs[i],1.0,ADD_VALUES));
1357a8116848SStefano Zampini     }
13589566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(rtest));
13599566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(rtest));
13609566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(rtest,&n));
13619566063dSJacob Faibussowitsch     PetscCall(VecGetOwnershipRange(rtest,&m,NULL));
13629566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(rtest,&array));
1363aed4548fSBarry 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]));
13649566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(rtest,&array));
13659566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(irow,&idxs));
13669566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(icol,&n));
13679566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(icol,&idxs));
1368a8116848SStefano Zampini     for (i=0;i<n;i++) {
13699566063dSJacob Faibussowitsch       PetscCall(VecSetValue(ltest,idxs[i],1.0,ADD_VALUES));
1370a8116848SStefano Zampini     }
13719566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(ltest));
13729566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(ltest));
13739566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(ltest,&n));
13749566063dSJacob Faibussowitsch     PetscCall(VecGetOwnershipRange(ltest,&m,NULL));
13759566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(ltest,&array));
1376aed4548fSBarry 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]));
13779566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(ltest,&array));
13789566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(icol,&idxs));
13799566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&rtest));
13809566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&ltest));
138176bd3646SJed Brown   }
1382a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
1383a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
1384a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
1385a8116848SStefano Zampini     IS                     is;
1386a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
1387306cf5c7SStefano Zampini     PetscInt               ll,newloc,irbs,icbs,arbs,acbs,rbs,cbs;
138894342113SStefano Zampini     PetscBool              cong;
1389a8116848SStefano Zampini     MPI_Comm               comm;
1390a8116848SStefano Zampini 
13919566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)mat,&comm));
13929566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSizes(mat,&arbs,&acbs));
13939566063dSJacob Faibussowitsch     PetscCall(ISGetBlockSize(irow,&irbs));
13949566063dSJacob Faibussowitsch     PetscCall(ISGetBlockSize(icol,&icbs));
1395306cf5c7SStefano Zampini     rbs  = arbs == irbs ? irbs : 1;
1396306cf5c7SStefano Zampini     cbs  = acbs == icbs ? icbs : 1;
13979566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(irow,&m));
13989566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(icol,&n));
13999566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm,newmat));
14009566063dSJacob Faibussowitsch     PetscCall(MatSetType(*newmat,MATIS));
14019566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE));
14029566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizes(*newmat,rbs,cbs));
1403a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
14049566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(irow,&idxs));
14059566063dSJacob Faibussowitsch     PetscCall(PetscLayoutMapLocal(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs));
14069566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(irow,&idxs));
14079566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(matis->sf_rootdata,matis->sf->nroots));
1408a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
14099566063dSJacob Faibussowitsch     PetscCall(PetscFree(lidxs));
14109566063dSJacob Faibussowitsch     PetscCall(PetscFree(lgidxs));
14119566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
14129566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
14133d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
14149566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newloc,&newgidxs));
14159566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newloc,&lidxs));
14163d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++)
1417a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
1418a8116848SStefano Zampini         lidxs[newloc] = i;
1419a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
1420a8116848SStefano Zampini       }
14219566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is));
14229566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is,&rl2g));
14239566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingSetBlockSize(rl2g,rbs));
14249566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
1425a8116848SStefano Zampini     /* local is to extract local submatrix */
1426a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
14279566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris));
14289566063dSJacob Faibussowitsch     PetscCall(MatHasCongruentLayouts(mat,&cong));
142994342113SStefano Zampini     if (cong && irow == icol && matis->csf == matis->sf) {
14309566063dSJacob Faibussowitsch       PetscCall(MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g));
14319566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)newmatis->getsub_ris));
1432a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
1433a8116848SStefano Zampini     } else {
1434a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
1435a8116848SStefano Zampini 
1436a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
14379566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(icol,&idxs));
14389566063dSJacob Faibussowitsch       PetscCall(PetscLayoutMapLocal(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs));
14399566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(icol,&idxs));
14409566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(matis->csf_rootdata,matis->csf->nroots));
1441a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
14429566063dSJacob Faibussowitsch       PetscCall(PetscFree(lidxs));
14439566063dSJacob Faibussowitsch       PetscCall(PetscFree(lgidxs));
14449566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata,MPI_REPLACE));
14459566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata,MPI_REPLACE));
14463d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
14479566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(newloc,&newgidxs));
14489566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(newloc,&lidxs));
14493d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++)
1450a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
1451a8116848SStefano Zampini           lidxs[newloc] = i;
1452a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
1453a8116848SStefano Zampini         }
14549566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is));
14559566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreateIS(is,&cl2g));
14569566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingSetBlockSize(cl2g,cbs));
14579566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is));
1458a8116848SStefano Zampini       /* local is to extract local submatrix */
14599566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis));
14609566063dSJacob Faibussowitsch       PetscCall(MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g));
14619566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
1462a8116848SStefano Zampini     }
14639566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
1464a8116848SStefano Zampini   } else {
14659566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(*newmat,&newlocmat));
1466a8116848SStefano Zampini   }
14679566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(mat,&locmat));
1468a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
14699566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat));
1470a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
14719566063dSJacob Faibussowitsch     PetscCall(MatISSetLocalMat(*newmat,newlocmat));
14729566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&newlocmat));
1473a8116848SStefano Zampini   }
14749566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY));
14759566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY));
1476a8116848SStefano Zampini   PetscFunctionReturn(0);
1477a8116848SStefano Zampini }
1478a8116848SStefano Zampini 
1479a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
14802b404112SStefano Zampini {
14812b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
14822b404112SStefano Zampini   PetscBool      ismatis;
14832b404112SStefano Zampini 
14842b404112SStefano Zampini   PetscFunctionBegin;
14859566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis));
148628b400f6SJacob Faibussowitsch   PetscCheck(ismatis,PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
14872b404112SStefano Zampini   b = (Mat_IS*)B->data;
14889566063dSJacob Faibussowitsch   PetscCall(MatCopy(a->A,b->A,str));
14899566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)B));
14902b404112SStefano Zampini   PetscFunctionReturn(0);
14912b404112SStefano Zampini }
14922b404112SStefano Zampini 
1493a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
14946bd84002SStefano Zampini {
1495527b2640SStefano Zampini   Vec               v;
1496527b2640SStefano Zampini   const PetscScalar *array;
1497527b2640SStefano Zampini   PetscInt          i,n;
14986bd84002SStefano Zampini 
14996bd84002SStefano Zampini   PetscFunctionBegin;
1500527b2640SStefano Zampini   *missing = PETSC_FALSE;
15019566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(A,NULL,&v));
15029566063dSJacob Faibussowitsch   PetscCall(MatGetDiagonal(A,v));
15039566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(v,&n));
15049566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(v,&array));
1505527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
15069566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(v,&array));
15079566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&v));
1508527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
1509527b2640SStefano Zampini   if (d) {
1510527b2640SStefano Zampini     *d = -1;
1511527b2640SStefano Zampini     if (*missing) {
1512527b2640SStefano Zampini       PetscInt rstart;
15139566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRange(A,&rstart,NULL));
1514527b2640SStefano Zampini       *d = i+rstart;
1515527b2640SStefano Zampini     }
1516527b2640SStefano Zampini   }
15176bd84002SStefano Zampini   PetscFunctionReturn(0);
15186bd84002SStefano Zampini }
15196bd84002SStefano Zampini 
1520cf0a3239SStefano Zampini static PetscErrorCode MatISSetUpSF_IS(Mat B)
152128f4e0baSStefano Zampini {
152228f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
152328f4e0baSStefano Zampini   const PetscInt *gidxs;
15244f2d7cafSStefano Zampini   PetscInt       nleaves;
152528f4e0baSStefano Zampini 
152628f4e0baSStefano Zampini   PetscFunctionBegin;
15274f2d7cafSStefano Zampini   if (matis->sf) PetscFunctionReturn(0);
15289566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf));
15299566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(matis->rmapping,&gidxs));
15309566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(matis->rmapping,&nleaves));
15319566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs));
15329566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->rmapping,&gidxs));
15339566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata));
1534e432b41dSStefano Zampini   if (matis->rmapping != matis->cmapping) { /* setup SF for columns */
15359566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetSize(matis->cmapping,&nleaves));
15369566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf));
15379566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetIndices(matis->cmapping,&gidxs));
15389566063dSJacob Faibussowitsch     PetscCall(PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs));
15399566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->cmapping,&gidxs));
15409566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata));
1541a8116848SStefano Zampini   } else {
1542a8116848SStefano Zampini     matis->csf = matis->sf;
1543a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
1544a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
1545a8116848SStefano Zampini   }
154628f4e0baSStefano Zampini   PetscFunctionReturn(0);
154728f4e0baSStefano Zampini }
15482e1947a5SStefano Zampini 
1549eb82efa4SStefano Zampini /*@
155075d48cdbSStefano Zampini    MatISStoreL2L - Store local-to-local operators during the Galerkin process of MatPtAP.
155175d48cdbSStefano Zampini 
1552d083f849SBarry Smith    Collective
155375d48cdbSStefano Zampini 
155475d48cdbSStefano Zampini    Input Parameters:
155575d48cdbSStefano Zampini +  A - the matrix
155675d48cdbSStefano Zampini -  store - the boolean flag
155775d48cdbSStefano Zampini 
155875d48cdbSStefano Zampini    Level: advanced
155975d48cdbSStefano Zampini 
156075d48cdbSStefano Zampini    Notes:
156175d48cdbSStefano Zampini 
1562db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateIS()`, `MatISSetPreallocation()`, `MatPtAP()`
156375d48cdbSStefano Zampini @*/
156475d48cdbSStefano Zampini PetscErrorCode MatISStoreL2L(Mat A, PetscBool store)
156575d48cdbSStefano Zampini {
156675d48cdbSStefano Zampini   PetscFunctionBegin;
156775d48cdbSStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
156875d48cdbSStefano Zampini   PetscValidType(A,1);
156975d48cdbSStefano Zampini   PetscValidLogicalCollectiveBool(A,store,2);
1570cac4c232SBarry Smith   PetscTryMethod(A,"MatISStoreL2L_C",(Mat,PetscBool),(A,store));
157175d48cdbSStefano Zampini   PetscFunctionReturn(0);
157275d48cdbSStefano Zampini }
157375d48cdbSStefano Zampini 
157475d48cdbSStefano Zampini static PetscErrorCode MatISStoreL2L_IS(Mat A, PetscBool store)
157575d48cdbSStefano Zampini {
157675d48cdbSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(A->data);
157775d48cdbSStefano Zampini 
157875d48cdbSStefano Zampini   PetscFunctionBegin;
157975d48cdbSStefano Zampini   matis->storel2l = store;
158075d48cdbSStefano Zampini   if (!store) {
15819566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",NULL));
158275d48cdbSStefano Zampini   }
158375d48cdbSStefano Zampini   PetscFunctionReturn(0);
158475d48cdbSStefano Zampini }
158575d48cdbSStefano Zampini 
158675d48cdbSStefano Zampini /*@
1587f03112d0SStefano Zampini    MatISFixLocalEmpty - Compress out zero local rows from the local matrices
1588f03112d0SStefano Zampini 
1589d083f849SBarry Smith    Collective
1590f03112d0SStefano Zampini 
1591f03112d0SStefano Zampini    Input Parameters:
1592f03112d0SStefano Zampini +  A - the matrix
1593f03112d0SStefano Zampini -  fix - the boolean flag
1594f03112d0SStefano Zampini 
1595f03112d0SStefano Zampini    Level: advanced
1596f03112d0SStefano Zampini 
1597f03112d0SStefano Zampini    Notes: When fix is true, new local matrices and l2g maps are generated during the final assembly process.
1598f03112d0SStefano Zampini 
1599db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateIS()`, `MatISSetPreallocation()`, `MatAssemblyEnd()`, `MAT_FINAL_ASSEMBLY`
1600f03112d0SStefano Zampini @*/
1601f03112d0SStefano Zampini PetscErrorCode MatISFixLocalEmpty(Mat A, PetscBool fix)
1602f03112d0SStefano Zampini {
1603f03112d0SStefano Zampini   PetscFunctionBegin;
1604f03112d0SStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
1605f03112d0SStefano Zampini   PetscValidType(A,1);
1606f03112d0SStefano Zampini   PetscValidLogicalCollectiveBool(A,fix,2);
1607cac4c232SBarry Smith   PetscTryMethod(A,"MatISFixLocalEmpty_C",(Mat,PetscBool),(A,fix));
1608f03112d0SStefano Zampini   PetscFunctionReturn(0);
1609f03112d0SStefano Zampini }
1610f03112d0SStefano Zampini 
1611f03112d0SStefano Zampini static PetscErrorCode MatISFixLocalEmpty_IS(Mat A, PetscBool fix)
1612f03112d0SStefano Zampini {
1613f03112d0SStefano Zampini   Mat_IS *matis = (Mat_IS*)(A->data);
1614f03112d0SStefano Zampini 
1615f03112d0SStefano Zampini   PetscFunctionBegin;
1616f03112d0SStefano Zampini   matis->locempty = fix;
1617f03112d0SStefano Zampini   PetscFunctionReturn(0);
1618f03112d0SStefano Zampini }
1619f03112d0SStefano Zampini 
1620f03112d0SStefano Zampini /*@
1621a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
1622a88811baSStefano Zampini 
1623d083f849SBarry Smith    Collective
1624a88811baSStefano Zampini 
1625a88811baSStefano Zampini    Input Parameters:
1626a88811baSStefano Zampini +  B - the matrix
1627a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1628a88811baSStefano Zampini            (same value is used for all local rows)
1629a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
1630a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
1631a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
1632a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
1633a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
1634a88811baSStefano Zampini            the diagonal entry even if it is zero.
1635a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1636a88811baSStefano Zampini            submatrix (same value is used for all local rows).
1637a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
1638a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
1639a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
1640a88811baSStefano Zampini            structure. The size of this array is equal to the number
1641a88811baSStefano Zampini            of local rows, i.e 'm'.
1642a88811baSStefano Zampini 
1643a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
1644a88811baSStefano Zampini 
1645a88811baSStefano Zampini    Level: intermediate
1646a88811baSStefano Zampini 
164795452b02SPatrick Sanan    Notes:
164895452b02SPatrick Sanan     This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
1649a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
1650a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
1651a88811baSStefano Zampini 
1652db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateIS()`, `MatMPIAIJSetPreallocation()`, `MatISGetLocalMat()`, `MATIS`
1653a88811baSStefano Zampini @*/
16542e1947a5SStefano Zampini PetscErrorCode MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
16552e1947a5SStefano Zampini {
16562e1947a5SStefano Zampini   PetscFunctionBegin;
16572e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
16582e1947a5SStefano Zampini   PetscValidType(B,1);
1659cac4c232SBarry Smith   PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));
16602e1947a5SStefano Zampini   PetscFunctionReturn(0);
16612e1947a5SStefano Zampini }
16622e1947a5SStefano Zampini 
1663844bd0d7SStefano Zampini /* this is used by DMDA */
1664844bd0d7SStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
16652e1947a5SStefano Zampini {
16662e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
166728f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
16682e1947a5SStefano Zampini 
16692e1947a5SStefano Zampini   PetscFunctionBegin;
16709566063dSJacob Faibussowitsch   PetscCall(MatSetUp(B));
16714f2d7cafSStefano Zampini   if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz;
16724f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
16734f2d7cafSStefano Zampini 
16744f2d7cafSStefano Zampini   if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz;
16754f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
16764f2d7cafSStefano Zampini 
16779566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
16789566063dSJacob Faibussowitsch   PetscCall(MatGetSize(matis->A,NULL,&nlocalcols));
16799566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(matis->A,&bs));
16809566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
16814f2d7cafSStefano Zampini 
16824f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
16839566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata));
16840f2f62c7SStefano Zampini #if defined(PETSC_HAVE_HYPRE)
16859566063dSJacob Faibussowitsch   PetscCall(MatHYPRESetPreallocation(matis->A,0,matis->sf_leafdata,0,NULL));
16860f2f62c7SStefano Zampini #endif
16874f2d7cafSStefano Zampini 
1688fc989267SStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) {
1689fc989267SStefano Zampini     PetscInt b;
1690fc989267SStefano Zampini 
1691fc989267SStefano Zampini     matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
1692fc989267SStefano Zampini     for (b=1;b<bs;b++) {
1693fc989267SStefano Zampini       matis->sf_leafdata[i] = PetscMax(matis->sf_leafdata[i],matis->sf_leafdata[i*bs+b]/bs);
1694fc989267SStefano Zampini     }
1695fc989267SStefano Zampini   }
16969566063dSJacob Faibussowitsch   PetscCall(MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata));
16974f2d7cafSStefano Zampini 
169800a59248SStefano Zampini   nlocalcols /= bs;
169900a59248SStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols - i);
17009566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata));
17010f2f62c7SStefano Zampini 
17020f2f62c7SStefano Zampini   /* for other matrix types */
17039566063dSJacob Faibussowitsch   PetscCall(MatSetUp(matis->A));
17042e1947a5SStefano Zampini   PetscFunctionReturn(0);
17052e1947a5SStefano Zampini }
1706b4319ba4SBarry Smith 
17073927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
17083927de2eSStefano Zampini {
17093927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
17103927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
1711ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
17123927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
17133927de2eSStefano Zampini   PetscInt        lrows,lcols;
17143927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
1715f03112d0SStefano Zampini   PetscMPIInt     size;
17163927de2eSStefano Zampini   PetscBool       isdense,issbaij;
17173927de2eSStefano Zampini 
17183927de2eSStefano Zampini   PetscFunctionBegin;
17199566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A),&size));
17209566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A,&rows,&cols));
17219566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(A,&bs));
17229566063dSJacob Faibussowitsch   PetscCall(MatGetSize(matis->A,&local_rows,&local_cols));
17239566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense));
17249566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij));
17259566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(matis->rmapping,&global_indices_r));
1726e432b41dSStefano Zampini   if (matis->rmapping != matis->cmapping) {
17279566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetIndices(matis->cmapping,&global_indices_c));
17280dfc91b7SStefano Zampini   } else global_indices_c = global_indices_r;
1729ecf5a873SStefano Zampini 
17309566063dSJacob Faibussowitsch   if (issbaij) PetscCall(MatGetRowUpperTriangular(matis->A));
17313927de2eSStefano Zampini   /*
1732ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
17333927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
17343927de2eSStefano Zampini   */
17359566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(A,&lrows,&lcols));
1736d0609cedSBarry Smith   MatPreallocateBegin(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);
17373927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
17389566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(rows,&row_ownership));
17399566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges));
1740f03112d0SStefano Zampini   for (i=0;i<size;i++) {
17415f80ce2aSJacob Faibussowitsch     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) row_ownership[j] = i;
17423927de2eSStefano Zampini   }
17439566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges));
17443927de2eSStefano Zampini 
17453927de2eSStefano Zampini   /*
17463927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
17473927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
17483927de2eSStefano Zampini   */
17499566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz));
17503927de2eSStefano Zampini   /* preallocation as a MATAIJ */
17513927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
17523927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
175312dfadf8SStefano Zampini       PetscInt owner = row_ownership[global_indices_r[i]];
175412dfadf8SStefano Zampini       for (j=0;j<local_cols;j++) {
1755ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
17563927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1]) { /* diag block */
17573927de2eSStefano Zampini           my_dnz[i] += 1;
17583927de2eSStefano Zampini         } else { /* offdiag block */
17593927de2eSStefano Zampini           my_onz[i] += 1;
17603927de2eSStefano Zampini         }
17613927de2eSStefano Zampini       }
17623927de2eSStefano Zampini     }
1763bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
1764bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
1765bb1015c3SStefano Zampini     PetscBool      done;
17669566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done));
17675f80ce2aSJacob Faibussowitsch     PetscCheck(done,PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1768bb1015c3SStefano Zampini     jptr = jj;
1769bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
1770bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
1771bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
1772bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
1773bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
1774bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1]) { /* diag block */
1775bb1015c3SStefano Zampini           my_dnz[i] += 1;
1776bb1015c3SStefano Zampini         } else { /* offdiag block */
1777bb1015c3SStefano Zampini           my_onz[i] += 1;
1778bb1015c3SStefano Zampini         }
1779bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
1780bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
1781bb1015c3SStefano Zampini           owner = row_ownership[index_col];
1782bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1]) {
1783bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
1784bb1015c3SStefano Zampini           } else {
1785bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
1786bb1015c3SStefano Zampini           }
1787bb1015c3SStefano Zampini         }
1788bb1015c3SStefano Zampini       }
1789bb1015c3SStefano Zampini     }
17909566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done));
17915f80ce2aSJacob Faibussowitsch     PetscCheck(done,PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1792bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
17933927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
17943927de2eSStefano Zampini       const PetscInt *cols;
1795ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
17969566063dSJacob Faibussowitsch       PetscCall(MatGetRow(matis->A,i,&ncols,&cols,NULL));
17973927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
17983927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
1799ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
18003927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1]) { /* diag block */
18013927de2eSStefano Zampini           my_dnz[i] += 1;
18023927de2eSStefano Zampini         } else { /* offdiag block */
18033927de2eSStefano Zampini           my_onz[i] += 1;
18043927de2eSStefano Zampini         }
18053927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
1806d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
18073927de2eSStefano Zampini           owner = row_ownership[index_col];
18083927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1]) {
1809d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
18103927de2eSStefano Zampini           } else {
1811d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
18123927de2eSStefano Zampini           }
18133927de2eSStefano Zampini         }
18143927de2eSStefano Zampini       }
18159566063dSJacob Faibussowitsch       PetscCall(MatRestoreRow(matis->A,i,&ncols,&cols,NULL));
18163927de2eSStefano Zampini     }
18173927de2eSStefano Zampini   }
1818ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
18199566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->cmapping,&global_indices_c));
1820ecf5a873SStefano Zampini   }
18219566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->rmapping,&global_indices_r));
18229566063dSJacob Faibussowitsch   PetscCall(PetscFree(row_ownership));
1823ecf5a873SStefano Zampini 
1824ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
18253927de2eSStefano Zampini   if (maxreduce) {
18269566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX));
18279566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX));
18289566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX));
18299566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX));
18303927de2eSStefano Zampini   } else {
18319566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM));
18329566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM));
18339566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM));
18349566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM));
18353927de2eSStefano Zampini   }
18369566063dSJacob Faibussowitsch   PetscCall(PetscFree2(my_dnz,my_onz));
18373927de2eSStefano Zampini 
18383927de2eSStefano Zampini   /* Resize preallocation if overestimated */
18393927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
18403927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
18413927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
18423927de2eSStefano Zampini   }
18431670daf9Sstefano_zampini 
18441670daf9Sstefano_zampini   /* Set preallocation */
18459566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSizesFromMats(B,A,A));
18469566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(B,0,dnz));
18479566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(B,0,dnz,0,onz));
184853b44cf5SStefano Zampini   for (i=0;i<lrows;i+=bs) {
184953b44cf5SStefano Zampini     PetscInt b, d = dnz[i],o = onz[i];
185053b44cf5SStefano Zampini 
185153b44cf5SStefano Zampini     for (b=1;b<bs;b++) {
185253b44cf5SStefano Zampini       d = PetscMax(d,dnz[i+b]);
185353b44cf5SStefano Zampini       o = PetscMax(o,onz[i+b]);
185453b44cf5SStefano Zampini     }
185553b44cf5SStefano Zampini     dnz[i/bs] = PetscMin(d/bs + d%bs,lcols/bs);
185653b44cf5SStefano Zampini     onz[i/bs] = PetscMin(o/bs + o%bs,(cols-lcols)/bs);
18573927de2eSStefano Zampini   }
18589566063dSJacob Faibussowitsch   PetscCall(MatSeqBAIJSetPreallocation(B,bs,0,dnz));
18599566063dSJacob Faibussowitsch   PetscCall(MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz));
18609566063dSJacob Faibussowitsch   PetscCall(MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz));
1861d0609cedSBarry Smith   MatPreallocateEnd(dnz,onz);
18629566063dSJacob Faibussowitsch   if (issbaij) PetscCall(MatRestoreRowUpperTriangular(matis->A));
18639566063dSJacob Faibussowitsch   PetscCall(MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE));
18643927de2eSStefano Zampini   PetscFunctionReturn(0);
18653927de2eSStefano Zampini }
18663927de2eSStefano Zampini 
1867487b449aSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_IS_XAIJ(Mat mat, MatType mtype, MatReuse reuse, Mat *M)
1868b7ce53b6SStefano Zampini {
1869b7ce53b6SStefano Zampini   Mat_IS            *matis = (Mat_IS*)(mat->data);
1870487b449aSStefano Zampini   Mat               local_mat,MT;
187153b44cf5SStefano Zampini   PetscInt          rbs,cbs,rows,cols,lrows,lcols;
1872b7ce53b6SStefano Zampini   PetscInt          local_rows,local_cols;
1873b9ed4604SStefano Zampini   PetscBool         isseqdense,isseqsbaij,isseqaij,isseqbaij;
1874f03112d0SStefano Zampini   PetscMPIInt       size;
18751683a169SBarry Smith   const PetscScalar *array;
1876b7ce53b6SStefano Zampini 
1877b7ce53b6SStefano Zampini   PetscFunctionBegin;
18789566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size));
1879f03112d0SStefano Zampini   if (size == 1 && mat->rmap->N == matis->A->rmap->N && mat->cmap->N == matis->A->cmap->N) {
18801670daf9Sstefano_zampini     Mat      B;
188153b44cf5SStefano Zampini     IS       irows = NULL,icols = NULL;
1882487b449aSStefano Zampini     PetscInt rbs,cbs;
18831670daf9Sstefano_zampini 
18849566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->rmapping,&rbs));
18859566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->cmapping,&cbs));
188653b44cf5SStefano Zampini     if (reuse != MAT_REUSE_MATRIX) { /* check if l2g maps are one-to-one */
188753b44cf5SStefano Zampini       IS             rows,cols;
188853b44cf5SStefano Zampini       const PetscInt *ridxs,*cidxs;
188953b44cf5SStefano Zampini       PetscInt       i,nw,*work;
189053b44cf5SStefano Zampini 
18919566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingGetBlockIndices(matis->rmapping,&ridxs));
18929566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingGetSize(matis->rmapping,&nw));
189353b44cf5SStefano Zampini       nw   = nw/rbs;
18949566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(nw,&work));
189553b44cf5SStefano Zampini       for (i=0;i<nw;i++) work[ridxs[i]] += 1;
189653b44cf5SStefano Zampini       for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break;
189753b44cf5SStefano Zampini       if (i == nw) {
18989566063dSJacob Faibussowitsch         PetscCall(ISCreateBlock(PETSC_COMM_SELF,rbs,nw,ridxs,PETSC_USE_POINTER,&rows));
18999566063dSJacob Faibussowitsch         PetscCall(ISSetPermutation(rows));
19009566063dSJacob Faibussowitsch         PetscCall(ISInvertPermutation(rows,PETSC_DECIDE,&irows));
19019566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&rows));
190253b44cf5SStefano Zampini       }
19039566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(matis->rmapping,&ridxs));
19049566063dSJacob Faibussowitsch       PetscCall(PetscFree(work));
1905e432b41dSStefano Zampini       if (irows && matis->rmapping != matis->cmapping) {
19069566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingGetBlockIndices(matis->cmapping,&cidxs));
19079566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingGetSize(matis->cmapping,&nw));
190853b44cf5SStefano Zampini         nw   = nw/cbs;
19099566063dSJacob Faibussowitsch         PetscCall(PetscCalloc1(nw,&work));
191053b44cf5SStefano Zampini         for (i=0;i<nw;i++) work[cidxs[i]] += 1;
191153b44cf5SStefano Zampini         for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break;
191253b44cf5SStefano Zampini         if (i == nw) {
19139566063dSJacob Faibussowitsch           PetscCall(ISCreateBlock(PETSC_COMM_SELF,cbs,nw,cidxs,PETSC_USE_POINTER,&cols));
19149566063dSJacob Faibussowitsch           PetscCall(ISSetPermutation(cols));
19159566063dSJacob Faibussowitsch           PetscCall(ISInvertPermutation(cols,PETSC_DECIDE,&icols));
19169566063dSJacob Faibussowitsch           PetscCall(ISDestroy(&cols));
191753b44cf5SStefano Zampini         }
19189566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(matis->cmapping,&cidxs));
19199566063dSJacob Faibussowitsch         PetscCall(PetscFree(work));
192053b44cf5SStefano Zampini       } else if (irows) {
19219566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)irows));
192253b44cf5SStefano Zampini         icols = irows;
192353b44cf5SStefano Zampini       }
192453b44cf5SStefano Zampini     } else {
19259566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject*)&irows));
19269566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject*)&icols));
19279566063dSJacob Faibussowitsch       if (irows) PetscCall(PetscObjectReference((PetscObject)irows));
19289566063dSJacob Faibussowitsch       if (icols) PetscCall(PetscObjectReference((PetscObject)icols));
192953b44cf5SStefano Zampini     }
193053b44cf5SStefano Zampini     if (!irows || !icols) {
19319566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&icols));
19329566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&irows));
193353b44cf5SStefano Zampini       goto general_assembly;
193453b44cf5SStefano Zampini     }
19359566063dSJacob Faibussowitsch     PetscCall(MatConvert(matis->A,mtype,MAT_INITIAL_MATRIX,&B));
1936487b449aSStefano Zampini     if (reuse != MAT_INPLACE_MATRIX) {
19379566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(B,irows,icols,reuse,M));
19389566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject)irows));
19399566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject)icols));
1940487b449aSStefano Zampini     } else {
1941487b449aSStefano Zampini       Mat C;
1942487b449aSStefano Zampini 
19439566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(B,irows,icols,MAT_INITIAL_MATRIX,&C));
19449566063dSJacob Faibussowitsch       PetscCall(MatHeaderReplace(mat,&C));
1945487b449aSStefano Zampini     }
19469566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
19479566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&icols));
19489566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&irows));
19497c03b4e8SStefano Zampini     PetscFunctionReturn(0);
19507c03b4e8SStefano Zampini   }
195153b44cf5SStefano Zampini general_assembly:
19529566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat,&rows,&cols));
19539566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->rmapping,&rbs));
19549566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->cmapping,&cbs));
19559566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mat,&lrows,&lcols));
19569566063dSJacob Faibussowitsch   PetscCall(MatGetSize(matis->A,&local_rows,&local_cols));
19579566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense));
19589566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij));
19599566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij));
19609566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij));
1961aed4548fSBarry Smith   PetscCheck(isseqdense || isseqaij || isseqbaij || isseqsbaij,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name);
196276bd3646SJed Brown   if (PetscDefined (USE_DEBUG)) {
196376bd3646SJed Brown     PetscBool         lb[4],bb[4];
196476bd3646SJed Brown 
1965b9ed4604SStefano Zampini     lb[0] = isseqdense;
1966b9ed4604SStefano Zampini     lb[1] = isseqaij;
1967b9ed4604SStefano Zampini     lb[2] = isseqbaij;
1968b9ed4604SStefano Zampini     lb[3] = isseqsbaij;
19691c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat)));
1970aed4548fSBarry Smith     PetscCheck(bb[0] || bb[1] || bb[2] || bb[3],PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type");
197176bd3646SJed Brown   }
1972b7ce53b6SStefano Zampini 
1973487b449aSStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
19749566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat),&MT));
19759566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(MT,lrows,lcols,rows,cols));
19769566063dSJacob Faibussowitsch     PetscCall(MatSetType(MT,mtype));
19779566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizes(MT,rbs,cbs));
19789566063dSJacob Faibussowitsch     PetscCall(MatISSetMPIXAIJPreallocation_Private(mat,MT,PETSC_FALSE));
1979b7ce53b6SStefano Zampini   } else {
198053b44cf5SStefano Zampini     PetscInt mrbs,mcbs,mrows,mcols,mlrows,mlcols;
1981487b449aSStefano Zampini 
1982b7ce53b6SStefano Zampini     /* some checks */
1983487b449aSStefano Zampini     MT   = *M;
19849566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSizes(MT,&mrbs,&mcbs));
19859566063dSJacob Faibussowitsch     PetscCall(MatGetSize(MT,&mrows,&mcols));
19869566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(MT,&mlrows,&mlcols));
198708401ef6SPierre Jolivet     PetscCheck(mrows == rows,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%" PetscInt_FMT " != %" PetscInt_FMT ")",rows,mrows);
198808401ef6SPierre Jolivet     PetscCheck(mcols == cols,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%" PetscInt_FMT " != %" PetscInt_FMT ")",cols,mcols);
198908401ef6SPierre Jolivet     PetscCheck(mlrows == lrows,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%" PetscInt_FMT " != %" PetscInt_FMT ")",lrows,mlrows);
199008401ef6SPierre Jolivet     PetscCheck(mlcols == lcols,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%" PetscInt_FMT " != %" PetscInt_FMT ")",lcols,mlcols);
199108401ef6SPierre Jolivet     PetscCheck(mrbs == rbs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong row block size (%" PetscInt_FMT " != %" PetscInt_FMT ")",rbs,mrbs);
199208401ef6SPierre Jolivet     PetscCheck(mcbs == cbs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong col block size (%" PetscInt_FMT " != %" PetscInt_FMT ")",cbs,mcbs);
19939566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries(MT));
1994b7ce53b6SStefano Zampini   }
1995d9a9e74cSStefano Zampini 
19968546b261SStefano Zampini   if (isseqsbaij || isseqbaij) {
19979566063dSJacob Faibussowitsch     PetscCall(MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&local_mat));
19988546b261SStefano Zampini     isseqaij = PETSC_TRUE;
1999d9a9e74cSStefano Zampini   } else {
20009566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)matis->A));
2001d9a9e74cSStefano Zampini     local_mat = matis->A;
2002d9a9e74cSStefano Zampini   }
2003686e3a49SStefano Zampini 
2004b7ce53b6SStefano Zampini   /* Set values */
20059566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(MT,matis->rmapping,matis->cmapping));
2006b9ed4604SStefano Zampini   if (isseqdense) { /* special case for dense local matrices */
200765066ba5SStefano Zampini     PetscInt          i,*dummy;
2008ecf5a873SStefano Zampini 
20099566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(PetscMax(local_rows,local_cols),&dummy));
201065066ba5SStefano Zampini     for (i=0;i<PetscMax(local_rows,local_cols);i++) dummy[i] = i;
20119566063dSJacob Faibussowitsch     PetscCall(MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_FALSE));
20129566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(local_mat,&array));
20139566063dSJacob Faibussowitsch     PetscCall(MatSetValuesLocal(MT,local_rows,dummy,local_cols,dummy,array,ADD_VALUES));
20149566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(local_mat,&array));
20159566063dSJacob Faibussowitsch     PetscCall(PetscFree(dummy));
2016686e3a49SStefano Zampini   } else if (isseqaij) {
20176afe12f5SStefano Zampini     const PetscInt *blocks;
20186afe12f5SStefano Zampini     PetscInt       i,nvtxs,*xadj,*adjncy, nb;
2019686e3a49SStefano Zampini     PetscBool      done;
20201683a169SBarry Smith     PetscScalar    *sarray;
2021686e3a49SStefano Zampini 
20229566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done));
202328b400f6SJacob Faibussowitsch     PetscCheck(done,PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
20249566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArray(local_mat,&sarray));
20259566063dSJacob Faibussowitsch     PetscCall(MatGetVariableBlockSizes(local_mat,&nb,&blocks));
20266afe12f5SStefano Zampini     if (nb) { /* speed up assembly for special blocked matrices (used by BDDC) */
20276afe12f5SStefano Zampini       PetscInt sum;
20286afe12f5SStefano Zampini 
20296afe12f5SStefano Zampini       for (i=0,sum=0;i<nb;i++) sum += blocks[i];
20306afe12f5SStefano Zampini       if (sum == nvtxs) {
20316afe12f5SStefano Zampini         PetscInt r;
20326afe12f5SStefano Zampini 
20336afe12f5SStefano Zampini         for (i=0,r=0;i<nb;i++) {
20346bdcaf15SBarry 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]);
20359566063dSJacob Faibussowitsch           PetscCall(MatSetValuesLocal(MT,blocks[i],adjncy+xadj[r],blocks[i],adjncy+xadj[r],sarray+xadj[r],ADD_VALUES));
20366afe12f5SStefano Zampini           r   += blocks[i];
20376afe12f5SStefano Zampini         }
20386afe12f5SStefano Zampini       } else {
2039686e3a49SStefano Zampini         for (i=0;i<nvtxs;i++) {
20409566063dSJacob Faibussowitsch           PetscCall(MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],sarray+xadj[i],ADD_VALUES));
2041686e3a49SStefano Zampini         }
20426afe12f5SStefano Zampini       }
20436afe12f5SStefano Zampini     } else {
20446afe12f5SStefano Zampini       for (i=0;i<nvtxs;i++) {
20459566063dSJacob Faibussowitsch         PetscCall(MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],sarray+xadj[i],ADD_VALUES));
20466afe12f5SStefano Zampini       }
20476afe12f5SStefano Zampini     }
20489566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done));
204928b400f6SJacob Faibussowitsch     PetscCheck(done,PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
20509566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJRestoreArray(local_mat,&sarray));
2051686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
2052ecf5a873SStefano Zampini     PetscInt i;
2053c0962df8SStefano Zampini 
2054686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
2055686e3a49SStefano Zampini       PetscInt       j;
2056ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
2057686e3a49SStefano Zampini 
20589566063dSJacob Faibussowitsch       PetscCall(MatGetRow(local_mat,i,&j,&local_indices_cols,&array));
20599566063dSJacob Faibussowitsch       PetscCall(MatSetValuesLocal(MT,1,&i,j,local_indices_cols,array,ADD_VALUES));
20609566063dSJacob Faibussowitsch       PetscCall(MatRestoreRow(local_mat,i,&j,&local_indices_cols,&array));
2061686e3a49SStefano Zampini     }
2062b7ce53b6SStefano Zampini   }
20639566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(MT,MAT_FINAL_ASSEMBLY));
20649566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&local_mat));
20659566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(MT,MAT_FINAL_ASSEMBLY));
20661baa6e33SBarry Smith   if (isseqdense) PetscCall(MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_TRUE));
2067487b449aSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
20689566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(mat,&MT));
2069487b449aSStefano Zampini   } else if (reuse == MAT_INITIAL_MATRIX) {
2070487b449aSStefano Zampini     *M = MT;
2071b7ce53b6SStefano Zampini   }
2072b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
2073b7ce53b6SStefano Zampini }
2074b7ce53b6SStefano Zampini 
2075b7ce53b6SStefano Zampini /*@
2076b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
2077b7ce53b6SStefano Zampini 
2078d8d19677SJose E. Roman   Input Parameters:
2079a2b725a8SWilliam Gropp +  mat - the matrix (should be of type MATIS)
2080a2b725a8SWilliam Gropp -  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
2081b7ce53b6SStefano Zampini 
2082b7ce53b6SStefano Zampini   Output Parameter:
2083b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
2084b7ce53b6SStefano Zampini 
2085b7ce53b6SStefano Zampini   Level: developer
2086b7ce53b6SStefano Zampini 
208795452b02SPatrick Sanan   Notes:
2088487b449aSStefano Zampini     This function has been deprecated and it will be removed in future releases. Update your code to use the MatConvert() interface.
2089b7ce53b6SStefano Zampini 
2090db781477SPatrick Sanan .seealso: `MATIS`, `MatConvert()`
2091b7ce53b6SStefano Zampini @*/
2092b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
2093b7ce53b6SStefano Zampini {
2094b7ce53b6SStefano Zampini   PetscFunctionBegin;
2095b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2096b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
2097b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
2098487b449aSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
2099b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
2100b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
210108401ef6SPierre Jolivet     PetscCheck(mat != *newmat,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
2102b7ce53b6SStefano Zampini   }
2103cac4c232SBarry Smith   PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatType,MatReuse,Mat*),(mat,MATAIJ,reuse,newmat));
2104b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
2105b7ce53b6SStefano Zampini }
2106b7ce53b6SStefano Zampini 
21078b9382cfSStefano Zampini static PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
2108ad6194a2SStefano Zampini {
2109ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
2110c9225affSStefano Zampini   PetscInt       rbs,cbs,m,n,M,N;
2111ad6194a2SStefano Zampini   Mat            B,localmat;
2112ad6194a2SStefano Zampini 
2113ad6194a2SStefano Zampini   PetscFunctionBegin;
21149566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs));
21159566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs));
21169566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat,&M,&N));
21179566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mat,&m,&n));
21189566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat),&B));
21199566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(B,m,n,M,N));
21209566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(B,rbs == cbs ? rbs : 1));
21219566063dSJacob Faibussowitsch   PetscCall(MatSetType(B,MATIS));
21229566063dSJacob Faibussowitsch   PetscCall(MatISSetLocalMatType(B,matis->lmattype));
21239566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(B,mat->rmap->mapping,mat->cmap->mapping));
21249566063dSJacob Faibussowitsch   PetscCall(MatDuplicate(matis->A,op,&localmat));
21259566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(localmat,matis->A->rmap->mapping,matis->A->cmap->mapping));
21269566063dSJacob Faibussowitsch   PetscCall(MatISSetLocalMat(B,localmat));
21279566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&localmat));
21289566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
21299566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
2130ad6194a2SStefano Zampini   *newmat = B;
2131ad6194a2SStefano Zampini   PetscFunctionReturn(0);
2132ad6194a2SStefano Zampini }
2133ad6194a2SStefano Zampini 
2134a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
213569796d55SStefano Zampini {
213669796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
213769796d55SStefano Zampini   PetscBool      local_sym;
213869796d55SStefano Zampini 
213969796d55SStefano Zampini   PetscFunctionBegin;
21409566063dSJacob Faibussowitsch   PetscCall(MatIsHermitian(matis->A,tol,&local_sym));
21411c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A)));
214269796d55SStefano Zampini   PetscFunctionReturn(0);
214369796d55SStefano Zampini }
214469796d55SStefano Zampini 
2145a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool *flg)
214669796d55SStefano Zampini {
214769796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
214869796d55SStefano Zampini   PetscBool      local_sym;
214969796d55SStefano Zampini 
215069796d55SStefano Zampini   PetscFunctionBegin;
2151e432b41dSStefano Zampini   if (matis->rmapping != matis->cmapping) {
2152e432b41dSStefano Zampini     *flg = PETSC_FALSE;
2153e432b41dSStefano Zampini     PetscFunctionReturn(0);
2154e432b41dSStefano Zampini   }
21559566063dSJacob Faibussowitsch   PetscCall(MatIsSymmetric(matis->A,tol,&local_sym));
21561c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A)));
215769796d55SStefano Zampini   PetscFunctionReturn(0);
215869796d55SStefano Zampini }
215969796d55SStefano Zampini 
216045471136SStefano Zampini static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool *flg)
216145471136SStefano Zampini {
216245471136SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
216345471136SStefano Zampini   PetscBool      local_sym;
216445471136SStefano Zampini 
216545471136SStefano Zampini   PetscFunctionBegin;
2166e432b41dSStefano Zampini   if (matis->rmapping != matis->cmapping) {
216745471136SStefano Zampini     *flg = PETSC_FALSE;
216845471136SStefano Zampini     PetscFunctionReturn(0);
216945471136SStefano Zampini   }
21709566063dSJacob Faibussowitsch   PetscCall(MatIsStructurallySymmetric(matis->A,&local_sym));
21711c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A)));
217245471136SStefano Zampini   PetscFunctionReturn(0);
217345471136SStefano Zampini }
217445471136SStefano Zampini 
2175a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
2176b4319ba4SBarry Smith {
2177b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
2178b4319ba4SBarry Smith 
2179b4319ba4SBarry Smith   PetscFunctionBegin;
21809566063dSJacob Faibussowitsch   PetscCall(PetscFree(b->bdiag));
21819566063dSJacob Faibussowitsch   PetscCall(PetscFree(b->lmattype));
21829566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&b->A));
21839566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&b->cctx));
21849566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&b->rctx));
21859566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&b->x));
21869566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&b->y));
21879566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&b->counter));
21889566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&b->getsub_ris));
21899566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&b->getsub_cis));
2190a8116848SStefano Zampini   if (b->sf != b->csf) {
21919566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&b->csf));
21929566063dSJacob Faibussowitsch     PetscCall(PetscFree2(b->csf_rootdata,b->csf_leafdata));
2193f03112d0SStefano Zampini   } else b->csf = NULL;
21949566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&b->sf));
21959566063dSJacob Faibussowitsch   PetscCall(PetscFree2(b->sf_rootdata,b->sf_leafdata));
21969566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&b->rmapping));
21979566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&b->cmapping));
2198d0dbe9f7SStefano Zampini   PetscCall(MatDestroy(&b->dA));
2199d0dbe9f7SStefano Zampini   PetscCall(MatDestroy(&b->assembledA));
22009566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->data));
22019566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)A,NULL));
22029566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMatType_C",NULL));
22039566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL));
22049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL));
22052e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISRestoreLocalMat_C",NULL));
22069566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL));
22079566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL));
22089566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",NULL));
22099566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",NULL));
22109566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalToGlobalMapping_C",NULL));
22119566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",NULL));
22129566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",NULL));
22139566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",NULL));
22149566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",NULL));
22159566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",NULL));
22169566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",NULL));
22179566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",NULL));
22189566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOOLocal_C",NULL));
22199566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOO_C",NULL));
22209566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetValuesCOO_C",NULL));
2221b4319ba4SBarry Smith   PetscFunctionReturn(0);
2222b4319ba4SBarry Smith }
2223b4319ba4SBarry Smith 
2224a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
2225b4319ba4SBarry Smith {
2226b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
2227b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
2228b4319ba4SBarry Smith 
2229b4319ba4SBarry Smith   PetscFunctionBegin;
2230b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
22319566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD));
22329566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD));
2233b4319ba4SBarry Smith 
2234b4319ba4SBarry Smith   /* multiply the local matrix */
22359566063dSJacob Faibussowitsch   PetscCall(MatMult(is->A,is->x,is->y));
2236b4319ba4SBarry Smith 
2237b4319ba4SBarry Smith   /* scatter product back into global memory */
22389566063dSJacob Faibussowitsch   PetscCall(VecSet(y,zero));
22399566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE));
22409566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE));
2241b4319ba4SBarry Smith   PetscFunctionReturn(0);
2242b4319ba4SBarry Smith }
2243b4319ba4SBarry Smith 
2244a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
22452e74eeadSLisandro Dalcin {
2246650997f4SStefano Zampini   Vec            temp_vec;
22472e74eeadSLisandro Dalcin 
22482e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
2249650997f4SStefano Zampini   if (v3 != v2) {
22509566063dSJacob Faibussowitsch     PetscCall(MatMult(A,v1,v3));
22519566063dSJacob Faibussowitsch     PetscCall(VecAXPY(v3,1.0,v2));
2252650997f4SStefano Zampini   } else {
22539566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(v2,&temp_vec));
22549566063dSJacob Faibussowitsch     PetscCall(MatMult(A,v1,temp_vec));
22559566063dSJacob Faibussowitsch     PetscCall(VecAXPY(temp_vec,1.0,v2));
22569566063dSJacob Faibussowitsch     PetscCall(VecCopy(temp_vec,v3));
22579566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&temp_vec));
2258650997f4SStefano Zampini   }
22592e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
22602e74eeadSLisandro Dalcin }
22612e74eeadSLisandro Dalcin 
2262a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
22632e74eeadSLisandro Dalcin {
22642e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
22652e74eeadSLisandro Dalcin 
2266e176bc59SStefano Zampini   PetscFunctionBegin;
22672e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
22689566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD));
22699566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD));
22702e74eeadSLisandro Dalcin 
22712e74eeadSLisandro Dalcin   /* multiply the local matrix */
22729566063dSJacob Faibussowitsch   PetscCall(MatMultTranspose(is->A,is->y,is->x));
22732e74eeadSLisandro Dalcin 
22742e74eeadSLisandro Dalcin   /* scatter product back into global vector */
22759566063dSJacob Faibussowitsch   PetscCall(VecSet(x,0));
22769566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE));
22779566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE));
22782e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
22792e74eeadSLisandro Dalcin }
22802e74eeadSLisandro Dalcin 
2281a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
22822e74eeadSLisandro Dalcin {
2283650997f4SStefano Zampini   Vec            temp_vec;
22842e74eeadSLisandro Dalcin 
22852e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
2286650997f4SStefano Zampini   if (v3 != v2) {
22879566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(A,v1,v3));
22889566063dSJacob Faibussowitsch     PetscCall(VecAXPY(v3,1.0,v2));
2289650997f4SStefano Zampini   } else {
22909566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(v2,&temp_vec));
22919566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(A,v1,temp_vec));
22929566063dSJacob Faibussowitsch     PetscCall(VecAXPY(temp_vec,1.0,v2));
22939566063dSJacob Faibussowitsch     PetscCall(VecCopy(temp_vec,v3));
22949566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&temp_vec));
2295650997f4SStefano Zampini   }
22962e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
22972e74eeadSLisandro Dalcin }
22982e74eeadSLisandro Dalcin 
2299a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
2300b4319ba4SBarry Smith {
2301b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
2302b4319ba4SBarry Smith   PetscViewer    sviewer;
2303ee2491ecSStefano Zampini   PetscBool      isascii,view = PETSC_TRUE;
2304b4319ba4SBarry Smith 
2305b4319ba4SBarry Smith   PetscFunctionBegin;
23069566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
2307ee2491ecSStefano Zampini   if (isascii)  {
2308ee2491ecSStefano Zampini     PetscViewerFormat format;
2309ee2491ecSStefano Zampini 
23109566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer,&format));
2311ee2491ecSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE;
2312ee2491ecSStefano Zampini   }
2313ee2491ecSStefano Zampini   if (!view) PetscFunctionReturn(0);
23149566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer));
23159566063dSJacob Faibussowitsch   PetscCall(MatView(a->A,sviewer));
23169566063dSJacob Faibussowitsch   PetscCall(PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer));
23179566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
2318b4319ba4SBarry Smith   PetscFunctionReturn(0);
2319b4319ba4SBarry Smith }
2320b4319ba4SBarry Smith 
2321b89f26deSStefano Zampini static PetscErrorCode MatInvertBlockDiagonal_IS(Mat mat,const PetscScalar **values)
2322b89f26deSStefano Zampini {
2323b89f26deSStefano Zampini   Mat_IS            *is = (Mat_IS*)mat->data;
2324b89f26deSStefano Zampini   MPI_Datatype      nodeType;
2325b89f26deSStefano Zampini   const PetscScalar *lv;
2326b89f26deSStefano Zampini   PetscInt          bs;
2327b89f26deSStefano Zampini 
2328b89f26deSStefano Zampini   PetscFunctionBegin;
23299566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(mat,&bs));
23309566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(is->A,bs));
23319566063dSJacob Faibussowitsch   PetscCall(MatInvertBlockDiagonal(is->A,&lv));
2332b89f26deSStefano Zampini   if (!is->bdiag) {
23339566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(bs*mat->rmap->n,&is->bdiag));
2334b89f26deSStefano Zampini   }
23359566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Type_contiguous(bs,MPIU_SCALAR,&nodeType));
23369566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Type_commit(&nodeType));
23379566063dSJacob Faibussowitsch   PetscCall(PetscSFReduceBegin(is->sf,nodeType,lv,is->bdiag,MPI_REPLACE));
23389566063dSJacob Faibussowitsch   PetscCall(PetscSFReduceEnd(is->sf,nodeType,lv,is->bdiag,MPI_REPLACE));
23399566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Type_free(&nodeType));
2340b89f26deSStefano Zampini   if (values) *values = is->bdiag;
2341b89f26deSStefano Zampini   PetscFunctionReturn(0);
2342b89f26deSStefano Zampini }
2343b89f26deSStefano Zampini 
23448546b261SStefano Zampini static PetscErrorCode MatISSetUpScatters_Private(Mat A)
2345b4319ba4SBarry Smith {
2346e176bc59SStefano Zampini   Vec            cglobal,rglobal;
23478546b261SStefano Zampini   IS             from;
23488546b261SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
2349b89f26deSStefano Zampini   PetscScalar    sum;
23508546b261SStefano Zampini   const PetscInt *garray;
23518546b261SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
2352e432b41dSStefano Zampini   VecType        rtype;
2353b4319ba4SBarry Smith 
2354b4319ba4SBarry Smith   PetscFunctionBegin;
23559566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(is->rmapping,&nr));
23569566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(is->rmapping,&rbs));
23579566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(is->cmapping,&nc));
23589566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(is->cmapping,&cbs));
23599566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&is->x));
23609566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&is->y));
23619566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&is->counter));
23629566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&is->rctx));
23639566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&is->cctx));
23649566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(is->A,&is->x,&is->y));
23659566063dSJacob Faibussowitsch   PetscCall(VecBindToCPU(is->y,PETSC_TRUE));
23669566063dSJacob Faibussowitsch   PetscCall(VecGetRootType_Private(is->y,&rtype));
23679566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->defaultvectype));
23689566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(rtype,&A->defaultvectype));
23699566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(A,&cglobal,&rglobal));
23709566063dSJacob Faibussowitsch   PetscCall(VecBindToCPU(rglobal,PETSC_TRUE));
23719566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->rmapping,&garray));
23729566063dSJacob Faibussowitsch   PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A),rbs,nr/rbs,garray,PETSC_USE_POINTER,&from));
23739566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(rglobal,from,is->y,NULL,&is->rctx));
23749566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->rmapping,&garray));
23759566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&from));
2376e432b41dSStefano Zampini   if (is->rmapping != is->cmapping) {
23779566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->cmapping,&garray));
23789566063dSJacob Faibussowitsch     PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A),cbs,nc/cbs,garray,PETSC_USE_POINTER,&from));
23799566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(cglobal,from,is->x,NULL,&is->cctx));
23809566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->cmapping,&garray));
23819566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&from));
23828546b261SStefano Zampini   } else {
23839566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)is->rctx));
23848546b261SStefano Zampini     is->cctx = is->rctx;
23858546b261SStefano Zampini   }
23869566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&cglobal));
2387b89f26deSStefano Zampini 
23888546b261SStefano Zampini   /* interface counter vector (local) */
23899566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(is->y,&is->counter));
23909566063dSJacob Faibussowitsch   PetscCall(VecBindToCPU(is->counter,PETSC_TRUE));
23919566063dSJacob Faibussowitsch   PetscCall(VecSet(is->y,1.));
23929566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE));
23939566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE));
23949566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD));
23959566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD));
23969566063dSJacob Faibussowitsch   PetscCall(VecBindToCPU(is->y,PETSC_FALSE));
23979566063dSJacob Faibussowitsch   PetscCall(VecBindToCPU(is->counter,PETSC_FALSE));
2398b89f26deSStefano Zampini 
2399b89f26deSStefano Zampini   /* special functions for block-diagonal matrices */
24009566063dSJacob Faibussowitsch   PetscCall(VecSum(rglobal,&sum));
2401b89f26deSStefano Zampini   A->ops->invertblockdiagonal = NULL;
2402e432b41dSStefano Zampini   if ((PetscInt)(PetscRealPart(sum)) == A->rmap->N && A->rmap->N == A->cmap->N && is->rmapping == is->cmapping) A->ops->invertblockdiagonal = MatInvertBlockDiagonal_IS;
24039566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&rglobal));
2404b0cc1f67SStefano Zampini 
2405b0cc1f67SStefano Zampini   /* setup SF for general purpose shared indices based communications */
24069566063dSJacob Faibussowitsch   PetscCall(MatISSetUpSF_IS(A));
24078546b261SStefano Zampini   PetscFunctionReturn(0);
24088546b261SStefano Zampini }
24098546b261SStefano Zampini 
2410e432b41dSStefano Zampini static PetscErrorCode MatISFilterL2GMap(Mat A, ISLocalToGlobalMapping map, ISLocalToGlobalMapping *nmap, ISLocalToGlobalMapping *lmap)
2411e432b41dSStefano Zampini {
2412e432b41dSStefano Zampini   IS                         is;
2413e432b41dSStefano Zampini   ISLocalToGlobalMappingType l2gtype;
2414e432b41dSStefano Zampini   const PetscInt             *idxs;
2415e432b41dSStefano Zampini   PetscHSetI                 ht;
2416e432b41dSStefano Zampini   PetscInt                   *nidxs;
2417e432b41dSStefano Zampini   PetscInt                   i,n,bs,c;
2418e432b41dSStefano Zampini   PetscBool                  flg[] = {PETSC_FALSE,PETSC_FALSE};
2419e432b41dSStefano Zampini 
2420e432b41dSStefano Zampini   PetscFunctionBegin;
24219566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(map,&n));
24229566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(map,&bs));
24239566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockIndices(map,&idxs));
24249566063dSJacob Faibussowitsch   PetscCall(PetscHSetICreate(&ht));
24259566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n/bs,&nidxs));
2426e432b41dSStefano Zampini   for (i=0,c=0;i<n/bs;i++) {
2427e432b41dSStefano Zampini     PetscBool missing;
2428e432b41dSStefano Zampini     if (idxs[i] < 0) { flg[0] = PETSC_TRUE; continue; }
24299566063dSJacob Faibussowitsch     PetscCall(PetscHSetIQueryAdd(ht,idxs[i],&missing));
2430e432b41dSStefano Zampini     if (!missing) flg[1] = PETSC_TRUE;
2431e432b41dSStefano Zampini     else nidxs[c++] = idxs[i];
2432e432b41dSStefano Zampini   }
24339566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDestroy(&ht));
24341c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(MPI_IN_PLACE,flg,2,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A)));
2435e432b41dSStefano Zampini   if (!flg[0] && !flg[1]) { /* Entries are all non negative and unique */
2436e432b41dSStefano Zampini     *nmap = NULL;
2437e432b41dSStefano Zampini     *lmap = NULL;
24389566063dSJacob Faibussowitsch     PetscCall(PetscFree(nidxs));
24399566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(map,&idxs));
2440e432b41dSStefano Zampini     PetscFunctionReturn(0);
2441e432b41dSStefano Zampini   }
2442e432b41dSStefano Zampini 
2443e432b41dSStefano Zampini   /* New l2g map without negative or repeated indices */
24449566063dSJacob Faibussowitsch   PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A),bs,c,nidxs,PETSC_USE_POINTER,&is));
24459566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(is,nmap));
24469566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
24479566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetType(map,&l2gtype));
24489566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingSetType(*nmap,l2gtype));
2449e432b41dSStefano Zampini 
2450e432b41dSStefano Zampini   /* New local l2g map for repeated indices */
24519566063dSJacob Faibussowitsch   PetscCall(ISGlobalToLocalMappingApplyBlock(*nmap,IS_GTOLM_MASK,n/bs,idxs,NULL,nidxs));
24529566063dSJacob Faibussowitsch   PetscCall(ISCreateBlock(PETSC_COMM_SELF,bs,n/bs,nidxs,PETSC_USE_POINTER,&is));
24539566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(is,lmap));
24549566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
2455e432b41dSStefano Zampini 
24569566063dSJacob Faibussowitsch   PetscCall(PetscFree(nidxs));
24579566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(map,&idxs));
2458e432b41dSStefano Zampini   PetscFunctionReturn(0);
2459e432b41dSStefano Zampini }
2460e432b41dSStefano Zampini 
24618546b261SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
24628546b261SStefano Zampini {
24638546b261SStefano Zampini   Mat_IS                 *is = (Mat_IS*)A->data;
2464e432b41dSStefano Zampini   ISLocalToGlobalMapping localrmapping = NULL, localcmapping = NULL;
2465e432b41dSStefano Zampini   PetscBool              cong, freem[] = { PETSC_FALSE, PETSC_FALSE };
2466e432b41dSStefano Zampini   PetscInt               nr,rbs,nc,cbs;
24678546b261SStefano Zampini 
24688546b261SStefano Zampini   PetscFunctionBegin;
2469fc989267SStefano Zampini   if (rmapping) PetscCheckSameComm(A,1,rmapping,2);
2470fc989267SStefano Zampini   if (cmapping) PetscCheckSameComm(A,1,cmapping,3);
2471e432b41dSStefano Zampini 
24729566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&is->rmapping));
24739566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&is->cmapping));
24749566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
24759566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
24769566063dSJacob Faibussowitsch   PetscCall(MatHasCongruentLayouts(A,&cong));
2477e432b41dSStefano Zampini 
2478fc989267SStefano Zampini   /* If NULL, local space matches global space */
2479fc989267SStefano Zampini   if (!rmapping) {
2480fc989267SStefano Zampini     IS is;
2481fc989267SStefano Zampini 
24829566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A),A->rmap->N,0,1,&is));
24839566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is,&rmapping));
24849566063dSJacob Faibussowitsch     if (A->rmap->bs > 0) PetscCall(ISLocalToGlobalMappingSetBlockSize(rmapping,A->rmap->bs));
24859566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
2486e432b41dSStefano Zampini     freem[0] = PETSC_TRUE;
2487e432b41dSStefano Zampini     if (!cmapping && cong && A->rmap->bs == A->cmap->bs) cmapping = rmapping;
2488e432b41dSStefano Zampini   } else if (!is->islocalref) { /* check if the l2g map has negative or repeated entries */
24899566063dSJacob Faibussowitsch     PetscCall(MatISFilterL2GMap(A,rmapping,&is->rmapping,&localrmapping));
2490e432b41dSStefano Zampini     if (rmapping == cmapping) {
24919566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)is->rmapping));
2492e432b41dSStefano Zampini       is->cmapping = is->rmapping;
24939566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)localrmapping));
2494e432b41dSStefano Zampini       localcmapping = localrmapping;
2495fc989267SStefano Zampini     }
2496fc989267SStefano Zampini   }
2497fc989267SStefano Zampini   if (!cmapping) {
2498fc989267SStefano Zampini     IS is;
2499fc989267SStefano Zampini 
25009566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A),A->cmap->N,0,1,&is));
25019566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is,&cmapping));
25029566063dSJacob Faibussowitsch     if (A->cmap->bs > 0) PetscCall(ISLocalToGlobalMappingSetBlockSize(cmapping,A->cmap->bs));
25039566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
2504e432b41dSStefano Zampini     freem[1] = PETSC_TRUE;
2505e432b41dSStefano Zampini   } else if (cmapping != rmapping && !is->islocalref) { /* check if the l2g map has negative or repeated entries */
25069566063dSJacob Faibussowitsch     PetscCall(MatISFilterL2GMap(A,cmapping,&is->cmapping,&localcmapping));
2507e432b41dSStefano Zampini   }
2508e432b41dSStefano Zampini   if (!is->rmapping) {
25099566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)rmapping));
2510e432b41dSStefano Zampini     is->rmapping = rmapping;
2511e432b41dSStefano Zampini   }
2512e432b41dSStefano Zampini   if (!is->cmapping) {
25139566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)cmapping));
2514e432b41dSStefano Zampini     is->cmapping = cmapping;
2515fc989267SStefano Zampini   }
2516fc989267SStefano Zampini 
2517fc989267SStefano Zampini   /* Clean up */
25189566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&is->A));
2519872cf891SStefano Zampini   if (is->csf != is->sf) {
25209566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&is->csf));
25219566063dSJacob Faibussowitsch     PetscCall(PetscFree2(is->csf_rootdata,is->csf_leafdata));
2522f03112d0SStefano Zampini   } else is->csf = NULL;
25239566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&is->sf));
25249566063dSJacob Faibussowitsch   PetscCall(PetscFree2(is->sf_rootdata,is->sf_leafdata));
25259566063dSJacob Faibussowitsch   PetscCall(PetscFree(is->bdiag));
25263bbff08aSStefano Zampini 
2527fc989267SStefano Zampini   /* check if the two mappings are actually the same for square matrices since MATIS has some optimization for this case
2528fc989267SStefano Zampini      (DOLFIN passes 2 different objects) */
25299566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(is->rmapping,&nr));
25309566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(is->rmapping,&rbs));
25319566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(is->cmapping,&nc));
25329566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(is->cmapping,&cbs));
2533e432b41dSStefano Zampini   if (is->rmapping != is->cmapping && cong) {
2534e432b41dSStefano Zampini     PetscBool same = PETSC_FALSE;
25356625354bSStefano Zampini     if (nr == nc && cbs == rbs) {
25366625354bSStefano Zampini       const PetscInt *idxs1,*idxs2;
25376625354bSStefano Zampini 
25389566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->rmapping,&idxs1));
25399566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->cmapping,&idxs2));
25409566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(idxs1,idxs2,nr/rbs,&same));
25419566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->rmapping,&idxs1));
25429566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->cmapping,&idxs2));
25436625354bSStefano Zampini     }
25441c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(MPI_IN_PLACE,&same,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A)));
2545e432b41dSStefano Zampini     if (same) {
25469566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingDestroy(&is->cmapping));
25479566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)is->rmapping));
2548e432b41dSStefano Zampini       is->cmapping = is->rmapping;
2549e432b41dSStefano Zampini     }
25506625354bSStefano Zampini   }
25519566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(A->rmap,rbs));
25529566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(A->cmap,cbs));
2553e432b41dSStefano Zampini   /* Pass the user defined maps to the layout */
25549566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping));
25559566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping));
25569566063dSJacob Faibussowitsch   if (freem[0]) PetscCall(ISLocalToGlobalMappingDestroy(&rmapping));
25579566063dSJacob Faibussowitsch   if (freem[1]) PetscCall(ISLocalToGlobalMappingDestroy(&cmapping));
25586625354bSStefano Zampini 
25596625354bSStefano Zampini   /* Create the local matrix A */
25609566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF,&is->A));
25619566063dSJacob Faibussowitsch   PetscCall(MatSetType(is->A,is->lmattype));
25629566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(is->A,nr,nc,nr,nc));
25639566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSizes(is->A,rbs,cbs));
25649566063dSJacob Faibussowitsch   PetscCall(MatSetOptionsPrefix(is->A,"is_"));
25659566063dSJacob Faibussowitsch   PetscCall(MatAppendOptionsPrefix(is->A,((PetscObject)A)->prefix));
25669566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(is->A->rmap));
25679566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(is->A->cmap));
25689566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(is->A,localrmapping,localcmapping));
25699566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&localrmapping));
25709566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&localcmapping));
2571b4319ba4SBarry Smith 
2572fc989267SStefano Zampini   /* setup scatters and local vectors for MatMult */
25739566063dSJacob Faibussowitsch   if (!is->islocalref) PetscCall(MatISSetUpScatters_Private(A));
2574fc989267SStefano Zampini   A->preallocated = PETSC_TRUE;
2575fc989267SStefano Zampini   PetscFunctionReturn(0);
2576fc989267SStefano Zampini }
2577fc989267SStefano Zampini 
2578fc989267SStefano Zampini static PetscErrorCode MatSetUp_IS(Mat A)
2579fc989267SStefano Zampini {
2580fc989267SStefano Zampini   ISLocalToGlobalMapping rmap, cmap;
2581fc989267SStefano Zampini 
2582fc989267SStefano Zampini   PetscFunctionBegin;
25839566063dSJacob Faibussowitsch   PetscCall(MatGetLocalToGlobalMapping(A,&rmap,&cmap));
2584fc989267SStefano Zampini   if (!rmap && !cmap) {
25859566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(A,NULL,NULL));
2586fc989267SStefano Zampini   }
2587b4319ba4SBarry Smith   PetscFunctionReturn(0);
2588b4319ba4SBarry Smith }
2589b4319ba4SBarry Smith 
2590a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
25912e74eeadSLisandro Dalcin {
25922e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
2593f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
25942e74eeadSLisandro Dalcin 
25952e74eeadSLisandro Dalcin   PetscFunctionBegin;
25969566063dSJacob Faibussowitsch   PetscCall(ISGlobalToLocalMappingApply(is->rmapping,IS_GTOLM_MASK,m,rows,&m,rows_l));
2597e432b41dSStefano Zampini   if (m != n || rows != cols || is->cmapping != is->rmapping) {
25989566063dSJacob Faibussowitsch     PetscCall(ISGlobalToLocalMappingApply(is->cmapping,IS_GTOLM_MASK,n,cols,&n,cols_l));
25999566063dSJacob Faibussowitsch     PetscCall(MatSetValues(is->A,m,rows_l,n,cols_l,values,addv));
2600e432b41dSStefano Zampini   } else {
26019566063dSJacob Faibussowitsch     PetscCall(MatSetValues(is->A,m,rows_l,m,rows_l,values,addv));
2602e432b41dSStefano Zampini   }
26032e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
26042e74eeadSLisandro Dalcin }
26052e74eeadSLisandro Dalcin 
2606a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
260797563a80SStefano Zampini {
260897563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
2609f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
261097563a80SStefano Zampini 
261197563a80SStefano Zampini   PetscFunctionBegin;
26129566063dSJacob Faibussowitsch   PetscCall(ISGlobalToLocalMappingApplyBlock(is->rmapping,IS_GTOLM_MASK,m,rows,&m,rows_l));
2613e432b41dSStefano Zampini   if (m != n || rows != cols || is->cmapping != is->rmapping) {
26149566063dSJacob Faibussowitsch     PetscCall(ISGlobalToLocalMappingApply(is->cmapping,IS_GTOLM_MASK,n,cols,&n,cols_l));
26159566063dSJacob Faibussowitsch     PetscCall(MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv));
2616e432b41dSStefano Zampini   } else {
26179566063dSJacob Faibussowitsch     PetscCall(MatSetValuesBlocked(is->A,m,rows_l,n,rows_l,values,addv));
2618e432b41dSStefano Zampini   }
261997563a80SStefano Zampini   PetscFunctionReturn(0);
262097563a80SStefano Zampini }
262197563a80SStefano Zampini 
2622a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
2623b4319ba4SBarry Smith {
2624b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2625b4319ba4SBarry Smith 
2626b4319ba4SBarry Smith   PetscFunctionBegin;
2627e432b41dSStefano Zampini   if (is->A->rmap->mapping || is->A->cmap->mapping) {
26289566063dSJacob Faibussowitsch     PetscCall(MatSetValuesLocal(is->A,m,rows,n,cols,values,addv));
2629872cf891SStefano Zampini   } else {
26309566063dSJacob Faibussowitsch     PetscCall(MatSetValues(is->A,m,rows,n,cols,values,addv));
2631872cf891SStefano Zampini   }
2632b4319ba4SBarry Smith   PetscFunctionReturn(0);
2633b4319ba4SBarry Smith }
2634b4319ba4SBarry Smith 
2635a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
2636f0006bf2SLisandro Dalcin {
2637f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
2638f0006bf2SLisandro Dalcin 
2639f0006bf2SLisandro Dalcin   PetscFunctionBegin;
2640e432b41dSStefano Zampini   if (is->A->rmap->mapping || is->A->cmap->mapping) {
26419566063dSJacob Faibussowitsch     PetscCall(MatSetValuesBlockedLocal(is->A,m,rows,n,cols,values,addv));
2642b4f971dfSStefano Zampini   } else {
26439566063dSJacob Faibussowitsch     PetscCall(MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv));
2644b4f971dfSStefano Zampini   }
2645f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
2646f0006bf2SLisandro Dalcin }
2647f0006bf2SLisandro Dalcin 
2648f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
2649f0ae7da4SStefano Zampini {
2650f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
2651f0ae7da4SStefano Zampini 
2652f0ae7da4SStefano Zampini   PetscFunctionBegin;
2653f0ae7da4SStefano Zampini   if (!n) {
2654f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
2655f0ae7da4SStefano Zampini   } else {
2656f0ae7da4SStefano Zampini     PetscInt i;
2657f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
2658f0ae7da4SStefano Zampini 
2659f0ae7da4SStefano Zampini     if (columns) {
26609566063dSJacob Faibussowitsch       PetscCall(MatZeroRowsColumns(is->A,n,rows,diag,NULL,NULL));
2661f0ae7da4SStefano Zampini     } else {
26629566063dSJacob Faibussowitsch       PetscCall(MatZeroRows(is->A,n,rows,diag,NULL,NULL));
2663f0ae7da4SStefano Zampini     }
2664f0ae7da4SStefano Zampini     if (diag != 0.) {
2665f0ae7da4SStefano Zampini       const PetscScalar *array;
26669566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(is->counter,&array));
2667f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
26689566063dSJacob Faibussowitsch         PetscCall(MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES));
2669f0ae7da4SStefano Zampini       }
26709566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(is->counter,&array));
2671f0ae7da4SStefano Zampini     }
26729566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY));
26739566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY));
2674f0ae7da4SStefano Zampini   }
2675f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
2676f0ae7da4SStefano Zampini }
2677f0ae7da4SStefano Zampini 
2678f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
26792e74eeadSLisandro Dalcin {
26806e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
26816e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
26826e520ac8SStefano Zampini   PetscInt       *lrows;
26832e74eeadSLisandro Dalcin 
26842e74eeadSLisandro Dalcin   PetscFunctionBegin;
2685cf9c20a2SJed Brown   if (PetscUnlikelyDebug(columns || diag != 0. || (x && b))) {
2686f0ae7da4SStefano Zampini     PetscBool cong;
268726b0207aSStefano Zampini 
26889566063dSJacob Faibussowitsch     PetscCall(PetscLayoutCompare(A->rmap,A->cmap,&cong));
268926b0207aSStefano Zampini     cong = (PetscBool)(cong && matis->sf == matis->csf);
269008401ef6SPierre 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");
2691aed4548fSBarry 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");
2692aed4548fSBarry 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");
2693f0ae7da4SStefano Zampini   }
26946e520ac8SStefano Zampini   /* get locally owned rows */
26959566063dSJacob Faibussowitsch   PetscCall(PetscLayoutMapLocal(A->rmap,n,rows,&len,&lrows,NULL));
26966e520ac8SStefano Zampini   /* fix right hand side if needed */
26976e520ac8SStefano Zampini   if (x && b) {
26986e520ac8SStefano Zampini     const PetscScalar *xx;
26996e520ac8SStefano Zampini     PetscScalar       *bb;
27006e520ac8SStefano Zampini 
27019566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
27029566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
27036e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
27049566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
27059566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
27062e74eeadSLisandro Dalcin   }
27076e520ac8SStefano Zampini   /* get rows associated to the local matrices */
27089566063dSJacob Faibussowitsch   PetscCall(MatGetSize(matis->A,&nl,NULL));
27099566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(matis->sf_leafdata,nl));
27109566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(matis->sf_rootdata,A->rmap->n));
27116e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
27129566063dSJacob Faibussowitsch   PetscCall(PetscFree(lrows));
27139566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
27149566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE));
27159566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nl,&lrows));
27166e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
27179566063dSJacob Faibussowitsch   PetscCall(MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns));
27189566063dSJacob Faibussowitsch   PetscCall(PetscFree(lrows));
2719d0dbe9f7SStefano Zampini   PetscCall(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY));
2720d0dbe9f7SStefano Zampini   PetscCall(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY));
27212e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
27222e74eeadSLisandro Dalcin }
27232e74eeadSLisandro Dalcin 
2724f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
2725b4319ba4SBarry Smith {
2726b4319ba4SBarry Smith   PetscFunctionBegin;
27279566063dSJacob Faibussowitsch   PetscCall(MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE));
2728f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
2729f0ae7da4SStefano Zampini }
27302205254eSKarl Rupp 
2731f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
2732f0ae7da4SStefano Zampini {
2733f0ae7da4SStefano Zampini   PetscFunctionBegin;
27349566063dSJacob Faibussowitsch   PetscCall(MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE));
2735b4319ba4SBarry Smith   PetscFunctionReturn(0);
2736b4319ba4SBarry Smith }
2737b4319ba4SBarry Smith 
2738a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
2739b4319ba4SBarry Smith {
2740b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2741b4319ba4SBarry Smith 
2742b4319ba4SBarry Smith   PetscFunctionBegin;
27439566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(is->A,type));
2744b4319ba4SBarry Smith   PetscFunctionReturn(0);
2745b4319ba4SBarry Smith }
2746b4319ba4SBarry Smith 
2747a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
2748b4319ba4SBarry Smith {
2749b4319ba4SBarry Smith   Mat_IS    *is = (Mat_IS*)A->data;
2750d0dbe9f7SStefano Zampini   PetscBool lnnz;
2751b4319ba4SBarry Smith 
2752b4319ba4SBarry Smith   PetscFunctionBegin;
27539566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(is->A,type));
2754872cf891SStefano Zampini   /* fix for local empty rows/cols */
2755872cf891SStefano Zampini   if (is->locempty && type == MAT_FINAL_ASSEMBLY) {
2756872cf891SStefano Zampini     Mat                    newlA;
2757f03112d0SStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g;
2758f03112d0SStefano Zampini     IS                     nzr,nzc;
2759f03112d0SStefano Zampini     PetscInt               nr,nc,nnzr,nnzc;
2760f03112d0SStefano Zampini     PetscBool              lnewl2g,newl2g;
2761872cf891SStefano Zampini 
27629566063dSJacob Faibussowitsch     PetscCall(MatGetSize(is->A,&nr,&nc));
27639566063dSJacob Faibussowitsch     PetscCall(MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_FALSE,PETSC_SMALL,&nzr));
2764f03112d0SStefano Zampini     if (!nzr) {
27659566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PetscObjectComm((PetscObject)is->A),nr,0,1,&nzr));
2766872cf891SStefano Zampini     }
27679566063dSJacob Faibussowitsch     PetscCall(MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_TRUE,PETSC_SMALL,&nzc));
2768f03112d0SStefano Zampini     if (!nzc) {
27699566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PetscObjectComm((PetscObject)is->A),nc,0,1,&nzc));
2770872cf891SStefano Zampini     }
27719566063dSJacob Faibussowitsch     PetscCall(ISGetSize(nzr,&nnzr));
27729566063dSJacob Faibussowitsch     PetscCall(ISGetSize(nzc,&nnzc));
2773e432b41dSStefano Zampini     if (nnzr != nr || nnzc != nc) { /* need new global l2g map */
2774f03112d0SStefano Zampini       lnewl2g = PETSC_TRUE;
27759566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A)));
2776f03112d0SStefano Zampini 
2777872cf891SStefano Zampini       /* extract valid submatrix */
27789566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(is->A,nzr,nzc,MAT_INITIAL_MATRIX,&newlA));
2779f03112d0SStefano Zampini     } else { /* local matrix fully populated */
2780f03112d0SStefano Zampini       lnewl2g = PETSC_FALSE;
27819566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A)));
27829566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)is->A));
2783f03112d0SStefano Zampini       newlA   = is->A;
2784f03112d0SStefano Zampini     }
2785e432b41dSStefano Zampini 
2786f03112d0SStefano Zampini     /* attach new global l2g map if needed */
2787f03112d0SStefano Zampini     if (newl2g) {
2788e432b41dSStefano Zampini       IS              zr,zc;
2789e432b41dSStefano Zampini       const  PetscInt *ridxs,*cidxs,*zridxs,*zcidxs;
2790e432b41dSStefano Zampini       PetscInt        *nidxs,i;
2791f03112d0SStefano Zampini 
27929566063dSJacob Faibussowitsch       PetscCall(ISComplement(nzr,0,nr,&zr));
27939566063dSJacob Faibussowitsch       PetscCall(ISComplement(nzc,0,nc,&zc));
27949566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(PetscMax(nr,nc),&nidxs));
27959566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingGetIndices(is->rmapping,&ridxs));
27969566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingGetIndices(is->cmapping,&cidxs));
27979566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(zr,&zridxs));
27989566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(zc,&zcidxs));
27999566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(zr,&nnzr));
28009566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(zc,&nnzc));
2801e432b41dSStefano Zampini 
28029566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(nidxs,ridxs,nr));
2803e432b41dSStefano Zampini       for (i = 0; i < nnzr; i++) nidxs[zridxs[i]] = -1;
28049566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nr,nidxs,PETSC_COPY_VALUES,&rl2g));
28059566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(nidxs,cidxs,nc));
2806e432b41dSStefano Zampini       for (i = 0; i < nnzc; i++) nidxs[zcidxs[i]] = -1;
28079566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nc,nidxs,PETSC_COPY_VALUES,&cl2g));
2808e432b41dSStefano Zampini 
28099566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(zr,&zridxs));
28109566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(zc,&zcidxs));
28119566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingRestoreIndices(is->rmapping,&ridxs));
28129566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingRestoreIndices(is->cmapping,&cidxs));
28139566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&nzr));
28149566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&nzc));
28159566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&zr));
28169566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&zc));
28179566063dSJacob Faibussowitsch       PetscCall(PetscFree(nidxs));
28189566063dSJacob Faibussowitsch       PetscCall(MatSetLocalToGlobalMapping(A,rl2g,cl2g));
28199566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
28209566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
2821f03112d0SStefano Zampini     }
28229566063dSJacob Faibussowitsch     PetscCall(MatISSetLocalMat(A,newlA));
28239566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&newlA));
28249566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&nzr));
28259566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&nzc));
2826872cf891SStefano Zampini     is->locempty = PETSC_FALSE;
2827f03112d0SStefano Zampini   }
2828d0dbe9f7SStefano Zampini   lnnz = (PetscBool)(is->A->nonzerostate == is->lnnzstate);
2829d0dbe9f7SStefano Zampini   is->lnnzstate = is->A->nonzerostate;
2830d0dbe9f7SStefano Zampini   PetscCall(MPIU_Allreduce(MPI_IN_PLACE,&lnnz,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A)));
2831d0dbe9f7SStefano Zampini   if (lnnz) A->nonzerostate++;
2832b4319ba4SBarry Smith   PetscFunctionReturn(0);
2833b4319ba4SBarry Smith }
2834b4319ba4SBarry Smith 
2835a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
2836b4319ba4SBarry Smith {
2837b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
2838b4319ba4SBarry Smith 
2839b4319ba4SBarry Smith   PetscFunctionBegin;
2840b4319ba4SBarry Smith   *local = is->A;
2841b4319ba4SBarry Smith   PetscFunctionReturn(0);
2842b4319ba4SBarry Smith }
2843b4319ba4SBarry Smith 
28443b3b1effSJed Brown static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat,Mat *local)
28453b3b1effSJed Brown {
28463b3b1effSJed Brown   PetscFunctionBegin;
28473b3b1effSJed Brown   *local = NULL;
28483b3b1effSJed Brown   PetscFunctionReturn(0);
28493b3b1effSJed Brown }
28503b3b1effSJed Brown 
2851b4319ba4SBarry Smith /*@
2852b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
2853b4319ba4SBarry Smith 
2854b4319ba4SBarry Smith   Input Parameter:
2855b4319ba4SBarry Smith .  mat - the matrix
2856b4319ba4SBarry Smith 
2857b4319ba4SBarry Smith   Output Parameter:
2858eb82efa4SStefano Zampini .  local - the local matrix
2859b4319ba4SBarry Smith 
2860b4319ba4SBarry Smith   Level: advanced
2861b4319ba4SBarry Smith 
2862b4319ba4SBarry Smith   Notes:
2863b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
2864b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
2865b4319ba4SBarry Smith   of the MatSetValues() operation.
2866b4319ba4SBarry Smith 
28673b3b1effSJed Brown   Call MatISRestoreLocalMat() when finished with the local matrix.
286896a6f129SJed Brown 
2869db781477SPatrick Sanan .seealso: `MATIS`
2870b4319ba4SBarry Smith @*/
28717087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
2872b4319ba4SBarry Smith {
2873b4319ba4SBarry Smith   PetscFunctionBegin;
28740700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2875b4319ba4SBarry Smith   PetscValidPointer(local,2);
2876cac4c232SBarry Smith   PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));
2877b4319ba4SBarry Smith   PetscFunctionReturn(0);
2878b4319ba4SBarry Smith }
2879b4319ba4SBarry Smith 
28803b3b1effSJed Brown /*@
28813b3b1effSJed Brown     MatISRestoreLocalMat - Restores the local matrix obtained with MatISGetLocalMat()
28823b3b1effSJed Brown 
28833b3b1effSJed Brown   Input Parameter:
28843b3b1effSJed Brown .  mat - the matrix
28853b3b1effSJed Brown 
28863b3b1effSJed Brown   Output Parameter:
28873b3b1effSJed Brown .  local - the local matrix
28883b3b1effSJed Brown 
28893b3b1effSJed Brown   Level: advanced
28903b3b1effSJed Brown 
2891db781477SPatrick Sanan .seealso: `MATIS`
28923b3b1effSJed Brown @*/
28933b3b1effSJed Brown PetscErrorCode MatISRestoreLocalMat(Mat mat,Mat *local)
28943b3b1effSJed Brown {
28953b3b1effSJed Brown   PetscFunctionBegin;
28963b3b1effSJed Brown   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
28973b3b1effSJed Brown   PetscValidPointer(local,2);
2898cac4c232SBarry Smith   PetscUseMethod(mat,"MatISRestoreLocalMat_C",(Mat,Mat*),(mat,local));
28993b3b1effSJed Brown   PetscFunctionReturn(0);
29003b3b1effSJed Brown }
29013b3b1effSJed Brown 
29028546b261SStefano Zampini static PetscErrorCode MatISSetLocalMatType_IS(Mat mat,MatType mtype)
29038546b261SStefano Zampini {
29048546b261SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
29058546b261SStefano Zampini 
29068546b261SStefano Zampini   PetscFunctionBegin;
29071baa6e33SBarry Smith   if (is->A) PetscCall(MatSetType(is->A,mtype));
29089566063dSJacob Faibussowitsch   PetscCall(PetscFree(is->lmattype));
29099566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(mtype,&is->lmattype));
29108546b261SStefano Zampini   PetscFunctionReturn(0);
29118546b261SStefano Zampini }
29128546b261SStefano Zampini 
29138546b261SStefano Zampini /*@
29148546b261SStefano Zampini     MatISSetLocalMatType - Specifies the type of local matrix
29158546b261SStefano Zampini 
2916d8d19677SJose E. Roman   Input Parameters:
2917a2b725a8SWilliam Gropp +  mat - the matrix
2918a2b725a8SWilliam Gropp -  mtype - the local matrix type
29198546b261SStefano Zampini 
29208546b261SStefano Zampini   Output Parameter:
29218546b261SStefano Zampini 
29228546b261SStefano Zampini   Level: advanced
29238546b261SStefano Zampini 
2924db781477SPatrick Sanan .seealso: `MATIS`, `MatSetType()`, `MatType`
29258546b261SStefano Zampini @*/
29268546b261SStefano Zampini PetscErrorCode MatISSetLocalMatType(Mat mat,MatType mtype)
29278546b261SStefano Zampini {
29288546b261SStefano Zampini   PetscFunctionBegin;
29298546b261SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2930cac4c232SBarry Smith   PetscUseMethod(mat,"MatISSetLocalMatType_C",(Mat,MatType),(mat,mtype));
29318546b261SStefano Zampini   PetscFunctionReturn(0);
29328546b261SStefano Zampini }
29338546b261SStefano Zampini 
2934a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
29353b03a366Sstefano_zampini {
29363b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
29373b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
29388546b261SStefano Zampini   MatType        mtype,otype;
29398546b261SStefano Zampini   PetscBool      sametype = PETSC_TRUE;
29403b03a366Sstefano_zampini 
29413b03a366Sstefano_zampini   PetscFunctionBegin;
2942e432b41dSStefano Zampini   if (is->A && !is->islocalref) {
29439566063dSJacob Faibussowitsch     PetscCall(MatGetSize(is->A,&orows,&ocols));
29449566063dSJacob Faibussowitsch     PetscCall(MatGetSize(local,&nrows,&ncols));
2945aed4548fSBarry 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);
29469566063dSJacob Faibussowitsch     PetscCall(MatGetType(local,&mtype));
29479566063dSJacob Faibussowitsch     PetscCall(MatGetType(is->A,&otype));
29489566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(mtype,otype,&sametype));
29494e4c7dbeSStefano Zampini   }
29509566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)local));
29519566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&is->A));
29523b03a366Sstefano_zampini   is->A = local;
29539566063dSJacob Faibussowitsch   PetscCall(MatGetType(is->A,&mtype));
29549566063dSJacob Faibussowitsch   PetscCall(MatISSetLocalMatType(mat,mtype));
29558546b261SStefano Zampini   if (!sametype && !is->islocalref) {
29569566063dSJacob Faibussowitsch     PetscCall(MatISSetUpScatters_Private(mat));
29578546b261SStefano Zampini   }
29583b03a366Sstefano_zampini   PetscFunctionReturn(0);
29593b03a366Sstefano_zampini }
29603b03a366Sstefano_zampini 
29613b03a366Sstefano_zampini /*@
2962eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
29633b03a366Sstefano_zampini 
29648546b261SStefano Zampini   Collective on Mat
29658546b261SStefano Zampini 
2966d8d19677SJose E. Roman   Input Parameters:
2967a2b725a8SWilliam Gropp +  mat - the matrix
2968a2b725a8SWilliam Gropp -  local - the local matrix
29693b03a366Sstefano_zampini 
29703b03a366Sstefano_zampini   Output Parameter:
29713b03a366Sstefano_zampini 
29723b03a366Sstefano_zampini   Level: advanced
29733b03a366Sstefano_zampini 
29743b03a366Sstefano_zampini   Notes:
29753b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
29763b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
29773b03a366Sstefano_zampini 
2978db781477SPatrick Sanan .seealso: `MATIS`
29793b03a366Sstefano_zampini @*/
29803b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
29813b03a366Sstefano_zampini {
29823b03a366Sstefano_zampini   PetscFunctionBegin;
29833b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2984b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
2985cac4c232SBarry Smith   PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));
29863b03a366Sstefano_zampini   PetscFunctionReturn(0);
29873b03a366Sstefano_zampini }
29883b03a366Sstefano_zampini 
2989a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
29906726f965SBarry Smith {
29916726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
29926726f965SBarry Smith 
29936726f965SBarry Smith   PetscFunctionBegin;
29949566063dSJacob Faibussowitsch   PetscCall(MatZeroEntries(a->A));
29956726f965SBarry Smith   PetscFunctionReturn(0);
29966726f965SBarry Smith }
29976726f965SBarry Smith 
2998a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
29992e74eeadSLisandro Dalcin {
30002e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
30012e74eeadSLisandro Dalcin 
30022e74eeadSLisandro Dalcin   PetscFunctionBegin;
30039566063dSJacob Faibussowitsch   PetscCall(MatScale(is->A,a));
30042e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
30052e74eeadSLisandro Dalcin }
30062e74eeadSLisandro Dalcin 
3007a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
30082e74eeadSLisandro Dalcin {
30092e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
30102e74eeadSLisandro Dalcin 
30112e74eeadSLisandro Dalcin   PetscFunctionBegin;
30122e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
30139566063dSJacob Faibussowitsch   PetscCall(MatGetDiagonal(is->A,is->y));
30142e74eeadSLisandro Dalcin 
30152e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
30169566063dSJacob Faibussowitsch   PetscCall(VecSet(v,0));
30179566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE));
30189566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE));
30192e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
30202e74eeadSLisandro Dalcin }
30212e74eeadSLisandro Dalcin 
3022a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
30236726f965SBarry Smith {
30246726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
30256726f965SBarry Smith 
30266726f965SBarry Smith   PetscFunctionBegin;
30279566063dSJacob Faibussowitsch   PetscCall(MatSetOption(a->A,op,flg));
30286726f965SBarry Smith   PetscFunctionReturn(0);
30296726f965SBarry Smith }
30306726f965SBarry Smith 
3031f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
3032f26d0771SStefano Zampini {
3033f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
3034f26d0771SStefano Zampini   Mat_IS         *x;
3035f26d0771SStefano Zampini 
3036f26d0771SStefano Zampini   PetscFunctionBegin;
303776bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
303876bd3646SJed Brown     PetscBool      ismatis;
30399566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis));
304028b400f6SJacob Faibussowitsch     PetscCheck(ismatis,PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
304176bd3646SJed Brown   }
3042f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
30439566063dSJacob Faibussowitsch   PetscCall(MatAXPY(y->A,a,x->A,str));
3044f26d0771SStefano Zampini   PetscFunctionReturn(0);
3045f26d0771SStefano Zampini }
3046f26d0771SStefano Zampini 
3047f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
3048f26d0771SStefano Zampini {
3049f26d0771SStefano Zampini   Mat                    lA;
3050e432b41dSStefano Zampini   Mat_IS                 *matis = (Mat_IS*)(A->data);
3051f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
3052f26d0771SStefano Zampini   IS                     is;
3053f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
3054f26d0771SStefano Zampini   PetscInt               nrg;
3055f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
3056f26d0771SStefano Zampini 
3057f26d0771SStefano Zampini   PetscFunctionBegin;
30589566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg));
30599566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(row,&nrl));
30609566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(row,&rl));
30619566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg));
306276bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
306308401ef6SPierre 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);
306476bd3646SJed Brown   }
30659566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrg,&idxs));
3066f26d0771SStefano Zampini   /* map from [0,nrl) to row */
3067f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
3068f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
30699566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(row,&rl));
30709566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg));
30719566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is));
30729566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(is,&rl2g));
30739566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
3074f26d0771SStefano Zampini   /* compute new l2g map for columns */
3075e432b41dSStefano Zampini   if (col != row || matis->rmapping != matis->cmapping || matis->A->rmap->mapping != matis->A->cmap->mapping) {
3076f26d0771SStefano Zampini     const PetscInt *cg,*cl;
3077f26d0771SStefano Zampini     PetscInt       ncg;
3078f26d0771SStefano Zampini     PetscInt       ncl;
3079f26d0771SStefano Zampini 
30809566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg));
30819566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(col,&ncl));
30829566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(col,&cl));
30839566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg));
308476bd3646SJed Brown     if (PetscDefined(USE_DEBUG)) {
308508401ef6SPierre 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);
308676bd3646SJed Brown     }
30879566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(ncg,&idxs));
3088f26d0771SStefano Zampini     /* map from [0,ncl) to col */
3089f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
3090f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
30919566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(col,&cl));
30929566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg));
30939566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is));
30949566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is,&cl2g));
30959566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
3096f26d0771SStefano Zampini   } else {
30979566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)rl2g));
3098f26d0771SStefano Zampini     cl2g = rl2g;
3099f26d0771SStefano Zampini   }
3100f26d0771SStefano Zampini   /* create the MATIS submatrix */
31019566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A,&M,&N));
31029566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A),submat));
31039566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N));
31049566063dSJacob Faibussowitsch   PetscCall(MatSetType(*submat,MATIS));
3105b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
3106f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
31079566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(*submat,rl2g,cl2g));
31089566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(A,&lA));
31099566063dSJacob Faibussowitsch   PetscCall(MatISSetLocalMat(*submat,lA));
31109566063dSJacob Faibussowitsch   PetscCall(MatSetUp(*submat));
31119566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY));
31129566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY));
31139566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
31149566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
3115e432b41dSStefano Zampini 
3116f26d0771SStefano Zampini   /* remove unsupported ops */
31179566063dSJacob Faibussowitsch   PetscCall(PetscMemzero((*submat)->ops,sizeof(struct _MatOps)));
3118f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
3119f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
3120f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
3121f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
3122f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
3123f26d0771SStefano Zampini   PetscFunctionReturn(0);
3124f26d0771SStefano Zampini }
3125f26d0771SStefano Zampini 
3126872cf891SStefano Zampini static PetscErrorCode MatSetFromOptions_IS(PetscOptionItems *PetscOptionsObject, Mat A)
3127872cf891SStefano Zampini {
3128872cf891SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
31298546b261SStefano Zampini   char           type[256];
31308546b261SStefano Zampini   PetscBool      flg;
3131872cf891SStefano Zampini 
3132872cf891SStefano Zampini   PetscFunctionBegin;
3133d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject,"MATIS options");
3134d0dbe9f7SStefano Zampini   PetscCall(PetscOptionsBool("-matis_keepassembled","Store an assembled version if needed","MatISKeepAssembled",a->keepassembled,&a->keepassembled,NULL));
31359566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-matis_fixempty","Fix local matrices in case of empty local rows/columns","MatISFixLocalEmpty",a->locempty,&a->locempty,NULL));
31369566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-matis_storel2l","Store local-to-local matrices generated from PtAP operations","MatISStoreL2L",a->storel2l,&a->storel2l,NULL));
31379566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-matis_localmat_type","Matrix type","MatISSetLocalMatType",MatList,a->lmattype,type,256,&flg));
31381baa6e33SBarry Smith   if (flg) PetscCall(MatISSetLocalMatType(A,type));
31391baa6e33SBarry Smith   if (a->A) PetscCall(MatSetFromOptions(a->A));
3140d0609cedSBarry Smith   PetscOptionsHeadEnd();
3141872cf891SStefano Zampini   PetscFunctionReturn(0);
3142872cf891SStefano Zampini }
3143872cf891SStefano Zampini 
3144284134d9SBarry Smith /*@
31453c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
3146284134d9SBarry Smith        process but not across processes.
3147284134d9SBarry Smith 
3148284134d9SBarry Smith    Input Parameters:
3149284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
3150e176bc59SStefano Zampini .     bs      - block size of the matrix
3151df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
3152e176bc59SStefano Zampini .     rmap    - local to global map for rows
3153e176bc59SStefano Zampini -     cmap    - local to global map for cols
3154284134d9SBarry Smith 
3155284134d9SBarry Smith    Output Parameter:
3156284134d9SBarry Smith .    A - the resulting matrix
3157284134d9SBarry Smith 
31588e6c10adSSatish Balay    Level: advanced
31598e6c10adSSatish Balay 
316095452b02SPatrick Sanan    Notes:
316195452b02SPatrick Sanan     See MATIS for more details.
3162fc989267SStefano 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
31636fdf41d1SStefano Zampini     used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
3164fc989267SStefano Zampini     If rmap (cmap) is NULL, then the local row (column) spaces matches the global space.
3165284134d9SBarry Smith 
3166db781477SPatrick Sanan .seealso: `MATIS`, `MatSetLocalToGlobalMapping()`
3167284134d9SBarry Smith @*/
3168e176bc59SStefano Zampini PetscErrorCode MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
3169284134d9SBarry Smith {
3170284134d9SBarry Smith   PetscFunctionBegin;
31719566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm,A));
31729566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A,m,n,M,N));
31736fdf41d1SStefano Zampini   if (bs > 0) {
31749566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSize(*A,bs));
31756fdf41d1SStefano Zampini   }
31769566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A,MATIS));
31779566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(*A,rmap,cmap));
3178284134d9SBarry Smith   PetscFunctionReturn(0);
3179284134d9SBarry Smith }
3180284134d9SBarry Smith 
31818b9382cfSStefano Zampini static PetscErrorCode MatHasOperation_IS(Mat A, MatOperation op, PetscBool *has)
31828b9382cfSStefano Zampini {
31838b9382cfSStefano Zampini   Mat_IS       *a = (Mat_IS*)A->data;
3184e26763e4SStefano Zampini   MatOperation tobefiltered[] = { MATOP_MULT_ADD, MATOP_MULT_TRANSPOSE_ADD, MATOP_GET_DIAGONAL_BLOCK, MATOP_INCREASE_OVERLAP};
31858b9382cfSStefano Zampini 
31868b9382cfSStefano Zampini   PetscFunctionBegin;
31878b9382cfSStefano Zampini   *has = PETSC_FALSE;
3188e26763e4SStefano Zampini   if (!((void**)A->ops)[op] || !a->A) PetscFunctionReturn(0);
3189d0dbe9f7SStefano Zampini   *has = PETSC_TRUE;
3190e26763e4SStefano Zampini   for (PetscInt i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(tobefiltered); i++) if (op == tobefiltered[i]) PetscFunctionReturn(0);
31919566063dSJacob Faibussowitsch   PetscCall(MatHasOperation(a->A,op,has));
31928b9382cfSStefano Zampini   PetscFunctionReturn(0);
31938b9382cfSStefano Zampini }
31948b9382cfSStefano Zampini 
3195e432b41dSStefano Zampini static PetscErrorCode MatSetValuesCOO_IS(Mat A,const PetscScalar v[],InsertMode imode)
3196e432b41dSStefano Zampini {
3197e432b41dSStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
3198e432b41dSStefano Zampini 
3199e432b41dSStefano Zampini   PetscFunctionBegin;
32009566063dSJacob Faibussowitsch   PetscCall(MatSetValuesCOO(a->A,v,imode));
32019566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY));
32029566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY));
3203e432b41dSStefano Zampini   PetscFunctionReturn(0);
3204e432b41dSStefano Zampini }
3205e432b41dSStefano Zampini 
3206e432b41dSStefano Zampini static PetscErrorCode MatSetPreallocationCOOLocal_IS(Mat A,PetscCount ncoo,PetscInt coo_i[],PetscInt coo_j[])
3207e432b41dSStefano Zampini {
3208e432b41dSStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
3209e432b41dSStefano Zampini 
3210e432b41dSStefano Zampini   PetscFunctionBegin;
3211e432b41dSStefano Zampini   PetscCheck(a->A,PetscObjectComm((PetscObject)A),PETSC_ERR_ORDER,"Need to provide l2g map first via MatSetLocalToGlobalMapping");
3212e432b41dSStefano Zampini   if (a->A->rmap->mapping || a->A->cmap->mapping) {
32139566063dSJacob Faibussowitsch     PetscCall(MatSetPreallocationCOOLocal(a->A,ncoo,coo_i,coo_j));
3214e432b41dSStefano Zampini   } else {
32159566063dSJacob Faibussowitsch     PetscCall(MatSetPreallocationCOO(a->A,ncoo,coo_i,coo_j));
3216e432b41dSStefano Zampini   }
32179566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetValuesCOO_C",MatSetValuesCOO_IS));
3218e432b41dSStefano Zampini   A->preallocated = PETSC_TRUE;
3219e432b41dSStefano Zampini   PetscFunctionReturn(0);
3220e432b41dSStefano Zampini }
3221e432b41dSStefano Zampini 
3222e8729f6fSJunchao Zhang static PetscErrorCode MatSetPreallocationCOO_IS(Mat A,PetscCount ncoo,PetscInt coo_i[],PetscInt coo_j[])
3223e432b41dSStefano Zampini {
3224e432b41dSStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
3225e432b41dSStefano Zampini 
3226e432b41dSStefano Zampini   PetscFunctionBegin;
3227e432b41dSStefano Zampini   PetscCheck(a->A,PetscObjectComm((PetscObject)A),PETSC_ERR_ORDER,"Need to provide l2g map first via MatSetLocalToGlobalMapping");
3228e432b41dSStefano 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);
3229e8729f6fSJunchao Zhang   PetscCall(ISGlobalToLocalMappingApply(a->rmapping,IS_GTOLM_MASK,ncoo,coo_i,NULL,coo_i));
3230e8729f6fSJunchao Zhang   PetscCall(ISGlobalToLocalMappingApply(a->cmapping,IS_GTOLM_MASK,ncoo,coo_j,NULL,coo_j));
3231e8729f6fSJunchao Zhang   PetscCall(MatSetPreallocationCOO(a->A,ncoo,coo_i,coo_j));
32329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetValuesCOO_C",MatSetValuesCOO_IS));
3233e432b41dSStefano Zampini   A->preallocated = PETSC_TRUE;
3234e432b41dSStefano Zampini   PetscFunctionReturn(0);
3235e432b41dSStefano Zampini }
3236e432b41dSStefano Zampini 
3237d0dbe9f7SStefano Zampini static PetscErrorCode MatISGetAssembled_Private(Mat A, Mat *tA)
3238d0dbe9f7SStefano Zampini {
3239d0dbe9f7SStefano Zampini   Mat_IS           *a = (Mat_IS*)A->data;
3240d0dbe9f7SStefano Zampini   PetscObjectState Astate, aAstate = PETSC_MIN_INT;
3241d0dbe9f7SStefano Zampini   PetscObjectState Annzstate, aAnnzstate = PETSC_MIN_INT;
3242d0dbe9f7SStefano Zampini 
3243d0dbe9f7SStefano Zampini   PetscFunctionBegin;
3244d0dbe9f7SStefano Zampini   PetscCall(PetscObjectStateGet((PetscObject)A,&Astate));
3245d0dbe9f7SStefano Zampini   Annzstate = A->nonzerostate;
3246d0dbe9f7SStefano Zampini   if (a->assembledA) {
3247d0dbe9f7SStefano Zampini     PetscCall(PetscObjectStateGet((PetscObject)a->assembledA,&aAstate));
3248d0dbe9f7SStefano Zampini     aAnnzstate = a->assembledA->nonzerostate;
3249d0dbe9f7SStefano Zampini   }
3250d0dbe9f7SStefano Zampini   if (aAnnzstate != Annzstate) PetscCall(MatDestroy(&a->assembledA));
3251d0dbe9f7SStefano Zampini   if (Astate != aAstate || !a->assembledA) {
3252d0dbe9f7SStefano Zampini     MatType     aAtype;
3253d0dbe9f7SStefano Zampini     PetscMPIInt size;
3254d0dbe9f7SStefano Zampini     PetscInt    rbs, cbs, bs;
3255d0dbe9f7SStefano Zampini 
3256d0dbe9f7SStefano Zampini     /* the assembled form is used as temporary storage for parallel operations
3257d0dbe9f7SStefano Zampini        like createsubmatrices and the like, do not waste device memory */
3258d0dbe9f7SStefano Zampini     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A),&size));
3259d0dbe9f7SStefano Zampini     PetscCall(ISLocalToGlobalMappingGetBlockSize(a->cmapping,&cbs));
3260d0dbe9f7SStefano Zampini     PetscCall(ISLocalToGlobalMappingGetBlockSize(a->rmapping,&rbs));
3261d0dbe9f7SStefano Zampini     bs = rbs == cbs ? rbs : 1;
3262d0dbe9f7SStefano Zampini     if (a->assembledA) PetscCall(MatGetType(a->assembledA,&aAtype));
3263d0dbe9f7SStefano Zampini     else if (size > 1) aAtype = bs > 1 ? MATMPIBAIJ : MATMPIAIJ;
3264d0dbe9f7SStefano Zampini     else aAtype = bs > 1 ? MATSEQBAIJ : MATSEQAIJ;
3265d0dbe9f7SStefano Zampini 
3266d0dbe9f7SStefano Zampini     PetscCall(MatConvert(A,aAtype,a->assembledA ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX,&a->assembledA));
3267d0dbe9f7SStefano Zampini     PetscCall(PetscObjectStateSet((PetscObject)a->assembledA,Astate));
3268d0dbe9f7SStefano Zampini     a->assembledA->nonzerostate = Annzstate;
3269d0dbe9f7SStefano Zampini   }
3270d0dbe9f7SStefano Zampini   PetscCall(PetscObjectReference((PetscObject)a->assembledA));
3271d0dbe9f7SStefano Zampini   *tA = a->assembledA;
3272d0dbe9f7SStefano Zampini   if (!a->keepassembled) PetscCall(MatDestroy(&a->assembledA));
3273d0dbe9f7SStefano Zampini   PetscFunctionReturn(0);
3274d0dbe9f7SStefano Zampini }
3275d0dbe9f7SStefano Zampini 
3276d0dbe9f7SStefano Zampini static PetscErrorCode MatISRestoreAssembled_Private(Mat A, Mat *tA)
3277d0dbe9f7SStefano Zampini {
3278d0dbe9f7SStefano Zampini   PetscFunctionBegin;
3279d0dbe9f7SStefano Zampini   PetscCall(MatDestroy(tA));
3280d0dbe9f7SStefano Zampini   *tA = NULL;
3281d0dbe9f7SStefano Zampini   PetscFunctionReturn(0);
3282d0dbe9f7SStefano Zampini }
3283d0dbe9f7SStefano Zampini 
3284d0dbe9f7SStefano Zampini static PetscErrorCode MatGetDiagonalBlock_IS(Mat A, Mat *dA)
3285d0dbe9f7SStefano Zampini {
3286d0dbe9f7SStefano Zampini   Mat_IS           *a = (Mat_IS*)A->data;
3287d0dbe9f7SStefano Zampini   PetscObjectState Astate, dAstate = PETSC_MIN_INT;
3288d0dbe9f7SStefano Zampini 
3289d0dbe9f7SStefano Zampini   PetscFunctionBegin;
3290d0dbe9f7SStefano Zampini   PetscCall(PetscObjectStateGet((PetscObject)A,&Astate));
3291d0dbe9f7SStefano Zampini   if (a->dA) PetscCall(PetscObjectStateGet((PetscObject)a->dA,&dAstate));
3292d0dbe9f7SStefano Zampini   if (Astate != dAstate) {
3293d0dbe9f7SStefano Zampini     Mat     tA;
3294d0dbe9f7SStefano Zampini     MatType ltype;
3295d0dbe9f7SStefano Zampini 
3296d0dbe9f7SStefano Zampini     PetscCall(MatDestroy(&a->dA));
3297d0dbe9f7SStefano Zampini     PetscCall(MatISGetAssembled_Private(A,&tA));
3298d0dbe9f7SStefano Zampini     PetscCall(MatGetDiagonalBlock(tA,&a->dA));
3299d0dbe9f7SStefano Zampini     PetscCall(MatPropagateSymmetryOptions(tA,a->dA));
3300d0dbe9f7SStefano Zampini     PetscCall(MatGetType(a->A,&ltype));
3301d0dbe9f7SStefano Zampini     PetscCall(MatConvert(a->dA,ltype,MAT_INPLACE_MATRIX,&a->dA));
3302d0dbe9f7SStefano Zampini     PetscCall(PetscObjectReference((PetscObject)a->dA));
3303d0dbe9f7SStefano Zampini     PetscCall(MatISRestoreAssembled_Private(A,&tA));
3304d0dbe9f7SStefano Zampini     PetscCall(PetscObjectStateSet((PetscObject)a->dA,Astate));
3305d0dbe9f7SStefano Zampini   }
3306d0dbe9f7SStefano Zampini   *dA = a->dA;
3307d0dbe9f7SStefano Zampini   PetscFunctionReturn(0);
3308d0dbe9f7SStefano Zampini }
3309d0dbe9f7SStefano Zampini 
3310d0dbe9f7SStefano Zampini static PetscErrorCode MatCreateSubMatrices_IS(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse reuse,Mat *submat[])
3311d0dbe9f7SStefano Zampini {
3312d0dbe9f7SStefano Zampini   Mat tA;
3313d0dbe9f7SStefano Zampini 
3314d0dbe9f7SStefano Zampini   PetscFunctionBegin;
3315d0dbe9f7SStefano Zampini   PetscCall(MatISGetAssembled_Private(A,&tA));
3316d0dbe9f7SStefano Zampini   PetscCall(MatCreateSubMatrices(tA,n,irow,icol,reuse,submat));
3317d0dbe9f7SStefano Zampini   /* MatCreateSubMatrices_MPIAIJ is a mess at the moment */
3318d0dbe9f7SStefano Zampini #if 0
3319d0dbe9f7SStefano Zampini   {
3320d0dbe9f7SStefano Zampini     Mat_IS    *a = (Mat_IS*)A->data;
3321d0dbe9f7SStefano Zampini     MatType   ltype;
3322d0dbe9f7SStefano Zampini     VecType   vtype;
3323d0dbe9f7SStefano Zampini     char      *flg;
3324d0dbe9f7SStefano Zampini 
3325d0dbe9f7SStefano Zampini     PetscCall(MatGetType(a->A,&ltype));
3326d0dbe9f7SStefano Zampini     PetscCall(MatGetVecType(a->A,&vtype));
3327d0dbe9f7SStefano Zampini     PetscCall(PetscStrstr(vtype,"cuda",&flg));
3328d0dbe9f7SStefano Zampini     if (!flg) PetscCall(PetscStrstr(vtype,"hip",&flg));
3329d0dbe9f7SStefano Zampini     if (!flg) PetscCall(PetscStrstr(vtype,"kokkos",&flg));
3330d0dbe9f7SStefano Zampini     if (flg) {
3331d0dbe9f7SStefano Zampini       for (PetscInt i = 0; i < n; i++) {
3332d0dbe9f7SStefano Zampini         Mat sA = (*submat)[i];
3333d0dbe9f7SStefano Zampini 
3334d0dbe9f7SStefano Zampini         PetscCall(MatConvert(sA,ltype,MAT_INPLACE_MATRIX,&sA));
3335d0dbe9f7SStefano Zampini         (*submat)[i] = sA;
3336d0dbe9f7SStefano Zampini       }
3337d0dbe9f7SStefano Zampini     }
3338d0dbe9f7SStefano Zampini   }
3339d0dbe9f7SStefano Zampini #endif
3340d0dbe9f7SStefano Zampini   PetscCall(MatISRestoreAssembled_Private(A,&tA));
3341d0dbe9f7SStefano Zampini   PetscFunctionReturn(0);
3342d0dbe9f7SStefano Zampini }
3343d0dbe9f7SStefano Zampini 
3344d0dbe9f7SStefano Zampini static PetscErrorCode MatIncreaseOverlap_IS(Mat A, PetscInt n, IS is[], PetscInt ov)
3345d0dbe9f7SStefano Zampini {
3346d0dbe9f7SStefano Zampini   Mat tA;
3347d0dbe9f7SStefano Zampini 
3348d0dbe9f7SStefano Zampini   PetscFunctionBegin;
3349d0dbe9f7SStefano Zampini   PetscCall(MatISGetAssembled_Private(A,&tA));
3350d0dbe9f7SStefano Zampini   PetscCall(MatIncreaseOverlap(tA,n,is,ov));
3351d0dbe9f7SStefano Zampini   PetscCall(MatISRestoreAssembled_Private(A,&tA));
3352d0dbe9f7SStefano Zampini   PetscFunctionReturn(0);
3353d0dbe9f7SStefano Zampini }
3354d0dbe9f7SStefano Zampini 
3355e432b41dSStefano Zampini /*@
3356e432b41dSStefano Zampini    MatISGetLocalToGlobalMapping - Gets the local-to-global numbering of the MATIS object
3357e432b41dSStefano Zampini 
3358e432b41dSStefano Zampini    Not Collective
3359e432b41dSStefano Zampini 
3360e432b41dSStefano Zampini    Input Parameter:
3361e432b41dSStefano Zampini .  A - the matrix
3362e432b41dSStefano Zampini 
3363e432b41dSStefano Zampini    Output Parameters:
3364e432b41dSStefano Zampini +  rmapping - row mapping
3365e432b41dSStefano Zampini -  cmapping - column mapping
3366e432b41dSStefano Zampini 
3367e432b41dSStefano 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.
3368e432b41dSStefano Zampini 
3369e432b41dSStefano Zampini    Level: advanced
3370e432b41dSStefano Zampini 
3371db781477SPatrick Sanan .seealso: `MatSetLocalToGlobalMapping()`
3372e432b41dSStefano Zampini @*/
3373e432b41dSStefano Zampini PetscErrorCode MatISGetLocalToGlobalMapping(Mat A,ISLocalToGlobalMapping *rmapping,ISLocalToGlobalMapping *cmapping)
3374e432b41dSStefano Zampini {
3375e432b41dSStefano Zampini   PetscFunctionBegin;
3376e432b41dSStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3377e432b41dSStefano Zampini   PetscValidType(A,1);
3378e432b41dSStefano Zampini   if (rmapping) PetscValidPointer(rmapping,2);
3379e432b41dSStefano Zampini   if (cmapping) PetscValidPointer(cmapping,3);
3380cac4c232SBarry Smith   PetscUseMethod(A,"MatISGetLocalToGlobalMapping_C",(Mat,ISLocalToGlobalMapping*,ISLocalToGlobalMapping*),(A,rmapping,cmapping));
3381e432b41dSStefano Zampini   PetscFunctionReturn(0);
3382e432b41dSStefano Zampini }
3383e432b41dSStefano Zampini 
3384e432b41dSStefano Zampini static PetscErrorCode MatISGetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping *r, ISLocalToGlobalMapping *c)
3385e432b41dSStefano Zampini {
3386e432b41dSStefano Zampini   Mat_IS *a = (Mat_IS*)A->data;
3387e432b41dSStefano Zampini 
3388e432b41dSStefano Zampini   PetscFunctionBegin;
3389e432b41dSStefano Zampini   if (r) *r = a->rmapping;
3390e432b41dSStefano Zampini   if (c) *c = a->cmapping;
3391e432b41dSStefano Zampini   PetscFunctionReturn(0);
3392e432b41dSStefano Zampini }
3393e432b41dSStefano Zampini 
3394b4319ba4SBarry Smith /*MC
3395f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
3396b89f26deSStefano Zampini    This stores the matrices in globally unassembled form. Each processor assembles only its local Neumann problem and the parallel matrix vector
3397b4319ba4SBarry Smith    product is handled "implicitly".
3398b4319ba4SBarry Smith 
3399b4319ba4SBarry Smith    Options Database Keys:
340075d48cdbSStefano Zampini + -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
340175d48cdbSStefano Zampini . -matis_fixempty - Fixes local matrices in case of empty local rows/columns.
340275d48cdbSStefano Zampini - -matis_storel2l - stores the local-to-local operators generated by the Galerkin process of MatPtAP().
3403b4319ba4SBarry Smith 
340495452b02SPatrick Sanan    Notes:
340595452b02SPatrick Sanan     Options prefix for the inner matrix are given by -is_mat_xxx
3406b4319ba4SBarry Smith 
3407b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
3408b4319ba4SBarry Smith 
3409b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
3410eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
3411b4319ba4SBarry Smith 
3412b4319ba4SBarry Smith   Level: advanced
3413b4319ba4SBarry Smith 
3414db781477SPatrick Sanan .seealso: `Mat`, `MatISGetLocalMat()`, `MatSetLocalToGlobalMapping()`, `MatISSetPreallocation()`, `MatCreateIS()`, `PCBDDC`, `KSPFETIDP`
3415b4319ba4SBarry Smith 
3416b4319ba4SBarry Smith M*/
34178cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
3418b4319ba4SBarry Smith {
3419e432b41dSStefano Zampini   Mat_IS         *a;
3420b4319ba4SBarry Smith 
3421b4319ba4SBarry Smith   PetscFunctionBegin;
34229566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(A,&a));
34239566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATAIJ,&a->lmattype));
3424e432b41dSStefano Zampini   A->data = (void*)a;
3425b4319ba4SBarry Smith 
3426e176bc59SStefano Zampini   /* matrix ops */
34279566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(A->ops,sizeof(struct _MatOps)));
3428b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
34292e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
34302e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
34312e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
3432b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
3433b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
34342e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
343598921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
3436b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
3437f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
34382e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
3439f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
3440b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
3441b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
3442b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
34436726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
34442e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
34452e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
34466726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
344769796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
344869796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
344945471136SStefano Zampini   A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS;
3450ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
34516bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
34522b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
3453659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
34547dae84e0SHong Zhang   A->ops->createsubmatrix         = MatCreateSubMatrix_IS;
3455f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
34563fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
34573fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
3458d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
34597fa8f2d3SStefano Zampini   A->ops->getinfo                 = MatGetInfo_IS;
3460ad219c80Sstefano_zampini   A->ops->diagonalscale           = MatDiagonalScale_IS;
3461872cf891SStefano Zampini   A->ops->setfromoptions          = MatSetFromOptions_IS;
3462fc989267SStefano Zampini   A->ops->setup                   = MatSetUp_IS;
34638b9382cfSStefano Zampini   A->ops->hasoperation            = MatHasOperation_IS;
3464d0dbe9f7SStefano Zampini   A->ops->getdiagonalblock        = MatGetDiagonalBlock_IS;
3465d0dbe9f7SStefano Zampini   A->ops->createsubmatrices       = MatCreateSubMatrices_IS;
3466d0dbe9f7SStefano Zampini   A->ops->increaseoverlap         = MatIncreaseOverlap_IS;
3467b4319ba4SBarry Smith 
3468b7ce53b6SStefano Zampini   /* special MATIS functions */
34699566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMatType_C",MatISSetLocalMatType_IS));
34709566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS));
34719566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISRestoreLocalMat_C",MatISRestoreLocalMat_IS));
34729566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS));
34739566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatConvert_IS_XAIJ));
34749566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS));
34759566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",MatISStoreL2L_IS));
34769566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",MatISFixLocalEmpty_IS));
34779566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalToGlobalMapping_C",MatISGetLocalToGlobalMapping_IS));
34789566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",MatConvert_IS_XAIJ));
34799566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",MatConvert_IS_XAIJ));
34809566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",MatConvert_IS_XAIJ));
34819566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",MatConvert_IS_XAIJ));
34829566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",MatConvert_IS_XAIJ));
34839566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",MatConvert_IS_XAIJ));
34849566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",MatConvert_IS_XAIJ));
34859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOOLocal_C",MatSetPreallocationCOOLocal_IS));
34869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOO_C",MatSetPreallocationCOO_IS));
34879566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)A,MATIS));
3488b4319ba4SBarry Smith   PetscFunctionReturn(0);
3489b4319ba4SBarry Smith }
3490