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, <est, &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(<est));
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, <ype));
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,<ype));
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