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 17b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat, PetscInt, const PetscInt *, PetscInt, const PetscInt *, const PetscScalar *, InsertMode); 18b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat, PetscInt, const PetscInt *, PetscInt, const PetscInt *, const PetscScalar *, InsertMode); 198546b261SStefano Zampini static PetscErrorCode MatISSetUpScatters_Private(Mat); 20f26d0771SStefano Zampini 21*49abdd8aSBarry Smith static PetscErrorCode MatISContainerDestroyPtAP_Private(void **ptr) 22d71ae5a4SJacob Faibussowitsch { 23*49abdd8aSBarry Smith MatISPtAP ptap = (MatISPtAP)*ptr; 2475d48cdbSStefano Zampini 2575d48cdbSStefano Zampini PetscFunctionBegin; 269566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrices(ptap->ris1 ? 2 : 1, &ptap->lP)); 279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ptap->cis0)); 289566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ptap->cis1)); 299566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ptap->ris0)); 309566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ptap->ris1)); 319566063dSJacob Faibussowitsch PetscCall(PetscFree(ptap)); 323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3375d48cdbSStefano Zampini } 3475d48cdbSStefano Zampini 35d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_IS_XAIJ(Mat A, Mat P, Mat C) 36d71ae5a4SJacob Faibussowitsch { 3775d48cdbSStefano Zampini MatISPtAP ptap; 3875d48cdbSStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 3975d48cdbSStefano Zampini Mat lA, lC; 4075d48cdbSStefano Zampini MatReuse reuse; 4175d48cdbSStefano Zampini IS ris[2], cis[2]; 4275d48cdbSStefano Zampini PetscContainer c; 4375d48cdbSStefano Zampini PetscInt n; 4475d48cdbSStefano Zampini 4575d48cdbSStefano Zampini PetscFunctionBegin; 469566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)C, "_MatIS_PtAP", (PetscObject *)&c)); 4728b400f6SJacob Faibussowitsch PetscCheck(c, PetscObjectComm((PetscObject)C), PETSC_ERR_PLIB, "Missing PtAP information"); 489566063dSJacob Faibussowitsch PetscCall(PetscContainerGetPointer(c, (void **)&ptap)); 4975d48cdbSStefano Zampini ris[0] = ptap->ris0; 5075d48cdbSStefano Zampini ris[1] = ptap->ris1; 5175d48cdbSStefano Zampini cis[0] = ptap->cis0; 5275d48cdbSStefano Zampini cis[1] = ptap->cis1; 5375d48cdbSStefano Zampini n = ptap->ris1 ? 2 : 1; 5475d48cdbSStefano Zampini reuse = ptap->lP ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX; 559566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(P, n, ris, cis, reuse, &ptap->lP)); 5675d48cdbSStefano Zampini 579566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A, &lA)); 589566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(C, &lC)); 5975d48cdbSStefano Zampini if (ptap->ris1) { /* unsymmetric A mapping */ 6075d48cdbSStefano Zampini Mat lPt; 6175d48cdbSStefano Zampini 629566063dSJacob Faibussowitsch PetscCall(MatTranspose(ptap->lP[1], MAT_INITIAL_MATRIX, &lPt)); 639566063dSJacob Faibussowitsch PetscCall(MatMatMatMult(lPt, lA, ptap->lP[0], reuse, ptap->fill, &lC)); 6457508eceSPierre Jolivet if (matis->storel2l) PetscCall(PetscObjectCompose((PetscObject)A, "_MatIS_PtAP_l2l", (PetscObject)lPt)); 659566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lPt)); 6675d48cdbSStefano Zampini } else { 679566063dSJacob Faibussowitsch PetscCall(MatPtAP(lA, ptap->lP[0], reuse, ptap->fill, &lC)); 6848a46eb9SPierre Jolivet if (matis->storel2l) PetscCall(PetscObjectCompose((PetscObject)C, "_MatIS_PtAP_l2l", (PetscObject)ptap->lP[0])); 6975d48cdbSStefano Zampini } 7075d48cdbSStefano Zampini if (reuse == MAT_INITIAL_MATRIX) { 719566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(C, lC)); 729566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lC)); 7375d48cdbSStefano Zampini } 749566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 759566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7775d48cdbSStefano Zampini } 7875d48cdbSStefano Zampini 79d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetNonzeroColumnsLocal_Private(Mat PT, IS *cis) 80d71ae5a4SJacob Faibussowitsch { 8175d48cdbSStefano Zampini Mat Po, Pd; 8275d48cdbSStefano Zampini IS zd, zo; 8375d48cdbSStefano Zampini const PetscInt *garray; 8475d48cdbSStefano Zampini PetscInt *aux, i, bs; 8575d48cdbSStefano Zampini PetscInt dc, stc, oc, ctd, cto; 8675d48cdbSStefano Zampini PetscBool ismpiaij, ismpibaij, isseqaij, isseqbaij; 8775d48cdbSStefano Zampini MPI_Comm comm; 8875d48cdbSStefano Zampini 8975d48cdbSStefano Zampini PetscFunctionBegin; 9075d48cdbSStefano Zampini PetscValidHeaderSpecific(PT, MAT_CLASSID, 1); 914f572ea9SToby Isaac PetscAssertPointer(cis, 2); 929566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)PT, &comm)); 9375d48cdbSStefano Zampini bs = 1; 949566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)PT, MATMPIAIJ, &ismpiaij)); 959566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)PT, MATMPIBAIJ, &ismpibaij)); 969566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)PT, MATSEQAIJ, &isseqaij)); 979566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)PT, MATSEQBAIJ, &isseqbaij)); 9875d48cdbSStefano Zampini if (isseqaij || isseqbaij) { 9975d48cdbSStefano Zampini Pd = PT; 10075d48cdbSStefano Zampini Po = NULL; 10175d48cdbSStefano Zampini garray = NULL; 10275d48cdbSStefano Zampini } else if (ismpiaij) { 1039566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(PT, &Pd, &Po, &garray)); 10475d48cdbSStefano Zampini } else if (ismpibaij) { 1059566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJGetSeqBAIJ(PT, &Pd, &Po, &garray)); 1069566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(PT, &bs)); 10757508eceSPierre Jolivet } else SETERRQ(comm, PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)PT)->type_name); 10875d48cdbSStefano Zampini 10975d48cdbSStefano Zampini /* identify any null columns in Pd or Po */ 11022f7620eSStefano Zampini /* We use a tolerance comparison since it may happen that, with geometric multigrid, 11122f7620eSStefano Zampini some of the columns are not really zero, but very close to */ 11275d48cdbSStefano Zampini zo = zd = NULL; 11348a46eb9SPierre Jolivet if (Po) PetscCall(MatFindNonzeroRowsOrCols_Basic(Po, PETSC_TRUE, PETSC_SMALL, &zo)); 1149566063dSJacob Faibussowitsch PetscCall(MatFindNonzeroRowsOrCols_Basic(Pd, PETSC_TRUE, PETSC_SMALL, &zd)); 11575d48cdbSStefano Zampini 1169566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(PT, NULL, &dc)); 1179566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(PT, &stc, NULL)); 1189566063dSJacob Faibussowitsch if (Po) PetscCall(MatGetLocalSize(Po, NULL, &oc)); 11975d48cdbSStefano Zampini else oc = 0; 1209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((dc + oc) / bs, &aux)); 12175d48cdbSStefano Zampini if (zd) { 12275d48cdbSStefano Zampini const PetscInt *idxs; 12375d48cdbSStefano Zampini PetscInt nz; 12475d48cdbSStefano Zampini 12575d48cdbSStefano Zampini /* this will throw an error if bs is not valid */ 1269566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(zd, bs)); 1279566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zd, &nz)); 1289566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zd, &idxs)); 12975d48cdbSStefano Zampini ctd = nz / bs; 13075d48cdbSStefano Zampini for (i = 0; i < ctd; i++) aux[i] = (idxs[bs * i] + stc) / bs; 1319566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zd, &idxs)); 13275d48cdbSStefano Zampini } else { 13375d48cdbSStefano Zampini ctd = dc / bs; 13475d48cdbSStefano Zampini for (i = 0; i < ctd; i++) aux[i] = i + stc / bs; 13575d48cdbSStefano Zampini } 13675d48cdbSStefano Zampini if (zo) { 13775d48cdbSStefano Zampini const PetscInt *idxs; 13875d48cdbSStefano Zampini PetscInt nz; 13975d48cdbSStefano Zampini 14075d48cdbSStefano Zampini /* this will throw an error if bs is not valid */ 1419566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(zo, bs)); 1429566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zo, &nz)); 1439566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zo, &idxs)); 14475d48cdbSStefano Zampini cto = nz / bs; 14575d48cdbSStefano Zampini for (i = 0; i < cto; i++) aux[i + ctd] = garray[idxs[bs * i] / bs]; 1469566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zo, &idxs)); 14775d48cdbSStefano Zampini } else { 14875d48cdbSStefano Zampini cto = oc / bs; 14975d48cdbSStefano Zampini for (i = 0; i < cto; i++) aux[i + ctd] = garray[i]; 15075d48cdbSStefano Zampini } 1519566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, bs, ctd + cto, aux, PETSC_OWN_POINTER, cis)); 1529566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zd)); 1539566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zo)); 1543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15575d48cdbSStefano Zampini } 15675d48cdbSStefano Zampini 157d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPSymbolic_IS_XAIJ(Mat A, Mat P, PetscReal fill, Mat C) 158d71ae5a4SJacob Faibussowitsch { 1598546b261SStefano Zampini Mat PT, lA; 16075d48cdbSStefano Zampini MatISPtAP ptap; 16175d48cdbSStefano Zampini ISLocalToGlobalMapping Crl2g, Ccl2g, rl2g, cl2g; 16275d48cdbSStefano Zampini PetscContainer c; 1638546b261SStefano Zampini MatType lmtype; 16475d48cdbSStefano Zampini const PetscInt *garray; 16575d48cdbSStefano Zampini PetscInt ibs, N, dc; 16675d48cdbSStefano Zampini MPI_Comm comm; 16775d48cdbSStefano Zampini 16875d48cdbSStefano Zampini PetscFunctionBegin; 1699566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 1709566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATIS)); 1719566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A, &lA)); 1729566063dSJacob Faibussowitsch PetscCall(MatGetType(lA, &lmtype)); 1739566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(C, lmtype)); 1749566063dSJacob Faibussowitsch PetscCall(MatGetSize(P, NULL, &N)); 1759566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(P, NULL, &dc)); 1769566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, dc, dc, N, N)); 17775d48cdbSStefano Zampini /* Not sure about this 1789566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(P,NULL,&ibs)); 1799566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(*C,ibs)); 18075d48cdbSStefano Zampini */ 18175d48cdbSStefano Zampini 1829566063dSJacob Faibussowitsch PetscCall(PetscNew(&ptap)); 1839566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c)); 1849566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(c, ptap)); 185*49abdd8aSBarry Smith PetscCall(PetscContainerSetCtxDestroy(c, MatISContainerDestroyPtAP_Private)); 1869566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)C, "_MatIS_PtAP", (PetscObject)c)); 1879566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&c)); 18875d48cdbSStefano Zampini ptap->fill = fill; 18975d48cdbSStefano Zampini 1909566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(A, &rl2g, &cl2g)); 19175d48cdbSStefano Zampini 1929566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(cl2g, &ibs)); 1939566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(cl2g, &N)); 1949566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(cl2g, &garray)); 1959566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, ibs, N / ibs, garray, PETSC_COPY_VALUES, &ptap->ris0)); 1969566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(cl2g, &garray)); 19775d48cdbSStefano Zampini 1989566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(P, ptap->ris0, NULL, MAT_INITIAL_MATRIX, &PT)); 1999566063dSJacob Faibussowitsch PetscCall(MatGetNonzeroColumnsLocal_Private(PT, &ptap->cis0)); 2009566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(ptap->cis0, &Ccl2g)); 2019566063dSJacob Faibussowitsch PetscCall(MatDestroy(&PT)); 20275d48cdbSStefano Zampini 20375d48cdbSStefano Zampini Crl2g = NULL; 20475d48cdbSStefano Zampini if (rl2g != cl2g) { /* unsymmetric A mapping */ 20575d48cdbSStefano Zampini PetscBool same, lsame = PETSC_FALSE; 20675d48cdbSStefano Zampini PetscInt N1, ibs1; 20775d48cdbSStefano Zampini 2089566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(rl2g, &N1)); 2099566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(rl2g, &ibs1)); 2109566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(rl2g, &garray)); 2114f58015eSStefano Zampini PetscCall(ISCreateBlock(comm, ibs, N1 / ibs, garray, PETSC_COPY_VALUES, &ptap->ris1)); 2129566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(rl2g, &garray)); 21375d48cdbSStefano Zampini if (ibs1 == ibs && N1 == N) { /* check if the l2gmaps are the same */ 21475d48cdbSStefano Zampini const PetscInt *i1, *i2; 21575d48cdbSStefano Zampini 2169566063dSJacob Faibussowitsch PetscCall(ISBlockGetIndices(ptap->ris0, &i1)); 2179566063dSJacob Faibussowitsch PetscCall(ISBlockGetIndices(ptap->ris1, &i2)); 2189566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(i1, i2, N, &lsame)); 21975d48cdbSStefano Zampini } 220462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&lsame, &same, 1, MPIU_BOOL, MPI_LAND, comm)); 22175d48cdbSStefano Zampini if (same) { 2229566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ptap->ris1)); 22375d48cdbSStefano Zampini } else { 2249566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(P, ptap->ris1, NULL, MAT_INITIAL_MATRIX, &PT)); 2259566063dSJacob Faibussowitsch PetscCall(MatGetNonzeroColumnsLocal_Private(PT, &ptap->cis1)); 2269566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(ptap->cis1, &Crl2g)); 2279566063dSJacob Faibussowitsch PetscCall(MatDestroy(&PT)); 22875d48cdbSStefano Zampini } 22975d48cdbSStefano Zampini } 23075d48cdbSStefano Zampini /* Not sure about this 23175d48cdbSStefano Zampini if (!Crl2g) { 2329566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(C,&ibs)); 2339566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetBlockSize(Ccl2g,ibs)); 23475d48cdbSStefano Zampini } 23575d48cdbSStefano Zampini */ 2369566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(C, Crl2g ? Crl2g : Ccl2g, Ccl2g)); 2379566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&Crl2g)); 2389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&Ccl2g)); 23975d48cdbSStefano Zampini 2404222ddf1SHong Zhang C->ops->ptapnumeric = MatPtAPNumeric_IS_XAIJ; 2413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24275d48cdbSStefano Zampini } 24375d48cdbSStefano Zampini 244d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_PtAP_IS_XAIJ(Mat C) 245d71ae5a4SJacob Faibussowitsch { 2464222ddf1SHong Zhang Mat_Product *product = C->product; 2474222ddf1SHong Zhang Mat A = product->A, P = product->B; 2484222ddf1SHong Zhang PetscReal fill = product->fill; 24975d48cdbSStefano Zampini 25075d48cdbSStefano Zampini PetscFunctionBegin; 2519566063dSJacob Faibussowitsch PetscCall(MatPtAPSymbolic_IS_XAIJ(A, P, fill, C)); 2524222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_PtAP; 2533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25475d48cdbSStefano Zampini } 25575d48cdbSStefano Zampini 256d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_IS_XAIJ_PtAP(Mat C) 257d71ae5a4SJacob Faibussowitsch { 2584222ddf1SHong Zhang PetscFunctionBegin; 2594222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_PtAP_IS_XAIJ; 2603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2614222ddf1SHong Zhang } 2624222ddf1SHong Zhang 263d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat C) 264d71ae5a4SJacob Faibussowitsch { 2654222ddf1SHong Zhang Mat_Product *product = C->product; 2664222ddf1SHong Zhang 2674222ddf1SHong Zhang PetscFunctionBegin; 26848a46eb9SPierre Jolivet if (product->type == MATPRODUCT_PtAP) PetscCall(MatProductSetFromOptions_IS_XAIJ_PtAP(C)); 2693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2704222ddf1SHong Zhang } 2714222ddf1SHong Zhang 272*49abdd8aSBarry Smith static PetscErrorCode MatISContainerDestroyFields_Private(void **ptr) 273d71ae5a4SJacob Faibussowitsch { 274*49abdd8aSBarry Smith MatISLocalFields lf = (MatISLocalFields)*ptr; 2755b003df0Sstefano_zampini PetscInt i; 2765b003df0Sstefano_zampini 277ab4d48faSStefano Zampini PetscFunctionBegin; 27848a46eb9SPierre Jolivet for (i = 0; i < lf->nr; i++) PetscCall(ISDestroy(&lf->rf[i])); 27948a46eb9SPierre Jolivet for (i = 0; i < lf->nc; i++) PetscCall(ISDestroy(&lf->cf[i])); 2809566063dSJacob Faibussowitsch PetscCall(PetscFree2(lf->rf, lf->cf)); 2819566063dSJacob Faibussowitsch PetscCall(PetscFree(lf)); 2823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2835b003df0Sstefano_zampini } 284a72627d2SStefano Zampini 285d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_SeqXAIJ_IS(Mat A, MatType type, MatReuse reuse, Mat *newmat) 286d71ae5a4SJacob Faibussowitsch { 287c9225affSStefano Zampini Mat B, lB; 288c9225affSStefano Zampini 289c9225affSStefano Zampini PetscFunctionBegin; 290c9225affSStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 291c9225affSStefano Zampini ISLocalToGlobalMapping rl2g, cl2g; 292c9225affSStefano Zampini PetscInt bs; 293c9225affSStefano Zampini IS is; 294c9225affSStefano Zampini 2959566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 2969566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), A->rmap->n / bs, 0, 1, &is)); 297c9225affSStefano Zampini if (bs > 1) { 298c9225affSStefano Zampini IS is2; 299c9225affSStefano Zampini PetscInt i, *aux; 300c9225affSStefano Zampini 3019566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &i)); 3029566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, (const PetscInt **)&aux)); 3039566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), bs, i, aux, PETSC_COPY_VALUES, &is2)); 3049566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, (const PetscInt **)&aux)); 3059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 306c9225affSStefano Zampini is = is2; 307c9225affSStefano Zampini } 3089566063dSJacob Faibussowitsch PetscCall(ISSetIdentity(is)); 3099566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g)); 3109566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3119566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), A->cmap->n / bs, 0, 1, &is)); 312c9225affSStefano Zampini if (bs > 1) { 313c9225affSStefano Zampini IS is2; 314c9225affSStefano Zampini PetscInt i, *aux; 315c9225affSStefano Zampini 3169566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &i)); 3179566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, (const PetscInt **)&aux)); 3189566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), bs, i, aux, PETSC_COPY_VALUES, &is2)); 3199566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, (const PetscInt **)&aux)); 3209566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 321c9225affSStefano Zampini is = is2; 322c9225affSStefano Zampini } 3239566063dSJacob Faibussowitsch PetscCall(ISSetIdentity(is)); 3249566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g)); 3259566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3269566063dSJacob Faibussowitsch PetscCall(MatCreateIS(PetscObjectComm((PetscObject)A), bs, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N, rl2g, cl2g, &B)); 3279566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 3289566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 3299566063dSJacob Faibussowitsch PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &lB)); 330c9225affSStefano Zampini if (reuse == MAT_INITIAL_MATRIX) *newmat = B; 331c9225affSStefano Zampini } else { 332c9225affSStefano Zampini B = *newmat; 3339566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 334c9225affSStefano Zampini lB = A; 335c9225affSStefano Zampini } 3369566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B, lB)); 3379566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lB)); 3389566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 3399566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 34048a46eb9SPierre Jolivet if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &B)); 3413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 342c9225affSStefano Zampini } 343c9225affSStefano Zampini 344d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISScaleDisassembling_Private(Mat A) 345d71ae5a4SJacob Faibussowitsch { 346f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)A->data; 347c9225affSStefano Zampini PetscScalar *aa; 348c9225affSStefano Zampini const PetscInt *ii, *jj; 349c9225affSStefano Zampini PetscInt i, n, m; 350fabe8965SStefano Zampini PetscInt *ecount, **eneighs; 351c9225affSStefano Zampini PetscBool flg; 352c9225affSStefano Zampini 353c9225affSStefano Zampini PetscFunctionBegin; 3549566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(matis->A, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg)); 35508401ef6SPierre Jolivet PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get IJ structure"); 3569566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetNodeInfo(matis->rmapping, &n, &ecount, &eneighs)); 35708401ef6SPierre Jolivet PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, m, n); 3589566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(matis->A, &aa)); 359c9225affSStefano Zampini for (i = 0; i < n; i++) { 360fabe8965SStefano Zampini if (ecount[i] > 1) { 361c9225affSStefano Zampini PetscInt j; 362c9225affSStefano Zampini 363c9225affSStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 364c9225affSStefano Zampini PetscInt i2 = jj[j], p, p2; 365fabe8965SStefano Zampini PetscReal scal = 0.0; 366c9225affSStefano Zampini 367c9225affSStefano Zampini for (p = 0; p < ecount[i]; p++) { 368c9225affSStefano Zampini for (p2 = 0; p2 < ecount[i2]; p2++) { 3699371c9d4SSatish Balay if (eneighs[i][p] == eneighs[i2][p2]) { 3709371c9d4SSatish Balay scal += 1.0; 3719371c9d4SSatish Balay break; 3729371c9d4SSatish Balay } 373c9225affSStefano Zampini } 374c9225affSStefano Zampini } 375fabe8965SStefano Zampini if (scal) aa[j] /= scal; 376c9225affSStefano Zampini } 377c9225affSStefano Zampini } 378c9225affSStefano Zampini } 3799566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(matis->rmapping, &n, &ecount, &eneighs)); 3809566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(matis->A, &aa)); 3819566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(matis->A, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg)); 38208401ef6SPierre Jolivet PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot restore IJ structure"); 3833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 384c9225affSStefano Zampini } 385c9225affSStefano Zampini 3869371c9d4SSatish Balay typedef enum { 3879371c9d4SSatish Balay MAT_IS_DISASSEMBLE_L2G_NATURAL, 3889371c9d4SSatish Balay MAT_IS_DISASSEMBLE_L2G_MAT, 3899371c9d4SSatish Balay MAT_IS_DISASSEMBLE_L2G_ND 3909371c9d4SSatish Balay } MatISDisassemblel2gType; 391fabe8965SStefano Zampini 392d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMPIXAIJComputeLocalToGlobalMapping_Private(Mat A, ISLocalToGlobalMapping *l2g) 393d71ae5a4SJacob Faibussowitsch { 394fabe8965SStefano Zampini Mat Ad, Ao; 395fabe8965SStefano Zampini IS is, ndmap, ndsub; 396c9225affSStefano Zampini MPI_Comm comm; 397fabe8965SStefano Zampini const PetscInt *garray, *ndmapi; 398fabe8965SStefano Zampini PetscInt bs, i, cnt, nl, *ncount, *ndmapc; 399fabe8965SStefano Zampini PetscBool ismpiaij, ismpibaij; 400f4259b30SLisandro Dalcin const char *const MatISDisassemblel2gTypes[] = {"NATURAL", "MAT", "ND", "MatISDisassemblel2gType", "MAT_IS_DISASSEMBLE_L2G_", NULL}; 401fabe8965SStefano Zampini MatISDisassemblel2gType mode = MAT_IS_DISASSEMBLE_L2G_NATURAL; 402fabe8965SStefano Zampini MatPartitioning part; 403fabe8965SStefano Zampini PetscSF sf; 40491d376acSStefano Zampini PetscObject dm; 405c9225affSStefano Zampini 406c9225affSStefano Zampini PetscFunctionBegin; 407d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)A), ((PetscObject)A)->prefix, "MatIS l2g disassembling options", "Mat"); 4089566063dSJacob 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)); 409d0609cedSBarry Smith PetscOptionsEnd(); 410fabe8965SStefano Zampini if (mode == MAT_IS_DISASSEMBLE_L2G_MAT) { 4119566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(A, l2g, NULL)); 4123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 413c9225affSStefano Zampini } 4149566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 4159566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 4169566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIBAIJ, &ismpibaij)); 4179566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 418fabe8965SStefano Zampini switch (mode) { 419fabe8965SStefano Zampini case MAT_IS_DISASSEMBLE_L2G_ND: 4209566063dSJacob Faibussowitsch PetscCall(MatPartitioningCreate(comm, &part)); 4219566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetAdjacency(part, A)); 4229566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)part, ((PetscObject)A)->prefix)); 4239566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetFromOptions(part)); 4249566063dSJacob Faibussowitsch PetscCall(MatPartitioningApplyND(part, &ndmap)); 4259566063dSJacob Faibussowitsch PetscCall(MatPartitioningDestroy(&part)); 4269566063dSJacob Faibussowitsch PetscCall(ISBuildTwoSided(ndmap, NULL, &ndsub)); 4279566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetUseScalableIncreaseOverlap(A, PETSC_TRUE)); 4289566063dSJacob Faibussowitsch PetscCall(MatIncreaseOverlap(A, 1, &ndsub, 1)); 4299566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(ndsub, l2g)); 430fabe8965SStefano Zampini 431fabe8965SStefano Zampini /* it may happen that a separator node is not properly shared */ 4329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetNodeInfo(*l2g, &nl, &ncount, NULL)); 4339566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &sf)); 4349566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(*l2g, &garray)); 4359566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(sf, A->rmap, nl, NULL, PETSC_OWN_POINTER, garray)); 4369566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(*l2g, &garray)); 4379566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(A->rmap->n, &ndmapc)); 4389566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(sf, MPIU_INT, ncount, ndmapc, MPI_REPLACE)); 4399566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(sf, MPIU_INT, ncount, ndmapc, MPI_REPLACE)); 4409566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(*l2g, NULL, &ncount, NULL)); 4419566063dSJacob Faibussowitsch PetscCall(ISGetIndices(ndmap, &ndmapi)); 442fabe8965SStefano Zampini for (i = 0, cnt = 0; i < A->rmap->n; i++) 4439371c9d4SSatish Balay if (ndmapi[i] < 0 && ndmapc[i] < 2) cnt++; 444fabe8965SStefano Zampini 445462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&cnt, &i, 1, MPIU_INT, MPI_MAX, comm)); 446fabe8965SStefano Zampini if (i) { /* we detected isolated separator nodes */ 447fabe8965SStefano Zampini Mat A2, A3; 448fabe8965SStefano Zampini IS *workis, is2; 449fabe8965SStefano Zampini PetscScalar *vals; 450fabe8965SStefano Zampini PetscInt gcnt = i, *dnz, *onz, j, *lndmapi; 451fabe8965SStefano Zampini ISLocalToGlobalMapping ll2g; 452fabe8965SStefano Zampini PetscBool flg; 453fabe8965SStefano Zampini const PetscInt *ii, *jj; 454fabe8965SStefano Zampini 455fabe8965SStefano Zampini /* communicate global id of separators */ 456d0609cedSBarry Smith MatPreallocateBegin(comm, A->rmap->n, A->cmap->n, dnz, onz); 4579371c9d4SSatish Balay for (i = 0, cnt = 0; i < A->rmap->n; i++) dnz[i] = ndmapi[i] < 0 ? i + A->rmap->rstart : -1; 458fabe8965SStefano Zampini 4599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl, &lndmapi)); 4609566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, dnz, lndmapi, MPI_REPLACE)); 461fabe8965SStefano Zampini 462fabe8965SStefano Zampini /* compute adjacency of isolated separators node */ 4639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(gcnt, &workis)); 464fabe8965SStefano Zampini for (i = 0, cnt = 0; i < A->rmap->n; i++) { 46548a46eb9SPierre Jolivet if (ndmapi[i] < 0 && ndmapc[i] < 2) PetscCall(ISCreateStride(comm, 1, i + A->rmap->rstart, 1, &workis[cnt++])); 466fabe8965SStefano Zampini } 46748a46eb9SPierre Jolivet for (i = cnt; i < gcnt; i++) PetscCall(ISCreateStride(comm, 0, 0, 1, &workis[i])); 468fabe8965SStefano Zampini for (i = 0; i < gcnt; i++) { 4699566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)workis[i], "ISOLATED")); 4709566063dSJacob Faibussowitsch PetscCall(ISViewFromOptions(workis[i], NULL, "-view_isolated_separators")); 471fabe8965SStefano Zampini } 472fabe8965SStefano Zampini 473fabe8965SStefano Zampini /* no communications since all the ISes correspond to locally owned rows */ 4749566063dSJacob Faibussowitsch PetscCall(MatIncreaseOverlap(A, gcnt, workis, 1)); 475fabe8965SStefano Zampini 476fabe8965SStefano Zampini /* end communicate global id of separators */ 4779566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, dnz, lndmapi, MPI_REPLACE)); 478fabe8965SStefano Zampini 479fabe8965SStefano Zampini /* communicate new layers : create a matrix and transpose it */ 4809566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(dnz, A->rmap->n)); 4819566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(onz, A->rmap->n)); 482fabe8965SStefano Zampini for (i = 0, j = 0; i < A->rmap->n; i++) { 483fabe8965SStefano Zampini if (ndmapi[i] < 0 && ndmapc[i] < 2) { 484fabe8965SStefano Zampini const PetscInt *idxs; 485fabe8965SStefano Zampini PetscInt s; 486fabe8965SStefano Zampini 4879566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(workis[j], &s)); 4889566063dSJacob Faibussowitsch PetscCall(ISGetIndices(workis[j], &idxs)); 4899566063dSJacob Faibussowitsch PetscCall(MatPreallocateSet(i + A->rmap->rstart, s, idxs, dnz, onz)); 490fabe8965SStefano Zampini j++; 491fabe8965SStefano Zampini } 492fabe8965SStefano Zampini } 49308401ef6SPierre Jolivet PetscCheck(j == cnt, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected local count %" PetscInt_FMT " != %" PetscInt_FMT, j, cnt); 494fabe8965SStefano Zampini 495fabe8965SStefano Zampini for (i = 0; i < gcnt; i++) { 4969566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)workis[i], "EXTENDED")); 4979566063dSJacob Faibussowitsch PetscCall(ISViewFromOptions(workis[i], NULL, "-view_isolated_separators")); 498fabe8965SStefano Zampini } 499fabe8965SStefano Zampini 500fabe8965SStefano Zampini for (i = 0, j = 0; i < A->rmap->n; i++) j = PetscMax(j, dnz[i] + onz[i]); 5019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(j, &vals)); 502fabe8965SStefano Zampini for (i = 0; i < j; i++) vals[i] = 1.0; 503fabe8965SStefano Zampini 5049566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &A2)); 5059566063dSJacob Faibussowitsch PetscCall(MatSetType(A2, MATMPIAIJ)); 5069566063dSJacob Faibussowitsch PetscCall(MatSetSizes(A2, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N)); 5079566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(A2, 0, dnz, 0, onz)); 5089566063dSJacob Faibussowitsch PetscCall(MatSetOption(A2, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE)); 509fabe8965SStefano Zampini for (i = 0, j = 0; i < A2->rmap->n; i++) { 510fabe8965SStefano Zampini PetscInt row = i + A2->rmap->rstart, s = dnz[i] + onz[i]; 511fabe8965SStefano Zampini const PetscInt *idxs; 512fabe8965SStefano Zampini 513fabe8965SStefano Zampini if (s) { 5149566063dSJacob Faibussowitsch PetscCall(ISGetIndices(workis[j], &idxs)); 5159566063dSJacob Faibussowitsch PetscCall(MatSetValues(A2, 1, &row, s, idxs, vals, INSERT_VALUES)); 5169566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(workis[j], &idxs)); 517fabe8965SStefano Zampini j++; 518fabe8965SStefano Zampini } 519fabe8965SStefano Zampini } 52008401ef6SPierre Jolivet PetscCheck(j == cnt, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected local count %" PetscInt_FMT " != %" PetscInt_FMT, j, cnt); 5219566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 5229566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A2, MAT_FINAL_ASSEMBLY)); 5239566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A2, MAT_FINAL_ASSEMBLY)); 5249566063dSJacob Faibussowitsch PetscCall(MatTranspose(A2, MAT_INPLACE_MATRIX, &A2)); 525fabe8965SStefano Zampini 526fabe8965SStefano Zampini /* extract submatrix corresponding to the coupling "owned separators" x "isolated separators" */ 527fabe8965SStefano Zampini for (i = 0, j = 0; i < nl; i++) 528fabe8965SStefano Zampini if (lndmapi[i] >= 0) lndmapi[j++] = lndmapi[i]; 5299566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, j, lndmapi, PETSC_USE_POINTER, &is)); 5309566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetLocalMatCondensed(A2, MAT_INITIAL_MATRIX, &is, NULL, &A3)); 5319566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 5329566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A2)); 533fabe8965SStefano Zampini 534fabe8965SStefano Zampini /* extend local to global map to include connected isolated separators */ 5359566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)A3, "_petsc_GetLocalMatCondensed_iscol", (PetscObject *)&is)); 53628b400f6SJacob Faibussowitsch PetscCheck(is, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing column map"); 5379566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &ll2g)); 5389566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A3, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &flg)); 53928b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get IJ structure"); 5409566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ii[i], jj, PETSC_COPY_VALUES, &is)); 5419566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A3, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &flg)); 54228b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get IJ structure"); 5439566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(ll2g, is, &is2)); 5449566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 5459566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&ll2g)); 546fabe8965SStefano Zampini 547fabe8965SStefano Zampini /* add new nodes to the local-to-global map */ 5489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(l2g)); 5499566063dSJacob Faibussowitsch PetscCall(ISExpand(ndsub, is2, &is)); 5509566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is2)); 5519566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, l2g)); 5529566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 553fabe8965SStefano Zampini 5549566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A3)); 5559566063dSJacob Faibussowitsch PetscCall(PetscFree(lndmapi)); 556d0609cedSBarry Smith MatPreallocateEnd(dnz, onz); 55748a46eb9SPierre Jolivet for (i = 0; i < gcnt; i++) PetscCall(ISDestroy(&workis[i])); 5589566063dSJacob Faibussowitsch PetscCall(PetscFree(workis)); 559fabe8965SStefano Zampini } 5609566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(ndmap, &ndmapi)); 5619566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 5629566063dSJacob Faibussowitsch PetscCall(PetscFree(ndmapc)); 5639566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ndmap)); 5649566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ndsub)); 5659566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetBlockSize(*l2g, bs)); 5664f58015eSStefano Zampini PetscCall(ISLocalToGlobalMappingViewFromOptions(*l2g, NULL, "-mat_is_nd_l2g_view")); 567fabe8965SStefano Zampini break; 568fabe8965SStefano Zampini case MAT_IS_DISASSEMBLE_L2G_NATURAL: 56991d376acSStefano Zampini PetscCall(PetscObjectQuery((PetscObject)A, "__PETSc_dm", (PetscObject *)&dm)); 57091d376acSStefano Zampini if (dm) { /* if a matrix comes from a DM, most likely we can use the l2gmap if any */ 57191d376acSStefano Zampini PetscCall(MatGetLocalToGlobalMapping(A, l2g, NULL)); 57291d376acSStefano Zampini PetscCall(PetscObjectReference((PetscObject)*l2g)); 5733ba16761SJacob Faibussowitsch if (*l2g) PetscFunctionReturn(PETSC_SUCCESS); 57491d376acSStefano Zampini } 575fabe8965SStefano Zampini if (ismpiaij) { 5769566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(A, &Ad, &Ao, &garray)); 577fabe8965SStefano Zampini } else if (ismpibaij) { 5789566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJGetSeqBAIJ(A, &Ad, &Ao, &garray)); 57998921bdaSJacob Faibussowitsch } else SETERRQ(comm, PETSC_ERR_SUP, "Type %s", ((PetscObject)A)->type_name); 580c9225affSStefano Zampini if (A->rmap->n) { 581fabe8965SStefano Zampini PetscInt dc, oc, stc, *aux; 582c9225affSStefano Zampini 583ebf8cefbSJunchao Zhang PetscCall(MatGetLocalSize(Ad, NULL, &dc)); 5849566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(Ao, NULL, &oc)); 585d0dbe9f7SStefano Zampini PetscCheck(!oc || garray, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "garray not present"); 5869566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(A, &stc, NULL)); 5879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((dc + oc) / bs, &aux)); 588c9225affSStefano Zampini for (i = 0; i < dc / bs; i++) aux[i] = i + stc / bs; 589ebf8cefbSJunchao Zhang for (i = 0; i < oc / bs; i++) aux[i + dc / bs] = (ismpiaij ? garray[i * bs] / bs : garray[i]); 5909566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, bs, (dc + oc) / bs, aux, PETSC_OWN_POINTER, &is)); 591c9225affSStefano Zampini } else { 5929566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, 1, 0, NULL, PETSC_OWN_POINTER, &is)); 593c9225affSStefano Zampini } 5949566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, l2g)); 5959566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 596fabe8965SStefano Zampini break; 597d71ae5a4SJacob Faibussowitsch default: 598d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unsupported l2g disassembling type %d", mode); 599c9225affSStefano Zampini } 6003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 601c9225affSStefano Zampini } 602c9225affSStefano Zampini 603d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat A, MatType type, MatReuse reuse, Mat *newmat) 604d71ae5a4SJacob Faibussowitsch { 605c9225affSStefano Zampini Mat lA, Ad, Ao, B = NULL; 6066989cf23SStefano Zampini ISLocalToGlobalMapping rl2g, cl2g; 6076989cf23SStefano Zampini IS is; 6086989cf23SStefano Zampini MPI_Comm comm; 6096989cf23SStefano Zampini void *ptrs[2]; 6106989cf23SStefano Zampini const char *names[2] = {"_convert_csr_aux", "_convert_csr_data"}; 611c9225affSStefano Zampini const PetscInt *garray; 6126989cf23SStefano Zampini PetscScalar *dd, *od, *aa, *data; 613c9225affSStefano Zampini const PetscInt *di, *dj, *oi, *oj; 614c9225affSStefano Zampini const PetscInt *odi, *odj, *ooi, *ooj; 6156989cf23SStefano Zampini PetscInt *aux, *ii, *jj; 616a50ef18cSStefano Zampini PetscInt rbs, cbs, lc, dr, dc, oc, str, stc, nnz, i, jd, jo, cum; 617a50ef18cSStefano Zampini PetscBool flg, ismpiaij, ismpibaij, was_inplace = PETSC_FALSE, cong; 618c9225affSStefano Zampini PetscMPIInt size; 6196989cf23SStefano Zampini 620ab4d48faSStefano Zampini PetscFunctionBegin; 6219566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 6229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 623c9225affSStefano Zampini if (size == 1) { 6249566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqXAIJ_IS(A, type, reuse, newmat)); 6253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 626c9225affSStefano Zampini } 627a50ef18cSStefano Zampini PetscCall(MatGetBlockSizes(A, &rbs, &cbs)); 628a50ef18cSStefano Zampini PetscCall(MatHasCongruentLayouts(A, &cong)); 629a50ef18cSStefano Zampini if (reuse != MAT_REUSE_MATRIX && cong && rbs == cbs) { 6309566063dSJacob Faibussowitsch PetscCall(MatMPIXAIJComputeLocalToGlobalMapping_Private(A, &rl2g)); 6319566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &B)); 6329566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATIS)); 633a50ef18cSStefano Zampini PetscCall(MatSetSizes(B, A->rmap->n, A->rmap->n, A->rmap->N, A->rmap->N)); 6349566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B, rl2g, rl2g)); 635a50ef18cSStefano Zampini PetscCall(MatSetBlockSizes(B, rbs, rbs)); 6369566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 637c9225affSStefano Zampini if (reuse == MAT_INPLACE_MATRIX) was_inplace = PETSC_TRUE; 638c9225affSStefano Zampini reuse = MAT_REUSE_MATRIX; 639c9225affSStefano Zampini } 640c9225affSStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 641c9225affSStefano Zampini Mat *newlA, lA; 642c9225affSStefano Zampini IS rows, cols; 643c9225affSStefano Zampini const PetscInt *ridx, *cidx; 644a50ef18cSStefano Zampini PetscInt nr, nc; 645c9225affSStefano Zampini 646c9225affSStefano Zampini if (!B) B = *newmat; 6479566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(B, &rl2g, &cl2g)); 6489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(rl2g, &ridx)); 6499566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(cl2g, &cidx)); 6509566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(rl2g, &nr)); 6519566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(cl2g, &nc)); 6529566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(rl2g, &rbs)); 6539566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(cl2g, &cbs)); 6549566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, rbs, nr / rbs, ridx, PETSC_USE_POINTER, &rows)); 655c9225affSStefano Zampini if (rl2g != cl2g) { 6569566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, cbs, nc / cbs, cidx, PETSC_USE_POINTER, &cols)); 657c9225affSStefano Zampini } else { 6589566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)rows)); 659c9225affSStefano Zampini cols = rows; 660c9225affSStefano Zampini } 6619566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(B, &lA)); 6629566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(A, 1, &rows, &cols, MAT_INITIAL_MATRIX, &newlA)); 6639566063dSJacob Faibussowitsch PetscCall(MatConvert(newlA[0], MATSEQAIJ, MAT_INPLACE_MATRIX, &newlA[0])); 6649566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(rl2g, &ridx)); 6659566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(cl2g, &cidx)); 6669566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rows)); 6679566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cols)); 668c9225affSStefano Zampini if (!lA->preallocated) { /* first time */ 6699566063dSJacob Faibussowitsch PetscCall(MatDuplicate(newlA[0], MAT_COPY_VALUES, &lA)); 6709566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B, lA)); 6719566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)lA)); 672c9225affSStefano Zampini } 6739566063dSJacob Faibussowitsch PetscCall(MatCopy(newlA[0], lA, SAME_NONZERO_PATTERN)); 6749566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrices(1, &newlA)); 6759566063dSJacob Faibussowitsch PetscCall(MatISScaleDisassembling_Private(B)); 6769566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 6779566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 6789566063dSJacob Faibussowitsch if (was_inplace) PetscCall(MatHeaderReplace(A, &B)); 679c9225affSStefano Zampini else *newmat = B; 6803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 681c9225affSStefano Zampini } 682a50ef18cSStefano Zampini /* general case, just compress out the column space */ 6839566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 6849566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIBAIJ, &ismpibaij)); 685c9225affSStefano Zampini if (ismpiaij) { 686a50ef18cSStefano Zampini cbs = 1; /* We cannot guarantee the off-process matrix will respect the column block size */ 6879566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(A, &Ad, &Ao, &garray)); 688c9225affSStefano Zampini } else if (ismpibaij) { 6899566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJGetSeqBAIJ(A, &Ad, &Ao, &garray)); 6909566063dSJacob Faibussowitsch PetscCall(MatConvert(Ad, MATSEQAIJ, MAT_INITIAL_MATRIX, &Ad)); 6919566063dSJacob Faibussowitsch PetscCall(MatConvert(Ao, MATSEQAIJ, MAT_INITIAL_MATRIX, &Ao)); 69298921bdaSJacob Faibussowitsch } else SETERRQ(comm, PETSC_ERR_SUP, "Type %s", ((PetscObject)A)->type_name); 6939566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(Ad, &dd)); 6949566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(Ao, &od)); 6956989cf23SStefano Zampini 6966989cf23SStefano Zampini /* access relevant information from MPIAIJ */ 6979566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &str, NULL)); 6989566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(A, &stc, NULL)); 699a50ef18cSStefano Zampini PetscCall(MatGetLocalSize(Ad, &dr, &dc)); 7009566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(Ao, NULL, &oc)); 701d72e20dbSStefano Zampini PetscCheck(!oc || garray, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "garray not present"); 702d72e20dbSStefano Zampini 7039566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(Ad, 0, PETSC_FALSE, PETSC_FALSE, &i, &di, &dj, &flg)); 70428b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get IJ structure"); 7059566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(Ao, 0, PETSC_FALSE, PETSC_FALSE, &i, &oi, &oj, &flg)); 70628b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get IJ structure"); 707c9225affSStefano Zampini nnz = di[dr] + oi[dr]; 708c9225affSStefano Zampini /* store original pointers to be restored later */ 7099371c9d4SSatish Balay odi = di; 7109371c9d4SSatish Balay odj = dj; 7119371c9d4SSatish Balay ooi = oi; 7129371c9d4SSatish Balay ooj = oj; 7136989cf23SStefano Zampini 7146989cf23SStefano Zampini /* generate l2g maps for rows and cols */ 715a50ef18cSStefano Zampini PetscCall(ISCreateStride(comm, dr / rbs, str / rbs, 1, &is)); 716a50ef18cSStefano Zampini if (rbs > 1) { 717c9225affSStefano Zampini IS is2; 718c9225affSStefano Zampini 7199566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &i)); 7209566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, (const PetscInt **)&aux)); 721a50ef18cSStefano Zampini PetscCall(ISCreateBlock(comm, rbs, i, aux, PETSC_COPY_VALUES, &is2)); 7229566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, (const PetscInt **)&aux)); 7239566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 724c9225affSStefano Zampini is = is2; 725c9225affSStefano Zampini } 7269566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g)); 7279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 728e363d98aSStefano Zampini if (dr) { 729a50ef18cSStefano Zampini PetscCall(PetscMalloc1((dc + oc) / cbs, &aux)); 730a50ef18cSStefano Zampini for (i = 0; i < dc / cbs; i++) aux[i] = i + stc / cbs; 731a50ef18cSStefano Zampini for (i = 0; i < oc / cbs; i++) aux[i + dc / cbs] = garray[i]; 732a50ef18cSStefano Zampini PetscCall(ISCreateBlock(comm, cbs, (dc + oc) / cbs, aux, PETSC_OWN_POINTER, &is)); 733e363d98aSStefano Zampini lc = dc + oc; 734e363d98aSStefano Zampini } else { 735a50ef18cSStefano Zampini PetscCall(ISCreateBlock(comm, cbs, 0, NULL, PETSC_OWN_POINTER, &is)); 736e363d98aSStefano Zampini lc = 0; 737e363d98aSStefano Zampini } 7389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g)); 7399566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 7406989cf23SStefano Zampini 7416989cf23SStefano Zampini /* create MATIS object */ 7429566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &B)); 7439566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, dr, dc, PETSC_DECIDE, PETSC_DECIDE)); 7449566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATIS)); 745a50ef18cSStefano Zampini PetscCall(MatSetBlockSizes(B, rbs, cbs)); 7469566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B, rl2g, cl2g)); 7479566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 7489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 7496989cf23SStefano Zampini 7506989cf23SStefano Zampini /* merge local matrices */ 7519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz + dr + 1, &aux)); 7529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &data)); 7536989cf23SStefano Zampini ii = aux; 7546989cf23SStefano Zampini jj = aux + dr + 1; 7556989cf23SStefano Zampini aa = data; 7566989cf23SStefano Zampini *ii = *(di++) + *(oi++); 7579371c9d4SSatish Balay for (jd = 0, jo = 0, cum = 0; *ii < nnz; cum++) { 7589371c9d4SSatish Balay for (; jd < *di; jd++) { 7599371c9d4SSatish Balay *jj++ = *dj++; 7609371c9d4SSatish Balay *aa++ = *dd++; 7619371c9d4SSatish Balay } 7629371c9d4SSatish Balay for (; jo < *oi; jo++) { 7639371c9d4SSatish Balay *jj++ = *oj++ + dc; 7649371c9d4SSatish Balay *aa++ = *od++; 7659371c9d4SSatish Balay } 7666989cf23SStefano Zampini *(++ii) = *(di++) + *(oi++); 7676989cf23SStefano Zampini } 7686989cf23SStefano Zampini for (; cum < dr; cum++) *(++ii) = nnz; 769c9225affSStefano Zampini 7709566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(Ad, 0, PETSC_FALSE, PETSC_FALSE, &i, &odi, &odj, &flg)); 77128b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot restore IJ structure"); 7729566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(Ao, 0, PETSC_FALSE, PETSC_FALSE, &i, &ooi, &ooj, &flg)); 77328b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot restore IJ structure"); 7749566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(Ad, &dd)); 7759566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(Ao, &od)); 776c9225affSStefano Zampini 7776989cf23SStefano Zampini ii = aux; 7786989cf23SStefano Zampini jj = aux + dr + 1; 7796989cf23SStefano Zampini aa = data; 7809566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, dr, lc, ii, jj, aa, &lA)); 7816989cf23SStefano Zampini 7826989cf23SStefano Zampini /* create containers to destroy the data */ 7836989cf23SStefano Zampini ptrs[0] = aux; 7846989cf23SStefano Zampini ptrs[1] = data; 785*49abdd8aSBarry Smith for (i = 0; i < 2; i++) PetscCall(PetscObjectContainerCompose((PetscObject)lA, names[i], ptrs[i], PetscCtxDestroyDefault)); 786c9225affSStefano Zampini if (ismpibaij) { /* destroy converted local matrices */ 7879566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Ad)); 7889566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Ao)); 789c9225affSStefano Zampini } 7906989cf23SStefano Zampini 7916989cf23SStefano Zampini /* finalize matrix */ 7929566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B, lA)); 7939566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lA)); 7949566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 7959566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 796c9225affSStefano Zampini if (reuse == MAT_INPLACE_MATRIX) { 7979566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &B)); 798c9225affSStefano Zampini } else *newmat = B; 7993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8006989cf23SStefano Zampini } 8016989cf23SStefano Zampini 802d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A, MatType type, MatReuse reuse, Mat *newmat) 803d71ae5a4SJacob Faibussowitsch { 8045e3038f0Sstefano_zampini Mat **nest, *snest, **rnest, lA, B; 8055e3038f0Sstefano_zampini IS *iscol, *isrow, *islrow, *islcol; 8065e3038f0Sstefano_zampini ISLocalToGlobalMapping rl2g, cl2g; 8075e3038f0Sstefano_zampini MPI_Comm comm; 8085b003df0Sstefano_zampini PetscInt *lr, *lc, *l2gidxs; 8095b003df0Sstefano_zampini PetscInt i, j, nr, nc, rbs, cbs; 8109e7b2b25Sstefano_zampini PetscBool convert, lreuse, *istrans; 8114f58015eSStefano Zampini PetscBool3 allow_repeated = PETSC_BOOL3_UNKNOWN; 8125e3038f0Sstefano_zampini 813ab4d48faSStefano Zampini PetscFunctionBegin; 8149566063dSJacob Faibussowitsch PetscCall(MatNestGetSubMats(A, &nr, &nc, &nest)); 8155e3038f0Sstefano_zampini lreuse = PETSC_FALSE; 8165e3038f0Sstefano_zampini rnest = NULL; 8175e3038f0Sstefano_zampini if (reuse == MAT_REUSE_MATRIX) { 8185e3038f0Sstefano_zampini PetscBool ismatis, isnest; 8195e3038f0Sstefano_zampini 8209566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)*newmat, MATIS, &ismatis)); 821f4f49eeaSPierre Jolivet PetscCheck(ismatis, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_USER, "Cannot reuse matrix of type %s", ((PetscObject)*newmat)->type_name); 8229566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*newmat, &lA)); 8239566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)lA, MATNEST, &isnest)); 8245e3038f0Sstefano_zampini if (isnest) { 8259566063dSJacob Faibussowitsch PetscCall(MatNestGetSubMats(lA, &i, &j, &rnest)); 8265e3038f0Sstefano_zampini lreuse = (PetscBool)(i == nr && j == nc); 8275e3038f0Sstefano_zampini if (!lreuse) rnest = NULL; 8285e3038f0Sstefano_zampini } 8295e3038f0Sstefano_zampini } 8309566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 8319566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(nr, &lr, nc, &lc)); 8329566063dSJacob Faibussowitsch PetscCall(PetscCalloc6(nr, &isrow, nc, &iscol, nr, &islrow, nc, &islcol, nr * nc, &snest, nr * nc, &istrans)); 8339566063dSJacob Faibussowitsch PetscCall(MatNestGetISs(A, isrow, iscol)); 8345e3038f0Sstefano_zampini for (i = 0; i < nr; i++) { 8355e3038f0Sstefano_zampini for (j = 0; j < nc; j++) { 8364f58015eSStefano Zampini PetscBool ismatis, sallow; 8379e7b2b25Sstefano_zampini PetscInt l1, l2, lb1, lb2, ij = i * nc + j; 8385e3038f0Sstefano_zampini 8395e3038f0Sstefano_zampini /* Null matrix pointers are allowed in MATNEST */ 8405e3038f0Sstefano_zampini if (!nest[i][j]) continue; 8415e3038f0Sstefano_zampini 8425e3038f0Sstefano_zampini /* Nested matrices should be of type MATIS */ 843013e2dc7SBarry Smith PetscCall(PetscObjectTypeCompare((PetscObject)nest[i][j], MATTRANSPOSEVIRTUAL, &istrans[ij])); 8449e7b2b25Sstefano_zampini if (istrans[ij]) { 8459e7b2b25Sstefano_zampini Mat T, lT; 8469566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(nest[i][j], &T)); 8479566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)T, MATIS, &ismatis)); 84828b400f6SJacob 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); 8494f58015eSStefano Zampini PetscCall(MatISGetAllowRepeated(T, &sallow)); 8509566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(T, &lT)); 8519566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(lT, &snest[ij])); 8529e7b2b25Sstefano_zampini } else { 8539566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)nest[i][j], MATIS, &ismatis)); 85428b400f6SJacob 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); 8554f58015eSStefano Zampini PetscCall(MatISGetAllowRepeated(nest[i][j], &sallow)); 8569566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(nest[i][j], &snest[ij])); 8579e7b2b25Sstefano_zampini } 8584f58015eSStefano Zampini if (allow_repeated == PETSC_BOOL3_UNKNOWN) allow_repeated = PetscBoolToBool3(sallow); 8594f58015eSStefano Zampini PetscCheck(sallow == PetscBool3ToBool(allow_repeated), comm, PETSC_ERR_SUP, "Cannot mix repeated and non repeated maps"); 8605e3038f0Sstefano_zampini 8615e3038f0Sstefano_zampini /* Check compatibility of local sizes */ 8629566063dSJacob Faibussowitsch PetscCall(MatGetSize(snest[ij], &l1, &l2)); 8639566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(snest[ij], &lb1, &lb2)); 8645e3038f0Sstefano_zampini if (!l1 || !l2) continue; 865aed4548fSBarry 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); 866aed4548fSBarry 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); 8675e3038f0Sstefano_zampini lr[i] = l1; 8685e3038f0Sstefano_zampini lc[j] = l2; 8695e3038f0Sstefano_zampini 870da81f932SPierre Jolivet /* check compatibility for local matrix reusage */ 8715e3038f0Sstefano_zampini if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE; 8725e3038f0Sstefano_zampini } 8735e3038f0Sstefano_zampini } 8745e3038f0Sstefano_zampini 87576bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 8765e3038f0Sstefano_zampini /* Check compatibility of l2g maps for rows */ 8775e3038f0Sstefano_zampini for (i = 0; i < nr; i++) { 8785e3038f0Sstefano_zampini rl2g = NULL; 8795e3038f0Sstefano_zampini for (j = 0; j < nc; j++) { 8805e3038f0Sstefano_zampini PetscInt n1, n2; 8815e3038f0Sstefano_zampini 8825e3038f0Sstefano_zampini if (!nest[i][j]) continue; 8839e7b2b25Sstefano_zampini if (istrans[i * nc + j]) { 8849e7b2b25Sstefano_zampini Mat T; 8859e7b2b25Sstefano_zampini 8869566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(nest[i][j], &T)); 8879566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(T, NULL, &cl2g)); 8889e7b2b25Sstefano_zampini } else { 8899566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(nest[i][j], &cl2g, NULL)); 8909e7b2b25Sstefano_zampini } 8919566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(cl2g, &n1)); 8925e3038f0Sstefano_zampini if (!n1) continue; 8935e3038f0Sstefano_zampini if (!rl2g) { 8945e3038f0Sstefano_zampini rl2g = cl2g; 8955e3038f0Sstefano_zampini } else { 8965e3038f0Sstefano_zampini const PetscInt *idxs1, *idxs2; 8975e3038f0Sstefano_zampini PetscBool same; 8985e3038f0Sstefano_zampini 8999566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(rl2g, &n2)); 90008401ef6SPierre 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); 9019566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(cl2g, &idxs1)); 9029566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(rl2g, &idxs2)); 9039566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(idxs1, idxs2, n1, &same)); 9049566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(cl2g, &idxs1)); 9059566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(rl2g, &idxs2)); 90628b400f6SJacob 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); 9075e3038f0Sstefano_zampini } 9085e3038f0Sstefano_zampini } 9095e3038f0Sstefano_zampini } 9105e3038f0Sstefano_zampini /* Check compatibility of l2g maps for columns */ 9115e3038f0Sstefano_zampini for (i = 0; i < nc; i++) { 9125e3038f0Sstefano_zampini rl2g = NULL; 9135e3038f0Sstefano_zampini for (j = 0; j < nr; j++) { 9145e3038f0Sstefano_zampini PetscInt n1, n2; 9155e3038f0Sstefano_zampini 9165e3038f0Sstefano_zampini if (!nest[j][i]) continue; 9179e7b2b25Sstefano_zampini if (istrans[j * nc + i]) { 9189e7b2b25Sstefano_zampini Mat T; 9199e7b2b25Sstefano_zampini 9209566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(nest[j][i], &T)); 9219566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(T, &cl2g, NULL)); 9229e7b2b25Sstefano_zampini } else { 9239566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(nest[j][i], NULL, &cl2g)); 9249e7b2b25Sstefano_zampini } 9259566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(cl2g, &n1)); 9265e3038f0Sstefano_zampini if (!n1) continue; 9275e3038f0Sstefano_zampini if (!rl2g) { 9285e3038f0Sstefano_zampini rl2g = cl2g; 9295e3038f0Sstefano_zampini } else { 9305e3038f0Sstefano_zampini const PetscInt *idxs1, *idxs2; 9315e3038f0Sstefano_zampini PetscBool same; 9325e3038f0Sstefano_zampini 9339566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(rl2g, &n2)); 93408401ef6SPierre 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); 9359566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(cl2g, &idxs1)); 9369566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(rl2g, &idxs2)); 9379566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(idxs1, idxs2, n1, &same)); 9389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(cl2g, &idxs1)); 9399566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(rl2g, &idxs2)); 94028b400f6SJacob 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); 9415e3038f0Sstefano_zampini } 9425e3038f0Sstefano_zampini } 9435e3038f0Sstefano_zampini } 94476bd3646SJed Brown } 9455e3038f0Sstefano_zampini 9465e3038f0Sstefano_zampini B = NULL; 9475e3038f0Sstefano_zampini if (reuse != MAT_REUSE_MATRIX) { 9485b003df0Sstefano_zampini PetscInt stl; 9495b003df0Sstefano_zampini 9505e3038f0Sstefano_zampini /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */ 9515e3038f0Sstefano_zampini for (i = 0, stl = 0; i < nr; i++) stl += lr[i]; 9529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(stl, &l2gidxs)); 9535b003df0Sstefano_zampini for (i = 0, stl = 0; i < nr; i++) { 9545e3038f0Sstefano_zampini Mat usedmat; 9555e3038f0Sstefano_zampini Mat_IS *matis; 9565e3038f0Sstefano_zampini const PetscInt *idxs; 9575e3038f0Sstefano_zampini 9585e3038f0Sstefano_zampini /* local IS for local NEST */ 9599566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, lr[i], stl, 1, &islrow[i])); 9605e3038f0Sstefano_zampini 9615e3038f0Sstefano_zampini /* l2gmap */ 9625e3038f0Sstefano_zampini j = 0; 9635e3038f0Sstefano_zampini usedmat = nest[i][j]; 9649e7b2b25Sstefano_zampini while (!usedmat && j < nc - 1) usedmat = nest[i][++j]; 96528b400f6SJacob Faibussowitsch PetscCheck(usedmat, comm, PETSC_ERR_SUP, "Cannot find valid row mat"); 9669e7b2b25Sstefano_zampini 9679e7b2b25Sstefano_zampini if (istrans[i * nc + j]) { 9689e7b2b25Sstefano_zampini Mat T; 9699566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(usedmat, &T)); 9709e7b2b25Sstefano_zampini usedmat = T; 9719e7b2b25Sstefano_zampini } 972f4f49eeaSPierre Jolivet matis = (Mat_IS *)usedmat->data; 9739566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isrow[i], &idxs)); 9749e7b2b25Sstefano_zampini if (istrans[i * nc + j]) { 9759566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->csf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 9769566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->csf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 9779e7b2b25Sstefano_zampini } else { 9789566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 9799566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 9809e7b2b25Sstefano_zampini } 9819566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(isrow[i], &idxs)); 9825e3038f0Sstefano_zampini stl += lr[i]; 9835e3038f0Sstefano_zampini } 9849566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(comm, 1, stl, l2gidxs, PETSC_OWN_POINTER, &rl2g)); 9855e3038f0Sstefano_zampini 9865e3038f0Sstefano_zampini /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */ 9875e3038f0Sstefano_zampini for (i = 0, stl = 0; i < nc; i++) stl += lc[i]; 9889566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(stl, &l2gidxs)); 9895b003df0Sstefano_zampini for (i = 0, stl = 0; i < nc; i++) { 9905e3038f0Sstefano_zampini Mat usedmat; 9915e3038f0Sstefano_zampini Mat_IS *matis; 9925e3038f0Sstefano_zampini const PetscInt *idxs; 9935e3038f0Sstefano_zampini 9945e3038f0Sstefano_zampini /* local IS for local NEST */ 9959566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, lc[i], stl, 1, &islcol[i])); 9965e3038f0Sstefano_zampini 9975e3038f0Sstefano_zampini /* l2gmap */ 9985e3038f0Sstefano_zampini j = 0; 9995e3038f0Sstefano_zampini usedmat = nest[j][i]; 10009e7b2b25Sstefano_zampini while (!usedmat && j < nr - 1) usedmat = nest[++j][i]; 100128b400f6SJacob Faibussowitsch PetscCheck(usedmat, comm, PETSC_ERR_SUP, "Cannot find valid column mat"); 10029e7b2b25Sstefano_zampini if (istrans[j * nc + i]) { 10039e7b2b25Sstefano_zampini Mat T; 10049566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(usedmat, &T)); 10059e7b2b25Sstefano_zampini usedmat = T; 10069e7b2b25Sstefano_zampini } 1007f4f49eeaSPierre Jolivet matis = (Mat_IS *)usedmat->data; 10089566063dSJacob Faibussowitsch PetscCall(ISGetIndices(iscol[i], &idxs)); 10099e7b2b25Sstefano_zampini if (istrans[j * nc + i]) { 10109566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 10119566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 10129e7b2b25Sstefano_zampini } else { 10139566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->csf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 10149566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->csf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 10159e7b2b25Sstefano_zampini } 10169566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(iscol[i], &idxs)); 10175e3038f0Sstefano_zampini stl += lc[i]; 10185e3038f0Sstefano_zampini } 10199566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(comm, 1, stl, l2gidxs, PETSC_OWN_POINTER, &cl2g)); 10205e3038f0Sstefano_zampini 10215e3038f0Sstefano_zampini /* Create MATIS */ 10229566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &B)); 10239566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N)); 10249566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(A, &rbs, &cbs)); 10259566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(B, rbs, cbs)); 10269566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATIS)); 10279566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(B, MATNEST)); 10284f58015eSStefano Zampini PetscCall(MatISSetAllowRepeated(B, PetscBool3ToBool(allow_repeated))); 10298546b261SStefano Zampini { /* hack : avoid setup of scatters */ 1030f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)B->data; 10318546b261SStefano Zampini matis->islocalref = PETSC_TRUE; 10328546b261SStefano Zampini } 10339566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B, rl2g, cl2g)); 10349566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 10359566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 10369566063dSJacob Faibussowitsch PetscCall(MatCreateNest(PETSC_COMM_SELF, nr, islrow, nc, islcol, snest, &lA)); 10379566063dSJacob Faibussowitsch PetscCall(MatNestSetVecType(lA, VECNEST)); 10389e7b2b25Sstefano_zampini for (i = 0; i < nr * nc; i++) { 103948a46eb9SPierre Jolivet if (istrans[i]) PetscCall(MatDestroy(&snest[i])); 10409e7b2b25Sstefano_zampini } 10419566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B, lA)); 10429566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lA)); 10438546b261SStefano Zampini { /* hack : setup of scatters done here */ 1044f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)B->data; 10458546b261SStefano Zampini 10468546b261SStefano Zampini matis->islocalref = PETSC_FALSE; 10479566063dSJacob Faibussowitsch PetscCall(MatISSetUpScatters_Private(B)); 10488546b261SStefano Zampini } 10499566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 10509566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 10515e3038f0Sstefano_zampini if (reuse == MAT_INPLACE_MATRIX) { 10529566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &B)); 10535e3038f0Sstefano_zampini } else { 10545e3038f0Sstefano_zampini *newmat = B; 10555e3038f0Sstefano_zampini } 10565e3038f0Sstefano_zampini } else { 10575e3038f0Sstefano_zampini if (lreuse) { 10589566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*newmat, &lA)); 10595e3038f0Sstefano_zampini for (i = 0; i < nr; i++) { 10605e3038f0Sstefano_zampini for (j = 0; j < nc; j++) { 10615e3038f0Sstefano_zampini if (snest[i * nc + j]) { 10629566063dSJacob Faibussowitsch PetscCall(MatNestSetSubMat(lA, i, j, snest[i * nc + j])); 106348a46eb9SPierre Jolivet if (istrans[i * nc + j]) PetscCall(MatDestroy(&snest[i * nc + j])); 10645e3038f0Sstefano_zampini } 10655e3038f0Sstefano_zampini } 10665e3038f0Sstefano_zampini } 10675e3038f0Sstefano_zampini } else { 10685b003df0Sstefano_zampini PetscInt stl; 10695b003df0Sstefano_zampini for (i = 0, stl = 0; i < nr; i++) { 10709566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, lr[i], stl, 1, &islrow[i])); 10715b003df0Sstefano_zampini stl += lr[i]; 10725e3038f0Sstefano_zampini } 10735b003df0Sstefano_zampini for (i = 0, stl = 0; i < nc; i++) { 10749566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, lc[i], stl, 1, &islcol[i])); 10755b003df0Sstefano_zampini stl += lc[i]; 10765e3038f0Sstefano_zampini } 10779566063dSJacob Faibussowitsch PetscCall(MatCreateNest(PETSC_COMM_SELF, nr, islrow, nc, islcol, snest, &lA)); 1078ab4d48faSStefano Zampini for (i = 0; i < nr * nc; i++) { 107948a46eb9SPierre Jolivet if (istrans[i]) PetscCall(MatDestroy(&snest[i])); 1080ab4d48faSStefano Zampini } 10819566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*newmat, lA)); 10829566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lA)); 10835e3038f0Sstefano_zampini } 10849566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*newmat, MAT_FINAL_ASSEMBLY)); 10859566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*newmat, MAT_FINAL_ASSEMBLY)); 10865e3038f0Sstefano_zampini } 10875e3038f0Sstefano_zampini 10885b003df0Sstefano_zampini /* Create local matrix in MATNEST format */ 10895b003df0Sstefano_zampini convert = PETSC_FALSE; 10904f58015eSStefano Zampini PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)A)->prefix, "-mat_is_convert_local_nest", &convert, NULL)); 10915b003df0Sstefano_zampini if (convert) { 10925b003df0Sstefano_zampini Mat M; 10935b003df0Sstefano_zampini MatISLocalFields lf; 10945b003df0Sstefano_zampini 10959566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*newmat, &lA)); 10969566063dSJacob Faibussowitsch PetscCall(MatConvert(lA, MATAIJ, MAT_INITIAL_MATRIX, &M)); 10979566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*newmat, M)); 10989566063dSJacob Faibussowitsch PetscCall(MatDestroy(&M)); 10995b003df0Sstefano_zampini 11005b003df0Sstefano_zampini /* attach local fields to the matrix */ 11019566063dSJacob Faibussowitsch PetscCall(PetscNew(&lf)); 11029566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nr, &lf->rf, nc, &lf->cf)); 11035b003df0Sstefano_zampini for (i = 0; i < nr; i++) { 11045b003df0Sstefano_zampini PetscInt n, st; 11055b003df0Sstefano_zampini 11069566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(islrow[i], &n)); 11079566063dSJacob Faibussowitsch PetscCall(ISStrideGetInfo(islrow[i], &st, NULL)); 11089566063dSJacob Faibussowitsch PetscCall(ISCreateStride(comm, n, st, 1, &lf->rf[i])); 11095b003df0Sstefano_zampini } 11105b003df0Sstefano_zampini for (i = 0; i < nc; i++) { 11115b003df0Sstefano_zampini PetscInt n, st; 11125b003df0Sstefano_zampini 11139566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(islcol[i], &n)); 11149566063dSJacob Faibussowitsch PetscCall(ISStrideGetInfo(islcol[i], &st, NULL)); 11159566063dSJacob Faibussowitsch PetscCall(ISCreateStride(comm, n, st, 1, &lf->cf[i])); 11165b003df0Sstefano_zampini } 11175b003df0Sstefano_zampini lf->nr = nr; 11185b003df0Sstefano_zampini lf->nc = nc; 111903e76207SPierre Jolivet PetscCall(PetscObjectContainerCompose((PetscObject)*newmat, "_convert_nest_lfields", lf, MatISContainerDestroyFields_Private)); 11205b003df0Sstefano_zampini } 11215b003df0Sstefano_zampini 11225e3038f0Sstefano_zampini /* Free workspace */ 112348a46eb9SPierre Jolivet for (i = 0; i < nr; i++) PetscCall(ISDestroy(&islrow[i])); 112448a46eb9SPierre Jolivet for (i = 0; i < nc; i++) PetscCall(ISDestroy(&islcol[i])); 11259566063dSJacob Faibussowitsch PetscCall(PetscFree6(isrow, iscol, islrow, islcol, snest, istrans)); 11269566063dSJacob Faibussowitsch PetscCall(PetscFree2(lr, lc)); 11273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11285e3038f0Sstefano_zampini } 11295e3038f0Sstefano_zampini 1130d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r) 1131d71ae5a4SJacob Faibussowitsch { 1132ad219c80Sstefano_zampini Mat_IS *matis = (Mat_IS *)A->data; 1133ad219c80Sstefano_zampini Vec ll, rr; 1134ad219c80Sstefano_zampini const PetscScalar *Y, *X; 1135ad219c80Sstefano_zampini PetscScalar *x, *y; 1136ad219c80Sstefano_zampini 1137ad219c80Sstefano_zampini PetscFunctionBegin; 1138ad219c80Sstefano_zampini if (l) { 1139ad219c80Sstefano_zampini ll = matis->y; 11409566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(l, &Y)); 11419566063dSJacob Faibussowitsch PetscCall(VecGetArray(ll, &y)); 11429566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_SCALAR, Y, y, MPI_REPLACE)); 1143ad219c80Sstefano_zampini } else { 1144ad219c80Sstefano_zampini ll = NULL; 1145ad219c80Sstefano_zampini } 1146ad219c80Sstefano_zampini if (r) { 1147ad219c80Sstefano_zampini rr = matis->x; 11489566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(r, &X)); 11499566063dSJacob Faibussowitsch PetscCall(VecGetArray(rr, &x)); 11509566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->csf, MPIU_SCALAR, X, x, MPI_REPLACE)); 1151ad219c80Sstefano_zampini } else { 1152ad219c80Sstefano_zampini rr = NULL; 1153ad219c80Sstefano_zampini } 1154ad219c80Sstefano_zampini if (ll) { 11559566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_SCALAR, Y, y, MPI_REPLACE)); 11569566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(l, &Y)); 11579566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(ll, &y)); 1158ad219c80Sstefano_zampini } 1159ad219c80Sstefano_zampini if (rr) { 11609566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->csf, MPIU_SCALAR, X, x, MPI_REPLACE)); 11619566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(r, &X)); 11629566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(rr, &x)); 1163ad219c80Sstefano_zampini } 11649566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(matis->A, ll, rr)); 11653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1166ad219c80Sstefano_zampini } 1167ad219c80Sstefano_zampini 1168d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetInfo_IS(Mat A, MatInfoType flag, MatInfo *ginfo) 1169d71ae5a4SJacob Faibussowitsch { 11707fa8f2d3SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 11717fa8f2d3SStefano Zampini MatInfo info; 11723966268fSBarry Smith PetscLogDouble isend[6], irecv[6]; 11737fa8f2d3SStefano Zampini PetscInt bs; 11747fa8f2d3SStefano Zampini 11757fa8f2d3SStefano Zampini PetscFunctionBegin; 11769566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 1177a2ccb5f9Sstefano_zampini if (matis->A->ops->getinfo) { 11789566063dSJacob Faibussowitsch PetscCall(MatGetInfo(matis->A, MAT_LOCAL, &info)); 11797fa8f2d3SStefano Zampini isend[0] = info.nz_used; 11807fa8f2d3SStefano Zampini isend[1] = info.nz_allocated; 11817fa8f2d3SStefano Zampini isend[2] = info.nz_unneeded; 11827fa8f2d3SStefano Zampini isend[3] = info.memory; 11837fa8f2d3SStefano Zampini isend[4] = info.mallocs; 1184a2ccb5f9Sstefano_zampini } else { 1185a2ccb5f9Sstefano_zampini isend[0] = 0.; 1186a2ccb5f9Sstefano_zampini isend[1] = 0.; 1187a2ccb5f9Sstefano_zampini isend[2] = 0.; 1188a2ccb5f9Sstefano_zampini isend[3] = 0.; 1189a2ccb5f9Sstefano_zampini isend[4] = 0.; 1190a2ccb5f9Sstefano_zampini } 1191314ce898Sstefano_zampini isend[5] = matis->A->num_ass; 11927fa8f2d3SStefano Zampini if (flag == MAT_LOCAL) { 11937fa8f2d3SStefano Zampini ginfo->nz_used = isend[0]; 11947fa8f2d3SStefano Zampini ginfo->nz_allocated = isend[1]; 11957fa8f2d3SStefano Zampini ginfo->nz_unneeded = isend[2]; 11967fa8f2d3SStefano Zampini ginfo->memory = isend[3]; 11977fa8f2d3SStefano Zampini ginfo->mallocs = isend[4]; 1198314ce898Sstefano_zampini ginfo->assemblies = isend[5]; 11997fa8f2d3SStefano Zampini } else if (flag == MAT_GLOBAL_MAX) { 1200462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(isend, irecv, 6, MPIU_PETSCLOGDOUBLE, MPI_MAX, PetscObjectComm((PetscObject)A))); 12017fa8f2d3SStefano Zampini 12027fa8f2d3SStefano Zampini ginfo->nz_used = irecv[0]; 12037fa8f2d3SStefano Zampini ginfo->nz_allocated = irecv[1]; 12047fa8f2d3SStefano Zampini ginfo->nz_unneeded = irecv[2]; 12057fa8f2d3SStefano Zampini ginfo->memory = irecv[3]; 12067fa8f2d3SStefano Zampini ginfo->mallocs = irecv[4]; 1207314ce898Sstefano_zampini ginfo->assemblies = irecv[5]; 12087fa8f2d3SStefano Zampini } else if (flag == MAT_GLOBAL_SUM) { 1209462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(isend, irecv, 5, MPIU_PETSCLOGDOUBLE, MPI_SUM, PetscObjectComm((PetscObject)A))); 12107fa8f2d3SStefano Zampini 12117fa8f2d3SStefano Zampini ginfo->nz_used = irecv[0]; 12127fa8f2d3SStefano Zampini ginfo->nz_allocated = irecv[1]; 12137fa8f2d3SStefano Zampini ginfo->nz_unneeded = irecv[2]; 12147fa8f2d3SStefano Zampini ginfo->memory = irecv[3]; 12157fa8f2d3SStefano Zampini ginfo->mallocs = irecv[4]; 12167fa8f2d3SStefano Zampini ginfo->assemblies = A->num_ass; 12177fa8f2d3SStefano Zampini } 12187fa8f2d3SStefano Zampini ginfo->block_size = bs; 12197fa8f2d3SStefano Zampini ginfo->fill_ratio_given = 0; 12207fa8f2d3SStefano Zampini ginfo->fill_ratio_needed = 0; 12217fa8f2d3SStefano Zampini ginfo->factor_mallocs = 0; 12223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12235e3038f0Sstefano_zampini } 12245e3038f0Sstefano_zampini 1225d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatTranspose_IS(Mat A, MatReuse reuse, Mat *B) 1226d71ae5a4SJacob Faibussowitsch { 1227d7f69cd0SStefano Zampini Mat C, lC, lA; 1228d7f69cd0SStefano Zampini 1229d7f69cd0SStefano Zampini PetscFunctionBegin; 12307fb60732SBarry Smith if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *B)); 1231cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) { 1232cf37664fSBarry Smith ISLocalToGlobalMapping rl2g, cl2g; 12334f58015eSStefano Zampini PetscBool allow_repeated; 12344f58015eSStefano Zampini 12359566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 12369566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, A->cmap->n, A->rmap->n, A->cmap->N, A->rmap->N)); 12379566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(C, PetscAbs(A->cmap->bs), PetscAbs(A->rmap->bs))); 12389566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATIS)); 12394f58015eSStefano Zampini PetscCall(MatISGetAllowRepeated(A, &allow_repeated)); 12404f58015eSStefano Zampini PetscCall(MatISSetAllowRepeated(C, allow_repeated)); 12419566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(A, &rl2g, &cl2g)); 12429566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(C, cl2g, rl2g)); 1243e432b41dSStefano Zampini } else C = *B; 1244d7f69cd0SStefano Zampini 1245d7f69cd0SStefano Zampini /* perform local transposition */ 12469566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A, &lA)); 12479566063dSJacob Faibussowitsch PetscCall(MatTranspose(lA, MAT_INITIAL_MATRIX, &lC)); 12489566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(lC, lA->cmap->mapping, lA->rmap->mapping)); 12499566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(C, lC)); 12509566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lC)); 1251d7f69cd0SStefano Zampini 1252cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) { 1253d7f69cd0SStefano Zampini *B = C; 1254d7f69cd0SStefano Zampini } else { 12559566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(A, &C)); 1256d7f69cd0SStefano Zampini } 12579566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY)); 12589566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY)); 12593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1260d7f69cd0SStefano Zampini } 1261d7f69cd0SStefano Zampini 1262d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDiagonalSet_IS(Mat A, Vec D, InsertMode insmode) 1263d71ae5a4SJacob Faibussowitsch { 12643fd1c9e7SStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 12653fd1c9e7SStefano Zampini 12663fd1c9e7SStefano Zampini PetscFunctionBegin; 12674f58015eSStefano Zampini PetscCheck(!is->allow_repeated || insmode == ADD_VALUES, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "INSERT_VALUES with repeated entries not supported"); 12684b89b9cdSStefano Zampini if (D) { /* MatShift_IS pass D = NULL */ 12699566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, D, is->y, INSERT_VALUES, SCATTER_FORWARD)); 12709566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, D, is->y, INSERT_VALUES, SCATTER_FORWARD)); 12713fd1c9e7SStefano Zampini } 12729566063dSJacob Faibussowitsch PetscCall(VecPointwiseDivide(is->y, is->y, is->counter)); 12739566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(is->A, is->y, insmode)); 12743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12753fd1c9e7SStefano Zampini } 12763fd1c9e7SStefano Zampini 1277d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatShift_IS(Mat A, PetscScalar a) 1278d71ae5a4SJacob Faibussowitsch { 12794b89b9cdSStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 12803fd1c9e7SStefano Zampini 12813fd1c9e7SStefano Zampini PetscFunctionBegin; 12829566063dSJacob Faibussowitsch PetscCall(VecSet(is->y, a)); 12839566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet_IS(A, NULL, ADD_VALUES)); 12843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12853fd1c9e7SStefano Zampini } 12863fd1c9e7SStefano Zampini 1287d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) 1288d71ae5a4SJacob Faibussowitsch { 1289f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION], cols_l[MATIS_MAX_ENTRIES_INSERTION]; 1290f26d0771SStefano Zampini 1291f26d0771SStefano Zampini PetscFunctionBegin; 1292aed4548fSBarry Smith PetscCheck(m <= MATIS_MAX_ENTRIES_INSERTION && n <= MATIS_MAX_ENTRIES_INSERTION, PETSC_COMM_SELF, PETSC_ERR_SUP, "Number of row/column indices must be <= %d: they are %" PetscInt_FMT " %" PetscInt_FMT, MATIS_MAX_ENTRIES_INSERTION, m, n); 12939566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(A->rmap->mapping, m, rows, rows_l)); 12949566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(A->cmap->mapping, n, cols, cols_l)); 12959566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal_IS(A, m, rows_l, n, cols_l, values, addv)); 12963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1297f26d0771SStefano Zampini } 1298f26d0771SStefano Zampini 1299d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) 1300d71ae5a4SJacob Faibussowitsch { 1301f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION], cols_l[MATIS_MAX_ENTRIES_INSERTION]; 1302f26d0771SStefano Zampini 1303f26d0771SStefano Zampini PetscFunctionBegin; 1304aed4548fSBarry Smith PetscCheck(m <= MATIS_MAX_ENTRIES_INSERTION && n <= MATIS_MAX_ENTRIES_INSERTION, PETSC_COMM_SELF, PETSC_ERR_SUP, "Number of row/column block indices must be <= %d: they are %" PetscInt_FMT " %" PetscInt_FMT, MATIS_MAX_ENTRIES_INSERTION, m, n); 13059566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(A->rmap->mapping, m, rows, rows_l)); 13069566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(A->cmap->mapping, n, cols, cols_l)); 13079566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlockedLocal_IS(A, m, rows_l, n, cols_l, values, addv)); 13083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1309f26d0771SStefano Zampini } 1310f26d0771SStefano Zampini 1311d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrix_IS(Mat mat, IS irow, IS icol, MatReuse scall, Mat *newmat) 1312d71ae5a4SJacob Faibussowitsch { 1313a8116848SStefano Zampini Mat locmat, newlocmat; 1314a8116848SStefano Zampini Mat_IS *newmatis; 1315a8116848SStefano Zampini const PetscInt *idxs; 1316a8116848SStefano Zampini PetscInt i, m, n; 1317a8116848SStefano Zampini 1318a8116848SStefano Zampini PetscFunctionBegin; 1319a8116848SStefano Zampini if (scall == MAT_REUSE_MATRIX) { 1320a8116848SStefano Zampini PetscBool ismatis; 1321a8116848SStefano Zampini 13229566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)*newmat, MATIS, &ismatis)); 132328b400f6SJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_ARG_WRONG, "Cannot reuse matrix! Not of MATIS type"); 1324a8116848SStefano Zampini newmatis = (Mat_IS *)(*newmat)->data; 132528b400f6SJacob Faibussowitsch PetscCheck(newmatis->getsub_ris, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_ARG_WRONG, "Cannot reuse matrix! Misses local row IS"); 132628b400f6SJacob Faibussowitsch PetscCheck(newmatis->getsub_cis, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_ARG_WRONG, "Cannot reuse matrix! Misses local col IS"); 1327a8116848SStefano Zampini } 1328a8116848SStefano Zampini /* irow and icol may not have duplicate entries */ 132976bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 133076bd3646SJed Brown Vec rtest, ltest; 133176bd3646SJed Brown const PetscScalar *array; 133276bd3646SJed Brown 13339566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(mat, <est, &rtest)); 13349566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(irow, &n)); 13359566063dSJacob Faibussowitsch PetscCall(ISGetIndices(irow, &idxs)); 133648a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(VecSetValue(rtest, idxs[i], 1.0, ADD_VALUES)); 13379566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(rtest)); 13389566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(rtest)); 13399566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(rtest, &n)); 13409566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(rtest, &m, NULL)); 13419566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(rtest, &array)); 1342aed4548fSBarry 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])); 13439566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(rtest, &array)); 13449566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(irow, &idxs)); 13459566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(icol, &n)); 13469566063dSJacob Faibussowitsch PetscCall(ISGetIndices(icol, &idxs)); 134748a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(VecSetValue(ltest, idxs[i], 1.0, ADD_VALUES)); 13489566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(ltest)); 13499566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(ltest)); 13509566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(ltest, &n)); 13519566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(ltest, &m, NULL)); 13529566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(ltest, &array)); 1353aed4548fSBarry 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])); 13549566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(ltest, &array)); 13559566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(icol, &idxs)); 13569566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rtest)); 13579566063dSJacob Faibussowitsch PetscCall(VecDestroy(<est)); 135876bd3646SJed Brown } 1359a8116848SStefano Zampini if (scall == MAT_INITIAL_MATRIX) { 1360a8116848SStefano Zampini Mat_IS *matis = (Mat_IS *)mat->data; 1361a8116848SStefano Zampini ISLocalToGlobalMapping rl2g; 1362a8116848SStefano Zampini IS is; 1363a8116848SStefano Zampini PetscInt *lidxs, *lgidxs, *newgidxs; 1364306cf5c7SStefano Zampini PetscInt ll, newloc, irbs, icbs, arbs, acbs, rbs, cbs; 136594342113SStefano Zampini PetscBool cong; 1366a8116848SStefano Zampini MPI_Comm comm; 1367a8116848SStefano Zampini 13689566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 13699566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(mat, &arbs, &acbs)); 13709566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(irow, &irbs)); 13719566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(icol, &icbs)); 1372306cf5c7SStefano Zampini rbs = arbs == irbs ? irbs : 1; 1373306cf5c7SStefano Zampini cbs = acbs == icbs ? icbs : 1; 13749566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(irow, &m)); 13759566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(icol, &n)); 13769566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, newmat)); 13779566063dSJacob Faibussowitsch PetscCall(MatSetType(*newmat, MATIS)); 13784f58015eSStefano Zampini PetscCall(MatISSetAllowRepeated(*newmat, matis->allow_repeated)); 13799566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*newmat, m, n, PETSC_DECIDE, PETSC_DECIDE)); 13809566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(*newmat, rbs, cbs)); 1381a8116848SStefano Zampini /* communicate irow to their owners in the layout */ 13829566063dSJacob Faibussowitsch PetscCall(ISGetIndices(irow, &idxs)); 13839566063dSJacob Faibussowitsch PetscCall(PetscLayoutMapLocal(mat->rmap, m, idxs, &ll, &lidxs, &lgidxs)); 13849566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(irow, &idxs)); 13859566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata, matis->sf->nroots)); 1386a8116848SStefano Zampini for (i = 0; i < ll; i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i] + 1; 13879566063dSJacob Faibussowitsch PetscCall(PetscFree(lidxs)); 13889566063dSJacob Faibussowitsch PetscCall(PetscFree(lgidxs)); 13899566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 13909566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 13919371c9d4SSatish Balay for (i = 0, newloc = 0; i < matis->sf->nleaves; i++) 13929371c9d4SSatish Balay if (matis->sf_leafdata[i]) newloc++; 13939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newloc, &newgidxs)); 13949566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newloc, &lidxs)); 13953d996552SStefano Zampini for (i = 0, newloc = 0; i < matis->sf->nleaves; i++) 1396a8116848SStefano Zampini if (matis->sf_leafdata[i]) { 1397a8116848SStefano Zampini lidxs[newloc] = i; 1398a8116848SStefano Zampini newgidxs[newloc++] = matis->sf_leafdata[i] - 1; 1399a8116848SStefano Zampini } 14009566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, newloc, newgidxs, PETSC_OWN_POINTER, &is)); 14019566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g)); 14029566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetBlockSize(rl2g, rbs)); 14039566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 1404a8116848SStefano Zampini /* local is to extract local submatrix */ 1405a8116848SStefano Zampini newmatis = (Mat_IS *)(*newmat)->data; 14069566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, newloc, lidxs, PETSC_OWN_POINTER, &newmatis->getsub_ris)); 14079566063dSJacob Faibussowitsch PetscCall(MatHasCongruentLayouts(mat, &cong)); 140894342113SStefano Zampini if (cong && irow == icol && matis->csf == matis->sf) { 14099566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*newmat, rl2g, rl2g)); 14109566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)newmatis->getsub_ris)); 1411a8116848SStefano Zampini newmatis->getsub_cis = newmatis->getsub_ris; 1412a8116848SStefano Zampini } else { 1413a8116848SStefano Zampini ISLocalToGlobalMapping cl2g; 1414a8116848SStefano Zampini 1415a8116848SStefano Zampini /* communicate icol to their owners in the layout */ 14169566063dSJacob Faibussowitsch PetscCall(ISGetIndices(icol, &idxs)); 14179566063dSJacob Faibussowitsch PetscCall(PetscLayoutMapLocal(mat->cmap, n, idxs, &ll, &lidxs, &lgidxs)); 14189566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(icol, &idxs)); 14199566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->csf_rootdata, matis->csf->nroots)); 1420a8116848SStefano Zampini for (i = 0; i < ll; i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i] + 1; 14219566063dSJacob Faibussowitsch PetscCall(PetscFree(lidxs)); 14229566063dSJacob Faibussowitsch PetscCall(PetscFree(lgidxs)); 14239566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->csf, MPIU_INT, matis->csf_rootdata, matis->csf_leafdata, MPI_REPLACE)); 14249566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->csf, MPIU_INT, matis->csf_rootdata, matis->csf_leafdata, MPI_REPLACE)); 14259371c9d4SSatish Balay for (i = 0, newloc = 0; i < matis->csf->nleaves; i++) 14269371c9d4SSatish Balay if (matis->csf_leafdata[i]) newloc++; 14279566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newloc, &newgidxs)); 14289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newloc, &lidxs)); 14293d996552SStefano Zampini for (i = 0, newloc = 0; i < matis->csf->nleaves; i++) 1430a8116848SStefano Zampini if (matis->csf_leafdata[i]) { 1431a8116848SStefano Zampini lidxs[newloc] = i; 1432a8116848SStefano Zampini newgidxs[newloc++] = matis->csf_leafdata[i] - 1; 1433a8116848SStefano Zampini } 14349566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, newloc, newgidxs, PETSC_OWN_POINTER, &is)); 14359566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g)); 14369566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetBlockSize(cl2g, cbs)); 14379566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 1438a8116848SStefano Zampini /* local is to extract local submatrix */ 14399566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, newloc, lidxs, PETSC_OWN_POINTER, &newmatis->getsub_cis)); 14409566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*newmat, rl2g, cl2g)); 14419566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 1442a8116848SStefano Zampini } 14439566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 1444a8116848SStefano Zampini } else { 14459566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*newmat, &newlocmat)); 1446a8116848SStefano Zampini } 14479566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(mat, &locmat)); 1448a8116848SStefano Zampini newmatis = (Mat_IS *)(*newmat)->data; 14499566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(locmat, newmatis->getsub_ris, newmatis->getsub_cis, scall, &newlocmat)); 1450a8116848SStefano Zampini if (scall == MAT_INITIAL_MATRIX) { 14519566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*newmat, newlocmat)); 14529566063dSJacob Faibussowitsch PetscCall(MatDestroy(&newlocmat)); 1453a8116848SStefano Zampini } 14549566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*newmat, MAT_FINAL_ASSEMBLY)); 14559566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*newmat, MAT_FINAL_ASSEMBLY)); 14563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1457a8116848SStefano Zampini } 1458a8116848SStefano Zampini 1459d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCopy_IS(Mat A, Mat B, MatStructure str) 1460d71ae5a4SJacob Faibussowitsch { 14612b404112SStefano Zampini Mat_IS *a = (Mat_IS *)A->data, *b; 14622b404112SStefano Zampini PetscBool ismatis; 14632b404112SStefano Zampini 14642b404112SStefano Zampini PetscFunctionBegin; 14659566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)B, MATIS, &ismatis)); 146628b400f6SJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Need to be implemented"); 14672b404112SStefano Zampini b = (Mat_IS *)B->data; 14689566063dSJacob Faibussowitsch PetscCall(MatCopy(a->A, b->A, str)); 14699566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)B)); 14703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14712b404112SStefano Zampini } 14722b404112SStefano Zampini 1473d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_IS(Mat A, PetscBool *missing, PetscInt *d) 1474d71ae5a4SJacob Faibussowitsch { 1475527b2640SStefano Zampini Vec v; 1476527b2640SStefano Zampini const PetscScalar *array; 1477527b2640SStefano Zampini PetscInt i, n; 14786bd84002SStefano Zampini 14796bd84002SStefano Zampini PetscFunctionBegin; 1480527b2640SStefano Zampini *missing = PETSC_FALSE; 14819566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, NULL, &v)); 14829566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(A, v)); 14839566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 14849566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &array)); 14859371c9d4SSatish Balay for (i = 0; i < n; i++) 14869371c9d4SSatish Balay if (array[i] == 0.) break; 14879566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &array)); 14889566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 1489527b2640SStefano Zampini if (i != n) *missing = PETSC_TRUE; 1490527b2640SStefano Zampini if (d) { 1491527b2640SStefano Zampini *d = -1; 1492527b2640SStefano Zampini if (*missing) { 1493527b2640SStefano Zampini PetscInt rstart; 14949566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rstart, NULL)); 1495527b2640SStefano Zampini *d = i + rstart; 1496527b2640SStefano Zampini } 1497527b2640SStefano Zampini } 14983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14996bd84002SStefano Zampini } 15006bd84002SStefano Zampini 1501d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISSetUpSF_IS(Mat B) 1502d71ae5a4SJacob Faibussowitsch { 1503f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)B->data; 150428f4e0baSStefano Zampini const PetscInt *gidxs; 15054f2d7cafSStefano Zampini PetscInt nleaves; 150628f4e0baSStefano Zampini 150728f4e0baSStefano Zampini PetscFunctionBegin; 15083ba16761SJacob Faibussowitsch if (matis->sf) PetscFunctionReturn(PETSC_SUCCESS); 15099566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)B), &matis->sf)); 15109566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->rmapping, &gidxs)); 15119566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->rmapping, &nleaves)); 15129566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(matis->sf, B->rmap, nleaves, NULL, PETSC_OWN_POINTER, gidxs)); 15139566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->rmapping, &gidxs)); 15149566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(matis->sf->nroots, &matis->sf_rootdata, matis->sf->nleaves, &matis->sf_leafdata)); 1515e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { /* setup SF for columns */ 15169566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->cmapping, &nleaves)); 15179566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)B), &matis->csf)); 15189566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->cmapping, &gidxs)); 15199566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(matis->csf, B->cmap, nleaves, NULL, PETSC_OWN_POINTER, gidxs)); 15209566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->cmapping, &gidxs)); 15219566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(matis->csf->nroots, &matis->csf_rootdata, matis->csf->nleaves, &matis->csf_leafdata)); 1522a8116848SStefano Zampini } else { 1523a8116848SStefano Zampini matis->csf = matis->sf; 1524a8116848SStefano Zampini matis->csf_leafdata = matis->sf_leafdata; 1525a8116848SStefano Zampini matis->csf_rootdata = matis->sf_rootdata; 1526a8116848SStefano Zampini } 15273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 152828f4e0baSStefano Zampini } 15292e1947a5SStefano Zampini 1530eb82efa4SStefano Zampini /*@ 15314f58015eSStefano Zampini MatISGetAllowRepeated - Get the flag to allow repeated entries in the local to global map 15324f58015eSStefano Zampini 15334f58015eSStefano Zampini Not Collective 15344f58015eSStefano Zampini 15354f58015eSStefano Zampini Input Parameter: 15364f58015eSStefano Zampini . A - the matrix 15374f58015eSStefano Zampini 15384f58015eSStefano Zampini Output Parameter: 15394f58015eSStefano Zampini . flg - the boolean flag 15404f58015eSStefano Zampini 15414f58015eSStefano Zampini Level: intermediate 15424f58015eSStefano Zampini 15434f58015eSStefano Zampini .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateIS()`, `MatSetLocalToGlobalMapping()`, `MatISSetAllowRepeated()` 15444f58015eSStefano Zampini @*/ 15454f58015eSStefano Zampini PetscErrorCode MatISGetAllowRepeated(Mat A, PetscBool *flg) 15464f58015eSStefano Zampini { 15474f58015eSStefano Zampini PetscBool ismatis; 15484f58015eSStefano Zampini 15494f58015eSStefano Zampini PetscFunctionBegin; 15504f58015eSStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 15514f58015eSStefano Zampini PetscAssertPointer(flg, 2); 15524f58015eSStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)A, MATIS, &ismatis)); 15534f58015eSStefano Zampini PetscCheck(ismatis, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)A)->type_name); 15544f58015eSStefano Zampini *flg = ((Mat_IS *)A->data)->allow_repeated; 15554f58015eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 15564f58015eSStefano Zampini } 15574f58015eSStefano Zampini 15584f58015eSStefano Zampini /*@ 15594f58015eSStefano Zampini MatISSetAllowRepeated - Set the flag to allow repeated entries in the local to global map 15604f58015eSStefano Zampini 15614f58015eSStefano Zampini Logically Collective 15624f58015eSStefano Zampini 15634f58015eSStefano Zampini Input Parameters: 15644f58015eSStefano Zampini + A - the matrix 15654f58015eSStefano Zampini - flg - the boolean flag 15664f58015eSStefano Zampini 15674f58015eSStefano Zampini Level: intermediate 15684f58015eSStefano Zampini 15694f58015eSStefano Zampini Notes: 15704f58015eSStefano Zampini The default value is `PETSC_FALSE`. 15714f58015eSStefano Zampini When called AFTER calling `MatSetLocalToGlobalMapping()` it will recreate the local matrices 15724f58015eSStefano Zampini if `flg` is different from the previously set value. 15734f58015eSStefano Zampini Specifically, when `flg` is true it will just recreate the local matrices, while if 15744f58015eSStefano Zampini `flg` is false will assemble the local matrices summing up repeated entries. 15754f58015eSStefano Zampini 15764f58015eSStefano Zampini .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateIS()`, `MatSetLocalToGlobalMapping()`, `MatISGetAllowRepeated()` 15774f58015eSStefano Zampini @*/ 15784f58015eSStefano Zampini PetscErrorCode MatISSetAllowRepeated(Mat A, PetscBool flg) 15794f58015eSStefano Zampini { 15804f58015eSStefano Zampini PetscFunctionBegin; 15814f58015eSStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 15824f58015eSStefano Zampini PetscValidType(A, 1); 15834f58015eSStefano Zampini PetscValidLogicalCollectiveBool(A, flg, 2); 15844f58015eSStefano Zampini PetscTryMethod(A, "MatISSetAllowRepeated_C", (Mat, PetscBool), (A, flg)); 15854f58015eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 15864f58015eSStefano Zampini } 15874f58015eSStefano Zampini 15884f58015eSStefano Zampini static PetscErrorCode MatISSetAllowRepeated_IS(Mat A, PetscBool flg) 15894f58015eSStefano Zampini { 15904f58015eSStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 15914f58015eSStefano Zampini Mat lA = NULL; 15924f58015eSStefano Zampini ISLocalToGlobalMapping lrmap, lcmap; 15934f58015eSStefano Zampini 15944f58015eSStefano Zampini PetscFunctionBegin; 15954f58015eSStefano Zampini if (flg == matis->allow_repeated) PetscFunctionReturn(PETSC_SUCCESS); 15964f58015eSStefano Zampini if (!matis->A) { /* matrix has not been preallocated yet */ 15974f58015eSStefano Zampini matis->allow_repeated = flg; 15984f58015eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 15994f58015eSStefano Zampini } 16004f58015eSStefano Zampini PetscCheck(!matis->islocalref, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not implemented for local references"); 16014f58015eSStefano Zampini if (matis->allow_repeated) { /* we will assemble the old local matrix if needed */ 16024f58015eSStefano Zampini lA = matis->A; 16034f58015eSStefano Zampini PetscCall(PetscObjectReference((PetscObject)lA)); 16044f58015eSStefano Zampini } 16054f58015eSStefano Zampini /* In case flg is True, we only recreate the local matrix */ 16064f58015eSStefano Zampini matis->allow_repeated = flg; 16074f58015eSStefano Zampini PetscCall(MatSetLocalToGlobalMapping(A, A->rmap->mapping, A->cmap->mapping)); 16084f58015eSStefano Zampini if (lA) { /* assemble previous local matrix if needed */ 16094f58015eSStefano Zampini Mat nA = matis->A; 16104f58015eSStefano Zampini 16114f58015eSStefano Zampini PetscCall(MatGetLocalToGlobalMapping(nA, &lrmap, &lcmap)); 16124f58015eSStefano Zampini if (!lrmap && !lcmap) { 16134f58015eSStefano Zampini PetscCall(MatISSetLocalMat(A, lA)); 16144f58015eSStefano Zampini } else { 16154f58015eSStefano Zampini Mat P = NULL, R = NULL; 16164f58015eSStefano Zampini MatProductType ptype; 16174f58015eSStefano Zampini 16184f58015eSStefano Zampini if (lrmap == lcmap) { 16194f58015eSStefano Zampini ptype = MATPRODUCT_PtAP; 16204f58015eSStefano Zampini PetscCall(MatCreateFromISLocalToGlobalMapping(lcmap, nA, PETSC_TRUE, PETSC_FALSE, NULL, &P)); 16214f58015eSStefano Zampini PetscCall(MatProductCreate(lA, P, NULL, &nA)); 16224f58015eSStefano Zampini } else { 16234f58015eSStefano Zampini if (lcmap) PetscCall(MatCreateFromISLocalToGlobalMapping(lcmap, nA, PETSC_TRUE, PETSC_FALSE, NULL, &P)); 16244f58015eSStefano Zampini if (lrmap) PetscCall(MatCreateFromISLocalToGlobalMapping(lrmap, nA, PETSC_FALSE, PETSC_TRUE, NULL, &R)); 16254f58015eSStefano Zampini if (R && P) { 16264f58015eSStefano Zampini ptype = MATPRODUCT_ABC; 16274f58015eSStefano Zampini PetscCall(MatProductCreate(R, lA, P, &nA)); 16284f58015eSStefano Zampini } else if (R) { 16294f58015eSStefano Zampini ptype = MATPRODUCT_AB; 16304f58015eSStefano Zampini PetscCall(MatProductCreate(R, lA, NULL, &nA)); 16314f58015eSStefano Zampini } else { 16324f58015eSStefano Zampini ptype = MATPRODUCT_AB; 16334f58015eSStefano Zampini PetscCall(MatProductCreate(lA, P, NULL, &nA)); 16344f58015eSStefano Zampini } 16354f58015eSStefano Zampini } 16364f58015eSStefano Zampini PetscCall(MatProductSetType(nA, ptype)); 16374f58015eSStefano Zampini PetscCall(MatProductSetFromOptions(nA)); 16384f58015eSStefano Zampini PetscCall(MatProductSymbolic(nA)); 16394f58015eSStefano Zampini PetscCall(MatProductNumeric(nA)); 16404f58015eSStefano Zampini PetscCall(MatProductClear(nA)); 16414f58015eSStefano Zampini PetscCall(MatConvert(nA, matis->lmattype, MAT_INPLACE_MATRIX, &nA)); 16424f58015eSStefano Zampini PetscCall(MatISSetLocalMat(A, nA)); 16434f58015eSStefano Zampini PetscCall(MatDestroy(&nA)); 16444f58015eSStefano Zampini PetscCall(MatDestroy(&P)); 16454f58015eSStefano Zampini PetscCall(MatDestroy(&R)); 16464f58015eSStefano Zampini } 16474f58015eSStefano Zampini } 16484f58015eSStefano Zampini PetscCall(MatDestroy(&lA)); 16494f58015eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 16504f58015eSStefano Zampini } 16514f58015eSStefano Zampini 16524f58015eSStefano Zampini /*@ 16532ef1f0ffSBarry Smith MatISStoreL2L - Store local-to-local operators during the Galerkin process of computing `MatPtAP()` 165475d48cdbSStefano Zampini 16554f58015eSStefano Zampini Logically Collective 165675d48cdbSStefano Zampini 165775d48cdbSStefano Zampini Input Parameters: 165875d48cdbSStefano Zampini + A - the matrix 165975d48cdbSStefano Zampini - store - the boolean flag 166075d48cdbSStefano Zampini 166175d48cdbSStefano Zampini Level: advanced 166275d48cdbSStefano Zampini 16631cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateIS()`, `MatISSetPreallocation()`, `MatPtAP()` 166475d48cdbSStefano Zampini @*/ 1665d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISStoreL2L(Mat A, PetscBool store) 1666d71ae5a4SJacob Faibussowitsch { 166775d48cdbSStefano Zampini PetscFunctionBegin; 166875d48cdbSStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 166975d48cdbSStefano Zampini PetscValidType(A, 1); 167075d48cdbSStefano Zampini PetscValidLogicalCollectiveBool(A, store, 2); 1671cac4c232SBarry Smith PetscTryMethod(A, "MatISStoreL2L_C", (Mat, PetscBool), (A, store)); 16723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 167375d48cdbSStefano Zampini } 167475d48cdbSStefano Zampini 1675d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISStoreL2L_IS(Mat A, PetscBool store) 1676d71ae5a4SJacob Faibussowitsch { 1677f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)A->data; 167875d48cdbSStefano Zampini 167975d48cdbSStefano Zampini PetscFunctionBegin; 168075d48cdbSStefano Zampini matis->storel2l = store; 168157508eceSPierre Jolivet if (!store) PetscCall(PetscObjectCompose((PetscObject)A, "_MatIS_PtAP_l2l", NULL)); 16823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 168375d48cdbSStefano Zampini } 168475d48cdbSStefano Zampini 168575d48cdbSStefano Zampini /*@ 1686f03112d0SStefano Zampini MatISFixLocalEmpty - Compress out zero local rows from the local matrices 1687f03112d0SStefano Zampini 16884f58015eSStefano Zampini Logically Collective 1689f03112d0SStefano Zampini 1690f03112d0SStefano Zampini Input Parameters: 1691f03112d0SStefano Zampini + A - the matrix 1692f03112d0SStefano Zampini - fix - the boolean flag 1693f03112d0SStefano Zampini 1694f03112d0SStefano Zampini Level: advanced 1695f03112d0SStefano Zampini 169611a5261eSBarry Smith Note: 16972fe279fdSBarry Smith When `fix` is `PETSC_TRUE`, new local matrices and l2g maps are generated during the final assembly process. 1698f03112d0SStefano Zampini 16991cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatCreate()`, `MatCreateIS()`, `MatISSetPreallocation()`, `MatAssemblyEnd()`, `MAT_FINAL_ASSEMBLY` 1700f03112d0SStefano Zampini @*/ 1701d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISFixLocalEmpty(Mat A, PetscBool fix) 1702d71ae5a4SJacob Faibussowitsch { 1703f03112d0SStefano Zampini PetscFunctionBegin; 1704f03112d0SStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1705f03112d0SStefano Zampini PetscValidType(A, 1); 1706f03112d0SStefano Zampini PetscValidLogicalCollectiveBool(A, fix, 2); 1707cac4c232SBarry Smith PetscTryMethod(A, "MatISFixLocalEmpty_C", (Mat, PetscBool), (A, fix)); 17083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1709f03112d0SStefano Zampini } 1710f03112d0SStefano Zampini 1711d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISFixLocalEmpty_IS(Mat A, PetscBool fix) 1712d71ae5a4SJacob Faibussowitsch { 1713f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)A->data; 1714f03112d0SStefano Zampini 1715f03112d0SStefano Zampini PetscFunctionBegin; 1716f03112d0SStefano Zampini matis->locempty = fix; 17173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1718f03112d0SStefano Zampini } 1719f03112d0SStefano Zampini 1720f03112d0SStefano Zampini /*@ 172111a5261eSBarry Smith MatISSetPreallocation - Preallocates memory for a `MATIS` parallel matrix. 1722a88811baSStefano Zampini 1723d083f849SBarry Smith Collective 1724a88811baSStefano Zampini 1725a88811baSStefano Zampini Input Parameters: 1726a88811baSStefano Zampini + B - the matrix 1727a88811baSStefano Zampini . d_nz - number of nonzeros per row in DIAGONAL portion of local submatrix 1728a88811baSStefano Zampini (same value is used for all local rows) 1729a88811baSStefano Zampini . d_nnz - array containing the number of nonzeros in the various rows of the 1730a88811baSStefano Zampini DIAGONAL portion of the local submatrix (possibly different for each row) 17312ef1f0ffSBarry Smith or `NULL`, if `d_nz` is used to specify the nonzero structure. 17322ef1f0ffSBarry Smith The size of this array is equal to the number of local rows, i.e `m`. 1733a88811baSStefano Zampini For matrices that will be factored, you must leave room for (and set) 1734a88811baSStefano Zampini the diagonal entry even if it is zero. 1735a88811baSStefano Zampini . o_nz - number of nonzeros per row in the OFF-DIAGONAL portion of local 1736a88811baSStefano Zampini submatrix (same value is used for all local rows). 1737a88811baSStefano Zampini - o_nnz - array containing the number of nonzeros in the various rows of the 1738a88811baSStefano Zampini OFF-DIAGONAL portion of the local submatrix (possibly different for 17392ef1f0ffSBarry Smith each row) or `NULL`, if `o_nz` is used to specify the nonzero 1740a88811baSStefano Zampini structure. The size of this array is equal to the number 17412ef1f0ffSBarry Smith of local rows, i.e `m`. 1742a88811baSStefano Zampini 1743a88811baSStefano Zampini If the *_nnz parameter is given then the *_nz parameter is ignored 1744a88811baSStefano Zampini 1745a88811baSStefano Zampini Level: intermediate 1746a88811baSStefano Zampini 174711a5261eSBarry Smith Note: 174811a5261eSBarry Smith This function has the same interface as the `MATMPIAIJ` preallocation routine in order to simplify the transition 174911a5261eSBarry Smith from the asssembled format to the unassembled one. It overestimates the preallocation of `MATIS` local 1750a88811baSStefano Zampini matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects. 1751a88811baSStefano Zampini 17521cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateIS()`, `MatMPIAIJSetPreallocation()`, `MatISGetLocalMat()`, `MATIS` 1753a88811baSStefano Zampini @*/ 1754d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISSetPreallocation(Mat B, PetscInt d_nz, const PetscInt d_nnz[], PetscInt o_nz, const PetscInt o_nnz[]) 1755d71ae5a4SJacob Faibussowitsch { 17562e1947a5SStefano Zampini PetscFunctionBegin; 17572e1947a5SStefano Zampini PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 17582e1947a5SStefano Zampini PetscValidType(B, 1); 1759cac4c232SBarry Smith PetscTryMethod(B, "MatISSetPreallocation_C", (Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]), (B, d_nz, d_nnz, o_nz, o_nnz)); 17603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17612e1947a5SStefano Zampini } 17622e1947a5SStefano Zampini 1763844bd0d7SStefano Zampini /* this is used by DMDA */ 1764d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatISSetPreallocation_IS(Mat B, PetscInt d_nz, const PetscInt d_nnz[], PetscInt o_nz, const PetscInt o_nnz[]) 1765d71ae5a4SJacob Faibussowitsch { 1766f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)B->data; 176728f4e0baSStefano Zampini PetscInt bs, i, nlocalcols; 17682e1947a5SStefano Zampini 17692e1947a5SStefano Zampini PetscFunctionBegin; 17709566063dSJacob Faibussowitsch PetscCall(MatSetUp(B)); 17719371c9d4SSatish Balay if (!d_nnz) 17729371c9d4SSatish Balay for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] = d_nz; 17739371c9d4SSatish Balay else 17749371c9d4SSatish Balay for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] = d_nnz[i]; 17754f2d7cafSStefano Zampini 17769371c9d4SSatish Balay if (!o_nnz) 17779371c9d4SSatish Balay for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] += o_nz; 17789371c9d4SSatish Balay else 17799371c9d4SSatish Balay for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] += o_nnz[i]; 17804f2d7cafSStefano Zampini 17819566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 17829566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, NULL, &nlocalcols)); 17839566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(matis->A, &bs)); 17849566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 17854f2d7cafSStefano Zampini 17864f2d7cafSStefano Zampini for (i = 0; i < matis->sf->nleaves; i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i], nlocalcols); 17879566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(matis->A, 0, matis->sf_leafdata)); 17880f2f62c7SStefano Zampini #if defined(PETSC_HAVE_HYPRE) 17899566063dSJacob Faibussowitsch PetscCall(MatHYPRESetPreallocation(matis->A, 0, matis->sf_leafdata, 0, NULL)); 17900f2f62c7SStefano Zampini #endif 17914f2d7cafSStefano Zampini 1792fc989267SStefano Zampini for (i = 0; i < matis->sf->nleaves / bs; i++) { 1793fc989267SStefano Zampini PetscInt b; 1794fc989267SStefano Zampini 1795fc989267SStefano Zampini matis->sf_leafdata[i] = matis->sf_leafdata[i * bs] / bs; 1796ad540459SPierre Jolivet for (b = 1; b < bs; b++) matis->sf_leafdata[i] = PetscMax(matis->sf_leafdata[i], matis->sf_leafdata[i * bs + b] / bs); 1797fc989267SStefano Zampini } 17989566063dSJacob Faibussowitsch PetscCall(MatSeqBAIJSetPreallocation(matis->A, bs, 0, matis->sf_leafdata)); 17994f2d7cafSStefano Zampini 180000a59248SStefano Zampini nlocalcols /= bs; 180100a59248SStefano Zampini for (i = 0; i < matis->sf->nleaves / bs; i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i], nlocalcols - i); 18029566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(matis->A, bs, 0, matis->sf_leafdata)); 18030f2f62c7SStefano Zampini 18040f2f62c7SStefano Zampini /* for other matrix types */ 18059566063dSJacob Faibussowitsch PetscCall(MatSetUp(matis->A)); 18063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18072e1947a5SStefano Zampini } 1808b4319ba4SBarry Smith 1809d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce) 1810d71ae5a4SJacob Faibussowitsch { 1811f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)A->data; 18123927de2eSStefano Zampini PetscInt *my_dnz, *my_onz, *dnz, *onz, *mat_ranges, *row_ownership; 1813ecf5a873SStefano Zampini const PetscInt *global_indices_r, *global_indices_c; 18143927de2eSStefano Zampini PetscInt i, j, bs, rows, cols; 18153927de2eSStefano Zampini PetscInt lrows, lcols; 18163927de2eSStefano Zampini PetscInt local_rows, local_cols; 1817f03112d0SStefano Zampini PetscMPIInt size; 18183927de2eSStefano Zampini PetscBool isdense, issbaij; 18193927de2eSStefano Zampini 18203927de2eSStefano Zampini PetscFunctionBegin; 18219566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 18229566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &rows, &cols)); 18239566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 18249566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, &local_rows, &local_cols)); 18259566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQDENSE, &isdense)); 18269566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQSBAIJ, &issbaij)); 18279566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->rmapping, &global_indices_r)); 1828e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { 18299566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->cmapping, &global_indices_c)); 18300dfc91b7SStefano Zampini } else global_indices_c = global_indices_r; 1831ecf5a873SStefano Zampini 18329566063dSJacob Faibussowitsch if (issbaij) PetscCall(MatGetRowUpperTriangular(matis->A)); 18333927de2eSStefano Zampini /* 1834ecf5a873SStefano Zampini An SF reduce is needed to sum up properly on shared rows. 18353927de2eSStefano Zampini Note that generally preallocation is not exact, since it overestimates nonzeros 18363927de2eSStefano Zampini */ 18379566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &lrows, &lcols)); 1838d0609cedSBarry Smith MatPreallocateBegin(PetscObjectComm((PetscObject)A), lrows, lcols, dnz, onz); 18393927de2eSStefano Zampini /* All processes need to compute entire row ownership */ 18409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rows, &row_ownership)); 18419566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRanges(A, (const PetscInt **)&mat_ranges)); 1842f03112d0SStefano Zampini for (i = 0; i < size; i++) { 18435f80ce2aSJacob Faibussowitsch for (j = mat_ranges[i]; j < mat_ranges[i + 1]; j++) row_ownership[j] = i; 18443927de2eSStefano Zampini } 18459566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangesColumn(A, (const PetscInt **)&mat_ranges)); 18463927de2eSStefano Zampini 18473927de2eSStefano Zampini /* 18483927de2eSStefano Zampini my_dnz and my_onz contains exact contribution to preallocation from each local mat 18493927de2eSStefano Zampini then, they will be summed up properly. This way, preallocation is always sufficient 18503927de2eSStefano Zampini */ 18519566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(local_rows, &my_dnz, local_rows, &my_onz)); 18523927de2eSStefano Zampini /* preallocation as a MATAIJ */ 18533927de2eSStefano Zampini if (isdense) { /* special case for dense local matrices */ 18543927de2eSStefano Zampini for (i = 0; i < local_rows; i++) { 185512dfadf8SStefano Zampini PetscInt owner = row_ownership[global_indices_r[i]]; 185612dfadf8SStefano Zampini for (j = 0; j < local_cols; j++) { 1857ecf5a873SStefano Zampini PetscInt index_col = global_indices_c[j]; 18583927de2eSStefano Zampini if (index_col > mat_ranges[owner] - 1 && index_col < mat_ranges[owner + 1]) { /* diag block */ 18593927de2eSStefano Zampini my_dnz[i] += 1; 18603927de2eSStefano Zampini } else { /* offdiag block */ 18613927de2eSStefano Zampini my_onz[i] += 1; 18623927de2eSStefano Zampini } 18633927de2eSStefano Zampini } 18643927de2eSStefano Zampini } 1865bb1015c3SStefano Zampini } else if (matis->A->ops->getrowij) { 1866bb1015c3SStefano Zampini const PetscInt *ii, *jj, *jptr; 1867bb1015c3SStefano Zampini PetscBool done; 18689566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(matis->A, 0, PETSC_FALSE, PETSC_FALSE, &local_rows, &ii, &jj, &done)); 1869f4f49eeaSPierre Jolivet PetscCheck(done, PetscObjectComm((PetscObject)matis->A), PETSC_ERR_PLIB, "Error in MatGetRowIJ"); 1870bb1015c3SStefano Zampini jptr = jj; 1871bb1015c3SStefano Zampini for (i = 0; i < local_rows; i++) { 1872bb1015c3SStefano Zampini PetscInt index_row = global_indices_r[i]; 1873bb1015c3SStefano Zampini for (j = 0; j < ii[i + 1] - ii[i]; j++, jptr++) { 1874bb1015c3SStefano Zampini PetscInt owner = row_ownership[index_row]; 1875bb1015c3SStefano Zampini PetscInt index_col = global_indices_c[*jptr]; 1876bb1015c3SStefano Zampini if (index_col > mat_ranges[owner] - 1 && index_col < mat_ranges[owner + 1]) { /* diag block */ 1877bb1015c3SStefano Zampini my_dnz[i] += 1; 1878bb1015c3SStefano Zampini } else { /* offdiag block */ 1879bb1015c3SStefano Zampini my_onz[i] += 1; 1880bb1015c3SStefano Zampini } 1881bb1015c3SStefano Zampini /* same as before, interchanging rows and cols */ 1882bb1015c3SStefano Zampini if (issbaij && index_col != index_row) { 1883bb1015c3SStefano Zampini owner = row_ownership[index_col]; 1884bb1015c3SStefano Zampini if (index_row > mat_ranges[owner] - 1 && index_row < mat_ranges[owner + 1]) { 1885bb1015c3SStefano Zampini my_dnz[*jptr] += 1; 1886bb1015c3SStefano Zampini } else { 1887bb1015c3SStefano Zampini my_onz[*jptr] += 1; 1888bb1015c3SStefano Zampini } 1889bb1015c3SStefano Zampini } 1890bb1015c3SStefano Zampini } 1891bb1015c3SStefano Zampini } 18929566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(matis->A, 0, PETSC_FALSE, PETSC_FALSE, &local_rows, &ii, &jj, &done)); 1893f4f49eeaSPierre Jolivet PetscCheck(done, PetscObjectComm((PetscObject)matis->A), PETSC_ERR_PLIB, "Error in MatRestoreRowIJ"); 1894bb1015c3SStefano Zampini } else { /* loop over rows and use MatGetRow */ 18953927de2eSStefano Zampini for (i = 0; i < local_rows; i++) { 18963927de2eSStefano Zampini const PetscInt *cols; 1897ecf5a873SStefano Zampini PetscInt ncols, index_row = global_indices_r[i]; 18989566063dSJacob Faibussowitsch PetscCall(MatGetRow(matis->A, i, &ncols, &cols, NULL)); 18993927de2eSStefano Zampini for (j = 0; j < ncols; j++) { 19003927de2eSStefano Zampini PetscInt owner = row_ownership[index_row]; 1901ecf5a873SStefano Zampini PetscInt index_col = global_indices_c[cols[j]]; 19023927de2eSStefano Zampini if (index_col > mat_ranges[owner] - 1 && index_col < mat_ranges[owner + 1]) { /* diag block */ 19033927de2eSStefano Zampini my_dnz[i] += 1; 19043927de2eSStefano Zampini } else { /* offdiag block */ 19053927de2eSStefano Zampini my_onz[i] += 1; 19063927de2eSStefano Zampini } 19073927de2eSStefano Zampini /* same as before, interchanging rows and cols */ 1908d9a9e74cSStefano Zampini if (issbaij && index_col != index_row) { 19093927de2eSStefano Zampini owner = row_ownership[index_col]; 19103927de2eSStefano Zampini if (index_row > mat_ranges[owner] - 1 && index_row < mat_ranges[owner + 1]) { 1911d9a9e74cSStefano Zampini my_dnz[cols[j]] += 1; 19123927de2eSStefano Zampini } else { 1913d9a9e74cSStefano Zampini my_onz[cols[j]] += 1; 19143927de2eSStefano Zampini } 19153927de2eSStefano Zampini } 19163927de2eSStefano Zampini } 19179566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(matis->A, i, &ncols, &cols, NULL)); 19183927de2eSStefano Zampini } 19193927de2eSStefano Zampini } 192048a46eb9SPierre Jolivet if (global_indices_c != global_indices_r) PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->cmapping, &global_indices_c)); 19219566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->rmapping, &global_indices_r)); 19229566063dSJacob Faibussowitsch PetscCall(PetscFree(row_ownership)); 1923ecf5a873SStefano Zampini 1924ecf5a873SStefano Zampini /* Reduce my_dnz and my_onz */ 19253927de2eSStefano Zampini if (maxreduce) { 19269566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, my_dnz, dnz, MPI_MAX)); 19279566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, my_onz, onz, MPI_MAX)); 19289566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, my_dnz, dnz, MPI_MAX)); 19299566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, my_onz, onz, MPI_MAX)); 19303927de2eSStefano Zampini } else { 19319566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, my_dnz, dnz, MPI_SUM)); 19329566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, my_onz, onz, MPI_SUM)); 19339566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, my_dnz, dnz, MPI_SUM)); 19349566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, my_onz, onz, MPI_SUM)); 19353927de2eSStefano Zampini } 19369566063dSJacob Faibussowitsch PetscCall(PetscFree2(my_dnz, my_onz)); 19373927de2eSStefano Zampini 19383927de2eSStefano Zampini /* Resize preallocation if overestimated */ 19393927de2eSStefano Zampini for (i = 0; i < lrows; i++) { 19403927de2eSStefano Zampini dnz[i] = PetscMin(dnz[i], lcols); 19413927de2eSStefano Zampini onz[i] = PetscMin(onz[i], cols - lcols); 19423927de2eSStefano Zampini } 19431670daf9Sstefano_zampini 19441670daf9Sstefano_zampini /* Set preallocation */ 19459566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B, A, A)); 19469566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B, 0, dnz)); 19479566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(B, 0, dnz, 0, onz)); 194853b44cf5SStefano Zampini for (i = 0; i < lrows; i += bs) { 194953b44cf5SStefano Zampini PetscInt b, d = dnz[i], o = onz[i]; 195053b44cf5SStefano Zampini 195153b44cf5SStefano Zampini for (b = 1; b < bs; b++) { 195253b44cf5SStefano Zampini d = PetscMax(d, dnz[i + b]); 195353b44cf5SStefano Zampini o = PetscMax(o, onz[i + b]); 195453b44cf5SStefano Zampini } 195553b44cf5SStefano Zampini dnz[i / bs] = PetscMin(d / bs + d % bs, lcols / bs); 195653b44cf5SStefano Zampini onz[i / bs] = PetscMin(o / bs + o % bs, (cols - lcols) / bs); 19573927de2eSStefano Zampini } 19589566063dSJacob Faibussowitsch PetscCall(MatSeqBAIJSetPreallocation(B, bs, 0, dnz)); 19599566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJSetPreallocation(B, bs, 0, dnz, 0, onz)); 19609566063dSJacob Faibussowitsch PetscCall(MatMPISBAIJSetPreallocation(B, bs, 0, dnz, 0, onz)); 1961d0609cedSBarry Smith MatPreallocateEnd(dnz, onz); 19629566063dSJacob Faibussowitsch if (issbaij) PetscCall(MatRestoreRowUpperTriangular(matis->A)); 19639566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 19643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19653927de2eSStefano Zampini } 19663927de2eSStefano Zampini 1967d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_IS_XAIJ(Mat mat, MatType mtype, MatReuse reuse, Mat *M) 1968d71ae5a4SJacob Faibussowitsch { 1969f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)mat->data; 1970487b449aSStefano Zampini Mat local_mat, MT; 197153b44cf5SStefano Zampini PetscInt rbs, cbs, rows, cols, lrows, lcols; 1972b7ce53b6SStefano Zampini PetscInt local_rows, local_cols; 1973b9ed4604SStefano Zampini PetscBool isseqdense, isseqsbaij, isseqaij, isseqbaij; 1974f03112d0SStefano Zampini PetscMPIInt size; 19751683a169SBarry Smith const PetscScalar *array; 1976b7ce53b6SStefano Zampini 1977b7ce53b6SStefano Zampini PetscFunctionBegin; 19789566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 19794f58015eSStefano Zampini if (size == 1 && mat->rmap->N == matis->A->rmap->N && mat->cmap->N == matis->A->cmap->N && !matis->allow_repeated) { 19801670daf9Sstefano_zampini Mat B; 198153b44cf5SStefano Zampini IS irows = NULL, icols = NULL; 1982487b449aSStefano Zampini PetscInt rbs, cbs; 19831670daf9Sstefano_zampini 19849566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->rmapping, &rbs)); 19859566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->cmapping, &cbs)); 198653b44cf5SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { /* check if l2g maps are one-to-one */ 198753b44cf5SStefano Zampini IS rows, cols; 198853b44cf5SStefano Zampini const PetscInt *ridxs, *cidxs; 19894f58015eSStefano Zampini PetscInt i, nw; 19904f58015eSStefano Zampini PetscBT work; 199153b44cf5SStefano Zampini 19929566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(matis->rmapping, &ridxs)); 19939566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->rmapping, &nw)); 199453b44cf5SStefano Zampini nw = nw / rbs; 19954f58015eSStefano Zampini PetscCall(PetscBTCreate(nw, &work)); 19964f58015eSStefano Zampini for (i = 0; i < nw; i++) PetscCall(PetscBTSet(work, ridxs[i])); 19979371c9d4SSatish Balay for (i = 0; i < nw; i++) 19984f58015eSStefano Zampini if (!PetscBTLookup(work, i)) break; 199953b44cf5SStefano Zampini if (i == nw) { 20009566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF, rbs, nw, ridxs, PETSC_USE_POINTER, &rows)); 20019566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(rows)); 20029566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(rows, PETSC_DECIDE, &irows)); 20039566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rows)); 200453b44cf5SStefano Zampini } 20059566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(matis->rmapping, &ridxs)); 20064f58015eSStefano Zampini PetscCall(PetscBTDestroy(&work)); 2007e432b41dSStefano Zampini if (irows && matis->rmapping != matis->cmapping) { 20089566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(matis->cmapping, &cidxs)); 20099566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->cmapping, &nw)); 201053b44cf5SStefano Zampini nw = nw / cbs; 20114f58015eSStefano Zampini PetscCall(PetscBTCreate(nw, &work)); 20124f58015eSStefano Zampini for (i = 0; i < nw; i++) PetscCall(PetscBTSet(work, cidxs[i])); 20139371c9d4SSatish Balay for (i = 0; i < nw; i++) 20144f58015eSStefano Zampini if (!PetscBTLookup(work, i)) break; 201553b44cf5SStefano Zampini if (i == nw) { 20169566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF, cbs, nw, cidxs, PETSC_USE_POINTER, &cols)); 20179566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(cols)); 20189566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(cols, PETSC_DECIDE, &icols)); 20199566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cols)); 202053b44cf5SStefano Zampini } 20219566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(matis->cmapping, &cidxs)); 20224f58015eSStefano Zampini PetscCall(PetscBTDestroy(&work)); 202353b44cf5SStefano Zampini } else if (irows) { 20249566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)irows)); 202553b44cf5SStefano Zampini icols = irows; 202653b44cf5SStefano Zampini } 202753b44cf5SStefano Zampini } else { 2028f4f49eeaSPierre Jolivet PetscCall(PetscObjectQuery((PetscObject)*M, "_MatIS_IS_XAIJ_irows", (PetscObject *)&irows)); 2029f4f49eeaSPierre Jolivet PetscCall(PetscObjectQuery((PetscObject)*M, "_MatIS_IS_XAIJ_icols", (PetscObject *)&icols)); 20309566063dSJacob Faibussowitsch if (irows) PetscCall(PetscObjectReference((PetscObject)irows)); 20319566063dSJacob Faibussowitsch if (icols) PetscCall(PetscObjectReference((PetscObject)icols)); 203253b44cf5SStefano Zampini } 203353b44cf5SStefano Zampini if (!irows || !icols) { 20349566063dSJacob Faibussowitsch PetscCall(ISDestroy(&icols)); 20359566063dSJacob Faibussowitsch PetscCall(ISDestroy(&irows)); 203653b44cf5SStefano Zampini goto general_assembly; 203753b44cf5SStefano Zampini } 20389566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, mtype, MAT_INITIAL_MATRIX, &B)); 2039487b449aSStefano Zampini if (reuse != MAT_INPLACE_MATRIX) { 20409566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(B, irows, icols, reuse, M)); 2041f4f49eeaSPierre Jolivet PetscCall(PetscObjectCompose((PetscObject)*M, "_MatIS_IS_XAIJ_irows", (PetscObject)irows)); 2042f4f49eeaSPierre Jolivet PetscCall(PetscObjectCompose((PetscObject)*M, "_MatIS_IS_XAIJ_icols", (PetscObject)icols)); 2043487b449aSStefano Zampini } else { 2044487b449aSStefano Zampini Mat C; 2045487b449aSStefano Zampini 20469566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(B, irows, icols, MAT_INITIAL_MATRIX, &C)); 20479566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(mat, &C)); 2048487b449aSStefano Zampini } 20499566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 20509566063dSJacob Faibussowitsch PetscCall(ISDestroy(&icols)); 20519566063dSJacob Faibussowitsch PetscCall(ISDestroy(&irows)); 20523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20537c03b4e8SStefano Zampini } 205453b44cf5SStefano Zampini general_assembly: 20559566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &rows, &cols)); 20569566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->rmapping, &rbs)); 20579566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->cmapping, &cbs)); 20589566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mat, &lrows, &lcols)); 20599566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, &local_rows, &local_cols)); 20609566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQDENSE, &isseqdense)); 20619566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQAIJ, &isseqaij)); 20629566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQBAIJ, &isseqbaij)); 20639566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQSBAIJ, &isseqsbaij)); 2064f4f49eeaSPierre Jolivet PetscCheck(isseqdense || isseqaij || isseqbaij || isseqsbaij, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)matis->A)->type_name); 206576bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 206676bd3646SJed Brown PetscBool lb[4], bb[4]; 206776bd3646SJed Brown 2068b9ed4604SStefano Zampini lb[0] = isseqdense; 2069b9ed4604SStefano Zampini lb[1] = isseqaij; 2070b9ed4604SStefano Zampini lb[2] = isseqbaij; 2071b9ed4604SStefano Zampini lb[3] = isseqsbaij; 2072462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(lb, bb, 4, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)mat))); 2073aed4548fSBarry Smith PetscCheck(bb[0] || bb[1] || bb[2] || bb[3], PETSC_COMM_SELF, PETSC_ERR_SUP, "Local matrices must have the same type"); 207476bd3646SJed Brown } 2075b7ce53b6SStefano Zampini 2076487b449aSStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 20779566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &MT)); 20789566063dSJacob Faibussowitsch PetscCall(MatSetSizes(MT, lrows, lcols, rows, cols)); 20799566063dSJacob Faibussowitsch PetscCall(MatSetType(MT, mtype)); 20809566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(MT, rbs, cbs)); 20819566063dSJacob Faibussowitsch PetscCall(MatISSetMPIXAIJPreallocation_Private(mat, MT, PETSC_FALSE)); 2082b7ce53b6SStefano Zampini } else { 208353b44cf5SStefano Zampini PetscInt mrbs, mcbs, mrows, mcols, mlrows, mlcols; 2084487b449aSStefano Zampini 2085b7ce53b6SStefano Zampini /* some checks */ 2086487b449aSStefano Zampini MT = *M; 20879566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(MT, &mrbs, &mcbs)); 20889566063dSJacob Faibussowitsch PetscCall(MatGetSize(MT, &mrows, &mcols)); 20899566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(MT, &mlrows, &mlcols)); 209008401ef6SPierre Jolivet PetscCheck(mrows == rows, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of rows (%" PetscInt_FMT " != %" PetscInt_FMT ")", rows, mrows); 209108401ef6SPierre Jolivet PetscCheck(mcols == cols, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of cols (%" PetscInt_FMT " != %" PetscInt_FMT ")", cols, mcols); 209208401ef6SPierre Jolivet PetscCheck(mlrows == lrows, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of local rows (%" PetscInt_FMT " != %" PetscInt_FMT ")", lrows, mlrows); 209308401ef6SPierre Jolivet PetscCheck(mlcols == lcols, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of local cols (%" PetscInt_FMT " != %" PetscInt_FMT ")", lcols, mlcols); 209408401ef6SPierre Jolivet PetscCheck(mrbs == rbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong row block size (%" PetscInt_FMT " != %" PetscInt_FMT ")", rbs, mrbs); 209508401ef6SPierre Jolivet PetscCheck(mcbs == cbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong col block size (%" PetscInt_FMT " != %" PetscInt_FMT ")", cbs, mcbs); 20969566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(MT)); 2097b7ce53b6SStefano Zampini } 2098d9a9e74cSStefano Zampini 20998546b261SStefano Zampini if (isseqsbaij || isseqbaij) { 21009566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &local_mat)); 21018546b261SStefano Zampini isseqaij = PETSC_TRUE; 2102d9a9e74cSStefano Zampini } else { 21039566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)matis->A)); 2104d9a9e74cSStefano Zampini local_mat = matis->A; 2105d9a9e74cSStefano Zampini } 2106686e3a49SStefano Zampini 2107b7ce53b6SStefano Zampini /* Set values */ 21089566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(MT, matis->rmapping, matis->cmapping)); 2109b9ed4604SStefano Zampini if (isseqdense) { /* special case for dense local matrices */ 211065066ba5SStefano Zampini PetscInt i, *dummy; 2111ecf5a873SStefano Zampini 21129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(PetscMax(local_rows, local_cols), &dummy)); 211365066ba5SStefano Zampini for (i = 0; i < PetscMax(local_rows, local_cols); i++) dummy[i] = i; 21149566063dSJacob Faibussowitsch PetscCall(MatSetOption(MT, MAT_ROW_ORIENTED, PETSC_FALSE)); 21159566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(local_mat, &array)); 21169566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(MT, local_rows, dummy, local_cols, dummy, array, ADD_VALUES)); 21179566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(local_mat, &array)); 21189566063dSJacob Faibussowitsch PetscCall(PetscFree(dummy)); 2119686e3a49SStefano Zampini } else if (isseqaij) { 21206afe12f5SStefano Zampini const PetscInt *blocks; 21216afe12f5SStefano Zampini PetscInt i, nvtxs, *xadj, *adjncy, nb; 2122686e3a49SStefano Zampini PetscBool done; 21231683a169SBarry Smith PetscScalar *sarray; 2124686e3a49SStefano Zampini 21259566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(local_mat, 0, PETSC_FALSE, PETSC_FALSE, &nvtxs, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &done)); 212628b400f6SJacob Faibussowitsch PetscCheck(done, PetscObjectComm((PetscObject)local_mat), PETSC_ERR_PLIB, "Error in MatGetRowIJ"); 21279566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(local_mat, &sarray)); 21289566063dSJacob Faibussowitsch PetscCall(MatGetVariableBlockSizes(local_mat, &nb, &blocks)); 21296afe12f5SStefano Zampini if (nb) { /* speed up assembly for special blocked matrices (used by BDDC) */ 21306afe12f5SStefano Zampini PetscInt sum; 21316afe12f5SStefano Zampini 21326afe12f5SStefano Zampini for (i = 0, sum = 0; i < nb; i++) sum += blocks[i]; 21336afe12f5SStefano Zampini if (sum == nvtxs) { 21346afe12f5SStefano Zampini PetscInt r; 21356afe12f5SStefano Zampini 21366afe12f5SStefano Zampini for (i = 0, r = 0; i < nb; i++) { 21376bdcaf15SBarry Smith PetscAssert(blocks[i] == xadj[r + 1] - xadj[r], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid block sizes prescribed for block %" PetscInt_FMT ": expected %" PetscInt_FMT ", got %" PetscInt_FMT, i, blocks[i], xadj[r + 1] - xadj[r]); 21389566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(MT, blocks[i], adjncy + xadj[r], blocks[i], adjncy + xadj[r], sarray + xadj[r], ADD_VALUES)); 21396afe12f5SStefano Zampini r += blocks[i]; 21406afe12f5SStefano Zampini } 21416afe12f5SStefano Zampini } else { 214248a46eb9SPierre Jolivet for (i = 0; i < nvtxs; i++) PetscCall(MatSetValuesLocal(MT, 1, &i, xadj[i + 1] - xadj[i], adjncy + xadj[i], sarray + xadj[i], ADD_VALUES)); 21436afe12f5SStefano Zampini } 21446afe12f5SStefano Zampini } else { 21458e3a54c0SPierre Jolivet for (i = 0; i < nvtxs; i++) PetscCall(MatSetValuesLocal(MT, 1, &i, xadj[i + 1] - xadj[i], PetscSafePointerPlusOffset(adjncy, xadj[i]), PetscSafePointerPlusOffset(sarray, xadj[i]), ADD_VALUES)); 21466afe12f5SStefano Zampini } 21479566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(local_mat, 0, PETSC_FALSE, PETSC_FALSE, &nvtxs, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &done)); 214828b400f6SJacob Faibussowitsch PetscCheck(done, PetscObjectComm((PetscObject)local_mat), PETSC_ERR_PLIB, "Error in MatRestoreRowIJ"); 21499566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(local_mat, &sarray)); 2150686e3a49SStefano Zampini } else { /* very basic values insertion for all other matrix types */ 21514f58015eSStefano Zampini for (PetscInt i = 0; i < local_rows; i++) { 2152686e3a49SStefano Zampini PetscInt j; 2153ecf5a873SStefano Zampini const PetscInt *local_indices_cols; 2154686e3a49SStefano Zampini 21559566063dSJacob Faibussowitsch PetscCall(MatGetRow(local_mat, i, &j, &local_indices_cols, &array)); 21569566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(MT, 1, &i, j, local_indices_cols, array, ADD_VALUES)); 21579566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(local_mat, i, &j, &local_indices_cols, &array)); 2158686e3a49SStefano Zampini } 2159b7ce53b6SStefano Zampini } 21609566063dSJacob Faibussowitsch PetscCall(MatDestroy(&local_mat)); 21614f58015eSStefano Zampini PetscCall(MatAssemblyBegin(MT, MAT_FINAL_ASSEMBLY)); 21629566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(MT, MAT_FINAL_ASSEMBLY)); 21631baa6e33SBarry Smith if (isseqdense) PetscCall(MatSetOption(MT, MAT_ROW_ORIENTED, PETSC_TRUE)); 2164487b449aSStefano Zampini if (reuse == MAT_INPLACE_MATRIX) { 21659566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(mat, &MT)); 2166487b449aSStefano Zampini } else if (reuse == MAT_INITIAL_MATRIX) { 2167487b449aSStefano Zampini *M = MT; 2168b7ce53b6SStefano Zampini } 21693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2170b7ce53b6SStefano Zampini } 2171b7ce53b6SStefano Zampini 2172d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDuplicate_IS(Mat mat, MatDuplicateOption op, Mat *newmat) 2173d71ae5a4SJacob Faibussowitsch { 2174f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)mat->data; 2175c9225affSStefano Zampini PetscInt rbs, cbs, m, n, M, N; 2176ad6194a2SStefano Zampini Mat B, localmat; 2177ad6194a2SStefano Zampini 2178ad6194a2SStefano Zampini PetscFunctionBegin; 21799566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &rbs)); 21809566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &cbs)); 21819566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &M, &N)); 21829566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mat, &m, &n)); 21839566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 21849566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, m, n, M, N)); 21859566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(B, rbs == cbs ? rbs : 1)); 21869566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATIS)); 21879566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(B, matis->lmattype)); 21884f58015eSStefano Zampini PetscCall(MatISSetAllowRepeated(B, matis->allow_repeated)); 21899566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B, mat->rmap->mapping, mat->cmap->mapping)); 21909566063dSJacob Faibussowitsch PetscCall(MatDuplicate(matis->A, op, &localmat)); 21919566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(localmat, matis->A->rmap->mapping, matis->A->cmap->mapping)); 21929566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B, localmat)); 21939566063dSJacob Faibussowitsch PetscCall(MatDestroy(&localmat)); 21949566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 21959566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 2196ad6194a2SStefano Zampini *newmat = B; 21973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2198ad6194a2SStefano Zampini } 2199ad6194a2SStefano Zampini 2200d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsHermitian_IS(Mat A, PetscReal tol, PetscBool *flg) 2201d71ae5a4SJacob Faibussowitsch { 220269796d55SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 220369796d55SStefano Zampini PetscBool local_sym; 220469796d55SStefano Zampini 220569796d55SStefano Zampini PetscFunctionBegin; 22069566063dSJacob Faibussowitsch PetscCall(MatIsHermitian(matis->A, tol, &local_sym)); 2207462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&local_sym, flg, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 22083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 220969796d55SStefano Zampini } 221069796d55SStefano Zampini 2211d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsSymmetric_IS(Mat A, PetscReal tol, PetscBool *flg) 2212d71ae5a4SJacob Faibussowitsch { 221369796d55SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 221469796d55SStefano Zampini PetscBool local_sym; 221569796d55SStefano Zampini 221669796d55SStefano Zampini PetscFunctionBegin; 2217e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { 2218e432b41dSStefano Zampini *flg = PETSC_FALSE; 22193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2220e432b41dSStefano Zampini } 22219566063dSJacob Faibussowitsch PetscCall(MatIsSymmetric(matis->A, tol, &local_sym)); 2222462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&local_sym, flg, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 22233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 222469796d55SStefano Zampini } 222569796d55SStefano Zampini 2226d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A, PetscBool *flg) 2227d71ae5a4SJacob Faibussowitsch { 222845471136SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 222945471136SStefano Zampini PetscBool local_sym; 223045471136SStefano Zampini 223145471136SStefano Zampini PetscFunctionBegin; 2232e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { 223345471136SStefano Zampini *flg = PETSC_FALSE; 22343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 223545471136SStefano Zampini } 22369566063dSJacob Faibussowitsch PetscCall(MatIsStructurallySymmetric(matis->A, &local_sym)); 2237462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&local_sym, flg, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 22383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 223945471136SStefano Zampini } 224045471136SStefano Zampini 2241d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_IS(Mat A) 2242d71ae5a4SJacob Faibussowitsch { 2243b4319ba4SBarry Smith Mat_IS *b = (Mat_IS *)A->data; 2244b4319ba4SBarry Smith 2245b4319ba4SBarry Smith PetscFunctionBegin; 22469566063dSJacob Faibussowitsch PetscCall(PetscFree(b->bdiag)); 22479566063dSJacob Faibussowitsch PetscCall(PetscFree(b->lmattype)); 22489566063dSJacob Faibussowitsch PetscCall(MatDestroy(&b->A)); 22499566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&b->cctx)); 22509566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&b->rctx)); 22519566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->x)); 22529566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->y)); 22539566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->counter)); 22549566063dSJacob Faibussowitsch PetscCall(ISDestroy(&b->getsub_ris)); 22559566063dSJacob Faibussowitsch PetscCall(ISDestroy(&b->getsub_cis)); 2256a8116848SStefano Zampini if (b->sf != b->csf) { 22579566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&b->csf)); 22589566063dSJacob Faibussowitsch PetscCall(PetscFree2(b->csf_rootdata, b->csf_leafdata)); 2259f03112d0SStefano Zampini } else b->csf = NULL; 22609566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&b->sf)); 22619566063dSJacob Faibussowitsch PetscCall(PetscFree2(b->sf_rootdata, b->sf_leafdata)); 22629566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&b->rmapping)); 22639566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&b->cmapping)); 2264d0dbe9f7SStefano Zampini PetscCall(MatDestroy(&b->dA)); 2265d0dbe9f7SStefano Zampini PetscCall(MatDestroy(&b->assembledA)); 22669566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 22679566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, NULL)); 22689566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMatType_C", NULL)); 22699566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalMat_C", NULL)); 22709566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMat_C", NULL)); 22712e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISRestoreLocalMat_C", NULL)); 22729566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetPreallocation_C", NULL)); 22739566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISStoreL2L_C", NULL)); 22749566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISFixLocalEmpty_C", NULL)); 22759566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalToGlobalMapping_C", NULL)); 22769566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpiaij_C", NULL)); 22779566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpibaij_C", NULL)); 22789566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpisbaij_C", NULL)); 22799566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqaij_C", NULL)); 22809566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqbaij_C", NULL)); 22819566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqsbaij_C", NULL)); 22829566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_aij_C", NULL)); 22839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOOLocal_C", NULL)); 22849566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL)); 22859566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL)); 22864f58015eSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetAllowRepeated_C", NULL)); 22873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2288b4319ba4SBarry Smith } 2289b4319ba4SBarry Smith 2290d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_IS(Mat A, Vec x, Vec y) 2291d71ae5a4SJacob Faibussowitsch { 2292b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)A->data; 2293b4319ba4SBarry Smith PetscScalar zero = 0.0; 2294b4319ba4SBarry Smith 2295b4319ba4SBarry Smith PetscFunctionBegin; 2296b4319ba4SBarry Smith /* scatter the global vector x into the local work vector */ 22979566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->cctx, x, is->x, INSERT_VALUES, SCATTER_FORWARD)); 22989566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->cctx, x, is->x, INSERT_VALUES, SCATTER_FORWARD)); 2299b4319ba4SBarry Smith 2300b4319ba4SBarry Smith /* multiply the local matrix */ 23019566063dSJacob Faibussowitsch PetscCall(MatMult(is->A, is->x, is->y)); 2302b4319ba4SBarry Smith 2303b4319ba4SBarry Smith /* scatter product back into global memory */ 23049566063dSJacob Faibussowitsch PetscCall(VecSet(y, zero)); 23059566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, is->y, y, ADD_VALUES, SCATTER_REVERSE)); 23069566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, is->y, y, ADD_VALUES, SCATTER_REVERSE)); 23073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2308b4319ba4SBarry Smith } 2309b4319ba4SBarry Smith 2310d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultAdd_IS(Mat A, Vec v1, Vec v2, Vec v3) 2311d71ae5a4SJacob Faibussowitsch { 2312650997f4SStefano Zampini Vec temp_vec; 23132e74eeadSLisandro Dalcin 23142e74eeadSLisandro Dalcin PetscFunctionBegin; /* v3 = v2 + A * v1.*/ 2315650997f4SStefano Zampini if (v3 != v2) { 23169566063dSJacob Faibussowitsch PetscCall(MatMult(A, v1, v3)); 23179566063dSJacob Faibussowitsch PetscCall(VecAXPY(v3, 1.0, v2)); 2318650997f4SStefano Zampini } else { 23199566063dSJacob Faibussowitsch PetscCall(VecDuplicate(v2, &temp_vec)); 23209566063dSJacob Faibussowitsch PetscCall(MatMult(A, v1, temp_vec)); 23219566063dSJacob Faibussowitsch PetscCall(VecAXPY(temp_vec, 1.0, v2)); 23229566063dSJacob Faibussowitsch PetscCall(VecCopy(temp_vec, v3)); 23239566063dSJacob Faibussowitsch PetscCall(VecDestroy(&temp_vec)); 2324650997f4SStefano Zampini } 23253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23262e74eeadSLisandro Dalcin } 23272e74eeadSLisandro Dalcin 2328d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTranspose_IS(Mat A, Vec y, Vec x) 2329d71ae5a4SJacob Faibussowitsch { 23302e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS *)A->data; 23312e74eeadSLisandro Dalcin 2332e176bc59SStefano Zampini PetscFunctionBegin; 23332e74eeadSLisandro Dalcin /* scatter the global vector x into the local work vector */ 23349566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, y, is->y, INSERT_VALUES, SCATTER_FORWARD)); 23359566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, y, is->y, INSERT_VALUES, SCATTER_FORWARD)); 23362e74eeadSLisandro Dalcin 23372e74eeadSLisandro Dalcin /* multiply the local matrix */ 23389566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(is->A, is->y, is->x)); 23392e74eeadSLisandro Dalcin 23402e74eeadSLisandro Dalcin /* scatter product back into global vector */ 23419566063dSJacob Faibussowitsch PetscCall(VecSet(x, 0)); 23429566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->cctx, is->x, x, ADD_VALUES, SCATTER_REVERSE)); 23439566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->cctx, is->x, x, ADD_VALUES, SCATTER_REVERSE)); 23443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23452e74eeadSLisandro Dalcin } 23462e74eeadSLisandro Dalcin 2347d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTransposeAdd_IS(Mat A, Vec v1, Vec v2, Vec v3) 2348d71ae5a4SJacob Faibussowitsch { 2349650997f4SStefano Zampini Vec temp_vec; 23502e74eeadSLisandro Dalcin 23512e74eeadSLisandro Dalcin PetscFunctionBegin; /* v3 = v2 + A' * v1.*/ 2352650997f4SStefano Zampini if (v3 != v2) { 23539566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(A, v1, v3)); 23549566063dSJacob Faibussowitsch PetscCall(VecAXPY(v3, 1.0, v2)); 2355650997f4SStefano Zampini } else { 23569566063dSJacob Faibussowitsch PetscCall(VecDuplicate(v2, &temp_vec)); 23579566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(A, v1, temp_vec)); 23589566063dSJacob Faibussowitsch PetscCall(VecAXPY(temp_vec, 1.0, v2)); 23599566063dSJacob Faibussowitsch PetscCall(VecCopy(temp_vec, v3)); 23609566063dSJacob Faibussowitsch PetscCall(VecDestroy(&temp_vec)); 2361650997f4SStefano Zampini } 23623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23632e74eeadSLisandro Dalcin } 23642e74eeadSLisandro Dalcin 2365d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_IS(Mat A, PetscViewer viewer) 2366d71ae5a4SJacob Faibussowitsch { 2367b4319ba4SBarry Smith Mat_IS *a = (Mat_IS *)A->data; 2368b4319ba4SBarry Smith PetscViewer sviewer; 23695042aa92SStefano Zampini PetscBool isascii, isbinary, viewl2g = PETSC_FALSE, native; 23705042aa92SStefano Zampini PetscViewerFormat format; 23715042aa92SStefano Zampini ISLocalToGlobalMapping rmap, cmap; 2372b4319ba4SBarry Smith 2373b4319ba4SBarry Smith PetscFunctionBegin; 23749566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 23755042aa92SStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 23769566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 23775042aa92SStefano Zampini native = (PetscBool)(format == PETSC_VIEWER_NATIVE); 23785042aa92SStefano Zampini if (native) { 23795042aa92SStefano Zampini rmap = A->rmap->mapping; 23805042aa92SStefano Zampini cmap = A->cmap->mapping; 23815042aa92SStefano Zampini } else { 23825042aa92SStefano Zampini rmap = a->rmapping; 23835042aa92SStefano Zampini cmap = a->cmapping; 2384ee2491ecSStefano Zampini } 23855042aa92SStefano Zampini if (isascii) { 23865042aa92SStefano Zampini if (format == PETSC_VIEWER_ASCII_INFO) PetscFunctionReturn(PETSC_SUCCESS); 23875042aa92SStefano Zampini if (format == PETSC_VIEWER_ASCII_INFO_DETAIL || format == PETSC_VIEWER_ASCII_MATLAB) viewl2g = PETSC_TRUE; 23885042aa92SStefano Zampini } else if (isbinary) { 23895042aa92SStefano Zampini PetscInt tr[6], nr, nc; 23905042aa92SStefano Zampini char lmattype[64] = {'\0'}; 23915042aa92SStefano Zampini PetscMPIInt size; 23925042aa92SStefano Zampini PetscBool skipHeader; 23935042aa92SStefano Zampini IS is; 23945042aa92SStefano Zampini 23955042aa92SStefano Zampini PetscCall(PetscViewerSetUp(viewer)); 23965042aa92SStefano Zampini PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 23975042aa92SStefano Zampini tr[0] = MAT_FILE_CLASSID; 23985042aa92SStefano Zampini tr[1] = A->rmap->N; 23995042aa92SStefano Zampini tr[2] = A->cmap->N; 24005042aa92SStefano Zampini tr[3] = -size; /* AIJ stores nnz here */ 24015042aa92SStefano Zampini tr[4] = (PetscInt)(rmap == cmap); 24025042aa92SStefano Zampini tr[5] = a->allow_repeated; 24035042aa92SStefano Zampini PetscCall(PetscSNPrintf(lmattype, sizeof(lmattype), "%s", a->lmattype)); 24045042aa92SStefano Zampini 24055042aa92SStefano Zampini PetscCall(PetscViewerBinaryWrite(viewer, tr, PETSC_STATIC_ARRAY_LENGTH(tr), PETSC_INT)); 24065042aa92SStefano Zampini PetscCall(PetscViewerBinaryWrite(viewer, lmattype, sizeof(lmattype), PETSC_CHAR)); 24075042aa92SStefano Zampini 24085042aa92SStefano Zampini /* first dump l2g info (we need the header for proper loading on different number of processes) */ 24095042aa92SStefano Zampini PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader)); 24105042aa92SStefano Zampini PetscCall(PetscViewerBinarySetSkipHeader(viewer, PETSC_FALSE)); 24115042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingView(rmap, viewer)); 24125042aa92SStefano Zampini if (cmap != rmap) PetscCall(ISLocalToGlobalMappingView(cmap, viewer)); 24135042aa92SStefano Zampini 24145042aa92SStefano Zampini /* then the sizes of the local matrices */ 24155042aa92SStefano Zampini PetscCall(MatGetSize(a->A, &nr, &nc)); 24165042aa92SStefano Zampini PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), 1, &nr, PETSC_USE_POINTER, &is)); 24175042aa92SStefano Zampini PetscCall(ISView(is, viewer)); 24185042aa92SStefano Zampini PetscCall(ISDestroy(&is)); 24195042aa92SStefano Zampini PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), 1, &nc, PETSC_USE_POINTER, &is)); 24205042aa92SStefano Zampini PetscCall(ISView(is, viewer)); 24215042aa92SStefano Zampini PetscCall(ISDestroy(&is)); 24225042aa92SStefano Zampini PetscCall(PetscViewerBinarySetSkipHeader(viewer, skipHeader)); 24235042aa92SStefano Zampini } 24245042aa92SStefano Zampini if (format == PETSC_VIEWER_ASCII_MATLAB) { 24255042aa92SStefano Zampini char name[64]; 24265042aa92SStefano Zampini PetscMPIInt size, rank; 24275042aa92SStefano Zampini 24285042aa92SStefano Zampini PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 24295042aa92SStefano Zampini PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 24305042aa92SStefano Zampini if (size > 1) PetscCall(PetscSNPrintf(name, sizeof(name), "lmat_%d", rank)); 24315042aa92SStefano Zampini else PetscCall(PetscSNPrintf(name, sizeof(name), "lmat")); 24325042aa92SStefano Zampini PetscCall(PetscObjectSetName((PetscObject)a->A, name)); 24335042aa92SStefano Zampini } 24345042aa92SStefano Zampini 24355042aa92SStefano Zampini /* Dump the local matrices */ 24365042aa92SStefano Zampini if (isbinary) { /* ViewerGetSubViewer does not work in parallel */ 24375042aa92SStefano Zampini PetscBool isaij; 24385042aa92SStefano Zampini PetscInt nr, nc; 24395042aa92SStefano Zampini Mat lA, B; 24405042aa92SStefano Zampini Mat_MPIAIJ *b; 24415042aa92SStefano Zampini 24425042aa92SStefano Zampini /* We create a temporary MPIAIJ matrix that stores the unassembled operator */ 24435042aa92SStefano Zampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)a->A, MATAIJ, &isaij)); 24445042aa92SStefano Zampini if (!isaij) PetscCall(MatConvert(a->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &lA)); 24455042aa92SStefano Zampini else { 24465042aa92SStefano Zampini PetscCall(PetscObjectReference((PetscObject)a->A)); 24475042aa92SStefano Zampini lA = a->A; 24485042aa92SStefano Zampini } 24495042aa92SStefano Zampini PetscCall(MatCreate(PetscObjectComm((PetscObject)viewer), &B)); 24505042aa92SStefano Zampini PetscCall(MatSetType(B, MATMPIAIJ)); 24515042aa92SStefano Zampini PetscCall(MatGetSize(lA, &nr, &nc)); 24525042aa92SStefano Zampini PetscCall(MatSetSizes(B, nr, nc, PETSC_DECIDE, PETSC_DECIDE)); 24535042aa92SStefano Zampini PetscCall(MatMPIAIJSetPreallocation(B, 0, NULL, 0, NULL)); 24545042aa92SStefano Zampini 24555042aa92SStefano Zampini b = (Mat_MPIAIJ *)B->data; 24565042aa92SStefano Zampini PetscCall(MatDestroy(&b->A)); 24575042aa92SStefano Zampini b->A = lA; 24585042aa92SStefano Zampini 24595042aa92SStefano Zampini PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 24605042aa92SStefano Zampini PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 24615042aa92SStefano Zampini PetscCall(MatView(B, viewer)); 24625042aa92SStefano Zampini PetscCall(MatDestroy(&B)); 24635042aa92SStefano Zampini } else { 24649566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 24659566063dSJacob Faibussowitsch PetscCall(MatView(a->A, sviewer)); 24669566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 24675042aa92SStefano Zampini } 24685042aa92SStefano Zampini 24695042aa92SStefano Zampini /* with ASCII, we dump the l2gmaps at the end */ 24705042aa92SStefano Zampini if (viewl2g) { 24715042aa92SStefano Zampini if (format == PETSC_VIEWER_ASCII_MATLAB) { 24725042aa92SStefano Zampini PetscCall(PetscObjectSetName((PetscObject)rmap, "row")); 24735042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingView(rmap, viewer)); 24745042aa92SStefano Zampini PetscCall(PetscObjectSetName((PetscObject)cmap, "col")); 24755042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingView(cmap, viewer)); 24765042aa92SStefano Zampini } else { 24775042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingView(rmap, viewer)); 24785042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingView(cmap, viewer)); 24795042aa92SStefano Zampini } 24805042aa92SStefano Zampini } 24815042aa92SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 24825042aa92SStefano Zampini } 24835042aa92SStefano Zampini 24845042aa92SStefano Zampini static PetscErrorCode MatLoad_IS(Mat A, PetscViewer viewer) 24855042aa92SStefano Zampini { 24865042aa92SStefano Zampini ISLocalToGlobalMapping rmap, cmap; 24875042aa92SStefano Zampini MPI_Comm comm = PetscObjectComm((PetscObject)A); 24885042aa92SStefano Zampini PetscBool isbinary, samel, allow, isbaij; 24895042aa92SStefano Zampini PetscInt tr[6], M, N, nr, nc, Asize, isn; 24905042aa92SStefano Zampini const PetscInt *idx; 24915042aa92SStefano Zampini PetscMPIInt size; 24925042aa92SStefano Zampini char lmattype[64]; 24935042aa92SStefano Zampini Mat dA, lA; 24945042aa92SStefano Zampini IS is; 24955042aa92SStefano Zampini 24965042aa92SStefano Zampini PetscFunctionBegin; 24975042aa92SStefano Zampini PetscCheckSameComm(A, 1, viewer, 2); 24985042aa92SStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 24995042aa92SStefano Zampini PetscCheck(isbinary, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Invalid viewer of type %s", ((PetscObject)viewer)->type_name); 25005042aa92SStefano Zampini 25015042aa92SStefano Zampini PetscCall(PetscViewerBinaryRead(viewer, tr, PETSC_STATIC_ARRAY_LENGTH(tr), NULL, PETSC_INT)); 25025042aa92SStefano Zampini PetscCheck(tr[0] == MAT_FILE_CLASSID, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a matrix next in file"); 25035042aa92SStefano Zampini PetscCheck(tr[1] >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a IS matrix next in file"); 25045042aa92SStefano Zampini PetscCheck(tr[2] >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a IS matrix next in file"); 25055042aa92SStefano Zampini PetscCheck(tr[3] < 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a IS matrix next in file"); 25065042aa92SStefano Zampini PetscCheck(tr[4] == 0 || tr[4] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a IS matrix next in file"); 25075042aa92SStefano Zampini PetscCheck(tr[5] == 0 || tr[5] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a IS matrix next in file"); 25085042aa92SStefano Zampini M = tr[1]; 25095042aa92SStefano Zampini N = tr[2]; 25105042aa92SStefano Zampini Asize = -tr[3]; 25115042aa92SStefano Zampini samel = (PetscBool)tr[4]; 25125042aa92SStefano Zampini allow = (PetscBool)tr[5]; 25135042aa92SStefano Zampini PetscCall(PetscViewerBinaryRead(viewer, lmattype, sizeof(lmattype), NULL, PETSC_CHAR)); 25145042aa92SStefano Zampini 25155042aa92SStefano Zampini /* if we are loading from a larger set of processes, allow repeated entries */ 25165042aa92SStefano Zampini PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 25175042aa92SStefano Zampini if (Asize > size) allow = PETSC_TRUE; 25185042aa92SStefano Zampini 25195042aa92SStefano Zampini /* set global sizes if not set already */ 25205042aa92SStefano Zampini if (A->rmap->N < 0) A->rmap->N = M; 25215042aa92SStefano Zampini if (A->cmap->N < 0) A->cmap->N = N; 25225042aa92SStefano Zampini PetscCall(PetscLayoutSetUp(A->rmap)); 25235042aa92SStefano Zampini PetscCall(PetscLayoutSetUp(A->cmap)); 25245042aa92SStefano Zampini PetscCheck(M == A->rmap->N, comm, PETSC_ERR_ARG_SIZ, "Matrix rows should be %" PetscInt_FMT ", found %" PetscInt_FMT, M, A->rmap->N); 25255042aa92SStefano Zampini PetscCheck(N == A->cmap->N, comm, PETSC_ERR_ARG_SIZ, "Matrix columns should be %" PetscInt_FMT ", found %" PetscInt_FMT, N, A->cmap->N); 25265042aa92SStefano Zampini 25275042aa92SStefano Zampini /* load l2g maps */ 25285042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingCreate(comm, 0, 0, NULL, PETSC_USE_POINTER, &rmap)); 25295042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingLoad(rmap, viewer)); 25305042aa92SStefano Zampini if (!samel) { 25315042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingCreate(comm, 0, 0, NULL, PETSC_USE_POINTER, &cmap)); 25325042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingLoad(cmap, viewer)); 25335042aa92SStefano Zampini } else { 25345042aa92SStefano Zampini PetscCall(PetscObjectReference((PetscObject)rmap)); 25355042aa92SStefano Zampini cmap = rmap; 25365042aa92SStefano Zampini } 25375042aa92SStefano Zampini 25385042aa92SStefano Zampini /* load sizes of local matrices */ 25395042aa92SStefano Zampini PetscCall(ISCreate(comm, &is)); 25405042aa92SStefano Zampini PetscCall(ISSetType(is, ISGENERAL)); 25415042aa92SStefano Zampini PetscCall(ISLoad(is, viewer)); 25425042aa92SStefano Zampini PetscCall(ISGetLocalSize(is, &isn)); 25435042aa92SStefano Zampini PetscCall(ISGetIndices(is, &idx)); 25445042aa92SStefano Zampini nr = 0; 25455042aa92SStefano Zampini for (PetscInt i = 0; i < isn; i++) nr += idx[i]; 25465042aa92SStefano Zampini PetscCall(ISRestoreIndices(is, &idx)); 25475042aa92SStefano Zampini PetscCall(ISDestroy(&is)); 25485042aa92SStefano Zampini PetscCall(ISCreate(comm, &is)); 25495042aa92SStefano Zampini PetscCall(ISSetType(is, ISGENERAL)); 25505042aa92SStefano Zampini PetscCall(ISLoad(is, viewer)); 25515042aa92SStefano Zampini PetscCall(ISGetLocalSize(is, &isn)); 25525042aa92SStefano Zampini PetscCall(ISGetIndices(is, &idx)); 25535042aa92SStefano Zampini nc = 0; 25545042aa92SStefano Zampini for (PetscInt i = 0; i < isn; i++) nc += idx[i]; 25555042aa92SStefano Zampini PetscCall(ISRestoreIndices(is, &idx)); 25565042aa92SStefano Zampini PetscCall(ISDestroy(&is)); 25575042aa92SStefano Zampini 25585042aa92SStefano Zampini /* now load the unassembled operator */ 25595042aa92SStefano Zampini PetscCall(MatCreate(comm, &dA)); 25605042aa92SStefano Zampini PetscCall(MatSetType(dA, MATMPIAIJ)); 25615042aa92SStefano Zampini PetscCall(MatSetSizes(dA, nr, nc, PETSC_DECIDE, PETSC_DECIDE)); 25625042aa92SStefano Zampini PetscCall(MatLoad(dA, viewer)); 25635042aa92SStefano Zampini PetscCall(MatMPIAIJGetSeqAIJ(dA, &lA, NULL, NULL)); 25645042aa92SStefano Zampini PetscCall(PetscObjectReference((PetscObject)lA)); 25655042aa92SStefano Zampini PetscCall(MatDestroy(&dA)); 25665042aa92SStefano Zampini 25675042aa92SStefano Zampini /* and convert to the desired format */ 25685042aa92SStefano Zampini PetscCall(PetscStrcmpAny(lmattype, &isbaij, MATSBAIJ, MATSEQSBAIJ, "")); 25695042aa92SStefano Zampini if (isbaij) PetscCall(MatSetOption(lA, MAT_SYMMETRIC, PETSC_TRUE)); 25705042aa92SStefano Zampini PetscCall(MatConvert(lA, lmattype, MAT_INPLACE_MATRIX, &lA)); 25715042aa92SStefano Zampini 25725042aa92SStefano Zampini /* assemble the MATIS object */ 25735042aa92SStefano Zampini PetscCall(MatISSetAllowRepeated(A, allow)); 25745042aa92SStefano Zampini PetscCall(MatSetLocalToGlobalMapping(A, rmap, cmap)); 25755042aa92SStefano Zampini PetscCall(MatISSetLocalMat(A, lA)); 25765042aa92SStefano Zampini PetscCall(MatDestroy(&lA)); 25775042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingDestroy(&rmap)); 25785042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingDestroy(&cmap)); 25795042aa92SStefano Zampini PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 25805042aa92SStefano Zampini PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 25813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2582b4319ba4SBarry Smith } 2583b4319ba4SBarry Smith 2584d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatInvertBlockDiagonal_IS(Mat mat, const PetscScalar **values) 2585d71ae5a4SJacob Faibussowitsch { 2586b89f26deSStefano Zampini Mat_IS *is = (Mat_IS *)mat->data; 2587b89f26deSStefano Zampini MPI_Datatype nodeType; 2588b89f26deSStefano Zampini const PetscScalar *lv; 2589b89f26deSStefano Zampini PetscInt bs; 2590b89f26deSStefano Zampini 2591b89f26deSStefano Zampini PetscFunctionBegin; 25929566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(mat, &bs)); 25939566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(is->A, bs)); 25949566063dSJacob Faibussowitsch PetscCall(MatInvertBlockDiagonal(is->A, &lv)); 259548a46eb9SPierre Jolivet if (!is->bdiag) PetscCall(PetscMalloc1(bs * mat->rmap->n, &is->bdiag)); 25966497c311SBarry Smith PetscCallMPI(MPI_Type_contiguous((PetscMPIInt)bs, MPIU_SCALAR, &nodeType)); 25979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&nodeType)); 25989566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(is->sf, nodeType, lv, is->bdiag, MPI_REPLACE)); 25999566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(is->sf, nodeType, lv, is->bdiag, MPI_REPLACE)); 26009566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&nodeType)); 2601b89f26deSStefano Zampini if (values) *values = is->bdiag; 26023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2603b89f26deSStefano Zampini } 2604b89f26deSStefano Zampini 2605d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISSetUpScatters_Private(Mat A) 2606d71ae5a4SJacob Faibussowitsch { 2607e176bc59SStefano Zampini Vec cglobal, rglobal; 26088546b261SStefano Zampini IS from; 26098546b261SStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 2610b89f26deSStefano Zampini PetscScalar sum; 26118546b261SStefano Zampini const PetscInt *garray; 26128546b261SStefano Zampini PetscInt nr, rbs, nc, cbs; 2613e432b41dSStefano Zampini VecType rtype; 2614b4319ba4SBarry Smith 2615b4319ba4SBarry Smith PetscFunctionBegin; 26169566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->rmapping, &nr)); 26179566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->rmapping, &rbs)); 26189566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->cmapping, &nc)); 26199566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->cmapping, &cbs)); 26209566063dSJacob Faibussowitsch PetscCall(VecDestroy(&is->x)); 26219566063dSJacob Faibussowitsch PetscCall(VecDestroy(&is->y)); 26229566063dSJacob Faibussowitsch PetscCall(VecDestroy(&is->counter)); 26239566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&is->rctx)); 26249566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&is->cctx)); 26259566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(is->A, &is->x, &is->y)); 26269566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->y, PETSC_TRUE)); 26279566063dSJacob Faibussowitsch PetscCall(VecGetRootType_Private(is->y, &rtype)); 26289566063dSJacob Faibussowitsch PetscCall(PetscFree(A->defaultvectype)); 26299566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(rtype, &A->defaultvectype)); 26309566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, &cglobal, &rglobal)); 26319566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(rglobal, PETSC_TRUE)); 26329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->rmapping, &garray)); 26339566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), rbs, nr / rbs, garray, PETSC_USE_POINTER, &from)); 26349566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(rglobal, from, is->y, NULL, &is->rctx)); 26359566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->rmapping, &garray)); 26369566063dSJacob Faibussowitsch PetscCall(ISDestroy(&from)); 2637e432b41dSStefano Zampini if (is->rmapping != is->cmapping) { 26389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->cmapping, &garray)); 26399566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), cbs, nc / cbs, garray, PETSC_USE_POINTER, &from)); 26409566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(cglobal, from, is->x, NULL, &is->cctx)); 26419566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->cmapping, &garray)); 26429566063dSJacob Faibussowitsch PetscCall(ISDestroy(&from)); 26438546b261SStefano Zampini } else { 26449566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->rctx)); 26458546b261SStefano Zampini is->cctx = is->rctx; 26468546b261SStefano Zampini } 26479566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cglobal)); 2648b89f26deSStefano Zampini 26498546b261SStefano Zampini /* interface counter vector (local) */ 26509566063dSJacob Faibussowitsch PetscCall(VecDuplicate(is->y, &is->counter)); 26519566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->counter, PETSC_TRUE)); 26529566063dSJacob Faibussowitsch PetscCall(VecSet(is->y, 1.)); 26539566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, is->y, rglobal, ADD_VALUES, SCATTER_REVERSE)); 26549566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, is->y, rglobal, ADD_VALUES, SCATTER_REVERSE)); 26559566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, rglobal, is->counter, INSERT_VALUES, SCATTER_FORWARD)); 26569566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, rglobal, is->counter, INSERT_VALUES, SCATTER_FORWARD)); 26579566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->y, PETSC_FALSE)); 26589566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->counter, PETSC_FALSE)); 2659b89f26deSStefano Zampini 2660b89f26deSStefano Zampini /* special functions for block-diagonal matrices */ 26619566063dSJacob Faibussowitsch PetscCall(VecSum(rglobal, &sum)); 2662b89f26deSStefano Zampini A->ops->invertblockdiagonal = NULL; 2663e432b41dSStefano Zampini if ((PetscInt)(PetscRealPart(sum)) == A->rmap->N && A->rmap->N == A->cmap->N && is->rmapping == is->cmapping) A->ops->invertblockdiagonal = MatInvertBlockDiagonal_IS; 26649566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rglobal)); 2665b0cc1f67SStefano Zampini 2666b0cc1f67SStefano Zampini /* setup SF for general purpose shared indices based communications */ 26679566063dSJacob Faibussowitsch PetscCall(MatISSetUpSF_IS(A)); 26683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 26698546b261SStefano Zampini } 26708546b261SStefano Zampini 2671d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISFilterL2GMap(Mat A, ISLocalToGlobalMapping map, ISLocalToGlobalMapping *nmap, ISLocalToGlobalMapping *lmap) 2672d71ae5a4SJacob Faibussowitsch { 26734f58015eSStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 2674e432b41dSStefano Zampini IS is; 2675e432b41dSStefano Zampini ISLocalToGlobalMappingType l2gtype; 2676e432b41dSStefano Zampini const PetscInt *idxs; 2677e432b41dSStefano Zampini PetscHSetI ht; 2678e432b41dSStefano Zampini PetscInt *nidxs; 2679e432b41dSStefano Zampini PetscInt i, n, bs, c; 2680e432b41dSStefano Zampini PetscBool flg[] = {PETSC_FALSE, PETSC_FALSE}; 2681e432b41dSStefano Zampini 2682e432b41dSStefano Zampini PetscFunctionBegin; 26839566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(map, &n)); 26849566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(map, &bs)); 26859566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(map, &idxs)); 26869566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&ht)); 26879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n / bs, &nidxs)); 2688e432b41dSStefano Zampini for (i = 0, c = 0; i < n / bs; i++) { 26894f58015eSStefano Zampini PetscBool missing = PETSC_TRUE; 26909371c9d4SSatish Balay if (idxs[i] < 0) { 26919371c9d4SSatish Balay flg[0] = PETSC_TRUE; 26929371c9d4SSatish Balay continue; 26939371c9d4SSatish Balay } 26944f58015eSStefano Zampini if (!matis->allow_repeated) PetscCall(PetscHSetIQueryAdd(ht, idxs[i], &missing)); 2695e432b41dSStefano Zampini if (!missing) flg[1] = PETSC_TRUE; 2696e432b41dSStefano Zampini else nidxs[c++] = idxs[i]; 2697e432b41dSStefano Zampini } 26989566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&ht)); 2699462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, flg, 2, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A))); 2700e432b41dSStefano Zampini if (!flg[0] && !flg[1]) { /* Entries are all non negative and unique */ 2701e432b41dSStefano Zampini *nmap = NULL; 2702e432b41dSStefano Zampini *lmap = NULL; 27039566063dSJacob Faibussowitsch PetscCall(PetscFree(nidxs)); 27049566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(map, &idxs)); 27053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2706e432b41dSStefano Zampini } 2707e432b41dSStefano Zampini 27084f58015eSStefano Zampini /* New l2g map without negative indices (and repeated indices if not allowed) */ 27099566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), bs, c, nidxs, PETSC_USE_POINTER, &is)); 27109566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, nmap)); 27119566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 27129566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetType(map, &l2gtype)); 27139566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(*nmap, l2gtype)); 2714e432b41dSStefano Zampini 27154f58015eSStefano Zampini /* New local l2g map for repeated indices if not allowed */ 27169566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(*nmap, IS_GTOLM_MASK, n / bs, idxs, NULL, nidxs)); 27179566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF, bs, n / bs, nidxs, PETSC_USE_POINTER, &is)); 27189566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, lmap)); 27199566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 27209566063dSJacob Faibussowitsch PetscCall(PetscFree(nidxs)); 27219566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(map, &idxs)); 27223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2723e432b41dSStefano Zampini } 2724e432b41dSStefano Zampini 2725d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2726d71ae5a4SJacob Faibussowitsch { 27278546b261SStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 2728e432b41dSStefano Zampini ISLocalToGlobalMapping localrmapping = NULL, localcmapping = NULL; 2729e432b41dSStefano Zampini PetscInt nr, rbs, nc, cbs; 27304f58015eSStefano Zampini PetscBool cong, freem[] = {PETSC_FALSE, PETSC_FALSE}; 27318546b261SStefano Zampini 27328546b261SStefano Zampini PetscFunctionBegin; 2733fc989267SStefano Zampini if (rmapping) PetscCheckSameComm(A, 1, rmapping, 2); 2734fc989267SStefano Zampini if (cmapping) PetscCheckSameComm(A, 1, cmapping, 3); 2735e432b41dSStefano Zampini 27369566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&is->rmapping)); 27379566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&is->cmapping)); 27389566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 27399566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 27409566063dSJacob Faibussowitsch PetscCall(MatHasCongruentLayouts(A, &cong)); 2741e432b41dSStefano Zampini 2742fc989267SStefano Zampini /* If NULL, local space matches global space */ 2743fc989267SStefano Zampini if (!rmapping) { 2744fc989267SStefano Zampini IS is; 2745fc989267SStefano Zampini 27469566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), A->rmap->N, 0, 1, &is)); 27479566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rmapping)); 27489566063dSJacob Faibussowitsch if (A->rmap->bs > 0) PetscCall(ISLocalToGlobalMappingSetBlockSize(rmapping, A->rmap->bs)); 27499566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2750e432b41dSStefano Zampini freem[0] = PETSC_TRUE; 2751e432b41dSStefano Zampini if (!cmapping && cong && A->rmap->bs == A->cmap->bs) cmapping = rmapping; 2752e432b41dSStefano Zampini } else if (!is->islocalref) { /* check if the l2g map has negative or repeated entries */ 27539566063dSJacob Faibussowitsch PetscCall(MatISFilterL2GMap(A, rmapping, &is->rmapping, &localrmapping)); 2754e432b41dSStefano Zampini if (rmapping == cmapping) { 27559566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->rmapping)); 2756e432b41dSStefano Zampini is->cmapping = is->rmapping; 27579566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)localrmapping)); 2758e432b41dSStefano Zampini localcmapping = localrmapping; 2759fc989267SStefano Zampini } 2760fc989267SStefano Zampini } 2761fc989267SStefano Zampini if (!cmapping) { 2762fc989267SStefano Zampini IS is; 2763fc989267SStefano Zampini 27649566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), A->cmap->N, 0, 1, &is)); 27659566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cmapping)); 27669566063dSJacob Faibussowitsch if (A->cmap->bs > 0) PetscCall(ISLocalToGlobalMappingSetBlockSize(cmapping, A->cmap->bs)); 27679566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2768e432b41dSStefano Zampini freem[1] = PETSC_TRUE; 2769e432b41dSStefano Zampini } else if (cmapping != rmapping && !is->islocalref) { /* check if the l2g map has negative or repeated entries */ 27709566063dSJacob Faibussowitsch PetscCall(MatISFilterL2GMap(A, cmapping, &is->cmapping, &localcmapping)); 2771e432b41dSStefano Zampini } 2772e432b41dSStefano Zampini if (!is->rmapping) { 27739566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)rmapping)); 2774e432b41dSStefano Zampini is->rmapping = rmapping; 2775e432b41dSStefano Zampini } 2776e432b41dSStefano Zampini if (!is->cmapping) { 27779566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)cmapping)); 2778e432b41dSStefano Zampini is->cmapping = cmapping; 2779fc989267SStefano Zampini } 2780fc989267SStefano Zampini 2781fc989267SStefano Zampini /* Clean up */ 27824f58015eSStefano Zampini is->lnnzstate = 0; 27834f58015eSStefano Zampini PetscCall(MatDestroy(&is->dA)); 27844f58015eSStefano Zampini PetscCall(MatDestroy(&is->assembledA)); 27859566063dSJacob Faibussowitsch PetscCall(MatDestroy(&is->A)); 2786872cf891SStefano Zampini if (is->csf != is->sf) { 27879566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&is->csf)); 27889566063dSJacob Faibussowitsch PetscCall(PetscFree2(is->csf_rootdata, is->csf_leafdata)); 2789f03112d0SStefano Zampini } else is->csf = NULL; 27909566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&is->sf)); 27919566063dSJacob Faibussowitsch PetscCall(PetscFree2(is->sf_rootdata, is->sf_leafdata)); 27929566063dSJacob Faibussowitsch PetscCall(PetscFree(is->bdiag)); 27933bbff08aSStefano Zampini 2794fc989267SStefano Zampini /* check if the two mappings are actually the same for square matrices since MATIS has some optimization for this case 2795fc989267SStefano Zampini (DOLFIN passes 2 different objects) */ 27969566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->rmapping, &nr)); 27979566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->rmapping, &rbs)); 27989566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->cmapping, &nc)); 27999566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->cmapping, &cbs)); 2800e432b41dSStefano Zampini if (is->rmapping != is->cmapping && cong) { 2801e432b41dSStefano Zampini PetscBool same = PETSC_FALSE; 28026625354bSStefano Zampini if (nr == nc && cbs == rbs) { 28036625354bSStefano Zampini const PetscInt *idxs1, *idxs2; 28046625354bSStefano Zampini 28059566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->rmapping, &idxs1)); 28069566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->cmapping, &idxs2)); 28079566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(idxs1, idxs2, nr / rbs, &same)); 28089566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->rmapping, &idxs1)); 28099566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->cmapping, &idxs2)); 28106625354bSStefano Zampini } 2811462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &same, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 2812e432b41dSStefano Zampini if (same) { 28139566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&is->cmapping)); 28149566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->rmapping)); 2815e432b41dSStefano Zampini is->cmapping = is->rmapping; 2816e432b41dSStefano Zampini } 28176625354bSStefano Zampini } 28189566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(A->rmap, rbs)); 28199566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(A->cmap, cbs)); 2820e432b41dSStefano Zampini /* Pass the user defined maps to the layout */ 28219566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetISLocalToGlobalMapping(A->rmap, rmapping)); 28229566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetISLocalToGlobalMapping(A->cmap, cmapping)); 28239566063dSJacob Faibussowitsch if (freem[0]) PetscCall(ISLocalToGlobalMappingDestroy(&rmapping)); 28249566063dSJacob Faibussowitsch if (freem[1]) PetscCall(ISLocalToGlobalMappingDestroy(&cmapping)); 28256625354bSStefano Zampini 28266625354bSStefano Zampini /* Create the local matrix A */ 28279566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &is->A)); 28289566063dSJacob Faibussowitsch PetscCall(MatSetType(is->A, is->lmattype)); 28299566063dSJacob Faibussowitsch PetscCall(MatSetSizes(is->A, nr, nc, nr, nc)); 28309566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(is->A, rbs, cbs)); 28319566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(is->A, "is_")); 28329566063dSJacob Faibussowitsch PetscCall(MatAppendOptionsPrefix(is->A, ((PetscObject)A)->prefix)); 28339566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(is->A->rmap)); 28349566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(is->A->cmap)); 28359566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(is->A, localrmapping, localcmapping)); 28369566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&localrmapping)); 28379566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&localcmapping)); 2838b4319ba4SBarry Smith 2839fc989267SStefano Zampini /* setup scatters and local vectors for MatMult */ 28409566063dSJacob Faibussowitsch if (!is->islocalref) PetscCall(MatISSetUpScatters_Private(A)); 2841fc989267SStefano Zampini A->preallocated = PETSC_TRUE; 28423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2843fc989267SStefano Zampini } 2844fc989267SStefano Zampini 2845d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetUp_IS(Mat A) 2846d71ae5a4SJacob Faibussowitsch { 2847fc989267SStefano Zampini ISLocalToGlobalMapping rmap, cmap; 2848fc989267SStefano Zampini 2849fc989267SStefano Zampini PetscFunctionBegin; 28509566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(A, &rmap, &cmap)); 285148a46eb9SPierre Jolivet if (!rmap && !cmap) PetscCall(MatSetLocalToGlobalMapping(A, NULL, NULL)); 28523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2853b4319ba4SBarry Smith } 2854b4319ba4SBarry Smith 2855d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) 2856d71ae5a4SJacob Faibussowitsch { 28572e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS *)mat->data; 2858f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION], cols_l[MATIS_MAX_ENTRIES_INSERTION]; 28592e74eeadSLisandro Dalcin 28602e74eeadSLisandro Dalcin PetscFunctionBegin; 28619566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(is->rmapping, IS_GTOLM_MASK, m, rows, &m, rows_l)); 2862e432b41dSStefano Zampini if (m != n || rows != cols || is->cmapping != is->rmapping) { 28639566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(is->cmapping, IS_GTOLM_MASK, n, cols, &n, cols_l)); 28649566063dSJacob Faibussowitsch PetscCall(MatSetValues(is->A, m, rows_l, n, cols_l, values, addv)); 2865e432b41dSStefano Zampini } else { 28669566063dSJacob Faibussowitsch PetscCall(MatSetValues(is->A, m, rows_l, m, rows_l, values, addv)); 2867e432b41dSStefano Zampini } 28683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 28692e74eeadSLisandro Dalcin } 28702e74eeadSLisandro Dalcin 2871d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) 2872d71ae5a4SJacob Faibussowitsch { 287397563a80SStefano Zampini Mat_IS *is = (Mat_IS *)mat->data; 2874f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION], cols_l[MATIS_MAX_ENTRIES_INSERTION]; 287597563a80SStefano Zampini 287697563a80SStefano Zampini PetscFunctionBegin; 28779566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(is->rmapping, IS_GTOLM_MASK, m, rows, &m, rows_l)); 2878e432b41dSStefano Zampini if (m != n || rows != cols || is->cmapping != is->rmapping) { 287984a95373SStefano Zampini PetscCall(ISGlobalToLocalMappingApplyBlock(is->cmapping, IS_GTOLM_MASK, n, cols, &n, cols_l)); 28809566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked(is->A, m, rows_l, n, cols_l, values, addv)); 2881e432b41dSStefano Zampini } else { 288284a95373SStefano Zampini PetscCall(MatSetValuesBlocked(is->A, m, rows_l, m, rows_l, values, addv)); 2883e432b41dSStefano Zampini } 28843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 288597563a80SStefano Zampini } 288697563a80SStefano Zampini 2887d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesLocal_IS(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) 2888d71ae5a4SJacob Faibussowitsch { 2889b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)A->data; 2890b4319ba4SBarry Smith 2891b4319ba4SBarry Smith PetscFunctionBegin; 2892e432b41dSStefano Zampini if (is->A->rmap->mapping || is->A->cmap->mapping) { 28939566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(is->A, m, rows, n, cols, values, addv)); 2894872cf891SStefano Zampini } else { 28959566063dSJacob Faibussowitsch PetscCall(MatSetValues(is->A, m, rows, n, cols, values, addv)); 2896872cf891SStefano Zampini } 28973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2898b4319ba4SBarry Smith } 2899b4319ba4SBarry Smith 2900d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) 2901d71ae5a4SJacob Faibussowitsch { 2902f0006bf2SLisandro Dalcin Mat_IS *is = (Mat_IS *)A->data; 2903f0006bf2SLisandro Dalcin 2904f0006bf2SLisandro Dalcin PetscFunctionBegin; 2905e432b41dSStefano Zampini if (is->A->rmap->mapping || is->A->cmap->mapping) { 29069566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlockedLocal(is->A, m, rows, n, cols, values, addv)); 2907b4f971dfSStefano Zampini } else { 29089566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked(is->A, m, rows, n, cols, values, addv)); 2909b4f971dfSStefano Zampini } 29103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2911f0006bf2SLisandro Dalcin } 2912f0006bf2SLisandro Dalcin 2913d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, PetscBool columns) 2914d71ae5a4SJacob Faibussowitsch { 2915f0ae7da4SStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 2916f0ae7da4SStefano Zampini 2917f0ae7da4SStefano Zampini PetscFunctionBegin; 2918f0ae7da4SStefano Zampini if (!n) { 2919f0ae7da4SStefano Zampini is->pure_neumann = PETSC_TRUE; 2920f0ae7da4SStefano Zampini } else { 2921f0ae7da4SStefano Zampini PetscInt i; 2922f0ae7da4SStefano Zampini is->pure_neumann = PETSC_FALSE; 2923f0ae7da4SStefano Zampini 2924f0ae7da4SStefano Zampini if (columns) { 29259566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns(is->A, n, rows, diag, NULL, NULL)); 2926f0ae7da4SStefano Zampini } else { 29279566063dSJacob Faibussowitsch PetscCall(MatZeroRows(is->A, n, rows, diag, NULL, NULL)); 2928f0ae7da4SStefano Zampini } 2929f0ae7da4SStefano Zampini if (diag != 0.) { 2930f0ae7da4SStefano Zampini const PetscScalar *array; 29319566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(is->counter, &array)); 293248a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(MatSetValue(is->A, rows[i], rows[i], diag / (array[rows[i]]), INSERT_VALUES)); 29339566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(is->counter, &array)); 2934f0ae7da4SStefano Zampini } 29359566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(is->A, MAT_FINAL_ASSEMBLY)); 29369566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(is->A, MAT_FINAL_ASSEMBLY)); 2937f0ae7da4SStefano Zampini } 29383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2939f0ae7da4SStefano Zampini } 2940f0ae7da4SStefano Zampini 2941d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, Vec x, Vec b, PetscBool columns) 2942d71ae5a4SJacob Faibussowitsch { 29436e520ac8SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 29446e520ac8SStefano Zampini PetscInt nr, nl, len, i; 29456e520ac8SStefano Zampini PetscInt *lrows; 29462e74eeadSLisandro Dalcin 29472e74eeadSLisandro Dalcin PetscFunctionBegin; 2948cf9c20a2SJed Brown if (PetscUnlikelyDebug(columns || diag != 0. || (x && b))) { 2949f0ae7da4SStefano Zampini PetscBool cong; 295026b0207aSStefano Zampini 29519566063dSJacob Faibussowitsch PetscCall(PetscLayoutCompare(A->rmap, A->cmap, &cong)); 295226b0207aSStefano Zampini cong = (PetscBool)(cong && matis->sf == matis->csf); 295308401ef6SPierre 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"); 2954aed4548fSBarry 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"); 2955aed4548fSBarry 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"); 2956f0ae7da4SStefano Zampini } 29576e520ac8SStefano Zampini /* get locally owned rows */ 29589566063dSJacob Faibussowitsch PetscCall(PetscLayoutMapLocal(A->rmap, n, rows, &len, &lrows, NULL)); 2959dd8e379bSPierre Jolivet /* fix right-hand side if needed */ 29606e520ac8SStefano Zampini if (x && b) { 29616e520ac8SStefano Zampini const PetscScalar *xx; 29626e520ac8SStefano Zampini PetscScalar *bb; 29636e520ac8SStefano Zampini 29649566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &xx)); 29659566063dSJacob Faibussowitsch PetscCall(VecGetArray(b, &bb)); 29666e520ac8SStefano Zampini for (i = 0; i < len; ++i) bb[lrows[i]] = diag * xx[lrows[i]]; 29679566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &xx)); 29689566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(b, &bb)); 29692e74eeadSLisandro Dalcin } 29706e520ac8SStefano Zampini /* get rows associated to the local matrices */ 29719566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, &nl, NULL)); 29729566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_leafdata, nl)); 29739566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata, A->rmap->n)); 29746e520ac8SStefano Zampini for (i = 0; i < len; i++) matis->sf_rootdata[lrows[i]] = 1; 29759566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 29769566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 29779566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 29789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl, &lrows)); 29799371c9d4SSatish Balay for (i = 0, nr = 0; i < nl; i++) 29809371c9d4SSatish Balay if (matis->sf_leafdata[i]) lrows[nr++] = i; 29819566063dSJacob Faibussowitsch PetscCall(MatISZeroRowsColumnsLocal_Private(A, nr, lrows, diag, columns)); 29829566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 2983d0dbe9f7SStefano Zampini PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 2984d0dbe9f7SStefano Zampini PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 29853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 29862e74eeadSLisandro Dalcin } 29872e74eeadSLisandro Dalcin 2988d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_IS(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 2989d71ae5a4SJacob Faibussowitsch { 2990b4319ba4SBarry Smith PetscFunctionBegin; 29919566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns_Private_IS(A, n, rows, diag, x, b, PETSC_FALSE)); 29923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2993f0ae7da4SStefano Zampini } 29942205254eSKarl Rupp 2995d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_IS(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 2996d71ae5a4SJacob Faibussowitsch { 2997f0ae7da4SStefano Zampini PetscFunctionBegin; 29989566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns_Private_IS(A, n, rows, diag, x, b, PETSC_TRUE)); 29993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3000b4319ba4SBarry Smith } 3001b4319ba4SBarry Smith 3002d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_IS(Mat A, MatAssemblyType type) 3003d71ae5a4SJacob Faibussowitsch { 3004b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)A->data; 3005b4319ba4SBarry Smith 3006b4319ba4SBarry Smith PetscFunctionBegin; 30079566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(is->A, type)); 30083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3009b4319ba4SBarry Smith } 3010b4319ba4SBarry Smith 3011d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_IS(Mat A, MatAssemblyType type) 3012d71ae5a4SJacob Faibussowitsch { 3013b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)A->data; 3014d0dbe9f7SStefano Zampini PetscBool lnnz; 3015b4319ba4SBarry Smith 3016b4319ba4SBarry Smith PetscFunctionBegin; 30179566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(is->A, type)); 3018872cf891SStefano Zampini /* fix for local empty rows/cols */ 3019872cf891SStefano Zampini if (is->locempty && type == MAT_FINAL_ASSEMBLY) { 3020872cf891SStefano Zampini Mat newlA; 3021f03112d0SStefano Zampini ISLocalToGlobalMapping rl2g, cl2g; 3022f03112d0SStefano Zampini IS nzr, nzc; 3023f03112d0SStefano Zampini PetscInt nr, nc, nnzr, nnzc; 3024f03112d0SStefano Zampini PetscBool lnewl2g, newl2g; 3025872cf891SStefano Zampini 30269566063dSJacob Faibussowitsch PetscCall(MatGetSize(is->A, &nr, &nc)); 30279566063dSJacob Faibussowitsch PetscCall(MatFindNonzeroRowsOrCols_Basic(is->A, PETSC_FALSE, PETSC_SMALL, &nzr)); 302848a46eb9SPierre Jolivet if (!nzr) PetscCall(ISCreateStride(PetscObjectComm((PetscObject)is->A), nr, 0, 1, &nzr)); 30299566063dSJacob Faibussowitsch PetscCall(MatFindNonzeroRowsOrCols_Basic(is->A, PETSC_TRUE, PETSC_SMALL, &nzc)); 303048a46eb9SPierre Jolivet if (!nzc) PetscCall(ISCreateStride(PetscObjectComm((PetscObject)is->A), nc, 0, 1, &nzc)); 30319566063dSJacob Faibussowitsch PetscCall(ISGetSize(nzr, &nnzr)); 30329566063dSJacob Faibussowitsch PetscCall(ISGetSize(nzc, &nnzc)); 3033e432b41dSStefano Zampini if (nnzr != nr || nnzc != nc) { /* need new global l2g map */ 3034f03112d0SStefano Zampini lnewl2g = PETSC_TRUE; 3035462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&lnewl2g, &newl2g, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A))); 3036f03112d0SStefano Zampini 3037872cf891SStefano Zampini /* extract valid submatrix */ 30389566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(is->A, nzr, nzc, MAT_INITIAL_MATRIX, &newlA)); 3039f03112d0SStefano Zampini } else { /* local matrix fully populated */ 3040f03112d0SStefano Zampini lnewl2g = PETSC_FALSE; 3041462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&lnewl2g, &newl2g, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A))); 30429566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->A)); 3043f03112d0SStefano Zampini newlA = is->A; 3044f03112d0SStefano Zampini } 3045e432b41dSStefano Zampini 3046f03112d0SStefano Zampini /* attach new global l2g map if needed */ 3047f03112d0SStefano Zampini if (newl2g) { 3048e432b41dSStefano Zampini IS zr, zc; 3049e432b41dSStefano Zampini const PetscInt *ridxs, *cidxs, *zridxs, *zcidxs; 3050e432b41dSStefano Zampini PetscInt *nidxs, i; 3051f03112d0SStefano Zampini 30529566063dSJacob Faibussowitsch PetscCall(ISComplement(nzr, 0, nr, &zr)); 30539566063dSJacob Faibussowitsch PetscCall(ISComplement(nzc, 0, nc, &zc)); 30549566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(PetscMax(nr, nc), &nidxs)); 30559566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(is->rmapping, &ridxs)); 30569566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(is->cmapping, &cidxs)); 30579566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zr, &zridxs)); 30589566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zc, &zcidxs)); 30599566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zr, &nnzr)); 30609566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zc, &nnzc)); 3061e432b41dSStefano Zampini 30629566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(nidxs, ridxs, nr)); 3063e432b41dSStefano Zampini for (i = 0; i < nnzr; i++) nidxs[zridxs[i]] = -1; 30649566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A), 1, nr, nidxs, PETSC_COPY_VALUES, &rl2g)); 30659566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(nidxs, cidxs, nc)); 3066e432b41dSStefano Zampini for (i = 0; i < nnzc; i++) nidxs[zcidxs[i]] = -1; 30679566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A), 1, nc, nidxs, PETSC_COPY_VALUES, &cl2g)); 3068e432b41dSStefano Zampini 30699566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zr, &zridxs)); 30709566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zc, &zcidxs)); 30719566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(is->rmapping, &ridxs)); 30729566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(is->cmapping, &cidxs)); 30739566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzr)); 30749566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzc)); 30759566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zr)); 30769566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zc)); 30779566063dSJacob Faibussowitsch PetscCall(PetscFree(nidxs)); 30789566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(A, rl2g, cl2g)); 30799566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 30809566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 3081f03112d0SStefano Zampini } 30829566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(A, newlA)); 30839566063dSJacob Faibussowitsch PetscCall(MatDestroy(&newlA)); 30849566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzr)); 30859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzc)); 3086872cf891SStefano Zampini is->locempty = PETSC_FALSE; 3087f03112d0SStefano Zampini } 3088d0dbe9f7SStefano Zampini lnnz = (PetscBool)(is->A->nonzerostate == is->lnnzstate); 3089d0dbe9f7SStefano Zampini is->lnnzstate = is->A->nonzerostate; 3090462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &lnnz, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 30914f58015eSStefano Zampini if (!lnnz) A->nonzerostate++; 30923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3093b4319ba4SBarry Smith } 3094b4319ba4SBarry Smith 3095d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISGetLocalMat_IS(Mat mat, Mat *local) 3096d71ae5a4SJacob Faibussowitsch { 3097b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)mat->data; 3098b4319ba4SBarry Smith 3099b4319ba4SBarry Smith PetscFunctionBegin; 3100b4319ba4SBarry Smith *local = is->A; 31013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3102b4319ba4SBarry Smith } 3103b4319ba4SBarry Smith 3104d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat, Mat *local) 3105d71ae5a4SJacob Faibussowitsch { 31063b3b1effSJed Brown PetscFunctionBegin; 31073b3b1effSJed Brown *local = NULL; 31083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31093b3b1effSJed Brown } 31103b3b1effSJed Brown 3111b4319ba4SBarry Smith /*@ 311211a5261eSBarry Smith MatISGetLocalMat - Gets the local matrix stored inside a `MATIS` matrix. 3113b4319ba4SBarry Smith 31144f58015eSStefano Zampini Not Collective. 31154f58015eSStefano Zampini 3116b4319ba4SBarry Smith Input Parameter: 3117b4319ba4SBarry Smith . mat - the matrix 3118b4319ba4SBarry Smith 3119b4319ba4SBarry Smith Output Parameter: 3120eb82efa4SStefano Zampini . local - the local matrix 3121b4319ba4SBarry Smith 31224f58015eSStefano Zampini Level: intermediate 3123b4319ba4SBarry Smith 3124b4319ba4SBarry Smith Notes: 3125b4319ba4SBarry Smith This can be called if you have precomputed the nonzero structure of the 3126b4319ba4SBarry Smith matrix and want to provide it to the inner matrix object to improve the performance 312711a5261eSBarry Smith of the `MatSetValues()` operation. 3128b4319ba4SBarry Smith 312911a5261eSBarry Smith Call `MatISRestoreLocalMat()` when finished with the local matrix. 313096a6f129SJed Brown 31311cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatISRestoreLocalMat()` 3132b4319ba4SBarry Smith @*/ 3133d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISGetLocalMat(Mat mat, Mat *local) 3134d71ae5a4SJacob Faibussowitsch { 3135b4319ba4SBarry Smith PetscFunctionBegin; 31360700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 31374f572ea9SToby Isaac PetscAssertPointer(local, 2); 3138cac4c232SBarry Smith PetscUseMethod(mat, "MatISGetLocalMat_C", (Mat, Mat *), (mat, local)); 31393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3140b4319ba4SBarry Smith } 3141b4319ba4SBarry Smith 31423b3b1effSJed Brown /*@ 314311a5261eSBarry Smith MatISRestoreLocalMat - Restores the local matrix obtained with `MatISGetLocalMat()` 31443b3b1effSJed Brown 31454f58015eSStefano Zampini Not Collective. 31464f58015eSStefano Zampini 31472ef1f0ffSBarry Smith Input Parameters: 31482ef1f0ffSBarry Smith + mat - the matrix 31492ef1f0ffSBarry Smith - local - the local matrix 31503b3b1effSJed Brown 31514f58015eSStefano Zampini Level: intermediate 31523b3b1effSJed Brown 31531cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatISGetLocalMat()` 31543b3b1effSJed Brown @*/ 3155d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISRestoreLocalMat(Mat mat, Mat *local) 3156d71ae5a4SJacob Faibussowitsch { 31573b3b1effSJed Brown PetscFunctionBegin; 31583b3b1effSJed Brown PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 31594f572ea9SToby Isaac PetscAssertPointer(local, 2); 3160cac4c232SBarry Smith PetscUseMethod(mat, "MatISRestoreLocalMat_C", (Mat, Mat *), (mat, local)); 31613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31623b3b1effSJed Brown } 31633b3b1effSJed Brown 3164d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISSetLocalMatType_IS(Mat mat, MatType mtype) 3165d71ae5a4SJacob Faibussowitsch { 31668546b261SStefano Zampini Mat_IS *is = (Mat_IS *)mat->data; 31678546b261SStefano Zampini 31688546b261SStefano Zampini PetscFunctionBegin; 31691baa6e33SBarry Smith if (is->A) PetscCall(MatSetType(is->A, mtype)); 31709566063dSJacob Faibussowitsch PetscCall(PetscFree(is->lmattype)); 31719566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(mtype, &is->lmattype)); 31723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31738546b261SStefano Zampini } 31748546b261SStefano Zampini 31755d83a8b1SBarry Smith /*@ 317611a5261eSBarry Smith MatISSetLocalMatType - Specifies the type of local matrix inside the `MATIS` 31778546b261SStefano Zampini 31784f58015eSStefano Zampini Logically Collective. 31794f58015eSStefano Zampini 3180d8d19677SJose E. Roman Input Parameters: 3181a2b725a8SWilliam Gropp + mat - the matrix 3182a2b725a8SWilliam Gropp - mtype - the local matrix type 31838546b261SStefano Zampini 31844f58015eSStefano Zampini Level: intermediate 31858546b261SStefano Zampini 31861cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatSetType()`, `MatType` 31878546b261SStefano Zampini @*/ 3188d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISSetLocalMatType(Mat mat, MatType mtype) 3189d71ae5a4SJacob Faibussowitsch { 31908546b261SStefano Zampini PetscFunctionBegin; 31918546b261SStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3192cac4c232SBarry Smith PetscUseMethod(mat, "MatISSetLocalMatType_C", (Mat, MatType), (mat, mtype)); 31933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31948546b261SStefano Zampini } 31958546b261SStefano Zampini 3196d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISSetLocalMat_IS(Mat mat, Mat local) 3197d71ae5a4SJacob Faibussowitsch { 31983b03a366Sstefano_zampini Mat_IS *is = (Mat_IS *)mat->data; 31993b03a366Sstefano_zampini PetscInt nrows, ncols, orows, ocols; 32008546b261SStefano Zampini MatType mtype, otype; 32018546b261SStefano Zampini PetscBool sametype = PETSC_TRUE; 32023b03a366Sstefano_zampini 32033b03a366Sstefano_zampini PetscFunctionBegin; 3204e432b41dSStefano Zampini if (is->A && !is->islocalref) { 32059566063dSJacob Faibussowitsch PetscCall(MatGetSize(is->A, &orows, &ocols)); 32069566063dSJacob Faibussowitsch PetscCall(MatGetSize(local, &nrows, &ncols)); 32075042aa92SStefano 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); 32089566063dSJacob Faibussowitsch PetscCall(MatGetType(local, &mtype)); 32099566063dSJacob Faibussowitsch PetscCall(MatGetType(is->A, &otype)); 32109566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, otype, &sametype)); 32114e4c7dbeSStefano Zampini } 32129566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)local)); 32139566063dSJacob Faibussowitsch PetscCall(MatDestroy(&is->A)); 32143b03a366Sstefano_zampini is->A = local; 32159566063dSJacob Faibussowitsch PetscCall(MatGetType(is->A, &mtype)); 32169566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(mat, mtype)); 321748a46eb9SPierre Jolivet if (!sametype && !is->islocalref) PetscCall(MatISSetUpScatters_Private(mat)); 32184f58015eSStefano Zampini is->lnnzstate = 0; 32193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32203b03a366Sstefano_zampini } 32213b03a366Sstefano_zampini 32223b03a366Sstefano_zampini /*@ 322311a5261eSBarry Smith MatISSetLocalMat - Replace the local matrix stored inside a `MATIS` object. 32243b03a366Sstefano_zampini 32254f58015eSStefano Zampini Not Collective 32268546b261SStefano Zampini 3227d8d19677SJose E. Roman Input Parameters: 3228a2b725a8SWilliam Gropp + mat - the matrix 3229a2b725a8SWilliam Gropp - local - the local matrix 32303b03a366Sstefano_zampini 32314f58015eSStefano Zampini Level: intermediate 323211a5261eSBarry Smith 32331cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatISSetLocalMatType`, `MatISGetLocalMat()` 32343b03a366Sstefano_zampini @*/ 3235d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISSetLocalMat(Mat mat, Mat local) 3236d71ae5a4SJacob Faibussowitsch { 32373b03a366Sstefano_zampini PetscFunctionBegin; 32383b03a366Sstefano_zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3239b7ce53b6SStefano Zampini PetscValidHeaderSpecific(local, MAT_CLASSID, 2); 3240cac4c232SBarry Smith PetscUseMethod(mat, "MatISSetLocalMat_C", (Mat, Mat), (mat, local)); 32413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32423b03a366Sstefano_zampini } 32433b03a366Sstefano_zampini 3244d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroEntries_IS(Mat A) 3245d71ae5a4SJacob Faibussowitsch { 32466726f965SBarry Smith Mat_IS *a = (Mat_IS *)A->data; 32476726f965SBarry Smith 32486726f965SBarry Smith PetscFunctionBegin; 32499566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(a->A)); 32503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32516726f965SBarry Smith } 32526726f965SBarry Smith 3253d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatScale_IS(Mat A, PetscScalar a) 3254d71ae5a4SJacob Faibussowitsch { 32552e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS *)A->data; 32562e74eeadSLisandro Dalcin 32572e74eeadSLisandro Dalcin PetscFunctionBegin; 32589566063dSJacob Faibussowitsch PetscCall(MatScale(is->A, a)); 32593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32602e74eeadSLisandro Dalcin } 32612e74eeadSLisandro Dalcin 3262d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v) 3263d71ae5a4SJacob Faibussowitsch { 32642e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS *)A->data; 32652e74eeadSLisandro Dalcin 32662e74eeadSLisandro Dalcin PetscFunctionBegin; 32672e74eeadSLisandro Dalcin /* get diagonal of the local matrix */ 32689566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(is->A, is->y)); 32692e74eeadSLisandro Dalcin 32702e74eeadSLisandro Dalcin /* scatter diagonal back into global vector */ 32719566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0)); 32729566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, is->y, v, ADD_VALUES, SCATTER_REVERSE)); 32739566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, is->y, v, ADD_VALUES, SCATTER_REVERSE)); 32743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32752e74eeadSLisandro Dalcin } 32762e74eeadSLisandro Dalcin 3277d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_IS(Mat A, MatOption op, PetscBool flg) 3278d71ae5a4SJacob Faibussowitsch { 32796726f965SBarry Smith Mat_IS *a = (Mat_IS *)A->data; 32806726f965SBarry Smith 32816726f965SBarry Smith PetscFunctionBegin; 32829566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg)); 32833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32846726f965SBarry Smith } 32856726f965SBarry Smith 3286d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAXPY_IS(Mat Y, PetscScalar a, Mat X, MatStructure str) 3287d71ae5a4SJacob Faibussowitsch { 3288f26d0771SStefano Zampini Mat_IS *y = (Mat_IS *)Y->data; 3289f26d0771SStefano Zampini Mat_IS *x; 3290f26d0771SStefano Zampini 3291f26d0771SStefano Zampini PetscFunctionBegin; 329276bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 329376bd3646SJed Brown PetscBool ismatis; 32949566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)X, MATIS, &ismatis)); 329528b400f6SJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)Y), PETSC_ERR_SUP, "Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS"); 329676bd3646SJed Brown } 3297f26d0771SStefano Zampini x = (Mat_IS *)X->data; 32989566063dSJacob Faibussowitsch PetscCall(MatAXPY(y->A, a, x->A, str)); 32993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3300f26d0771SStefano Zampini } 3301f26d0771SStefano Zampini 3302d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A, IS row, IS col, Mat *submat) 3303d71ae5a4SJacob Faibussowitsch { 3304f26d0771SStefano Zampini Mat lA; 3305f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)A->data; 3306f26d0771SStefano Zampini ISLocalToGlobalMapping rl2g, cl2g; 3307f26d0771SStefano Zampini IS is; 3308f26d0771SStefano Zampini const PetscInt *rg, *rl; 3309f26d0771SStefano Zampini PetscInt nrg; 3310f26d0771SStefano Zampini PetscInt N, M, nrl, i, *idxs; 3311f26d0771SStefano Zampini 3312f26d0771SStefano Zampini PetscFunctionBegin; 33139566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(A->rmap->mapping, &rg)); 33149566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(row, &nrl)); 33159566063dSJacob Faibussowitsch PetscCall(ISGetIndices(row, &rl)); 33169566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(A->rmap->mapping, &nrg)); 331776bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 331808401ef6SPierre Jolivet for (i = 0; i < nrl; i++) PetscCheck(rl[i] < nrg, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Local row index %" PetscInt_FMT " -> %" PetscInt_FMT " greater then maximum possible %" PetscInt_FMT, i, rl[i], nrg); 331976bd3646SJed Brown } 33209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nrg, &idxs)); 3321f26d0771SStefano Zampini /* map from [0,nrl) to row */ 3322f26d0771SStefano Zampini for (i = 0; i < nrl; i++) idxs[i] = rl[i]; 3323f26d0771SStefano Zampini for (i = nrl; i < nrg; i++) idxs[i] = -1; 33249566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(row, &rl)); 33259566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping, &rg)); 33269566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A), nrg, idxs, PETSC_OWN_POINTER, &is)); 33279566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g)); 33289566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3329f26d0771SStefano Zampini /* compute new l2g map for columns */ 3330e432b41dSStefano Zampini if (col != row || matis->rmapping != matis->cmapping || matis->A->rmap->mapping != matis->A->cmap->mapping) { 3331f26d0771SStefano Zampini const PetscInt *cg, *cl; 3332f26d0771SStefano Zampini PetscInt ncg; 3333f26d0771SStefano Zampini PetscInt ncl; 3334f26d0771SStefano Zampini 33359566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(A->cmap->mapping, &cg)); 33369566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(col, &ncl)); 33379566063dSJacob Faibussowitsch PetscCall(ISGetIndices(col, &cl)); 33389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(A->cmap->mapping, &ncg)); 333976bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 334008401ef6SPierre Jolivet for (i = 0; i < ncl; i++) PetscCheck(cl[i] < ncg, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Local column index %" PetscInt_FMT " -> %" PetscInt_FMT " greater then maximum possible %" PetscInt_FMT, i, cl[i], ncg); 334176bd3646SJed Brown } 33429566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncg, &idxs)); 3343f26d0771SStefano Zampini /* map from [0,ncl) to col */ 3344f26d0771SStefano Zampini for (i = 0; i < ncl; i++) idxs[i] = cl[i]; 3345f26d0771SStefano Zampini for (i = ncl; i < ncg; i++) idxs[i] = -1; 33469566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(col, &cl)); 33479566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping, &cg)); 33489566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A), ncg, idxs, PETSC_OWN_POINTER, &is)); 33499566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g)); 33509566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3351f26d0771SStefano Zampini } else { 33529566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)rl2g)); 3353f26d0771SStefano Zampini cl2g = rl2g; 3354f26d0771SStefano Zampini } 3355f26d0771SStefano Zampini /* create the MATIS submatrix */ 33569566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, &N)); 33579566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), submat)); 33589566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*submat, PETSC_DECIDE, PETSC_DECIDE, M, N)); 33599566063dSJacob Faibussowitsch PetscCall(MatSetType(*submat, MATIS)); 3360b0aa3428SStefano Zampini matis = (Mat_IS *)((*submat)->data); 3361f26d0771SStefano Zampini matis->islocalref = PETSC_TRUE; 33629566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*submat, rl2g, cl2g)); 33639566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A, &lA)); 33649566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*submat, lA)); 33659566063dSJacob Faibussowitsch PetscCall(MatSetUp(*submat)); 33669566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*submat, MAT_FINAL_ASSEMBLY)); 33679566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*submat, MAT_FINAL_ASSEMBLY)); 33689566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 33699566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 3370e432b41dSStefano Zampini 3371f26d0771SStefano Zampini /* remove unsupported ops */ 33729566063dSJacob Faibussowitsch PetscCall(PetscMemzero((*submat)->ops, sizeof(struct _MatOps))); 3373f26d0771SStefano Zampini (*submat)->ops->destroy = MatDestroy_IS; 3374f26d0771SStefano Zampini (*submat)->ops->setvalueslocal = MatSetValuesLocal_SubMat_IS; 3375f26d0771SStefano Zampini (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS; 3376f26d0771SStefano Zampini (*submat)->ops->assemblybegin = MatAssemblyBegin_IS; 3377f26d0771SStefano Zampini (*submat)->ops->assemblyend = MatAssemblyEnd_IS; 33783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3379f26d0771SStefano Zampini } 3380f26d0771SStefano Zampini 3381d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetFromOptions_IS(Mat A, PetscOptionItems *PetscOptionsObject) 3382d71ae5a4SJacob Faibussowitsch { 3383872cf891SStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 33848546b261SStefano Zampini char type[256]; 33858546b261SStefano Zampini PetscBool flg; 3386872cf891SStefano Zampini 3387872cf891SStefano Zampini PetscFunctionBegin; 3388d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "MATIS options"); 33894f58015eSStefano Zampini PetscCall(PetscOptionsDeprecated("-matis_keepassembled", "-mat_is_keepassembled", "3.21", NULL)); 33904f58015eSStefano Zampini PetscCall(PetscOptionsDeprecated("-matis_fixempty", "-mat_is_fixempty", "3.21", NULL)); 33914f58015eSStefano Zampini PetscCall(PetscOptionsDeprecated("-matis_storel2l", "-mat_is_storel2l", "3.21", NULL)); 33924f58015eSStefano Zampini PetscCall(PetscOptionsDeprecated("-matis_localmat_type", "-mat_is_localmat_type", "3.21", NULL)); 33934f58015eSStefano Zampini PetscCall(PetscOptionsBool("-mat_is_keepassembled", "Store an assembled version if needed", NULL, a->keepassembled, &a->keepassembled, NULL)); 33944f58015eSStefano Zampini PetscCall(PetscOptionsBool("-mat_is_fixempty", "Fix local matrices in case of empty local rows/columns", "MatISFixLocalEmpty", a->locempty, &a->locempty, NULL)); 33954f58015eSStefano Zampini PetscCall(PetscOptionsBool("-mat_is_storel2l", "Store local-to-local matrices generated from PtAP operations", "MatISStoreL2L", a->storel2l, &a->storel2l, NULL)); 33964f58015eSStefano Zampini PetscCall(PetscOptionsBool("-mat_is_allow_repeated", "Allow local repeated entries", "MatISSetAllowRepeated", a->allow_repeated, &a->allow_repeated, NULL)); 33974f58015eSStefano Zampini PetscCall(PetscOptionsFList("-mat_is_localmat_type", "Matrix type", "MatISSetLocalMatType", MatList, a->lmattype, type, 256, &flg)); 33981baa6e33SBarry Smith if (flg) PetscCall(MatISSetLocalMatType(A, type)); 33991baa6e33SBarry Smith if (a->A) PetscCall(MatSetFromOptions(a->A)); 3400d0609cedSBarry Smith PetscOptionsHeadEnd(); 34013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3402872cf891SStefano Zampini } 3403872cf891SStefano Zampini 3404284134d9SBarry Smith /*@ 34054f58015eSStefano Zampini MatCreateIS - Creates a "process" unassembled matrix. 34064f58015eSStefano Zampini 34074f58015eSStefano Zampini Collective. 3408284134d9SBarry Smith 3409284134d9SBarry Smith Input Parameters: 3410284134d9SBarry Smith + comm - MPI communicator that will share the matrix 3411e176bc59SStefano Zampini . bs - block size of the matrix 34122920cce0SJacob Faibussowitsch . m - local size of left vector used in matrix vector products 34132920cce0SJacob Faibussowitsch . n - local size of right vector used in matrix vector products 34142920cce0SJacob Faibussowitsch . M - global size of left vector used in matrix vector products 34152920cce0SJacob Faibussowitsch . N - global size of right vector used in matrix vector products 3416e176bc59SStefano Zampini . rmap - local to global map for rows 3417e176bc59SStefano Zampini - cmap - local to global map for cols 3418284134d9SBarry Smith 3419284134d9SBarry Smith Output Parameter: 3420284134d9SBarry Smith . A - the resulting matrix 3421284134d9SBarry Smith 34224f58015eSStefano Zampini Level: intermediate 34238e6c10adSSatish Balay 342495452b02SPatrick Sanan Notes: 34252ef1f0ffSBarry 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 34264f58015eSStefano Zampini used in `MatMult()` operations. The local sizes of `rmap` and `cmap` define the size of the local matrices. 342711a5261eSBarry Smith 34282ef1f0ffSBarry Smith If `rmap` (`cmap`) is `NULL`, then the local row (column) spaces matches the global space. 3429284134d9SBarry Smith 34301cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatSetLocalToGlobalMapping()` 3431284134d9SBarry Smith @*/ 3432d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateIS(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt M, PetscInt N, ISLocalToGlobalMapping rmap, ISLocalToGlobalMapping cmap, Mat *A) 3433d71ae5a4SJacob Faibussowitsch { 3434284134d9SBarry Smith PetscFunctionBegin; 34359566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, A)); 34369566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A, m, n, M, N)); 343748a46eb9SPierre Jolivet if (bs > 0) PetscCall(MatSetBlockSize(*A, bs)); 34389566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATIS)); 34399566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*A, rmap, cmap)); 34403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3441284134d9SBarry Smith } 3442284134d9SBarry Smith 3443d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHasOperation_IS(Mat A, MatOperation op, PetscBool *has) 3444d71ae5a4SJacob Faibussowitsch { 34458b9382cfSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3446e26763e4SStefano Zampini MatOperation tobefiltered[] = {MATOP_MULT_ADD, MATOP_MULT_TRANSPOSE_ADD, MATOP_GET_DIAGONAL_BLOCK, MATOP_INCREASE_OVERLAP}; 34478b9382cfSStefano Zampini 34488b9382cfSStefano Zampini PetscFunctionBegin; 34498b9382cfSStefano Zampini *has = PETSC_FALSE; 34503ba16761SJacob Faibussowitsch if (!((void **)A->ops)[op] || !a->A) PetscFunctionReturn(PETSC_SUCCESS); 3451d0dbe9f7SStefano Zampini *has = PETSC_TRUE; 34529371c9d4SSatish Balay for (PetscInt i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(tobefiltered); i++) 34533ba16761SJacob Faibussowitsch if (op == tobefiltered[i]) PetscFunctionReturn(PETSC_SUCCESS); 34549566063dSJacob Faibussowitsch PetscCall(MatHasOperation(a->A, op, has)); 34553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34568b9382cfSStefano Zampini } 34578b9382cfSStefano Zampini 3458d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesCOO_IS(Mat A, const PetscScalar v[], InsertMode imode) 3459d71ae5a4SJacob Faibussowitsch { 3460e432b41dSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3461e432b41dSStefano Zampini 3462e432b41dSStefano Zampini PetscFunctionBegin; 34639566063dSJacob Faibussowitsch PetscCall(MatSetValuesCOO(a->A, v, imode)); 34649566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 34659566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 34663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3467e432b41dSStefano Zampini } 3468e432b41dSStefano Zampini 3469d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetPreallocationCOOLocal_IS(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[]) 3470d71ae5a4SJacob Faibussowitsch { 3471e432b41dSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3472e432b41dSStefano Zampini 3473e432b41dSStefano Zampini PetscFunctionBegin; 3474e432b41dSStefano Zampini PetscCheck(a->A, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Need to provide l2g map first via MatSetLocalToGlobalMapping"); 3475e432b41dSStefano Zampini if (a->A->rmap->mapping || a->A->cmap->mapping) { 34769566063dSJacob Faibussowitsch PetscCall(MatSetPreallocationCOOLocal(a->A, ncoo, coo_i, coo_j)); 3477e432b41dSStefano Zampini } else { 34789566063dSJacob Faibussowitsch PetscCall(MatSetPreallocationCOO(a->A, ncoo, coo_i, coo_j)); 3479e432b41dSStefano Zampini } 34809566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", MatSetValuesCOO_IS)); 3481e432b41dSStefano Zampini A->preallocated = PETSC_TRUE; 34823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3483e432b41dSStefano Zampini } 3484e432b41dSStefano Zampini 3485d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetPreallocationCOO_IS(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[]) 3486d71ae5a4SJacob Faibussowitsch { 3487e432b41dSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3488e432b41dSStefano Zampini 3489e432b41dSStefano Zampini PetscFunctionBegin; 3490e432b41dSStefano Zampini PetscCheck(a->A, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Need to provide l2g map first via MatSetLocalToGlobalMapping"); 34911690c2aeSBarry Smith PetscCheck(ncoo <= PETSC_INT_MAX, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "ncoo %" PetscCount_FMT " overflowed PetscInt; configure --with-64-bit-indices or request support", ncoo); 34926497c311SBarry Smith PetscCall(ISGlobalToLocalMappingApply(a->rmapping, IS_GTOLM_MASK, (PetscInt)ncoo, coo_i, NULL, coo_i)); 34936497c311SBarry Smith PetscCall(ISGlobalToLocalMappingApply(a->cmapping, IS_GTOLM_MASK, (PetscInt)ncoo, coo_j, NULL, coo_j)); 3494e8729f6fSJunchao Zhang PetscCall(MatSetPreallocationCOO(a->A, ncoo, coo_i, coo_j)); 34959566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", MatSetValuesCOO_IS)); 3496e432b41dSStefano Zampini A->preallocated = PETSC_TRUE; 34973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3498e432b41dSStefano Zampini } 3499e432b41dSStefano Zampini 3500d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISGetAssembled_Private(Mat A, Mat *tA) 3501d71ae5a4SJacob Faibussowitsch { 3502d0dbe9f7SStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 35031690c2aeSBarry Smith PetscObjectState Astate, aAstate = PETSC_INT_MIN; 35041690c2aeSBarry Smith PetscObjectState Annzstate, aAnnzstate = PETSC_INT_MIN; 3505d0dbe9f7SStefano Zampini 3506d0dbe9f7SStefano Zampini PetscFunctionBegin; 3507d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateGet((PetscObject)A, &Astate)); 3508d0dbe9f7SStefano Zampini Annzstate = A->nonzerostate; 3509d0dbe9f7SStefano Zampini if (a->assembledA) { 3510d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateGet((PetscObject)a->assembledA, &aAstate)); 3511d0dbe9f7SStefano Zampini aAnnzstate = a->assembledA->nonzerostate; 3512d0dbe9f7SStefano Zampini } 3513d0dbe9f7SStefano Zampini if (aAnnzstate != Annzstate) PetscCall(MatDestroy(&a->assembledA)); 3514d0dbe9f7SStefano Zampini if (Astate != aAstate || !a->assembledA) { 3515d0dbe9f7SStefano Zampini MatType aAtype; 3516d0dbe9f7SStefano Zampini PetscMPIInt size; 3517d0dbe9f7SStefano Zampini PetscInt rbs, cbs, bs; 3518d0dbe9f7SStefano Zampini 3519d0dbe9f7SStefano Zampini /* the assembled form is used as temporary storage for parallel operations 3520d0dbe9f7SStefano Zampini like createsubmatrices and the like, do not waste device memory */ 3521d0dbe9f7SStefano Zampini PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 3522d0dbe9f7SStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockSize(a->cmapping, &cbs)); 3523d0dbe9f7SStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockSize(a->rmapping, &rbs)); 3524d0dbe9f7SStefano Zampini bs = rbs == cbs ? rbs : 1; 3525d0dbe9f7SStefano Zampini if (a->assembledA) PetscCall(MatGetType(a->assembledA, &aAtype)); 3526d0dbe9f7SStefano Zampini else if (size > 1) aAtype = bs > 1 ? MATMPIBAIJ : MATMPIAIJ; 3527d0dbe9f7SStefano Zampini else aAtype = bs > 1 ? MATSEQBAIJ : MATSEQAIJ; 3528d0dbe9f7SStefano Zampini 3529d0dbe9f7SStefano Zampini PetscCall(MatConvert(A, aAtype, a->assembledA ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX, &a->assembledA)); 3530d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateSet((PetscObject)a->assembledA, Astate)); 3531d0dbe9f7SStefano Zampini a->assembledA->nonzerostate = Annzstate; 3532d0dbe9f7SStefano Zampini } 3533d0dbe9f7SStefano Zampini PetscCall(PetscObjectReference((PetscObject)a->assembledA)); 3534d0dbe9f7SStefano Zampini *tA = a->assembledA; 3535d0dbe9f7SStefano Zampini if (!a->keepassembled) PetscCall(MatDestroy(&a->assembledA)); 35363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3537d0dbe9f7SStefano Zampini } 3538d0dbe9f7SStefano Zampini 3539d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISRestoreAssembled_Private(Mat A, Mat *tA) 3540d71ae5a4SJacob Faibussowitsch { 3541d0dbe9f7SStefano Zampini PetscFunctionBegin; 3542d0dbe9f7SStefano Zampini PetscCall(MatDestroy(tA)); 3543d0dbe9f7SStefano Zampini *tA = NULL; 35443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3545d0dbe9f7SStefano Zampini } 3546d0dbe9f7SStefano Zampini 3547d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonalBlock_IS(Mat A, Mat *dA) 3548d71ae5a4SJacob Faibussowitsch { 3549d0dbe9f7SStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 35501690c2aeSBarry Smith PetscObjectState Astate, dAstate = PETSC_INT_MIN; 3551d0dbe9f7SStefano Zampini 3552d0dbe9f7SStefano Zampini PetscFunctionBegin; 3553d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateGet((PetscObject)A, &Astate)); 3554d0dbe9f7SStefano Zampini if (a->dA) PetscCall(PetscObjectStateGet((PetscObject)a->dA, &dAstate)); 3555d0dbe9f7SStefano Zampini if (Astate != dAstate) { 3556d0dbe9f7SStefano Zampini Mat tA; 3557d0dbe9f7SStefano Zampini MatType ltype; 3558d0dbe9f7SStefano Zampini 3559d0dbe9f7SStefano Zampini PetscCall(MatDestroy(&a->dA)); 3560d0dbe9f7SStefano Zampini PetscCall(MatISGetAssembled_Private(A, &tA)); 3561d0dbe9f7SStefano Zampini PetscCall(MatGetDiagonalBlock(tA, &a->dA)); 3562d0dbe9f7SStefano Zampini PetscCall(MatPropagateSymmetryOptions(tA, a->dA)); 3563d0dbe9f7SStefano Zampini PetscCall(MatGetType(a->A, <ype)); 3564d0dbe9f7SStefano Zampini PetscCall(MatConvert(a->dA, ltype, MAT_INPLACE_MATRIX, &a->dA)); 3565d0dbe9f7SStefano Zampini PetscCall(PetscObjectReference((PetscObject)a->dA)); 3566d0dbe9f7SStefano Zampini PetscCall(MatISRestoreAssembled_Private(A, &tA)); 3567d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateSet((PetscObject)a->dA, Astate)); 3568d0dbe9f7SStefano Zampini } 3569d0dbe9f7SStefano Zampini *dA = a->dA; 35703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3571d0dbe9f7SStefano Zampini } 3572d0dbe9f7SStefano Zampini 3573d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrices_IS(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse reuse, Mat *submat[]) 3574d71ae5a4SJacob Faibussowitsch { 3575d0dbe9f7SStefano Zampini Mat tA; 3576d0dbe9f7SStefano Zampini 3577d0dbe9f7SStefano Zampini PetscFunctionBegin; 3578d0dbe9f7SStefano Zampini PetscCall(MatISGetAssembled_Private(A, &tA)); 3579d0dbe9f7SStefano Zampini PetscCall(MatCreateSubMatrices(tA, n, irow, icol, reuse, submat)); 3580d0dbe9f7SStefano Zampini /* MatCreateSubMatrices_MPIAIJ is a mess at the moment */ 3581d0dbe9f7SStefano Zampini #if 0 3582d0dbe9f7SStefano Zampini { 3583d0dbe9f7SStefano Zampini Mat_IS *a = (Mat_IS*)A->data; 3584d0dbe9f7SStefano Zampini MatType ltype; 3585d0dbe9f7SStefano Zampini VecType vtype; 3586d0dbe9f7SStefano Zampini char *flg; 3587d0dbe9f7SStefano Zampini 3588d0dbe9f7SStefano Zampini PetscCall(MatGetType(a->A,<ype)); 3589d0dbe9f7SStefano Zampini PetscCall(MatGetVecType(a->A,&vtype)); 3590d0dbe9f7SStefano Zampini PetscCall(PetscStrstr(vtype,"cuda",&flg)); 3591d0dbe9f7SStefano Zampini if (!flg) PetscCall(PetscStrstr(vtype,"hip",&flg)); 3592d0dbe9f7SStefano Zampini if (!flg) PetscCall(PetscStrstr(vtype,"kokkos",&flg)); 3593d0dbe9f7SStefano Zampini if (flg) { 3594d0dbe9f7SStefano Zampini for (PetscInt i = 0; i < n; i++) { 3595d0dbe9f7SStefano Zampini Mat sA = (*submat)[i]; 3596d0dbe9f7SStefano Zampini 3597d0dbe9f7SStefano Zampini PetscCall(MatConvert(sA,ltype,MAT_INPLACE_MATRIX,&sA)); 3598d0dbe9f7SStefano Zampini (*submat)[i] = sA; 3599d0dbe9f7SStefano Zampini } 3600d0dbe9f7SStefano Zampini } 3601d0dbe9f7SStefano Zampini } 3602d0dbe9f7SStefano Zampini #endif 3603d0dbe9f7SStefano Zampini PetscCall(MatISRestoreAssembled_Private(A, &tA)); 36043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3605d0dbe9f7SStefano Zampini } 3606d0dbe9f7SStefano Zampini 3607d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIncreaseOverlap_IS(Mat A, PetscInt n, IS is[], PetscInt ov) 3608d71ae5a4SJacob Faibussowitsch { 3609d0dbe9f7SStefano Zampini Mat tA; 3610d0dbe9f7SStefano Zampini 3611d0dbe9f7SStefano Zampini PetscFunctionBegin; 3612d0dbe9f7SStefano Zampini PetscCall(MatISGetAssembled_Private(A, &tA)); 3613d0dbe9f7SStefano Zampini PetscCall(MatIncreaseOverlap(tA, n, is, ov)); 3614d0dbe9f7SStefano Zampini PetscCall(MatISRestoreAssembled_Private(A, &tA)); 36153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3616d0dbe9f7SStefano Zampini } 3617d0dbe9f7SStefano Zampini 3618e432b41dSStefano Zampini /*@ 361911a5261eSBarry Smith MatISGetLocalToGlobalMapping - Gets the local-to-global numbering of the `MATIS` object 3620e432b41dSStefano Zampini 3621e432b41dSStefano Zampini Not Collective 3622e432b41dSStefano Zampini 3623e432b41dSStefano Zampini Input Parameter: 3624e432b41dSStefano Zampini . A - the matrix 3625e432b41dSStefano Zampini 3626e432b41dSStefano Zampini Output Parameters: 3627e432b41dSStefano Zampini + rmapping - row mapping 3628e432b41dSStefano Zampini - cmapping - column mapping 3629e432b41dSStefano Zampini 36302ef1f0ffSBarry Smith Level: advanced 36312ef1f0ffSBarry Smith 363211a5261eSBarry Smith Note: 363311a5261eSBarry 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. 3634e432b41dSStefano Zampini 36351cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatIS`, `MatSetLocalToGlobalMapping()` 3636e432b41dSStefano Zampini @*/ 3637d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 3638d71ae5a4SJacob Faibussowitsch { 3639e432b41dSStefano Zampini PetscFunctionBegin; 3640e432b41dSStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3641e432b41dSStefano Zampini PetscValidType(A, 1); 36424f572ea9SToby Isaac if (rmapping) PetscAssertPointer(rmapping, 2); 36434f572ea9SToby Isaac if (cmapping) PetscAssertPointer(cmapping, 3); 3644cac4c232SBarry Smith PetscUseMethod(A, "MatISGetLocalToGlobalMapping_C", (Mat, ISLocalToGlobalMapping *, ISLocalToGlobalMapping *), (A, rmapping, cmapping)); 36453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3646e432b41dSStefano Zampini } 3647e432b41dSStefano Zampini 3648d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISGetLocalToGlobalMapping_IS(Mat A, ISLocalToGlobalMapping *r, ISLocalToGlobalMapping *c) 3649d71ae5a4SJacob Faibussowitsch { 3650e432b41dSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3651e432b41dSStefano Zampini 3652e432b41dSStefano Zampini PetscFunctionBegin; 3653e432b41dSStefano Zampini if (r) *r = a->rmapping; 3654e432b41dSStefano Zampini if (c) *c = a->cmapping; 36553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3656e432b41dSStefano Zampini } 3657e432b41dSStefano Zampini 3658a50ef18cSStefano Zampini static PetscErrorCode MatSetBlockSizes_IS(Mat A, PetscInt rbs, PetscInt cbs) 3659a50ef18cSStefano Zampini { 3660a50ef18cSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3661a50ef18cSStefano Zampini 3662a50ef18cSStefano Zampini PetscFunctionBegin; 3663a50ef18cSStefano Zampini if (a->A) PetscCall(MatSetBlockSizes(a->A, rbs, cbs)); 3664a50ef18cSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 3665a50ef18cSStefano Zampini } 3666a50ef18cSStefano Zampini 3667b4319ba4SBarry Smith /*MC 36684f58015eSStefano Zampini MATIS - MATIS = "is" - A matrix type to be used for non-overlapping domain decomposition methods (e.g. `PCBDDC` or `KSPFETIDP`). 36694f58015eSStefano Zampini This stores the matrices in globally unassembled form and the parallel matrix vector product is handled "implicitly". 3670b4319ba4SBarry Smith 3671b4319ba4SBarry Smith Options Database Keys: 36724f58015eSStefano Zampini + -mat_type is - Set the matrix type to `MATIS`. 36734f58015eSStefano Zampini . -mat_is_allow_repeated - Allow repeated entries in the local part of the local to global maps. 36744f58015eSStefano Zampini . -mat_is_fixempty - Fix local matrices in case of empty local rows/columns. 36754f58015eSStefano Zampini - -mat_is_storel2l - Store the local-to-local operators generated by the Galerkin process of `MatPtAP()`. 36762ef1f0ffSBarry Smith 36774f58015eSStefano Zampini Level: intermediate 3678b4319ba4SBarry Smith 367995452b02SPatrick Sanan Notes: 36802ef1f0ffSBarry Smith Options prefix for the inner matrix are given by `-is_mat_xxx` 3681b4319ba4SBarry Smith 368211a5261eSBarry Smith You must call `MatSetLocalToGlobalMapping()` before using this matrix type. 3683b4319ba4SBarry Smith 3684b4319ba4SBarry Smith You can do matrix preallocation on the local matrix after you obtain it with 36854f58015eSStefano Zampini `MatISGetLocalMat()`; otherwise, you could use `MatISSetPreallocation()` or `MatXAIJSetPreallocation()` 3686b4319ba4SBarry Smith 36871cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `Mat`, `MatISGetLocalMat()`, `MatSetLocalToGlobalMapping()`, `MatISSetPreallocation()`, `MatCreateIS()`, `PCBDDC`, `KSPFETIDP` 3688b4319ba4SBarry Smith M*/ 3689d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A) 3690d71ae5a4SJacob Faibussowitsch { 3691e432b41dSStefano Zampini Mat_IS *a; 3692b4319ba4SBarry Smith 3693b4319ba4SBarry Smith PetscFunctionBegin; 36944dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&a)); 36959566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATAIJ, &a->lmattype)); 3696e432b41dSStefano Zampini A->data = (void *)a; 3697b4319ba4SBarry Smith 3698e176bc59SStefano Zampini /* matrix ops */ 36999566063dSJacob Faibussowitsch PetscCall(PetscMemzero(A->ops, sizeof(struct _MatOps))); 3700b4319ba4SBarry Smith A->ops->mult = MatMult_IS; 37012e74eeadSLisandro Dalcin A->ops->multadd = MatMultAdd_IS; 37022e74eeadSLisandro Dalcin A->ops->multtranspose = MatMultTranspose_IS; 37032e74eeadSLisandro Dalcin A->ops->multtransposeadd = MatMultTransposeAdd_IS; 3704b4319ba4SBarry Smith A->ops->destroy = MatDestroy_IS; 3705b4319ba4SBarry Smith A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS; 37062e74eeadSLisandro Dalcin A->ops->setvalues = MatSetValues_IS; 370798921651SStefano Zampini A->ops->setvaluesblocked = MatSetValuesBlocked_IS; 3708b4319ba4SBarry Smith A->ops->setvalueslocal = MatSetValuesLocal_IS; 3709f0006bf2SLisandro Dalcin A->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_IS; 37102e74eeadSLisandro Dalcin A->ops->zerorows = MatZeroRows_IS; 3711f0ae7da4SStefano Zampini A->ops->zerorowscolumns = MatZeroRowsColumns_IS; 3712b4319ba4SBarry Smith A->ops->assemblybegin = MatAssemblyBegin_IS; 3713b4319ba4SBarry Smith A->ops->assemblyend = MatAssemblyEnd_IS; 3714b4319ba4SBarry Smith A->ops->view = MatView_IS; 37155042aa92SStefano Zampini A->ops->load = MatLoad_IS; 37166726f965SBarry Smith A->ops->zeroentries = MatZeroEntries_IS; 37172e74eeadSLisandro Dalcin A->ops->scale = MatScale_IS; 37182e74eeadSLisandro Dalcin A->ops->getdiagonal = MatGetDiagonal_IS; 37196726f965SBarry Smith A->ops->setoption = MatSetOption_IS; 372069796d55SStefano Zampini A->ops->ishermitian = MatIsHermitian_IS; 372169796d55SStefano Zampini A->ops->issymmetric = MatIsSymmetric_IS; 372245471136SStefano Zampini A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS; 3723ad6194a2SStefano Zampini A->ops->duplicate = MatDuplicate_IS; 37246bd84002SStefano Zampini A->ops->missingdiagonal = MatMissingDiagonal_IS; 37252b404112SStefano Zampini A->ops->copy = MatCopy_IS; 3726659959c5SStefano Zampini A->ops->getlocalsubmatrix = MatGetLocalSubMatrix_IS; 37277dae84e0SHong Zhang A->ops->createsubmatrix = MatCreateSubMatrix_IS; 3728f26d0771SStefano Zampini A->ops->axpy = MatAXPY_IS; 37293fd1c9e7SStefano Zampini A->ops->diagonalset = MatDiagonalSet_IS; 37303fd1c9e7SStefano Zampini A->ops->shift = MatShift_IS; 3731d7f69cd0SStefano Zampini A->ops->transpose = MatTranspose_IS; 37327fa8f2d3SStefano Zampini A->ops->getinfo = MatGetInfo_IS; 3733ad219c80Sstefano_zampini A->ops->diagonalscale = MatDiagonalScale_IS; 3734872cf891SStefano Zampini A->ops->setfromoptions = MatSetFromOptions_IS; 3735fc989267SStefano Zampini A->ops->setup = MatSetUp_IS; 37368b9382cfSStefano Zampini A->ops->hasoperation = MatHasOperation_IS; 3737d0dbe9f7SStefano Zampini A->ops->getdiagonalblock = MatGetDiagonalBlock_IS; 3738d0dbe9f7SStefano Zampini A->ops->createsubmatrices = MatCreateSubMatrices_IS; 3739d0dbe9f7SStefano Zampini A->ops->increaseoverlap = MatIncreaseOverlap_IS; 3740a50ef18cSStefano Zampini A->ops->setblocksizes = MatSetBlockSizes_IS; 3741b4319ba4SBarry Smith 3742b7ce53b6SStefano Zampini /* special MATIS functions */ 37439566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMatType_C", MatISSetLocalMatType_IS)); 37449566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalMat_C", MatISGetLocalMat_IS)); 37459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISRestoreLocalMat_C", MatISRestoreLocalMat_IS)); 37469566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMat_C", MatISSetLocalMat_IS)); 37479566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetPreallocation_C", MatISSetPreallocation_IS)); 37484f58015eSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetAllowRepeated_C", MatISSetAllowRepeated_IS)); 37499566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISStoreL2L_C", MatISStoreL2L_IS)); 37509566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISFixLocalEmpty_C", MatISFixLocalEmpty_IS)); 37519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalToGlobalMapping_C", MatISGetLocalToGlobalMapping_IS)); 37529566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpiaij_C", MatConvert_IS_XAIJ)); 37539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpibaij_C", MatConvert_IS_XAIJ)); 37549566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpisbaij_C", MatConvert_IS_XAIJ)); 37559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqaij_C", MatConvert_IS_XAIJ)); 37569566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqbaij_C", MatConvert_IS_XAIJ)); 37579566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqsbaij_C", MatConvert_IS_XAIJ)); 37589566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_aij_C", MatConvert_IS_XAIJ)); 37599566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOOLocal_C", MatSetPreallocationCOOLocal_IS)); 37609566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_IS)); 37619566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, MATIS)); 37623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3763b4319ba4SBarry Smith } 3764