xref: /petsc/src/mat/impls/is/matis.c (revision 4e8208cbcbc709572b8abe32f33c78b69c819375)
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*/
115042aa92SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
124f2d7cafSStefano Zampini #include <petsc/private/sfimpl.h>
13a72d46e8SStefano Zampini #include <petsc/private/vecimpl.h>
14e432b41dSStefano Zampini #include <petsc/private/hashseti.h>
1528f4e0baSStefano Zampini 
16f26d0771SStefano Zampini #define MATIS_MAX_ENTRIES_INSERTION 2048
17076fee34SStefano Zampini 
18076fee34SStefano Zampini /* copied from src/mat/impls/localref/mlocalref.c */
19076fee34SStefano Zampini #define IndexSpaceGet(buf, nrow, ncol, irowm, icolm) \
20076fee34SStefano Zampini   do { \
21076fee34SStefano Zampini     if (nrow + ncol > (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { \
22076fee34SStefano Zampini       PetscCall(PetscMalloc2(nrow, &irowm, ncol, &icolm)); \
23076fee34SStefano Zampini     } else { \
24076fee34SStefano Zampini       irowm = &buf[0]; \
25076fee34SStefano Zampini       icolm = &buf[nrow]; \
26076fee34SStefano Zampini     } \
27076fee34SStefano Zampini   } while (0)
28076fee34SStefano Zampini 
29076fee34SStefano Zampini #define IndexSpaceRestore(buf, nrow, ncol, irowm, icolm) \
30076fee34SStefano Zampini   do { \
31076fee34SStefano Zampini     if (nrow + ncol > (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) PetscCall(PetscFree2(irowm, icolm)); \
32076fee34SStefano Zampini   } while (0)
33076fee34SStefano Zampini 
BlockIndicesExpand(PetscInt n,const PetscInt idx[],PetscInt bs,PetscInt idxm[])34076fee34SStefano Zampini static void BlockIndicesExpand(PetscInt n, const PetscInt idx[], PetscInt bs, PetscInt idxm[])
35076fee34SStefano Zampini {
36076fee34SStefano Zampini   for (PetscInt i = 0; i < n; i++) {
37076fee34SStefano Zampini     for (PetscInt j = 0; j < bs; j++) idxm[i * bs + j] = idx[i] * bs + j;
38076fee34SStefano Zampini   }
39076fee34SStefano Zampini }
40076fee34SStefano Zampini 
41b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat, PetscInt, const PetscInt *, PetscInt, const PetscInt *, const PetscScalar *, InsertMode);
42b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat, PetscInt, const PetscInt *, PetscInt, const PetscInt *, const PetscScalar *, InsertMode);
438546b261SStefano Zampini static PetscErrorCode MatISSetUpScatters_Private(Mat);
44f26d0771SStefano Zampini 
MatISContainerDestroyPtAP_Private(PetscCtxRt ptr)45*2a8381b2SBarry Smith static PetscErrorCode MatISContainerDestroyPtAP_Private(PetscCtxRt ptr)
46d71ae5a4SJacob Faibussowitsch {
47*2a8381b2SBarry Smith   MatISPtAP ptap = *(MatISPtAP *)ptr;
4875d48cdbSStefano Zampini 
4975d48cdbSStefano Zampini   PetscFunctionBegin;
509566063dSJacob Faibussowitsch   PetscCall(MatDestroySubMatrices(ptap->ris1 ? 2 : 1, &ptap->lP));
519566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&ptap->cis0));
529566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&ptap->cis1));
539566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&ptap->ris0));
549566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&ptap->ris1));
559566063dSJacob Faibussowitsch   PetscCall(PetscFree(ptap));
563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5775d48cdbSStefano Zampini }
5875d48cdbSStefano Zampini 
MatPtAPNumeric_IS_XAIJ(Mat A,Mat P,Mat C)59d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_IS_XAIJ(Mat A, Mat P, Mat C)
60d71ae5a4SJacob Faibussowitsch {
6175d48cdbSStefano Zampini   MatISPtAP      ptap;
6275d48cdbSStefano Zampini   Mat_IS        *matis = (Mat_IS *)A->data;
6375d48cdbSStefano Zampini   Mat            lA, lC;
6475d48cdbSStefano Zampini   MatReuse       reuse;
6575d48cdbSStefano Zampini   IS             ris[2], cis[2];
6675d48cdbSStefano Zampini   PetscContainer c;
6775d48cdbSStefano Zampini   PetscInt       n;
6875d48cdbSStefano Zampini 
6975d48cdbSStefano Zampini   PetscFunctionBegin;
709566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)C, "_MatIS_PtAP", (PetscObject *)&c));
7128b400f6SJacob Faibussowitsch   PetscCheck(c, PetscObjectComm((PetscObject)C), PETSC_ERR_PLIB, "Missing PtAP information");
72*2a8381b2SBarry Smith   PetscCall(PetscContainerGetPointer(c, &ptap));
7375d48cdbSStefano Zampini   ris[0] = ptap->ris0;
7475d48cdbSStefano Zampini   ris[1] = ptap->ris1;
7575d48cdbSStefano Zampini   cis[0] = ptap->cis0;
7675d48cdbSStefano Zampini   cis[1] = ptap->cis1;
7775d48cdbSStefano Zampini   n      = ptap->ris1 ? 2 : 1;
7875d48cdbSStefano Zampini   reuse  = ptap->lP ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX;
799566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrices(P, n, ris, cis, reuse, &ptap->lP));
8075d48cdbSStefano Zampini 
819566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(A, &lA));
829566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(C, &lC));
8375d48cdbSStefano Zampini   if (ptap->ris1) { /* unsymmetric A mapping */
8475d48cdbSStefano Zampini     Mat lPt;
8575d48cdbSStefano Zampini 
869566063dSJacob Faibussowitsch     PetscCall(MatTranspose(ptap->lP[1], MAT_INITIAL_MATRIX, &lPt));
879566063dSJacob Faibussowitsch     PetscCall(MatMatMatMult(lPt, lA, ptap->lP[0], reuse, ptap->fill, &lC));
8857508eceSPierre Jolivet     if (matis->storel2l) PetscCall(PetscObjectCompose((PetscObject)A, "_MatIS_PtAP_l2l", (PetscObject)lPt));
899566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&lPt));
9075d48cdbSStefano Zampini   } else {
919566063dSJacob Faibussowitsch     PetscCall(MatPtAP(lA, ptap->lP[0], reuse, ptap->fill, &lC));
9248a46eb9SPierre Jolivet     if (matis->storel2l) PetscCall(PetscObjectCompose((PetscObject)C, "_MatIS_PtAP_l2l", (PetscObject)ptap->lP[0]));
9375d48cdbSStefano Zampini   }
9475d48cdbSStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
959566063dSJacob Faibussowitsch     PetscCall(MatISSetLocalMat(C, lC));
969566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&lC));
9775d48cdbSStefano Zampini   }
989566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
999566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
1003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10175d48cdbSStefano Zampini }
10275d48cdbSStefano Zampini 
MatGetNonzeroColumnsLocal_Private(Mat PT,IS * cis)103d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetNonzeroColumnsLocal_Private(Mat PT, IS *cis)
104d71ae5a4SJacob Faibussowitsch {
10575d48cdbSStefano Zampini   Mat             Po, Pd;
10675d48cdbSStefano Zampini   IS              zd, zo;
10775d48cdbSStefano Zampini   const PetscInt *garray;
10875d48cdbSStefano Zampini   PetscInt       *aux, i, bs;
10975d48cdbSStefano Zampini   PetscInt        dc, stc, oc, ctd, cto;
11075d48cdbSStefano Zampini   PetscBool       ismpiaij, ismpibaij, isseqaij, isseqbaij;
11175d48cdbSStefano Zampini   MPI_Comm        comm;
11275d48cdbSStefano Zampini 
11375d48cdbSStefano Zampini   PetscFunctionBegin;
11475d48cdbSStefano Zampini   PetscValidHeaderSpecific(PT, MAT_CLASSID, 1);
1154f572ea9SToby Isaac   PetscAssertPointer(cis, 2);
1169566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)PT, &comm));
11775d48cdbSStefano Zampini   bs = 1;
1189566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)PT, MATMPIAIJ, &ismpiaij));
1199566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)PT, MATMPIBAIJ, &ismpibaij));
1209566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)PT, MATSEQAIJ, &isseqaij));
1219566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)PT, MATSEQBAIJ, &isseqbaij));
12275d48cdbSStefano Zampini   if (isseqaij || isseqbaij) {
12375d48cdbSStefano Zampini     Pd     = PT;
12475d48cdbSStefano Zampini     Po     = NULL;
12575d48cdbSStefano Zampini     garray = NULL;
12675d48cdbSStefano Zampini   } else if (ismpiaij) {
1279566063dSJacob Faibussowitsch     PetscCall(MatMPIAIJGetSeqAIJ(PT, &Pd, &Po, &garray));
12875d48cdbSStefano Zampini   } else if (ismpibaij) {
1299566063dSJacob Faibussowitsch     PetscCall(MatMPIBAIJGetSeqBAIJ(PT, &Pd, &Po, &garray));
1309566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(PT, &bs));
13157508eceSPierre Jolivet   } else SETERRQ(comm, PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)PT)->type_name);
13275d48cdbSStefano Zampini 
13375d48cdbSStefano Zampini   /* identify any null columns in Pd or Po */
13422f7620eSStefano Zampini   /* We use a tolerance comparison since it may happen that, with geometric multigrid,
13522f7620eSStefano Zampini      some of the columns are not really zero, but very close to */
13675d48cdbSStefano Zampini   zo = zd = NULL;
13748a46eb9SPierre Jolivet   if (Po) PetscCall(MatFindNonzeroRowsOrCols_Basic(Po, PETSC_TRUE, PETSC_SMALL, &zo));
1389566063dSJacob Faibussowitsch   PetscCall(MatFindNonzeroRowsOrCols_Basic(Pd, PETSC_TRUE, PETSC_SMALL, &zd));
13975d48cdbSStefano Zampini 
1409566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(PT, NULL, &dc));
1419566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRangeColumn(PT, &stc, NULL));
1429566063dSJacob Faibussowitsch   if (Po) PetscCall(MatGetLocalSize(Po, NULL, &oc));
14375d48cdbSStefano Zampini   else oc = 0;
1449566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1((dc + oc) / bs, &aux));
14575d48cdbSStefano Zampini   if (zd) {
14675d48cdbSStefano Zampini     const PetscInt *idxs;
14775d48cdbSStefano Zampini     PetscInt        nz;
14875d48cdbSStefano Zampini 
14975d48cdbSStefano Zampini     /* this will throw an error if bs is not valid */
1509566063dSJacob Faibussowitsch     PetscCall(ISSetBlockSize(zd, bs));
1519566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(zd, &nz));
1529566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(zd, &idxs));
15375d48cdbSStefano Zampini     ctd = nz / bs;
15475d48cdbSStefano Zampini     for (i = 0; i < ctd; i++) aux[i] = (idxs[bs * i] + stc) / bs;
1559566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(zd, &idxs));
15675d48cdbSStefano Zampini   } else {
15775d48cdbSStefano Zampini     ctd = dc / bs;
15875d48cdbSStefano Zampini     for (i = 0; i < ctd; i++) aux[i] = i + stc / bs;
15975d48cdbSStefano Zampini   }
16075d48cdbSStefano Zampini   if (zo) {
16175d48cdbSStefano Zampini     const PetscInt *idxs;
16275d48cdbSStefano Zampini     PetscInt        nz;
16375d48cdbSStefano Zampini 
16475d48cdbSStefano Zampini     /* this will throw an error if bs is not valid */
1659566063dSJacob Faibussowitsch     PetscCall(ISSetBlockSize(zo, bs));
1669566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(zo, &nz));
1679566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(zo, &idxs));
16875d48cdbSStefano Zampini     cto = nz / bs;
16975d48cdbSStefano Zampini     for (i = 0; i < cto; i++) aux[i + ctd] = garray[idxs[bs * i] / bs];
1709566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(zo, &idxs));
17175d48cdbSStefano Zampini   } else {
17275d48cdbSStefano Zampini     cto = oc / bs;
17375d48cdbSStefano Zampini     for (i = 0; i < cto; i++) aux[i + ctd] = garray[i];
17475d48cdbSStefano Zampini   }
1759566063dSJacob Faibussowitsch   PetscCall(ISCreateBlock(comm, bs, ctd + cto, aux, PETSC_OWN_POINTER, cis));
1769566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&zd));
1779566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&zo));
1783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17975d48cdbSStefano Zampini }
18075d48cdbSStefano Zampini 
MatPtAPSymbolic_IS_XAIJ(Mat A,Mat P,PetscReal fill,Mat C)181d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPSymbolic_IS_XAIJ(Mat A, Mat P, PetscReal fill, Mat C)
182d71ae5a4SJacob Faibussowitsch {
1838546b261SStefano Zampini   Mat                    PT, lA;
18475d48cdbSStefano Zampini   MatISPtAP              ptap;
18575d48cdbSStefano Zampini   ISLocalToGlobalMapping Crl2g, Ccl2g, rl2g, cl2g;
18675d48cdbSStefano Zampini   PetscContainer         c;
1878546b261SStefano Zampini   MatType                lmtype;
18875d48cdbSStefano Zampini   const PetscInt        *garray;
18975d48cdbSStefano Zampini   PetscInt               ibs, N, dc;
19075d48cdbSStefano Zampini   MPI_Comm               comm;
19175d48cdbSStefano Zampini 
19275d48cdbSStefano Zampini   PetscFunctionBegin;
1939566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
1949566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATIS));
1959566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(A, &lA));
1969566063dSJacob Faibussowitsch   PetscCall(MatGetType(lA, &lmtype));
1979566063dSJacob Faibussowitsch   PetscCall(MatISSetLocalMatType(C, lmtype));
1989566063dSJacob Faibussowitsch   PetscCall(MatGetSize(P, NULL, &N));
1999566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(P, NULL, &dc));
2009566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(C, dc, dc, N, N));
20175d48cdbSStefano Zampini   /* Not sure about this
2029566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSizes(P,NULL,&ibs));
2039566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(*C,ibs));
20475d48cdbSStefano Zampini */
20575d48cdbSStefano Zampini 
2069566063dSJacob Faibussowitsch   PetscCall(PetscNew(&ptap));
2079566063dSJacob Faibussowitsch   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c));
2089566063dSJacob Faibussowitsch   PetscCall(PetscContainerSetPointer(c, ptap));
20949abdd8aSBarry Smith   PetscCall(PetscContainerSetCtxDestroy(c, MatISContainerDestroyPtAP_Private));
2109566063dSJacob Faibussowitsch   PetscCall(PetscObjectCompose((PetscObject)C, "_MatIS_PtAP", (PetscObject)c));
2119566063dSJacob Faibussowitsch   PetscCall(PetscContainerDestroy(&c));
21275d48cdbSStefano Zampini   ptap->fill = fill;
21375d48cdbSStefano Zampini 
2149566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalToGlobalMapping(A, &rl2g, &cl2g));
21575d48cdbSStefano Zampini 
2169566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(cl2g, &ibs));
2179566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(cl2g, &N));
2189566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockIndices(cl2g, &garray));
2199566063dSJacob Faibussowitsch   PetscCall(ISCreateBlock(comm, ibs, N / ibs, garray, PETSC_COPY_VALUES, &ptap->ris0));
2209566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(cl2g, &garray));
22175d48cdbSStefano Zampini 
2229566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrix(P, ptap->ris0, NULL, MAT_INITIAL_MATRIX, &PT));
2239566063dSJacob Faibussowitsch   PetscCall(MatGetNonzeroColumnsLocal_Private(PT, &ptap->cis0));
2249566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(ptap->cis0, &Ccl2g));
2259566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&PT));
22675d48cdbSStefano Zampini 
22775d48cdbSStefano Zampini   Crl2g = NULL;
22875d48cdbSStefano Zampini   if (rl2g != cl2g) { /* unsymmetric A mapping */
22975d48cdbSStefano Zampini     PetscBool same, lsame = PETSC_FALSE;
23075d48cdbSStefano Zampini     PetscInt  N1, ibs1;
23175d48cdbSStefano Zampini 
2329566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetSize(rl2g, &N1));
2339566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockSize(rl2g, &ibs1));
2349566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockIndices(rl2g, &garray));
2354f58015eSStefano Zampini     PetscCall(ISCreateBlock(comm, ibs, N1 / ibs, garray, PETSC_COPY_VALUES, &ptap->ris1));
2369566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(rl2g, &garray));
23775d48cdbSStefano Zampini     if (ibs1 == ibs && N1 == N) { /* check if the l2gmaps are the same */
23875d48cdbSStefano Zampini       const PetscInt *i1, *i2;
23975d48cdbSStefano Zampini 
2409566063dSJacob Faibussowitsch       PetscCall(ISBlockGetIndices(ptap->ris0, &i1));
2419566063dSJacob Faibussowitsch       PetscCall(ISBlockGetIndices(ptap->ris1, &i2));
2429566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(i1, i2, N, &lsame));
24375d48cdbSStefano Zampini     }
2445440e5dcSBarry Smith     PetscCallMPI(MPIU_Allreduce(&lsame, &same, 1, MPI_C_BOOL, MPI_LAND, comm));
24575d48cdbSStefano Zampini     if (same) {
2469566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&ptap->ris1));
24775d48cdbSStefano Zampini     } else {
2489566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(P, ptap->ris1, NULL, MAT_INITIAL_MATRIX, &PT));
2499566063dSJacob Faibussowitsch       PetscCall(MatGetNonzeroColumnsLocal_Private(PT, &ptap->cis1));
2509566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreateIS(ptap->cis1, &Crl2g));
2519566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&PT));
25275d48cdbSStefano Zampini     }
25375d48cdbSStefano Zampini   }
25475d48cdbSStefano Zampini   /* Not sure about this
25575d48cdbSStefano Zampini   if (!Crl2g) {
2569566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(C,&ibs));
2579566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingSetBlockSize(Ccl2g,ibs));
25875d48cdbSStefano Zampini   }
25975d48cdbSStefano Zampini */
2609566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(C, Crl2g ? Crl2g : Ccl2g, Ccl2g));
2619566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&Crl2g));
2629566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&Ccl2g));
26375d48cdbSStefano Zampini 
2644222ddf1SHong Zhang   C->ops->ptapnumeric = MatPtAPNumeric_IS_XAIJ;
2653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26675d48cdbSStefano Zampini }
26775d48cdbSStefano Zampini 
MatProductSymbolic_PtAP_IS_XAIJ(Mat C)268d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_PtAP_IS_XAIJ(Mat C)
269d71ae5a4SJacob Faibussowitsch {
2704222ddf1SHong Zhang   Mat_Product *product = C->product;
2714222ddf1SHong Zhang   Mat          A = product->A, P = product->B;
2724222ddf1SHong Zhang   PetscReal    fill = product->fill;
27375d48cdbSStefano Zampini 
27475d48cdbSStefano Zampini   PetscFunctionBegin;
2759566063dSJacob Faibussowitsch   PetscCall(MatPtAPSymbolic_IS_XAIJ(A, P, fill, C));
2764222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
2773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27875d48cdbSStefano Zampini }
27975d48cdbSStefano Zampini 
MatProductSetFromOptions_IS_XAIJ_PtAP(Mat C)280d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_IS_XAIJ_PtAP(Mat C)
281d71ae5a4SJacob Faibussowitsch {
2824222ddf1SHong Zhang   PetscFunctionBegin;
2834222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_PtAP_IS_XAIJ;
2843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2854222ddf1SHong Zhang }
2864222ddf1SHong Zhang 
MatProductSetFromOptions_IS_XAIJ(Mat C)287d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat C)
288d71ae5a4SJacob Faibussowitsch {
2894222ddf1SHong Zhang   Mat_Product *product = C->product;
2904222ddf1SHong Zhang 
2914222ddf1SHong Zhang   PetscFunctionBegin;
29248a46eb9SPierre Jolivet   if (product->type == MATPRODUCT_PtAP) PetscCall(MatProductSetFromOptions_IS_XAIJ_PtAP(C));
2933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2944222ddf1SHong Zhang }
2954222ddf1SHong Zhang 
MatISContainerDestroyFields_Private(PetscCtxRt ptr)296*2a8381b2SBarry Smith static PetscErrorCode MatISContainerDestroyFields_Private(PetscCtxRt ptr)
297d71ae5a4SJacob Faibussowitsch {
298*2a8381b2SBarry Smith   MatISLocalFields lf = *(MatISLocalFields *)ptr;
2995b003df0Sstefano_zampini   PetscInt         i;
3005b003df0Sstefano_zampini 
301ab4d48faSStefano Zampini   PetscFunctionBegin;
30248a46eb9SPierre Jolivet   for (i = 0; i < lf->nr; i++) PetscCall(ISDestroy(&lf->rf[i]));
30348a46eb9SPierre Jolivet   for (i = 0; i < lf->nc; i++) PetscCall(ISDestroy(&lf->cf[i]));
3049566063dSJacob Faibussowitsch   PetscCall(PetscFree2(lf->rf, lf->cf));
3059566063dSJacob Faibussowitsch   PetscCall(PetscFree(lf));
3063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3075b003df0Sstefano_zampini }
308a72627d2SStefano Zampini 
MatConvert_SeqXAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat * newmat)309d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_SeqXAIJ_IS(Mat A, MatType type, MatReuse reuse, Mat *newmat)
310d71ae5a4SJacob Faibussowitsch {
311c9225affSStefano Zampini   Mat B, lB;
312c9225affSStefano Zampini 
313c9225affSStefano Zampini   PetscFunctionBegin;
314c9225affSStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
315c9225affSStefano Zampini     ISLocalToGlobalMapping rl2g, cl2g;
316c9225affSStefano Zampini     PetscInt               bs;
317c9225affSStefano Zampini     IS                     is;
318c9225affSStefano Zampini 
3199566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(A, &bs));
3209566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), A->rmap->n / bs, 0, 1, &is));
321c9225affSStefano Zampini     if (bs > 1) {
322c9225affSStefano Zampini       IS       is2;
323c9225affSStefano Zampini       PetscInt i, *aux;
324c9225affSStefano Zampini 
3259566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(is, &i));
3269566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(is, (const PetscInt **)&aux));
3279566063dSJacob Faibussowitsch       PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), bs, i, aux, PETSC_COPY_VALUES, &is2));
3289566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(is, (const PetscInt **)&aux));
3299566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is));
330c9225affSStefano Zampini       is = is2;
331c9225affSStefano Zampini     }
3329566063dSJacob Faibussowitsch     PetscCall(ISSetIdentity(is));
3339566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g));
3349566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
3359566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), A->cmap->n / bs, 0, 1, &is));
336c9225affSStefano Zampini     if (bs > 1) {
337c9225affSStefano Zampini       IS       is2;
338c9225affSStefano Zampini       PetscInt i, *aux;
339c9225affSStefano Zampini 
3409566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(is, &i));
3419566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(is, (const PetscInt **)&aux));
3429566063dSJacob Faibussowitsch       PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), bs, i, aux, PETSC_COPY_VALUES, &is2));
3439566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(is, (const PetscInt **)&aux));
3449566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is));
345c9225affSStefano Zampini       is = is2;
346c9225affSStefano Zampini     }
3479566063dSJacob Faibussowitsch     PetscCall(ISSetIdentity(is));
3489566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g));
3499566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
3509566063dSJacob Faibussowitsch     PetscCall(MatCreateIS(PetscObjectComm((PetscObject)A), bs, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N, rl2g, cl2g, &B));
3519566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
3529566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
3539566063dSJacob Faibussowitsch     PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &lB));
354c9225affSStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) *newmat = B;
355c9225affSStefano Zampini   } else {
356c9225affSStefano Zampini     B = *newmat;
3579566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)A));
358c9225affSStefano Zampini     lB = A;
359c9225affSStefano Zampini   }
3609566063dSJacob Faibussowitsch   PetscCall(MatISSetLocalMat(B, lB));
3619566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&lB));
3629566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
3639566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
36448a46eb9SPierre Jolivet   if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &B));
3653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
366c9225affSStefano Zampini }
367c9225affSStefano Zampini 
MatISScaleDisassembling_Private(Mat A)368d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISScaleDisassembling_Private(Mat A)
369d71ae5a4SJacob Faibussowitsch {
370f4f49eeaSPierre Jolivet   Mat_IS         *matis = (Mat_IS *)A->data;
371c9225affSStefano Zampini   PetscScalar    *aa;
372c9225affSStefano Zampini   const PetscInt *ii, *jj;
373c9225affSStefano Zampini   PetscInt        i, n, m;
374fabe8965SStefano Zampini   PetscInt       *ecount, **eneighs;
375c9225affSStefano Zampini   PetscBool       flg;
376c9225affSStefano Zampini 
377c9225affSStefano Zampini   PetscFunctionBegin;
3789566063dSJacob Faibussowitsch   PetscCall(MatGetRowIJ(matis->A, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg));
37908401ef6SPierre Jolivet   PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get IJ structure");
3809566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetNodeInfo(matis->rmapping, &n, &ecount, &eneighs));
38108401ef6SPierre Jolivet   PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, m, n);
3829566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(matis->A, &aa));
383c9225affSStefano Zampini   for (i = 0; i < n; i++) {
384fabe8965SStefano Zampini     if (ecount[i] > 1) {
385c9225affSStefano Zampini       PetscInt j;
386c9225affSStefano Zampini 
387c9225affSStefano Zampini       for (j = ii[i]; j < ii[i + 1]; j++) {
388c9225affSStefano Zampini         PetscInt  i2   = jj[j], p, p2;
389fabe8965SStefano Zampini         PetscReal scal = 0.0;
390c9225affSStefano Zampini 
391c9225affSStefano Zampini         for (p = 0; p < ecount[i]; p++) {
392c9225affSStefano Zampini           for (p2 = 0; p2 < ecount[i2]; p2++) {
3939371c9d4SSatish Balay             if (eneighs[i][p] == eneighs[i2][p2]) {
3949371c9d4SSatish Balay               scal += 1.0;
3959371c9d4SSatish Balay               break;
3969371c9d4SSatish Balay             }
397c9225affSStefano Zampini           }
398c9225affSStefano Zampini         }
399fabe8965SStefano Zampini         if (scal) aa[j] /= scal;
400c9225affSStefano Zampini       }
401c9225affSStefano Zampini     }
402c9225affSStefano Zampini   }
4039566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(matis->rmapping, &n, &ecount, &eneighs));
4049566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(matis->A, &aa));
4059566063dSJacob Faibussowitsch   PetscCall(MatRestoreRowIJ(matis->A, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg));
40608401ef6SPierre Jolivet   PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot restore IJ structure");
4073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
408c9225affSStefano Zampini }
409c9225affSStefano Zampini 
4109371c9d4SSatish Balay typedef enum {
4119371c9d4SSatish Balay   MAT_IS_DISASSEMBLE_L2G_NATURAL,
4129371c9d4SSatish Balay   MAT_IS_DISASSEMBLE_L2G_MAT,
4139371c9d4SSatish Balay   MAT_IS_DISASSEMBLE_L2G_ND
4149371c9d4SSatish Balay } MatISDisassemblel2gType;
415fabe8965SStefano Zampini 
MatMPIXAIJComputeLocalToGlobalMapping_Private(Mat A,ISLocalToGlobalMapping * l2g)416d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMPIXAIJComputeLocalToGlobalMapping_Private(Mat A, ISLocalToGlobalMapping *l2g)
417d71ae5a4SJacob Faibussowitsch {
418fabe8965SStefano Zampini   Mat                     Ad, Ao;
419fabe8965SStefano Zampini   IS                      is, ndmap, ndsub;
420c9225affSStefano Zampini   MPI_Comm                comm;
421fabe8965SStefano Zampini   const PetscInt         *garray, *ndmapi;
422fabe8965SStefano Zampini   PetscInt                bs, i, cnt, nl, *ncount, *ndmapc;
423fabe8965SStefano Zampini   PetscBool               ismpiaij, ismpibaij;
424f4259b30SLisandro Dalcin   const char *const       MatISDisassemblel2gTypes[] = {"NATURAL", "MAT", "ND", "MatISDisassemblel2gType", "MAT_IS_DISASSEMBLE_L2G_", NULL};
425fabe8965SStefano Zampini   MatISDisassemblel2gType mode                       = MAT_IS_DISASSEMBLE_L2G_NATURAL;
426fabe8965SStefano Zampini   MatPartitioning         part;
427fabe8965SStefano Zampini   PetscSF                 sf;
42891d376acSStefano Zampini   PetscObject             dm;
429c9225affSStefano Zampini 
430c9225affSStefano Zampini   PetscFunctionBegin;
431d0609cedSBarry Smith   PetscOptionsBegin(PetscObjectComm((PetscObject)A), ((PetscObject)A)->prefix, "MatIS l2g disassembling options", "Mat");
4329566063dSJacob 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));
433d0609cedSBarry Smith   PetscOptionsEnd();
434fabe8965SStefano Zampini   if (mode == MAT_IS_DISASSEMBLE_L2G_MAT) {
4359566063dSJacob Faibussowitsch     PetscCall(MatGetLocalToGlobalMapping(A, l2g, NULL));
4363ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
437c9225affSStefano Zampini   }
4389566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
4399566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
4409566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIBAIJ, &ismpibaij));
4419566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(A, &bs));
442fabe8965SStefano Zampini   switch (mode) {
443fabe8965SStefano Zampini   case MAT_IS_DISASSEMBLE_L2G_ND:
4449566063dSJacob Faibussowitsch     PetscCall(MatPartitioningCreate(comm, &part));
4459566063dSJacob Faibussowitsch     PetscCall(MatPartitioningSetAdjacency(part, A));
4469566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)part, ((PetscObject)A)->prefix));
4479566063dSJacob Faibussowitsch     PetscCall(MatPartitioningSetFromOptions(part));
4489566063dSJacob Faibussowitsch     PetscCall(MatPartitioningApplyND(part, &ndmap));
4499566063dSJacob Faibussowitsch     PetscCall(MatPartitioningDestroy(&part));
4509566063dSJacob Faibussowitsch     PetscCall(ISBuildTwoSided(ndmap, NULL, &ndsub));
4519566063dSJacob Faibussowitsch     PetscCall(MatMPIAIJSetUseScalableIncreaseOverlap(A, PETSC_TRUE));
4529566063dSJacob Faibussowitsch     PetscCall(MatIncreaseOverlap(A, 1, &ndsub, 1));
4539566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(ndsub, l2g));
454fabe8965SStefano Zampini 
455fabe8965SStefano Zampini     /* it may happen that a separator node is not properly shared */
4569566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetNodeInfo(*l2g, &nl, &ncount, NULL));
4579566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(comm, &sf));
4589566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetIndices(*l2g, &garray));
4599566063dSJacob Faibussowitsch     PetscCall(PetscSFSetGraphLayout(sf, A->rmap, nl, NULL, PETSC_OWN_POINTER, garray));
4609566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreIndices(*l2g, &garray));
4619566063dSJacob Faibussowitsch     PetscCall(PetscCalloc1(A->rmap->n, &ndmapc));
4629566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceBegin(sf, MPIU_INT, ncount, ndmapc, MPI_REPLACE));
4639566063dSJacob Faibussowitsch     PetscCall(PetscSFReduceEnd(sf, MPIU_INT, ncount, ndmapc, MPI_REPLACE));
4649566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(*l2g, NULL, &ncount, NULL));
4659566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(ndmap, &ndmapi));
466fabe8965SStefano Zampini     for (i = 0, cnt = 0; i < A->rmap->n; i++)
4679371c9d4SSatish Balay       if (ndmapi[i] < 0 && ndmapc[i] < 2) cnt++;
468fabe8965SStefano Zampini 
469462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(&cnt, &i, 1, MPIU_INT, MPI_MAX, comm));
470fabe8965SStefano Zampini     if (i) { /* we detected isolated separator nodes */
471fabe8965SStefano Zampini       Mat                    A2, A3;
472fabe8965SStefano Zampini       IS                    *workis, is2;
473fabe8965SStefano Zampini       PetscScalar           *vals;
474fabe8965SStefano Zampini       PetscInt               gcnt = i, *dnz, *onz, j, *lndmapi;
475fabe8965SStefano Zampini       ISLocalToGlobalMapping ll2g;
476fabe8965SStefano Zampini       PetscBool              flg;
477fabe8965SStefano Zampini       const PetscInt        *ii, *jj;
478fabe8965SStefano Zampini 
479fabe8965SStefano Zampini       /* communicate global id of separators */
480d0609cedSBarry Smith       MatPreallocateBegin(comm, A->rmap->n, A->cmap->n, dnz, onz);
4819371c9d4SSatish Balay       for (i = 0, cnt = 0; i < A->rmap->n; i++) dnz[i] = ndmapi[i] < 0 ? i + A->rmap->rstart : -1;
482fabe8965SStefano Zampini 
4839566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(nl, &lndmapi));
4849566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastBegin(sf, MPIU_INT, dnz, lndmapi, MPI_REPLACE));
485fabe8965SStefano Zampini 
486fabe8965SStefano Zampini       /* compute adjacency of isolated separators node */
4879566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(gcnt, &workis));
488fabe8965SStefano Zampini       for (i = 0, cnt = 0; i < A->rmap->n; i++) {
48948a46eb9SPierre Jolivet         if (ndmapi[i] < 0 && ndmapc[i] < 2) PetscCall(ISCreateStride(comm, 1, i + A->rmap->rstart, 1, &workis[cnt++]));
490fabe8965SStefano Zampini       }
49148a46eb9SPierre Jolivet       for (i = cnt; i < gcnt; i++) PetscCall(ISCreateStride(comm, 0, 0, 1, &workis[i]));
492fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
4939566063dSJacob Faibussowitsch         PetscCall(PetscObjectSetName((PetscObject)workis[i], "ISOLATED"));
4949566063dSJacob Faibussowitsch         PetscCall(ISViewFromOptions(workis[i], NULL, "-view_isolated_separators"));
495fabe8965SStefano Zampini       }
496fabe8965SStefano Zampini 
497fabe8965SStefano Zampini       /* no communications since all the ISes correspond to locally owned rows */
4989566063dSJacob Faibussowitsch       PetscCall(MatIncreaseOverlap(A, gcnt, workis, 1));
499fabe8965SStefano Zampini 
500fabe8965SStefano Zampini       /* end communicate global id of separators */
5019566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastEnd(sf, MPIU_INT, dnz, lndmapi, MPI_REPLACE));
502fabe8965SStefano Zampini 
503fabe8965SStefano Zampini       /* communicate new layers : create a matrix and transpose it */
5049566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(dnz, A->rmap->n));
5059566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(onz, A->rmap->n));
506fabe8965SStefano Zampini       for (i = 0, j = 0; i < A->rmap->n; i++) {
507fabe8965SStefano Zampini         if (ndmapi[i] < 0 && ndmapc[i] < 2) {
508fabe8965SStefano Zampini           const PetscInt *idxs;
509fabe8965SStefano Zampini           PetscInt        s;
510fabe8965SStefano Zampini 
5119566063dSJacob Faibussowitsch           PetscCall(ISGetLocalSize(workis[j], &s));
5129566063dSJacob Faibussowitsch           PetscCall(ISGetIndices(workis[j], &idxs));
5139566063dSJacob Faibussowitsch           PetscCall(MatPreallocateSet(i + A->rmap->rstart, s, idxs, dnz, onz));
514fabe8965SStefano Zampini           j++;
515fabe8965SStefano Zampini         }
516fabe8965SStefano Zampini       }
51708401ef6SPierre Jolivet       PetscCheck(j == cnt, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected local count %" PetscInt_FMT " != %" PetscInt_FMT, j, cnt);
518fabe8965SStefano Zampini 
519fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
5209566063dSJacob Faibussowitsch         PetscCall(PetscObjectSetName((PetscObject)workis[i], "EXTENDED"));
5219566063dSJacob Faibussowitsch         PetscCall(ISViewFromOptions(workis[i], NULL, "-view_isolated_separators"));
522fabe8965SStefano Zampini       }
523fabe8965SStefano Zampini 
524fabe8965SStefano Zampini       for (i = 0, j = 0; i < A->rmap->n; i++) j = PetscMax(j, dnz[i] + onz[i]);
5259566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(j, &vals));
526fabe8965SStefano Zampini       for (i = 0; i < j; i++) vals[i] = 1.0;
527fabe8965SStefano Zampini 
5289566063dSJacob Faibussowitsch       PetscCall(MatCreate(comm, &A2));
5299566063dSJacob Faibussowitsch       PetscCall(MatSetType(A2, MATMPIAIJ));
5309566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(A2, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
5319566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJSetPreallocation(A2, 0, dnz, 0, onz));
5329566063dSJacob Faibussowitsch       PetscCall(MatSetOption(A2, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE));
533fabe8965SStefano Zampini       for (i = 0, j = 0; i < A2->rmap->n; i++) {
534fabe8965SStefano Zampini         PetscInt        row = i + A2->rmap->rstart, s = dnz[i] + onz[i];
535fabe8965SStefano Zampini         const PetscInt *idxs;
536fabe8965SStefano Zampini 
537fabe8965SStefano Zampini         if (s) {
5389566063dSJacob Faibussowitsch           PetscCall(ISGetIndices(workis[j], &idxs));
5399566063dSJacob Faibussowitsch           PetscCall(MatSetValues(A2, 1, &row, s, idxs, vals, INSERT_VALUES));
5409566063dSJacob Faibussowitsch           PetscCall(ISRestoreIndices(workis[j], &idxs));
541fabe8965SStefano Zampini           j++;
542fabe8965SStefano Zampini         }
543fabe8965SStefano Zampini       }
54408401ef6SPierre Jolivet       PetscCheck(j == cnt, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected local count %" PetscInt_FMT " != %" PetscInt_FMT, j, cnt);
5459566063dSJacob Faibussowitsch       PetscCall(PetscFree(vals));
5469566063dSJacob Faibussowitsch       PetscCall(MatAssemblyBegin(A2, MAT_FINAL_ASSEMBLY));
5479566063dSJacob Faibussowitsch       PetscCall(MatAssemblyEnd(A2, MAT_FINAL_ASSEMBLY));
5489566063dSJacob Faibussowitsch       PetscCall(MatTranspose(A2, MAT_INPLACE_MATRIX, &A2));
549fabe8965SStefano Zampini 
550fabe8965SStefano Zampini       /* extract submatrix corresponding to the coupling "owned separators" x "isolated separators" */
551fabe8965SStefano Zampini       for (i = 0, j = 0; i < nl; i++)
552fabe8965SStefano Zampini         if (lndmapi[i] >= 0) lndmapi[j++] = lndmapi[i];
5539566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(comm, j, lndmapi, PETSC_USE_POINTER, &is));
5549566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJGetLocalMatCondensed(A2, MAT_INITIAL_MATRIX, &is, NULL, &A3));
5559566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is));
5569566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&A2));
557fabe8965SStefano Zampini 
558fabe8965SStefano Zampini       /* extend local to global map to include connected isolated separators */
5599566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)A3, "_petsc_GetLocalMatCondensed_iscol", (PetscObject *)&is));
56028b400f6SJacob Faibussowitsch       PetscCheck(is, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing column map");
5619566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreateIS(is, &ll2g));
5629566063dSJacob Faibussowitsch       PetscCall(MatGetRowIJ(A3, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &flg));
56328b400f6SJacob Faibussowitsch       PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get IJ structure");
5649566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ii[i], jj, PETSC_COPY_VALUES, &is));
5659566063dSJacob Faibussowitsch       PetscCall(MatRestoreRowIJ(A3, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &flg));
56628b400f6SJacob Faibussowitsch       PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get IJ structure");
5679566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingApplyIS(ll2g, is, &is2));
5689566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is));
5699566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingDestroy(&ll2g));
570fabe8965SStefano Zampini 
571fabe8965SStefano Zampini       /* add new nodes to the local-to-global map */
5729566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingDestroy(l2g));
5739566063dSJacob Faibussowitsch       PetscCall(ISExpand(ndsub, is2, &is));
5749566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is2));
5759566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreateIS(is, l2g));
5769566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is));
577fabe8965SStefano Zampini 
5789566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&A3));
5799566063dSJacob Faibussowitsch       PetscCall(PetscFree(lndmapi));
580d0609cedSBarry Smith       MatPreallocateEnd(dnz, onz);
58148a46eb9SPierre Jolivet       for (i = 0; i < gcnt; i++) PetscCall(ISDestroy(&workis[i]));
5829566063dSJacob Faibussowitsch       PetscCall(PetscFree(workis));
583fabe8965SStefano Zampini     }
5849566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(ndmap, &ndmapi));
5859566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sf));
5869566063dSJacob Faibussowitsch     PetscCall(PetscFree(ndmapc));
5879566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&ndmap));
5889566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&ndsub));
5899566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingSetBlockSize(*l2g, bs));
5904f58015eSStefano Zampini     PetscCall(ISLocalToGlobalMappingViewFromOptions(*l2g, NULL, "-mat_is_nd_l2g_view"));
591fabe8965SStefano Zampini     break;
592fabe8965SStefano Zampini   case MAT_IS_DISASSEMBLE_L2G_NATURAL:
593835f2295SStefano Zampini     PetscCall(PetscObjectQuery((PetscObject)A, "__PETSc_dm", &dm));
59491d376acSStefano Zampini     if (dm) { /* if a matrix comes from a DM, most likely we can use the l2gmap if any */
59591d376acSStefano Zampini       PetscCall(MatGetLocalToGlobalMapping(A, l2g, NULL));
59691d376acSStefano Zampini       PetscCall(PetscObjectReference((PetscObject)*l2g));
5973ba16761SJacob Faibussowitsch       if (*l2g) PetscFunctionReturn(PETSC_SUCCESS);
59891d376acSStefano Zampini     }
599fabe8965SStefano Zampini     if (ismpiaij) {
6009566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJGetSeqAIJ(A, &Ad, &Ao, &garray));
601fabe8965SStefano Zampini     } else if (ismpibaij) {
6029566063dSJacob Faibussowitsch       PetscCall(MatMPIBAIJGetSeqBAIJ(A, &Ad, &Ao, &garray));
60398921bdaSJacob Faibussowitsch     } else SETERRQ(comm, PETSC_ERR_SUP, "Type %s", ((PetscObject)A)->type_name);
604c9225affSStefano Zampini     if (A->rmap->n) {
605fabe8965SStefano Zampini       PetscInt dc, oc, stc, *aux;
606c9225affSStefano Zampini 
607ebf8cefbSJunchao Zhang       PetscCall(MatGetLocalSize(Ad, NULL, &dc));
6089566063dSJacob Faibussowitsch       PetscCall(MatGetLocalSize(Ao, NULL, &oc));
609d0dbe9f7SStefano Zampini       PetscCheck(!oc || garray, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "garray not present");
6109566063dSJacob Faibussowitsch       PetscCall(MatGetOwnershipRangeColumn(A, &stc, NULL));
6119566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1((dc + oc) / bs, &aux));
612c9225affSStefano Zampini       for (i = 0; i < dc / bs; i++) aux[i] = i + stc / bs;
613ebf8cefbSJunchao Zhang       for (i = 0; i < oc / bs; i++) aux[i + dc / bs] = (ismpiaij ? garray[i * bs] / bs : garray[i]);
6149566063dSJacob Faibussowitsch       PetscCall(ISCreateBlock(comm, bs, (dc + oc) / bs, aux, PETSC_OWN_POINTER, &is));
615c9225affSStefano Zampini     } else {
6169566063dSJacob Faibussowitsch       PetscCall(ISCreateBlock(comm, 1, 0, NULL, PETSC_OWN_POINTER, &is));
617c9225affSStefano Zampini     }
6189566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is, l2g));
6199566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
620fabe8965SStefano Zampini     break;
621d71ae5a4SJacob Faibussowitsch   default:
622d71ae5a4SJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unsupported l2g disassembling type %d", mode);
623c9225affSStefano Zampini   }
6243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
625c9225affSStefano Zampini }
626c9225affSStefano Zampini 
MatConvert_XAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat * newmat)627d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat A, MatType type, MatReuse reuse, Mat *newmat)
628d71ae5a4SJacob Faibussowitsch {
629c9225affSStefano Zampini   Mat                    lA, Ad, Ao, B = NULL;
6306989cf23SStefano Zampini   ISLocalToGlobalMapping rl2g, cl2g;
6316989cf23SStefano Zampini   IS                     is;
6326989cf23SStefano Zampini   MPI_Comm               comm;
6336989cf23SStefano Zampini   void                  *ptrs[2];
6346989cf23SStefano Zampini   const char            *names[2] = {"_convert_csr_aux", "_convert_csr_data"};
635c9225affSStefano Zampini   const PetscInt        *garray;
6366989cf23SStefano Zampini   PetscScalar           *dd, *od, *aa, *data;
637c9225affSStefano Zampini   const PetscInt        *di, *dj, *oi, *oj;
638c9225affSStefano Zampini   const PetscInt        *odi, *odj, *ooi, *ooj;
6396989cf23SStefano Zampini   PetscInt              *aux, *ii, *jj;
640a50ef18cSStefano Zampini   PetscInt               rbs, cbs, lc, dr, dc, oc, str, stc, nnz, i, jd, jo, cum;
641a50ef18cSStefano Zampini   PetscBool              flg, ismpiaij, ismpibaij, was_inplace = PETSC_FALSE, cong;
642c9225affSStefano Zampini   PetscMPIInt            size;
6436989cf23SStefano Zampini 
644ab4d48faSStefano Zampini   PetscFunctionBegin;
6459566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
6469566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
647c9225affSStefano Zampini   if (size == 1) {
6489566063dSJacob Faibussowitsch     PetscCall(MatConvert_SeqXAIJ_IS(A, type, reuse, newmat));
6493ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
650c9225affSStefano Zampini   }
651a50ef18cSStefano Zampini   PetscCall(MatGetBlockSizes(A, &rbs, &cbs));
652a50ef18cSStefano Zampini   PetscCall(MatHasCongruentLayouts(A, &cong));
653a50ef18cSStefano Zampini   if (reuse != MAT_REUSE_MATRIX && cong && rbs == cbs) {
6549566063dSJacob Faibussowitsch     PetscCall(MatMPIXAIJComputeLocalToGlobalMapping_Private(A, &rl2g));
6559566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm, &B));
6569566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, MATIS));
657a50ef18cSStefano Zampini     PetscCall(MatSetSizes(B, A->rmap->n, A->rmap->n, A->rmap->N, A->rmap->N));
6589566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(B, rl2g, rl2g));
659a50ef18cSStefano Zampini     PetscCall(MatSetBlockSizes(B, rbs, rbs));
6609566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
661c9225affSStefano Zampini     if (reuse == MAT_INPLACE_MATRIX) was_inplace = PETSC_TRUE;
662c9225affSStefano Zampini     reuse = MAT_REUSE_MATRIX;
663c9225affSStefano Zampini   }
664c9225affSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
665c9225affSStefano Zampini     Mat            *newlA, lA;
666c9225affSStefano Zampini     IS              rows, cols;
667c9225affSStefano Zampini     const PetscInt *ridx, *cidx;
668a50ef18cSStefano Zampini     PetscInt        nr, nc;
669c9225affSStefano Zampini 
670c9225affSStefano Zampini     if (!B) B = *newmat;
6719566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalToGlobalMapping(B, &rl2g, &cl2g));
6729566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockIndices(rl2g, &ridx));
6739566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockIndices(cl2g, &cidx));
6749566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetSize(rl2g, &nr));
6759566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetSize(cl2g, &nc));
6769566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockSize(rl2g, &rbs));
6779566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockSize(cl2g, &cbs));
6789566063dSJacob Faibussowitsch     PetscCall(ISCreateBlock(comm, rbs, nr / rbs, ridx, PETSC_USE_POINTER, &rows));
679c9225affSStefano Zampini     if (rl2g != cl2g) {
6809566063dSJacob Faibussowitsch       PetscCall(ISCreateBlock(comm, cbs, nc / cbs, cidx, PETSC_USE_POINTER, &cols));
681c9225affSStefano Zampini     } else {
6829566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)rows));
683c9225affSStefano Zampini       cols = rows;
684c9225affSStefano Zampini     }
6859566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(B, &lA));
6869566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrices(A, 1, &rows, &cols, MAT_INITIAL_MATRIX, &newlA));
6879566063dSJacob Faibussowitsch     PetscCall(MatConvert(newlA[0], MATSEQAIJ, MAT_INPLACE_MATRIX, &newlA[0]));
6889566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(rl2g, &ridx));
6899566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(cl2g, &cidx));
6909566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&rows));
6919566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&cols));
692c9225affSStefano Zampini     if (!lA->preallocated) { /* first time */
6939566063dSJacob Faibussowitsch       PetscCall(MatDuplicate(newlA[0], MAT_COPY_VALUES, &lA));
6949566063dSJacob Faibussowitsch       PetscCall(MatISSetLocalMat(B, lA));
6959566063dSJacob Faibussowitsch       PetscCall(PetscObjectDereference((PetscObject)lA));
696c9225affSStefano Zampini     }
6979566063dSJacob Faibussowitsch     PetscCall(MatCopy(newlA[0], lA, SAME_NONZERO_PATTERN));
6989566063dSJacob Faibussowitsch     PetscCall(MatDestroySubMatrices(1, &newlA));
6999566063dSJacob Faibussowitsch     PetscCall(MatISScaleDisassembling_Private(B));
7009566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
7019566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
7029566063dSJacob Faibussowitsch     if (was_inplace) PetscCall(MatHeaderReplace(A, &B));
703c9225affSStefano Zampini     else *newmat = B;
7043ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
705c9225affSStefano Zampini   }
706a50ef18cSStefano Zampini   /* general case, just compress out the column space */
7079566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
7089566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIBAIJ, &ismpibaij));
709c9225affSStefano Zampini   if (ismpiaij) {
710a50ef18cSStefano Zampini     cbs = 1; /* We cannot guarantee the off-process matrix will respect the column block size */
7119566063dSJacob Faibussowitsch     PetscCall(MatMPIAIJGetSeqAIJ(A, &Ad, &Ao, &garray));
712c9225affSStefano Zampini   } else if (ismpibaij) {
7139566063dSJacob Faibussowitsch     PetscCall(MatMPIBAIJGetSeqBAIJ(A, &Ad, &Ao, &garray));
7149566063dSJacob Faibussowitsch     PetscCall(MatConvert(Ad, MATSEQAIJ, MAT_INITIAL_MATRIX, &Ad));
7159566063dSJacob Faibussowitsch     PetscCall(MatConvert(Ao, MATSEQAIJ, MAT_INITIAL_MATRIX, &Ao));
71698921bdaSJacob Faibussowitsch   } else SETERRQ(comm, PETSC_ERR_SUP, "Type %s", ((PetscObject)A)->type_name);
7179566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(Ad, &dd));
7189566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArray(Ao, &od));
7196989cf23SStefano Zampini 
7206989cf23SStefano Zampini   /* access relevant information from MPIAIJ */
7219566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &str, NULL));
7229566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRangeColumn(A, &stc, NULL));
723a50ef18cSStefano Zampini   PetscCall(MatGetLocalSize(Ad, &dr, &dc));
7249566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(Ao, NULL, &oc));
725d72e20dbSStefano Zampini   PetscCheck(!oc || garray, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "garray not present");
726d72e20dbSStefano Zampini 
7279566063dSJacob Faibussowitsch   PetscCall(MatGetRowIJ(Ad, 0, PETSC_FALSE, PETSC_FALSE, &i, &di, &dj, &flg));
72828b400f6SJacob Faibussowitsch   PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get IJ structure");
7299566063dSJacob Faibussowitsch   PetscCall(MatGetRowIJ(Ao, 0, PETSC_FALSE, PETSC_FALSE, &i, &oi, &oj, &flg));
73028b400f6SJacob Faibussowitsch   PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get IJ structure");
731c9225affSStefano Zampini   nnz = di[dr] + oi[dr];
732c9225affSStefano Zampini   /* store original pointers to be restored later */
7339371c9d4SSatish Balay   odi = di;
7349371c9d4SSatish Balay   odj = dj;
7359371c9d4SSatish Balay   ooi = oi;
7369371c9d4SSatish Balay   ooj = oj;
7376989cf23SStefano Zampini 
7386989cf23SStefano Zampini   /* generate l2g maps for rows and cols */
739a50ef18cSStefano Zampini   PetscCall(ISCreateStride(comm, dr / rbs, str / rbs, 1, &is));
740a50ef18cSStefano Zampini   if (rbs > 1) {
741c9225affSStefano Zampini     IS is2;
742c9225affSStefano Zampini 
7439566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(is, &i));
7449566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(is, (const PetscInt **)&aux));
745a50ef18cSStefano Zampini     PetscCall(ISCreateBlock(comm, rbs, i, aux, PETSC_COPY_VALUES, &is2));
7469566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(is, (const PetscInt **)&aux));
7479566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
748c9225affSStefano Zampini     is = is2;
749c9225affSStefano Zampini   }
7509566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g));
7519566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
752e363d98aSStefano Zampini   if (dr) {
753a50ef18cSStefano Zampini     PetscCall(PetscMalloc1((dc + oc) / cbs, &aux));
754a50ef18cSStefano Zampini     for (i = 0; i < dc / cbs; i++) aux[i] = i + stc / cbs;
755a50ef18cSStefano Zampini     for (i = 0; i < oc / cbs; i++) aux[i + dc / cbs] = garray[i];
756a50ef18cSStefano Zampini     PetscCall(ISCreateBlock(comm, cbs, (dc + oc) / cbs, aux, PETSC_OWN_POINTER, &is));
757e363d98aSStefano Zampini     lc = dc + oc;
758e363d98aSStefano Zampini   } else {
759a50ef18cSStefano Zampini     PetscCall(ISCreateBlock(comm, cbs, 0, NULL, PETSC_OWN_POINTER, &is));
760e363d98aSStefano Zampini     lc = 0;
761e363d98aSStefano Zampini   }
7629566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g));
7639566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
7646989cf23SStefano Zampini 
7656989cf23SStefano Zampini   /* create MATIS object */
7669566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, &B));
7679566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(B, dr, dc, PETSC_DECIDE, PETSC_DECIDE));
7689566063dSJacob Faibussowitsch   PetscCall(MatSetType(B, MATIS));
769a50ef18cSStefano Zampini   PetscCall(MatSetBlockSizes(B, rbs, cbs));
7709566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(B, rl2g, cl2g));
7719566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
7729566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
7736989cf23SStefano Zampini 
7746989cf23SStefano Zampini   /* merge local matrices */
7759566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nnz + dr + 1, &aux));
7769566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nnz, &data));
7776989cf23SStefano Zampini   ii  = aux;
7786989cf23SStefano Zampini   jj  = aux + dr + 1;
7796989cf23SStefano Zampini   aa  = data;
7806989cf23SStefano Zampini   *ii = *(di++) + *(oi++);
7819371c9d4SSatish Balay   for (jd = 0, jo = 0, cum = 0; *ii < nnz; cum++) {
7829371c9d4SSatish Balay     for (; jd < *di; jd++) {
7839371c9d4SSatish Balay       *jj++ = *dj++;
7849371c9d4SSatish Balay       *aa++ = *dd++;
7859371c9d4SSatish Balay     }
7869371c9d4SSatish Balay     for (; jo < *oi; jo++) {
7879371c9d4SSatish Balay       *jj++ = *oj++ + dc;
7889371c9d4SSatish Balay       *aa++ = *od++;
7899371c9d4SSatish Balay     }
7906989cf23SStefano Zampini     *(++ii) = *(di++) + *(oi++);
7916989cf23SStefano Zampini   }
7926989cf23SStefano Zampini   for (; cum < dr; cum++) *(++ii) = nnz;
793c9225affSStefano Zampini 
7949566063dSJacob Faibussowitsch   PetscCall(MatRestoreRowIJ(Ad, 0, PETSC_FALSE, PETSC_FALSE, &i, &odi, &odj, &flg));
79528b400f6SJacob Faibussowitsch   PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot restore IJ structure");
7969566063dSJacob Faibussowitsch   PetscCall(MatRestoreRowIJ(Ao, 0, PETSC_FALSE, PETSC_FALSE, &i, &ooi, &ooj, &flg));
79728b400f6SJacob Faibussowitsch   PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot restore IJ structure");
7989566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(Ad, &dd));
7999566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArray(Ao, &od));
800c9225affSStefano Zampini 
8016989cf23SStefano Zampini   ii = aux;
8026989cf23SStefano Zampini   jj = aux + dr + 1;
8036989cf23SStefano Zampini   aa = data;
8049566063dSJacob Faibussowitsch   PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, dr, lc, ii, jj, aa, &lA));
8056989cf23SStefano Zampini 
8066989cf23SStefano Zampini   /* create containers to destroy the data */
8076989cf23SStefano Zampini   ptrs[0] = aux;
8086989cf23SStefano Zampini   ptrs[1] = data;
80949abdd8aSBarry Smith   for (i = 0; i < 2; i++) PetscCall(PetscObjectContainerCompose((PetscObject)lA, names[i], ptrs[i], PetscCtxDestroyDefault));
810c9225affSStefano Zampini   if (ismpibaij) { /* destroy converted local matrices */
8119566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Ad));
8129566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Ao));
813c9225affSStefano Zampini   }
8146989cf23SStefano Zampini 
8156989cf23SStefano Zampini   /* finalize matrix */
8169566063dSJacob Faibussowitsch   PetscCall(MatISSetLocalMat(B, lA));
8179566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&lA));
8189566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
8199566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
820ac530a7eSPierre Jolivet   if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &B));
821ac530a7eSPierre Jolivet   else *newmat = B;
8223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8236989cf23SStefano Zampini }
8246989cf23SStefano Zampini 
MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat * newmat)825d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A, MatType type, MatReuse reuse, Mat *newmat)
826d71ae5a4SJacob Faibussowitsch {
8275e3038f0Sstefano_zampini   Mat                  **nest, *snest, **rnest, lA, B;
8285e3038f0Sstefano_zampini   IS                    *iscol, *isrow, *islrow, *islcol;
8295e3038f0Sstefano_zampini   ISLocalToGlobalMapping rl2g, cl2g;
8305e3038f0Sstefano_zampini   MPI_Comm               comm;
8315b003df0Sstefano_zampini   PetscInt              *lr, *lc, *l2gidxs;
8325b003df0Sstefano_zampini   PetscInt               i, j, nr, nc, rbs, cbs;
8339e7b2b25Sstefano_zampini   PetscBool              convert, lreuse, *istrans;
8344f58015eSStefano Zampini   PetscBool3             allow_repeated = PETSC_BOOL3_UNKNOWN;
8355e3038f0Sstefano_zampini 
836ab4d48faSStefano Zampini   PetscFunctionBegin;
8379566063dSJacob Faibussowitsch   PetscCall(MatNestGetSubMats(A, &nr, &nc, &nest));
8385e3038f0Sstefano_zampini   lreuse = PETSC_FALSE;
8395e3038f0Sstefano_zampini   rnest  = NULL;
8405e3038f0Sstefano_zampini   if (reuse == MAT_REUSE_MATRIX) {
8415e3038f0Sstefano_zampini     PetscBool ismatis, isnest;
8425e3038f0Sstefano_zampini 
8439566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)*newmat, MATIS, &ismatis));
844f4f49eeaSPierre Jolivet     PetscCheck(ismatis, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_USER, "Cannot reuse matrix of type %s", ((PetscObject)*newmat)->type_name);
8459566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(*newmat, &lA));
8469566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)lA, MATNEST, &isnest));
8475e3038f0Sstefano_zampini     if (isnest) {
8489566063dSJacob Faibussowitsch       PetscCall(MatNestGetSubMats(lA, &i, &j, &rnest));
8495e3038f0Sstefano_zampini       lreuse = (PetscBool)(i == nr && j == nc);
8505e3038f0Sstefano_zampini       if (!lreuse) rnest = NULL;
8515e3038f0Sstefano_zampini     }
8525e3038f0Sstefano_zampini   }
8539566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
8549566063dSJacob Faibussowitsch   PetscCall(PetscCalloc2(nr, &lr, nc, &lc));
8559566063dSJacob Faibussowitsch   PetscCall(PetscCalloc6(nr, &isrow, nc, &iscol, nr, &islrow, nc, &islcol, nr * nc, &snest, nr * nc, &istrans));
8569566063dSJacob Faibussowitsch   PetscCall(MatNestGetISs(A, isrow, iscol));
8575e3038f0Sstefano_zampini   for (i = 0; i < nr; i++) {
8585e3038f0Sstefano_zampini     for (j = 0; j < nc; j++) {
8594f58015eSStefano Zampini       PetscBool ismatis, sallow;
8609e7b2b25Sstefano_zampini       PetscInt  l1, l2, lb1, lb2, ij = i * nc + j;
8615e3038f0Sstefano_zampini 
8625e3038f0Sstefano_zampini       /* Null matrix pointers are allowed in MATNEST */
8635e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
8645e3038f0Sstefano_zampini 
8655e3038f0Sstefano_zampini       /* Nested matrices should be of type MATIS */
866013e2dc7SBarry Smith       PetscCall(PetscObjectTypeCompare((PetscObject)nest[i][j], MATTRANSPOSEVIRTUAL, &istrans[ij]));
8679e7b2b25Sstefano_zampini       if (istrans[ij]) {
8689e7b2b25Sstefano_zampini         Mat T, lT;
8699566063dSJacob Faibussowitsch         PetscCall(MatTransposeGetMat(nest[i][j], &T));
8709566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)T, MATIS, &ismatis));
87128b400f6SJacob 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);
8724f58015eSStefano Zampini         PetscCall(MatISGetAllowRepeated(T, &sallow));
8739566063dSJacob Faibussowitsch         PetscCall(MatISGetLocalMat(T, &lT));
8749566063dSJacob Faibussowitsch         PetscCall(MatCreateTranspose(lT, &snest[ij]));
8759e7b2b25Sstefano_zampini       } else {
8769566063dSJacob Faibussowitsch         PetscCall(PetscObjectTypeCompare((PetscObject)nest[i][j], MATIS, &ismatis));
87728b400f6SJacob 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);
8784f58015eSStefano Zampini         PetscCall(MatISGetAllowRepeated(nest[i][j], &sallow));
8799566063dSJacob Faibussowitsch         PetscCall(MatISGetLocalMat(nest[i][j], &snest[ij]));
8809e7b2b25Sstefano_zampini       }
8814f58015eSStefano Zampini       if (allow_repeated == PETSC_BOOL3_UNKNOWN) allow_repeated = PetscBoolToBool3(sallow);
8824f58015eSStefano Zampini       PetscCheck(sallow == PetscBool3ToBool(allow_repeated), comm, PETSC_ERR_SUP, "Cannot mix repeated and non repeated maps");
8835e3038f0Sstefano_zampini 
8845e3038f0Sstefano_zampini       /* Check compatibility of local sizes */
8859566063dSJacob Faibussowitsch       PetscCall(MatGetSize(snest[ij], &l1, &l2));
8869566063dSJacob Faibussowitsch       PetscCall(MatGetBlockSizes(snest[ij], &lb1, &lb2));
8875e3038f0Sstefano_zampini       if (!l1 || !l2) continue;
888aed4548fSBarry 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);
889aed4548fSBarry 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);
8905e3038f0Sstefano_zampini       lr[i] = l1;
8915e3038f0Sstefano_zampini       lc[j] = l2;
8925e3038f0Sstefano_zampini 
893da81f932SPierre Jolivet       /* check compatibility for local matrix reusage */
8945e3038f0Sstefano_zampini       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
8955e3038f0Sstefano_zampini     }
8965e3038f0Sstefano_zampini   }
8975e3038f0Sstefano_zampini 
89876bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
8995e3038f0Sstefano_zampini     /* Check compatibility of l2g maps for rows */
9005e3038f0Sstefano_zampini     for (i = 0; i < nr; i++) {
9015e3038f0Sstefano_zampini       rl2g = NULL;
9025e3038f0Sstefano_zampini       for (j = 0; j < nc; j++) {
9035e3038f0Sstefano_zampini         PetscInt n1, n2;
9045e3038f0Sstefano_zampini 
9055e3038f0Sstefano_zampini         if (!nest[i][j]) continue;
9069e7b2b25Sstefano_zampini         if (istrans[i * nc + j]) {
9079e7b2b25Sstefano_zampini           Mat T;
9089e7b2b25Sstefano_zampini 
9099566063dSJacob Faibussowitsch           PetscCall(MatTransposeGetMat(nest[i][j], &T));
9109566063dSJacob Faibussowitsch           PetscCall(MatISGetLocalToGlobalMapping(T, NULL, &cl2g));
9119e7b2b25Sstefano_zampini         } else {
9129566063dSJacob Faibussowitsch           PetscCall(MatISGetLocalToGlobalMapping(nest[i][j], &cl2g, NULL));
9139e7b2b25Sstefano_zampini         }
9149566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingGetSize(cl2g, &n1));
9155e3038f0Sstefano_zampini         if (!n1) continue;
9165e3038f0Sstefano_zampini         if (!rl2g) {
9175e3038f0Sstefano_zampini           rl2g = cl2g;
9185e3038f0Sstefano_zampini         } else {
9195e3038f0Sstefano_zampini           const PetscInt *idxs1, *idxs2;
9205e3038f0Sstefano_zampini           PetscBool       same;
9215e3038f0Sstefano_zampini 
9229566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingGetSize(rl2g, &n2));
92308401ef6SPierre 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);
9249566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingGetIndices(cl2g, &idxs1));
9259566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingGetIndices(rl2g, &idxs2));
9269566063dSJacob Faibussowitsch           PetscCall(PetscArraycmp(idxs1, idxs2, n1, &same));
9279566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingRestoreIndices(cl2g, &idxs1));
9289566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingRestoreIndices(rl2g, &idxs2));
92928b400f6SJacob 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);
9305e3038f0Sstefano_zampini         }
9315e3038f0Sstefano_zampini       }
9325e3038f0Sstefano_zampini     }
9335e3038f0Sstefano_zampini     /* Check compatibility of l2g maps for columns */
9345e3038f0Sstefano_zampini     for (i = 0; i < nc; i++) {
9355e3038f0Sstefano_zampini       rl2g = NULL;
9365e3038f0Sstefano_zampini       for (j = 0; j < nr; j++) {
9375e3038f0Sstefano_zampini         PetscInt n1, n2;
9385e3038f0Sstefano_zampini 
9395e3038f0Sstefano_zampini         if (!nest[j][i]) continue;
9409e7b2b25Sstefano_zampini         if (istrans[j * nc + i]) {
9419e7b2b25Sstefano_zampini           Mat T;
9429e7b2b25Sstefano_zampini 
9439566063dSJacob Faibussowitsch           PetscCall(MatTransposeGetMat(nest[j][i], &T));
9449566063dSJacob Faibussowitsch           PetscCall(MatISGetLocalToGlobalMapping(T, &cl2g, NULL));
9459e7b2b25Sstefano_zampini         } else {
9469566063dSJacob Faibussowitsch           PetscCall(MatISGetLocalToGlobalMapping(nest[j][i], NULL, &cl2g));
9479e7b2b25Sstefano_zampini         }
9489566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingGetSize(cl2g, &n1));
9495e3038f0Sstefano_zampini         if (!n1) continue;
9505e3038f0Sstefano_zampini         if (!rl2g) {
9515e3038f0Sstefano_zampini           rl2g = cl2g;
9525e3038f0Sstefano_zampini         } else {
9535e3038f0Sstefano_zampini           const PetscInt *idxs1, *idxs2;
9545e3038f0Sstefano_zampini           PetscBool       same;
9555e3038f0Sstefano_zampini 
9569566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingGetSize(rl2g, &n2));
95708401ef6SPierre 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);
9589566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingGetIndices(cl2g, &idxs1));
9599566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingGetIndices(rl2g, &idxs2));
9609566063dSJacob Faibussowitsch           PetscCall(PetscArraycmp(idxs1, idxs2, n1, &same));
9619566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingRestoreIndices(cl2g, &idxs1));
9629566063dSJacob Faibussowitsch           PetscCall(ISLocalToGlobalMappingRestoreIndices(rl2g, &idxs2));
96328b400f6SJacob 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);
9645e3038f0Sstefano_zampini         }
9655e3038f0Sstefano_zampini       }
9665e3038f0Sstefano_zampini     }
96776bd3646SJed Brown   }
9685e3038f0Sstefano_zampini 
9695e3038f0Sstefano_zampini   B = NULL;
9705e3038f0Sstefano_zampini   if (reuse != MAT_REUSE_MATRIX) {
9715b003df0Sstefano_zampini     PetscInt stl;
9725b003df0Sstefano_zampini 
9735e3038f0Sstefano_zampini     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
9745e3038f0Sstefano_zampini     for (i = 0, stl = 0; i < nr; i++) stl += lr[i];
9759566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(stl, &l2gidxs));
9765b003df0Sstefano_zampini     for (i = 0, stl = 0; i < nr; i++) {
9775e3038f0Sstefano_zampini       Mat             usedmat;
9785e3038f0Sstefano_zampini       Mat_IS         *matis;
9795e3038f0Sstefano_zampini       const PetscInt *idxs;
9805e3038f0Sstefano_zampini 
9815e3038f0Sstefano_zampini       /* local IS for local NEST */
9829566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF, lr[i], stl, 1, &islrow[i]));
9835e3038f0Sstefano_zampini 
9845e3038f0Sstefano_zampini       /* l2gmap */
9855e3038f0Sstefano_zampini       j       = 0;
9865e3038f0Sstefano_zampini       usedmat = nest[i][j];
9879e7b2b25Sstefano_zampini       while (!usedmat && j < nc - 1) usedmat = nest[i][++j];
98828b400f6SJacob Faibussowitsch       PetscCheck(usedmat, comm, PETSC_ERR_SUP, "Cannot find valid row mat");
9899e7b2b25Sstefano_zampini 
9909e7b2b25Sstefano_zampini       if (istrans[i * nc + j]) {
9919e7b2b25Sstefano_zampini         Mat T;
9929566063dSJacob Faibussowitsch         PetscCall(MatTransposeGetMat(usedmat, &T));
9939e7b2b25Sstefano_zampini         usedmat = T;
9949e7b2b25Sstefano_zampini       }
995f4f49eeaSPierre Jolivet       matis = (Mat_IS *)usedmat->data;
9969566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(isrow[i], &idxs));
9979e7b2b25Sstefano_zampini       if (istrans[i * nc + j]) {
9989566063dSJacob Faibussowitsch         PetscCall(PetscSFBcastBegin(matis->csf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE));
9999566063dSJacob Faibussowitsch         PetscCall(PetscSFBcastEnd(matis->csf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE));
10009e7b2b25Sstefano_zampini       } else {
10019566063dSJacob Faibussowitsch         PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE));
10029566063dSJacob Faibussowitsch         PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE));
10039e7b2b25Sstefano_zampini       }
10049566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(isrow[i], &idxs));
10055e3038f0Sstefano_zampini       stl += lr[i];
10065e3038f0Sstefano_zampini     }
10079566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreate(comm, 1, stl, l2gidxs, PETSC_OWN_POINTER, &rl2g));
10085e3038f0Sstefano_zampini 
10095e3038f0Sstefano_zampini     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
10105e3038f0Sstefano_zampini     for (i = 0, stl = 0; i < nc; i++) stl += lc[i];
10119566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(stl, &l2gidxs));
10125b003df0Sstefano_zampini     for (i = 0, stl = 0; i < nc; i++) {
10135e3038f0Sstefano_zampini       Mat             usedmat;
10145e3038f0Sstefano_zampini       Mat_IS         *matis;
10155e3038f0Sstefano_zampini       const PetscInt *idxs;
10165e3038f0Sstefano_zampini 
10175e3038f0Sstefano_zampini       /* local IS for local NEST */
10189566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(PETSC_COMM_SELF, lc[i], stl, 1, &islcol[i]));
10195e3038f0Sstefano_zampini 
10205e3038f0Sstefano_zampini       /* l2gmap */
10215e3038f0Sstefano_zampini       j       = 0;
10225e3038f0Sstefano_zampini       usedmat = nest[j][i];
10239e7b2b25Sstefano_zampini       while (!usedmat && j < nr - 1) usedmat = nest[++j][i];
102428b400f6SJacob Faibussowitsch       PetscCheck(usedmat, comm, PETSC_ERR_SUP, "Cannot find valid column mat");
10259e7b2b25Sstefano_zampini       if (istrans[j * nc + i]) {
10269e7b2b25Sstefano_zampini         Mat T;
10279566063dSJacob Faibussowitsch         PetscCall(MatTransposeGetMat(usedmat, &T));
10289e7b2b25Sstefano_zampini         usedmat = T;
10299e7b2b25Sstefano_zampini       }
1030f4f49eeaSPierre Jolivet       matis = (Mat_IS *)usedmat->data;
10319566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(iscol[i], &idxs));
10329e7b2b25Sstefano_zampini       if (istrans[j * nc + i]) {
10339566063dSJacob Faibussowitsch         PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE));
10349566063dSJacob Faibussowitsch         PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE));
10359e7b2b25Sstefano_zampini       } else {
10369566063dSJacob Faibussowitsch         PetscCall(PetscSFBcastBegin(matis->csf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE));
10379566063dSJacob Faibussowitsch         PetscCall(PetscSFBcastEnd(matis->csf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE));
10389e7b2b25Sstefano_zampini       }
10399566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(iscol[i], &idxs));
10405e3038f0Sstefano_zampini       stl += lc[i];
10415e3038f0Sstefano_zampini     }
10429566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreate(comm, 1, stl, l2gidxs, PETSC_OWN_POINTER, &cl2g));
10435e3038f0Sstefano_zampini 
10445e3038f0Sstefano_zampini     /* Create MATIS */
10459566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm, &B));
10469566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
10479566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSizes(A, &rbs, &cbs));
10489566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizes(B, rbs, cbs));
10499566063dSJacob Faibussowitsch     PetscCall(MatSetType(B, MATIS));
10509566063dSJacob Faibussowitsch     PetscCall(MatISSetLocalMatType(B, MATNEST));
10514f58015eSStefano Zampini     PetscCall(MatISSetAllowRepeated(B, PetscBool3ToBool(allow_repeated)));
10528546b261SStefano Zampini     { /* hack : avoid setup of scatters */
1053f4f49eeaSPierre Jolivet       Mat_IS *matis     = (Mat_IS *)B->data;
10540d2733adSStefano Zampini       matis->islocalref = B;
10558546b261SStefano Zampini     }
10569566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(B, rl2g, cl2g));
10579566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
10589566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
10599566063dSJacob Faibussowitsch     PetscCall(MatCreateNest(PETSC_COMM_SELF, nr, islrow, nc, islcol, snest, &lA));
10609566063dSJacob Faibussowitsch     PetscCall(MatNestSetVecType(lA, VECNEST));
10619e7b2b25Sstefano_zampini     for (i = 0; i < nr * nc; i++) {
106248a46eb9SPierre Jolivet       if (istrans[i]) PetscCall(MatDestroy(&snest[i]));
10639e7b2b25Sstefano_zampini     }
10649566063dSJacob Faibussowitsch     PetscCall(MatISSetLocalMat(B, lA));
10659566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&lA));
10668546b261SStefano Zampini     { /* hack : setup of scatters done here */
1067f4f49eeaSPierre Jolivet       Mat_IS *matis = (Mat_IS *)B->data;
10688546b261SStefano Zampini 
10690d2733adSStefano Zampini       matis->islocalref = NULL;
10709566063dSJacob Faibussowitsch       PetscCall(MatISSetUpScatters_Private(B));
10718546b261SStefano Zampini     }
10729566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
10739566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
10745e3038f0Sstefano_zampini     if (reuse == MAT_INPLACE_MATRIX) {
10759566063dSJacob Faibussowitsch       PetscCall(MatHeaderReplace(A, &B));
10765e3038f0Sstefano_zampini     } else {
10775e3038f0Sstefano_zampini       *newmat = B;
10785e3038f0Sstefano_zampini     }
10795e3038f0Sstefano_zampini   } else {
10805e3038f0Sstefano_zampini     if (lreuse) {
10819566063dSJacob Faibussowitsch       PetscCall(MatISGetLocalMat(*newmat, &lA));
10825e3038f0Sstefano_zampini       for (i = 0; i < nr; i++) {
10835e3038f0Sstefano_zampini         for (j = 0; j < nc; j++) {
10845e3038f0Sstefano_zampini           if (snest[i * nc + j]) {
10859566063dSJacob Faibussowitsch             PetscCall(MatNestSetSubMat(lA, i, j, snest[i * nc + j]));
108648a46eb9SPierre Jolivet             if (istrans[i * nc + j]) PetscCall(MatDestroy(&snest[i * nc + j]));
10875e3038f0Sstefano_zampini           }
10885e3038f0Sstefano_zampini         }
10895e3038f0Sstefano_zampini       }
10905e3038f0Sstefano_zampini     } else {
10915b003df0Sstefano_zampini       PetscInt stl;
10925b003df0Sstefano_zampini       for (i = 0, stl = 0; i < nr; i++) {
10939566063dSJacob Faibussowitsch         PetscCall(ISCreateStride(PETSC_COMM_SELF, lr[i], stl, 1, &islrow[i]));
10945b003df0Sstefano_zampini         stl += lr[i];
10955e3038f0Sstefano_zampini       }
10965b003df0Sstefano_zampini       for (i = 0, stl = 0; i < nc; i++) {
10979566063dSJacob Faibussowitsch         PetscCall(ISCreateStride(PETSC_COMM_SELF, lc[i], stl, 1, &islcol[i]));
10985b003df0Sstefano_zampini         stl += lc[i];
10995e3038f0Sstefano_zampini       }
11009566063dSJacob Faibussowitsch       PetscCall(MatCreateNest(PETSC_COMM_SELF, nr, islrow, nc, islcol, snest, &lA));
1101ab4d48faSStefano Zampini       for (i = 0; i < nr * nc; i++) {
110248a46eb9SPierre Jolivet         if (istrans[i]) PetscCall(MatDestroy(&snest[i]));
1103ab4d48faSStefano Zampini       }
11049566063dSJacob Faibussowitsch       PetscCall(MatISSetLocalMat(*newmat, lA));
11059566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&lA));
11065e3038f0Sstefano_zampini     }
11079566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(*newmat, MAT_FINAL_ASSEMBLY));
11089566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(*newmat, MAT_FINAL_ASSEMBLY));
11095e3038f0Sstefano_zampini   }
11105e3038f0Sstefano_zampini 
11115b003df0Sstefano_zampini   /* Create local matrix in MATNEST format */
11125b003df0Sstefano_zampini   convert = PETSC_FALSE;
11134f58015eSStefano Zampini   PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)A)->prefix, "-mat_is_convert_local_nest", &convert, NULL));
11145b003df0Sstefano_zampini   if (convert) {
11155b003df0Sstefano_zampini     Mat              M;
11165b003df0Sstefano_zampini     MatISLocalFields lf;
11175b003df0Sstefano_zampini 
11189566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(*newmat, &lA));
11199566063dSJacob Faibussowitsch     PetscCall(MatConvert(lA, MATAIJ, MAT_INITIAL_MATRIX, &M));
11209566063dSJacob Faibussowitsch     PetscCall(MatISSetLocalMat(*newmat, M));
11219566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&M));
11225b003df0Sstefano_zampini 
11235b003df0Sstefano_zampini     /* attach local fields to the matrix */
11249566063dSJacob Faibussowitsch     PetscCall(PetscNew(&lf));
11259566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nr, &lf->rf, nc, &lf->cf));
11265b003df0Sstefano_zampini     for (i = 0; i < nr; i++) {
11275b003df0Sstefano_zampini       PetscInt n, st;
11285b003df0Sstefano_zampini 
11299566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(islrow[i], &n));
11309566063dSJacob Faibussowitsch       PetscCall(ISStrideGetInfo(islrow[i], &st, NULL));
11319566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(comm, n, st, 1, &lf->rf[i]));
11325b003df0Sstefano_zampini     }
11335b003df0Sstefano_zampini     for (i = 0; i < nc; i++) {
11345b003df0Sstefano_zampini       PetscInt n, st;
11355b003df0Sstefano_zampini 
11369566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(islcol[i], &n));
11379566063dSJacob Faibussowitsch       PetscCall(ISStrideGetInfo(islcol[i], &st, NULL));
11389566063dSJacob Faibussowitsch       PetscCall(ISCreateStride(comm, n, st, 1, &lf->cf[i]));
11395b003df0Sstefano_zampini     }
11405b003df0Sstefano_zampini     lf->nr = nr;
11415b003df0Sstefano_zampini     lf->nc = nc;
114203e76207SPierre Jolivet     PetscCall(PetscObjectContainerCompose((PetscObject)*newmat, "_convert_nest_lfields", lf, MatISContainerDestroyFields_Private));
11435b003df0Sstefano_zampini   }
11445b003df0Sstefano_zampini 
11455e3038f0Sstefano_zampini   /* Free workspace */
114648a46eb9SPierre Jolivet   for (i = 0; i < nr; i++) PetscCall(ISDestroy(&islrow[i]));
114748a46eb9SPierre Jolivet   for (i = 0; i < nc; i++) PetscCall(ISDestroy(&islcol[i]));
11489566063dSJacob Faibussowitsch   PetscCall(PetscFree6(isrow, iscol, islrow, islcol, snest, istrans));
11499566063dSJacob Faibussowitsch   PetscCall(PetscFree2(lr, lc));
11503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11515e3038f0Sstefano_zampini }
11525e3038f0Sstefano_zampini 
MatDiagonalScale_IS(Mat A,Vec l,Vec r)1153d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r)
1154d71ae5a4SJacob Faibussowitsch {
1155ad219c80Sstefano_zampini   Mat_IS            *matis = (Mat_IS *)A->data;
1156ad219c80Sstefano_zampini   Vec                ll, rr;
1157ad219c80Sstefano_zampini   const PetscScalar *Y, *X;
1158ad219c80Sstefano_zampini   PetscScalar       *x, *y;
1159ad219c80Sstefano_zampini 
1160ad219c80Sstefano_zampini   PetscFunctionBegin;
1161ad219c80Sstefano_zampini   if (l) {
1162ad219c80Sstefano_zampini     ll = matis->y;
11639566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(l, &Y));
11649566063dSJacob Faibussowitsch     PetscCall(VecGetArray(ll, &y));
11659566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(matis->sf, MPIU_SCALAR, Y, y, MPI_REPLACE));
1166ad219c80Sstefano_zampini   } else {
1167ad219c80Sstefano_zampini     ll = NULL;
1168ad219c80Sstefano_zampini   }
1169ad219c80Sstefano_zampini   if (r) {
1170ad219c80Sstefano_zampini     rr = matis->x;
11719566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(r, &X));
11729566063dSJacob Faibussowitsch     PetscCall(VecGetArray(rr, &x));
11739566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(matis->csf, MPIU_SCALAR, X, x, MPI_REPLACE));
1174ad219c80Sstefano_zampini   } else {
1175ad219c80Sstefano_zampini     rr = NULL;
1176ad219c80Sstefano_zampini   }
1177ad219c80Sstefano_zampini   if (ll) {
11789566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(matis->sf, MPIU_SCALAR, Y, y, MPI_REPLACE));
11799566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(l, &Y));
11809566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(ll, &y));
1181ad219c80Sstefano_zampini   }
1182ad219c80Sstefano_zampini   if (rr) {
11839566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(matis->csf, MPIU_SCALAR, X, x, MPI_REPLACE));
11849566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(r, &X));
11859566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(rr, &x));
1186ad219c80Sstefano_zampini   }
11879566063dSJacob Faibussowitsch   PetscCall(MatDiagonalScale(matis->A, ll, rr));
11883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1189ad219c80Sstefano_zampini }
1190ad219c80Sstefano_zampini 
MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo * ginfo)1191d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetInfo_IS(Mat A, MatInfoType flag, MatInfo *ginfo)
1192d71ae5a4SJacob Faibussowitsch {
11937fa8f2d3SStefano Zampini   Mat_IS        *matis = (Mat_IS *)A->data;
11947fa8f2d3SStefano Zampini   MatInfo        info;
11953966268fSBarry Smith   PetscLogDouble isend[6], irecv[6];
11967fa8f2d3SStefano Zampini   PetscInt       bs;
11977fa8f2d3SStefano Zampini 
11987fa8f2d3SStefano Zampini   PetscFunctionBegin;
11999566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(A, &bs));
1200a2ccb5f9Sstefano_zampini   if (matis->A->ops->getinfo) {
12019566063dSJacob Faibussowitsch     PetscCall(MatGetInfo(matis->A, MAT_LOCAL, &info));
12027fa8f2d3SStefano Zampini     isend[0] = info.nz_used;
12037fa8f2d3SStefano Zampini     isend[1] = info.nz_allocated;
12047fa8f2d3SStefano Zampini     isend[2] = info.nz_unneeded;
12057fa8f2d3SStefano Zampini     isend[3] = info.memory;
12067fa8f2d3SStefano Zampini     isend[4] = info.mallocs;
1207a2ccb5f9Sstefano_zampini   } else {
1208a2ccb5f9Sstefano_zampini     isend[0] = 0.;
1209a2ccb5f9Sstefano_zampini     isend[1] = 0.;
1210a2ccb5f9Sstefano_zampini     isend[2] = 0.;
1211a2ccb5f9Sstefano_zampini     isend[3] = 0.;
1212a2ccb5f9Sstefano_zampini     isend[4] = 0.;
1213a2ccb5f9Sstefano_zampini   }
1214314ce898Sstefano_zampini   isend[5] = matis->A->num_ass;
12157fa8f2d3SStefano Zampini   if (flag == MAT_LOCAL) {
12167fa8f2d3SStefano Zampini     ginfo->nz_used      = isend[0];
12177fa8f2d3SStefano Zampini     ginfo->nz_allocated = isend[1];
12187fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = isend[2];
12197fa8f2d3SStefano Zampini     ginfo->memory       = isend[3];
12207fa8f2d3SStefano Zampini     ginfo->mallocs      = isend[4];
1221314ce898Sstefano_zampini     ginfo->assemblies   = isend[5];
12227fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_MAX) {
1223462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(isend, irecv, 6, MPIU_PETSCLOGDOUBLE, MPI_MAX, PetscObjectComm((PetscObject)A)));
12247fa8f2d3SStefano Zampini 
12257fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
12267fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
12277fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
12287fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
12297fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
1230314ce898Sstefano_zampini     ginfo->assemblies   = irecv[5];
12317fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_SUM) {
1232462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(isend, irecv, 5, MPIU_PETSCLOGDOUBLE, MPI_SUM, PetscObjectComm((PetscObject)A)));
12337fa8f2d3SStefano Zampini 
12347fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
12357fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
12367fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
12377fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
12387fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
12397fa8f2d3SStefano Zampini     ginfo->assemblies   = A->num_ass;
12407fa8f2d3SStefano Zampini   }
12417fa8f2d3SStefano Zampini   ginfo->block_size        = bs;
12427fa8f2d3SStefano Zampini   ginfo->fill_ratio_given  = 0;
12437fa8f2d3SStefano Zampini   ginfo->fill_ratio_needed = 0;
12447fa8f2d3SStefano Zampini   ginfo->factor_mallocs    = 0;
12453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12465e3038f0Sstefano_zampini }
12475e3038f0Sstefano_zampini 
MatTranspose_IS(Mat A,MatReuse reuse,Mat * B)1248d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatTranspose_IS(Mat A, MatReuse reuse, Mat *B)
1249d71ae5a4SJacob Faibussowitsch {
1250d7f69cd0SStefano Zampini   Mat C, lC, lA;
1251d7f69cd0SStefano Zampini 
1252d7f69cd0SStefano Zampini   PetscFunctionBegin;
12537fb60732SBarry Smith   if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *B));
1254cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) {
1255cf37664fSBarry Smith     ISLocalToGlobalMapping rl2g, cl2g;
12564f58015eSStefano Zampini     PetscBool              allow_repeated;
12574f58015eSStefano Zampini 
12589566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
12599566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(C, A->cmap->n, A->rmap->n, A->cmap->N, A->rmap->N));
126058b7e2c1SStefano Zampini     PetscCall(MatSetBlockSizes(C, A->cmap->bs, A->rmap->bs));
12619566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATIS));
12624f58015eSStefano Zampini     PetscCall(MatISGetAllowRepeated(A, &allow_repeated));
12634f58015eSStefano Zampini     PetscCall(MatISSetAllowRepeated(C, allow_repeated));
12649566063dSJacob Faibussowitsch     PetscCall(MatGetLocalToGlobalMapping(A, &rl2g, &cl2g));
12659566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(C, cl2g, rl2g));
1266e432b41dSStefano Zampini   } else C = *B;
1267d7f69cd0SStefano Zampini 
1268d7f69cd0SStefano Zampini   /* perform local transposition */
12699566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(A, &lA));
12709566063dSJacob Faibussowitsch   PetscCall(MatTranspose(lA, MAT_INITIAL_MATRIX, &lC));
12719566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(lC, lA->cmap->mapping, lA->rmap->mapping));
12729566063dSJacob Faibussowitsch   PetscCall(MatISSetLocalMat(C, lC));
12739566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&lC));
1274d7f69cd0SStefano Zampini 
1275cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) {
1276d7f69cd0SStefano Zampini     *B = C;
1277d7f69cd0SStefano Zampini   } else {
12789566063dSJacob Faibussowitsch     PetscCall(MatHeaderMerge(A, &C));
1279d7f69cd0SStefano Zampini   }
12809566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY));
12819566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY));
12823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1283d7f69cd0SStefano Zampini }
1284d7f69cd0SStefano Zampini 
MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)1285d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDiagonalSet_IS(Mat A, Vec D, InsertMode insmode)
1286d71ae5a4SJacob Faibussowitsch {
12873fd1c9e7SStefano Zampini   Mat_IS *is = (Mat_IS *)A->data;
12883fd1c9e7SStefano Zampini 
12893fd1c9e7SStefano Zampini   PetscFunctionBegin;
12904f58015eSStefano Zampini   PetscCheck(!is->allow_repeated || insmode == ADD_VALUES, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "INSERT_VALUES with repeated entries not supported");
12914b89b9cdSStefano Zampini   if (D) { /* MatShift_IS pass D = NULL */
12929566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(is->rctx, D, is->y, INSERT_VALUES, SCATTER_FORWARD));
12939566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(is->rctx, D, is->y, INSERT_VALUES, SCATTER_FORWARD));
12943fd1c9e7SStefano Zampini   }
12959566063dSJacob Faibussowitsch   PetscCall(VecPointwiseDivide(is->y, is->y, is->counter));
12969566063dSJacob Faibussowitsch   PetscCall(MatDiagonalSet(is->A, is->y, insmode));
12973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12983fd1c9e7SStefano Zampini }
12993fd1c9e7SStefano Zampini 
MatShift_IS(Mat A,PetscScalar a)1300d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatShift_IS(Mat A, PetscScalar a)
1301d71ae5a4SJacob Faibussowitsch {
13024b89b9cdSStefano Zampini   Mat_IS *is = (Mat_IS *)A->data;
13033fd1c9e7SStefano Zampini 
13043fd1c9e7SStefano Zampini   PetscFunctionBegin;
13059566063dSJacob Faibussowitsch   PetscCall(VecSet(is->y, a));
13069566063dSJacob Faibussowitsch   PetscCall(MatDiagonalSet_IS(A, NULL, ADD_VALUES));
13073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13083fd1c9e7SStefano Zampini }
13093fd1c9e7SStefano Zampini 
MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt * rows,PetscInt n,const PetscInt * cols,const PetscScalar * values,InsertMode addv)1310d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv)
1311d71ae5a4SJacob Faibussowitsch {
1312076fee34SStefano Zampini   PetscInt buf[2 * MATIS_MAX_ENTRIES_INSERTION], *rows_l = NULL, *cols_l = NULL;
1313f26d0771SStefano Zampini 
1314f26d0771SStefano Zampini   PetscFunctionBegin;
1315076fee34SStefano Zampini   IndexSpaceGet(buf, m, n, rows_l, cols_l);
13169566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingApply(A->rmap->mapping, m, rows, rows_l));
13179566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingApply(A->cmap->mapping, n, cols, cols_l));
13189566063dSJacob Faibussowitsch   PetscCall(MatSetValuesLocal_IS(A, m, rows_l, n, cols_l, values, addv));
1319076fee34SStefano Zampini   IndexSpaceRestore(buf, m, n, rows_l, cols_l);
13203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1321f26d0771SStefano Zampini }
1322f26d0771SStefano Zampini 
MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt * rows,PetscInt n,const PetscInt * cols,const PetscScalar * values,InsertMode addv)1323d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv)
1324d71ae5a4SJacob Faibussowitsch {
1325076fee34SStefano Zampini   PetscInt buf[2 * MATIS_MAX_ENTRIES_INSERTION], *rows_l = NULL, *cols_l = NULL, rbs, cbs;
1326f26d0771SStefano Zampini 
1327f26d0771SStefano Zampini   PetscFunctionBegin;
1328076fee34SStefano Zampini   /* We cannot guarantee the local matrix will have the same block size of the original matrix */
1329076fee34SStefano Zampini   PetscCall(ISLocalToGlobalMappingGetBlockSize(A->rmap->mapping, &rbs));
1330076fee34SStefano Zampini   PetscCall(ISLocalToGlobalMappingGetBlockSize(A->cmap->mapping, &cbs));
1331076fee34SStefano Zampini   IndexSpaceGet(buf, m * rbs, n * cbs, rows_l, cols_l);
1332076fee34SStefano Zampini   BlockIndicesExpand(m, rows, rbs, rows_l);
1333076fee34SStefano Zampini   BlockIndicesExpand(n, cols, cbs, cols_l);
1334076fee34SStefano Zampini   PetscCall(ISLocalToGlobalMappingApply(A->rmap->mapping, m * rbs, rows_l, rows_l));
1335076fee34SStefano Zampini   PetscCall(ISLocalToGlobalMappingApply(A->cmap->mapping, n * cbs, cols_l, cols_l));
1336076fee34SStefano Zampini   PetscCall(MatSetValuesLocal_IS(A, m * rbs, rows_l, n * cbs, cols_l, values, addv));
1337076fee34SStefano Zampini   IndexSpaceRestore(buf, m * rbs, n * cbs, rows_l, cols_l);
13383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1339f26d0771SStefano Zampini }
1340f26d0771SStefano Zampini 
MatZeroRowsLocal_SubMat_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)13410d2733adSStefano Zampini static PetscErrorCode MatZeroRowsLocal_SubMat_IS(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
13420d2733adSStefano Zampini {
13430d2733adSStefano Zampini   PetscInt *rows_l;
13440d2733adSStefano Zampini   Mat_IS   *is = (Mat_IS *)A->data;
13450d2733adSStefano Zampini 
13460d2733adSStefano Zampini   PetscFunctionBegin;
13470d2733adSStefano Zampini   PetscCall(PetscMalloc1(n, &rows_l));
13480d2733adSStefano Zampini   PetscCall(ISLocalToGlobalMappingApply(A->rmap->mapping, n, rows, rows_l));
13490d2733adSStefano Zampini   PetscCall(MatZeroRowsLocal(is->islocalref, n, rows_l, diag, x, b));
13500d2733adSStefano Zampini   PetscCall(PetscFree(rows_l));
13510d2733adSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
13520d2733adSStefano Zampini }
13530d2733adSStefano Zampini 
MatZeroRowsColumnsLocal_SubMat_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)13540d2733adSStefano Zampini static PetscErrorCode MatZeroRowsColumnsLocal_SubMat_IS(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
13550d2733adSStefano Zampini {
13560d2733adSStefano Zampini   PetscInt *rows_l;
13570d2733adSStefano Zampini   Mat_IS   *is = (Mat_IS *)A->data;
13580d2733adSStefano Zampini 
13590d2733adSStefano Zampini   PetscFunctionBegin;
13600d2733adSStefano Zampini   PetscCall(PetscMalloc1(n, &rows_l));
13610d2733adSStefano Zampini   PetscCall(ISLocalToGlobalMappingApply(A->rmap->mapping, n, rows, rows_l));
13620d2733adSStefano Zampini   PetscCall(MatZeroRowsColumnsLocal(is->islocalref, n, rows_l, diag, x, b));
13630d2733adSStefano Zampini   PetscCall(PetscFree(rows_l));
13640d2733adSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
13650d2733adSStefano Zampini }
13660d2733adSStefano Zampini 
MatCreateSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat * newmat)1367d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrix_IS(Mat mat, IS irow, IS icol, MatReuse scall, Mat *newmat)
1368d71ae5a4SJacob Faibussowitsch {
1369a8116848SStefano Zampini   Mat             locmat, newlocmat;
1370a8116848SStefano Zampini   Mat_IS         *newmatis;
1371a8116848SStefano Zampini   const PetscInt *idxs;
1372a8116848SStefano Zampini   PetscInt        i, m, n;
1373a8116848SStefano Zampini 
1374a8116848SStefano Zampini   PetscFunctionBegin;
1375a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
1376a8116848SStefano Zampini     PetscBool ismatis;
1377a8116848SStefano Zampini 
13789566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)*newmat, MATIS, &ismatis));
137928b400f6SJacob Faibussowitsch     PetscCheck(ismatis, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_ARG_WRONG, "Cannot reuse matrix! Not of MATIS type");
1380a8116848SStefano Zampini     newmatis = (Mat_IS *)(*newmat)->data;
138128b400f6SJacob Faibussowitsch     PetscCheck(newmatis->getsub_ris, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_ARG_WRONG, "Cannot reuse matrix! Misses local row IS");
138228b400f6SJacob Faibussowitsch     PetscCheck(newmatis->getsub_cis, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_ARG_WRONG, "Cannot reuse matrix! Misses local col IS");
1383a8116848SStefano Zampini   }
1384a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
138576bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
138676bd3646SJed Brown     Vec                rtest, ltest;
138776bd3646SJed Brown     const PetscScalar *array;
138876bd3646SJed Brown 
13899566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(mat, &ltest, &rtest));
13909566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(irow, &n));
13919566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(irow, &idxs));
139248a46eb9SPierre Jolivet     for (i = 0; i < n; i++) PetscCall(VecSetValue(rtest, idxs[i], 1.0, ADD_VALUES));
13939566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(rtest));
13949566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(rtest));
13959566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(rtest, &n));
13969566063dSJacob Faibussowitsch     PetscCall(VecGetOwnershipRange(rtest, &m, NULL));
13979566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(rtest, &array));
1398aed4548fSBarry 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]));
13999566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(rtest, &array));
14009566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(irow, &idxs));
14019566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(icol, &n));
14029566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(icol, &idxs));
140348a46eb9SPierre Jolivet     for (i = 0; i < n; i++) PetscCall(VecSetValue(ltest, idxs[i], 1.0, ADD_VALUES));
14049566063dSJacob Faibussowitsch     PetscCall(VecAssemblyBegin(ltest));
14059566063dSJacob Faibussowitsch     PetscCall(VecAssemblyEnd(ltest));
14069566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(ltest, &n));
14079566063dSJacob Faibussowitsch     PetscCall(VecGetOwnershipRange(ltest, &m, NULL));
14089566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(ltest, &array));
1409aed4548fSBarry 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]));
14109566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(ltest, &array));
14119566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(icol, &idxs));
14129566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&rtest));
14139566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&ltest));
141476bd3646SJed Brown   }
1415a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
1416a8116848SStefano Zampini     Mat_IS                *matis = (Mat_IS *)mat->data;
1417a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
1418a8116848SStefano Zampini     IS                     is;
1419a8116848SStefano Zampini     PetscInt              *lidxs, *lgidxs, *newgidxs;
1420306cf5c7SStefano Zampini     PetscInt               ll, newloc, irbs, icbs, arbs, acbs, rbs, cbs;
142194342113SStefano Zampini     PetscBool              cong;
1422a8116848SStefano Zampini     MPI_Comm               comm;
1423a8116848SStefano Zampini 
14249566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
14259566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSizes(mat, &arbs, &acbs));
14269566063dSJacob Faibussowitsch     PetscCall(ISGetBlockSize(irow, &irbs));
14279566063dSJacob Faibussowitsch     PetscCall(ISGetBlockSize(icol, &icbs));
1428306cf5c7SStefano Zampini     rbs = arbs == irbs ? irbs : 1;
1429306cf5c7SStefano Zampini     cbs = acbs == icbs ? icbs : 1;
14309566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(irow, &m));
14319566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(icol, &n));
14329566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm, newmat));
14339566063dSJacob Faibussowitsch     PetscCall(MatSetType(*newmat, MATIS));
14344f58015eSStefano Zampini     PetscCall(MatISSetAllowRepeated(*newmat, matis->allow_repeated));
14359566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(*newmat, m, n, PETSC_DECIDE, PETSC_DECIDE));
14369566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizes(*newmat, rbs, cbs));
1437a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
14389566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(irow, &idxs));
14399566063dSJacob Faibussowitsch     PetscCall(PetscLayoutMapLocal(mat->rmap, m, idxs, &ll, &lidxs, &lgidxs));
14409566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(irow, &idxs));
14419566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(matis->sf_rootdata, matis->sf->nroots));
1442a8116848SStefano Zampini     for (i = 0; i < ll; i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i] + 1;
14439566063dSJacob Faibussowitsch     PetscCall(PetscFree(lidxs));
14449566063dSJacob Faibussowitsch     PetscCall(PetscFree(lgidxs));
14459566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE));
14469566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE));
14479371c9d4SSatish Balay     for (i = 0, newloc = 0; i < matis->sf->nleaves; i++)
14489371c9d4SSatish Balay       if (matis->sf_leafdata[i]) newloc++;
14499566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newloc, &newgidxs));
14509566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newloc, &lidxs));
14513d996552SStefano Zampini     for (i = 0, newloc = 0; i < matis->sf->nleaves; i++)
1452a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
1453a8116848SStefano Zampini         lidxs[newloc]      = i;
1454a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i] - 1;
1455a8116848SStefano Zampini       }
14569566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, newloc, newgidxs, PETSC_OWN_POINTER, &is));
14579566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g));
14589566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingSetBlockSize(rl2g, rbs));
14599566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
1460a8116848SStefano Zampini     /* local is to extract local submatrix */
1461a8116848SStefano Zampini     newmatis = (Mat_IS *)(*newmat)->data;
14629566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, newloc, lidxs, PETSC_OWN_POINTER, &newmatis->getsub_ris));
14639566063dSJacob Faibussowitsch     PetscCall(MatHasCongruentLayouts(mat, &cong));
146494342113SStefano Zampini     if (cong && irow == icol && matis->csf == matis->sf) {
14659566063dSJacob Faibussowitsch       PetscCall(MatSetLocalToGlobalMapping(*newmat, rl2g, rl2g));
14669566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)newmatis->getsub_ris));
1467a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
1468a8116848SStefano Zampini     } else {
1469a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
1470a8116848SStefano Zampini 
1471a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
14729566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(icol, &idxs));
14739566063dSJacob Faibussowitsch       PetscCall(PetscLayoutMapLocal(mat->cmap, n, idxs, &ll, &lidxs, &lgidxs));
14749566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(icol, &idxs));
14759566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(matis->csf_rootdata, matis->csf->nroots));
1476a8116848SStefano Zampini       for (i = 0; i < ll; i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i] + 1;
14779566063dSJacob Faibussowitsch       PetscCall(PetscFree(lidxs));
14789566063dSJacob Faibussowitsch       PetscCall(PetscFree(lgidxs));
14799566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastBegin(matis->csf, MPIU_INT, matis->csf_rootdata, matis->csf_leafdata, MPI_REPLACE));
14809566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastEnd(matis->csf, MPIU_INT, matis->csf_rootdata, matis->csf_leafdata, MPI_REPLACE));
14819371c9d4SSatish Balay       for (i = 0, newloc = 0; i < matis->csf->nleaves; i++)
14829371c9d4SSatish Balay         if (matis->csf_leafdata[i]) newloc++;
14839566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(newloc, &newgidxs));
14849566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(newloc, &lidxs));
14853d996552SStefano Zampini       for (i = 0, newloc = 0; i < matis->csf->nleaves; i++)
1486a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
1487a8116848SStefano Zampini           lidxs[newloc]      = i;
1488a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i] - 1;
1489a8116848SStefano Zampini         }
14909566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(comm, newloc, newgidxs, PETSC_OWN_POINTER, &is));
14919566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g));
14929566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingSetBlockSize(cl2g, cbs));
14939566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&is));
1494a8116848SStefano Zampini       /* local is to extract local submatrix */
14959566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(comm, newloc, lidxs, PETSC_OWN_POINTER, &newmatis->getsub_cis));
14969566063dSJacob Faibussowitsch       PetscCall(MatSetLocalToGlobalMapping(*newmat, rl2g, cl2g));
14979566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
1498a8116848SStefano Zampini     }
14999566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
1500a8116848SStefano Zampini   } else {
15019566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(*newmat, &newlocmat));
1502a8116848SStefano Zampini   }
15039566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(mat, &locmat));
1504a8116848SStefano Zampini   newmatis = (Mat_IS *)(*newmat)->data;
15059566063dSJacob Faibussowitsch   PetscCall(MatCreateSubMatrix(locmat, newmatis->getsub_ris, newmatis->getsub_cis, scall, &newlocmat));
1506a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
15079566063dSJacob Faibussowitsch     PetscCall(MatISSetLocalMat(*newmat, newlocmat));
15089566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&newlocmat));
1509a8116848SStefano Zampini   }
15109566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*newmat, MAT_FINAL_ASSEMBLY));
15119566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*newmat, MAT_FINAL_ASSEMBLY));
15123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1513a8116848SStefano Zampini }
1514a8116848SStefano Zampini 
MatCopy_IS(Mat A,Mat B,MatStructure str)1515d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCopy_IS(Mat A, Mat B, MatStructure str)
1516d71ae5a4SJacob Faibussowitsch {
15172b404112SStefano Zampini   Mat_IS   *a = (Mat_IS *)A->data, *b;
15182b404112SStefano Zampini   PetscBool ismatis;
15192b404112SStefano Zampini 
15202b404112SStefano Zampini   PetscFunctionBegin;
15219566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)B, MATIS, &ismatis));
152228b400f6SJacob Faibussowitsch   PetscCheck(ismatis, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Need to be implemented");
15232b404112SStefano Zampini   b = (Mat_IS *)B->data;
15249566063dSJacob Faibussowitsch   PetscCall(MatCopy(a->A, b->A, str));
15259566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateIncrease((PetscObject)B));
15263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15272b404112SStefano Zampini }
15282b404112SStefano Zampini 
MatISSetUpSF_IS(Mat B)1529d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISSetUpSF_IS(Mat B)
1530d71ae5a4SJacob Faibussowitsch {
1531f4f49eeaSPierre Jolivet   Mat_IS         *matis = (Mat_IS *)B->data;
153228f4e0baSStefano Zampini   const PetscInt *gidxs;
15334f2d7cafSStefano Zampini   PetscInt        nleaves;
153428f4e0baSStefano Zampini 
153528f4e0baSStefano Zampini   PetscFunctionBegin;
15363ba16761SJacob Faibussowitsch   if (matis->sf) PetscFunctionReturn(PETSC_SUCCESS);
15379566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)B), &matis->sf));
15389566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(matis->rmapping, &gidxs));
15399566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(matis->rmapping, &nleaves));
15409566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraphLayout(matis->sf, B->rmap, nleaves, NULL, PETSC_OWN_POINTER, gidxs));
15419566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->rmapping, &gidxs));
15429566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(matis->sf->nroots, &matis->sf_rootdata, matis->sf->nleaves, &matis->sf_leafdata));
1543e432b41dSStefano Zampini   if (matis->rmapping != matis->cmapping) { /* setup SF for columns */
15449566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetSize(matis->cmapping, &nleaves));
15459566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)B), &matis->csf));
15469566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetIndices(matis->cmapping, &gidxs));
15479566063dSJacob Faibussowitsch     PetscCall(PetscSFSetGraphLayout(matis->csf, B->cmap, nleaves, NULL, PETSC_OWN_POINTER, gidxs));
15489566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->cmapping, &gidxs));
15499566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(matis->csf->nroots, &matis->csf_rootdata, matis->csf->nleaves, &matis->csf_leafdata));
1550a8116848SStefano Zampini   } else {
1551a8116848SStefano Zampini     matis->csf          = matis->sf;
1552a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
1553a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
1554a8116848SStefano Zampini   }
15553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
155628f4e0baSStefano Zampini }
15572e1947a5SStefano Zampini 
1558eb82efa4SStefano Zampini /*@
15594f58015eSStefano Zampini   MatISGetAllowRepeated - Get the flag to allow repeated entries in the local to global map
15604f58015eSStefano Zampini 
15614f58015eSStefano Zampini   Not Collective
15624f58015eSStefano Zampini 
15634f58015eSStefano Zampini   Input Parameter:
15644f58015eSStefano Zampini . A - the matrix
15654f58015eSStefano Zampini 
15664f58015eSStefano Zampini   Output Parameter:
15674f58015eSStefano Zampini . flg - the boolean flag
15684f58015eSStefano Zampini 
15694f58015eSStefano Zampini   Level: intermediate
15704f58015eSStefano Zampini 
15714f58015eSStefano Zampini .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateIS()`, `MatSetLocalToGlobalMapping()`, `MatISSetAllowRepeated()`
15724f58015eSStefano Zampini @*/
MatISGetAllowRepeated(Mat A,PetscBool * flg)15734f58015eSStefano Zampini PetscErrorCode MatISGetAllowRepeated(Mat A, PetscBool *flg)
15744f58015eSStefano Zampini {
15754f58015eSStefano Zampini   PetscBool ismatis;
15764f58015eSStefano Zampini 
15774f58015eSStefano Zampini   PetscFunctionBegin;
15784f58015eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
15794f58015eSStefano Zampini   PetscAssertPointer(flg, 2);
15804f58015eSStefano Zampini   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATIS, &ismatis));
15814f58015eSStefano Zampini   PetscCheck(ismatis, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)A)->type_name);
15824f58015eSStefano Zampini   *flg = ((Mat_IS *)A->data)->allow_repeated;
15834f58015eSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
15844f58015eSStefano Zampini }
15854f58015eSStefano Zampini 
15864f58015eSStefano Zampini /*@
15874f58015eSStefano Zampini   MatISSetAllowRepeated - Set the flag to allow repeated entries in the local to global map
15884f58015eSStefano Zampini 
15894f58015eSStefano Zampini   Logically Collective
15904f58015eSStefano Zampini 
15914f58015eSStefano Zampini   Input Parameters:
15924f58015eSStefano Zampini + A   - the matrix
15934f58015eSStefano Zampini - flg - the boolean flag
15944f58015eSStefano Zampini 
15954f58015eSStefano Zampini   Level: intermediate
15964f58015eSStefano Zampini 
15974f58015eSStefano Zampini   Notes:
15984f58015eSStefano Zampini   The default value is `PETSC_FALSE`.
15994f58015eSStefano Zampini   When called AFTER calling `MatSetLocalToGlobalMapping()` it will recreate the local matrices
16004f58015eSStefano Zampini   if `flg` is different from the previously set value.
16014f58015eSStefano Zampini   Specifically, when `flg` is true it will just recreate the local matrices, while if
16024f58015eSStefano Zampini   `flg` is false will assemble the local matrices summing up repeated entries.
16034f58015eSStefano Zampini 
16044f58015eSStefano Zampini .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateIS()`, `MatSetLocalToGlobalMapping()`, `MatISGetAllowRepeated()`
16054f58015eSStefano Zampini @*/
MatISSetAllowRepeated(Mat A,PetscBool flg)16064f58015eSStefano Zampini PetscErrorCode MatISSetAllowRepeated(Mat A, PetscBool flg)
16074f58015eSStefano Zampini {
16084f58015eSStefano Zampini   PetscFunctionBegin;
16094f58015eSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
16104f58015eSStefano Zampini   PetscValidType(A, 1);
16114f58015eSStefano Zampini   PetscValidLogicalCollectiveBool(A, flg, 2);
16124f58015eSStefano Zampini   PetscTryMethod(A, "MatISSetAllowRepeated_C", (Mat, PetscBool), (A, flg));
16134f58015eSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
16144f58015eSStefano Zampini }
16154f58015eSStefano Zampini 
MatISSetAllowRepeated_IS(Mat A,PetscBool flg)16164f58015eSStefano Zampini static PetscErrorCode MatISSetAllowRepeated_IS(Mat A, PetscBool flg)
16174f58015eSStefano Zampini {
16184f58015eSStefano Zampini   Mat_IS                *matis = (Mat_IS *)A->data;
16194f58015eSStefano Zampini   Mat                    lA    = NULL;
16204f58015eSStefano Zampini   ISLocalToGlobalMapping lrmap, lcmap;
16214f58015eSStefano Zampini 
16224f58015eSStefano Zampini   PetscFunctionBegin;
16234f58015eSStefano Zampini   if (flg == matis->allow_repeated) PetscFunctionReturn(PETSC_SUCCESS);
16244f58015eSStefano Zampini   if (!matis->A) { /* matrix has not been preallocated yet */
16254f58015eSStefano Zampini     matis->allow_repeated = flg;
16264f58015eSStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
16274f58015eSStefano Zampini   }
16284f58015eSStefano Zampini   PetscCheck(!matis->islocalref, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not implemented for local references");
16294f58015eSStefano Zampini   if (matis->allow_repeated) { /* we will assemble the old local matrix if needed */
16304f58015eSStefano Zampini     lA = matis->A;
16314f58015eSStefano Zampini     PetscCall(PetscObjectReference((PetscObject)lA));
16324f58015eSStefano Zampini   }
16334f58015eSStefano Zampini   /* In case flg is True, we only recreate the local matrix */
16344f58015eSStefano Zampini   matis->allow_repeated = flg;
16354f58015eSStefano Zampini   PetscCall(MatSetLocalToGlobalMapping(A, A->rmap->mapping, A->cmap->mapping));
16364f58015eSStefano Zampini   if (lA) { /* assemble previous local matrix if needed */
16374f58015eSStefano Zampini     Mat nA = matis->A;
16384f58015eSStefano Zampini 
16394f58015eSStefano Zampini     PetscCall(MatGetLocalToGlobalMapping(nA, &lrmap, &lcmap));
16404f58015eSStefano Zampini     if (!lrmap && !lcmap) {
16414f58015eSStefano Zampini       PetscCall(MatISSetLocalMat(A, lA));
16424f58015eSStefano Zampini     } else {
16434f58015eSStefano Zampini       Mat            P = NULL, R = NULL;
16444f58015eSStefano Zampini       MatProductType ptype;
16454f58015eSStefano Zampini 
16464f58015eSStefano Zampini       if (lrmap == lcmap) {
16474f58015eSStefano Zampini         ptype = MATPRODUCT_PtAP;
16484f58015eSStefano Zampini         PetscCall(MatCreateFromISLocalToGlobalMapping(lcmap, nA, PETSC_TRUE, PETSC_FALSE, NULL, &P));
16494f58015eSStefano Zampini         PetscCall(MatProductCreate(lA, P, NULL, &nA));
16504f58015eSStefano Zampini       } else {
16514f58015eSStefano Zampini         if (lcmap) PetscCall(MatCreateFromISLocalToGlobalMapping(lcmap, nA, PETSC_TRUE, PETSC_FALSE, NULL, &P));
16524f58015eSStefano Zampini         if (lrmap) PetscCall(MatCreateFromISLocalToGlobalMapping(lrmap, nA, PETSC_FALSE, PETSC_TRUE, NULL, &R));
16534f58015eSStefano Zampini         if (R && P) {
16544f58015eSStefano Zampini           ptype = MATPRODUCT_ABC;
16554f58015eSStefano Zampini           PetscCall(MatProductCreate(R, lA, P, &nA));
16564f58015eSStefano Zampini         } else if (R) {
16574f58015eSStefano Zampini           ptype = MATPRODUCT_AB;
16584f58015eSStefano Zampini           PetscCall(MatProductCreate(R, lA, NULL, &nA));
16594f58015eSStefano Zampini         } else {
16604f58015eSStefano Zampini           ptype = MATPRODUCT_AB;
16614f58015eSStefano Zampini           PetscCall(MatProductCreate(lA, P, NULL, &nA));
16624f58015eSStefano Zampini         }
16634f58015eSStefano Zampini       }
16644f58015eSStefano Zampini       PetscCall(MatProductSetType(nA, ptype));
16654f58015eSStefano Zampini       PetscCall(MatProductSetFromOptions(nA));
16664f58015eSStefano Zampini       PetscCall(MatProductSymbolic(nA));
16674f58015eSStefano Zampini       PetscCall(MatProductNumeric(nA));
16684f58015eSStefano Zampini       PetscCall(MatProductClear(nA));
16694f58015eSStefano Zampini       PetscCall(MatConvert(nA, matis->lmattype, MAT_INPLACE_MATRIX, &nA));
16704f58015eSStefano Zampini       PetscCall(MatISSetLocalMat(A, nA));
16714f58015eSStefano Zampini       PetscCall(MatDestroy(&nA));
16724f58015eSStefano Zampini       PetscCall(MatDestroy(&P));
16734f58015eSStefano Zampini       PetscCall(MatDestroy(&R));
16744f58015eSStefano Zampini     }
16754f58015eSStefano Zampini   }
16764f58015eSStefano Zampini   PetscCall(MatDestroy(&lA));
16774f58015eSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
16784f58015eSStefano Zampini }
16794f58015eSStefano Zampini 
16804f58015eSStefano Zampini /*@
16812ef1f0ffSBarry Smith   MatISStoreL2L - Store local-to-local operators during the Galerkin process of computing `MatPtAP()`
168275d48cdbSStefano Zampini 
16834f58015eSStefano Zampini   Logically Collective
168475d48cdbSStefano Zampini 
168575d48cdbSStefano Zampini   Input Parameters:
168675d48cdbSStefano Zampini + A     - the matrix
168775d48cdbSStefano Zampini - store - the boolean flag
168875d48cdbSStefano Zampini 
168975d48cdbSStefano Zampini   Level: advanced
169075d48cdbSStefano Zampini 
16911cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateIS()`, `MatISSetPreallocation()`, `MatPtAP()`
169275d48cdbSStefano Zampini @*/
MatISStoreL2L(Mat A,PetscBool store)1693d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISStoreL2L(Mat A, PetscBool store)
1694d71ae5a4SJacob Faibussowitsch {
169575d48cdbSStefano Zampini   PetscFunctionBegin;
169675d48cdbSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
169775d48cdbSStefano Zampini   PetscValidType(A, 1);
169875d48cdbSStefano Zampini   PetscValidLogicalCollectiveBool(A, store, 2);
1699cac4c232SBarry Smith   PetscTryMethod(A, "MatISStoreL2L_C", (Mat, PetscBool), (A, store));
17003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
170175d48cdbSStefano Zampini }
170275d48cdbSStefano Zampini 
MatISStoreL2L_IS(Mat A,PetscBool store)1703d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISStoreL2L_IS(Mat A, PetscBool store)
1704d71ae5a4SJacob Faibussowitsch {
1705f4f49eeaSPierre Jolivet   Mat_IS *matis = (Mat_IS *)A->data;
170675d48cdbSStefano Zampini 
170775d48cdbSStefano Zampini   PetscFunctionBegin;
170875d48cdbSStefano Zampini   matis->storel2l = store;
170957508eceSPierre Jolivet   if (!store) PetscCall(PetscObjectCompose((PetscObject)A, "_MatIS_PtAP_l2l", NULL));
17103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
171175d48cdbSStefano Zampini }
171275d48cdbSStefano Zampini 
171375d48cdbSStefano Zampini /*@
1714f03112d0SStefano Zampini   MatISFixLocalEmpty - Compress out zero local rows from the local matrices
1715f03112d0SStefano Zampini 
17164f58015eSStefano Zampini   Logically Collective
1717f03112d0SStefano Zampini 
1718f03112d0SStefano Zampini   Input Parameters:
1719f03112d0SStefano Zampini + A   - the matrix
1720f03112d0SStefano Zampini - fix - the boolean flag
1721f03112d0SStefano Zampini 
1722f03112d0SStefano Zampini   Level: advanced
1723f03112d0SStefano Zampini 
172411a5261eSBarry Smith   Note:
17252fe279fdSBarry Smith   When `fix` is `PETSC_TRUE`, new local matrices and l2g maps are generated during the final assembly process.
1726f03112d0SStefano Zampini 
17271cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatCreate()`, `MatCreateIS()`, `MatISSetPreallocation()`, `MatAssemblyEnd()`, `MAT_FINAL_ASSEMBLY`
1728f03112d0SStefano Zampini @*/
MatISFixLocalEmpty(Mat A,PetscBool fix)1729d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISFixLocalEmpty(Mat A, PetscBool fix)
1730d71ae5a4SJacob Faibussowitsch {
1731f03112d0SStefano Zampini   PetscFunctionBegin;
1732f03112d0SStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1733f03112d0SStefano Zampini   PetscValidType(A, 1);
1734f03112d0SStefano Zampini   PetscValidLogicalCollectiveBool(A, fix, 2);
1735cac4c232SBarry Smith   PetscTryMethod(A, "MatISFixLocalEmpty_C", (Mat, PetscBool), (A, fix));
17363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1737f03112d0SStefano Zampini }
1738f03112d0SStefano Zampini 
MatISFixLocalEmpty_IS(Mat A,PetscBool fix)1739d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISFixLocalEmpty_IS(Mat A, PetscBool fix)
1740d71ae5a4SJacob Faibussowitsch {
1741f4f49eeaSPierre Jolivet   Mat_IS *matis = (Mat_IS *)A->data;
1742f03112d0SStefano Zampini 
1743f03112d0SStefano Zampini   PetscFunctionBegin;
1744f03112d0SStefano Zampini   matis->locempty = fix;
17453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1746f03112d0SStefano Zampini }
1747f03112d0SStefano Zampini 
1748f03112d0SStefano Zampini /*@
174911a5261eSBarry Smith   MatISSetPreallocation - Preallocates memory for a `MATIS` parallel matrix.
1750a88811baSStefano Zampini 
1751d083f849SBarry Smith   Collective
1752a88811baSStefano Zampini 
1753a88811baSStefano Zampini   Input Parameters:
1754a88811baSStefano Zampini + B     - the matrix
1755a88811baSStefano Zampini . d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1756a88811baSStefano Zampini            (same value is used for all local rows)
1757a88811baSStefano Zampini . d_nnz - array containing the number of nonzeros in the various rows of the
1758a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
17592ef1f0ffSBarry Smith            or `NULL`, if `d_nz` is used to specify the nonzero structure.
17602ef1f0ffSBarry Smith            The size of this array is equal to the number of local rows, i.e `m`.
1761a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
1762a88811baSStefano Zampini            the diagonal entry even if it is zero.
1763a88811baSStefano Zampini . o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1764a88811baSStefano Zampini            submatrix (same value is used for all local rows).
1765a88811baSStefano Zampini - o_nnz - array containing the number of nonzeros in the various rows of the
1766a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
17672ef1f0ffSBarry Smith            each row) or `NULL`, if `o_nz` is used to specify the nonzero
1768a88811baSStefano Zampini            structure. The size of this array is equal to the number
17692ef1f0ffSBarry Smith            of local rows, i.e `m`.
1770a88811baSStefano Zampini 
1771a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
1772a88811baSStefano Zampini 
1773a88811baSStefano Zampini   Level: intermediate
1774a88811baSStefano Zampini 
177511a5261eSBarry Smith   Note:
177611a5261eSBarry Smith   This function has the same interface as the `MATMPIAIJ` preallocation routine in order to simplify the transition
177711a5261eSBarry Smith   from the asssembled format to the unassembled one. It overestimates the preallocation of `MATIS` local
1778a88811baSStefano Zampini   matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
1779a88811baSStefano Zampini 
17801cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateIS()`, `MatMPIAIJSetPreallocation()`, `MatISGetLocalMat()`, `MATIS`
1781a88811baSStefano Zampini @*/
MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])1782d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISSetPreallocation(Mat B, PetscInt d_nz, const PetscInt d_nnz[], PetscInt o_nz, const PetscInt o_nnz[])
1783d71ae5a4SJacob Faibussowitsch {
17842e1947a5SStefano Zampini   PetscFunctionBegin;
17852e1947a5SStefano Zampini   PetscValidHeaderSpecific(B, MAT_CLASSID, 1);
17862e1947a5SStefano Zampini   PetscValidType(B, 1);
1787cac4c232SBarry Smith   PetscTryMethod(B, "MatISSetPreallocation_C", (Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]), (B, d_nz, d_nnz, o_nz, o_nnz));
17883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17892e1947a5SStefano Zampini }
17902e1947a5SStefano Zampini 
MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])1791523895eeSPierre Jolivet static PetscErrorCode MatISSetPreallocation_IS(Mat B, PetscInt d_nz, const PetscInt d_nnz[], PetscInt o_nz, const PetscInt o_nnz[])
1792d71ae5a4SJacob Faibussowitsch {
1793f4f49eeaSPierre Jolivet   Mat_IS  *matis = (Mat_IS *)B->data;
179428f4e0baSStefano Zampini   PetscInt bs, i, nlocalcols;
17952e1947a5SStefano Zampini 
17962e1947a5SStefano Zampini   PetscFunctionBegin;
17979566063dSJacob Faibussowitsch   PetscCall(MatSetUp(B));
17989371c9d4SSatish Balay   if (!d_nnz)
17999371c9d4SSatish Balay     for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] = d_nz;
18009371c9d4SSatish Balay   else
18019371c9d4SSatish Balay     for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] = d_nnz[i];
18024f2d7cafSStefano Zampini 
18039371c9d4SSatish Balay   if (!o_nnz)
18049371c9d4SSatish Balay     for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] += o_nz;
18059371c9d4SSatish Balay   else
18069371c9d4SSatish Balay     for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] += o_nnz[i];
18074f2d7cafSStefano Zampini 
18089566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE));
18099566063dSJacob Faibussowitsch   PetscCall(MatGetSize(matis->A, NULL, &nlocalcols));
18109566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(matis->A, &bs));
18119566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE));
18124f2d7cafSStefano Zampini 
18134f2d7cafSStefano Zampini   for (i = 0; i < matis->sf->nleaves; i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i], nlocalcols);
18149566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(matis->A, 0, matis->sf_leafdata));
18150f2f62c7SStefano Zampini #if defined(PETSC_HAVE_HYPRE)
18169566063dSJacob Faibussowitsch   PetscCall(MatHYPRESetPreallocation(matis->A, 0, matis->sf_leafdata, 0, NULL));
18170f2f62c7SStefano Zampini #endif
18184f2d7cafSStefano Zampini 
1819fc989267SStefano Zampini   for (i = 0; i < matis->sf->nleaves / bs; i++) {
1820fc989267SStefano Zampini     PetscInt b;
1821fc989267SStefano Zampini 
1822fc989267SStefano Zampini     matis->sf_leafdata[i] = matis->sf_leafdata[i * bs] / bs;
1823ad540459SPierre Jolivet     for (b = 1; b < bs; b++) matis->sf_leafdata[i] = PetscMax(matis->sf_leafdata[i], matis->sf_leafdata[i * bs + b] / bs);
1824fc989267SStefano Zampini   }
18259566063dSJacob Faibussowitsch   PetscCall(MatSeqBAIJSetPreallocation(matis->A, bs, 0, matis->sf_leafdata));
18264f2d7cafSStefano Zampini 
182700a59248SStefano Zampini   nlocalcols /= bs;
182800a59248SStefano Zampini   for (i = 0; i < matis->sf->nleaves / bs; i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i], nlocalcols - i);
18299566063dSJacob Faibussowitsch   PetscCall(MatSeqSBAIJSetPreallocation(matis->A, bs, 0, matis->sf_leafdata));
18300f2f62c7SStefano Zampini 
18310f2f62c7SStefano Zampini   /* for other matrix types */
18329566063dSJacob Faibussowitsch   PetscCall(MatSetUp(matis->A));
18333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18342e1947a5SStefano Zampini }
1835b4319ba4SBarry Smith 
MatConvert_IS_XAIJ(Mat mat,MatType mtype,MatReuse reuse,Mat * M)1836d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_IS_XAIJ(Mat mat, MatType mtype, MatReuse reuse, Mat *M)
1837d71ae5a4SJacob Faibussowitsch {
1838f4f49eeaSPierre Jolivet   Mat_IS            *matis     = (Mat_IS *)mat->data;
1839ac7f1a8bSStefano Zampini   Mat                local_mat = NULL, MT;
184053b44cf5SStefano Zampini   PetscInt           rbs, cbs, rows, cols, lrows, lcols;
1841b7ce53b6SStefano Zampini   PetscInt           local_rows, local_cols;
1842b9ed4604SStefano Zampini   PetscBool          isseqdense, isseqsbaij, isseqaij, isseqbaij;
1843f03112d0SStefano Zampini   PetscMPIInt        size;
18441683a169SBarry Smith   const PetscScalar *array;
1845b7ce53b6SStefano Zampini 
1846b7ce53b6SStefano Zampini   PetscFunctionBegin;
18479566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
18484f58015eSStefano Zampini   if (size == 1 && mat->rmap->N == matis->A->rmap->N && mat->cmap->N == matis->A->cmap->N && !matis->allow_repeated) {
18491670daf9Sstefano_zampini     Mat      B;
185053b44cf5SStefano Zampini     IS       irows = NULL, icols = NULL;
1851487b449aSStefano Zampini     PetscInt rbs, cbs;
18521670daf9Sstefano_zampini 
18539566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->rmapping, &rbs));
18549566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->cmapping, &cbs));
185553b44cf5SStefano Zampini     if (reuse != MAT_REUSE_MATRIX) { /* check if l2g maps are one-to-one */
185653b44cf5SStefano Zampini       IS              rows, cols;
185753b44cf5SStefano Zampini       const PetscInt *ridxs, *cidxs;
18584f58015eSStefano Zampini       PetscInt        i, nw;
18594f58015eSStefano Zampini       PetscBT         work;
186053b44cf5SStefano Zampini 
18619566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingGetBlockIndices(matis->rmapping, &ridxs));
18629566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingGetSize(matis->rmapping, &nw));
186353b44cf5SStefano Zampini       nw = nw / rbs;
18644f58015eSStefano Zampini       PetscCall(PetscBTCreate(nw, &work));
18654f58015eSStefano Zampini       for (i = 0; i < nw; i++) PetscCall(PetscBTSet(work, ridxs[i]));
18669371c9d4SSatish Balay       for (i = 0; i < nw; i++)
18674f58015eSStefano Zampini         if (!PetscBTLookup(work, i)) break;
186853b44cf5SStefano Zampini       if (i == nw) {
18699566063dSJacob Faibussowitsch         PetscCall(ISCreateBlock(PETSC_COMM_SELF, rbs, nw, ridxs, PETSC_USE_POINTER, &rows));
18709566063dSJacob Faibussowitsch         PetscCall(ISSetPermutation(rows));
18719566063dSJacob Faibussowitsch         PetscCall(ISInvertPermutation(rows, PETSC_DECIDE, &irows));
18729566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&rows));
187353b44cf5SStefano Zampini       }
18749566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(matis->rmapping, &ridxs));
18754f58015eSStefano Zampini       PetscCall(PetscBTDestroy(&work));
1876e432b41dSStefano Zampini       if (irows && matis->rmapping != matis->cmapping) {
18779566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingGetBlockIndices(matis->cmapping, &cidxs));
18789566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingGetSize(matis->cmapping, &nw));
187953b44cf5SStefano Zampini         nw = nw / cbs;
18804f58015eSStefano Zampini         PetscCall(PetscBTCreate(nw, &work));
18814f58015eSStefano Zampini         for (i = 0; i < nw; i++) PetscCall(PetscBTSet(work, cidxs[i]));
18829371c9d4SSatish Balay         for (i = 0; i < nw; i++)
18834f58015eSStefano Zampini           if (!PetscBTLookup(work, i)) break;
188453b44cf5SStefano Zampini         if (i == nw) {
18859566063dSJacob Faibussowitsch           PetscCall(ISCreateBlock(PETSC_COMM_SELF, cbs, nw, cidxs, PETSC_USE_POINTER, &cols));
18869566063dSJacob Faibussowitsch           PetscCall(ISSetPermutation(cols));
18879566063dSJacob Faibussowitsch           PetscCall(ISInvertPermutation(cols, PETSC_DECIDE, &icols));
18889566063dSJacob Faibussowitsch           PetscCall(ISDestroy(&cols));
188953b44cf5SStefano Zampini         }
18909566063dSJacob Faibussowitsch         PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(matis->cmapping, &cidxs));
18914f58015eSStefano Zampini         PetscCall(PetscBTDestroy(&work));
189253b44cf5SStefano Zampini       } else if (irows) {
18939566063dSJacob Faibussowitsch         PetscCall(PetscObjectReference((PetscObject)irows));
189453b44cf5SStefano Zampini         icols = irows;
189553b44cf5SStefano Zampini       }
189653b44cf5SStefano Zampini     } else {
1897f4f49eeaSPierre Jolivet       PetscCall(PetscObjectQuery((PetscObject)*M, "_MatIS_IS_XAIJ_irows", (PetscObject *)&irows));
1898f4f49eeaSPierre Jolivet       PetscCall(PetscObjectQuery((PetscObject)*M, "_MatIS_IS_XAIJ_icols", (PetscObject *)&icols));
18999566063dSJacob Faibussowitsch       if (irows) PetscCall(PetscObjectReference((PetscObject)irows));
19009566063dSJacob Faibussowitsch       if (icols) PetscCall(PetscObjectReference((PetscObject)icols));
190153b44cf5SStefano Zampini     }
190253b44cf5SStefano Zampini     if (!irows || !icols) {
19039566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&icols));
19049566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&irows));
190553b44cf5SStefano Zampini       goto general_assembly;
190653b44cf5SStefano Zampini     }
19079566063dSJacob Faibussowitsch     PetscCall(MatConvert(matis->A, mtype, MAT_INITIAL_MATRIX, &B));
1908487b449aSStefano Zampini     if (reuse != MAT_INPLACE_MATRIX) {
19099566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(B, irows, icols, reuse, M));
1910f4f49eeaSPierre Jolivet       PetscCall(PetscObjectCompose((PetscObject)*M, "_MatIS_IS_XAIJ_irows", (PetscObject)irows));
1911f4f49eeaSPierre Jolivet       PetscCall(PetscObjectCompose((PetscObject)*M, "_MatIS_IS_XAIJ_icols", (PetscObject)icols));
1912487b449aSStefano Zampini     } else {
1913487b449aSStefano Zampini       Mat C;
1914487b449aSStefano Zampini 
19159566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(B, irows, icols, MAT_INITIAL_MATRIX, &C));
19169566063dSJacob Faibussowitsch       PetscCall(MatHeaderReplace(mat, &C));
1917487b449aSStefano Zampini     }
19189566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
19199566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&icols));
19209566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&irows));
19213ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
19227c03b4e8SStefano Zampini   }
192353b44cf5SStefano Zampini general_assembly:
19249566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &rows, &cols));
19259566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->rmapping, &rbs));
19269566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->cmapping, &cbs));
19279566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mat, &lrows, &lcols));
19289566063dSJacob Faibussowitsch   PetscCall(MatGetSize(matis->A, &local_rows, &local_cols));
19299566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQDENSE, &isseqdense));
19309566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQAIJ, &isseqaij));
19319566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQBAIJ, &isseqbaij));
19329566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQSBAIJ, &isseqsbaij));
1933f4f49eeaSPierre Jolivet   PetscCheck(isseqdense || isseqaij || isseqbaij || isseqsbaij, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)matis->A)->type_name);
193476bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
193576bd3646SJed Brown     PetscBool lb[4], bb[4];
193676bd3646SJed Brown 
1937b9ed4604SStefano Zampini     lb[0] = isseqdense;
1938b9ed4604SStefano Zampini     lb[1] = isseqaij;
1939b9ed4604SStefano Zampini     lb[2] = isseqbaij;
1940b9ed4604SStefano Zampini     lb[3] = isseqsbaij;
19415440e5dcSBarry Smith     PetscCallMPI(MPIU_Allreduce(lb, bb, 4, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)mat)));
1942aed4548fSBarry Smith     PetscCheck(bb[0] || bb[1] || bb[2] || bb[3], PETSC_COMM_SELF, PETSC_ERR_SUP, "Local matrices must have the same type");
194376bd3646SJed Brown   }
1944b7ce53b6SStefano Zampini 
1945487b449aSStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
1946ac7f1a8bSStefano Zampini     PetscCount ncoo;
1947ac7f1a8bSStefano Zampini     PetscInt  *coo_i, *coo_j;
1948ac7f1a8bSStefano Zampini 
19499566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &MT));
19509566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(MT, lrows, lcols, rows, cols));
19519566063dSJacob Faibussowitsch     PetscCall(MatSetType(MT, mtype));
19529566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizes(MT, rbs, cbs));
1953ac7f1a8bSStefano Zampini     if (!isseqaij && !isseqdense) {
1954ac7f1a8bSStefano Zampini       PetscCall(MatConvert(matis->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &local_mat));
1955ac7f1a8bSStefano Zampini     } else {
1956ac7f1a8bSStefano Zampini       PetscCall(PetscObjectReference((PetscObject)matis->A));
1957ac7f1a8bSStefano Zampini       local_mat = matis->A;
1958ac7f1a8bSStefano Zampini     }
1959ac7f1a8bSStefano Zampini     PetscCall(MatSetLocalToGlobalMapping(MT, matis->rmapping, matis->cmapping));
1960ac7f1a8bSStefano Zampini     if (isseqdense) {
1961ac7f1a8bSStefano Zampini       PetscInt nr, nc;
1962ac7f1a8bSStefano Zampini 
1963ac7f1a8bSStefano Zampini       PetscCall(MatGetSize(local_mat, &nr, &nc));
1964ac7f1a8bSStefano Zampini       ncoo = nr * nc;
1965ac7f1a8bSStefano Zampini       PetscCall(PetscMalloc2(ncoo, &coo_i, ncoo, &coo_j));
1966ac7f1a8bSStefano Zampini       for (PetscInt j = 0; j < nc; j++) {
1967ac7f1a8bSStefano Zampini         for (PetscInt i = 0; i < nr; i++) {
1968ac7f1a8bSStefano Zampini           coo_i[j * nr + i] = i;
1969ac7f1a8bSStefano Zampini           coo_j[j * nr + i] = j;
1970ac7f1a8bSStefano Zampini         }
1971ac7f1a8bSStefano Zampini       }
1972ac7f1a8bSStefano Zampini     } else {
1973ac7f1a8bSStefano Zampini       const PetscInt *ii, *jj;
1974ac7f1a8bSStefano Zampini       PetscInt        nr;
1975ac7f1a8bSStefano Zampini       PetscBool       done;
1976ac7f1a8bSStefano Zampini 
1977ac7f1a8bSStefano Zampini       PetscCall(MatGetRowIJ(local_mat, 0, PETSC_FALSE, PETSC_FALSE, &nr, &ii, &jj, &done));
1978ac7f1a8bSStefano Zampini       PetscCheck(done, PetscObjectComm((PetscObject)local_mat), PETSC_ERR_PLIB, "Error in MatGetRowIJ");
1979ac7f1a8bSStefano Zampini       ncoo = ii[nr];
1980ac7f1a8bSStefano Zampini       PetscCall(PetscMalloc2(ncoo, &coo_i, ncoo, &coo_j));
1981ac7f1a8bSStefano Zampini       PetscCall(PetscArraycpy(coo_j, jj, ncoo));
1982ac7f1a8bSStefano Zampini       for (PetscInt i = 0; i < nr; i++) {
1983ac7f1a8bSStefano Zampini         for (PetscInt j = ii[i]; j < ii[i + 1]; j++) coo_i[j] = i;
1984ac7f1a8bSStefano Zampini       }
1985ac7f1a8bSStefano Zampini       PetscCall(MatRestoreRowIJ(local_mat, 0, PETSC_FALSE, PETSC_FALSE, &nr, &ii, &jj, &done));
1986ac7f1a8bSStefano Zampini       PetscCheck(done, PetscObjectComm((PetscObject)local_mat), PETSC_ERR_PLIB, "Error in MatRestoreRowIJ");
1987ac7f1a8bSStefano Zampini     }
1988ac7f1a8bSStefano Zampini     PetscCall(MatSetPreallocationCOOLocal(MT, ncoo, coo_i, coo_j));
1989ac7f1a8bSStefano Zampini     PetscCall(PetscFree2(coo_i, coo_j));
1990b7ce53b6SStefano Zampini   } else {
199153b44cf5SStefano Zampini     PetscInt mrbs, mcbs, mrows, mcols, mlrows, mlcols;
1992487b449aSStefano Zampini 
1993b7ce53b6SStefano Zampini     /* some checks */
1994487b449aSStefano Zampini     MT = *M;
19959566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSizes(MT, &mrbs, &mcbs));
19969566063dSJacob Faibussowitsch     PetscCall(MatGetSize(MT, &mrows, &mcols));
19979566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(MT, &mlrows, &mlcols));
199808401ef6SPierre Jolivet     PetscCheck(mrows == rows, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of rows (%" PetscInt_FMT " != %" PetscInt_FMT ")", rows, mrows);
199908401ef6SPierre Jolivet     PetscCheck(mcols == cols, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of cols (%" PetscInt_FMT " != %" PetscInt_FMT ")", cols, mcols);
200008401ef6SPierre Jolivet     PetscCheck(mlrows == lrows, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of local rows (%" PetscInt_FMT " != %" PetscInt_FMT ")", lrows, mlrows);
200108401ef6SPierre Jolivet     PetscCheck(mlcols == lcols, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of local cols (%" PetscInt_FMT " != %" PetscInt_FMT ")", lcols, mlcols);
200208401ef6SPierre Jolivet     PetscCheck(mrbs == rbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong row block size (%" PetscInt_FMT " != %" PetscInt_FMT ")", rbs, mrbs);
200308401ef6SPierre Jolivet     PetscCheck(mcbs == cbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong col block size (%" PetscInt_FMT " != %" PetscInt_FMT ")", cbs, mcbs);
20049566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries(MT));
2005ac7f1a8bSStefano Zampini     if (!isseqaij && !isseqdense) {
20069566063dSJacob Faibussowitsch       PetscCall(MatConvert(matis->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &local_mat));
2007d9a9e74cSStefano Zampini     } else {
20089566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)matis->A));
2009d9a9e74cSStefano Zampini       local_mat = matis->A;
2010d9a9e74cSStefano Zampini     }
2011ac7f1a8bSStefano Zampini   }
2012686e3a49SStefano Zampini 
2013b7ce53b6SStefano Zampini   /* Set values */
2014ac7f1a8bSStefano Zampini   if (isseqdense) {
20159566063dSJacob Faibussowitsch     PetscCall(MatDenseGetArrayRead(local_mat, &array));
2016ac7f1a8bSStefano Zampini     PetscCall(MatSetValuesCOO(MT, array, INSERT_VALUES));
20179566063dSJacob Faibussowitsch     PetscCall(MatDenseRestoreArrayRead(local_mat, &array));
20186afe12f5SStefano Zampini   } else {
2019ac7f1a8bSStefano Zampini     PetscCall(MatSeqAIJGetArrayRead(local_mat, &array));
2020ac7f1a8bSStefano Zampini     PetscCall(MatSetValuesCOO(MT, array, INSERT_VALUES));
2021ac7f1a8bSStefano Zampini     PetscCall(MatSeqAIJRestoreArrayRead(local_mat, &array));
2022b7ce53b6SStefano Zampini   }
20239566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&local_mat));
20244f58015eSStefano Zampini   PetscCall(MatAssemblyBegin(MT, MAT_FINAL_ASSEMBLY));
20259566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(MT, MAT_FINAL_ASSEMBLY));
2026487b449aSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
20279566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(mat, &MT));
2028487b449aSStefano Zampini   } else if (reuse == MAT_INITIAL_MATRIX) {
2029487b449aSStefano Zampini     *M = MT;
2030b7ce53b6SStefano Zampini   }
20313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2032b7ce53b6SStefano Zampini }
2033b7ce53b6SStefano Zampini 
MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat * newmat)2034d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDuplicate_IS(Mat mat, MatDuplicateOption op, Mat *newmat)
2035d71ae5a4SJacob Faibussowitsch {
2036f4f49eeaSPierre Jolivet   Mat_IS  *matis = (Mat_IS *)mat->data;
2037c9225affSStefano Zampini   PetscInt rbs, cbs, m, n, M, N;
2038ad6194a2SStefano Zampini   Mat      B, localmat;
2039ad6194a2SStefano Zampini 
2040ad6194a2SStefano Zampini   PetscFunctionBegin;
20419566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &rbs));
20429566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &cbs));
20439566063dSJacob Faibussowitsch   PetscCall(MatGetSize(mat, &M, &N));
20449566063dSJacob Faibussowitsch   PetscCall(MatGetLocalSize(mat, &m, &n));
20459566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
20469566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(B, m, n, M, N));
20479566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(B, rbs == cbs ? rbs : 1));
20489566063dSJacob Faibussowitsch   PetscCall(MatSetType(B, MATIS));
20499566063dSJacob Faibussowitsch   PetscCall(MatISSetLocalMatType(B, matis->lmattype));
20504f58015eSStefano Zampini   PetscCall(MatISSetAllowRepeated(B, matis->allow_repeated));
20519566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(B, mat->rmap->mapping, mat->cmap->mapping));
20529566063dSJacob Faibussowitsch   PetscCall(MatDuplicate(matis->A, op, &localmat));
20539566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(localmat, matis->A->rmap->mapping, matis->A->cmap->mapping));
20549566063dSJacob Faibussowitsch   PetscCall(MatISSetLocalMat(B, localmat));
20559566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&localmat));
20569566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
20579566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
2058ad6194a2SStefano Zampini   *newmat = B;
20593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2060ad6194a2SStefano Zampini }
2061ad6194a2SStefano Zampini 
MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool * flg)2062d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsHermitian_IS(Mat A, PetscReal tol, PetscBool *flg)
2063d71ae5a4SJacob Faibussowitsch {
206469796d55SStefano Zampini   Mat_IS   *matis = (Mat_IS *)A->data;
206569796d55SStefano Zampini   PetscBool local_sym;
206669796d55SStefano Zampini 
206769796d55SStefano Zampini   PetscFunctionBegin;
20689566063dSJacob Faibussowitsch   PetscCall(MatIsHermitian(matis->A, tol, &local_sym));
20695440e5dcSBarry Smith   PetscCallMPI(MPIU_Allreduce(&local_sym, flg, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A)));
20703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
207169796d55SStefano Zampini }
207269796d55SStefano Zampini 
MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool * flg)2073d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsSymmetric_IS(Mat A, PetscReal tol, PetscBool *flg)
2074d71ae5a4SJacob Faibussowitsch {
207569796d55SStefano Zampini   Mat_IS   *matis = (Mat_IS *)A->data;
207669796d55SStefano Zampini   PetscBool local_sym;
207769796d55SStefano Zampini 
207869796d55SStefano Zampini   PetscFunctionBegin;
2079e432b41dSStefano Zampini   if (matis->rmapping != matis->cmapping) {
2080e432b41dSStefano Zampini     *flg = PETSC_FALSE;
20813ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2082e432b41dSStefano Zampini   }
20839566063dSJacob Faibussowitsch   PetscCall(MatIsSymmetric(matis->A, tol, &local_sym));
20845440e5dcSBarry Smith   PetscCallMPI(MPIU_Allreduce(&local_sym, flg, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A)));
20853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
208669796d55SStefano Zampini }
208769796d55SStefano Zampini 
MatIsStructurallySymmetric_IS(Mat A,PetscBool * flg)2088d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A, PetscBool *flg)
2089d71ae5a4SJacob Faibussowitsch {
209045471136SStefano Zampini   Mat_IS   *matis = (Mat_IS *)A->data;
209145471136SStefano Zampini   PetscBool local_sym;
209245471136SStefano Zampini 
209345471136SStefano Zampini   PetscFunctionBegin;
2094e432b41dSStefano Zampini   if (matis->rmapping != matis->cmapping) {
209545471136SStefano Zampini     *flg = PETSC_FALSE;
20963ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
209745471136SStefano Zampini   }
20989566063dSJacob Faibussowitsch   PetscCall(MatIsStructurallySymmetric(matis->A, &local_sym));
20995440e5dcSBarry Smith   PetscCallMPI(MPIU_Allreduce(&local_sym, flg, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A)));
21003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
210145471136SStefano Zampini }
210245471136SStefano Zampini 
MatDestroy_IS(Mat A)2103d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_IS(Mat A)
2104d71ae5a4SJacob Faibussowitsch {
2105b4319ba4SBarry Smith   Mat_IS *b = (Mat_IS *)A->data;
2106b4319ba4SBarry Smith 
2107b4319ba4SBarry Smith   PetscFunctionBegin;
21089566063dSJacob Faibussowitsch   PetscCall(PetscFree(b->bdiag));
21099566063dSJacob Faibussowitsch   PetscCall(PetscFree(b->lmattype));
21109566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&b->A));
21119566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&b->cctx));
21129566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&b->rctx));
21139566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&b->x));
21149566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&b->y));
21159566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&b->counter));
21169566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&b->getsub_ris));
21179566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&b->getsub_cis));
2118a8116848SStefano Zampini   if (b->sf != b->csf) {
21199566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&b->csf));
21209566063dSJacob Faibussowitsch     PetscCall(PetscFree2(b->csf_rootdata, b->csf_leafdata));
2121f03112d0SStefano Zampini   } else b->csf = NULL;
21229566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&b->sf));
21239566063dSJacob Faibussowitsch   PetscCall(PetscFree2(b->sf_rootdata, b->sf_leafdata));
21249566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&b->rmapping));
21259566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&b->cmapping));
2126d0dbe9f7SStefano Zampini   PetscCall(MatDestroy(&b->dA));
2127d0dbe9f7SStefano Zampini   PetscCall(MatDestroy(&b->assembledA));
21289566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->data));
21299566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)A, NULL));
21309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMatType_C", NULL));
21319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalMat_C", NULL));
21329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMat_C", NULL));
21332e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISRestoreLocalMat_C", NULL));
21349566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetPreallocation_C", NULL));
21359566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISStoreL2L_C", NULL));
21369566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISFixLocalEmpty_C", NULL));
21379566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalToGlobalMapping_C", NULL));
21389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpiaij_C", NULL));
21399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpibaij_C", NULL));
21409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpisbaij_C", NULL));
21419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqaij_C", NULL));
21429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqbaij_C", NULL));
21439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqsbaij_C", NULL));
21449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_aij_C", NULL));
21459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOOLocal_C", NULL));
21469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL));
21479566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL));
21484f58015eSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetAllowRepeated_C", NULL));
21493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2150b4319ba4SBarry Smith }
2151b4319ba4SBarry Smith 
MatMult_IS(Mat A,Vec x,Vec y)2152d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_IS(Mat A, Vec x, Vec y)
2153d71ae5a4SJacob Faibussowitsch {
2154b4319ba4SBarry Smith   Mat_IS     *is   = (Mat_IS *)A->data;
2155b4319ba4SBarry Smith   PetscScalar zero = 0.0;
2156b4319ba4SBarry Smith 
2157b4319ba4SBarry Smith   PetscFunctionBegin;
2158b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
21599566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(is->cctx, x, is->x, INSERT_VALUES, SCATTER_FORWARD));
21609566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(is->cctx, x, is->x, INSERT_VALUES, SCATTER_FORWARD));
2161b4319ba4SBarry Smith 
2162b4319ba4SBarry Smith   /* multiply the local matrix */
21639566063dSJacob Faibussowitsch   PetscCall(MatMult(is->A, is->x, is->y));
2164b4319ba4SBarry Smith 
2165b4319ba4SBarry Smith   /* scatter product back into global memory */
21669566063dSJacob Faibussowitsch   PetscCall(VecSet(y, zero));
21679566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(is->rctx, is->y, y, ADD_VALUES, SCATTER_REVERSE));
21689566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(is->rctx, is->y, y, ADD_VALUES, SCATTER_REVERSE));
21693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2170b4319ba4SBarry Smith }
2171b4319ba4SBarry Smith 
MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)2172d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultAdd_IS(Mat A, Vec v1, Vec v2, Vec v3)
2173d71ae5a4SJacob Faibussowitsch {
2174650997f4SStefano Zampini   Vec temp_vec;
21752e74eeadSLisandro Dalcin 
21762e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
2177650997f4SStefano Zampini   if (v3 != v2) {
21789566063dSJacob Faibussowitsch     PetscCall(MatMult(A, v1, v3));
21799566063dSJacob Faibussowitsch     PetscCall(VecAXPY(v3, 1.0, v2));
2180650997f4SStefano Zampini   } else {
21819566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(v2, &temp_vec));
21829566063dSJacob Faibussowitsch     PetscCall(MatMult(A, v1, temp_vec));
21839566063dSJacob Faibussowitsch     PetscCall(VecAXPY(temp_vec, 1.0, v2));
21849566063dSJacob Faibussowitsch     PetscCall(VecCopy(temp_vec, v3));
21859566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&temp_vec));
2186650997f4SStefano Zampini   }
21873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21882e74eeadSLisandro Dalcin }
21892e74eeadSLisandro Dalcin 
MatMultTranspose_IS(Mat A,Vec y,Vec x)2190d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTranspose_IS(Mat A, Vec y, Vec x)
2191d71ae5a4SJacob Faibussowitsch {
21922e74eeadSLisandro Dalcin   Mat_IS *is = (Mat_IS *)A->data;
21932e74eeadSLisandro Dalcin 
2194e176bc59SStefano Zampini   PetscFunctionBegin;
21952e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
21969566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(is->rctx, y, is->y, INSERT_VALUES, SCATTER_FORWARD));
21979566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(is->rctx, y, is->y, INSERT_VALUES, SCATTER_FORWARD));
21982e74eeadSLisandro Dalcin 
21992e74eeadSLisandro Dalcin   /* multiply the local matrix */
22009566063dSJacob Faibussowitsch   PetscCall(MatMultTranspose(is->A, is->y, is->x));
22012e74eeadSLisandro Dalcin 
22022e74eeadSLisandro Dalcin   /* scatter product back into global vector */
22039566063dSJacob Faibussowitsch   PetscCall(VecSet(x, 0));
22049566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(is->cctx, is->x, x, ADD_VALUES, SCATTER_REVERSE));
22059566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(is->cctx, is->x, x, ADD_VALUES, SCATTER_REVERSE));
22063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22072e74eeadSLisandro Dalcin }
22082e74eeadSLisandro Dalcin 
MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)2209d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTransposeAdd_IS(Mat A, Vec v1, Vec v2, Vec v3)
2210d71ae5a4SJacob Faibussowitsch {
2211650997f4SStefano Zampini   Vec temp_vec;
22122e74eeadSLisandro Dalcin 
22132e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
2214650997f4SStefano Zampini   if (v3 != v2) {
22159566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(A, v1, v3));
22169566063dSJacob Faibussowitsch     PetscCall(VecAXPY(v3, 1.0, v2));
2217650997f4SStefano Zampini   } else {
22189566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(v2, &temp_vec));
22199566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(A, v1, temp_vec));
22209566063dSJacob Faibussowitsch     PetscCall(VecAXPY(temp_vec, 1.0, v2));
22219566063dSJacob Faibussowitsch     PetscCall(VecCopy(temp_vec, v3));
22229566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&temp_vec));
2223650997f4SStefano Zampini   }
22243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22252e74eeadSLisandro Dalcin }
22262e74eeadSLisandro Dalcin 
ISLocalToGlobalMappingView_Multi(ISLocalToGlobalMapping mapping,PetscInt lsize,PetscInt gsize,const PetscInt vblocks[],PetscViewer viewer)2227a3ef7f04SStefano Zampini static PetscErrorCode ISLocalToGlobalMappingView_Multi(ISLocalToGlobalMapping mapping, PetscInt lsize, PetscInt gsize, const PetscInt vblocks[], PetscViewer viewer)
2228a3ef7f04SStefano Zampini {
2229a3ef7f04SStefano Zampini   PetscInt        tr[3], n;
2230a3ef7f04SStefano Zampini   const PetscInt *indices;
2231a3ef7f04SStefano Zampini 
2232a3ef7f04SStefano Zampini   PetscFunctionBegin;
2233a3ef7f04SStefano Zampini   tr[0] = IS_LTOGM_FILE_CLASSID;
2234a3ef7f04SStefano Zampini   tr[1] = 1;
2235a3ef7f04SStefano Zampini   tr[2] = gsize;
2236a3ef7f04SStefano Zampini   PetscCall(PetscViewerBinaryWrite(viewer, tr, 3, PETSC_INT));
2237a3ef7f04SStefano Zampini   PetscCall(PetscViewerBinaryWriteAll(viewer, vblocks, lsize, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
2238a3ef7f04SStefano Zampini   PetscCall(ISLocalToGlobalMappingGetSize(mapping, &n));
2239a3ef7f04SStefano Zampini   PetscCall(ISLocalToGlobalMappingGetIndices(mapping, &indices));
2240a3ef7f04SStefano Zampini   PetscCall(PetscViewerBinaryWriteAll(viewer, indices, n, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT));
2241a3ef7f04SStefano Zampini   PetscCall(ISLocalToGlobalMappingRestoreIndices(mapping, &indices));
2242a3ef7f04SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2243a3ef7f04SStefano Zampini }
2244a3ef7f04SStefano Zampini 
MatView_IS(Mat A,PetscViewer viewer)2245d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_IS(Mat A, PetscViewer viewer)
2246d71ae5a4SJacob Faibussowitsch {
2247b4319ba4SBarry Smith   Mat_IS                *a = (Mat_IS *)A->data;
2248b4319ba4SBarry Smith   PetscViewer            sviewer;
22495042aa92SStefano Zampini   PetscBool              isascii, isbinary, viewl2g = PETSC_FALSE, native;
22505042aa92SStefano Zampini   PetscViewerFormat      format;
22515042aa92SStefano Zampini   ISLocalToGlobalMapping rmap, cmap;
2252b4319ba4SBarry Smith 
2253b4319ba4SBarry Smith   PetscFunctionBegin;
22549566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
22555042aa92SStefano Zampini   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
22569566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
22575042aa92SStefano Zampini   native = (PetscBool)(format == PETSC_VIEWER_NATIVE);
22585042aa92SStefano Zampini   if (native) {
22595042aa92SStefano Zampini     rmap = A->rmap->mapping;
22605042aa92SStefano Zampini     cmap = A->cmap->mapping;
22615042aa92SStefano Zampini   } else {
22625042aa92SStefano Zampini     rmap = a->rmapping;
22635042aa92SStefano Zampini     cmap = a->cmapping;
2264ee2491ecSStefano Zampini   }
22655042aa92SStefano Zampini   if (isascii) {
22665042aa92SStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO) PetscFunctionReturn(PETSC_SUCCESS);
22675042aa92SStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO_DETAIL || format == PETSC_VIEWER_ASCII_MATLAB) viewl2g = PETSC_TRUE;
22685042aa92SStefano Zampini   } else if (isbinary) {
2269a3ef7f04SStefano Zampini     PetscInt        tr[6], nr, nc, lsize = 0;
22705042aa92SStefano Zampini     char            lmattype[64] = {'\0'};
22715042aa92SStefano Zampini     PetscMPIInt     size;
2272a3ef7f04SStefano Zampini     PetscBool       skipHeader, vbs = PETSC_FALSE;
22735042aa92SStefano Zampini     IS              is;
2274a3ef7f04SStefano Zampini     const PetscInt *vblocks = NULL;
22755042aa92SStefano Zampini 
22765042aa92SStefano Zampini     PetscCall(PetscViewerSetUp(viewer));
2277a3ef7f04SStefano Zampini     PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)A)->prefix, "-mat_is_view_variableblocksizes", &vbs, NULL));
2278a3ef7f04SStefano Zampini     if (vbs) {
2279a3ef7f04SStefano Zampini       PetscCall(MatGetVariableBlockSizes(a->A, &lsize, &vblocks));
2280a3ef7f04SStefano Zampini       PetscCall(PetscMPIIntCast(lsize, &size));
2281a3ef7f04SStefano Zampini       PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &size, 1, MPI_INT, MPI_SUM, PetscObjectComm((PetscObject)viewer)));
2282a3ef7f04SStefano Zampini     } else {
22835042aa92SStefano Zampini       PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size));
2284a3ef7f04SStefano Zampini     }
22855042aa92SStefano Zampini     tr[0] = MAT_FILE_CLASSID;
22865042aa92SStefano Zampini     tr[1] = A->rmap->N;
22875042aa92SStefano Zampini     tr[2] = A->cmap->N;
22885042aa92SStefano Zampini     tr[3] = -size; /* AIJ stores nnz here */
22895042aa92SStefano Zampini     tr[4] = (PetscInt)(rmap == cmap);
22905042aa92SStefano Zampini     tr[5] = a->allow_repeated;
22915042aa92SStefano Zampini     PetscCall(PetscSNPrintf(lmattype, sizeof(lmattype), "%s", a->lmattype));
22925042aa92SStefano Zampini 
22935042aa92SStefano Zampini     PetscCall(PetscViewerBinaryWrite(viewer, tr, PETSC_STATIC_ARRAY_LENGTH(tr), PETSC_INT));
22945042aa92SStefano Zampini     PetscCall(PetscViewerBinaryWrite(viewer, lmattype, sizeof(lmattype), PETSC_CHAR));
22955042aa92SStefano Zampini 
22965042aa92SStefano Zampini     /* first dump l2g info (we need the header for proper loading on different number of processes) */
22975042aa92SStefano Zampini     PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader));
22985042aa92SStefano Zampini     PetscCall(PetscViewerBinarySetSkipHeader(viewer, PETSC_FALSE));
2299a3ef7f04SStefano Zampini     if (vbs) {
2300a3ef7f04SStefano Zampini       PetscCall(ISLocalToGlobalMappingView_Multi(rmap, lsize, size, vblocks, viewer));
2301a3ef7f04SStefano Zampini       if (cmap != rmap) PetscCall(ISLocalToGlobalMappingView_Multi(cmap, lsize, size, vblocks, viewer));
2302a3ef7f04SStefano Zampini       PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), lsize, vblocks, PETSC_USE_POINTER, &is));
2303a3ef7f04SStefano Zampini       PetscCall(ISView(is, viewer));
2304a3ef7f04SStefano Zampini       PetscCall(ISView(is, viewer));
2305a3ef7f04SStefano Zampini       PetscCall(ISDestroy(&is));
2306a3ef7f04SStefano Zampini     } else {
23075042aa92SStefano Zampini       PetscCall(ISLocalToGlobalMappingView(rmap, viewer));
23085042aa92SStefano Zampini       if (cmap != rmap) PetscCall(ISLocalToGlobalMappingView(cmap, viewer));
23095042aa92SStefano Zampini 
23105042aa92SStefano Zampini       /* then the sizes of the local matrices */
23115042aa92SStefano Zampini       PetscCall(MatGetSize(a->A, &nr, &nc));
23125042aa92SStefano Zampini       PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), 1, &nr, PETSC_USE_POINTER, &is));
23135042aa92SStefano Zampini       PetscCall(ISView(is, viewer));
23145042aa92SStefano Zampini       PetscCall(ISDestroy(&is));
23155042aa92SStefano Zampini       PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), 1, &nc, PETSC_USE_POINTER, &is));
23165042aa92SStefano Zampini       PetscCall(ISView(is, viewer));
23175042aa92SStefano Zampini       PetscCall(ISDestroy(&is));
2318a3ef7f04SStefano Zampini     }
23195042aa92SStefano Zampini     PetscCall(PetscViewerBinarySetSkipHeader(viewer, skipHeader));
23205042aa92SStefano Zampini   }
23215042aa92SStefano Zampini   if (format == PETSC_VIEWER_ASCII_MATLAB) {
23225042aa92SStefano Zampini     char        name[64];
23235042aa92SStefano Zampini     PetscMPIInt size, rank;
23245042aa92SStefano Zampini 
23255042aa92SStefano Zampini     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size));
23265042aa92SStefano Zampini     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
23275042aa92SStefano Zampini     if (size > 1) PetscCall(PetscSNPrintf(name, sizeof(name), "lmat_%d", rank));
23285042aa92SStefano Zampini     else PetscCall(PetscSNPrintf(name, sizeof(name), "lmat"));
23295042aa92SStefano Zampini     PetscCall(PetscObjectSetName((PetscObject)a->A, name));
23305042aa92SStefano Zampini   }
23315042aa92SStefano Zampini 
23325042aa92SStefano Zampini   /* Dump the local matrices */
23335042aa92SStefano Zampini   if (isbinary) { /* ViewerGetSubViewer does not work in parallel */
23345042aa92SStefano Zampini     PetscBool   isaij;
23355042aa92SStefano Zampini     PetscInt    nr, nc;
23365042aa92SStefano Zampini     Mat         lA, B;
23375042aa92SStefano Zampini     Mat_MPIAIJ *b;
23385042aa92SStefano Zampini 
23395042aa92SStefano Zampini     /* We create a temporary MPIAIJ matrix that stores the unassembled operator */
23405042aa92SStefano Zampini     PetscCall(PetscObjectBaseTypeCompare((PetscObject)a->A, MATAIJ, &isaij));
23415042aa92SStefano Zampini     if (!isaij) PetscCall(MatConvert(a->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &lA));
23425042aa92SStefano Zampini     else {
23435042aa92SStefano Zampini       PetscCall(PetscObjectReference((PetscObject)a->A));
23445042aa92SStefano Zampini       lA = a->A;
23455042aa92SStefano Zampini     }
23465042aa92SStefano Zampini     PetscCall(MatCreate(PetscObjectComm((PetscObject)viewer), &B));
23475042aa92SStefano Zampini     PetscCall(MatSetType(B, MATMPIAIJ));
23485042aa92SStefano Zampini     PetscCall(MatGetSize(lA, &nr, &nc));
23495042aa92SStefano Zampini     PetscCall(MatSetSizes(B, nr, nc, PETSC_DECIDE, PETSC_DECIDE));
23505042aa92SStefano Zampini     PetscCall(MatMPIAIJSetPreallocation(B, 0, NULL, 0, NULL));
23515042aa92SStefano Zampini 
23525042aa92SStefano Zampini     b = (Mat_MPIAIJ *)B->data;
23535042aa92SStefano Zampini     PetscCall(MatDestroy(&b->A));
23545042aa92SStefano Zampini     b->A = lA;
23555042aa92SStefano Zampini 
23565042aa92SStefano Zampini     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
23575042aa92SStefano Zampini     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
23585042aa92SStefano Zampini     PetscCall(MatView(B, viewer));
23595042aa92SStefano Zampini     PetscCall(MatDestroy(&B));
23605042aa92SStefano Zampini   } else {
23619566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetSubViewer(viewer, PETSC_COMM_SELF, &sviewer));
23629566063dSJacob Faibussowitsch     PetscCall(MatView(a->A, sviewer));
23639566063dSJacob Faibussowitsch     PetscCall(PetscViewerRestoreSubViewer(viewer, PETSC_COMM_SELF, &sviewer));
23645042aa92SStefano Zampini   }
23655042aa92SStefano Zampini 
23665042aa92SStefano Zampini   /* with ASCII, we dump the l2gmaps at the end */
23675042aa92SStefano Zampini   if (viewl2g) {
23685042aa92SStefano Zampini     if (format == PETSC_VIEWER_ASCII_MATLAB) {
23695042aa92SStefano Zampini       PetscCall(PetscObjectSetName((PetscObject)rmap, "row"));
23705042aa92SStefano Zampini       PetscCall(ISLocalToGlobalMappingView(rmap, viewer));
23715042aa92SStefano Zampini       PetscCall(PetscObjectSetName((PetscObject)cmap, "col"));
23725042aa92SStefano Zampini       PetscCall(ISLocalToGlobalMappingView(cmap, viewer));
23735042aa92SStefano Zampini     } else {
23745042aa92SStefano Zampini       PetscCall(ISLocalToGlobalMappingView(rmap, viewer));
23755042aa92SStefano Zampini       PetscCall(ISLocalToGlobalMappingView(cmap, viewer));
23765042aa92SStefano Zampini     }
23775042aa92SStefano Zampini   }
23785042aa92SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
23795042aa92SStefano Zampini }
23805042aa92SStefano Zampini 
ISLocalToGlobalMappingHasRepeatedLocal_Private(ISLocalToGlobalMapping map,PetscBool * has)2381a3ef7f04SStefano Zampini static PetscErrorCode ISLocalToGlobalMappingHasRepeatedLocal_Private(ISLocalToGlobalMapping map, PetscBool *has)
2382a3ef7f04SStefano Zampini {
2383a3ef7f04SStefano Zampini   const PetscInt *idxs;
2384a3ef7f04SStefano Zampini   PetscHSetI      ht;
2385a3ef7f04SStefano Zampini   PetscInt        n, bs;
2386a3ef7f04SStefano Zampini 
2387a3ef7f04SStefano Zampini   PetscFunctionBegin;
2388a3ef7f04SStefano Zampini   PetscCall(ISLocalToGlobalMappingGetSize(map, &n));
2389a3ef7f04SStefano Zampini   PetscCall(ISLocalToGlobalMappingGetBlockSize(map, &bs));
2390a3ef7f04SStefano Zampini   PetscCall(ISLocalToGlobalMappingGetBlockIndices(map, &idxs));
2391a3ef7f04SStefano Zampini   PetscCall(PetscHSetICreate(&ht));
2392a3ef7f04SStefano Zampini   *has = PETSC_FALSE;
2393a3ef7f04SStefano Zampini   for (PetscInt i = 0; i < n / bs; i++) {
2394a3ef7f04SStefano Zampini     PetscBool missing = PETSC_TRUE;
2395a3ef7f04SStefano Zampini     if (idxs[i] < 0) continue;
2396a3ef7f04SStefano Zampini     PetscCall(PetscHSetIQueryAdd(ht, idxs[i], &missing));
2397a3ef7f04SStefano Zampini     if (!missing) {
2398a3ef7f04SStefano Zampini       *has = PETSC_TRUE;
2399a3ef7f04SStefano Zampini       break;
2400a3ef7f04SStefano Zampini     }
2401a3ef7f04SStefano Zampini   }
2402a3ef7f04SStefano Zampini   PetscCall(PetscHSetIDestroy(&ht));
2403a3ef7f04SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
2404a3ef7f04SStefano Zampini }
2405a3ef7f04SStefano Zampini 
MatLoad_IS(Mat A,PetscViewer viewer)24065042aa92SStefano Zampini static PetscErrorCode MatLoad_IS(Mat A, PetscViewer viewer)
24075042aa92SStefano Zampini {
24085042aa92SStefano Zampini   ISLocalToGlobalMapping rmap, cmap;
24095042aa92SStefano Zampini   MPI_Comm               comm = PetscObjectComm((PetscObject)A);
24105042aa92SStefano Zampini   PetscBool              isbinary, samel, allow, isbaij;
24115042aa92SStefano Zampini   PetscInt               tr[6], M, N, nr, nc, Asize, isn;
24125042aa92SStefano Zampini   const PetscInt        *idx;
24135042aa92SStefano Zampini   PetscMPIInt            size;
24145042aa92SStefano Zampini   char                   lmattype[64];
24155042aa92SStefano Zampini   Mat                    dA, lA;
24165042aa92SStefano Zampini   IS                     is;
24175042aa92SStefano Zampini 
24185042aa92SStefano Zampini   PetscFunctionBegin;
24195042aa92SStefano Zampini   PetscCheckSameComm(A, 1, viewer, 2);
24205042aa92SStefano Zampini   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
24215042aa92SStefano Zampini   PetscCheck(isbinary, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Invalid viewer of type %s", ((PetscObject)viewer)->type_name);
24225042aa92SStefano Zampini 
24235042aa92SStefano Zampini   PetscCall(PetscViewerBinaryRead(viewer, tr, PETSC_STATIC_ARRAY_LENGTH(tr), NULL, PETSC_INT));
24245042aa92SStefano Zampini   PetscCheck(tr[0] == MAT_FILE_CLASSID, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a matrix next in file");
24255042aa92SStefano Zampini   PetscCheck(tr[1] >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a IS matrix next in file");
24265042aa92SStefano Zampini   PetscCheck(tr[2] >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a IS matrix next in file");
24275042aa92SStefano Zampini   PetscCheck(tr[3] < 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a IS matrix next in file");
24285042aa92SStefano Zampini   PetscCheck(tr[4] == 0 || tr[4] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a IS matrix next in file");
24295042aa92SStefano Zampini   PetscCheck(tr[5] == 0 || tr[5] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a IS matrix next in file");
24305042aa92SStefano Zampini   M     = tr[1];
24315042aa92SStefano Zampini   N     = tr[2];
24325042aa92SStefano Zampini   Asize = -tr[3];
24335042aa92SStefano Zampini   samel = (PetscBool)tr[4];
24345042aa92SStefano Zampini   allow = (PetscBool)tr[5];
24355042aa92SStefano Zampini   PetscCall(PetscViewerBinaryRead(viewer, lmattype, sizeof(lmattype), NULL, PETSC_CHAR));
24365042aa92SStefano Zampini 
24375042aa92SStefano Zampini   /* if we are loading from a larger set of processes, allow repeated entries */
24385042aa92SStefano Zampini   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size));
24395042aa92SStefano Zampini   if (Asize > size) allow = PETSC_TRUE;
24405042aa92SStefano Zampini 
24415042aa92SStefano Zampini   /* set global sizes if not set already */
24425042aa92SStefano Zampini   if (A->rmap->N < 0) A->rmap->N = M;
24435042aa92SStefano Zampini   if (A->cmap->N < 0) A->cmap->N = N;
24445042aa92SStefano Zampini   PetscCall(PetscLayoutSetUp(A->rmap));
24455042aa92SStefano Zampini   PetscCall(PetscLayoutSetUp(A->cmap));
24465042aa92SStefano Zampini   PetscCheck(M == A->rmap->N, comm, PETSC_ERR_ARG_SIZ, "Matrix rows should be %" PetscInt_FMT ", found %" PetscInt_FMT, M, A->rmap->N);
24475042aa92SStefano Zampini   PetscCheck(N == A->cmap->N, comm, PETSC_ERR_ARG_SIZ, "Matrix columns should be %" PetscInt_FMT ", found %" PetscInt_FMT, N, A->cmap->N);
24485042aa92SStefano Zampini 
24495042aa92SStefano Zampini   /* load l2g maps */
24505042aa92SStefano Zampini   PetscCall(ISLocalToGlobalMappingCreate(comm, 0, 0, NULL, PETSC_USE_POINTER, &rmap));
24515042aa92SStefano Zampini   PetscCall(ISLocalToGlobalMappingLoad(rmap, viewer));
24525042aa92SStefano Zampini   if (!samel) {
24535042aa92SStefano Zampini     PetscCall(ISLocalToGlobalMappingCreate(comm, 0, 0, NULL, PETSC_USE_POINTER, &cmap));
24545042aa92SStefano Zampini     PetscCall(ISLocalToGlobalMappingLoad(cmap, viewer));
24555042aa92SStefano Zampini   } else {
24565042aa92SStefano Zampini     PetscCall(PetscObjectReference((PetscObject)rmap));
24575042aa92SStefano Zampini     cmap = rmap;
24585042aa92SStefano Zampini   }
24595042aa92SStefano Zampini 
24605042aa92SStefano Zampini   /* load sizes of local matrices */
24615042aa92SStefano Zampini   PetscCall(ISCreate(comm, &is));
24625042aa92SStefano Zampini   PetscCall(ISSetType(is, ISGENERAL));
24635042aa92SStefano Zampini   PetscCall(ISLoad(is, viewer));
24645042aa92SStefano Zampini   PetscCall(ISGetLocalSize(is, &isn));
24655042aa92SStefano Zampini   PetscCall(ISGetIndices(is, &idx));
24665042aa92SStefano Zampini   nr = 0;
24675042aa92SStefano Zampini   for (PetscInt i = 0; i < isn; i++) nr += idx[i];
24685042aa92SStefano Zampini   PetscCall(ISRestoreIndices(is, &idx));
24695042aa92SStefano Zampini   PetscCall(ISDestroy(&is));
24705042aa92SStefano Zampini   PetscCall(ISCreate(comm, &is));
24715042aa92SStefano Zampini   PetscCall(ISSetType(is, ISGENERAL));
24725042aa92SStefano Zampini   PetscCall(ISLoad(is, viewer));
24735042aa92SStefano Zampini   PetscCall(ISGetLocalSize(is, &isn));
24745042aa92SStefano Zampini   PetscCall(ISGetIndices(is, &idx));
24755042aa92SStefano Zampini   nc = 0;
24765042aa92SStefano Zampini   for (PetscInt i = 0; i < isn; i++) nc += idx[i];
24775042aa92SStefano Zampini   PetscCall(ISRestoreIndices(is, &idx));
24785042aa92SStefano Zampini   PetscCall(ISDestroy(&is));
24795042aa92SStefano Zampini 
24805042aa92SStefano Zampini   /* now load the unassembled operator */
24815042aa92SStefano Zampini   PetscCall(MatCreate(comm, &dA));
24825042aa92SStefano Zampini   PetscCall(MatSetType(dA, MATMPIAIJ));
24835042aa92SStefano Zampini   PetscCall(MatSetSizes(dA, nr, nc, PETSC_DECIDE, PETSC_DECIDE));
24845042aa92SStefano Zampini   PetscCall(MatLoad(dA, viewer));
24855042aa92SStefano Zampini   PetscCall(MatMPIAIJGetSeqAIJ(dA, &lA, NULL, NULL));
24865042aa92SStefano Zampini   PetscCall(PetscObjectReference((PetscObject)lA));
24875042aa92SStefano Zampini   PetscCall(MatDestroy(&dA));
24885042aa92SStefano Zampini 
24895042aa92SStefano Zampini   /* and convert to the desired format */
24905042aa92SStefano Zampini   PetscCall(PetscStrcmpAny(lmattype, &isbaij, MATSBAIJ, MATSEQSBAIJ, ""));
24915042aa92SStefano Zampini   if (isbaij) PetscCall(MatSetOption(lA, MAT_SYMMETRIC, PETSC_TRUE));
24925042aa92SStefano Zampini   PetscCall(MatConvert(lA, lmattype, MAT_INPLACE_MATRIX, &lA));
24935042aa92SStefano Zampini 
2494a3ef7f04SStefano Zampini   /* check if we actually have repeated entries */
2495a3ef7f04SStefano Zampini   if (allow) {
2496a3ef7f04SStefano Zampini     PetscBool rhas, chas, hasrepeated;
2497a3ef7f04SStefano Zampini 
2498a3ef7f04SStefano Zampini     PetscCall(ISLocalToGlobalMappingHasRepeatedLocal_Private(rmap, &rhas));
2499a3ef7f04SStefano Zampini     if (rmap != cmap) PetscCall(ISLocalToGlobalMappingHasRepeatedLocal_Private(cmap, &chas));
2500a3ef7f04SStefano Zampini     else chas = rhas;
2501a3ef7f04SStefano Zampini     hasrepeated = (PetscBool)(rhas || chas);
25025440e5dcSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &hasrepeated, 1, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A)));
2503a3ef7f04SStefano Zampini     if (!hasrepeated) allow = PETSC_FALSE;
2504a3ef7f04SStefano Zampini   }
2505a3ef7f04SStefano Zampini 
25065042aa92SStefano Zampini   /* assemble the MATIS object */
25075042aa92SStefano Zampini   PetscCall(MatISSetAllowRepeated(A, allow));
25085042aa92SStefano Zampini   PetscCall(MatSetLocalToGlobalMapping(A, rmap, cmap));
25095042aa92SStefano Zampini   PetscCall(MatISSetLocalMat(A, lA));
25105042aa92SStefano Zampini   PetscCall(MatDestroy(&lA));
25115042aa92SStefano Zampini   PetscCall(ISLocalToGlobalMappingDestroy(&rmap));
25125042aa92SStefano Zampini   PetscCall(ISLocalToGlobalMappingDestroy(&cmap));
25135042aa92SStefano Zampini   PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
25145042aa92SStefano Zampini   PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
25153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2516b4319ba4SBarry Smith }
2517b4319ba4SBarry Smith 
MatInvertBlockDiagonal_IS(Mat mat,const PetscScalar ** values)2518d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatInvertBlockDiagonal_IS(Mat mat, const PetscScalar **values)
2519d71ae5a4SJacob Faibussowitsch {
2520b89f26deSStefano Zampini   Mat_IS            *is = (Mat_IS *)mat->data;
2521b89f26deSStefano Zampini   MPI_Datatype       nodeType;
2522b89f26deSStefano Zampini   const PetscScalar *lv;
2523b89f26deSStefano Zampini   PetscInt           bs;
2524835f2295SStefano Zampini   PetscMPIInt        mbs;
2525b89f26deSStefano Zampini 
2526b89f26deSStefano Zampini   PetscFunctionBegin;
25279566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(mat, &bs));
25289566063dSJacob Faibussowitsch   PetscCall(MatSetBlockSize(is->A, bs));
25299566063dSJacob Faibussowitsch   PetscCall(MatInvertBlockDiagonal(is->A, &lv));
253048a46eb9SPierre Jolivet   if (!is->bdiag) PetscCall(PetscMalloc1(bs * mat->rmap->n, &is->bdiag));
2531835f2295SStefano Zampini   PetscCall(PetscMPIIntCast(bs, &mbs));
2532835f2295SStefano Zampini   PetscCallMPI(MPI_Type_contiguous(mbs, MPIU_SCALAR, &nodeType));
25339566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Type_commit(&nodeType));
25349566063dSJacob Faibussowitsch   PetscCall(PetscSFReduceBegin(is->sf, nodeType, lv, is->bdiag, MPI_REPLACE));
25359566063dSJacob Faibussowitsch   PetscCall(PetscSFReduceEnd(is->sf, nodeType, lv, is->bdiag, MPI_REPLACE));
25369566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Type_free(&nodeType));
2537b89f26deSStefano Zampini   if (values) *values = is->bdiag;
25383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2539b89f26deSStefano Zampini }
2540b89f26deSStefano Zampini 
MatISSetUpScatters_Private(Mat A)2541d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISSetUpScatters_Private(Mat A)
2542d71ae5a4SJacob Faibussowitsch {
2543e176bc59SStefano Zampini   Vec             cglobal, rglobal;
25448546b261SStefano Zampini   IS              from;
25458546b261SStefano Zampini   Mat_IS         *is = (Mat_IS *)A->data;
2546b89f26deSStefano Zampini   PetscScalar     sum;
25478546b261SStefano Zampini   const PetscInt *garray;
25488546b261SStefano Zampini   PetscInt        nr, rbs, nc, cbs;
2549e432b41dSStefano Zampini   VecType         rtype;
2550b4319ba4SBarry Smith 
2551b4319ba4SBarry Smith   PetscFunctionBegin;
25529566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(is->rmapping, &nr));
25539566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(is->rmapping, &rbs));
25549566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(is->cmapping, &nc));
25559566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(is->cmapping, &cbs));
25569566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&is->x));
25579566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&is->y));
25589566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&is->counter));
25599566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&is->rctx));
25609566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&is->cctx));
25619566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(is->A, &is->x, &is->y));
25629566063dSJacob Faibussowitsch   PetscCall(VecBindToCPU(is->y, PETSC_TRUE));
25639566063dSJacob Faibussowitsch   PetscCall(VecGetRootType_Private(is->y, &rtype));
25649566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->defaultvectype));
25659566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(rtype, &A->defaultvectype));
25669566063dSJacob Faibussowitsch   PetscCall(MatCreateVecs(A, &cglobal, &rglobal));
25679566063dSJacob Faibussowitsch   PetscCall(VecBindToCPU(rglobal, PETSC_TRUE));
25689566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->rmapping, &garray));
25699566063dSJacob Faibussowitsch   PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), rbs, nr / rbs, garray, PETSC_USE_POINTER, &from));
25709566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(rglobal, from, is->y, NULL, &is->rctx));
25719566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->rmapping, &garray));
25729566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&from));
2573e432b41dSStefano Zampini   if (is->rmapping != is->cmapping) {
25749566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->cmapping, &garray));
25759566063dSJacob Faibussowitsch     PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), cbs, nc / cbs, garray, PETSC_USE_POINTER, &from));
25769566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(cglobal, from, is->x, NULL, &is->cctx));
25779566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->cmapping, &garray));
25789566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&from));
25798546b261SStefano Zampini   } else {
25809566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)is->rctx));
25818546b261SStefano Zampini     is->cctx = is->rctx;
25828546b261SStefano Zampini   }
25839566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&cglobal));
2584b89f26deSStefano Zampini 
25858546b261SStefano Zampini   /* interface counter vector (local) */
25869566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(is->y, &is->counter));
25879566063dSJacob Faibussowitsch   PetscCall(VecBindToCPU(is->counter, PETSC_TRUE));
25889566063dSJacob Faibussowitsch   PetscCall(VecSet(is->y, 1.));
25899566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(is->rctx, is->y, rglobal, ADD_VALUES, SCATTER_REVERSE));
25909566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(is->rctx, is->y, rglobal, ADD_VALUES, SCATTER_REVERSE));
25919566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(is->rctx, rglobal, is->counter, INSERT_VALUES, SCATTER_FORWARD));
25929566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(is->rctx, rglobal, is->counter, INSERT_VALUES, SCATTER_FORWARD));
25939566063dSJacob Faibussowitsch   PetscCall(VecBindToCPU(is->y, PETSC_FALSE));
25949566063dSJacob Faibussowitsch   PetscCall(VecBindToCPU(is->counter, PETSC_FALSE));
2595b89f26deSStefano Zampini 
2596b89f26deSStefano Zampini   /* special functions for block-diagonal matrices */
25979566063dSJacob Faibussowitsch   PetscCall(VecSum(rglobal, &sum));
2598b89f26deSStefano Zampini   A->ops->invertblockdiagonal = NULL;
2599e432b41dSStefano Zampini   if ((PetscInt)(PetscRealPart(sum)) == A->rmap->N && A->rmap->N == A->cmap->N && is->rmapping == is->cmapping) A->ops->invertblockdiagonal = MatInvertBlockDiagonal_IS;
26009566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&rglobal));
2601b0cc1f67SStefano Zampini 
2602b0cc1f67SStefano Zampini   /* setup SF for general purpose shared indices based communications */
26039566063dSJacob Faibussowitsch   PetscCall(MatISSetUpSF_IS(A));
26043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
26058546b261SStefano Zampini }
26068546b261SStefano Zampini 
MatISFilterL2GMap(Mat A,ISLocalToGlobalMapping map,ISLocalToGlobalMapping * nmap,ISLocalToGlobalMapping * lmap)2607d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISFilterL2GMap(Mat A, ISLocalToGlobalMapping map, ISLocalToGlobalMapping *nmap, ISLocalToGlobalMapping *lmap)
2608d71ae5a4SJacob Faibussowitsch {
26094f58015eSStefano Zampini   Mat_IS                    *matis = (Mat_IS *)A->data;
2610e432b41dSStefano Zampini   IS                         is;
2611e432b41dSStefano Zampini   ISLocalToGlobalMappingType l2gtype;
2612e432b41dSStefano Zampini   const PetscInt            *idxs;
2613e432b41dSStefano Zampini   PetscHSetI                 ht;
2614e432b41dSStefano Zampini   PetscInt                  *nidxs;
2615e432b41dSStefano Zampini   PetscInt                   i, n, bs, c;
2616e432b41dSStefano Zampini   PetscBool                  flg[] = {PETSC_FALSE, PETSC_FALSE};
2617e432b41dSStefano Zampini 
2618e432b41dSStefano Zampini   PetscFunctionBegin;
26199566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(map, &n));
26209566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(map, &bs));
26219566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockIndices(map, &idxs));
26229566063dSJacob Faibussowitsch   PetscCall(PetscHSetICreate(&ht));
26239566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n / bs, &nidxs));
2624e432b41dSStefano Zampini   for (i = 0, c = 0; i < n / bs; i++) {
26254f58015eSStefano Zampini     PetscBool missing = PETSC_TRUE;
26269371c9d4SSatish Balay     if (idxs[i] < 0) {
26279371c9d4SSatish Balay       flg[0] = PETSC_TRUE;
26289371c9d4SSatish Balay       continue;
26299371c9d4SSatish Balay     }
26304f58015eSStefano Zampini     if (!matis->allow_repeated) PetscCall(PetscHSetIQueryAdd(ht, idxs[i], &missing));
2631e432b41dSStefano Zampini     if (!missing) flg[1] = PETSC_TRUE;
2632e432b41dSStefano Zampini     else nidxs[c++] = idxs[i];
2633e432b41dSStefano Zampini   }
26349566063dSJacob Faibussowitsch   PetscCall(PetscHSetIDestroy(&ht));
26355440e5dcSBarry Smith   PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, flg, 2, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A)));
2636e432b41dSStefano Zampini   if (!flg[0] && !flg[1]) { /* Entries are all non negative and unique */
2637e432b41dSStefano Zampini     *nmap = NULL;
2638e432b41dSStefano Zampini     *lmap = NULL;
26399566063dSJacob Faibussowitsch     PetscCall(PetscFree(nidxs));
26409566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(map, &idxs));
26413ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
2642e432b41dSStefano Zampini   }
2643e432b41dSStefano Zampini 
26444f58015eSStefano Zampini   /* New l2g map without negative indices (and repeated indices if not allowed) */
26459566063dSJacob Faibussowitsch   PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), bs, c, nidxs, PETSC_USE_POINTER, &is));
26469566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(is, nmap));
26479566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
26489566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetType(map, &l2gtype));
26499566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingSetType(*nmap, l2gtype));
2650e432b41dSStefano Zampini 
26514f58015eSStefano Zampini   /* New local l2g map for repeated indices if not allowed */
26529566063dSJacob Faibussowitsch   PetscCall(ISGlobalToLocalMappingApplyBlock(*nmap, IS_GTOLM_MASK, n / bs, idxs, NULL, nidxs));
26539566063dSJacob Faibussowitsch   PetscCall(ISCreateBlock(PETSC_COMM_SELF, bs, n / bs, nidxs, PETSC_USE_POINTER, &is));
26549566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(is, lmap));
26559566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
26569566063dSJacob Faibussowitsch   PetscCall(PetscFree(nidxs));
26579566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(map, &idxs));
26583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2659e432b41dSStefano Zampini }
2660e432b41dSStefano Zampini 
MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)2661d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2662d71ae5a4SJacob Faibussowitsch {
26638546b261SStefano Zampini   Mat_IS                *is            = (Mat_IS *)A->data;
2664e432b41dSStefano Zampini   ISLocalToGlobalMapping localrmapping = NULL, localcmapping = NULL;
2665e432b41dSStefano Zampini   PetscInt               nr, rbs, nc, cbs;
26664f58015eSStefano Zampini   PetscBool              cong, freem[] = {PETSC_FALSE, PETSC_FALSE};
26678546b261SStefano Zampini 
26688546b261SStefano Zampini   PetscFunctionBegin;
2669fc989267SStefano Zampini   if (rmapping) PetscCheckSameComm(A, 1, rmapping, 2);
2670fc989267SStefano Zampini   if (cmapping) PetscCheckSameComm(A, 1, cmapping, 3);
2671e432b41dSStefano Zampini 
26729566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&is->rmapping));
26739566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&is->cmapping));
26749566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
26759566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
26769566063dSJacob Faibussowitsch   PetscCall(MatHasCongruentLayouts(A, &cong));
2677e432b41dSStefano Zampini 
2678fc989267SStefano Zampini   /* If NULL, local space matches global space */
2679fc989267SStefano Zampini   if (!rmapping) {
2680fc989267SStefano Zampini     IS is;
2681fc989267SStefano Zampini 
26829566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), A->rmap->N, 0, 1, &is));
26839566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is, &rmapping));
268458b7e2c1SStefano Zampini     PetscCall(ISLocalToGlobalMappingSetBlockSize(rmapping, A->rmap->bs));
26859566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
2686e432b41dSStefano Zampini     freem[0] = PETSC_TRUE;
2687e432b41dSStefano Zampini     if (!cmapping && cong && A->rmap->bs == A->cmap->bs) cmapping = rmapping;
2688e432b41dSStefano Zampini   } else if (!is->islocalref) { /* check if the l2g map has negative or repeated entries */
26899566063dSJacob Faibussowitsch     PetscCall(MatISFilterL2GMap(A, rmapping, &is->rmapping, &localrmapping));
2690e432b41dSStefano Zampini     if (rmapping == cmapping) {
26919566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)is->rmapping));
2692e432b41dSStefano Zampini       is->cmapping = is->rmapping;
26939566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)localrmapping));
2694e432b41dSStefano Zampini       localcmapping = localrmapping;
2695fc989267SStefano Zampini     }
2696fc989267SStefano Zampini   }
2697fc989267SStefano Zampini   if (!cmapping) {
2698fc989267SStefano Zampini     IS is;
2699fc989267SStefano Zampini 
27009566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), A->cmap->N, 0, 1, &is));
27019566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is, &cmapping));
270258b7e2c1SStefano Zampini     PetscCall(ISLocalToGlobalMappingSetBlockSize(cmapping, A->cmap->bs));
27039566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
2704e432b41dSStefano Zampini     freem[1] = PETSC_TRUE;
2705e432b41dSStefano Zampini   } else if (cmapping != rmapping && !is->islocalref) { /* check if the l2g map has negative or repeated entries */
27069566063dSJacob Faibussowitsch     PetscCall(MatISFilterL2GMap(A, cmapping, &is->cmapping, &localcmapping));
2707e432b41dSStefano Zampini   }
2708e432b41dSStefano Zampini   if (!is->rmapping) {
27099566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)rmapping));
2710e432b41dSStefano Zampini     is->rmapping = rmapping;
2711e432b41dSStefano Zampini   }
2712e432b41dSStefano Zampini   if (!is->cmapping) {
27139566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)cmapping));
2714e432b41dSStefano Zampini     is->cmapping = cmapping;
2715fc989267SStefano Zampini   }
2716fc989267SStefano Zampini 
2717fc989267SStefano Zampini   /* Clean up */
27184f58015eSStefano Zampini   is->lnnzstate = 0;
27194f58015eSStefano Zampini   PetscCall(MatDestroy(&is->dA));
27204f58015eSStefano Zampini   PetscCall(MatDestroy(&is->assembledA));
27219566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&is->A));
2722872cf891SStefano Zampini   if (is->csf != is->sf) {
27239566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&is->csf));
27249566063dSJacob Faibussowitsch     PetscCall(PetscFree2(is->csf_rootdata, is->csf_leafdata));
2725f03112d0SStefano Zampini   } else is->csf = NULL;
27269566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&is->sf));
27279566063dSJacob Faibussowitsch   PetscCall(PetscFree2(is->sf_rootdata, is->sf_leafdata));
27289566063dSJacob Faibussowitsch   PetscCall(PetscFree(is->bdiag));
27293bbff08aSStefano Zampini 
2730fc989267SStefano Zampini   /* check if the two mappings are actually the same for square matrices since MATIS has some optimization for this case
2731fc989267SStefano Zampini      (DOLFIN passes 2 different objects) */
27329566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(is->rmapping, &nr));
27339566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(is->rmapping, &rbs));
27349566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(is->cmapping, &nc));
27359566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetBlockSize(is->cmapping, &cbs));
2736e432b41dSStefano Zampini   if (is->rmapping != is->cmapping && cong) {
2737e432b41dSStefano Zampini     PetscBool same = PETSC_FALSE;
27386625354bSStefano Zampini     if (nr == nc && cbs == rbs) {
27396625354bSStefano Zampini       const PetscInt *idxs1, *idxs2;
27406625354bSStefano Zampini 
27419566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->rmapping, &idxs1));
27429566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->cmapping, &idxs2));
27439566063dSJacob Faibussowitsch       PetscCall(PetscArraycmp(idxs1, idxs2, nr / rbs, &same));
27449566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->rmapping, &idxs1));
27459566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->cmapping, &idxs2));
27466625354bSStefano Zampini     }
27475440e5dcSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &same, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A)));
2748e432b41dSStefano Zampini     if (same) {
27499566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingDestroy(&is->cmapping));
27509566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)is->rmapping));
2751e432b41dSStefano Zampini       is->cmapping = is->rmapping;
2752e432b41dSStefano Zampini     }
27536625354bSStefano Zampini   }
27549566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(A->rmap, rbs));
27559566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(A->cmap, cbs));
2756e432b41dSStefano Zampini   /* Pass the user defined maps to the layout */
27579566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetISLocalToGlobalMapping(A->rmap, rmapping));
27589566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetISLocalToGlobalMapping(A->cmap, cmapping));
27599566063dSJacob Faibussowitsch   if (freem[0]) PetscCall(ISLocalToGlobalMappingDestroy(&rmapping));
27609566063dSJacob Faibussowitsch   if (freem[1]) PetscCall(ISLocalToGlobalMappingDestroy(&cmapping));
27616625354bSStefano Zampini 
276239b6f3f9SStefano Zampini   if (!is->islocalref) {
27636625354bSStefano Zampini     /* Create the local matrix A */
27649566063dSJacob Faibussowitsch     PetscCall(MatCreate(PETSC_COMM_SELF, &is->A));
27659566063dSJacob Faibussowitsch     PetscCall(MatSetType(is->A, is->lmattype));
27669566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(is->A, nr, nc, nr, nc));
27679566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSizes(is->A, rbs, cbs));
27689566063dSJacob Faibussowitsch     PetscCall(MatSetOptionsPrefix(is->A, "is_"));
27699566063dSJacob Faibussowitsch     PetscCall(MatAppendOptionsPrefix(is->A, ((PetscObject)A)->prefix));
27709566063dSJacob Faibussowitsch     PetscCall(PetscLayoutSetUp(is->A->rmap));
27719566063dSJacob Faibussowitsch     PetscCall(PetscLayoutSetUp(is->A->cmap));
27729566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(is->A, localrmapping, localcmapping));
27739566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&localrmapping));
27749566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&localcmapping));
2775fc989267SStefano Zampini     /* setup scatters and local vectors for MatMult */
277639b6f3f9SStefano Zampini     PetscCall(MatISSetUpScatters_Private(A));
277739b6f3f9SStefano Zampini   }
2778fc989267SStefano Zampini   A->preallocated = PETSC_TRUE;
27793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2780fc989267SStefano Zampini }
2781fc989267SStefano Zampini 
MatSetUp_IS(Mat A)2782d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetUp_IS(Mat A)
2783d71ae5a4SJacob Faibussowitsch {
278429f134acSStefano Zampini   Mat_IS                *is = (Mat_IS *)A->data;
2785fc989267SStefano Zampini   ISLocalToGlobalMapping rmap, cmap;
2786fc989267SStefano Zampini 
2787fc989267SStefano Zampini   PetscFunctionBegin;
278829f134acSStefano Zampini   if (!is->sf) {
27899566063dSJacob Faibussowitsch     PetscCall(MatGetLocalToGlobalMapping(A, &rmap, &cmap));
279029f134acSStefano Zampini     PetscCall(MatSetLocalToGlobalMapping(A, rmap, cmap));
279129f134acSStefano Zampini   }
27923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2793b4319ba4SBarry Smith }
2794b4319ba4SBarry Smith 
MatSetValues_IS(Mat mat,PetscInt m,const PetscInt * rows,PetscInt n,const PetscInt * cols,const PetscScalar * values,InsertMode addv)2795d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv)
2796d71ae5a4SJacob Faibussowitsch {
27972e74eeadSLisandro Dalcin   Mat_IS  *is = (Mat_IS *)mat->data;
2798076fee34SStefano Zampini   PetscInt buf[2 * MATIS_MAX_ENTRIES_INSERTION], *rows_l = NULL, *cols_l = NULL;
27992e74eeadSLisandro Dalcin 
28002e74eeadSLisandro Dalcin   PetscFunctionBegin;
2801076fee34SStefano Zampini   IndexSpaceGet(buf, m, n, rows_l, cols_l);
28029566063dSJacob Faibussowitsch   PetscCall(ISGlobalToLocalMappingApply(is->rmapping, IS_GTOLM_MASK, m, rows, &m, rows_l));
2803e432b41dSStefano Zampini   if (m != n || rows != cols || is->cmapping != is->rmapping) {
28049566063dSJacob Faibussowitsch     PetscCall(ISGlobalToLocalMappingApply(is->cmapping, IS_GTOLM_MASK, n, cols, &n, cols_l));
28059566063dSJacob Faibussowitsch     PetscCall(MatSetValues(is->A, m, rows_l, n, cols_l, values, addv));
2806e432b41dSStefano Zampini   } else {
28079566063dSJacob Faibussowitsch     PetscCall(MatSetValues(is->A, m, rows_l, m, rows_l, values, addv));
2808e432b41dSStefano Zampini   }
2809076fee34SStefano Zampini   IndexSpaceRestore(buf, m, n, rows_l, cols_l);
28103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28112e74eeadSLisandro Dalcin }
28122e74eeadSLisandro Dalcin 
MatSetValuesBlocked_IS(Mat mat,PetscInt m,const PetscInt * rows,PetscInt n,const PetscInt * cols,const PetscScalar * values,InsertMode addv)2813d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv)
2814d71ae5a4SJacob Faibussowitsch {
281597563a80SStefano Zampini   Mat_IS  *is = (Mat_IS *)mat->data;
2816076fee34SStefano Zampini   PetscInt buf[2 * MATIS_MAX_ENTRIES_INSERTION], *rows_l = NULL, *cols_l = NULL;
281797563a80SStefano Zampini 
281897563a80SStefano Zampini   PetscFunctionBegin;
2819076fee34SStefano Zampini   IndexSpaceGet(buf, m, n, rows_l, cols_l);
28209566063dSJacob Faibussowitsch   PetscCall(ISGlobalToLocalMappingApplyBlock(is->rmapping, IS_GTOLM_MASK, m, rows, &m, rows_l));
2821e432b41dSStefano Zampini   if (m != n || rows != cols || is->cmapping != is->rmapping) {
282284a95373SStefano Zampini     PetscCall(ISGlobalToLocalMappingApplyBlock(is->cmapping, IS_GTOLM_MASK, n, cols, &n, cols_l));
28239566063dSJacob Faibussowitsch     PetscCall(MatSetValuesBlocked(is->A, m, rows_l, n, cols_l, values, addv));
2824e432b41dSStefano Zampini   } else {
282584a95373SStefano Zampini     PetscCall(MatSetValuesBlocked(is->A, m, rows_l, m, rows_l, values, addv));
2826e432b41dSStefano Zampini   }
2827076fee34SStefano Zampini   IndexSpaceRestore(buf, m, n, rows_l, cols_l);
28283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
282997563a80SStefano Zampini }
283097563a80SStefano Zampini 
MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt * rows,PetscInt n,const PetscInt * cols,const PetscScalar * values,InsertMode addv)2831d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesLocal_IS(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv)
2832d71ae5a4SJacob Faibussowitsch {
2833b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS *)A->data;
2834b4319ba4SBarry Smith 
2835b4319ba4SBarry Smith   PetscFunctionBegin;
2836e432b41dSStefano Zampini   if (is->A->rmap->mapping || is->A->cmap->mapping) {
28379566063dSJacob Faibussowitsch     PetscCall(MatSetValuesLocal(is->A, m, rows, n, cols, values, addv));
2838872cf891SStefano Zampini   } else {
28399566063dSJacob Faibussowitsch     PetscCall(MatSetValues(is->A, m, rows, n, cols, values, addv));
2840872cf891SStefano Zampini   }
28413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2842b4319ba4SBarry Smith }
2843b4319ba4SBarry Smith 
MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt * rows,PetscInt n,const PetscInt * cols,const PetscScalar * values,InsertMode addv)2844d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv)
2845d71ae5a4SJacob Faibussowitsch {
2846f0006bf2SLisandro Dalcin   Mat_IS *is = (Mat_IS *)A->data;
2847f0006bf2SLisandro Dalcin 
2848f0006bf2SLisandro Dalcin   PetscFunctionBegin;
2849e432b41dSStefano Zampini   if (is->A->rmap->mapping || is->A->cmap->mapping) {
28509566063dSJacob Faibussowitsch     PetscCall(MatSetValuesBlockedLocal(is->A, m, rows, n, cols, values, addv));
2851b4f971dfSStefano Zampini   } else {
28529566063dSJacob Faibussowitsch     PetscCall(MatSetValuesBlocked(is->A, m, rows, n, cols, values, addv));
2853b4f971dfSStefano Zampini   }
28543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2855f0006bf2SLisandro Dalcin }
2856f0006bf2SLisandro Dalcin 
MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)2857d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, PetscBool columns)
2858d71ae5a4SJacob Faibussowitsch {
2859f0ae7da4SStefano Zampini   Mat_IS *is = (Mat_IS *)A->data;
2860f0ae7da4SStefano Zampini 
2861f0ae7da4SStefano Zampini   PetscFunctionBegin;
28620d2733adSStefano Zampini   if (!n) PetscFunctionReturn(PETSC_SUCCESS);
2863f0ae7da4SStefano Zampini   is->pure_neumann = PETSC_FALSE;
2864f0ae7da4SStefano Zampini 
2865f0ae7da4SStefano Zampini   if (columns) {
28669566063dSJacob Faibussowitsch     PetscCall(MatZeroRowsColumns(is->A, n, rows, diag, NULL, NULL));
2867f0ae7da4SStefano Zampini   } else {
28689566063dSJacob Faibussowitsch     PetscCall(MatZeroRows(is->A, n, rows, diag, NULL, NULL));
2869f0ae7da4SStefano Zampini   }
2870f0ae7da4SStefano Zampini   if (diag != 0.) {
2871f0ae7da4SStefano Zampini     const PetscScalar *array;
28720d2733adSStefano Zampini 
28739566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(is->counter, &array));
28740d2733adSStefano Zampini     for (PetscInt i = 0; i < n; i++) PetscCall(MatSetValue(is->A, rows[i], rows[i], diag / (array[rows[i]]), INSERT_VALUES));
28759566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(is->counter, &array));
28769566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(is->A, MAT_FINAL_ASSEMBLY));
28779566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(is->A, MAT_FINAL_ASSEMBLY));
2878f0ae7da4SStefano Zampini   }
28793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2880f0ae7da4SStefano Zampini }
2881f0ae7da4SStefano Zampini 
MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)2882d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, Vec x, Vec b, PetscBool columns)
2883d71ae5a4SJacob Faibussowitsch {
28846e520ac8SStefano Zampini   Mat_IS   *matis = (Mat_IS *)A->data;
28850d2733adSStefano Zampini   PetscInt  nr, nl, len;
28860d2733adSStefano Zampini   PetscInt *lrows = NULL;
28872e74eeadSLisandro Dalcin 
28882e74eeadSLisandro Dalcin   PetscFunctionBegin;
2889cf9c20a2SJed Brown   if (PetscUnlikelyDebug(columns || diag != 0. || (x && b))) {
2890f0ae7da4SStefano Zampini     PetscBool cong;
289126b0207aSStefano Zampini 
28929566063dSJacob Faibussowitsch     PetscCall(PetscLayoutCompare(A->rmap, A->cmap, &cong));
289326b0207aSStefano Zampini     cong = (PetscBool)(cong && matis->sf == matis->csf);
289408401ef6SPierre 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");
2895aed4548fSBarry 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");
2896aed4548fSBarry 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");
2897f0ae7da4SStefano Zampini   }
28980d2733adSStefano Zampini   PetscCall(MatGetSize(matis->A, &nl, NULL));
28996e520ac8SStefano Zampini   /* get locally owned rows */
29009566063dSJacob Faibussowitsch   PetscCall(PetscLayoutMapLocal(A->rmap, n, rows, &len, &lrows, NULL));
2901dd8e379bSPierre Jolivet   /* fix right-hand side if needed */
29026e520ac8SStefano Zampini   if (x && b) {
29036e520ac8SStefano Zampini     const PetscScalar *xx;
29046e520ac8SStefano Zampini     PetscScalar       *bb;
29056e520ac8SStefano Zampini 
29069566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
29079566063dSJacob Faibussowitsch     PetscCall(VecGetArray(b, &bb));
29080d2733adSStefano Zampini     for (PetscInt i = 0; i < len; ++i) bb[lrows[i]] = diag * xx[lrows[i]];
29099566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
29109566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(b, &bb));
29112e74eeadSLisandro Dalcin   }
29126e520ac8SStefano Zampini   /* get rows associated to the local matrices */
29139566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(matis->sf_leafdata, nl));
29149566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(matis->sf_rootdata, A->rmap->n));
29150d2733adSStefano Zampini   for (PetscInt i = 0; i < len; i++) matis->sf_rootdata[lrows[i]] = 1;
29169566063dSJacob Faibussowitsch   PetscCall(PetscFree(lrows));
29179566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE));
29189566063dSJacob Faibussowitsch   PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE));
29199566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nl, &lrows));
29200d2733adSStefano Zampini   nr = 0;
29210d2733adSStefano Zampini   for (PetscInt i = 0; i < nl; i++)
29229371c9d4SSatish Balay     if (matis->sf_leafdata[i]) lrows[nr++] = i;
29239566063dSJacob Faibussowitsch   PetscCall(MatISZeroRowsColumnsLocal_Private(A, nr, lrows, diag, columns));
29249566063dSJacob Faibussowitsch   PetscCall(PetscFree(lrows));
29253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29262e74eeadSLisandro Dalcin }
29272e74eeadSLisandro Dalcin 
MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)2928d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_IS(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
2929d71ae5a4SJacob Faibussowitsch {
2930b4319ba4SBarry Smith   PetscFunctionBegin;
29319566063dSJacob Faibussowitsch   PetscCall(MatZeroRowsColumns_Private_IS(A, n, rows, diag, x, b, PETSC_FALSE));
29323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2933f0ae7da4SStefano Zampini }
29342205254eSKarl Rupp 
MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)2935d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_IS(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
2936d71ae5a4SJacob Faibussowitsch {
2937f0ae7da4SStefano Zampini   PetscFunctionBegin;
29389566063dSJacob Faibussowitsch   PetscCall(MatZeroRowsColumns_Private_IS(A, n, rows, diag, x, b, PETSC_TRUE));
29393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2940b4319ba4SBarry Smith }
2941b4319ba4SBarry Smith 
MatAssemblyBegin_IS(Mat A,MatAssemblyType type)2942d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_IS(Mat A, MatAssemblyType type)
2943d71ae5a4SJacob Faibussowitsch {
2944b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS *)A->data;
2945b4319ba4SBarry Smith 
2946b4319ba4SBarry Smith   PetscFunctionBegin;
29479566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(is->A, type));
29483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2949b4319ba4SBarry Smith }
2950b4319ba4SBarry Smith 
MatAssemblyEnd_IS(Mat A,MatAssemblyType type)2951d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_IS(Mat A, MatAssemblyType type)
2952d71ae5a4SJacob Faibussowitsch {
2953b4319ba4SBarry Smith   Mat_IS   *is = (Mat_IS *)A->data;
2954d0dbe9f7SStefano Zampini   PetscBool lnnz;
2955b4319ba4SBarry Smith 
2956b4319ba4SBarry Smith   PetscFunctionBegin;
29579566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(is->A, type));
2958872cf891SStefano Zampini   /* fix for local empty rows/cols */
2959872cf891SStefano Zampini   if (is->locempty && type == MAT_FINAL_ASSEMBLY) {
2960872cf891SStefano Zampini     Mat                    newlA;
2961f03112d0SStefano Zampini     ISLocalToGlobalMapping rl2g, cl2g;
2962f03112d0SStefano Zampini     IS                     nzr, nzc;
2963f03112d0SStefano Zampini     PetscInt               nr, nc, nnzr, nnzc;
2964f03112d0SStefano Zampini     PetscBool              lnewl2g, newl2g;
2965872cf891SStefano Zampini 
29669566063dSJacob Faibussowitsch     PetscCall(MatGetSize(is->A, &nr, &nc));
29679566063dSJacob Faibussowitsch     PetscCall(MatFindNonzeroRowsOrCols_Basic(is->A, PETSC_FALSE, PETSC_SMALL, &nzr));
296848a46eb9SPierre Jolivet     if (!nzr) PetscCall(ISCreateStride(PetscObjectComm((PetscObject)is->A), nr, 0, 1, &nzr));
29699566063dSJacob Faibussowitsch     PetscCall(MatFindNonzeroRowsOrCols_Basic(is->A, PETSC_TRUE, PETSC_SMALL, &nzc));
297048a46eb9SPierre Jolivet     if (!nzc) PetscCall(ISCreateStride(PetscObjectComm((PetscObject)is->A), nc, 0, 1, &nzc));
29719566063dSJacob Faibussowitsch     PetscCall(ISGetSize(nzr, &nnzr));
29729566063dSJacob Faibussowitsch     PetscCall(ISGetSize(nzc, &nnzc));
2973e432b41dSStefano Zampini     if (nnzr != nr || nnzc != nc) { /* need new global l2g map */
2974f03112d0SStefano Zampini       lnewl2g = PETSC_TRUE;
29755440e5dcSBarry Smith       PetscCallMPI(MPIU_Allreduce(&lnewl2g, &newl2g, 1, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A)));
2976f03112d0SStefano Zampini 
2977872cf891SStefano Zampini       /* extract valid submatrix */
29789566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(is->A, nzr, nzc, MAT_INITIAL_MATRIX, &newlA));
2979f03112d0SStefano Zampini     } else { /* local matrix fully populated */
2980f03112d0SStefano Zampini       lnewl2g = PETSC_FALSE;
29815440e5dcSBarry Smith       PetscCallMPI(MPIU_Allreduce(&lnewl2g, &newl2g, 1, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A)));
29829566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)is->A));
2983f03112d0SStefano Zampini       newlA = is->A;
2984f03112d0SStefano Zampini     }
2985e432b41dSStefano Zampini 
2986f03112d0SStefano Zampini     /* attach new global l2g map if needed */
2987f03112d0SStefano Zampini     if (newl2g) {
2988e432b41dSStefano Zampini       IS              zr, zc;
2989e432b41dSStefano Zampini       const PetscInt *ridxs, *cidxs, *zridxs, *zcidxs;
2990e432b41dSStefano Zampini       PetscInt       *nidxs, i;
2991f03112d0SStefano Zampini 
29929566063dSJacob Faibussowitsch       PetscCall(ISComplement(nzr, 0, nr, &zr));
29939566063dSJacob Faibussowitsch       PetscCall(ISComplement(nzc, 0, nc, &zc));
29949566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(PetscMax(nr, nc), &nidxs));
29959566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingGetIndices(is->rmapping, &ridxs));
29969566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingGetIndices(is->cmapping, &cidxs));
29979566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(zr, &zridxs));
29989566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(zc, &zcidxs));
29999566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(zr, &nnzr));
30009566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(zc, &nnzc));
3001e432b41dSStefano Zampini 
30029566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(nidxs, ridxs, nr));
3003e432b41dSStefano Zampini       for (i = 0; i < nnzr; i++) nidxs[zridxs[i]] = -1;
30049566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A), 1, nr, nidxs, PETSC_COPY_VALUES, &rl2g));
30059566063dSJacob Faibussowitsch       PetscCall(PetscArraycpy(nidxs, cidxs, nc));
3006e432b41dSStefano Zampini       for (i = 0; i < nnzc; i++) nidxs[zcidxs[i]] = -1;
30079566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A), 1, nc, nidxs, PETSC_COPY_VALUES, &cl2g));
3008e432b41dSStefano Zampini 
30099566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(zr, &zridxs));
30109566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(zc, &zcidxs));
30119566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingRestoreIndices(is->rmapping, &ridxs));
30129566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingRestoreIndices(is->cmapping, &cidxs));
30139566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&nzr));
30149566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&nzc));
30159566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&zr));
30169566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&zc));
30179566063dSJacob Faibussowitsch       PetscCall(PetscFree(nidxs));
30189566063dSJacob Faibussowitsch       PetscCall(MatSetLocalToGlobalMapping(A, rl2g, cl2g));
30199566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
30209566063dSJacob Faibussowitsch       PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
3021f03112d0SStefano Zampini     }
30229566063dSJacob Faibussowitsch     PetscCall(MatISSetLocalMat(A, newlA));
30239566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&newlA));
30249566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&nzr));
30259566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&nzc));
3026872cf891SStefano Zampini     is->locempty = PETSC_FALSE;
3027f03112d0SStefano Zampini   }
3028d0dbe9f7SStefano Zampini   lnnz          = (PetscBool)(is->A->nonzerostate == is->lnnzstate);
3029d0dbe9f7SStefano Zampini   is->lnnzstate = is->A->nonzerostate;
30305440e5dcSBarry Smith   PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &lnnz, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A)));
30314f58015eSStefano Zampini   if (!lnnz) A->nonzerostate++;
30323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3033b4319ba4SBarry Smith }
3034b4319ba4SBarry Smith 
MatISGetLocalMat_IS(Mat mat,Mat * local)3035d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISGetLocalMat_IS(Mat mat, Mat *local)
3036d71ae5a4SJacob Faibussowitsch {
3037b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS *)mat->data;
3038b4319ba4SBarry Smith 
3039b4319ba4SBarry Smith   PetscFunctionBegin;
3040b4319ba4SBarry Smith   *local = is->A;
30413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3042b4319ba4SBarry Smith }
3043b4319ba4SBarry Smith 
MatISRestoreLocalMat_IS(Mat mat,Mat * local)3044d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat, Mat *local)
3045d71ae5a4SJacob Faibussowitsch {
30463b3b1effSJed Brown   PetscFunctionBegin;
30473b3b1effSJed Brown   *local = NULL;
30483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30493b3b1effSJed Brown }
30503b3b1effSJed Brown 
3051b4319ba4SBarry Smith /*@
305211a5261eSBarry Smith   MatISGetLocalMat - Gets the local matrix stored inside a `MATIS` matrix.
3053b4319ba4SBarry Smith 
30544f58015eSStefano Zampini   Not Collective.
30554f58015eSStefano Zampini 
3056b4319ba4SBarry Smith   Input Parameter:
3057b4319ba4SBarry Smith . mat - the matrix
3058b4319ba4SBarry Smith 
3059b4319ba4SBarry Smith   Output Parameter:
3060eb82efa4SStefano Zampini . local - the local matrix
3061b4319ba4SBarry Smith 
30624f58015eSStefano Zampini   Level: intermediate
3063b4319ba4SBarry Smith 
3064b4319ba4SBarry Smith   Notes:
3065b4319ba4SBarry Smith   This can be called if you have precomputed the nonzero structure of the
3066b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
306711a5261eSBarry Smith   of the `MatSetValues()` operation.
3068b4319ba4SBarry Smith 
306911a5261eSBarry Smith   Call `MatISRestoreLocalMat()` when finished with the local matrix.
307096a6f129SJed Brown 
30711cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatISRestoreLocalMat()`
3072b4319ba4SBarry Smith @*/
MatISGetLocalMat(Mat mat,Mat * local)3073d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISGetLocalMat(Mat mat, Mat *local)
3074d71ae5a4SJacob Faibussowitsch {
3075b4319ba4SBarry Smith   PetscFunctionBegin;
30760700a824SBarry Smith   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
30774f572ea9SToby Isaac   PetscAssertPointer(local, 2);
3078cac4c232SBarry Smith   PetscUseMethod(mat, "MatISGetLocalMat_C", (Mat, Mat *), (mat, local));
30793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3080b4319ba4SBarry Smith }
3081b4319ba4SBarry Smith 
30823b3b1effSJed Brown /*@
308311a5261eSBarry Smith   MatISRestoreLocalMat - Restores the local matrix obtained with `MatISGetLocalMat()`
30843b3b1effSJed Brown 
30854f58015eSStefano Zampini   Not Collective.
30864f58015eSStefano Zampini 
30872ef1f0ffSBarry Smith   Input Parameters:
30882ef1f0ffSBarry Smith + mat   - the matrix
30892ef1f0ffSBarry Smith - local - the local matrix
30903b3b1effSJed Brown 
30914f58015eSStefano Zampini   Level: intermediate
30923b3b1effSJed Brown 
30931cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatISGetLocalMat()`
30943b3b1effSJed Brown @*/
MatISRestoreLocalMat(Mat mat,Mat * local)3095d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISRestoreLocalMat(Mat mat, Mat *local)
3096d71ae5a4SJacob Faibussowitsch {
30973b3b1effSJed Brown   PetscFunctionBegin;
30983b3b1effSJed Brown   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
30994f572ea9SToby Isaac   PetscAssertPointer(local, 2);
3100cac4c232SBarry Smith   PetscUseMethod(mat, "MatISRestoreLocalMat_C", (Mat, Mat *), (mat, local));
31013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31023b3b1effSJed Brown }
31033b3b1effSJed Brown 
MatISSetLocalMatType_IS(Mat mat,MatType mtype)3104d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISSetLocalMatType_IS(Mat mat, MatType mtype)
3105d71ae5a4SJacob Faibussowitsch {
31068546b261SStefano Zampini   Mat_IS *is = (Mat_IS *)mat->data;
31078546b261SStefano Zampini 
31088546b261SStefano Zampini   PetscFunctionBegin;
31091baa6e33SBarry Smith   if (is->A) PetscCall(MatSetType(is->A, mtype));
31109566063dSJacob Faibussowitsch   PetscCall(PetscFree(is->lmattype));
31119566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(mtype, &is->lmattype));
31123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31138546b261SStefano Zampini }
31148546b261SStefano Zampini 
31155d83a8b1SBarry Smith /*@
311611a5261eSBarry Smith   MatISSetLocalMatType - Specifies the type of local matrix inside the `MATIS`
31178546b261SStefano Zampini 
31184f58015eSStefano Zampini   Logically Collective.
31194f58015eSStefano Zampini 
3120d8d19677SJose E. Roman   Input Parameters:
3121a2b725a8SWilliam Gropp + mat   - the matrix
3122a2b725a8SWilliam Gropp - mtype - the local matrix type
31238546b261SStefano Zampini 
31244f58015eSStefano Zampini   Level: intermediate
31258546b261SStefano Zampini 
31261cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatSetType()`, `MatType`
31278546b261SStefano Zampini @*/
MatISSetLocalMatType(Mat mat,MatType mtype)3128d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISSetLocalMatType(Mat mat, MatType mtype)
3129d71ae5a4SJacob Faibussowitsch {
31308546b261SStefano Zampini   PetscFunctionBegin;
31318546b261SStefano Zampini   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3132cac4c232SBarry Smith   PetscUseMethod(mat, "MatISSetLocalMatType_C", (Mat, MatType), (mat, mtype));
31333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31348546b261SStefano Zampini }
31358546b261SStefano Zampini 
MatISSetLocalMat_IS(Mat mat,Mat local)3136d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISSetLocalMat_IS(Mat mat, Mat local)
3137d71ae5a4SJacob Faibussowitsch {
31383b03a366Sstefano_zampini   Mat_IS   *is = (Mat_IS *)mat->data;
31393b03a366Sstefano_zampini   PetscInt  nrows, ncols, orows, ocols;
31408546b261SStefano Zampini   MatType   mtype, otype;
31418546b261SStefano Zampini   PetscBool sametype = PETSC_TRUE;
31423b03a366Sstefano_zampini 
31433b03a366Sstefano_zampini   PetscFunctionBegin;
3144e432b41dSStefano Zampini   if (is->A && !is->islocalref) {
31459566063dSJacob Faibussowitsch     PetscCall(MatGetSize(is->A, &orows, &ocols));
31469566063dSJacob Faibussowitsch     PetscCall(MatGetSize(local, &nrows, &ncols));
31475042aa92SStefano Zampini     PetscCheck(orows == nrows && ocols == ncols, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Local MATIS matrix should be of size %" PetscInt_FMT "x%" PetscInt_FMT " (passed a %" PetscInt_FMT "x%" PetscInt_FMT " matrix)", orows, ocols, nrows, ncols);
31489566063dSJacob Faibussowitsch     PetscCall(MatGetType(local, &mtype));
31499566063dSJacob Faibussowitsch     PetscCall(MatGetType(is->A, &otype));
31509566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(mtype, otype, &sametype));
31514e4c7dbeSStefano Zampini   }
31529566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)local));
31539566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&is->A));
31543b03a366Sstefano_zampini   is->A = local;
31559566063dSJacob Faibussowitsch   PetscCall(MatGetType(is->A, &mtype));
31569566063dSJacob Faibussowitsch   PetscCall(MatISSetLocalMatType(mat, mtype));
315748a46eb9SPierre Jolivet   if (!sametype && !is->islocalref) PetscCall(MatISSetUpScatters_Private(mat));
31584f58015eSStefano Zampini   is->lnnzstate = 0;
31593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31603b03a366Sstefano_zampini }
31613b03a366Sstefano_zampini 
31623b03a366Sstefano_zampini /*@
316311a5261eSBarry Smith   MatISSetLocalMat - Replace the local matrix stored inside a `MATIS` object.
31643b03a366Sstefano_zampini 
31654f58015eSStefano Zampini   Not Collective
31668546b261SStefano Zampini 
3167d8d19677SJose E. Roman   Input Parameters:
3168a2b725a8SWilliam Gropp + mat   - the matrix
3169a2b725a8SWilliam Gropp - local - the local matrix
31703b03a366Sstefano_zampini 
31714f58015eSStefano Zampini   Level: intermediate
317211a5261eSBarry Smith 
31731cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatISSetLocalMatType`, `MatISGetLocalMat()`
31743b03a366Sstefano_zampini @*/
MatISSetLocalMat(Mat mat,Mat local)3175d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISSetLocalMat(Mat mat, Mat local)
3176d71ae5a4SJacob Faibussowitsch {
31773b03a366Sstefano_zampini   PetscFunctionBegin;
31783b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3179b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local, MAT_CLASSID, 2);
3180cac4c232SBarry Smith   PetscUseMethod(mat, "MatISSetLocalMat_C", (Mat, Mat), (mat, local));
31813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31823b03a366Sstefano_zampini }
31833b03a366Sstefano_zampini 
MatZeroEntries_IS(Mat A)3184d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroEntries_IS(Mat A)
3185d71ae5a4SJacob Faibussowitsch {
31866726f965SBarry Smith   Mat_IS *a = (Mat_IS *)A->data;
31876726f965SBarry Smith 
31886726f965SBarry Smith   PetscFunctionBegin;
31899566063dSJacob Faibussowitsch   PetscCall(MatZeroEntries(a->A));
31903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31916726f965SBarry Smith }
31926726f965SBarry Smith 
MatScale_IS(Mat A,PetscScalar a)3193d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatScale_IS(Mat A, PetscScalar a)
3194d71ae5a4SJacob Faibussowitsch {
31952e74eeadSLisandro Dalcin   Mat_IS *is = (Mat_IS *)A->data;
31962e74eeadSLisandro Dalcin 
31972e74eeadSLisandro Dalcin   PetscFunctionBegin;
31989566063dSJacob Faibussowitsch   PetscCall(MatScale(is->A, a));
31993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32002e74eeadSLisandro Dalcin }
32012e74eeadSLisandro Dalcin 
MatGetDiagonal_IS(Mat A,Vec v)3202d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
3203d71ae5a4SJacob Faibussowitsch {
32042e74eeadSLisandro Dalcin   Mat_IS *is = (Mat_IS *)A->data;
32052e74eeadSLisandro Dalcin 
32062e74eeadSLisandro Dalcin   PetscFunctionBegin;
32072e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
32089566063dSJacob Faibussowitsch   PetscCall(MatGetDiagonal(is->A, is->y));
32092e74eeadSLisandro Dalcin 
32102e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
32119566063dSJacob Faibussowitsch   PetscCall(VecSet(v, 0));
32129566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(is->rctx, is->y, v, ADD_VALUES, SCATTER_REVERSE));
32139566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(is->rctx, is->y, v, ADD_VALUES, SCATTER_REVERSE));
32143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32152e74eeadSLisandro Dalcin }
32162e74eeadSLisandro Dalcin 
MatSetOption_IS(Mat A,MatOption op,PetscBool flg)3217d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_IS(Mat A, MatOption op, PetscBool flg)
3218d71ae5a4SJacob Faibussowitsch {
32196726f965SBarry Smith   Mat_IS *a = (Mat_IS *)A->data;
32206726f965SBarry Smith 
32216726f965SBarry Smith   PetscFunctionBegin;
32229566063dSJacob Faibussowitsch   PetscCall(MatSetOption(a->A, op, flg));
32233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
32246726f965SBarry Smith }
32256726f965SBarry Smith 
MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)3226d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAXPY_IS(Mat Y, PetscScalar a, Mat X, MatStructure str)
3227d71ae5a4SJacob Faibussowitsch {
3228f26d0771SStefano Zampini   Mat_IS *y = (Mat_IS *)Y->data;
3229f26d0771SStefano Zampini   Mat_IS *x;
3230f26d0771SStefano Zampini 
3231f26d0771SStefano Zampini   PetscFunctionBegin;
323276bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
323376bd3646SJed Brown     PetscBool ismatis;
32349566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)X, MATIS, &ismatis));
323528b400f6SJacob Faibussowitsch     PetscCheck(ismatis, PetscObjectComm((PetscObject)Y), PETSC_ERR_SUP, "Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
323676bd3646SJed Brown   }
3237f26d0771SStefano Zampini   x = (Mat_IS *)X->data;
32389566063dSJacob Faibussowitsch   PetscCall(MatAXPY(y->A, a, x->A, str));
32393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3240f26d0771SStefano Zampini }
3241f26d0771SStefano Zampini 
MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat * submat)3242d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A, IS row, IS col, Mat *submat)
3243d71ae5a4SJacob Faibussowitsch {
3244f26d0771SStefano Zampini   Mat                    lA;
3245f4f49eeaSPierre Jolivet   Mat_IS                *matis = (Mat_IS *)A->data;
3246f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g, cl2g;
3247f26d0771SStefano Zampini   IS                     is;
3248f26d0771SStefano Zampini   const PetscInt        *rg, *rl;
3249076fee34SStefano Zampini   PetscInt               nrg, rbs, cbs;
3250f26d0771SStefano Zampini   PetscInt               N, M, nrl, i, *idxs;
3251f26d0771SStefano Zampini 
3252f26d0771SStefano Zampini   PetscFunctionBegin;
3253076fee34SStefano Zampini   PetscCall(ISGetBlockSize(row, &rbs));
3254076fee34SStefano Zampini   PetscCall(ISGetBlockSize(col, &cbs));
32559566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(A->rmap->mapping, &rg));
32569566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(row, &nrl));
32579566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(row, &rl));
32589566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetSize(A->rmap->mapping, &nrg));
325976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
3260e87b5d96SPierre 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 than maximum possible %" PetscInt_FMT, i, rl[i], nrg);
326176bd3646SJed Brown   }
3262076fee34SStefano Zampini   if (nrg % rbs) nrg = rbs * (nrg / rbs + 1);
32639566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrg, &idxs));
3264f26d0771SStefano Zampini   /* map from [0,nrl) to row */
3265f26d0771SStefano Zampini   for (i = 0; i < nrl; i++) idxs[i] = rl[i];
3266f26d0771SStefano Zampini   for (i = nrl; i < nrg; i++) idxs[i] = -1;
32679566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(row, &rl));
32689566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping, &rg));
32699566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A), nrg, idxs, PETSC_OWN_POINTER, &is));
32709566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g));
3271076fee34SStefano Zampini   PetscCall(ISLocalToGlobalMappingSetBlockSize(rl2g, rbs));
32729566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is));
3273f26d0771SStefano Zampini   /* compute new l2g map for columns */
3274e432b41dSStefano Zampini   if (col != row || matis->rmapping != matis->cmapping || matis->A->rmap->mapping != matis->A->cmap->mapping) {
3275f26d0771SStefano Zampini     const PetscInt *cg, *cl;
3276f26d0771SStefano Zampini     PetscInt        ncg;
3277f26d0771SStefano Zampini     PetscInt        ncl;
3278f26d0771SStefano Zampini 
32799566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetIndices(A->cmap->mapping, &cg));
32809566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(col, &ncl));
32819566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(col, &cl));
32829566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetSize(A->cmap->mapping, &ncg));
328376bd3646SJed Brown     if (PetscDefined(USE_DEBUG)) {
3284e87b5d96SPierre 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 than maximum possible %" PetscInt_FMT, i, cl[i], ncg);
328576bd3646SJed Brown     }
3286076fee34SStefano Zampini     if (ncg % cbs) ncg = cbs * (ncg / cbs + 1);
32879566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(ncg, &idxs));
3288f26d0771SStefano Zampini     /* map from [0,ncl) to col */
3289f26d0771SStefano Zampini     for (i = 0; i < ncl; i++) idxs[i] = cl[i];
3290f26d0771SStefano Zampini     for (i = ncl; i < ncg; i++) idxs[i] = -1;
32919566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(col, &cl));
32929566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping, &cg));
32939566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A), ncg, idxs, PETSC_OWN_POINTER, &is));
32949566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g));
3295076fee34SStefano Zampini     PetscCall(ISLocalToGlobalMappingSetBlockSize(cl2g, cbs));
32969566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
3297f26d0771SStefano Zampini   } else {
32989566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)rl2g));
3299f26d0771SStefano Zampini     cl2g = rl2g;
3300f26d0771SStefano Zampini   }
33010d2733adSStefano Zampini 
3302f26d0771SStefano Zampini   /* create the MATIS submatrix */
33039566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &M, &N));
33049566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)A), submat));
33059566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*submat, PETSC_DECIDE, PETSC_DECIDE, M, N));
33069566063dSJacob Faibussowitsch   PetscCall(MatSetType(*submat, MATIS));
3307b0aa3428SStefano Zampini   matis             = (Mat_IS *)((*submat)->data);
33080d2733adSStefano Zampini   matis->islocalref = A;
33099566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(*submat, rl2g, cl2g));
33109566063dSJacob Faibussowitsch   PetscCall(MatISGetLocalMat(A, &lA));
33119566063dSJacob Faibussowitsch   PetscCall(MatISSetLocalMat(*submat, lA));
33129566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
33139566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
3314e432b41dSStefano Zampini 
3315f26d0771SStefano Zampini   /* remove unsupported ops */
33169566063dSJacob Faibussowitsch   PetscCall(PetscMemzero((*submat)->ops, sizeof(struct _MatOps)));
3317f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
3318f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
3319f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
33200d2733adSStefano Zampini   (*submat)->ops->zerorowslocal         = MatZeroRowsLocal_SubMat_IS;
33210d2733adSStefano Zampini   (*submat)->ops->zerorowscolumnslocal  = MatZeroRowsColumnsLocal_SubMat_IS;
332239b6f3f9SStefano Zampini   (*submat)->ops->getlocalsubmatrix     = MatGetLocalSubMatrix_IS;
33233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3324f26d0771SStefano Zampini }
3325f26d0771SStefano Zampini 
MatSetFromOptions_IS(Mat A,PetscOptionItems PetscOptionsObject)3326ce78bad3SBarry Smith static PetscErrorCode MatSetFromOptions_IS(Mat A, PetscOptionItems PetscOptionsObject)
3327d71ae5a4SJacob Faibussowitsch {
3328872cf891SStefano Zampini   Mat_IS   *a = (Mat_IS *)A->data;
33298546b261SStefano Zampini   char      type[256];
33308546b261SStefano Zampini   PetscBool flg;
3331872cf891SStefano Zampini 
3332872cf891SStefano Zampini   PetscFunctionBegin;
3333d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "MATIS options");
33344f58015eSStefano Zampini   PetscCall(PetscOptionsDeprecated("-matis_keepassembled", "-mat_is_keepassembled", "3.21", NULL));
33354f58015eSStefano Zampini   PetscCall(PetscOptionsDeprecated("-matis_fixempty", "-mat_is_fixempty", "3.21", NULL));
33364f58015eSStefano Zampini   PetscCall(PetscOptionsDeprecated("-matis_storel2l", "-mat_is_storel2l", "3.21", NULL));
33374f58015eSStefano Zampini   PetscCall(PetscOptionsDeprecated("-matis_localmat_type", "-mat_is_localmat_type", "3.21", NULL));
33384f58015eSStefano Zampini   PetscCall(PetscOptionsBool("-mat_is_keepassembled", "Store an assembled version if needed", NULL, a->keepassembled, &a->keepassembled, NULL));
33394f58015eSStefano Zampini   PetscCall(PetscOptionsBool("-mat_is_fixempty", "Fix local matrices in case of empty local rows/columns", "MatISFixLocalEmpty", a->locempty, &a->locempty, NULL));
33404f58015eSStefano Zampini   PetscCall(PetscOptionsBool("-mat_is_storel2l", "Store local-to-local matrices generated from PtAP operations", "MatISStoreL2L", a->storel2l, &a->storel2l, NULL));
33414f58015eSStefano Zampini   PetscCall(PetscOptionsBool("-mat_is_allow_repeated", "Allow local repeated entries", "MatISSetAllowRepeated", a->allow_repeated, &a->allow_repeated, NULL));
33424f58015eSStefano Zampini   PetscCall(PetscOptionsFList("-mat_is_localmat_type", "Matrix type", "MatISSetLocalMatType", MatList, a->lmattype, type, 256, &flg));
33431baa6e33SBarry Smith   if (flg) PetscCall(MatISSetLocalMatType(A, type));
33441baa6e33SBarry Smith   if (a->A) PetscCall(MatSetFromOptions(a->A));
3345d0609cedSBarry Smith   PetscOptionsHeadEnd();
33463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3347872cf891SStefano Zampini }
3348872cf891SStefano Zampini 
3349284134d9SBarry Smith /*@
33504f58015eSStefano Zampini   MatCreateIS - Creates a "process" unassembled matrix.
33514f58015eSStefano Zampini 
33524f58015eSStefano Zampini   Collective.
3353284134d9SBarry Smith 
3354284134d9SBarry Smith   Input Parameters:
3355284134d9SBarry Smith + comm - MPI communicator that will share the matrix
3356e176bc59SStefano Zampini . bs   - block size of the matrix
33572920cce0SJacob Faibussowitsch . m    - local size of left vector used in matrix vector products
33582920cce0SJacob Faibussowitsch . n    - local size of right vector used in matrix vector products
33592920cce0SJacob Faibussowitsch . M    - global size of left vector used in matrix vector products
33602920cce0SJacob Faibussowitsch . N    - global size of right vector used in matrix vector products
3361e176bc59SStefano Zampini . rmap - local to global map for rows
3362e176bc59SStefano Zampini - cmap - local to global map for cols
3363284134d9SBarry Smith 
3364284134d9SBarry Smith   Output Parameter:
3365284134d9SBarry Smith . A - the resulting matrix
3366284134d9SBarry Smith 
33674f58015eSStefano Zampini   Level: intermediate
33688e6c10adSSatish Balay 
336995452b02SPatrick Sanan   Notes:
33702ef1f0ffSBarry Smith   `m` and `n` are NOT related to the size of the map; they represent the size of the local parts of the distributed vectors
33714f58015eSStefano Zampini   used in `MatMult()` operations. The local sizes of `rmap` and `cmap` define the size of the local matrices.
337211a5261eSBarry Smith 
33732ef1f0ffSBarry Smith   If `rmap` (`cmap`) is `NULL`, then the local row (column) spaces matches the global space.
3374284134d9SBarry Smith 
33751cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatSetLocalToGlobalMapping()`
3376284134d9SBarry Smith @*/
MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat * A)3377d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateIS(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt M, PetscInt N, ISLocalToGlobalMapping rmap, ISLocalToGlobalMapping cmap, Mat *A)
3378d71ae5a4SJacob Faibussowitsch {
3379284134d9SBarry Smith   PetscFunctionBegin;
33809566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, A));
33819566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*A, m, n, M, N));
338248a46eb9SPierre Jolivet   if (bs > 0) PetscCall(MatSetBlockSize(*A, bs));
33839566063dSJacob Faibussowitsch   PetscCall(MatSetType(*A, MATIS));
33849566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(*A, rmap, cmap));
33853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3386284134d9SBarry Smith }
3387284134d9SBarry Smith 
MatHasOperation_IS(Mat A,MatOperation op,PetscBool * has)3388d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHasOperation_IS(Mat A, MatOperation op, PetscBool *has)
3389d71ae5a4SJacob Faibussowitsch {
33908b9382cfSStefano Zampini   Mat_IS      *a              = (Mat_IS *)A->data;
3391e26763e4SStefano Zampini   MatOperation tobefiltered[] = {MATOP_MULT_ADD, MATOP_MULT_TRANSPOSE_ADD, MATOP_GET_DIAGONAL_BLOCK, MATOP_INCREASE_OVERLAP};
33928b9382cfSStefano Zampini 
33938b9382cfSStefano Zampini   PetscFunctionBegin;
33948b9382cfSStefano Zampini   *has = PETSC_FALSE;
33953ba16761SJacob Faibussowitsch   if (!((void **)A->ops)[op] || !a->A) PetscFunctionReturn(PETSC_SUCCESS);
3396d0dbe9f7SStefano Zampini   *has = PETSC_TRUE;
33979371c9d4SSatish Balay   for (PetscInt i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(tobefiltered); i++)
33983ba16761SJacob Faibussowitsch     if (op == tobefiltered[i]) PetscFunctionReturn(PETSC_SUCCESS);
33999566063dSJacob Faibussowitsch   PetscCall(MatHasOperation(a->A, op, has));
34003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34018b9382cfSStefano Zampini }
34028b9382cfSStefano Zampini 
MatSetValuesCOO_IS(Mat A,const PetscScalar v[],InsertMode imode)3403d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesCOO_IS(Mat A, const PetscScalar v[], InsertMode imode)
3404d71ae5a4SJacob Faibussowitsch {
3405e432b41dSStefano Zampini   Mat_IS *a = (Mat_IS *)A->data;
3406e432b41dSStefano Zampini 
3407e432b41dSStefano Zampini   PetscFunctionBegin;
34089566063dSJacob Faibussowitsch   PetscCall(MatSetValuesCOO(a->A, v, imode));
34099566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
34109566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
34113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3412e432b41dSStefano Zampini }
3413e432b41dSStefano Zampini 
MatSetPreallocationCOOLocal_IS(Mat A,PetscCount ncoo,PetscInt coo_i[],PetscInt coo_j[])3414d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetPreallocationCOOLocal_IS(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[])
3415d71ae5a4SJacob Faibussowitsch {
3416e432b41dSStefano Zampini   Mat_IS *a = (Mat_IS *)A->data;
3417e432b41dSStefano Zampini 
3418e432b41dSStefano Zampini   PetscFunctionBegin;
3419e432b41dSStefano Zampini   PetscCheck(a->A, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Need to provide l2g map first via MatSetLocalToGlobalMapping");
3420e432b41dSStefano Zampini   if (a->A->rmap->mapping || a->A->cmap->mapping) {
34219566063dSJacob Faibussowitsch     PetscCall(MatSetPreallocationCOOLocal(a->A, ncoo, coo_i, coo_j));
3422e432b41dSStefano Zampini   } else {
34239566063dSJacob Faibussowitsch     PetscCall(MatSetPreallocationCOO(a->A, ncoo, coo_i, coo_j));
3424e432b41dSStefano Zampini   }
34259566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", MatSetValuesCOO_IS));
3426e432b41dSStefano Zampini   A->preallocated = PETSC_TRUE;
34273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3428e432b41dSStefano Zampini }
3429e432b41dSStefano Zampini 
MatSetPreallocationCOO_IS(Mat A,PetscCount ncoo,PetscInt coo_i[],PetscInt coo_j[])3430d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetPreallocationCOO_IS(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[])
3431d71ae5a4SJacob Faibussowitsch {
3432e432b41dSStefano Zampini   Mat_IS  *a = (Mat_IS *)A->data;
3433835f2295SStefano Zampini   PetscInt ncoo_i;
3434e432b41dSStefano Zampini 
3435e432b41dSStefano Zampini   PetscFunctionBegin;
3436e432b41dSStefano Zampini   PetscCheck(a->A, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Need to provide l2g map first via MatSetLocalToGlobalMapping");
3437835f2295SStefano Zampini   PetscCall(PetscIntCast(ncoo, &ncoo_i));
3438835f2295SStefano Zampini   PetscCall(ISGlobalToLocalMappingApply(a->rmapping, IS_GTOLM_MASK, ncoo_i, coo_i, NULL, coo_i));
3439835f2295SStefano Zampini   PetscCall(ISGlobalToLocalMappingApply(a->cmapping, IS_GTOLM_MASK, ncoo_i, coo_j, NULL, coo_j));
3440e8729f6fSJunchao Zhang   PetscCall(MatSetPreallocationCOO(a->A, ncoo, coo_i, coo_j));
34419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", MatSetValuesCOO_IS));
3442e432b41dSStefano Zampini   A->preallocated = PETSC_TRUE;
34433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3444e432b41dSStefano Zampini }
3445e432b41dSStefano Zampini 
MatISGetAssembled_Private(Mat A,Mat * tA)3446d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISGetAssembled_Private(Mat A, Mat *tA)
3447d71ae5a4SJacob Faibussowitsch {
3448d0dbe9f7SStefano Zampini   Mat_IS          *a = (Mat_IS *)A->data;
34491690c2aeSBarry Smith   PetscObjectState Astate, aAstate       = PETSC_INT_MIN;
34501690c2aeSBarry Smith   PetscObjectState Annzstate, aAnnzstate = PETSC_INT_MIN;
3451d0dbe9f7SStefano Zampini 
3452d0dbe9f7SStefano Zampini   PetscFunctionBegin;
3453d0dbe9f7SStefano Zampini   PetscCall(PetscObjectStateGet((PetscObject)A, &Astate));
3454d0dbe9f7SStefano Zampini   Annzstate = A->nonzerostate;
3455d0dbe9f7SStefano Zampini   if (a->assembledA) {
3456d0dbe9f7SStefano Zampini     PetscCall(PetscObjectStateGet((PetscObject)a->assembledA, &aAstate));
3457d0dbe9f7SStefano Zampini     aAnnzstate = a->assembledA->nonzerostate;
3458d0dbe9f7SStefano Zampini   }
3459d0dbe9f7SStefano Zampini   if (aAnnzstate != Annzstate) PetscCall(MatDestroy(&a->assembledA));
3460d0dbe9f7SStefano Zampini   if (Astate != aAstate || !a->assembledA) {
3461d0dbe9f7SStefano Zampini     MatType     aAtype;
3462d0dbe9f7SStefano Zampini     PetscMPIInt size;
3463d0dbe9f7SStefano Zampini     PetscInt    rbs, cbs, bs;
3464d0dbe9f7SStefano Zampini 
3465d0dbe9f7SStefano Zampini     /* the assembled form is used as temporary storage for parallel operations
3466d0dbe9f7SStefano Zampini        like createsubmatrices and the like, do not waste device memory */
3467d0dbe9f7SStefano Zampini     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
3468d0dbe9f7SStefano Zampini     PetscCall(ISLocalToGlobalMappingGetBlockSize(a->cmapping, &cbs));
3469d0dbe9f7SStefano Zampini     PetscCall(ISLocalToGlobalMappingGetBlockSize(a->rmapping, &rbs));
3470d0dbe9f7SStefano Zampini     bs = rbs == cbs ? rbs : 1;
3471d0dbe9f7SStefano Zampini     if (a->assembledA) PetscCall(MatGetType(a->assembledA, &aAtype));
3472d0dbe9f7SStefano Zampini     else if (size > 1) aAtype = bs > 1 ? MATMPIBAIJ : MATMPIAIJ;
3473d0dbe9f7SStefano Zampini     else aAtype = bs > 1 ? MATSEQBAIJ : MATSEQAIJ;
3474d0dbe9f7SStefano Zampini 
3475d0dbe9f7SStefano Zampini     PetscCall(MatConvert(A, aAtype, a->assembledA ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX, &a->assembledA));
3476d0dbe9f7SStefano Zampini     PetscCall(PetscObjectStateSet((PetscObject)a->assembledA, Astate));
3477d0dbe9f7SStefano Zampini     a->assembledA->nonzerostate = Annzstate;
3478d0dbe9f7SStefano Zampini   }
3479d0dbe9f7SStefano Zampini   PetscCall(PetscObjectReference((PetscObject)a->assembledA));
3480d0dbe9f7SStefano Zampini   *tA = a->assembledA;
3481d0dbe9f7SStefano Zampini   if (!a->keepassembled) PetscCall(MatDestroy(&a->assembledA));
34823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3483d0dbe9f7SStefano Zampini }
3484d0dbe9f7SStefano Zampini 
MatISRestoreAssembled_Private(Mat A,Mat * tA)3485d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISRestoreAssembled_Private(Mat A, Mat *tA)
3486d71ae5a4SJacob Faibussowitsch {
3487d0dbe9f7SStefano Zampini   PetscFunctionBegin;
3488d0dbe9f7SStefano Zampini   PetscCall(MatDestroy(tA));
3489d0dbe9f7SStefano Zampini   *tA = NULL;
34903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3491d0dbe9f7SStefano Zampini }
3492d0dbe9f7SStefano Zampini 
MatGetDiagonalBlock_IS(Mat A,Mat * dA)3493d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonalBlock_IS(Mat A, Mat *dA)
3494d71ae5a4SJacob Faibussowitsch {
3495d0dbe9f7SStefano Zampini   Mat_IS          *a = (Mat_IS *)A->data;
34961690c2aeSBarry Smith   PetscObjectState Astate, dAstate = PETSC_INT_MIN;
3497d0dbe9f7SStefano Zampini 
3498d0dbe9f7SStefano Zampini   PetscFunctionBegin;
3499d0dbe9f7SStefano Zampini   PetscCall(PetscObjectStateGet((PetscObject)A, &Astate));
3500d0dbe9f7SStefano Zampini   if (a->dA) PetscCall(PetscObjectStateGet((PetscObject)a->dA, &dAstate));
3501d0dbe9f7SStefano Zampini   if (Astate != dAstate) {
3502d0dbe9f7SStefano Zampini     Mat     tA;
3503d0dbe9f7SStefano Zampini     MatType ltype;
3504d0dbe9f7SStefano Zampini 
3505d0dbe9f7SStefano Zampini     PetscCall(MatDestroy(&a->dA));
3506d0dbe9f7SStefano Zampini     PetscCall(MatISGetAssembled_Private(A, &tA));
3507d0dbe9f7SStefano Zampini     PetscCall(MatGetDiagonalBlock(tA, &a->dA));
3508d0dbe9f7SStefano Zampini     PetscCall(MatPropagateSymmetryOptions(tA, a->dA));
3509d0dbe9f7SStefano Zampini     PetscCall(MatGetType(a->A, &ltype));
3510d0dbe9f7SStefano Zampini     PetscCall(MatConvert(a->dA, ltype, MAT_INPLACE_MATRIX, &a->dA));
3511d0dbe9f7SStefano Zampini     PetscCall(PetscObjectReference((PetscObject)a->dA));
3512d0dbe9f7SStefano Zampini     PetscCall(MatISRestoreAssembled_Private(A, &tA));
3513d0dbe9f7SStefano Zampini     PetscCall(PetscObjectStateSet((PetscObject)a->dA, Astate));
3514d0dbe9f7SStefano Zampini   }
3515d0dbe9f7SStefano Zampini   *dA = a->dA;
35163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3517d0dbe9f7SStefano Zampini }
3518d0dbe9f7SStefano Zampini 
MatCreateSubMatrices_IS(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse reuse,Mat * submat[])3519d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrices_IS(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse reuse, Mat *submat[])
3520d71ae5a4SJacob Faibussowitsch {
3521d0dbe9f7SStefano Zampini   Mat tA;
3522d0dbe9f7SStefano Zampini 
3523d0dbe9f7SStefano Zampini   PetscFunctionBegin;
3524d0dbe9f7SStefano Zampini   PetscCall(MatISGetAssembled_Private(A, &tA));
3525d0dbe9f7SStefano Zampini   PetscCall(MatCreateSubMatrices(tA, n, irow, icol, reuse, submat));
3526d0dbe9f7SStefano Zampini   /* MatCreateSubMatrices_MPIAIJ is a mess at the moment */
3527d0dbe9f7SStefano Zampini #if 0
3528d0dbe9f7SStefano Zampini   {
3529d0dbe9f7SStefano Zampini     Mat_IS    *a = (Mat_IS*)A->data;
3530d0dbe9f7SStefano Zampini     MatType   ltype;
3531d0dbe9f7SStefano Zampini     VecType   vtype;
3532d0dbe9f7SStefano Zampini     char      *flg;
3533d0dbe9f7SStefano Zampini 
3534d0dbe9f7SStefano Zampini     PetscCall(MatGetType(a->A,&ltype));
3535d0dbe9f7SStefano Zampini     PetscCall(MatGetVecType(a->A,&vtype));
3536d0dbe9f7SStefano Zampini     PetscCall(PetscStrstr(vtype,"cuda",&flg));
3537d0dbe9f7SStefano Zampini     if (!flg) PetscCall(PetscStrstr(vtype,"hip",&flg));
3538d0dbe9f7SStefano Zampini     if (!flg) PetscCall(PetscStrstr(vtype,"kokkos",&flg));
3539d0dbe9f7SStefano Zampini     if (flg) {
3540d0dbe9f7SStefano Zampini       for (PetscInt i = 0; i < n; i++) {
3541d0dbe9f7SStefano Zampini         Mat sA = (*submat)[i];
3542d0dbe9f7SStefano Zampini 
3543d0dbe9f7SStefano Zampini         PetscCall(MatConvert(sA,ltype,MAT_INPLACE_MATRIX,&sA));
3544d0dbe9f7SStefano Zampini         (*submat)[i] = sA;
3545d0dbe9f7SStefano Zampini       }
3546d0dbe9f7SStefano Zampini     }
3547d0dbe9f7SStefano Zampini   }
3548d0dbe9f7SStefano Zampini #endif
3549d0dbe9f7SStefano Zampini   PetscCall(MatISRestoreAssembled_Private(A, &tA));
35503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3551d0dbe9f7SStefano Zampini }
3552d0dbe9f7SStefano Zampini 
MatIncreaseOverlap_IS(Mat A,PetscInt n,IS is[],PetscInt ov)3553d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIncreaseOverlap_IS(Mat A, PetscInt n, IS is[], PetscInt ov)
3554d71ae5a4SJacob Faibussowitsch {
3555d0dbe9f7SStefano Zampini   Mat tA;
3556d0dbe9f7SStefano Zampini 
3557d0dbe9f7SStefano Zampini   PetscFunctionBegin;
3558d0dbe9f7SStefano Zampini   PetscCall(MatISGetAssembled_Private(A, &tA));
3559d0dbe9f7SStefano Zampini   PetscCall(MatIncreaseOverlap(tA, n, is, ov));
3560d0dbe9f7SStefano Zampini   PetscCall(MatISRestoreAssembled_Private(A, &tA));
35613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3562d0dbe9f7SStefano Zampini }
3563d0dbe9f7SStefano Zampini 
3564e432b41dSStefano Zampini /*@
356511a5261eSBarry Smith   MatISGetLocalToGlobalMapping - Gets the local-to-global numbering of the `MATIS` object
3566e432b41dSStefano Zampini 
3567e432b41dSStefano Zampini   Not Collective
3568e432b41dSStefano Zampini 
3569e432b41dSStefano Zampini   Input Parameter:
3570e432b41dSStefano Zampini . A - the matrix
3571e432b41dSStefano Zampini 
3572e432b41dSStefano Zampini   Output Parameters:
3573e432b41dSStefano Zampini + rmapping - row mapping
3574e432b41dSStefano Zampini - cmapping - column mapping
3575e432b41dSStefano Zampini 
35762ef1f0ffSBarry Smith   Level: advanced
35772ef1f0ffSBarry Smith 
357811a5261eSBarry Smith   Note:
357911a5261eSBarry Smith   The returned map can be different from the one used to construct the `MATIS` object, since it will not contain negative or repeated indices.
3580e432b41dSStefano Zampini 
3581bfe80ac4SPierre Jolivet .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatSetLocalToGlobalMapping()`
3582e432b41dSStefano Zampini @*/
MatISGetLocalToGlobalMapping(Mat A,ISLocalToGlobalMapping * rmapping,ISLocalToGlobalMapping * cmapping)3583d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
3584d71ae5a4SJacob Faibussowitsch {
3585e432b41dSStefano Zampini   PetscFunctionBegin;
3586e432b41dSStefano Zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3587e432b41dSStefano Zampini   PetscValidType(A, 1);
35884f572ea9SToby Isaac   if (rmapping) PetscAssertPointer(rmapping, 2);
35894f572ea9SToby Isaac   if (cmapping) PetscAssertPointer(cmapping, 3);
3590cac4c232SBarry Smith   PetscUseMethod(A, "MatISGetLocalToGlobalMapping_C", (Mat, ISLocalToGlobalMapping *, ISLocalToGlobalMapping *), (A, rmapping, cmapping));
35913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3592e432b41dSStefano Zampini }
3593e432b41dSStefano Zampini 
MatISGetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping * r,ISLocalToGlobalMapping * c)3594d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISGetLocalToGlobalMapping_IS(Mat A, ISLocalToGlobalMapping *r, ISLocalToGlobalMapping *c)
3595d71ae5a4SJacob Faibussowitsch {
3596e432b41dSStefano Zampini   Mat_IS *a = (Mat_IS *)A->data;
3597e432b41dSStefano Zampini 
3598e432b41dSStefano Zampini   PetscFunctionBegin;
3599e432b41dSStefano Zampini   if (r) *r = a->rmapping;
3600e432b41dSStefano Zampini   if (c) *c = a->cmapping;
36013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3602e432b41dSStefano Zampini }
3603e432b41dSStefano Zampini 
MatSetBlockSizes_IS(Mat A,PetscInt rbs,PetscInt cbs)3604a50ef18cSStefano Zampini static PetscErrorCode MatSetBlockSizes_IS(Mat A, PetscInt rbs, PetscInt cbs)
3605a50ef18cSStefano Zampini {
3606a50ef18cSStefano Zampini   Mat_IS *a = (Mat_IS *)A->data;
3607a50ef18cSStefano Zampini 
3608a50ef18cSStefano Zampini   PetscFunctionBegin;
3609a50ef18cSStefano Zampini   if (a->A) PetscCall(MatSetBlockSizes(a->A, rbs, cbs));
3610a50ef18cSStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
3611a50ef18cSStefano Zampini }
3612a50ef18cSStefano Zampini 
3613b4319ba4SBarry Smith /*MC
36144f58015eSStefano Zampini   MATIS - MATIS = "is" - A matrix type to be used for non-overlapping domain decomposition methods (e.g. `PCBDDC` or `KSPFETIDP`).
36154f58015eSStefano Zampini   This stores the matrices in globally unassembled form and the parallel matrix vector product is handled "implicitly".
3616b4319ba4SBarry Smith 
3617b4319ba4SBarry Smith   Options Database Keys:
36184f58015eSStefano Zampini + -mat_type is           - Set the matrix type to `MATIS`.
36194f58015eSStefano Zampini . -mat_is_allow_repeated - Allow repeated entries in the local part of the local to global maps.
36204f58015eSStefano Zampini . -mat_is_fixempty       - Fix local matrices in case of empty local rows/columns.
36214f58015eSStefano Zampini - -mat_is_storel2l       - Store the local-to-local operators generated by the Galerkin process of `MatPtAP()`.
36222ef1f0ffSBarry Smith 
36234f58015eSStefano Zampini   Level: intermediate
3624b4319ba4SBarry Smith 
362595452b02SPatrick Sanan   Notes:
36262ef1f0ffSBarry Smith   Options prefix for the inner matrix are given by `-is_mat_xxx`
3627b4319ba4SBarry Smith 
362811a5261eSBarry Smith   You must call `MatSetLocalToGlobalMapping()` before using this matrix type.
3629b4319ba4SBarry Smith 
3630b4319ba4SBarry Smith   You can do matrix preallocation on the local matrix after you obtain it with
36314f58015eSStefano Zampini   `MatISGetLocalMat()`; otherwise, you could use `MatISSetPreallocation()` or `MatXAIJSetPreallocation()`
3632b4319ba4SBarry Smith 
36331cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `Mat`, `MatISGetLocalMat()`, `MatSetLocalToGlobalMapping()`, `MatISSetPreallocation()`, `MatCreateIS()`, `PCBDDC`, `KSPFETIDP`
3634b4319ba4SBarry Smith M*/
MatCreate_IS(Mat A)3635d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
3636d71ae5a4SJacob Faibussowitsch {
3637e432b41dSStefano Zampini   Mat_IS *a;
3638b4319ba4SBarry Smith 
3639b4319ba4SBarry Smith   PetscFunctionBegin;
36404dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&a));
36419566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(MATAIJ, &a->lmattype));
3642e432b41dSStefano Zampini   A->data = (void *)a;
3643b4319ba4SBarry Smith 
3644e176bc59SStefano Zampini   /* matrix ops */
36459566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(A->ops, sizeof(struct _MatOps)));
3646b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
36472e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
36482e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
36492e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
3650b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
3651b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
36522e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
365398921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
3654b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
3655f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
36562e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
3657f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
3658b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
3659b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
3660b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
36615042aa92SStefano Zampini   A->ops->load                    = MatLoad_IS;
36626726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
36632e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
36642e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
36656726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
366669796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
366769796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
366845471136SStefano Zampini   A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS;
3669ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
36702b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
3671659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
36727dae84e0SHong Zhang   A->ops->createsubmatrix         = MatCreateSubMatrix_IS;
3673f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
36743fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
36753fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
3676d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
36777fa8f2d3SStefano Zampini   A->ops->getinfo                 = MatGetInfo_IS;
3678ad219c80Sstefano_zampini   A->ops->diagonalscale           = MatDiagonalScale_IS;
3679872cf891SStefano Zampini   A->ops->setfromoptions          = MatSetFromOptions_IS;
3680fc989267SStefano Zampini   A->ops->setup                   = MatSetUp_IS;
36818b9382cfSStefano Zampini   A->ops->hasoperation            = MatHasOperation_IS;
3682d0dbe9f7SStefano Zampini   A->ops->getdiagonalblock        = MatGetDiagonalBlock_IS;
3683d0dbe9f7SStefano Zampini   A->ops->createsubmatrices       = MatCreateSubMatrices_IS;
3684d0dbe9f7SStefano Zampini   A->ops->increaseoverlap         = MatIncreaseOverlap_IS;
3685a50ef18cSStefano Zampini   A->ops->setblocksizes           = MatSetBlockSizes_IS;
3686b4319ba4SBarry Smith 
3687b7ce53b6SStefano Zampini   /* special MATIS functions */
36889566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMatType_C", MatISSetLocalMatType_IS));
36899566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalMat_C", MatISGetLocalMat_IS));
36909566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISRestoreLocalMat_C", MatISRestoreLocalMat_IS));
36919566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMat_C", MatISSetLocalMat_IS));
36929566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetPreallocation_C", MatISSetPreallocation_IS));
36934f58015eSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetAllowRepeated_C", MatISSetAllowRepeated_IS));
36949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISStoreL2L_C", MatISStoreL2L_IS));
36959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISFixLocalEmpty_C", MatISFixLocalEmpty_IS));
36969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalToGlobalMapping_C", MatISGetLocalToGlobalMapping_IS));
36979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpiaij_C", MatConvert_IS_XAIJ));
36989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpibaij_C", MatConvert_IS_XAIJ));
36999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpisbaij_C", MatConvert_IS_XAIJ));
37009566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqaij_C", MatConvert_IS_XAIJ));
37019566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqbaij_C", MatConvert_IS_XAIJ));
37029566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqsbaij_C", MatConvert_IS_XAIJ));
37039566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_aij_C", MatConvert_IS_XAIJ));
37049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOOLocal_C", MatSetPreallocationCOOLocal_IS));
37059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_IS));
37069566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)A, MATIS));
37073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3708b4319ba4SBarry Smith }
3709