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 17*076fee34SStefano Zampini 18*076fee34SStefano Zampini /* copied from src/mat/impls/localref/mlocalref.c */ 19*076fee34SStefano Zampini #define IndexSpaceGet(buf, nrow, ncol, irowm, icolm) \ 20*076fee34SStefano Zampini do { \ 21*076fee34SStefano Zampini if (nrow + ncol > (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { \ 22*076fee34SStefano Zampini PetscCall(PetscMalloc2(nrow, &irowm, ncol, &icolm)); \ 23*076fee34SStefano Zampini } else { \ 24*076fee34SStefano Zampini irowm = &buf[0]; \ 25*076fee34SStefano Zampini icolm = &buf[nrow]; \ 26*076fee34SStefano Zampini } \ 27*076fee34SStefano Zampini } while (0) 28*076fee34SStefano Zampini 29*076fee34SStefano Zampini #define IndexSpaceRestore(buf, nrow, ncol, irowm, icolm) \ 30*076fee34SStefano Zampini do { \ 31*076fee34SStefano Zampini if (nrow + ncol > (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) PetscCall(PetscFree2(irowm, icolm)); \ 32*076fee34SStefano Zampini } while (0) 33*076fee34SStefano Zampini 34*076fee34SStefano Zampini static void BlockIndicesExpand(PetscInt n, const PetscInt idx[], PetscInt bs, PetscInt idxm[]) 35*076fee34SStefano Zampini { 36*076fee34SStefano Zampini for (PetscInt i = 0; i < n; i++) { 37*076fee34SStefano Zampini for (PetscInt j = 0; j < bs; j++) idxm[i * bs + j] = idx[i] * bs + j; 38*076fee34SStefano Zampini } 39*076fee34SStefano Zampini } 40*076fee34SStefano 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 4549abdd8aSBarry Smith static PetscErrorCode MatISContainerDestroyPtAP_Private(void **ptr) 46d71ae5a4SJacob Faibussowitsch { 4749abdd8aSBarry 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 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"); 729566063dSJacob Faibussowitsch PetscCall(PetscContainerGetPointer(c, (void **)&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 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 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 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 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 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 29649abdd8aSBarry Smith static PetscErrorCode MatISContainerDestroyFields_Private(void **ptr) 297d71ae5a4SJacob Faibussowitsch { 29849abdd8aSBarry 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 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 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 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 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 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 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 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 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 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 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 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 { 1312*076fee34SStefano Zampini PetscInt buf[2 * MATIS_MAX_ENTRIES_INSERTION], *rows_l = NULL, *cols_l = NULL; 1313f26d0771SStefano Zampini 1314f26d0771SStefano Zampini PetscFunctionBegin; 1315*076fee34SStefano 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)); 1319*076fee34SStefano Zampini IndexSpaceRestore(buf, m, n, rows_l, cols_l); 13203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1321f26d0771SStefano Zampini } 1322f26d0771SStefano Zampini 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 { 1325*076fee34SStefano Zampini PetscInt buf[2 * MATIS_MAX_ENTRIES_INSERTION], *rows_l = NULL, *cols_l = NULL, rbs, cbs; 1326f26d0771SStefano Zampini 1327f26d0771SStefano Zampini PetscFunctionBegin; 1328*076fee34SStefano Zampini /* We cannot guarantee the local matrix will have the same block size of the original matrix */ 1329*076fee34SStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockSize(A->rmap->mapping, &rbs)); 1330*076fee34SStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockSize(A->cmap->mapping, &cbs)); 1331*076fee34SStefano Zampini IndexSpaceGet(buf, m * rbs, n * cbs, rows_l, cols_l); 1332*076fee34SStefano Zampini BlockIndicesExpand(m, rows, rbs, rows_l); 1333*076fee34SStefano Zampini BlockIndicesExpand(n, cols, cbs, cols_l); 1334*076fee34SStefano Zampini PetscCall(ISLocalToGlobalMappingApply(A->rmap->mapping, m * rbs, rows_l, rows_l)); 1335*076fee34SStefano Zampini PetscCall(ISLocalToGlobalMappingApply(A->cmap->mapping, n * cbs, cols_l, cols_l)); 1336*076fee34SStefano Zampini PetscCall(MatSetValuesLocal_IS(A, m * rbs, rows_l, n * cbs, cols_l, values, addv)); 1337*076fee34SStefano Zampini IndexSpaceRestore(buf, m * rbs, n * cbs, rows_l, cols_l); 13383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1339f26d0771SStefano Zampini } 1340f26d0771SStefano Zampini 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 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 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 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 1529d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_IS(Mat A, PetscBool *missing, PetscInt *d) 1530d71ae5a4SJacob Faibussowitsch { 1531527b2640SStefano Zampini Vec v; 1532527b2640SStefano Zampini const PetscScalar *array; 1533527b2640SStefano Zampini PetscInt i, n; 15346bd84002SStefano Zampini 15356bd84002SStefano Zampini PetscFunctionBegin; 1536527b2640SStefano Zampini *missing = PETSC_FALSE; 15379566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, NULL, &v)); 15389566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(A, v)); 15399566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 15409566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &array)); 15419371c9d4SSatish Balay for (i = 0; i < n; i++) 15429371c9d4SSatish Balay if (array[i] == 0.) break; 15439566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &array)); 15449566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 1545527b2640SStefano Zampini if (i != n) *missing = PETSC_TRUE; 1546527b2640SStefano Zampini if (d) { 1547527b2640SStefano Zampini *d = -1; 1548527b2640SStefano Zampini if (*missing) { 1549527b2640SStefano Zampini PetscInt rstart; 15509566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rstart, NULL)); 1551527b2640SStefano Zampini *d = i + rstart; 1552527b2640SStefano Zampini } 1553527b2640SStefano Zampini } 15543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15556bd84002SStefano Zampini } 15566bd84002SStefano Zampini 1557d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISSetUpSF_IS(Mat B) 1558d71ae5a4SJacob Faibussowitsch { 1559f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)B->data; 156028f4e0baSStefano Zampini const PetscInt *gidxs; 15614f2d7cafSStefano Zampini PetscInt nleaves; 156228f4e0baSStefano Zampini 156328f4e0baSStefano Zampini PetscFunctionBegin; 15643ba16761SJacob Faibussowitsch if (matis->sf) PetscFunctionReturn(PETSC_SUCCESS); 15659566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)B), &matis->sf)); 15669566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->rmapping, &gidxs)); 15679566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->rmapping, &nleaves)); 15689566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(matis->sf, B->rmap, nleaves, NULL, PETSC_OWN_POINTER, gidxs)); 15699566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->rmapping, &gidxs)); 15709566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(matis->sf->nroots, &matis->sf_rootdata, matis->sf->nleaves, &matis->sf_leafdata)); 1571e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { /* setup SF for columns */ 15729566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->cmapping, &nleaves)); 15739566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)B), &matis->csf)); 15749566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->cmapping, &gidxs)); 15759566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(matis->csf, B->cmap, nleaves, NULL, PETSC_OWN_POINTER, gidxs)); 15769566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->cmapping, &gidxs)); 15779566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(matis->csf->nroots, &matis->csf_rootdata, matis->csf->nleaves, &matis->csf_leafdata)); 1578a8116848SStefano Zampini } else { 1579a8116848SStefano Zampini matis->csf = matis->sf; 1580a8116848SStefano Zampini matis->csf_leafdata = matis->sf_leafdata; 1581a8116848SStefano Zampini matis->csf_rootdata = matis->sf_rootdata; 1582a8116848SStefano Zampini } 15833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 158428f4e0baSStefano Zampini } 15852e1947a5SStefano Zampini 1586eb82efa4SStefano Zampini /*@ 15874f58015eSStefano Zampini MatISGetAllowRepeated - Get the flag to allow repeated entries in the local to global map 15884f58015eSStefano Zampini 15894f58015eSStefano Zampini Not Collective 15904f58015eSStefano Zampini 15914f58015eSStefano Zampini Input Parameter: 15924f58015eSStefano Zampini . A - the matrix 15934f58015eSStefano Zampini 15944f58015eSStefano Zampini Output Parameter: 15954f58015eSStefano Zampini . flg - the boolean flag 15964f58015eSStefano Zampini 15974f58015eSStefano Zampini Level: intermediate 15984f58015eSStefano Zampini 15994f58015eSStefano Zampini .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateIS()`, `MatSetLocalToGlobalMapping()`, `MatISSetAllowRepeated()` 16004f58015eSStefano Zampini @*/ 16014f58015eSStefano Zampini PetscErrorCode MatISGetAllowRepeated(Mat A, PetscBool *flg) 16024f58015eSStefano Zampini { 16034f58015eSStefano Zampini PetscBool ismatis; 16044f58015eSStefano Zampini 16054f58015eSStefano Zampini PetscFunctionBegin; 16064f58015eSStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 16074f58015eSStefano Zampini PetscAssertPointer(flg, 2); 16084f58015eSStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)A, MATIS, &ismatis)); 16094f58015eSStefano Zampini PetscCheck(ismatis, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)A)->type_name); 16104f58015eSStefano Zampini *flg = ((Mat_IS *)A->data)->allow_repeated; 16114f58015eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 16124f58015eSStefano Zampini } 16134f58015eSStefano Zampini 16144f58015eSStefano Zampini /*@ 16154f58015eSStefano Zampini MatISSetAllowRepeated - Set the flag to allow repeated entries in the local to global map 16164f58015eSStefano Zampini 16174f58015eSStefano Zampini Logically Collective 16184f58015eSStefano Zampini 16194f58015eSStefano Zampini Input Parameters: 16204f58015eSStefano Zampini + A - the matrix 16214f58015eSStefano Zampini - flg - the boolean flag 16224f58015eSStefano Zampini 16234f58015eSStefano Zampini Level: intermediate 16244f58015eSStefano Zampini 16254f58015eSStefano Zampini Notes: 16264f58015eSStefano Zampini The default value is `PETSC_FALSE`. 16274f58015eSStefano Zampini When called AFTER calling `MatSetLocalToGlobalMapping()` it will recreate the local matrices 16284f58015eSStefano Zampini if `flg` is different from the previously set value. 16294f58015eSStefano Zampini Specifically, when `flg` is true it will just recreate the local matrices, while if 16304f58015eSStefano Zampini `flg` is false will assemble the local matrices summing up repeated entries. 16314f58015eSStefano Zampini 16324f58015eSStefano Zampini .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateIS()`, `MatSetLocalToGlobalMapping()`, `MatISGetAllowRepeated()` 16334f58015eSStefano Zampini @*/ 16344f58015eSStefano Zampini PetscErrorCode MatISSetAllowRepeated(Mat A, PetscBool flg) 16354f58015eSStefano Zampini { 16364f58015eSStefano Zampini PetscFunctionBegin; 16374f58015eSStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 16384f58015eSStefano Zampini PetscValidType(A, 1); 16394f58015eSStefano Zampini PetscValidLogicalCollectiveBool(A, flg, 2); 16404f58015eSStefano Zampini PetscTryMethod(A, "MatISSetAllowRepeated_C", (Mat, PetscBool), (A, flg)); 16414f58015eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 16424f58015eSStefano Zampini } 16434f58015eSStefano Zampini 16444f58015eSStefano Zampini static PetscErrorCode MatISSetAllowRepeated_IS(Mat A, PetscBool flg) 16454f58015eSStefano Zampini { 16464f58015eSStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 16474f58015eSStefano Zampini Mat lA = NULL; 16484f58015eSStefano Zampini ISLocalToGlobalMapping lrmap, lcmap; 16494f58015eSStefano Zampini 16504f58015eSStefano Zampini PetscFunctionBegin; 16514f58015eSStefano Zampini if (flg == matis->allow_repeated) PetscFunctionReturn(PETSC_SUCCESS); 16524f58015eSStefano Zampini if (!matis->A) { /* matrix has not been preallocated yet */ 16534f58015eSStefano Zampini matis->allow_repeated = flg; 16544f58015eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 16554f58015eSStefano Zampini } 16564f58015eSStefano Zampini PetscCheck(!matis->islocalref, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not implemented for local references"); 16574f58015eSStefano Zampini if (matis->allow_repeated) { /* we will assemble the old local matrix if needed */ 16584f58015eSStefano Zampini lA = matis->A; 16594f58015eSStefano Zampini PetscCall(PetscObjectReference((PetscObject)lA)); 16604f58015eSStefano Zampini } 16614f58015eSStefano Zampini /* In case flg is True, we only recreate the local matrix */ 16624f58015eSStefano Zampini matis->allow_repeated = flg; 16634f58015eSStefano Zampini PetscCall(MatSetLocalToGlobalMapping(A, A->rmap->mapping, A->cmap->mapping)); 16644f58015eSStefano Zampini if (lA) { /* assemble previous local matrix if needed */ 16654f58015eSStefano Zampini Mat nA = matis->A; 16664f58015eSStefano Zampini 16674f58015eSStefano Zampini PetscCall(MatGetLocalToGlobalMapping(nA, &lrmap, &lcmap)); 16684f58015eSStefano Zampini if (!lrmap && !lcmap) { 16694f58015eSStefano Zampini PetscCall(MatISSetLocalMat(A, lA)); 16704f58015eSStefano Zampini } else { 16714f58015eSStefano Zampini Mat P = NULL, R = NULL; 16724f58015eSStefano Zampini MatProductType ptype; 16734f58015eSStefano Zampini 16744f58015eSStefano Zampini if (lrmap == lcmap) { 16754f58015eSStefano Zampini ptype = MATPRODUCT_PtAP; 16764f58015eSStefano Zampini PetscCall(MatCreateFromISLocalToGlobalMapping(lcmap, nA, PETSC_TRUE, PETSC_FALSE, NULL, &P)); 16774f58015eSStefano Zampini PetscCall(MatProductCreate(lA, P, NULL, &nA)); 16784f58015eSStefano Zampini } else { 16794f58015eSStefano Zampini if (lcmap) PetscCall(MatCreateFromISLocalToGlobalMapping(lcmap, nA, PETSC_TRUE, PETSC_FALSE, NULL, &P)); 16804f58015eSStefano Zampini if (lrmap) PetscCall(MatCreateFromISLocalToGlobalMapping(lrmap, nA, PETSC_FALSE, PETSC_TRUE, NULL, &R)); 16814f58015eSStefano Zampini if (R && P) { 16824f58015eSStefano Zampini ptype = MATPRODUCT_ABC; 16834f58015eSStefano Zampini PetscCall(MatProductCreate(R, lA, P, &nA)); 16844f58015eSStefano Zampini } else if (R) { 16854f58015eSStefano Zampini ptype = MATPRODUCT_AB; 16864f58015eSStefano Zampini PetscCall(MatProductCreate(R, lA, NULL, &nA)); 16874f58015eSStefano Zampini } else { 16884f58015eSStefano Zampini ptype = MATPRODUCT_AB; 16894f58015eSStefano Zampini PetscCall(MatProductCreate(lA, P, NULL, &nA)); 16904f58015eSStefano Zampini } 16914f58015eSStefano Zampini } 16924f58015eSStefano Zampini PetscCall(MatProductSetType(nA, ptype)); 16934f58015eSStefano Zampini PetscCall(MatProductSetFromOptions(nA)); 16944f58015eSStefano Zampini PetscCall(MatProductSymbolic(nA)); 16954f58015eSStefano Zampini PetscCall(MatProductNumeric(nA)); 16964f58015eSStefano Zampini PetscCall(MatProductClear(nA)); 16974f58015eSStefano Zampini PetscCall(MatConvert(nA, matis->lmattype, MAT_INPLACE_MATRIX, &nA)); 16984f58015eSStefano Zampini PetscCall(MatISSetLocalMat(A, nA)); 16994f58015eSStefano Zampini PetscCall(MatDestroy(&nA)); 17004f58015eSStefano Zampini PetscCall(MatDestroy(&P)); 17014f58015eSStefano Zampini PetscCall(MatDestroy(&R)); 17024f58015eSStefano Zampini } 17034f58015eSStefano Zampini } 17044f58015eSStefano Zampini PetscCall(MatDestroy(&lA)); 17054f58015eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 17064f58015eSStefano Zampini } 17074f58015eSStefano Zampini 17084f58015eSStefano Zampini /*@ 17092ef1f0ffSBarry Smith MatISStoreL2L - Store local-to-local operators during the Galerkin process of computing `MatPtAP()` 171075d48cdbSStefano Zampini 17114f58015eSStefano Zampini Logically Collective 171275d48cdbSStefano Zampini 171375d48cdbSStefano Zampini Input Parameters: 171475d48cdbSStefano Zampini + A - the matrix 171575d48cdbSStefano Zampini - store - the boolean flag 171675d48cdbSStefano Zampini 171775d48cdbSStefano Zampini Level: advanced 171875d48cdbSStefano Zampini 17191cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateIS()`, `MatISSetPreallocation()`, `MatPtAP()` 172075d48cdbSStefano Zampini @*/ 1721d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISStoreL2L(Mat A, PetscBool store) 1722d71ae5a4SJacob Faibussowitsch { 172375d48cdbSStefano Zampini PetscFunctionBegin; 172475d48cdbSStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 172575d48cdbSStefano Zampini PetscValidType(A, 1); 172675d48cdbSStefano Zampini PetscValidLogicalCollectiveBool(A, store, 2); 1727cac4c232SBarry Smith PetscTryMethod(A, "MatISStoreL2L_C", (Mat, PetscBool), (A, store)); 17283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 172975d48cdbSStefano Zampini } 173075d48cdbSStefano Zampini 1731d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISStoreL2L_IS(Mat A, PetscBool store) 1732d71ae5a4SJacob Faibussowitsch { 1733f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)A->data; 173475d48cdbSStefano Zampini 173575d48cdbSStefano Zampini PetscFunctionBegin; 173675d48cdbSStefano Zampini matis->storel2l = store; 173757508eceSPierre Jolivet if (!store) PetscCall(PetscObjectCompose((PetscObject)A, "_MatIS_PtAP_l2l", NULL)); 17383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 173975d48cdbSStefano Zampini } 174075d48cdbSStefano Zampini 174175d48cdbSStefano Zampini /*@ 1742f03112d0SStefano Zampini MatISFixLocalEmpty - Compress out zero local rows from the local matrices 1743f03112d0SStefano Zampini 17444f58015eSStefano Zampini Logically Collective 1745f03112d0SStefano Zampini 1746f03112d0SStefano Zampini Input Parameters: 1747f03112d0SStefano Zampini + A - the matrix 1748f03112d0SStefano Zampini - fix - the boolean flag 1749f03112d0SStefano Zampini 1750f03112d0SStefano Zampini Level: advanced 1751f03112d0SStefano Zampini 175211a5261eSBarry Smith Note: 17532fe279fdSBarry Smith When `fix` is `PETSC_TRUE`, new local matrices and l2g maps are generated during the final assembly process. 1754f03112d0SStefano Zampini 17551cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatCreate()`, `MatCreateIS()`, `MatISSetPreallocation()`, `MatAssemblyEnd()`, `MAT_FINAL_ASSEMBLY` 1756f03112d0SStefano Zampini @*/ 1757d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISFixLocalEmpty(Mat A, PetscBool fix) 1758d71ae5a4SJacob Faibussowitsch { 1759f03112d0SStefano Zampini PetscFunctionBegin; 1760f03112d0SStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1761f03112d0SStefano Zampini PetscValidType(A, 1); 1762f03112d0SStefano Zampini PetscValidLogicalCollectiveBool(A, fix, 2); 1763cac4c232SBarry Smith PetscTryMethod(A, "MatISFixLocalEmpty_C", (Mat, PetscBool), (A, fix)); 17643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1765f03112d0SStefano Zampini } 1766f03112d0SStefano Zampini 1767d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISFixLocalEmpty_IS(Mat A, PetscBool fix) 1768d71ae5a4SJacob Faibussowitsch { 1769f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)A->data; 1770f03112d0SStefano Zampini 1771f03112d0SStefano Zampini PetscFunctionBegin; 1772f03112d0SStefano Zampini matis->locempty = fix; 17733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1774f03112d0SStefano Zampini } 1775f03112d0SStefano Zampini 1776f03112d0SStefano Zampini /*@ 177711a5261eSBarry Smith MatISSetPreallocation - Preallocates memory for a `MATIS` parallel matrix. 1778a88811baSStefano Zampini 1779d083f849SBarry Smith Collective 1780a88811baSStefano Zampini 1781a88811baSStefano Zampini Input Parameters: 1782a88811baSStefano Zampini + B - the matrix 1783a88811baSStefano Zampini . d_nz - number of nonzeros per row in DIAGONAL portion of local submatrix 1784a88811baSStefano Zampini (same value is used for all local rows) 1785a88811baSStefano Zampini . d_nnz - array containing the number of nonzeros in the various rows of the 1786a88811baSStefano Zampini DIAGONAL portion of the local submatrix (possibly different for each row) 17872ef1f0ffSBarry Smith or `NULL`, if `d_nz` is used to specify the nonzero structure. 17882ef1f0ffSBarry Smith The size of this array is equal to the number of local rows, i.e `m`. 1789a88811baSStefano Zampini For matrices that will be factored, you must leave room for (and set) 1790a88811baSStefano Zampini the diagonal entry even if it is zero. 1791a88811baSStefano Zampini . o_nz - number of nonzeros per row in the OFF-DIAGONAL portion of local 1792a88811baSStefano Zampini submatrix (same value is used for all local rows). 1793a88811baSStefano Zampini - o_nnz - array containing the number of nonzeros in the various rows of the 1794a88811baSStefano Zampini OFF-DIAGONAL portion of the local submatrix (possibly different for 17952ef1f0ffSBarry Smith each row) or `NULL`, if `o_nz` is used to specify the nonzero 1796a88811baSStefano Zampini structure. The size of this array is equal to the number 17972ef1f0ffSBarry Smith of local rows, i.e `m`. 1798a88811baSStefano Zampini 1799a88811baSStefano Zampini If the *_nnz parameter is given then the *_nz parameter is ignored 1800a88811baSStefano Zampini 1801a88811baSStefano Zampini Level: intermediate 1802a88811baSStefano Zampini 180311a5261eSBarry Smith Note: 180411a5261eSBarry Smith This function has the same interface as the `MATMPIAIJ` preallocation routine in order to simplify the transition 180511a5261eSBarry Smith from the asssembled format to the unassembled one. It overestimates the preallocation of `MATIS` local 1806a88811baSStefano Zampini matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects. 1807a88811baSStefano Zampini 18081cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateIS()`, `MatMPIAIJSetPreallocation()`, `MatISGetLocalMat()`, `MATIS` 1809a88811baSStefano Zampini @*/ 1810d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISSetPreallocation(Mat B, PetscInt d_nz, const PetscInt d_nnz[], PetscInt o_nz, const PetscInt o_nnz[]) 1811d71ae5a4SJacob Faibussowitsch { 18122e1947a5SStefano Zampini PetscFunctionBegin; 18132e1947a5SStefano Zampini PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 18142e1947a5SStefano Zampini PetscValidType(B, 1); 1815cac4c232SBarry Smith PetscTryMethod(B, "MatISSetPreallocation_C", (Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]), (B, d_nz, d_nnz, o_nz, o_nnz)); 18163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18172e1947a5SStefano Zampini } 18182e1947a5SStefano Zampini 1819523895eeSPierre Jolivet static PetscErrorCode MatISSetPreallocation_IS(Mat B, PetscInt d_nz, const PetscInt d_nnz[], PetscInt o_nz, const PetscInt o_nnz[]) 1820d71ae5a4SJacob Faibussowitsch { 1821f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)B->data; 182228f4e0baSStefano Zampini PetscInt bs, i, nlocalcols; 18232e1947a5SStefano Zampini 18242e1947a5SStefano Zampini PetscFunctionBegin; 18259566063dSJacob Faibussowitsch PetscCall(MatSetUp(B)); 18269371c9d4SSatish Balay if (!d_nnz) 18279371c9d4SSatish Balay for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] = d_nz; 18289371c9d4SSatish Balay else 18299371c9d4SSatish Balay for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] = d_nnz[i]; 18304f2d7cafSStefano Zampini 18319371c9d4SSatish Balay if (!o_nnz) 18329371c9d4SSatish Balay for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] += o_nz; 18339371c9d4SSatish Balay else 18349371c9d4SSatish Balay for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] += o_nnz[i]; 18354f2d7cafSStefano Zampini 18369566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 18379566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, NULL, &nlocalcols)); 18389566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(matis->A, &bs)); 18399566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 18404f2d7cafSStefano Zampini 18414f2d7cafSStefano Zampini for (i = 0; i < matis->sf->nleaves; i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i], nlocalcols); 18429566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(matis->A, 0, matis->sf_leafdata)); 18430f2f62c7SStefano Zampini #if defined(PETSC_HAVE_HYPRE) 18449566063dSJacob Faibussowitsch PetscCall(MatHYPRESetPreallocation(matis->A, 0, matis->sf_leafdata, 0, NULL)); 18450f2f62c7SStefano Zampini #endif 18464f2d7cafSStefano Zampini 1847fc989267SStefano Zampini for (i = 0; i < matis->sf->nleaves / bs; i++) { 1848fc989267SStefano Zampini PetscInt b; 1849fc989267SStefano Zampini 1850fc989267SStefano Zampini matis->sf_leafdata[i] = matis->sf_leafdata[i * bs] / bs; 1851ad540459SPierre Jolivet for (b = 1; b < bs; b++) matis->sf_leafdata[i] = PetscMax(matis->sf_leafdata[i], matis->sf_leafdata[i * bs + b] / bs); 1852fc989267SStefano Zampini } 18539566063dSJacob Faibussowitsch PetscCall(MatSeqBAIJSetPreallocation(matis->A, bs, 0, matis->sf_leafdata)); 18544f2d7cafSStefano Zampini 185500a59248SStefano Zampini nlocalcols /= bs; 185600a59248SStefano Zampini for (i = 0; i < matis->sf->nleaves / bs; i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i], nlocalcols - i); 18579566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(matis->A, bs, 0, matis->sf_leafdata)); 18580f2f62c7SStefano Zampini 18590f2f62c7SStefano Zampini /* for other matrix types */ 18609566063dSJacob Faibussowitsch PetscCall(MatSetUp(matis->A)); 18613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18622e1947a5SStefano Zampini } 1863b4319ba4SBarry Smith 1864d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_IS_XAIJ(Mat mat, MatType mtype, MatReuse reuse, Mat *M) 1865d71ae5a4SJacob Faibussowitsch { 1866f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)mat->data; 1867ac7f1a8bSStefano Zampini Mat local_mat = NULL, MT; 186853b44cf5SStefano Zampini PetscInt rbs, cbs, rows, cols, lrows, lcols; 1869b7ce53b6SStefano Zampini PetscInt local_rows, local_cols; 1870b9ed4604SStefano Zampini PetscBool isseqdense, isseqsbaij, isseqaij, isseqbaij; 1871f03112d0SStefano Zampini PetscMPIInt size; 18721683a169SBarry Smith const PetscScalar *array; 1873b7ce53b6SStefano Zampini 1874b7ce53b6SStefano Zampini PetscFunctionBegin; 18759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 18764f58015eSStefano Zampini if (size == 1 && mat->rmap->N == matis->A->rmap->N && mat->cmap->N == matis->A->cmap->N && !matis->allow_repeated) { 18771670daf9Sstefano_zampini Mat B; 187853b44cf5SStefano Zampini IS irows = NULL, icols = NULL; 1879487b449aSStefano Zampini PetscInt rbs, cbs; 18801670daf9Sstefano_zampini 18819566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->rmapping, &rbs)); 18829566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->cmapping, &cbs)); 188353b44cf5SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { /* check if l2g maps are one-to-one */ 188453b44cf5SStefano Zampini IS rows, cols; 188553b44cf5SStefano Zampini const PetscInt *ridxs, *cidxs; 18864f58015eSStefano Zampini PetscInt i, nw; 18874f58015eSStefano Zampini PetscBT work; 188853b44cf5SStefano Zampini 18899566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(matis->rmapping, &ridxs)); 18909566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->rmapping, &nw)); 189153b44cf5SStefano Zampini nw = nw / rbs; 18924f58015eSStefano Zampini PetscCall(PetscBTCreate(nw, &work)); 18934f58015eSStefano Zampini for (i = 0; i < nw; i++) PetscCall(PetscBTSet(work, ridxs[i])); 18949371c9d4SSatish Balay for (i = 0; i < nw; i++) 18954f58015eSStefano Zampini if (!PetscBTLookup(work, i)) break; 189653b44cf5SStefano Zampini if (i == nw) { 18979566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF, rbs, nw, ridxs, PETSC_USE_POINTER, &rows)); 18989566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(rows)); 18999566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(rows, PETSC_DECIDE, &irows)); 19009566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rows)); 190153b44cf5SStefano Zampini } 19029566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(matis->rmapping, &ridxs)); 19034f58015eSStefano Zampini PetscCall(PetscBTDestroy(&work)); 1904e432b41dSStefano Zampini if (irows && matis->rmapping != matis->cmapping) { 19059566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(matis->cmapping, &cidxs)); 19069566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->cmapping, &nw)); 190753b44cf5SStefano Zampini nw = nw / cbs; 19084f58015eSStefano Zampini PetscCall(PetscBTCreate(nw, &work)); 19094f58015eSStefano Zampini for (i = 0; i < nw; i++) PetscCall(PetscBTSet(work, cidxs[i])); 19109371c9d4SSatish Balay for (i = 0; i < nw; i++) 19114f58015eSStefano Zampini if (!PetscBTLookup(work, i)) break; 191253b44cf5SStefano Zampini if (i == nw) { 19139566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF, cbs, nw, cidxs, PETSC_USE_POINTER, &cols)); 19149566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(cols)); 19159566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(cols, PETSC_DECIDE, &icols)); 19169566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cols)); 191753b44cf5SStefano Zampini } 19189566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(matis->cmapping, &cidxs)); 19194f58015eSStefano Zampini PetscCall(PetscBTDestroy(&work)); 192053b44cf5SStefano Zampini } else if (irows) { 19219566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)irows)); 192253b44cf5SStefano Zampini icols = irows; 192353b44cf5SStefano Zampini } 192453b44cf5SStefano Zampini } else { 1925f4f49eeaSPierre Jolivet PetscCall(PetscObjectQuery((PetscObject)*M, "_MatIS_IS_XAIJ_irows", (PetscObject *)&irows)); 1926f4f49eeaSPierre Jolivet PetscCall(PetscObjectQuery((PetscObject)*M, "_MatIS_IS_XAIJ_icols", (PetscObject *)&icols)); 19279566063dSJacob Faibussowitsch if (irows) PetscCall(PetscObjectReference((PetscObject)irows)); 19289566063dSJacob Faibussowitsch if (icols) PetscCall(PetscObjectReference((PetscObject)icols)); 192953b44cf5SStefano Zampini } 193053b44cf5SStefano Zampini if (!irows || !icols) { 19319566063dSJacob Faibussowitsch PetscCall(ISDestroy(&icols)); 19329566063dSJacob Faibussowitsch PetscCall(ISDestroy(&irows)); 193353b44cf5SStefano Zampini goto general_assembly; 193453b44cf5SStefano Zampini } 19359566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, mtype, MAT_INITIAL_MATRIX, &B)); 1936487b449aSStefano Zampini if (reuse != MAT_INPLACE_MATRIX) { 19379566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(B, irows, icols, reuse, M)); 1938f4f49eeaSPierre Jolivet PetscCall(PetscObjectCompose((PetscObject)*M, "_MatIS_IS_XAIJ_irows", (PetscObject)irows)); 1939f4f49eeaSPierre Jolivet PetscCall(PetscObjectCompose((PetscObject)*M, "_MatIS_IS_XAIJ_icols", (PetscObject)icols)); 1940487b449aSStefano Zampini } else { 1941487b449aSStefano Zampini Mat C; 1942487b449aSStefano Zampini 19439566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(B, irows, icols, MAT_INITIAL_MATRIX, &C)); 19449566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(mat, &C)); 1945487b449aSStefano Zampini } 19469566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 19479566063dSJacob Faibussowitsch PetscCall(ISDestroy(&icols)); 19489566063dSJacob Faibussowitsch PetscCall(ISDestroy(&irows)); 19493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19507c03b4e8SStefano Zampini } 195153b44cf5SStefano Zampini general_assembly: 19529566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &rows, &cols)); 19539566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->rmapping, &rbs)); 19549566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->cmapping, &cbs)); 19559566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mat, &lrows, &lcols)); 19569566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, &local_rows, &local_cols)); 19579566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQDENSE, &isseqdense)); 19589566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQAIJ, &isseqaij)); 19599566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQBAIJ, &isseqbaij)); 19609566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQSBAIJ, &isseqsbaij)); 1961f4f49eeaSPierre Jolivet PetscCheck(isseqdense || isseqaij || isseqbaij || isseqsbaij, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)matis->A)->type_name); 196276bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 196376bd3646SJed Brown PetscBool lb[4], bb[4]; 196476bd3646SJed Brown 1965b9ed4604SStefano Zampini lb[0] = isseqdense; 1966b9ed4604SStefano Zampini lb[1] = isseqaij; 1967b9ed4604SStefano Zampini lb[2] = isseqbaij; 1968b9ed4604SStefano Zampini lb[3] = isseqsbaij; 19695440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(lb, bb, 4, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)mat))); 1970aed4548fSBarry Smith PetscCheck(bb[0] || bb[1] || bb[2] || bb[3], PETSC_COMM_SELF, PETSC_ERR_SUP, "Local matrices must have the same type"); 197176bd3646SJed Brown } 1972b7ce53b6SStefano Zampini 1973487b449aSStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 1974ac7f1a8bSStefano Zampini PetscCount ncoo; 1975ac7f1a8bSStefano Zampini PetscInt *coo_i, *coo_j; 1976ac7f1a8bSStefano Zampini 19779566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &MT)); 19789566063dSJacob Faibussowitsch PetscCall(MatSetSizes(MT, lrows, lcols, rows, cols)); 19799566063dSJacob Faibussowitsch PetscCall(MatSetType(MT, mtype)); 19809566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(MT, rbs, cbs)); 1981ac7f1a8bSStefano Zampini if (!isseqaij && !isseqdense) { 1982ac7f1a8bSStefano Zampini PetscCall(MatConvert(matis->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &local_mat)); 1983ac7f1a8bSStefano Zampini } else { 1984ac7f1a8bSStefano Zampini PetscCall(PetscObjectReference((PetscObject)matis->A)); 1985ac7f1a8bSStefano Zampini local_mat = matis->A; 1986ac7f1a8bSStefano Zampini } 1987ac7f1a8bSStefano Zampini PetscCall(MatSetLocalToGlobalMapping(MT, matis->rmapping, matis->cmapping)); 1988ac7f1a8bSStefano Zampini if (isseqdense) { 1989ac7f1a8bSStefano Zampini PetscInt nr, nc; 1990ac7f1a8bSStefano Zampini 1991ac7f1a8bSStefano Zampini PetscCall(MatGetSize(local_mat, &nr, &nc)); 1992ac7f1a8bSStefano Zampini ncoo = nr * nc; 1993ac7f1a8bSStefano Zampini PetscCall(PetscMalloc2(ncoo, &coo_i, ncoo, &coo_j)); 1994ac7f1a8bSStefano Zampini for (PetscInt j = 0; j < nc; j++) { 1995ac7f1a8bSStefano Zampini for (PetscInt i = 0; i < nr; i++) { 1996ac7f1a8bSStefano Zampini coo_i[j * nr + i] = i; 1997ac7f1a8bSStefano Zampini coo_j[j * nr + i] = j; 1998ac7f1a8bSStefano Zampini } 1999ac7f1a8bSStefano Zampini } 2000ac7f1a8bSStefano Zampini } else { 2001ac7f1a8bSStefano Zampini const PetscInt *ii, *jj; 2002ac7f1a8bSStefano Zampini PetscInt nr; 2003ac7f1a8bSStefano Zampini PetscBool done; 2004ac7f1a8bSStefano Zampini 2005ac7f1a8bSStefano Zampini PetscCall(MatGetRowIJ(local_mat, 0, PETSC_FALSE, PETSC_FALSE, &nr, &ii, &jj, &done)); 2006ac7f1a8bSStefano Zampini PetscCheck(done, PetscObjectComm((PetscObject)local_mat), PETSC_ERR_PLIB, "Error in MatGetRowIJ"); 2007ac7f1a8bSStefano Zampini ncoo = ii[nr]; 2008ac7f1a8bSStefano Zampini PetscCall(PetscMalloc2(ncoo, &coo_i, ncoo, &coo_j)); 2009ac7f1a8bSStefano Zampini PetscCall(PetscArraycpy(coo_j, jj, ncoo)); 2010ac7f1a8bSStefano Zampini for (PetscInt i = 0; i < nr; i++) { 2011ac7f1a8bSStefano Zampini for (PetscInt j = ii[i]; j < ii[i + 1]; j++) coo_i[j] = i; 2012ac7f1a8bSStefano Zampini } 2013ac7f1a8bSStefano Zampini PetscCall(MatRestoreRowIJ(local_mat, 0, PETSC_FALSE, PETSC_FALSE, &nr, &ii, &jj, &done)); 2014ac7f1a8bSStefano Zampini PetscCheck(done, PetscObjectComm((PetscObject)local_mat), PETSC_ERR_PLIB, "Error in MatRestoreRowIJ"); 2015ac7f1a8bSStefano Zampini } 2016ac7f1a8bSStefano Zampini PetscCall(MatSetPreallocationCOOLocal(MT, ncoo, coo_i, coo_j)); 2017ac7f1a8bSStefano Zampini PetscCall(PetscFree2(coo_i, coo_j)); 2018b7ce53b6SStefano Zampini } else { 201953b44cf5SStefano Zampini PetscInt mrbs, mcbs, mrows, mcols, mlrows, mlcols; 2020487b449aSStefano Zampini 2021b7ce53b6SStefano Zampini /* some checks */ 2022487b449aSStefano Zampini MT = *M; 20239566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(MT, &mrbs, &mcbs)); 20249566063dSJacob Faibussowitsch PetscCall(MatGetSize(MT, &mrows, &mcols)); 20259566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(MT, &mlrows, &mlcols)); 202608401ef6SPierre Jolivet PetscCheck(mrows == rows, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of rows (%" PetscInt_FMT " != %" PetscInt_FMT ")", rows, mrows); 202708401ef6SPierre Jolivet PetscCheck(mcols == cols, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of cols (%" PetscInt_FMT " != %" PetscInt_FMT ")", cols, mcols); 202808401ef6SPierre Jolivet PetscCheck(mlrows == lrows, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of local rows (%" PetscInt_FMT " != %" PetscInt_FMT ")", lrows, mlrows); 202908401ef6SPierre Jolivet PetscCheck(mlcols == lcols, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of local cols (%" PetscInt_FMT " != %" PetscInt_FMT ")", lcols, mlcols); 203008401ef6SPierre Jolivet PetscCheck(mrbs == rbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong row block size (%" PetscInt_FMT " != %" PetscInt_FMT ")", rbs, mrbs); 203108401ef6SPierre Jolivet PetscCheck(mcbs == cbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong col block size (%" PetscInt_FMT " != %" PetscInt_FMT ")", cbs, mcbs); 20329566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(MT)); 2033ac7f1a8bSStefano Zampini if (!isseqaij && !isseqdense) { 20349566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &local_mat)); 2035d9a9e74cSStefano Zampini } else { 20369566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)matis->A)); 2037d9a9e74cSStefano Zampini local_mat = matis->A; 2038d9a9e74cSStefano Zampini } 2039ac7f1a8bSStefano Zampini } 2040686e3a49SStefano Zampini 2041b7ce53b6SStefano Zampini /* Set values */ 2042ac7f1a8bSStefano Zampini if (isseqdense) { 20439566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(local_mat, &array)); 2044ac7f1a8bSStefano Zampini PetscCall(MatSetValuesCOO(MT, array, INSERT_VALUES)); 20459566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(local_mat, &array)); 20466afe12f5SStefano Zampini } else { 2047ac7f1a8bSStefano Zampini PetscCall(MatSeqAIJGetArrayRead(local_mat, &array)); 2048ac7f1a8bSStefano Zampini PetscCall(MatSetValuesCOO(MT, array, INSERT_VALUES)); 2049ac7f1a8bSStefano Zampini PetscCall(MatSeqAIJRestoreArrayRead(local_mat, &array)); 2050b7ce53b6SStefano Zampini } 20519566063dSJacob Faibussowitsch PetscCall(MatDestroy(&local_mat)); 20524f58015eSStefano Zampini PetscCall(MatAssemblyBegin(MT, MAT_FINAL_ASSEMBLY)); 20539566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(MT, MAT_FINAL_ASSEMBLY)); 2054487b449aSStefano Zampini if (reuse == MAT_INPLACE_MATRIX) { 20559566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(mat, &MT)); 2056487b449aSStefano Zampini } else if (reuse == MAT_INITIAL_MATRIX) { 2057487b449aSStefano Zampini *M = MT; 2058b7ce53b6SStefano Zampini } 20593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2060b7ce53b6SStefano Zampini } 2061b7ce53b6SStefano Zampini 2062d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDuplicate_IS(Mat mat, MatDuplicateOption op, Mat *newmat) 2063d71ae5a4SJacob Faibussowitsch { 2064f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)mat->data; 2065c9225affSStefano Zampini PetscInt rbs, cbs, m, n, M, N; 2066ad6194a2SStefano Zampini Mat B, localmat; 2067ad6194a2SStefano Zampini 2068ad6194a2SStefano Zampini PetscFunctionBegin; 20699566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &rbs)); 20709566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &cbs)); 20719566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &M, &N)); 20729566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mat, &m, &n)); 20739566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 20749566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, m, n, M, N)); 20759566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(B, rbs == cbs ? rbs : 1)); 20769566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATIS)); 20779566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(B, matis->lmattype)); 20784f58015eSStefano Zampini PetscCall(MatISSetAllowRepeated(B, matis->allow_repeated)); 20799566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B, mat->rmap->mapping, mat->cmap->mapping)); 20809566063dSJacob Faibussowitsch PetscCall(MatDuplicate(matis->A, op, &localmat)); 20819566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(localmat, matis->A->rmap->mapping, matis->A->cmap->mapping)); 20829566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B, localmat)); 20839566063dSJacob Faibussowitsch PetscCall(MatDestroy(&localmat)); 20849566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 20859566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 2086ad6194a2SStefano Zampini *newmat = B; 20873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2088ad6194a2SStefano Zampini } 2089ad6194a2SStefano Zampini 2090d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsHermitian_IS(Mat A, PetscReal tol, PetscBool *flg) 2091d71ae5a4SJacob Faibussowitsch { 209269796d55SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 209369796d55SStefano Zampini PetscBool local_sym; 209469796d55SStefano Zampini 209569796d55SStefano Zampini PetscFunctionBegin; 20969566063dSJacob Faibussowitsch PetscCall(MatIsHermitian(matis->A, tol, &local_sym)); 20975440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&local_sym, flg, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 20983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 209969796d55SStefano Zampini } 210069796d55SStefano Zampini 2101d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsSymmetric_IS(Mat A, PetscReal tol, PetscBool *flg) 2102d71ae5a4SJacob Faibussowitsch { 210369796d55SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 210469796d55SStefano Zampini PetscBool local_sym; 210569796d55SStefano Zampini 210669796d55SStefano Zampini PetscFunctionBegin; 2107e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { 2108e432b41dSStefano Zampini *flg = PETSC_FALSE; 21093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2110e432b41dSStefano Zampini } 21119566063dSJacob Faibussowitsch PetscCall(MatIsSymmetric(matis->A, tol, &local_sym)); 21125440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&local_sym, flg, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 21133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 211469796d55SStefano Zampini } 211569796d55SStefano Zampini 2116d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A, PetscBool *flg) 2117d71ae5a4SJacob Faibussowitsch { 211845471136SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 211945471136SStefano Zampini PetscBool local_sym; 212045471136SStefano Zampini 212145471136SStefano Zampini PetscFunctionBegin; 2122e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { 212345471136SStefano Zampini *flg = PETSC_FALSE; 21243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 212545471136SStefano Zampini } 21269566063dSJacob Faibussowitsch PetscCall(MatIsStructurallySymmetric(matis->A, &local_sym)); 21275440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&local_sym, flg, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 21283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 212945471136SStefano Zampini } 213045471136SStefano Zampini 2131d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_IS(Mat A) 2132d71ae5a4SJacob Faibussowitsch { 2133b4319ba4SBarry Smith Mat_IS *b = (Mat_IS *)A->data; 2134b4319ba4SBarry Smith 2135b4319ba4SBarry Smith PetscFunctionBegin; 21369566063dSJacob Faibussowitsch PetscCall(PetscFree(b->bdiag)); 21379566063dSJacob Faibussowitsch PetscCall(PetscFree(b->lmattype)); 21389566063dSJacob Faibussowitsch PetscCall(MatDestroy(&b->A)); 21399566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&b->cctx)); 21409566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&b->rctx)); 21419566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->x)); 21429566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->y)); 21439566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->counter)); 21449566063dSJacob Faibussowitsch PetscCall(ISDestroy(&b->getsub_ris)); 21459566063dSJacob Faibussowitsch PetscCall(ISDestroy(&b->getsub_cis)); 2146a8116848SStefano Zampini if (b->sf != b->csf) { 21479566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&b->csf)); 21489566063dSJacob Faibussowitsch PetscCall(PetscFree2(b->csf_rootdata, b->csf_leafdata)); 2149f03112d0SStefano Zampini } else b->csf = NULL; 21509566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&b->sf)); 21519566063dSJacob Faibussowitsch PetscCall(PetscFree2(b->sf_rootdata, b->sf_leafdata)); 21529566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&b->rmapping)); 21539566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&b->cmapping)); 2154d0dbe9f7SStefano Zampini PetscCall(MatDestroy(&b->dA)); 2155d0dbe9f7SStefano Zampini PetscCall(MatDestroy(&b->assembledA)); 21569566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 21579566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, NULL)); 21589566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMatType_C", NULL)); 21599566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalMat_C", NULL)); 21609566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMat_C", NULL)); 21612e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISRestoreLocalMat_C", NULL)); 21629566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetPreallocation_C", NULL)); 21639566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISStoreL2L_C", NULL)); 21649566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISFixLocalEmpty_C", NULL)); 21659566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalToGlobalMapping_C", NULL)); 21669566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpiaij_C", NULL)); 21679566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpibaij_C", NULL)); 21689566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpisbaij_C", NULL)); 21699566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqaij_C", NULL)); 21709566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqbaij_C", NULL)); 21719566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqsbaij_C", NULL)); 21729566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_aij_C", NULL)); 21739566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOOLocal_C", NULL)); 21749566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL)); 21759566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL)); 21764f58015eSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetAllowRepeated_C", NULL)); 21773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2178b4319ba4SBarry Smith } 2179b4319ba4SBarry Smith 2180d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_IS(Mat A, Vec x, Vec y) 2181d71ae5a4SJacob Faibussowitsch { 2182b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)A->data; 2183b4319ba4SBarry Smith PetscScalar zero = 0.0; 2184b4319ba4SBarry Smith 2185b4319ba4SBarry Smith PetscFunctionBegin; 2186b4319ba4SBarry Smith /* scatter the global vector x into the local work vector */ 21879566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->cctx, x, is->x, INSERT_VALUES, SCATTER_FORWARD)); 21889566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->cctx, x, is->x, INSERT_VALUES, SCATTER_FORWARD)); 2189b4319ba4SBarry Smith 2190b4319ba4SBarry Smith /* multiply the local matrix */ 21919566063dSJacob Faibussowitsch PetscCall(MatMult(is->A, is->x, is->y)); 2192b4319ba4SBarry Smith 2193b4319ba4SBarry Smith /* scatter product back into global memory */ 21949566063dSJacob Faibussowitsch PetscCall(VecSet(y, zero)); 21959566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, is->y, y, ADD_VALUES, SCATTER_REVERSE)); 21969566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, is->y, y, ADD_VALUES, SCATTER_REVERSE)); 21973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2198b4319ba4SBarry Smith } 2199b4319ba4SBarry Smith 2200d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultAdd_IS(Mat A, Vec v1, Vec v2, Vec v3) 2201d71ae5a4SJacob Faibussowitsch { 2202650997f4SStefano Zampini Vec temp_vec; 22032e74eeadSLisandro Dalcin 22042e74eeadSLisandro Dalcin PetscFunctionBegin; /* v3 = v2 + A * v1.*/ 2205650997f4SStefano Zampini if (v3 != v2) { 22069566063dSJacob Faibussowitsch PetscCall(MatMult(A, v1, v3)); 22079566063dSJacob Faibussowitsch PetscCall(VecAXPY(v3, 1.0, v2)); 2208650997f4SStefano Zampini } else { 22099566063dSJacob Faibussowitsch PetscCall(VecDuplicate(v2, &temp_vec)); 22109566063dSJacob Faibussowitsch PetscCall(MatMult(A, v1, temp_vec)); 22119566063dSJacob Faibussowitsch PetscCall(VecAXPY(temp_vec, 1.0, v2)); 22129566063dSJacob Faibussowitsch PetscCall(VecCopy(temp_vec, v3)); 22139566063dSJacob Faibussowitsch PetscCall(VecDestroy(&temp_vec)); 2214650997f4SStefano Zampini } 22153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22162e74eeadSLisandro Dalcin } 22172e74eeadSLisandro Dalcin 2218d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTranspose_IS(Mat A, Vec y, Vec x) 2219d71ae5a4SJacob Faibussowitsch { 22202e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS *)A->data; 22212e74eeadSLisandro Dalcin 2222e176bc59SStefano Zampini PetscFunctionBegin; 22232e74eeadSLisandro Dalcin /* scatter the global vector x into the local work vector */ 22249566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, y, is->y, INSERT_VALUES, SCATTER_FORWARD)); 22259566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, y, is->y, INSERT_VALUES, SCATTER_FORWARD)); 22262e74eeadSLisandro Dalcin 22272e74eeadSLisandro Dalcin /* multiply the local matrix */ 22289566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(is->A, is->y, is->x)); 22292e74eeadSLisandro Dalcin 22302e74eeadSLisandro Dalcin /* scatter product back into global vector */ 22319566063dSJacob Faibussowitsch PetscCall(VecSet(x, 0)); 22329566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->cctx, is->x, x, ADD_VALUES, SCATTER_REVERSE)); 22339566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->cctx, is->x, x, ADD_VALUES, SCATTER_REVERSE)); 22343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22352e74eeadSLisandro Dalcin } 22362e74eeadSLisandro Dalcin 2237d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTransposeAdd_IS(Mat A, Vec v1, Vec v2, Vec v3) 2238d71ae5a4SJacob Faibussowitsch { 2239650997f4SStefano Zampini Vec temp_vec; 22402e74eeadSLisandro Dalcin 22412e74eeadSLisandro Dalcin PetscFunctionBegin; /* v3 = v2 + A' * v1.*/ 2242650997f4SStefano Zampini if (v3 != v2) { 22439566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(A, v1, v3)); 22449566063dSJacob Faibussowitsch PetscCall(VecAXPY(v3, 1.0, v2)); 2245650997f4SStefano Zampini } else { 22469566063dSJacob Faibussowitsch PetscCall(VecDuplicate(v2, &temp_vec)); 22479566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(A, v1, temp_vec)); 22489566063dSJacob Faibussowitsch PetscCall(VecAXPY(temp_vec, 1.0, v2)); 22499566063dSJacob Faibussowitsch PetscCall(VecCopy(temp_vec, v3)); 22509566063dSJacob Faibussowitsch PetscCall(VecDestroy(&temp_vec)); 2251650997f4SStefano Zampini } 22523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22532e74eeadSLisandro Dalcin } 22542e74eeadSLisandro Dalcin 2255a3ef7f04SStefano Zampini static PetscErrorCode ISLocalToGlobalMappingView_Multi(ISLocalToGlobalMapping mapping, PetscInt lsize, PetscInt gsize, const PetscInt vblocks[], PetscViewer viewer) 2256a3ef7f04SStefano Zampini { 2257a3ef7f04SStefano Zampini PetscInt tr[3], n; 2258a3ef7f04SStefano Zampini const PetscInt *indices; 2259a3ef7f04SStefano Zampini 2260a3ef7f04SStefano Zampini PetscFunctionBegin; 2261a3ef7f04SStefano Zampini tr[0] = IS_LTOGM_FILE_CLASSID; 2262a3ef7f04SStefano Zampini tr[1] = 1; 2263a3ef7f04SStefano Zampini tr[2] = gsize; 2264a3ef7f04SStefano Zampini PetscCall(PetscViewerBinaryWrite(viewer, tr, 3, PETSC_INT)); 2265a3ef7f04SStefano Zampini PetscCall(PetscViewerBinaryWriteAll(viewer, vblocks, lsize, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT)); 2266a3ef7f04SStefano Zampini PetscCall(ISLocalToGlobalMappingGetSize(mapping, &n)); 2267a3ef7f04SStefano Zampini PetscCall(ISLocalToGlobalMappingGetIndices(mapping, &indices)); 2268a3ef7f04SStefano Zampini PetscCall(PetscViewerBinaryWriteAll(viewer, indices, n, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT)); 2269a3ef7f04SStefano Zampini PetscCall(ISLocalToGlobalMappingRestoreIndices(mapping, &indices)); 2270a3ef7f04SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2271a3ef7f04SStefano Zampini } 2272a3ef7f04SStefano Zampini 2273d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_IS(Mat A, PetscViewer viewer) 2274d71ae5a4SJacob Faibussowitsch { 2275b4319ba4SBarry Smith Mat_IS *a = (Mat_IS *)A->data; 2276b4319ba4SBarry Smith PetscViewer sviewer; 22775042aa92SStefano Zampini PetscBool isascii, isbinary, viewl2g = PETSC_FALSE, native; 22785042aa92SStefano Zampini PetscViewerFormat format; 22795042aa92SStefano Zampini ISLocalToGlobalMapping rmap, cmap; 2280b4319ba4SBarry Smith 2281b4319ba4SBarry Smith PetscFunctionBegin; 22829566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 22835042aa92SStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 22849566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 22855042aa92SStefano Zampini native = (PetscBool)(format == PETSC_VIEWER_NATIVE); 22865042aa92SStefano Zampini if (native) { 22875042aa92SStefano Zampini rmap = A->rmap->mapping; 22885042aa92SStefano Zampini cmap = A->cmap->mapping; 22895042aa92SStefano Zampini } else { 22905042aa92SStefano Zampini rmap = a->rmapping; 22915042aa92SStefano Zampini cmap = a->cmapping; 2292ee2491ecSStefano Zampini } 22935042aa92SStefano Zampini if (isascii) { 22945042aa92SStefano Zampini if (format == PETSC_VIEWER_ASCII_INFO) PetscFunctionReturn(PETSC_SUCCESS); 22955042aa92SStefano Zampini if (format == PETSC_VIEWER_ASCII_INFO_DETAIL || format == PETSC_VIEWER_ASCII_MATLAB) viewl2g = PETSC_TRUE; 22965042aa92SStefano Zampini } else if (isbinary) { 2297a3ef7f04SStefano Zampini PetscInt tr[6], nr, nc, lsize = 0; 22985042aa92SStefano Zampini char lmattype[64] = {'\0'}; 22995042aa92SStefano Zampini PetscMPIInt size; 2300a3ef7f04SStefano Zampini PetscBool skipHeader, vbs = PETSC_FALSE; 23015042aa92SStefano Zampini IS is; 2302a3ef7f04SStefano Zampini const PetscInt *vblocks = NULL; 23035042aa92SStefano Zampini 23045042aa92SStefano Zampini PetscCall(PetscViewerSetUp(viewer)); 2305a3ef7f04SStefano Zampini PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)A)->prefix, "-mat_is_view_variableblocksizes", &vbs, NULL)); 2306a3ef7f04SStefano Zampini if (vbs) { 2307a3ef7f04SStefano Zampini PetscCall(MatGetVariableBlockSizes(a->A, &lsize, &vblocks)); 2308a3ef7f04SStefano Zampini PetscCall(PetscMPIIntCast(lsize, &size)); 2309a3ef7f04SStefano Zampini PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &size, 1, MPI_INT, MPI_SUM, PetscObjectComm((PetscObject)viewer))); 2310a3ef7f04SStefano Zampini } else { 23115042aa92SStefano Zampini PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 2312a3ef7f04SStefano Zampini } 23135042aa92SStefano Zampini tr[0] = MAT_FILE_CLASSID; 23145042aa92SStefano Zampini tr[1] = A->rmap->N; 23155042aa92SStefano Zampini tr[2] = A->cmap->N; 23165042aa92SStefano Zampini tr[3] = -size; /* AIJ stores nnz here */ 23175042aa92SStefano Zampini tr[4] = (PetscInt)(rmap == cmap); 23185042aa92SStefano Zampini tr[5] = a->allow_repeated; 23195042aa92SStefano Zampini PetscCall(PetscSNPrintf(lmattype, sizeof(lmattype), "%s", a->lmattype)); 23205042aa92SStefano Zampini 23215042aa92SStefano Zampini PetscCall(PetscViewerBinaryWrite(viewer, tr, PETSC_STATIC_ARRAY_LENGTH(tr), PETSC_INT)); 23225042aa92SStefano Zampini PetscCall(PetscViewerBinaryWrite(viewer, lmattype, sizeof(lmattype), PETSC_CHAR)); 23235042aa92SStefano Zampini 23245042aa92SStefano Zampini /* first dump l2g info (we need the header for proper loading on different number of processes) */ 23255042aa92SStefano Zampini PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader)); 23265042aa92SStefano Zampini PetscCall(PetscViewerBinarySetSkipHeader(viewer, PETSC_FALSE)); 2327a3ef7f04SStefano Zampini if (vbs) { 2328a3ef7f04SStefano Zampini PetscCall(ISLocalToGlobalMappingView_Multi(rmap, lsize, size, vblocks, viewer)); 2329a3ef7f04SStefano Zampini if (cmap != rmap) PetscCall(ISLocalToGlobalMappingView_Multi(cmap, lsize, size, vblocks, viewer)); 2330a3ef7f04SStefano Zampini PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), lsize, vblocks, PETSC_USE_POINTER, &is)); 2331a3ef7f04SStefano Zampini PetscCall(ISView(is, viewer)); 2332a3ef7f04SStefano Zampini PetscCall(ISView(is, viewer)); 2333a3ef7f04SStefano Zampini PetscCall(ISDestroy(&is)); 2334a3ef7f04SStefano Zampini } else { 23355042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingView(rmap, viewer)); 23365042aa92SStefano Zampini if (cmap != rmap) PetscCall(ISLocalToGlobalMappingView(cmap, viewer)); 23375042aa92SStefano Zampini 23385042aa92SStefano Zampini /* then the sizes of the local matrices */ 23395042aa92SStefano Zampini PetscCall(MatGetSize(a->A, &nr, &nc)); 23405042aa92SStefano Zampini PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), 1, &nr, PETSC_USE_POINTER, &is)); 23415042aa92SStefano Zampini PetscCall(ISView(is, viewer)); 23425042aa92SStefano Zampini PetscCall(ISDestroy(&is)); 23435042aa92SStefano Zampini PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), 1, &nc, PETSC_USE_POINTER, &is)); 23445042aa92SStefano Zampini PetscCall(ISView(is, viewer)); 23455042aa92SStefano Zampini PetscCall(ISDestroy(&is)); 2346a3ef7f04SStefano Zampini } 23475042aa92SStefano Zampini PetscCall(PetscViewerBinarySetSkipHeader(viewer, skipHeader)); 23485042aa92SStefano Zampini } 23495042aa92SStefano Zampini if (format == PETSC_VIEWER_ASCII_MATLAB) { 23505042aa92SStefano Zampini char name[64]; 23515042aa92SStefano Zampini PetscMPIInt size, rank; 23525042aa92SStefano Zampini 23535042aa92SStefano Zampini PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 23545042aa92SStefano Zampini PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 23555042aa92SStefano Zampini if (size > 1) PetscCall(PetscSNPrintf(name, sizeof(name), "lmat_%d", rank)); 23565042aa92SStefano Zampini else PetscCall(PetscSNPrintf(name, sizeof(name), "lmat")); 23575042aa92SStefano Zampini PetscCall(PetscObjectSetName((PetscObject)a->A, name)); 23585042aa92SStefano Zampini } 23595042aa92SStefano Zampini 23605042aa92SStefano Zampini /* Dump the local matrices */ 23615042aa92SStefano Zampini if (isbinary) { /* ViewerGetSubViewer does not work in parallel */ 23625042aa92SStefano Zampini PetscBool isaij; 23635042aa92SStefano Zampini PetscInt nr, nc; 23645042aa92SStefano Zampini Mat lA, B; 23655042aa92SStefano Zampini Mat_MPIAIJ *b; 23665042aa92SStefano Zampini 23675042aa92SStefano Zampini /* We create a temporary MPIAIJ matrix that stores the unassembled operator */ 23685042aa92SStefano Zampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)a->A, MATAIJ, &isaij)); 23695042aa92SStefano Zampini if (!isaij) PetscCall(MatConvert(a->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &lA)); 23705042aa92SStefano Zampini else { 23715042aa92SStefano Zampini PetscCall(PetscObjectReference((PetscObject)a->A)); 23725042aa92SStefano Zampini lA = a->A; 23735042aa92SStefano Zampini } 23745042aa92SStefano Zampini PetscCall(MatCreate(PetscObjectComm((PetscObject)viewer), &B)); 23755042aa92SStefano Zampini PetscCall(MatSetType(B, MATMPIAIJ)); 23765042aa92SStefano Zampini PetscCall(MatGetSize(lA, &nr, &nc)); 23775042aa92SStefano Zampini PetscCall(MatSetSizes(B, nr, nc, PETSC_DECIDE, PETSC_DECIDE)); 23785042aa92SStefano Zampini PetscCall(MatMPIAIJSetPreallocation(B, 0, NULL, 0, NULL)); 23795042aa92SStefano Zampini 23805042aa92SStefano Zampini b = (Mat_MPIAIJ *)B->data; 23815042aa92SStefano Zampini PetscCall(MatDestroy(&b->A)); 23825042aa92SStefano Zampini b->A = lA; 23835042aa92SStefano Zampini 23845042aa92SStefano Zampini PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 23855042aa92SStefano Zampini PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 23865042aa92SStefano Zampini PetscCall(MatView(B, viewer)); 23875042aa92SStefano Zampini PetscCall(MatDestroy(&B)); 23885042aa92SStefano Zampini } else { 23899566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 23909566063dSJacob Faibussowitsch PetscCall(MatView(a->A, sviewer)); 23919566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 23925042aa92SStefano Zampini } 23935042aa92SStefano Zampini 23945042aa92SStefano Zampini /* with ASCII, we dump the l2gmaps at the end */ 23955042aa92SStefano Zampini if (viewl2g) { 23965042aa92SStefano Zampini if (format == PETSC_VIEWER_ASCII_MATLAB) { 23975042aa92SStefano Zampini PetscCall(PetscObjectSetName((PetscObject)rmap, "row")); 23985042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingView(rmap, viewer)); 23995042aa92SStefano Zampini PetscCall(PetscObjectSetName((PetscObject)cmap, "col")); 24005042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingView(cmap, viewer)); 24015042aa92SStefano Zampini } else { 24025042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingView(rmap, viewer)); 24035042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingView(cmap, viewer)); 24045042aa92SStefano Zampini } 24055042aa92SStefano Zampini } 24065042aa92SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 24075042aa92SStefano Zampini } 24085042aa92SStefano Zampini 2409a3ef7f04SStefano Zampini static PetscErrorCode ISLocalToGlobalMappingHasRepeatedLocal_Private(ISLocalToGlobalMapping map, PetscBool *has) 2410a3ef7f04SStefano Zampini { 2411a3ef7f04SStefano Zampini const PetscInt *idxs; 2412a3ef7f04SStefano Zampini PetscHSetI ht; 2413a3ef7f04SStefano Zampini PetscInt n, bs; 2414a3ef7f04SStefano Zampini 2415a3ef7f04SStefano Zampini PetscFunctionBegin; 2416a3ef7f04SStefano Zampini PetscCall(ISLocalToGlobalMappingGetSize(map, &n)); 2417a3ef7f04SStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockSize(map, &bs)); 2418a3ef7f04SStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockIndices(map, &idxs)); 2419a3ef7f04SStefano Zampini PetscCall(PetscHSetICreate(&ht)); 2420a3ef7f04SStefano Zampini *has = PETSC_FALSE; 2421a3ef7f04SStefano Zampini for (PetscInt i = 0; i < n / bs; i++) { 2422a3ef7f04SStefano Zampini PetscBool missing = PETSC_TRUE; 2423a3ef7f04SStefano Zampini if (idxs[i] < 0) continue; 2424a3ef7f04SStefano Zampini PetscCall(PetscHSetIQueryAdd(ht, idxs[i], &missing)); 2425a3ef7f04SStefano Zampini if (!missing) { 2426a3ef7f04SStefano Zampini *has = PETSC_TRUE; 2427a3ef7f04SStefano Zampini break; 2428a3ef7f04SStefano Zampini } 2429a3ef7f04SStefano Zampini } 2430a3ef7f04SStefano Zampini PetscCall(PetscHSetIDestroy(&ht)); 2431a3ef7f04SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2432a3ef7f04SStefano Zampini } 2433a3ef7f04SStefano Zampini 24345042aa92SStefano Zampini static PetscErrorCode MatLoad_IS(Mat A, PetscViewer viewer) 24355042aa92SStefano Zampini { 24365042aa92SStefano Zampini ISLocalToGlobalMapping rmap, cmap; 24375042aa92SStefano Zampini MPI_Comm comm = PetscObjectComm((PetscObject)A); 24385042aa92SStefano Zampini PetscBool isbinary, samel, allow, isbaij; 24395042aa92SStefano Zampini PetscInt tr[6], M, N, nr, nc, Asize, isn; 24405042aa92SStefano Zampini const PetscInt *idx; 24415042aa92SStefano Zampini PetscMPIInt size; 24425042aa92SStefano Zampini char lmattype[64]; 24435042aa92SStefano Zampini Mat dA, lA; 24445042aa92SStefano Zampini IS is; 24455042aa92SStefano Zampini 24465042aa92SStefano Zampini PetscFunctionBegin; 24475042aa92SStefano Zampini PetscCheckSameComm(A, 1, viewer, 2); 24485042aa92SStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 24495042aa92SStefano Zampini PetscCheck(isbinary, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Invalid viewer of type %s", ((PetscObject)viewer)->type_name); 24505042aa92SStefano Zampini 24515042aa92SStefano Zampini PetscCall(PetscViewerBinaryRead(viewer, tr, PETSC_STATIC_ARRAY_LENGTH(tr), NULL, PETSC_INT)); 24525042aa92SStefano Zampini PetscCheck(tr[0] == MAT_FILE_CLASSID, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a matrix next in file"); 24535042aa92SStefano Zampini PetscCheck(tr[1] >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a IS matrix next in file"); 24545042aa92SStefano Zampini PetscCheck(tr[2] >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a IS matrix next in file"); 24555042aa92SStefano Zampini PetscCheck(tr[3] < 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a IS matrix next in file"); 24565042aa92SStefano Zampini PetscCheck(tr[4] == 0 || tr[4] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a IS matrix next in file"); 24575042aa92SStefano Zampini PetscCheck(tr[5] == 0 || tr[5] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a IS matrix next in file"); 24585042aa92SStefano Zampini M = tr[1]; 24595042aa92SStefano Zampini N = tr[2]; 24605042aa92SStefano Zampini Asize = -tr[3]; 24615042aa92SStefano Zampini samel = (PetscBool)tr[4]; 24625042aa92SStefano Zampini allow = (PetscBool)tr[5]; 24635042aa92SStefano Zampini PetscCall(PetscViewerBinaryRead(viewer, lmattype, sizeof(lmattype), NULL, PETSC_CHAR)); 24645042aa92SStefano Zampini 24655042aa92SStefano Zampini /* if we are loading from a larger set of processes, allow repeated entries */ 24665042aa92SStefano Zampini PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 24675042aa92SStefano Zampini if (Asize > size) allow = PETSC_TRUE; 24685042aa92SStefano Zampini 24695042aa92SStefano Zampini /* set global sizes if not set already */ 24705042aa92SStefano Zampini if (A->rmap->N < 0) A->rmap->N = M; 24715042aa92SStefano Zampini if (A->cmap->N < 0) A->cmap->N = N; 24725042aa92SStefano Zampini PetscCall(PetscLayoutSetUp(A->rmap)); 24735042aa92SStefano Zampini PetscCall(PetscLayoutSetUp(A->cmap)); 24745042aa92SStefano Zampini PetscCheck(M == A->rmap->N, comm, PETSC_ERR_ARG_SIZ, "Matrix rows should be %" PetscInt_FMT ", found %" PetscInt_FMT, M, A->rmap->N); 24755042aa92SStefano Zampini PetscCheck(N == A->cmap->N, comm, PETSC_ERR_ARG_SIZ, "Matrix columns should be %" PetscInt_FMT ", found %" PetscInt_FMT, N, A->cmap->N); 24765042aa92SStefano Zampini 24775042aa92SStefano Zampini /* load l2g maps */ 24785042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingCreate(comm, 0, 0, NULL, PETSC_USE_POINTER, &rmap)); 24795042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingLoad(rmap, viewer)); 24805042aa92SStefano Zampini if (!samel) { 24815042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingCreate(comm, 0, 0, NULL, PETSC_USE_POINTER, &cmap)); 24825042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingLoad(cmap, viewer)); 24835042aa92SStefano Zampini } else { 24845042aa92SStefano Zampini PetscCall(PetscObjectReference((PetscObject)rmap)); 24855042aa92SStefano Zampini cmap = rmap; 24865042aa92SStefano Zampini } 24875042aa92SStefano Zampini 24885042aa92SStefano Zampini /* load sizes of local matrices */ 24895042aa92SStefano Zampini PetscCall(ISCreate(comm, &is)); 24905042aa92SStefano Zampini PetscCall(ISSetType(is, ISGENERAL)); 24915042aa92SStefano Zampini PetscCall(ISLoad(is, viewer)); 24925042aa92SStefano Zampini PetscCall(ISGetLocalSize(is, &isn)); 24935042aa92SStefano Zampini PetscCall(ISGetIndices(is, &idx)); 24945042aa92SStefano Zampini nr = 0; 24955042aa92SStefano Zampini for (PetscInt i = 0; i < isn; i++) nr += idx[i]; 24965042aa92SStefano Zampini PetscCall(ISRestoreIndices(is, &idx)); 24975042aa92SStefano Zampini PetscCall(ISDestroy(&is)); 24985042aa92SStefano Zampini PetscCall(ISCreate(comm, &is)); 24995042aa92SStefano Zampini PetscCall(ISSetType(is, ISGENERAL)); 25005042aa92SStefano Zampini PetscCall(ISLoad(is, viewer)); 25015042aa92SStefano Zampini PetscCall(ISGetLocalSize(is, &isn)); 25025042aa92SStefano Zampini PetscCall(ISGetIndices(is, &idx)); 25035042aa92SStefano Zampini nc = 0; 25045042aa92SStefano Zampini for (PetscInt i = 0; i < isn; i++) nc += idx[i]; 25055042aa92SStefano Zampini PetscCall(ISRestoreIndices(is, &idx)); 25065042aa92SStefano Zampini PetscCall(ISDestroy(&is)); 25075042aa92SStefano Zampini 25085042aa92SStefano Zampini /* now load the unassembled operator */ 25095042aa92SStefano Zampini PetscCall(MatCreate(comm, &dA)); 25105042aa92SStefano Zampini PetscCall(MatSetType(dA, MATMPIAIJ)); 25115042aa92SStefano Zampini PetscCall(MatSetSizes(dA, nr, nc, PETSC_DECIDE, PETSC_DECIDE)); 25125042aa92SStefano Zampini PetscCall(MatLoad(dA, viewer)); 25135042aa92SStefano Zampini PetscCall(MatMPIAIJGetSeqAIJ(dA, &lA, NULL, NULL)); 25145042aa92SStefano Zampini PetscCall(PetscObjectReference((PetscObject)lA)); 25155042aa92SStefano Zampini PetscCall(MatDestroy(&dA)); 25165042aa92SStefano Zampini 25175042aa92SStefano Zampini /* and convert to the desired format */ 25185042aa92SStefano Zampini PetscCall(PetscStrcmpAny(lmattype, &isbaij, MATSBAIJ, MATSEQSBAIJ, "")); 25195042aa92SStefano Zampini if (isbaij) PetscCall(MatSetOption(lA, MAT_SYMMETRIC, PETSC_TRUE)); 25205042aa92SStefano Zampini PetscCall(MatConvert(lA, lmattype, MAT_INPLACE_MATRIX, &lA)); 25215042aa92SStefano Zampini 2522a3ef7f04SStefano Zampini /* check if we actually have repeated entries */ 2523a3ef7f04SStefano Zampini if (allow) { 2524a3ef7f04SStefano Zampini PetscBool rhas, chas, hasrepeated; 2525a3ef7f04SStefano Zampini 2526a3ef7f04SStefano Zampini PetscCall(ISLocalToGlobalMappingHasRepeatedLocal_Private(rmap, &rhas)); 2527a3ef7f04SStefano Zampini if (rmap != cmap) PetscCall(ISLocalToGlobalMappingHasRepeatedLocal_Private(cmap, &chas)); 2528a3ef7f04SStefano Zampini else chas = rhas; 2529a3ef7f04SStefano Zampini hasrepeated = (PetscBool)(rhas || chas); 25305440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &hasrepeated, 1, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A))); 2531a3ef7f04SStefano Zampini if (!hasrepeated) allow = PETSC_FALSE; 2532a3ef7f04SStefano Zampini } 2533a3ef7f04SStefano Zampini 25345042aa92SStefano Zampini /* assemble the MATIS object */ 25355042aa92SStefano Zampini PetscCall(MatISSetAllowRepeated(A, allow)); 25365042aa92SStefano Zampini PetscCall(MatSetLocalToGlobalMapping(A, rmap, cmap)); 25375042aa92SStefano Zampini PetscCall(MatISSetLocalMat(A, lA)); 25385042aa92SStefano Zampini PetscCall(MatDestroy(&lA)); 25395042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingDestroy(&rmap)); 25405042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingDestroy(&cmap)); 25415042aa92SStefano Zampini PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 25425042aa92SStefano Zampini PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 25433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2544b4319ba4SBarry Smith } 2545b4319ba4SBarry Smith 2546d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatInvertBlockDiagonal_IS(Mat mat, const PetscScalar **values) 2547d71ae5a4SJacob Faibussowitsch { 2548b89f26deSStefano Zampini Mat_IS *is = (Mat_IS *)mat->data; 2549b89f26deSStefano Zampini MPI_Datatype nodeType; 2550b89f26deSStefano Zampini const PetscScalar *lv; 2551b89f26deSStefano Zampini PetscInt bs; 2552835f2295SStefano Zampini PetscMPIInt mbs; 2553b89f26deSStefano Zampini 2554b89f26deSStefano Zampini PetscFunctionBegin; 25559566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(mat, &bs)); 25569566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(is->A, bs)); 25579566063dSJacob Faibussowitsch PetscCall(MatInvertBlockDiagonal(is->A, &lv)); 255848a46eb9SPierre Jolivet if (!is->bdiag) PetscCall(PetscMalloc1(bs * mat->rmap->n, &is->bdiag)); 2559835f2295SStefano Zampini PetscCall(PetscMPIIntCast(bs, &mbs)); 2560835f2295SStefano Zampini PetscCallMPI(MPI_Type_contiguous(mbs, MPIU_SCALAR, &nodeType)); 25619566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&nodeType)); 25629566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(is->sf, nodeType, lv, is->bdiag, MPI_REPLACE)); 25639566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(is->sf, nodeType, lv, is->bdiag, MPI_REPLACE)); 25649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&nodeType)); 2565b89f26deSStefano Zampini if (values) *values = is->bdiag; 25663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2567b89f26deSStefano Zampini } 2568b89f26deSStefano Zampini 2569d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISSetUpScatters_Private(Mat A) 2570d71ae5a4SJacob Faibussowitsch { 2571e176bc59SStefano Zampini Vec cglobal, rglobal; 25728546b261SStefano Zampini IS from; 25738546b261SStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 2574b89f26deSStefano Zampini PetscScalar sum; 25758546b261SStefano Zampini const PetscInt *garray; 25768546b261SStefano Zampini PetscInt nr, rbs, nc, cbs; 2577e432b41dSStefano Zampini VecType rtype; 2578b4319ba4SBarry Smith 2579b4319ba4SBarry Smith PetscFunctionBegin; 25809566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->rmapping, &nr)); 25819566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->rmapping, &rbs)); 25829566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->cmapping, &nc)); 25839566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->cmapping, &cbs)); 25849566063dSJacob Faibussowitsch PetscCall(VecDestroy(&is->x)); 25859566063dSJacob Faibussowitsch PetscCall(VecDestroy(&is->y)); 25869566063dSJacob Faibussowitsch PetscCall(VecDestroy(&is->counter)); 25879566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&is->rctx)); 25889566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&is->cctx)); 25899566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(is->A, &is->x, &is->y)); 25909566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->y, PETSC_TRUE)); 25919566063dSJacob Faibussowitsch PetscCall(VecGetRootType_Private(is->y, &rtype)); 25929566063dSJacob Faibussowitsch PetscCall(PetscFree(A->defaultvectype)); 25939566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(rtype, &A->defaultvectype)); 25949566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, &cglobal, &rglobal)); 25959566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(rglobal, PETSC_TRUE)); 25969566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->rmapping, &garray)); 25979566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), rbs, nr / rbs, garray, PETSC_USE_POINTER, &from)); 25989566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(rglobal, from, is->y, NULL, &is->rctx)); 25999566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->rmapping, &garray)); 26009566063dSJacob Faibussowitsch PetscCall(ISDestroy(&from)); 2601e432b41dSStefano Zampini if (is->rmapping != is->cmapping) { 26029566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->cmapping, &garray)); 26039566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), cbs, nc / cbs, garray, PETSC_USE_POINTER, &from)); 26049566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(cglobal, from, is->x, NULL, &is->cctx)); 26059566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->cmapping, &garray)); 26069566063dSJacob Faibussowitsch PetscCall(ISDestroy(&from)); 26078546b261SStefano Zampini } else { 26089566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->rctx)); 26098546b261SStefano Zampini is->cctx = is->rctx; 26108546b261SStefano Zampini } 26119566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cglobal)); 2612b89f26deSStefano Zampini 26138546b261SStefano Zampini /* interface counter vector (local) */ 26149566063dSJacob Faibussowitsch PetscCall(VecDuplicate(is->y, &is->counter)); 26159566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->counter, PETSC_TRUE)); 26169566063dSJacob Faibussowitsch PetscCall(VecSet(is->y, 1.)); 26179566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, is->y, rglobal, ADD_VALUES, SCATTER_REVERSE)); 26189566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, is->y, rglobal, ADD_VALUES, SCATTER_REVERSE)); 26199566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, rglobal, is->counter, INSERT_VALUES, SCATTER_FORWARD)); 26209566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, rglobal, is->counter, INSERT_VALUES, SCATTER_FORWARD)); 26219566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->y, PETSC_FALSE)); 26229566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->counter, PETSC_FALSE)); 2623b89f26deSStefano Zampini 2624b89f26deSStefano Zampini /* special functions for block-diagonal matrices */ 26259566063dSJacob Faibussowitsch PetscCall(VecSum(rglobal, &sum)); 2626b89f26deSStefano Zampini A->ops->invertblockdiagonal = NULL; 2627e432b41dSStefano Zampini if ((PetscInt)(PetscRealPart(sum)) == A->rmap->N && A->rmap->N == A->cmap->N && is->rmapping == is->cmapping) A->ops->invertblockdiagonal = MatInvertBlockDiagonal_IS; 26289566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rglobal)); 2629b0cc1f67SStefano Zampini 2630b0cc1f67SStefano Zampini /* setup SF for general purpose shared indices based communications */ 26319566063dSJacob Faibussowitsch PetscCall(MatISSetUpSF_IS(A)); 26323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 26338546b261SStefano Zampini } 26348546b261SStefano Zampini 2635d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISFilterL2GMap(Mat A, ISLocalToGlobalMapping map, ISLocalToGlobalMapping *nmap, ISLocalToGlobalMapping *lmap) 2636d71ae5a4SJacob Faibussowitsch { 26374f58015eSStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 2638e432b41dSStefano Zampini IS is; 2639e432b41dSStefano Zampini ISLocalToGlobalMappingType l2gtype; 2640e432b41dSStefano Zampini const PetscInt *idxs; 2641e432b41dSStefano Zampini PetscHSetI ht; 2642e432b41dSStefano Zampini PetscInt *nidxs; 2643e432b41dSStefano Zampini PetscInt i, n, bs, c; 2644e432b41dSStefano Zampini PetscBool flg[] = {PETSC_FALSE, PETSC_FALSE}; 2645e432b41dSStefano Zampini 2646e432b41dSStefano Zampini PetscFunctionBegin; 26479566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(map, &n)); 26489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(map, &bs)); 26499566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(map, &idxs)); 26509566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&ht)); 26519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n / bs, &nidxs)); 2652e432b41dSStefano Zampini for (i = 0, c = 0; i < n / bs; i++) { 26534f58015eSStefano Zampini PetscBool missing = PETSC_TRUE; 26549371c9d4SSatish Balay if (idxs[i] < 0) { 26559371c9d4SSatish Balay flg[0] = PETSC_TRUE; 26569371c9d4SSatish Balay continue; 26579371c9d4SSatish Balay } 26584f58015eSStefano Zampini if (!matis->allow_repeated) PetscCall(PetscHSetIQueryAdd(ht, idxs[i], &missing)); 2659e432b41dSStefano Zampini if (!missing) flg[1] = PETSC_TRUE; 2660e432b41dSStefano Zampini else nidxs[c++] = idxs[i]; 2661e432b41dSStefano Zampini } 26629566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&ht)); 26635440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, flg, 2, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A))); 2664e432b41dSStefano Zampini if (!flg[0] && !flg[1]) { /* Entries are all non negative and unique */ 2665e432b41dSStefano Zampini *nmap = NULL; 2666e432b41dSStefano Zampini *lmap = NULL; 26679566063dSJacob Faibussowitsch PetscCall(PetscFree(nidxs)); 26689566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(map, &idxs)); 26693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2670e432b41dSStefano Zampini } 2671e432b41dSStefano Zampini 26724f58015eSStefano Zampini /* New l2g map without negative indices (and repeated indices if not allowed) */ 26739566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), bs, c, nidxs, PETSC_USE_POINTER, &is)); 26749566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, nmap)); 26759566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 26769566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetType(map, &l2gtype)); 26779566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(*nmap, l2gtype)); 2678e432b41dSStefano Zampini 26794f58015eSStefano Zampini /* New local l2g map for repeated indices if not allowed */ 26809566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(*nmap, IS_GTOLM_MASK, n / bs, idxs, NULL, nidxs)); 26819566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF, bs, n / bs, nidxs, PETSC_USE_POINTER, &is)); 26829566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, lmap)); 26839566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 26849566063dSJacob Faibussowitsch PetscCall(PetscFree(nidxs)); 26859566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(map, &idxs)); 26863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2687e432b41dSStefano Zampini } 2688e432b41dSStefano Zampini 2689d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2690d71ae5a4SJacob Faibussowitsch { 26918546b261SStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 2692e432b41dSStefano Zampini ISLocalToGlobalMapping localrmapping = NULL, localcmapping = NULL; 2693e432b41dSStefano Zampini PetscInt nr, rbs, nc, cbs; 26944f58015eSStefano Zampini PetscBool cong, freem[] = {PETSC_FALSE, PETSC_FALSE}; 26958546b261SStefano Zampini 26968546b261SStefano Zampini PetscFunctionBegin; 2697fc989267SStefano Zampini if (rmapping) PetscCheckSameComm(A, 1, rmapping, 2); 2698fc989267SStefano Zampini if (cmapping) PetscCheckSameComm(A, 1, cmapping, 3); 2699e432b41dSStefano Zampini 27009566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&is->rmapping)); 27019566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&is->cmapping)); 27029566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 27039566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 27049566063dSJacob Faibussowitsch PetscCall(MatHasCongruentLayouts(A, &cong)); 2705e432b41dSStefano Zampini 2706fc989267SStefano Zampini /* If NULL, local space matches global space */ 2707fc989267SStefano Zampini if (!rmapping) { 2708fc989267SStefano Zampini IS is; 2709fc989267SStefano Zampini 27109566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), A->rmap->N, 0, 1, &is)); 27119566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rmapping)); 271258b7e2c1SStefano Zampini PetscCall(ISLocalToGlobalMappingSetBlockSize(rmapping, A->rmap->bs)); 27139566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2714e432b41dSStefano Zampini freem[0] = PETSC_TRUE; 2715e432b41dSStefano Zampini if (!cmapping && cong && A->rmap->bs == A->cmap->bs) cmapping = rmapping; 2716e432b41dSStefano Zampini } else if (!is->islocalref) { /* check if the l2g map has negative or repeated entries */ 27179566063dSJacob Faibussowitsch PetscCall(MatISFilterL2GMap(A, rmapping, &is->rmapping, &localrmapping)); 2718e432b41dSStefano Zampini if (rmapping == cmapping) { 27199566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->rmapping)); 2720e432b41dSStefano Zampini is->cmapping = is->rmapping; 27219566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)localrmapping)); 2722e432b41dSStefano Zampini localcmapping = localrmapping; 2723fc989267SStefano Zampini } 2724fc989267SStefano Zampini } 2725fc989267SStefano Zampini if (!cmapping) { 2726fc989267SStefano Zampini IS is; 2727fc989267SStefano Zampini 27289566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), A->cmap->N, 0, 1, &is)); 27299566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cmapping)); 273058b7e2c1SStefano Zampini PetscCall(ISLocalToGlobalMappingSetBlockSize(cmapping, A->cmap->bs)); 27319566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2732e432b41dSStefano Zampini freem[1] = PETSC_TRUE; 2733e432b41dSStefano Zampini } else if (cmapping != rmapping && !is->islocalref) { /* check if the l2g map has negative or repeated entries */ 27349566063dSJacob Faibussowitsch PetscCall(MatISFilterL2GMap(A, cmapping, &is->cmapping, &localcmapping)); 2735e432b41dSStefano Zampini } 2736e432b41dSStefano Zampini if (!is->rmapping) { 27379566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)rmapping)); 2738e432b41dSStefano Zampini is->rmapping = rmapping; 2739e432b41dSStefano Zampini } 2740e432b41dSStefano Zampini if (!is->cmapping) { 27419566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)cmapping)); 2742e432b41dSStefano Zampini is->cmapping = cmapping; 2743fc989267SStefano Zampini } 2744fc989267SStefano Zampini 2745fc989267SStefano Zampini /* Clean up */ 27464f58015eSStefano Zampini is->lnnzstate = 0; 27474f58015eSStefano Zampini PetscCall(MatDestroy(&is->dA)); 27484f58015eSStefano Zampini PetscCall(MatDestroy(&is->assembledA)); 27499566063dSJacob Faibussowitsch PetscCall(MatDestroy(&is->A)); 2750872cf891SStefano Zampini if (is->csf != is->sf) { 27519566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&is->csf)); 27529566063dSJacob Faibussowitsch PetscCall(PetscFree2(is->csf_rootdata, is->csf_leafdata)); 2753f03112d0SStefano Zampini } else is->csf = NULL; 27549566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&is->sf)); 27559566063dSJacob Faibussowitsch PetscCall(PetscFree2(is->sf_rootdata, is->sf_leafdata)); 27569566063dSJacob Faibussowitsch PetscCall(PetscFree(is->bdiag)); 27573bbff08aSStefano Zampini 2758fc989267SStefano Zampini /* check if the two mappings are actually the same for square matrices since MATIS has some optimization for this case 2759fc989267SStefano Zampini (DOLFIN passes 2 different objects) */ 27609566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->rmapping, &nr)); 27619566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->rmapping, &rbs)); 27629566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->cmapping, &nc)); 27639566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->cmapping, &cbs)); 2764e432b41dSStefano Zampini if (is->rmapping != is->cmapping && cong) { 2765e432b41dSStefano Zampini PetscBool same = PETSC_FALSE; 27666625354bSStefano Zampini if (nr == nc && cbs == rbs) { 27676625354bSStefano Zampini const PetscInt *idxs1, *idxs2; 27686625354bSStefano Zampini 27699566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->rmapping, &idxs1)); 27709566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->cmapping, &idxs2)); 27719566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(idxs1, idxs2, nr / rbs, &same)); 27729566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->rmapping, &idxs1)); 27739566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->cmapping, &idxs2)); 27746625354bSStefano Zampini } 27755440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &same, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 2776e432b41dSStefano Zampini if (same) { 27779566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&is->cmapping)); 27789566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->rmapping)); 2779e432b41dSStefano Zampini is->cmapping = is->rmapping; 2780e432b41dSStefano Zampini } 27816625354bSStefano Zampini } 27829566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(A->rmap, rbs)); 27839566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(A->cmap, cbs)); 2784e432b41dSStefano Zampini /* Pass the user defined maps to the layout */ 27859566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetISLocalToGlobalMapping(A->rmap, rmapping)); 27869566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetISLocalToGlobalMapping(A->cmap, cmapping)); 27879566063dSJacob Faibussowitsch if (freem[0]) PetscCall(ISLocalToGlobalMappingDestroy(&rmapping)); 27889566063dSJacob Faibussowitsch if (freem[1]) PetscCall(ISLocalToGlobalMappingDestroy(&cmapping)); 27896625354bSStefano Zampini 279039b6f3f9SStefano Zampini if (!is->islocalref) { 27916625354bSStefano Zampini /* Create the local matrix A */ 27929566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &is->A)); 27939566063dSJacob Faibussowitsch PetscCall(MatSetType(is->A, is->lmattype)); 27949566063dSJacob Faibussowitsch PetscCall(MatSetSizes(is->A, nr, nc, nr, nc)); 27959566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(is->A, rbs, cbs)); 27969566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(is->A, "is_")); 27979566063dSJacob Faibussowitsch PetscCall(MatAppendOptionsPrefix(is->A, ((PetscObject)A)->prefix)); 27989566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(is->A->rmap)); 27999566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(is->A->cmap)); 28009566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(is->A, localrmapping, localcmapping)); 28019566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&localrmapping)); 28029566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&localcmapping)); 2803fc989267SStefano Zampini /* setup scatters and local vectors for MatMult */ 280439b6f3f9SStefano Zampini PetscCall(MatISSetUpScatters_Private(A)); 280539b6f3f9SStefano Zampini } 2806fc989267SStefano Zampini A->preallocated = PETSC_TRUE; 28073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2808fc989267SStefano Zampini } 2809fc989267SStefano Zampini 2810d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetUp_IS(Mat A) 2811d71ae5a4SJacob Faibussowitsch { 281229f134acSStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 2813fc989267SStefano Zampini ISLocalToGlobalMapping rmap, cmap; 2814fc989267SStefano Zampini 2815fc989267SStefano Zampini PetscFunctionBegin; 281629f134acSStefano Zampini if (!is->sf) { 28179566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(A, &rmap, &cmap)); 281829f134acSStefano Zampini PetscCall(MatSetLocalToGlobalMapping(A, rmap, cmap)); 281929f134acSStefano Zampini } 28203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2821b4319ba4SBarry Smith } 2822b4319ba4SBarry Smith 2823d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) 2824d71ae5a4SJacob Faibussowitsch { 28252e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS *)mat->data; 2826*076fee34SStefano Zampini PetscInt buf[2 * MATIS_MAX_ENTRIES_INSERTION], *rows_l = NULL, *cols_l = NULL; 28272e74eeadSLisandro Dalcin 28282e74eeadSLisandro Dalcin PetscFunctionBegin; 2829*076fee34SStefano Zampini IndexSpaceGet(buf, m, n, rows_l, cols_l); 28309566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(is->rmapping, IS_GTOLM_MASK, m, rows, &m, rows_l)); 2831e432b41dSStefano Zampini if (m != n || rows != cols || is->cmapping != is->rmapping) { 28329566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(is->cmapping, IS_GTOLM_MASK, n, cols, &n, cols_l)); 28339566063dSJacob Faibussowitsch PetscCall(MatSetValues(is->A, m, rows_l, n, cols_l, values, addv)); 2834e432b41dSStefano Zampini } else { 28359566063dSJacob Faibussowitsch PetscCall(MatSetValues(is->A, m, rows_l, m, rows_l, values, addv)); 2836e432b41dSStefano Zampini } 2837*076fee34SStefano Zampini IndexSpaceRestore(buf, m, n, rows_l, cols_l); 28383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 28392e74eeadSLisandro Dalcin } 28402e74eeadSLisandro Dalcin 2841d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) 2842d71ae5a4SJacob Faibussowitsch { 284397563a80SStefano Zampini Mat_IS *is = (Mat_IS *)mat->data; 2844*076fee34SStefano Zampini PetscInt buf[2 * MATIS_MAX_ENTRIES_INSERTION], *rows_l = NULL, *cols_l = NULL; 284597563a80SStefano Zampini 284697563a80SStefano Zampini PetscFunctionBegin; 2847*076fee34SStefano Zampini IndexSpaceGet(buf, m, n, rows_l, cols_l); 28489566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(is->rmapping, IS_GTOLM_MASK, m, rows, &m, rows_l)); 2849e432b41dSStefano Zampini if (m != n || rows != cols || is->cmapping != is->rmapping) { 285084a95373SStefano Zampini PetscCall(ISGlobalToLocalMappingApplyBlock(is->cmapping, IS_GTOLM_MASK, n, cols, &n, cols_l)); 28519566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked(is->A, m, rows_l, n, cols_l, values, addv)); 2852e432b41dSStefano Zampini } else { 285384a95373SStefano Zampini PetscCall(MatSetValuesBlocked(is->A, m, rows_l, m, rows_l, values, addv)); 2854e432b41dSStefano Zampini } 2855*076fee34SStefano Zampini IndexSpaceRestore(buf, m, n, rows_l, cols_l); 28563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 285797563a80SStefano Zampini } 285897563a80SStefano Zampini 2859d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesLocal_IS(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) 2860d71ae5a4SJacob Faibussowitsch { 2861b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)A->data; 2862b4319ba4SBarry Smith 2863b4319ba4SBarry Smith PetscFunctionBegin; 2864e432b41dSStefano Zampini if (is->A->rmap->mapping || is->A->cmap->mapping) { 28659566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(is->A, m, rows, n, cols, values, addv)); 2866872cf891SStefano Zampini } else { 28679566063dSJacob Faibussowitsch PetscCall(MatSetValues(is->A, m, rows, n, cols, values, addv)); 2868872cf891SStefano Zampini } 28693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2870b4319ba4SBarry Smith } 2871b4319ba4SBarry Smith 2872d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) 2873d71ae5a4SJacob Faibussowitsch { 2874f0006bf2SLisandro Dalcin Mat_IS *is = (Mat_IS *)A->data; 2875f0006bf2SLisandro Dalcin 2876f0006bf2SLisandro Dalcin PetscFunctionBegin; 2877e432b41dSStefano Zampini if (is->A->rmap->mapping || is->A->cmap->mapping) { 28789566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlockedLocal(is->A, m, rows, n, cols, values, addv)); 2879b4f971dfSStefano Zampini } else { 28809566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked(is->A, m, rows, n, cols, values, addv)); 2881b4f971dfSStefano Zampini } 28823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2883f0006bf2SLisandro Dalcin } 2884f0006bf2SLisandro Dalcin 2885d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, PetscBool columns) 2886d71ae5a4SJacob Faibussowitsch { 2887f0ae7da4SStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 2888f0ae7da4SStefano Zampini 2889f0ae7da4SStefano Zampini PetscFunctionBegin; 28900d2733adSStefano Zampini if (!n) PetscFunctionReturn(PETSC_SUCCESS); 2891f0ae7da4SStefano Zampini is->pure_neumann = PETSC_FALSE; 2892f0ae7da4SStefano Zampini 2893f0ae7da4SStefano Zampini if (columns) { 28949566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns(is->A, n, rows, diag, NULL, NULL)); 2895f0ae7da4SStefano Zampini } else { 28969566063dSJacob Faibussowitsch PetscCall(MatZeroRows(is->A, n, rows, diag, NULL, NULL)); 2897f0ae7da4SStefano Zampini } 2898f0ae7da4SStefano Zampini if (diag != 0.) { 2899f0ae7da4SStefano Zampini const PetscScalar *array; 29000d2733adSStefano Zampini 29019566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(is->counter, &array)); 29020d2733adSStefano Zampini for (PetscInt i = 0; i < n; i++) PetscCall(MatSetValue(is->A, rows[i], rows[i], diag / (array[rows[i]]), INSERT_VALUES)); 29039566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(is->counter, &array)); 29049566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(is->A, MAT_FINAL_ASSEMBLY)); 29059566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(is->A, MAT_FINAL_ASSEMBLY)); 2906f0ae7da4SStefano Zampini } 29073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2908f0ae7da4SStefano Zampini } 2909f0ae7da4SStefano Zampini 2910d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, Vec x, Vec b, PetscBool columns) 2911d71ae5a4SJacob Faibussowitsch { 29126e520ac8SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 29130d2733adSStefano Zampini PetscInt nr, nl, len; 29140d2733adSStefano Zampini PetscInt *lrows = NULL; 29152e74eeadSLisandro Dalcin 29162e74eeadSLisandro Dalcin PetscFunctionBegin; 2917cf9c20a2SJed Brown if (PetscUnlikelyDebug(columns || diag != 0. || (x && b))) { 2918f0ae7da4SStefano Zampini PetscBool cong; 291926b0207aSStefano Zampini 29209566063dSJacob Faibussowitsch PetscCall(PetscLayoutCompare(A->rmap, A->cmap, &cong)); 292126b0207aSStefano Zampini cong = (PetscBool)(cong && matis->sf == matis->csf); 292208401ef6SPierre 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"); 2923aed4548fSBarry 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"); 2924aed4548fSBarry 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"); 2925f0ae7da4SStefano Zampini } 29260d2733adSStefano Zampini PetscCall(MatGetSize(matis->A, &nl, NULL)); 29276e520ac8SStefano Zampini /* get locally owned rows */ 29289566063dSJacob Faibussowitsch PetscCall(PetscLayoutMapLocal(A->rmap, n, rows, &len, &lrows, NULL)); 2929dd8e379bSPierre Jolivet /* fix right-hand side if needed */ 29306e520ac8SStefano Zampini if (x && b) { 29316e520ac8SStefano Zampini const PetscScalar *xx; 29326e520ac8SStefano Zampini PetscScalar *bb; 29336e520ac8SStefano Zampini 29349566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &xx)); 29359566063dSJacob Faibussowitsch PetscCall(VecGetArray(b, &bb)); 29360d2733adSStefano Zampini for (PetscInt i = 0; i < len; ++i) bb[lrows[i]] = diag * xx[lrows[i]]; 29379566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &xx)); 29389566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(b, &bb)); 29392e74eeadSLisandro Dalcin } 29406e520ac8SStefano Zampini /* get rows associated to the local matrices */ 29419566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_leafdata, nl)); 29429566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata, A->rmap->n)); 29430d2733adSStefano Zampini for (PetscInt i = 0; i < len; i++) matis->sf_rootdata[lrows[i]] = 1; 29449566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 29459566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 29469566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 29479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl, &lrows)); 29480d2733adSStefano Zampini nr = 0; 29490d2733adSStefano Zampini for (PetscInt i = 0; i < nl; i++) 29509371c9d4SSatish Balay if (matis->sf_leafdata[i]) lrows[nr++] = i; 29519566063dSJacob Faibussowitsch PetscCall(MatISZeroRowsColumnsLocal_Private(A, nr, lrows, diag, columns)); 29529566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 29533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 29542e74eeadSLisandro Dalcin } 29552e74eeadSLisandro Dalcin 2956d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_IS(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 2957d71ae5a4SJacob Faibussowitsch { 2958b4319ba4SBarry Smith PetscFunctionBegin; 29599566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns_Private_IS(A, n, rows, diag, x, b, PETSC_FALSE)); 29603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2961f0ae7da4SStefano Zampini } 29622205254eSKarl Rupp 2963d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_IS(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 2964d71ae5a4SJacob Faibussowitsch { 2965f0ae7da4SStefano Zampini PetscFunctionBegin; 29669566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns_Private_IS(A, n, rows, diag, x, b, PETSC_TRUE)); 29673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2968b4319ba4SBarry Smith } 2969b4319ba4SBarry Smith 2970d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_IS(Mat A, MatAssemblyType type) 2971d71ae5a4SJacob Faibussowitsch { 2972b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)A->data; 2973b4319ba4SBarry Smith 2974b4319ba4SBarry Smith PetscFunctionBegin; 29759566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(is->A, type)); 29763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2977b4319ba4SBarry Smith } 2978b4319ba4SBarry Smith 2979d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_IS(Mat A, MatAssemblyType type) 2980d71ae5a4SJacob Faibussowitsch { 2981b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)A->data; 2982d0dbe9f7SStefano Zampini PetscBool lnnz; 2983b4319ba4SBarry Smith 2984b4319ba4SBarry Smith PetscFunctionBegin; 29859566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(is->A, type)); 2986872cf891SStefano Zampini /* fix for local empty rows/cols */ 2987872cf891SStefano Zampini if (is->locempty && type == MAT_FINAL_ASSEMBLY) { 2988872cf891SStefano Zampini Mat newlA; 2989f03112d0SStefano Zampini ISLocalToGlobalMapping rl2g, cl2g; 2990f03112d0SStefano Zampini IS nzr, nzc; 2991f03112d0SStefano Zampini PetscInt nr, nc, nnzr, nnzc; 2992f03112d0SStefano Zampini PetscBool lnewl2g, newl2g; 2993872cf891SStefano Zampini 29949566063dSJacob Faibussowitsch PetscCall(MatGetSize(is->A, &nr, &nc)); 29959566063dSJacob Faibussowitsch PetscCall(MatFindNonzeroRowsOrCols_Basic(is->A, PETSC_FALSE, PETSC_SMALL, &nzr)); 299648a46eb9SPierre Jolivet if (!nzr) PetscCall(ISCreateStride(PetscObjectComm((PetscObject)is->A), nr, 0, 1, &nzr)); 29979566063dSJacob Faibussowitsch PetscCall(MatFindNonzeroRowsOrCols_Basic(is->A, PETSC_TRUE, PETSC_SMALL, &nzc)); 299848a46eb9SPierre Jolivet if (!nzc) PetscCall(ISCreateStride(PetscObjectComm((PetscObject)is->A), nc, 0, 1, &nzc)); 29999566063dSJacob Faibussowitsch PetscCall(ISGetSize(nzr, &nnzr)); 30009566063dSJacob Faibussowitsch PetscCall(ISGetSize(nzc, &nnzc)); 3001e432b41dSStefano Zampini if (nnzr != nr || nnzc != nc) { /* need new global l2g map */ 3002f03112d0SStefano Zampini lnewl2g = PETSC_TRUE; 30035440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&lnewl2g, &newl2g, 1, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A))); 3004f03112d0SStefano Zampini 3005872cf891SStefano Zampini /* extract valid submatrix */ 30069566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(is->A, nzr, nzc, MAT_INITIAL_MATRIX, &newlA)); 3007f03112d0SStefano Zampini } else { /* local matrix fully populated */ 3008f03112d0SStefano Zampini lnewl2g = PETSC_FALSE; 30095440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&lnewl2g, &newl2g, 1, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A))); 30109566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->A)); 3011f03112d0SStefano Zampini newlA = is->A; 3012f03112d0SStefano Zampini } 3013e432b41dSStefano Zampini 3014f03112d0SStefano Zampini /* attach new global l2g map if needed */ 3015f03112d0SStefano Zampini if (newl2g) { 3016e432b41dSStefano Zampini IS zr, zc; 3017e432b41dSStefano Zampini const PetscInt *ridxs, *cidxs, *zridxs, *zcidxs; 3018e432b41dSStefano Zampini PetscInt *nidxs, i; 3019f03112d0SStefano Zampini 30209566063dSJacob Faibussowitsch PetscCall(ISComplement(nzr, 0, nr, &zr)); 30219566063dSJacob Faibussowitsch PetscCall(ISComplement(nzc, 0, nc, &zc)); 30229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(PetscMax(nr, nc), &nidxs)); 30239566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(is->rmapping, &ridxs)); 30249566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(is->cmapping, &cidxs)); 30259566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zr, &zridxs)); 30269566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zc, &zcidxs)); 30279566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zr, &nnzr)); 30289566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zc, &nnzc)); 3029e432b41dSStefano Zampini 30309566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(nidxs, ridxs, nr)); 3031e432b41dSStefano Zampini for (i = 0; i < nnzr; i++) nidxs[zridxs[i]] = -1; 30329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A), 1, nr, nidxs, PETSC_COPY_VALUES, &rl2g)); 30339566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(nidxs, cidxs, nc)); 3034e432b41dSStefano Zampini for (i = 0; i < nnzc; i++) nidxs[zcidxs[i]] = -1; 30359566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A), 1, nc, nidxs, PETSC_COPY_VALUES, &cl2g)); 3036e432b41dSStefano Zampini 30379566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zr, &zridxs)); 30389566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zc, &zcidxs)); 30399566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(is->rmapping, &ridxs)); 30409566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(is->cmapping, &cidxs)); 30419566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzr)); 30429566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzc)); 30439566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zr)); 30449566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zc)); 30459566063dSJacob Faibussowitsch PetscCall(PetscFree(nidxs)); 30469566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(A, rl2g, cl2g)); 30479566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 30489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 3049f03112d0SStefano Zampini } 30509566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(A, newlA)); 30519566063dSJacob Faibussowitsch PetscCall(MatDestroy(&newlA)); 30529566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzr)); 30539566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzc)); 3054872cf891SStefano Zampini is->locempty = PETSC_FALSE; 3055f03112d0SStefano Zampini } 3056d0dbe9f7SStefano Zampini lnnz = (PetscBool)(is->A->nonzerostate == is->lnnzstate); 3057d0dbe9f7SStefano Zampini is->lnnzstate = is->A->nonzerostate; 30585440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &lnnz, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 30594f58015eSStefano Zampini if (!lnnz) A->nonzerostate++; 30603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3061b4319ba4SBarry Smith } 3062b4319ba4SBarry Smith 3063d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISGetLocalMat_IS(Mat mat, Mat *local) 3064d71ae5a4SJacob Faibussowitsch { 3065b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)mat->data; 3066b4319ba4SBarry Smith 3067b4319ba4SBarry Smith PetscFunctionBegin; 3068b4319ba4SBarry Smith *local = is->A; 30693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3070b4319ba4SBarry Smith } 3071b4319ba4SBarry Smith 3072d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat, Mat *local) 3073d71ae5a4SJacob Faibussowitsch { 30743b3b1effSJed Brown PetscFunctionBegin; 30753b3b1effSJed Brown *local = NULL; 30763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30773b3b1effSJed Brown } 30783b3b1effSJed Brown 3079b4319ba4SBarry Smith /*@ 308011a5261eSBarry Smith MatISGetLocalMat - Gets the local matrix stored inside a `MATIS` matrix. 3081b4319ba4SBarry Smith 30824f58015eSStefano Zampini Not Collective. 30834f58015eSStefano Zampini 3084b4319ba4SBarry Smith Input Parameter: 3085b4319ba4SBarry Smith . mat - the matrix 3086b4319ba4SBarry Smith 3087b4319ba4SBarry Smith Output Parameter: 3088eb82efa4SStefano Zampini . local - the local matrix 3089b4319ba4SBarry Smith 30904f58015eSStefano Zampini Level: intermediate 3091b4319ba4SBarry Smith 3092b4319ba4SBarry Smith Notes: 3093b4319ba4SBarry Smith This can be called if you have precomputed the nonzero structure of the 3094b4319ba4SBarry Smith matrix and want to provide it to the inner matrix object to improve the performance 309511a5261eSBarry Smith of the `MatSetValues()` operation. 3096b4319ba4SBarry Smith 309711a5261eSBarry Smith Call `MatISRestoreLocalMat()` when finished with the local matrix. 309896a6f129SJed Brown 30991cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatISRestoreLocalMat()` 3100b4319ba4SBarry Smith @*/ 3101d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISGetLocalMat(Mat mat, Mat *local) 3102d71ae5a4SJacob Faibussowitsch { 3103b4319ba4SBarry Smith PetscFunctionBegin; 31040700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 31054f572ea9SToby Isaac PetscAssertPointer(local, 2); 3106cac4c232SBarry Smith PetscUseMethod(mat, "MatISGetLocalMat_C", (Mat, Mat *), (mat, local)); 31073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3108b4319ba4SBarry Smith } 3109b4319ba4SBarry Smith 31103b3b1effSJed Brown /*@ 311111a5261eSBarry Smith MatISRestoreLocalMat - Restores the local matrix obtained with `MatISGetLocalMat()` 31123b3b1effSJed Brown 31134f58015eSStefano Zampini Not Collective. 31144f58015eSStefano Zampini 31152ef1f0ffSBarry Smith Input Parameters: 31162ef1f0ffSBarry Smith + mat - the matrix 31172ef1f0ffSBarry Smith - local - the local matrix 31183b3b1effSJed Brown 31194f58015eSStefano Zampini Level: intermediate 31203b3b1effSJed Brown 31211cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatISGetLocalMat()` 31223b3b1effSJed Brown @*/ 3123d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISRestoreLocalMat(Mat mat, Mat *local) 3124d71ae5a4SJacob Faibussowitsch { 31253b3b1effSJed Brown PetscFunctionBegin; 31263b3b1effSJed Brown PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 31274f572ea9SToby Isaac PetscAssertPointer(local, 2); 3128cac4c232SBarry Smith PetscUseMethod(mat, "MatISRestoreLocalMat_C", (Mat, Mat *), (mat, local)); 31293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31303b3b1effSJed Brown } 31313b3b1effSJed Brown 3132d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISSetLocalMatType_IS(Mat mat, MatType mtype) 3133d71ae5a4SJacob Faibussowitsch { 31348546b261SStefano Zampini Mat_IS *is = (Mat_IS *)mat->data; 31358546b261SStefano Zampini 31368546b261SStefano Zampini PetscFunctionBegin; 31371baa6e33SBarry Smith if (is->A) PetscCall(MatSetType(is->A, mtype)); 31389566063dSJacob Faibussowitsch PetscCall(PetscFree(is->lmattype)); 31399566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(mtype, &is->lmattype)); 31403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31418546b261SStefano Zampini } 31428546b261SStefano Zampini 31435d83a8b1SBarry Smith /*@ 314411a5261eSBarry Smith MatISSetLocalMatType - Specifies the type of local matrix inside the `MATIS` 31458546b261SStefano Zampini 31464f58015eSStefano Zampini Logically Collective. 31474f58015eSStefano Zampini 3148d8d19677SJose E. Roman Input Parameters: 3149a2b725a8SWilliam Gropp + mat - the matrix 3150a2b725a8SWilliam Gropp - mtype - the local matrix type 31518546b261SStefano Zampini 31524f58015eSStefano Zampini Level: intermediate 31538546b261SStefano Zampini 31541cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatSetType()`, `MatType` 31558546b261SStefano Zampini @*/ 3156d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISSetLocalMatType(Mat mat, MatType mtype) 3157d71ae5a4SJacob Faibussowitsch { 31588546b261SStefano Zampini PetscFunctionBegin; 31598546b261SStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3160cac4c232SBarry Smith PetscUseMethod(mat, "MatISSetLocalMatType_C", (Mat, MatType), (mat, mtype)); 31613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31628546b261SStefano Zampini } 31638546b261SStefano Zampini 3164d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISSetLocalMat_IS(Mat mat, Mat local) 3165d71ae5a4SJacob Faibussowitsch { 31663b03a366Sstefano_zampini Mat_IS *is = (Mat_IS *)mat->data; 31673b03a366Sstefano_zampini PetscInt nrows, ncols, orows, ocols; 31688546b261SStefano Zampini MatType mtype, otype; 31698546b261SStefano Zampini PetscBool sametype = PETSC_TRUE; 31703b03a366Sstefano_zampini 31713b03a366Sstefano_zampini PetscFunctionBegin; 3172e432b41dSStefano Zampini if (is->A && !is->islocalref) { 31739566063dSJacob Faibussowitsch PetscCall(MatGetSize(is->A, &orows, &ocols)); 31749566063dSJacob Faibussowitsch PetscCall(MatGetSize(local, &nrows, &ncols)); 31755042aa92SStefano 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); 31769566063dSJacob Faibussowitsch PetscCall(MatGetType(local, &mtype)); 31779566063dSJacob Faibussowitsch PetscCall(MatGetType(is->A, &otype)); 31789566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, otype, &sametype)); 31794e4c7dbeSStefano Zampini } 31809566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)local)); 31819566063dSJacob Faibussowitsch PetscCall(MatDestroy(&is->A)); 31823b03a366Sstefano_zampini is->A = local; 31839566063dSJacob Faibussowitsch PetscCall(MatGetType(is->A, &mtype)); 31849566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(mat, mtype)); 318548a46eb9SPierre Jolivet if (!sametype && !is->islocalref) PetscCall(MatISSetUpScatters_Private(mat)); 31864f58015eSStefano Zampini is->lnnzstate = 0; 31873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31883b03a366Sstefano_zampini } 31893b03a366Sstefano_zampini 31903b03a366Sstefano_zampini /*@ 319111a5261eSBarry Smith MatISSetLocalMat - Replace the local matrix stored inside a `MATIS` object. 31923b03a366Sstefano_zampini 31934f58015eSStefano Zampini Not Collective 31948546b261SStefano Zampini 3195d8d19677SJose E. Roman Input Parameters: 3196a2b725a8SWilliam Gropp + mat - the matrix 3197a2b725a8SWilliam Gropp - local - the local matrix 31983b03a366Sstefano_zampini 31994f58015eSStefano Zampini Level: intermediate 320011a5261eSBarry Smith 32011cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatISSetLocalMatType`, `MatISGetLocalMat()` 32023b03a366Sstefano_zampini @*/ 3203d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISSetLocalMat(Mat mat, Mat local) 3204d71ae5a4SJacob Faibussowitsch { 32053b03a366Sstefano_zampini PetscFunctionBegin; 32063b03a366Sstefano_zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3207b7ce53b6SStefano Zampini PetscValidHeaderSpecific(local, MAT_CLASSID, 2); 3208cac4c232SBarry Smith PetscUseMethod(mat, "MatISSetLocalMat_C", (Mat, Mat), (mat, local)); 32093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32103b03a366Sstefano_zampini } 32113b03a366Sstefano_zampini 3212d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroEntries_IS(Mat A) 3213d71ae5a4SJacob Faibussowitsch { 32146726f965SBarry Smith Mat_IS *a = (Mat_IS *)A->data; 32156726f965SBarry Smith 32166726f965SBarry Smith PetscFunctionBegin; 32179566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(a->A)); 32183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32196726f965SBarry Smith } 32206726f965SBarry Smith 3221d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatScale_IS(Mat A, PetscScalar a) 3222d71ae5a4SJacob Faibussowitsch { 32232e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS *)A->data; 32242e74eeadSLisandro Dalcin 32252e74eeadSLisandro Dalcin PetscFunctionBegin; 32269566063dSJacob Faibussowitsch PetscCall(MatScale(is->A, a)); 32273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32282e74eeadSLisandro Dalcin } 32292e74eeadSLisandro Dalcin 3230d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v) 3231d71ae5a4SJacob Faibussowitsch { 32322e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS *)A->data; 32332e74eeadSLisandro Dalcin 32342e74eeadSLisandro Dalcin PetscFunctionBegin; 32352e74eeadSLisandro Dalcin /* get diagonal of the local matrix */ 32369566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(is->A, is->y)); 32372e74eeadSLisandro Dalcin 32382e74eeadSLisandro Dalcin /* scatter diagonal back into global vector */ 32399566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0)); 32409566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, is->y, v, ADD_VALUES, SCATTER_REVERSE)); 32419566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, is->y, v, ADD_VALUES, SCATTER_REVERSE)); 32423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32432e74eeadSLisandro Dalcin } 32442e74eeadSLisandro Dalcin 3245d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_IS(Mat A, MatOption op, PetscBool flg) 3246d71ae5a4SJacob Faibussowitsch { 32476726f965SBarry Smith Mat_IS *a = (Mat_IS *)A->data; 32486726f965SBarry Smith 32496726f965SBarry Smith PetscFunctionBegin; 32509566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg)); 32513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32526726f965SBarry Smith } 32536726f965SBarry Smith 3254d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAXPY_IS(Mat Y, PetscScalar a, Mat X, MatStructure str) 3255d71ae5a4SJacob Faibussowitsch { 3256f26d0771SStefano Zampini Mat_IS *y = (Mat_IS *)Y->data; 3257f26d0771SStefano Zampini Mat_IS *x; 3258f26d0771SStefano Zampini 3259f26d0771SStefano Zampini PetscFunctionBegin; 326076bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 326176bd3646SJed Brown PetscBool ismatis; 32629566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)X, MATIS, &ismatis)); 326328b400f6SJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)Y), PETSC_ERR_SUP, "Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS"); 326476bd3646SJed Brown } 3265f26d0771SStefano Zampini x = (Mat_IS *)X->data; 32669566063dSJacob Faibussowitsch PetscCall(MatAXPY(y->A, a, x->A, str)); 32673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3268f26d0771SStefano Zampini } 3269f26d0771SStefano Zampini 3270d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A, IS row, IS col, Mat *submat) 3271d71ae5a4SJacob Faibussowitsch { 3272f26d0771SStefano Zampini Mat lA; 3273f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)A->data; 3274f26d0771SStefano Zampini ISLocalToGlobalMapping rl2g, cl2g; 3275f26d0771SStefano Zampini IS is; 3276f26d0771SStefano Zampini const PetscInt *rg, *rl; 3277*076fee34SStefano Zampini PetscInt nrg, rbs, cbs; 3278f26d0771SStefano Zampini PetscInt N, M, nrl, i, *idxs; 3279f26d0771SStefano Zampini 3280f26d0771SStefano Zampini PetscFunctionBegin; 3281*076fee34SStefano Zampini PetscCall(ISGetBlockSize(row, &rbs)); 3282*076fee34SStefano Zampini PetscCall(ISGetBlockSize(col, &cbs)); 32839566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(A->rmap->mapping, &rg)); 32849566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(row, &nrl)); 32859566063dSJacob Faibussowitsch PetscCall(ISGetIndices(row, &rl)); 32869566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(A->rmap->mapping, &nrg)); 328776bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3288e87b5d96SPierre 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); 328976bd3646SJed Brown } 3290*076fee34SStefano Zampini if (nrg % rbs) nrg = rbs * (nrg / rbs + 1); 32919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nrg, &idxs)); 3292f26d0771SStefano Zampini /* map from [0,nrl) to row */ 3293f26d0771SStefano Zampini for (i = 0; i < nrl; i++) idxs[i] = rl[i]; 3294f26d0771SStefano Zampini for (i = nrl; i < nrg; i++) idxs[i] = -1; 32959566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(row, &rl)); 32969566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping, &rg)); 32979566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A), nrg, idxs, PETSC_OWN_POINTER, &is)); 32989566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g)); 3299*076fee34SStefano Zampini PetscCall(ISLocalToGlobalMappingSetBlockSize(rl2g, rbs)); 33009566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3301f26d0771SStefano Zampini /* compute new l2g map for columns */ 3302e432b41dSStefano Zampini if (col != row || matis->rmapping != matis->cmapping || matis->A->rmap->mapping != matis->A->cmap->mapping) { 3303f26d0771SStefano Zampini const PetscInt *cg, *cl; 3304f26d0771SStefano Zampini PetscInt ncg; 3305f26d0771SStefano Zampini PetscInt ncl; 3306f26d0771SStefano Zampini 33079566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(A->cmap->mapping, &cg)); 33089566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(col, &ncl)); 33099566063dSJacob Faibussowitsch PetscCall(ISGetIndices(col, &cl)); 33109566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(A->cmap->mapping, &ncg)); 331176bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3312e87b5d96SPierre 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); 331376bd3646SJed Brown } 3314*076fee34SStefano Zampini if (ncg % cbs) ncg = cbs * (ncg / cbs + 1); 33159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncg, &idxs)); 3316f26d0771SStefano Zampini /* map from [0,ncl) to col */ 3317f26d0771SStefano Zampini for (i = 0; i < ncl; i++) idxs[i] = cl[i]; 3318f26d0771SStefano Zampini for (i = ncl; i < ncg; i++) idxs[i] = -1; 33199566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(col, &cl)); 33209566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping, &cg)); 33219566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A), ncg, idxs, PETSC_OWN_POINTER, &is)); 33229566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g)); 3323*076fee34SStefano Zampini PetscCall(ISLocalToGlobalMappingSetBlockSize(cl2g, cbs)); 33249566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3325f26d0771SStefano Zampini } else { 33269566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)rl2g)); 3327f26d0771SStefano Zampini cl2g = rl2g; 3328f26d0771SStefano Zampini } 33290d2733adSStefano Zampini 3330f26d0771SStefano Zampini /* create the MATIS submatrix */ 33319566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, &N)); 33329566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), submat)); 33339566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*submat, PETSC_DECIDE, PETSC_DECIDE, M, N)); 33349566063dSJacob Faibussowitsch PetscCall(MatSetType(*submat, MATIS)); 3335b0aa3428SStefano Zampini matis = (Mat_IS *)((*submat)->data); 33360d2733adSStefano Zampini matis->islocalref = A; 33379566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*submat, rl2g, cl2g)); 33389566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A, &lA)); 33399566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*submat, lA)); 33409566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 33419566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 3342e432b41dSStefano Zampini 3343f26d0771SStefano Zampini /* remove unsupported ops */ 33449566063dSJacob Faibussowitsch PetscCall(PetscMemzero((*submat)->ops, sizeof(struct _MatOps))); 3345f26d0771SStefano Zampini (*submat)->ops->destroy = MatDestroy_IS; 3346f26d0771SStefano Zampini (*submat)->ops->setvalueslocal = MatSetValuesLocal_SubMat_IS; 3347f26d0771SStefano Zampini (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS; 33480d2733adSStefano Zampini (*submat)->ops->zerorowslocal = MatZeroRowsLocal_SubMat_IS; 33490d2733adSStefano Zampini (*submat)->ops->zerorowscolumnslocal = MatZeroRowsColumnsLocal_SubMat_IS; 335039b6f3f9SStefano Zampini (*submat)->ops->getlocalsubmatrix = MatGetLocalSubMatrix_IS; 33513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3352f26d0771SStefano Zampini } 3353f26d0771SStefano Zampini 3354ce78bad3SBarry Smith static PetscErrorCode MatSetFromOptions_IS(Mat A, PetscOptionItems PetscOptionsObject) 3355d71ae5a4SJacob Faibussowitsch { 3356872cf891SStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 33578546b261SStefano Zampini char type[256]; 33588546b261SStefano Zampini PetscBool flg; 3359872cf891SStefano Zampini 3360872cf891SStefano Zampini PetscFunctionBegin; 3361d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "MATIS options"); 33624f58015eSStefano Zampini PetscCall(PetscOptionsDeprecated("-matis_keepassembled", "-mat_is_keepassembled", "3.21", NULL)); 33634f58015eSStefano Zampini PetscCall(PetscOptionsDeprecated("-matis_fixempty", "-mat_is_fixempty", "3.21", NULL)); 33644f58015eSStefano Zampini PetscCall(PetscOptionsDeprecated("-matis_storel2l", "-mat_is_storel2l", "3.21", NULL)); 33654f58015eSStefano Zampini PetscCall(PetscOptionsDeprecated("-matis_localmat_type", "-mat_is_localmat_type", "3.21", NULL)); 33664f58015eSStefano Zampini PetscCall(PetscOptionsBool("-mat_is_keepassembled", "Store an assembled version if needed", NULL, a->keepassembled, &a->keepassembled, NULL)); 33674f58015eSStefano Zampini PetscCall(PetscOptionsBool("-mat_is_fixempty", "Fix local matrices in case of empty local rows/columns", "MatISFixLocalEmpty", a->locempty, &a->locempty, NULL)); 33684f58015eSStefano Zampini PetscCall(PetscOptionsBool("-mat_is_storel2l", "Store local-to-local matrices generated from PtAP operations", "MatISStoreL2L", a->storel2l, &a->storel2l, NULL)); 33694f58015eSStefano Zampini PetscCall(PetscOptionsBool("-mat_is_allow_repeated", "Allow local repeated entries", "MatISSetAllowRepeated", a->allow_repeated, &a->allow_repeated, NULL)); 33704f58015eSStefano Zampini PetscCall(PetscOptionsFList("-mat_is_localmat_type", "Matrix type", "MatISSetLocalMatType", MatList, a->lmattype, type, 256, &flg)); 33711baa6e33SBarry Smith if (flg) PetscCall(MatISSetLocalMatType(A, type)); 33721baa6e33SBarry Smith if (a->A) PetscCall(MatSetFromOptions(a->A)); 3373d0609cedSBarry Smith PetscOptionsHeadEnd(); 33743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3375872cf891SStefano Zampini } 3376872cf891SStefano Zampini 3377284134d9SBarry Smith /*@ 33784f58015eSStefano Zampini MatCreateIS - Creates a "process" unassembled matrix. 33794f58015eSStefano Zampini 33804f58015eSStefano Zampini Collective. 3381284134d9SBarry Smith 3382284134d9SBarry Smith Input Parameters: 3383284134d9SBarry Smith + comm - MPI communicator that will share the matrix 3384e176bc59SStefano Zampini . bs - block size of the matrix 33852920cce0SJacob Faibussowitsch . m - local size of left vector used in matrix vector products 33862920cce0SJacob Faibussowitsch . n - local size of right vector used in matrix vector products 33872920cce0SJacob Faibussowitsch . M - global size of left vector used in matrix vector products 33882920cce0SJacob Faibussowitsch . N - global size of right vector used in matrix vector products 3389e176bc59SStefano Zampini . rmap - local to global map for rows 3390e176bc59SStefano Zampini - cmap - local to global map for cols 3391284134d9SBarry Smith 3392284134d9SBarry Smith Output Parameter: 3393284134d9SBarry Smith . A - the resulting matrix 3394284134d9SBarry Smith 33954f58015eSStefano Zampini Level: intermediate 33968e6c10adSSatish Balay 339795452b02SPatrick Sanan Notes: 33982ef1f0ffSBarry 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 33994f58015eSStefano Zampini used in `MatMult()` operations. The local sizes of `rmap` and `cmap` define the size of the local matrices. 340011a5261eSBarry Smith 34012ef1f0ffSBarry Smith If `rmap` (`cmap`) is `NULL`, then the local row (column) spaces matches the global space. 3402284134d9SBarry Smith 34031cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatSetLocalToGlobalMapping()` 3404284134d9SBarry Smith @*/ 3405d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateIS(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt M, PetscInt N, ISLocalToGlobalMapping rmap, ISLocalToGlobalMapping cmap, Mat *A) 3406d71ae5a4SJacob Faibussowitsch { 3407284134d9SBarry Smith PetscFunctionBegin; 34089566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, A)); 34099566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A, m, n, M, N)); 341048a46eb9SPierre Jolivet if (bs > 0) PetscCall(MatSetBlockSize(*A, bs)); 34119566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATIS)); 34129566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*A, rmap, cmap)); 34133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3414284134d9SBarry Smith } 3415284134d9SBarry Smith 3416d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHasOperation_IS(Mat A, MatOperation op, PetscBool *has) 3417d71ae5a4SJacob Faibussowitsch { 34188b9382cfSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3419e26763e4SStefano Zampini MatOperation tobefiltered[] = {MATOP_MULT_ADD, MATOP_MULT_TRANSPOSE_ADD, MATOP_GET_DIAGONAL_BLOCK, MATOP_INCREASE_OVERLAP}; 34208b9382cfSStefano Zampini 34218b9382cfSStefano Zampini PetscFunctionBegin; 34228b9382cfSStefano Zampini *has = PETSC_FALSE; 34233ba16761SJacob Faibussowitsch if (!((void **)A->ops)[op] || !a->A) PetscFunctionReturn(PETSC_SUCCESS); 3424d0dbe9f7SStefano Zampini *has = PETSC_TRUE; 34259371c9d4SSatish Balay for (PetscInt i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(tobefiltered); i++) 34263ba16761SJacob Faibussowitsch if (op == tobefiltered[i]) PetscFunctionReturn(PETSC_SUCCESS); 34279566063dSJacob Faibussowitsch PetscCall(MatHasOperation(a->A, op, has)); 34283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34298b9382cfSStefano Zampini } 34308b9382cfSStefano Zampini 3431d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesCOO_IS(Mat A, const PetscScalar v[], InsertMode imode) 3432d71ae5a4SJacob Faibussowitsch { 3433e432b41dSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3434e432b41dSStefano Zampini 3435e432b41dSStefano Zampini PetscFunctionBegin; 34369566063dSJacob Faibussowitsch PetscCall(MatSetValuesCOO(a->A, v, imode)); 34379566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 34389566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 34393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3440e432b41dSStefano Zampini } 3441e432b41dSStefano Zampini 3442d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetPreallocationCOOLocal_IS(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[]) 3443d71ae5a4SJacob Faibussowitsch { 3444e432b41dSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3445e432b41dSStefano Zampini 3446e432b41dSStefano Zampini PetscFunctionBegin; 3447e432b41dSStefano Zampini PetscCheck(a->A, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Need to provide l2g map first via MatSetLocalToGlobalMapping"); 3448e432b41dSStefano Zampini if (a->A->rmap->mapping || a->A->cmap->mapping) { 34499566063dSJacob Faibussowitsch PetscCall(MatSetPreallocationCOOLocal(a->A, ncoo, coo_i, coo_j)); 3450e432b41dSStefano Zampini } else { 34519566063dSJacob Faibussowitsch PetscCall(MatSetPreallocationCOO(a->A, ncoo, coo_i, coo_j)); 3452e432b41dSStefano Zampini } 34539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", MatSetValuesCOO_IS)); 3454e432b41dSStefano Zampini A->preallocated = PETSC_TRUE; 34553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3456e432b41dSStefano Zampini } 3457e432b41dSStefano Zampini 3458d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetPreallocationCOO_IS(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[]) 3459d71ae5a4SJacob Faibussowitsch { 3460e432b41dSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3461835f2295SStefano Zampini PetscInt ncoo_i; 3462e432b41dSStefano Zampini 3463e432b41dSStefano Zampini PetscFunctionBegin; 3464e432b41dSStefano Zampini PetscCheck(a->A, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Need to provide l2g map first via MatSetLocalToGlobalMapping"); 3465835f2295SStefano Zampini PetscCall(PetscIntCast(ncoo, &ncoo_i)); 3466835f2295SStefano Zampini PetscCall(ISGlobalToLocalMappingApply(a->rmapping, IS_GTOLM_MASK, ncoo_i, coo_i, NULL, coo_i)); 3467835f2295SStefano Zampini PetscCall(ISGlobalToLocalMappingApply(a->cmapping, IS_GTOLM_MASK, ncoo_i, coo_j, NULL, coo_j)); 3468e8729f6fSJunchao Zhang PetscCall(MatSetPreallocationCOO(a->A, ncoo, coo_i, coo_j)); 34699566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", MatSetValuesCOO_IS)); 3470e432b41dSStefano Zampini A->preallocated = PETSC_TRUE; 34713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3472e432b41dSStefano Zampini } 3473e432b41dSStefano Zampini 3474d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISGetAssembled_Private(Mat A, Mat *tA) 3475d71ae5a4SJacob Faibussowitsch { 3476d0dbe9f7SStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 34771690c2aeSBarry Smith PetscObjectState Astate, aAstate = PETSC_INT_MIN; 34781690c2aeSBarry Smith PetscObjectState Annzstate, aAnnzstate = PETSC_INT_MIN; 3479d0dbe9f7SStefano Zampini 3480d0dbe9f7SStefano Zampini PetscFunctionBegin; 3481d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateGet((PetscObject)A, &Astate)); 3482d0dbe9f7SStefano Zampini Annzstate = A->nonzerostate; 3483d0dbe9f7SStefano Zampini if (a->assembledA) { 3484d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateGet((PetscObject)a->assembledA, &aAstate)); 3485d0dbe9f7SStefano Zampini aAnnzstate = a->assembledA->nonzerostate; 3486d0dbe9f7SStefano Zampini } 3487d0dbe9f7SStefano Zampini if (aAnnzstate != Annzstate) PetscCall(MatDestroy(&a->assembledA)); 3488d0dbe9f7SStefano Zampini if (Astate != aAstate || !a->assembledA) { 3489d0dbe9f7SStefano Zampini MatType aAtype; 3490d0dbe9f7SStefano Zampini PetscMPIInt size; 3491d0dbe9f7SStefano Zampini PetscInt rbs, cbs, bs; 3492d0dbe9f7SStefano Zampini 3493d0dbe9f7SStefano Zampini /* the assembled form is used as temporary storage for parallel operations 3494d0dbe9f7SStefano Zampini like createsubmatrices and the like, do not waste device memory */ 3495d0dbe9f7SStefano Zampini PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 3496d0dbe9f7SStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockSize(a->cmapping, &cbs)); 3497d0dbe9f7SStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockSize(a->rmapping, &rbs)); 3498d0dbe9f7SStefano Zampini bs = rbs == cbs ? rbs : 1; 3499d0dbe9f7SStefano Zampini if (a->assembledA) PetscCall(MatGetType(a->assembledA, &aAtype)); 3500d0dbe9f7SStefano Zampini else if (size > 1) aAtype = bs > 1 ? MATMPIBAIJ : MATMPIAIJ; 3501d0dbe9f7SStefano Zampini else aAtype = bs > 1 ? MATSEQBAIJ : MATSEQAIJ; 3502d0dbe9f7SStefano Zampini 3503d0dbe9f7SStefano Zampini PetscCall(MatConvert(A, aAtype, a->assembledA ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX, &a->assembledA)); 3504d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateSet((PetscObject)a->assembledA, Astate)); 3505d0dbe9f7SStefano Zampini a->assembledA->nonzerostate = Annzstate; 3506d0dbe9f7SStefano Zampini } 3507d0dbe9f7SStefano Zampini PetscCall(PetscObjectReference((PetscObject)a->assembledA)); 3508d0dbe9f7SStefano Zampini *tA = a->assembledA; 3509d0dbe9f7SStefano Zampini if (!a->keepassembled) PetscCall(MatDestroy(&a->assembledA)); 35103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3511d0dbe9f7SStefano Zampini } 3512d0dbe9f7SStefano Zampini 3513d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISRestoreAssembled_Private(Mat A, Mat *tA) 3514d71ae5a4SJacob Faibussowitsch { 3515d0dbe9f7SStefano Zampini PetscFunctionBegin; 3516d0dbe9f7SStefano Zampini PetscCall(MatDestroy(tA)); 3517d0dbe9f7SStefano Zampini *tA = NULL; 35183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3519d0dbe9f7SStefano Zampini } 3520d0dbe9f7SStefano Zampini 3521d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonalBlock_IS(Mat A, Mat *dA) 3522d71ae5a4SJacob Faibussowitsch { 3523d0dbe9f7SStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 35241690c2aeSBarry Smith PetscObjectState Astate, dAstate = PETSC_INT_MIN; 3525d0dbe9f7SStefano Zampini 3526d0dbe9f7SStefano Zampini PetscFunctionBegin; 3527d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateGet((PetscObject)A, &Astate)); 3528d0dbe9f7SStefano Zampini if (a->dA) PetscCall(PetscObjectStateGet((PetscObject)a->dA, &dAstate)); 3529d0dbe9f7SStefano Zampini if (Astate != dAstate) { 3530d0dbe9f7SStefano Zampini Mat tA; 3531d0dbe9f7SStefano Zampini MatType ltype; 3532d0dbe9f7SStefano Zampini 3533d0dbe9f7SStefano Zampini PetscCall(MatDestroy(&a->dA)); 3534d0dbe9f7SStefano Zampini PetscCall(MatISGetAssembled_Private(A, &tA)); 3535d0dbe9f7SStefano Zampini PetscCall(MatGetDiagonalBlock(tA, &a->dA)); 3536d0dbe9f7SStefano Zampini PetscCall(MatPropagateSymmetryOptions(tA, a->dA)); 3537d0dbe9f7SStefano Zampini PetscCall(MatGetType(a->A, <ype)); 3538d0dbe9f7SStefano Zampini PetscCall(MatConvert(a->dA, ltype, MAT_INPLACE_MATRIX, &a->dA)); 3539d0dbe9f7SStefano Zampini PetscCall(PetscObjectReference((PetscObject)a->dA)); 3540d0dbe9f7SStefano Zampini PetscCall(MatISRestoreAssembled_Private(A, &tA)); 3541d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateSet((PetscObject)a->dA, Astate)); 3542d0dbe9f7SStefano Zampini } 3543d0dbe9f7SStefano Zampini *dA = a->dA; 35443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3545d0dbe9f7SStefano Zampini } 3546d0dbe9f7SStefano Zampini 3547d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrices_IS(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse reuse, Mat *submat[]) 3548d71ae5a4SJacob Faibussowitsch { 3549d0dbe9f7SStefano Zampini Mat tA; 3550d0dbe9f7SStefano Zampini 3551d0dbe9f7SStefano Zampini PetscFunctionBegin; 3552d0dbe9f7SStefano Zampini PetscCall(MatISGetAssembled_Private(A, &tA)); 3553d0dbe9f7SStefano Zampini PetscCall(MatCreateSubMatrices(tA, n, irow, icol, reuse, submat)); 3554d0dbe9f7SStefano Zampini /* MatCreateSubMatrices_MPIAIJ is a mess at the moment */ 3555d0dbe9f7SStefano Zampini #if 0 3556d0dbe9f7SStefano Zampini { 3557d0dbe9f7SStefano Zampini Mat_IS *a = (Mat_IS*)A->data; 3558d0dbe9f7SStefano Zampini MatType ltype; 3559d0dbe9f7SStefano Zampini VecType vtype; 3560d0dbe9f7SStefano Zampini char *flg; 3561d0dbe9f7SStefano Zampini 3562d0dbe9f7SStefano Zampini PetscCall(MatGetType(a->A,<ype)); 3563d0dbe9f7SStefano Zampini PetscCall(MatGetVecType(a->A,&vtype)); 3564d0dbe9f7SStefano Zampini PetscCall(PetscStrstr(vtype,"cuda",&flg)); 3565d0dbe9f7SStefano Zampini if (!flg) PetscCall(PetscStrstr(vtype,"hip",&flg)); 3566d0dbe9f7SStefano Zampini if (!flg) PetscCall(PetscStrstr(vtype,"kokkos",&flg)); 3567d0dbe9f7SStefano Zampini if (flg) { 3568d0dbe9f7SStefano Zampini for (PetscInt i = 0; i < n; i++) { 3569d0dbe9f7SStefano Zampini Mat sA = (*submat)[i]; 3570d0dbe9f7SStefano Zampini 3571d0dbe9f7SStefano Zampini PetscCall(MatConvert(sA,ltype,MAT_INPLACE_MATRIX,&sA)); 3572d0dbe9f7SStefano Zampini (*submat)[i] = sA; 3573d0dbe9f7SStefano Zampini } 3574d0dbe9f7SStefano Zampini } 3575d0dbe9f7SStefano Zampini } 3576d0dbe9f7SStefano Zampini #endif 3577d0dbe9f7SStefano Zampini PetscCall(MatISRestoreAssembled_Private(A, &tA)); 35783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3579d0dbe9f7SStefano Zampini } 3580d0dbe9f7SStefano Zampini 3581d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIncreaseOverlap_IS(Mat A, PetscInt n, IS is[], PetscInt ov) 3582d71ae5a4SJacob Faibussowitsch { 3583d0dbe9f7SStefano Zampini Mat tA; 3584d0dbe9f7SStefano Zampini 3585d0dbe9f7SStefano Zampini PetscFunctionBegin; 3586d0dbe9f7SStefano Zampini PetscCall(MatISGetAssembled_Private(A, &tA)); 3587d0dbe9f7SStefano Zampini PetscCall(MatIncreaseOverlap(tA, n, is, ov)); 3588d0dbe9f7SStefano Zampini PetscCall(MatISRestoreAssembled_Private(A, &tA)); 35893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3590d0dbe9f7SStefano Zampini } 3591d0dbe9f7SStefano Zampini 3592e432b41dSStefano Zampini /*@ 359311a5261eSBarry Smith MatISGetLocalToGlobalMapping - Gets the local-to-global numbering of the `MATIS` object 3594e432b41dSStefano Zampini 3595e432b41dSStefano Zampini Not Collective 3596e432b41dSStefano Zampini 3597e432b41dSStefano Zampini Input Parameter: 3598e432b41dSStefano Zampini . A - the matrix 3599e432b41dSStefano Zampini 3600e432b41dSStefano Zampini Output Parameters: 3601e432b41dSStefano Zampini + rmapping - row mapping 3602e432b41dSStefano Zampini - cmapping - column mapping 3603e432b41dSStefano Zampini 36042ef1f0ffSBarry Smith Level: advanced 36052ef1f0ffSBarry Smith 360611a5261eSBarry Smith Note: 360711a5261eSBarry 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. 3608e432b41dSStefano Zampini 3609bfe80ac4SPierre Jolivet .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatSetLocalToGlobalMapping()` 3610e432b41dSStefano Zampini @*/ 3611d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 3612d71ae5a4SJacob Faibussowitsch { 3613e432b41dSStefano Zampini PetscFunctionBegin; 3614e432b41dSStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3615e432b41dSStefano Zampini PetscValidType(A, 1); 36164f572ea9SToby Isaac if (rmapping) PetscAssertPointer(rmapping, 2); 36174f572ea9SToby Isaac if (cmapping) PetscAssertPointer(cmapping, 3); 3618cac4c232SBarry Smith PetscUseMethod(A, "MatISGetLocalToGlobalMapping_C", (Mat, ISLocalToGlobalMapping *, ISLocalToGlobalMapping *), (A, rmapping, cmapping)); 36193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3620e432b41dSStefano Zampini } 3621e432b41dSStefano Zampini 3622d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISGetLocalToGlobalMapping_IS(Mat A, ISLocalToGlobalMapping *r, ISLocalToGlobalMapping *c) 3623d71ae5a4SJacob Faibussowitsch { 3624e432b41dSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3625e432b41dSStefano Zampini 3626e432b41dSStefano Zampini PetscFunctionBegin; 3627e432b41dSStefano Zampini if (r) *r = a->rmapping; 3628e432b41dSStefano Zampini if (c) *c = a->cmapping; 36293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3630e432b41dSStefano Zampini } 3631e432b41dSStefano Zampini 3632a50ef18cSStefano Zampini static PetscErrorCode MatSetBlockSizes_IS(Mat A, PetscInt rbs, PetscInt cbs) 3633a50ef18cSStefano Zampini { 3634a50ef18cSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3635a50ef18cSStefano Zampini 3636a50ef18cSStefano Zampini PetscFunctionBegin; 3637a50ef18cSStefano Zampini if (a->A) PetscCall(MatSetBlockSizes(a->A, rbs, cbs)); 3638a50ef18cSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 3639a50ef18cSStefano Zampini } 3640a50ef18cSStefano Zampini 3641b4319ba4SBarry Smith /*MC 36424f58015eSStefano Zampini MATIS - MATIS = "is" - A matrix type to be used for non-overlapping domain decomposition methods (e.g. `PCBDDC` or `KSPFETIDP`). 36434f58015eSStefano Zampini This stores the matrices in globally unassembled form and the parallel matrix vector product is handled "implicitly". 3644b4319ba4SBarry Smith 3645b4319ba4SBarry Smith Options Database Keys: 36464f58015eSStefano Zampini + -mat_type is - Set the matrix type to `MATIS`. 36474f58015eSStefano Zampini . -mat_is_allow_repeated - Allow repeated entries in the local part of the local to global maps. 36484f58015eSStefano Zampini . -mat_is_fixempty - Fix local matrices in case of empty local rows/columns. 36494f58015eSStefano Zampini - -mat_is_storel2l - Store the local-to-local operators generated by the Galerkin process of `MatPtAP()`. 36502ef1f0ffSBarry Smith 36514f58015eSStefano Zampini Level: intermediate 3652b4319ba4SBarry Smith 365395452b02SPatrick Sanan Notes: 36542ef1f0ffSBarry Smith Options prefix for the inner matrix are given by `-is_mat_xxx` 3655b4319ba4SBarry Smith 365611a5261eSBarry Smith You must call `MatSetLocalToGlobalMapping()` before using this matrix type. 3657b4319ba4SBarry Smith 3658b4319ba4SBarry Smith You can do matrix preallocation on the local matrix after you obtain it with 36594f58015eSStefano Zampini `MatISGetLocalMat()`; otherwise, you could use `MatISSetPreallocation()` or `MatXAIJSetPreallocation()` 3660b4319ba4SBarry Smith 36611cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `Mat`, `MatISGetLocalMat()`, `MatSetLocalToGlobalMapping()`, `MatISSetPreallocation()`, `MatCreateIS()`, `PCBDDC`, `KSPFETIDP` 3662b4319ba4SBarry Smith M*/ 3663d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A) 3664d71ae5a4SJacob Faibussowitsch { 3665e432b41dSStefano Zampini Mat_IS *a; 3666b4319ba4SBarry Smith 3667b4319ba4SBarry Smith PetscFunctionBegin; 36684dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&a)); 36699566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATAIJ, &a->lmattype)); 3670e432b41dSStefano Zampini A->data = (void *)a; 3671b4319ba4SBarry Smith 3672e176bc59SStefano Zampini /* matrix ops */ 36739566063dSJacob Faibussowitsch PetscCall(PetscMemzero(A->ops, sizeof(struct _MatOps))); 3674b4319ba4SBarry Smith A->ops->mult = MatMult_IS; 36752e74eeadSLisandro Dalcin A->ops->multadd = MatMultAdd_IS; 36762e74eeadSLisandro Dalcin A->ops->multtranspose = MatMultTranspose_IS; 36772e74eeadSLisandro Dalcin A->ops->multtransposeadd = MatMultTransposeAdd_IS; 3678b4319ba4SBarry Smith A->ops->destroy = MatDestroy_IS; 3679b4319ba4SBarry Smith A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS; 36802e74eeadSLisandro Dalcin A->ops->setvalues = MatSetValues_IS; 368198921651SStefano Zampini A->ops->setvaluesblocked = MatSetValuesBlocked_IS; 3682b4319ba4SBarry Smith A->ops->setvalueslocal = MatSetValuesLocal_IS; 3683f0006bf2SLisandro Dalcin A->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_IS; 36842e74eeadSLisandro Dalcin A->ops->zerorows = MatZeroRows_IS; 3685f0ae7da4SStefano Zampini A->ops->zerorowscolumns = MatZeroRowsColumns_IS; 3686b4319ba4SBarry Smith A->ops->assemblybegin = MatAssemblyBegin_IS; 3687b4319ba4SBarry Smith A->ops->assemblyend = MatAssemblyEnd_IS; 3688b4319ba4SBarry Smith A->ops->view = MatView_IS; 36895042aa92SStefano Zampini A->ops->load = MatLoad_IS; 36906726f965SBarry Smith A->ops->zeroentries = MatZeroEntries_IS; 36912e74eeadSLisandro Dalcin A->ops->scale = MatScale_IS; 36922e74eeadSLisandro Dalcin A->ops->getdiagonal = MatGetDiagonal_IS; 36936726f965SBarry Smith A->ops->setoption = MatSetOption_IS; 369469796d55SStefano Zampini A->ops->ishermitian = MatIsHermitian_IS; 369569796d55SStefano Zampini A->ops->issymmetric = MatIsSymmetric_IS; 369645471136SStefano Zampini A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS; 3697ad6194a2SStefano Zampini A->ops->duplicate = MatDuplicate_IS; 36986bd84002SStefano Zampini A->ops->missingdiagonal = MatMissingDiagonal_IS; 36992b404112SStefano Zampini A->ops->copy = MatCopy_IS; 3700659959c5SStefano Zampini A->ops->getlocalsubmatrix = MatGetLocalSubMatrix_IS; 37017dae84e0SHong Zhang A->ops->createsubmatrix = MatCreateSubMatrix_IS; 3702f26d0771SStefano Zampini A->ops->axpy = MatAXPY_IS; 37033fd1c9e7SStefano Zampini A->ops->diagonalset = MatDiagonalSet_IS; 37043fd1c9e7SStefano Zampini A->ops->shift = MatShift_IS; 3705d7f69cd0SStefano Zampini A->ops->transpose = MatTranspose_IS; 37067fa8f2d3SStefano Zampini A->ops->getinfo = MatGetInfo_IS; 3707ad219c80Sstefano_zampini A->ops->diagonalscale = MatDiagonalScale_IS; 3708872cf891SStefano Zampini A->ops->setfromoptions = MatSetFromOptions_IS; 3709fc989267SStefano Zampini A->ops->setup = MatSetUp_IS; 37108b9382cfSStefano Zampini A->ops->hasoperation = MatHasOperation_IS; 3711d0dbe9f7SStefano Zampini A->ops->getdiagonalblock = MatGetDiagonalBlock_IS; 3712d0dbe9f7SStefano Zampini A->ops->createsubmatrices = MatCreateSubMatrices_IS; 3713d0dbe9f7SStefano Zampini A->ops->increaseoverlap = MatIncreaseOverlap_IS; 3714a50ef18cSStefano Zampini A->ops->setblocksizes = MatSetBlockSizes_IS; 3715b4319ba4SBarry Smith 3716b7ce53b6SStefano Zampini /* special MATIS functions */ 37179566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMatType_C", MatISSetLocalMatType_IS)); 37189566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalMat_C", MatISGetLocalMat_IS)); 37199566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISRestoreLocalMat_C", MatISRestoreLocalMat_IS)); 37209566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMat_C", MatISSetLocalMat_IS)); 37219566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetPreallocation_C", MatISSetPreallocation_IS)); 37224f58015eSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetAllowRepeated_C", MatISSetAllowRepeated_IS)); 37239566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISStoreL2L_C", MatISStoreL2L_IS)); 37249566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISFixLocalEmpty_C", MatISFixLocalEmpty_IS)); 37259566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalToGlobalMapping_C", MatISGetLocalToGlobalMapping_IS)); 37269566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpiaij_C", MatConvert_IS_XAIJ)); 37279566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpibaij_C", MatConvert_IS_XAIJ)); 37289566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpisbaij_C", MatConvert_IS_XAIJ)); 37299566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqaij_C", MatConvert_IS_XAIJ)); 37309566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqbaij_C", MatConvert_IS_XAIJ)); 37319566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqsbaij_C", MatConvert_IS_XAIJ)); 37329566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_aij_C", MatConvert_IS_XAIJ)); 37339566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOOLocal_C", MatSetPreallocationCOOLocal_IS)); 37349566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_IS)); 37359566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, MATIS)); 37363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3737b4319ba4SBarry Smith } 3738