1b4319ba4SBarry Smith /* 2b4319ba4SBarry Smith Creates a matrix class for using the Neumann-Neumann type preconditioners. 3b4319ba4SBarry Smith This stores the matrices in globally unassembled form. Each processor 4b4319ba4SBarry Smith assembles only its local Neumann problem and the parallel matrix vector 5b4319ba4SBarry Smith product is handled "implicitly". 6b4319ba4SBarry Smith 7b4319ba4SBarry Smith Currently this allows for only one subdomain per processor. 8b4319ba4SBarry Smith */ 9b4319ba4SBarry Smith 10d0dbe9f7SStefano Zampini #include <petsc/private/matisimpl.h> /*I "petscmat.h" I*/ 114f2d7cafSStefano Zampini #include <petsc/private/sfimpl.h> 12a72d46e8SStefano Zampini #include <petsc/private/vecimpl.h> 13e432b41dSStefano Zampini #include <petsc/private/hashseti.h> 1428f4e0baSStefano Zampini 15f26d0771SStefano Zampini #define MATIS_MAX_ENTRIES_INSERTION 2048 16b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat, PetscInt, const PetscInt *, PetscInt, const PetscInt *, const PetscScalar *, InsertMode); 17b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat, PetscInt, const PetscInt *, PetscInt, const PetscInt *, const PetscScalar *, InsertMode); 188546b261SStefano Zampini static PetscErrorCode MatISSetUpScatters_Private(Mat); 19f26d0771SStefano Zampini 209371c9d4SSatish Balay static PetscErrorCode MatISContainerDestroyPtAP_Private(void *ptr) { 2175d48cdbSStefano Zampini MatISPtAP ptap = (MatISPtAP)ptr; 2275d48cdbSStefano Zampini 2375d48cdbSStefano Zampini PetscFunctionBegin; 249566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrices(ptap->ris1 ? 2 : 1, &ptap->lP)); 259566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ptap->cis0)); 269566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ptap->cis1)); 279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ptap->ris0)); 289566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ptap->ris1)); 299566063dSJacob Faibussowitsch PetscCall(PetscFree(ptap)); 3075d48cdbSStefano Zampini PetscFunctionReturn(0); 3175d48cdbSStefano Zampini } 3275d48cdbSStefano Zampini 339371c9d4SSatish Balay static PetscErrorCode MatPtAPNumeric_IS_XAIJ(Mat A, Mat P, Mat C) { 3475d48cdbSStefano Zampini MatISPtAP ptap; 3575d48cdbSStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 3675d48cdbSStefano Zampini Mat lA, lC; 3775d48cdbSStefano Zampini MatReuse reuse; 3875d48cdbSStefano Zampini IS ris[2], cis[2]; 3975d48cdbSStefano Zampini PetscContainer c; 4075d48cdbSStefano Zampini PetscInt n; 4175d48cdbSStefano Zampini 4275d48cdbSStefano Zampini PetscFunctionBegin; 439566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)C, "_MatIS_PtAP", (PetscObject *)&c)); 4428b400f6SJacob Faibussowitsch PetscCheck(c, PetscObjectComm((PetscObject)C), PETSC_ERR_PLIB, "Missing PtAP information"); 459566063dSJacob Faibussowitsch PetscCall(PetscContainerGetPointer(c, (void **)&ptap)); 4675d48cdbSStefano Zampini ris[0] = ptap->ris0; 4775d48cdbSStefano Zampini ris[1] = ptap->ris1; 4875d48cdbSStefano Zampini cis[0] = ptap->cis0; 4975d48cdbSStefano Zampini cis[1] = ptap->cis1; 5075d48cdbSStefano Zampini n = ptap->ris1 ? 2 : 1; 5175d48cdbSStefano Zampini reuse = ptap->lP ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX; 529566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(P, n, ris, cis, reuse, &ptap->lP)); 5375d48cdbSStefano Zampini 549566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A, &lA)); 559566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(C, &lC)); 5675d48cdbSStefano Zampini if (ptap->ris1) { /* unsymmetric A mapping */ 5775d48cdbSStefano Zampini Mat lPt; 5875d48cdbSStefano Zampini 599566063dSJacob Faibussowitsch PetscCall(MatTranspose(ptap->lP[1], MAT_INITIAL_MATRIX, &lPt)); 609566063dSJacob Faibussowitsch PetscCall(MatMatMatMult(lPt, lA, ptap->lP[0], reuse, ptap->fill, &lC)); 6148a46eb9SPierre Jolivet if (matis->storel2l) PetscCall(PetscObjectCompose((PetscObject)(A), "_MatIS_PtAP_l2l", (PetscObject)lPt)); 629566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lPt)); 6375d48cdbSStefano Zampini } else { 649566063dSJacob Faibussowitsch PetscCall(MatPtAP(lA, ptap->lP[0], reuse, ptap->fill, &lC)); 6548a46eb9SPierre Jolivet if (matis->storel2l) PetscCall(PetscObjectCompose((PetscObject)C, "_MatIS_PtAP_l2l", (PetscObject)ptap->lP[0])); 6675d48cdbSStefano Zampini } 6775d48cdbSStefano Zampini if (reuse == MAT_INITIAL_MATRIX) { 689566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(C, lC)); 699566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lC)); 7075d48cdbSStefano Zampini } 719566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 729566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 7375d48cdbSStefano Zampini PetscFunctionReturn(0); 7475d48cdbSStefano Zampini } 7575d48cdbSStefano Zampini 769371c9d4SSatish Balay static PetscErrorCode MatGetNonzeroColumnsLocal_Private(Mat PT, IS *cis) { 7775d48cdbSStefano Zampini Mat Po, Pd; 7875d48cdbSStefano Zampini IS zd, zo; 7975d48cdbSStefano Zampini const PetscInt *garray; 8075d48cdbSStefano Zampini PetscInt *aux, i, bs; 8175d48cdbSStefano Zampini PetscInt dc, stc, oc, ctd, cto; 8275d48cdbSStefano Zampini PetscBool ismpiaij, ismpibaij, isseqaij, isseqbaij; 8375d48cdbSStefano Zampini MPI_Comm comm; 8475d48cdbSStefano Zampini 8575d48cdbSStefano Zampini PetscFunctionBegin; 8675d48cdbSStefano Zampini PetscValidHeaderSpecific(PT, MAT_CLASSID, 1); 8775d48cdbSStefano Zampini PetscValidPointer(cis, 2); 889566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)PT, &comm)); 8975d48cdbSStefano Zampini bs = 1; 909566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)PT, MATMPIAIJ, &ismpiaij)); 919566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)PT, MATMPIBAIJ, &ismpibaij)); 929566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)PT, MATSEQAIJ, &isseqaij)); 939566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)PT, MATSEQBAIJ, &isseqbaij)); 9475d48cdbSStefano Zampini if (isseqaij || isseqbaij) { 9575d48cdbSStefano Zampini Pd = PT; 9675d48cdbSStefano Zampini Po = NULL; 9775d48cdbSStefano Zampini garray = NULL; 9875d48cdbSStefano Zampini } else if (ismpiaij) { 999566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(PT, &Pd, &Po, &garray)); 10075d48cdbSStefano Zampini } else if (ismpibaij) { 1019566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJGetSeqBAIJ(PT, &Pd, &Po, &garray)); 1029566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(PT, &bs)); 10398921bdaSJacob Faibussowitsch } else SETERRQ(comm, PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)(PT))->type_name); 10475d48cdbSStefano Zampini 10575d48cdbSStefano Zampini /* identify any null columns in Pd or Po */ 10622f7620eSStefano Zampini /* We use a tolerance comparison since it may happen that, with geometric multigrid, 10722f7620eSStefano Zampini some of the columns are not really zero, but very close to */ 10875d48cdbSStefano Zampini zo = zd = NULL; 10948a46eb9SPierre Jolivet if (Po) PetscCall(MatFindNonzeroRowsOrCols_Basic(Po, PETSC_TRUE, PETSC_SMALL, &zo)); 1109566063dSJacob Faibussowitsch PetscCall(MatFindNonzeroRowsOrCols_Basic(Pd, PETSC_TRUE, PETSC_SMALL, &zd)); 11175d48cdbSStefano Zampini 1129566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(PT, NULL, &dc)); 1139566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(PT, &stc, NULL)); 1149566063dSJacob Faibussowitsch if (Po) PetscCall(MatGetLocalSize(Po, NULL, &oc)); 11575d48cdbSStefano Zampini else oc = 0; 1169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((dc + oc) / bs, &aux)); 11775d48cdbSStefano Zampini if (zd) { 11875d48cdbSStefano Zampini const PetscInt *idxs; 11975d48cdbSStefano Zampini PetscInt nz; 12075d48cdbSStefano Zampini 12175d48cdbSStefano Zampini /* this will throw an error if bs is not valid */ 1229566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(zd, bs)); 1239566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zd, &nz)); 1249566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zd, &idxs)); 12575d48cdbSStefano Zampini ctd = nz / bs; 12675d48cdbSStefano Zampini for (i = 0; i < ctd; i++) aux[i] = (idxs[bs * i] + stc) / bs; 1279566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zd, &idxs)); 12875d48cdbSStefano Zampini } else { 12975d48cdbSStefano Zampini ctd = dc / bs; 13075d48cdbSStefano Zampini for (i = 0; i < ctd; i++) aux[i] = i + stc / bs; 13175d48cdbSStefano Zampini } 13275d48cdbSStefano Zampini if (zo) { 13375d48cdbSStefano Zampini const PetscInt *idxs; 13475d48cdbSStefano Zampini PetscInt nz; 13575d48cdbSStefano Zampini 13675d48cdbSStefano Zampini /* this will throw an error if bs is not valid */ 1379566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(zo, bs)); 1389566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zo, &nz)); 1399566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zo, &idxs)); 14075d48cdbSStefano Zampini cto = nz / bs; 14175d48cdbSStefano Zampini for (i = 0; i < cto; i++) aux[i + ctd] = garray[idxs[bs * i] / bs]; 1429566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zo, &idxs)); 14375d48cdbSStefano Zampini } else { 14475d48cdbSStefano Zampini cto = oc / bs; 14575d48cdbSStefano Zampini for (i = 0; i < cto; i++) aux[i + ctd] = garray[i]; 14675d48cdbSStefano Zampini } 1479566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, bs, ctd + cto, aux, PETSC_OWN_POINTER, cis)); 1489566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zd)); 1499566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zo)); 15075d48cdbSStefano Zampini PetscFunctionReturn(0); 15175d48cdbSStefano Zampini } 15275d48cdbSStefano Zampini 1539371c9d4SSatish Balay static PetscErrorCode MatPtAPSymbolic_IS_XAIJ(Mat A, Mat P, PetscReal fill, Mat C) { 1548546b261SStefano Zampini Mat PT, lA; 15575d48cdbSStefano Zampini MatISPtAP ptap; 15675d48cdbSStefano Zampini ISLocalToGlobalMapping Crl2g, Ccl2g, rl2g, cl2g; 15775d48cdbSStefano Zampini PetscContainer c; 1588546b261SStefano Zampini MatType lmtype; 15975d48cdbSStefano Zampini const PetscInt *garray; 16075d48cdbSStefano Zampini PetscInt ibs, N, dc; 16175d48cdbSStefano Zampini MPI_Comm comm; 16275d48cdbSStefano Zampini 16375d48cdbSStefano Zampini PetscFunctionBegin; 1649566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 1659566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATIS)); 1669566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A, &lA)); 1679566063dSJacob Faibussowitsch PetscCall(MatGetType(lA, &lmtype)); 1689566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(C, lmtype)); 1699566063dSJacob Faibussowitsch PetscCall(MatGetSize(P, NULL, &N)); 1709566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(P, NULL, &dc)); 1719566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, dc, dc, N, N)); 17275d48cdbSStefano Zampini /* Not sure about this 1739566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(P,NULL,&ibs)); 1749566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(*C,ibs)); 17575d48cdbSStefano Zampini */ 17675d48cdbSStefano Zampini 1779566063dSJacob Faibussowitsch PetscCall(PetscNew(&ptap)); 1789566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c)); 1799566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(c, ptap)); 1809566063dSJacob Faibussowitsch PetscCall(PetscContainerSetUserDestroy(c, MatISContainerDestroyPtAP_Private)); 1819566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)C, "_MatIS_PtAP", (PetscObject)c)); 1829566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&c)); 18375d48cdbSStefano Zampini ptap->fill = fill; 18475d48cdbSStefano Zampini 1859566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(A, &rl2g, &cl2g)); 18675d48cdbSStefano Zampini 1879566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(cl2g, &ibs)); 1889566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(cl2g, &N)); 1899566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(cl2g, &garray)); 1909566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, ibs, N / ibs, garray, PETSC_COPY_VALUES, &ptap->ris0)); 1919566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(cl2g, &garray)); 19275d48cdbSStefano Zampini 1939566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(P, ptap->ris0, NULL, MAT_INITIAL_MATRIX, &PT)); 1949566063dSJacob Faibussowitsch PetscCall(MatGetNonzeroColumnsLocal_Private(PT, &ptap->cis0)); 1959566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(ptap->cis0, &Ccl2g)); 1969566063dSJacob Faibussowitsch PetscCall(MatDestroy(&PT)); 19775d48cdbSStefano Zampini 19875d48cdbSStefano Zampini Crl2g = NULL; 19975d48cdbSStefano Zampini if (rl2g != cl2g) { /* unsymmetric A mapping */ 20075d48cdbSStefano Zampini PetscBool same, lsame = PETSC_FALSE; 20175d48cdbSStefano Zampini PetscInt N1, ibs1; 20275d48cdbSStefano Zampini 2039566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(rl2g, &N1)); 2049566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(rl2g, &ibs1)); 2059566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(rl2g, &garray)); 2069566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, ibs, N / ibs, garray, PETSC_COPY_VALUES, &ptap->ris1)); 2079566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(rl2g, &garray)); 20875d48cdbSStefano Zampini if (ibs1 == ibs && N1 == N) { /* check if the l2gmaps are the same */ 20975d48cdbSStefano Zampini const PetscInt *i1, *i2; 21075d48cdbSStefano Zampini 2119566063dSJacob Faibussowitsch PetscCall(ISBlockGetIndices(ptap->ris0, &i1)); 2129566063dSJacob Faibussowitsch PetscCall(ISBlockGetIndices(ptap->ris1, &i2)); 2139566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(i1, i2, N, &lsame)); 21475d48cdbSStefano Zampini } 2151c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&lsame, &same, 1, MPIU_BOOL, MPI_LAND, comm)); 21675d48cdbSStefano Zampini if (same) { 2179566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ptap->ris1)); 21875d48cdbSStefano Zampini } else { 2199566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(P, ptap->ris1, NULL, MAT_INITIAL_MATRIX, &PT)); 2209566063dSJacob Faibussowitsch PetscCall(MatGetNonzeroColumnsLocal_Private(PT, &ptap->cis1)); 2219566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(ptap->cis1, &Crl2g)); 2229566063dSJacob Faibussowitsch PetscCall(MatDestroy(&PT)); 22375d48cdbSStefano Zampini } 22475d48cdbSStefano Zampini } 22575d48cdbSStefano Zampini /* Not sure about this 22675d48cdbSStefano Zampini if (!Crl2g) { 2279566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(C,&ibs)); 2289566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetBlockSize(Ccl2g,ibs)); 22975d48cdbSStefano Zampini } 23075d48cdbSStefano Zampini */ 2319566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(C, Crl2g ? Crl2g : Ccl2g, Ccl2g)); 2329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&Crl2g)); 2339566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&Ccl2g)); 23475d48cdbSStefano Zampini 2354222ddf1SHong Zhang C->ops->ptapnumeric = MatPtAPNumeric_IS_XAIJ; 23675d48cdbSStefano Zampini PetscFunctionReturn(0); 23775d48cdbSStefano Zampini } 23875d48cdbSStefano Zampini 2394222ddf1SHong Zhang /* ----------------------------------------- */ 2409371c9d4SSatish Balay static PetscErrorCode MatProductSymbolic_PtAP_IS_XAIJ(Mat C) { 2414222ddf1SHong Zhang Mat_Product *product = C->product; 2424222ddf1SHong Zhang Mat A = product->A, P = product->B; 2434222ddf1SHong Zhang PetscReal fill = product->fill; 24475d48cdbSStefano Zampini 24575d48cdbSStefano Zampini PetscFunctionBegin; 2469566063dSJacob Faibussowitsch PetscCall(MatPtAPSymbolic_IS_XAIJ(A, P, fill, C)); 2474222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_PtAP; 24875d48cdbSStefano Zampini PetscFunctionReturn(0); 24975d48cdbSStefano Zampini } 25075d48cdbSStefano Zampini 2519371c9d4SSatish Balay static PetscErrorCode MatProductSetFromOptions_IS_XAIJ_PtAP(Mat C) { 2524222ddf1SHong Zhang PetscFunctionBegin; 2534222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_PtAP_IS_XAIJ; 2544222ddf1SHong Zhang PetscFunctionReturn(0); 2554222ddf1SHong Zhang } 2564222ddf1SHong Zhang 2579371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat C) { 2584222ddf1SHong Zhang Mat_Product *product = C->product; 2594222ddf1SHong Zhang 2604222ddf1SHong Zhang PetscFunctionBegin; 26148a46eb9SPierre Jolivet if (product->type == MATPRODUCT_PtAP) PetscCall(MatProductSetFromOptions_IS_XAIJ_PtAP(C)); 2624222ddf1SHong Zhang PetscFunctionReturn(0); 2634222ddf1SHong Zhang } 2644222ddf1SHong Zhang 2654222ddf1SHong Zhang /* ----------------------------------------- */ 2669371c9d4SSatish Balay static PetscErrorCode MatISContainerDestroyFields_Private(void *ptr) { 2675b003df0Sstefano_zampini MatISLocalFields lf = (MatISLocalFields)ptr; 2685b003df0Sstefano_zampini PetscInt i; 2695b003df0Sstefano_zampini 270ab4d48faSStefano Zampini PetscFunctionBegin; 27148a46eb9SPierre Jolivet for (i = 0; i < lf->nr; i++) PetscCall(ISDestroy(&lf->rf[i])); 27248a46eb9SPierre Jolivet for (i = 0; i < lf->nc; i++) PetscCall(ISDestroy(&lf->cf[i])); 2739566063dSJacob Faibussowitsch PetscCall(PetscFree2(lf->rf, lf->cf)); 2749566063dSJacob Faibussowitsch PetscCall(PetscFree(lf)); 2755b003df0Sstefano_zampini PetscFunctionReturn(0); 2765b003df0Sstefano_zampini } 277a72627d2SStefano Zampini 2789371c9d4SSatish Balay static PetscErrorCode MatConvert_SeqXAIJ_IS(Mat A, MatType type, MatReuse reuse, Mat *newmat) { 279c9225affSStefano Zampini Mat B, lB; 280c9225affSStefano Zampini 281c9225affSStefano Zampini PetscFunctionBegin; 282c9225affSStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 283c9225affSStefano Zampini ISLocalToGlobalMapping rl2g, cl2g; 284c9225affSStefano Zampini PetscInt bs; 285c9225affSStefano Zampini IS is; 286c9225affSStefano Zampini 2879566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 2889566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), A->rmap->n / bs, 0, 1, &is)); 289c9225affSStefano Zampini if (bs > 1) { 290c9225affSStefano Zampini IS is2; 291c9225affSStefano Zampini PetscInt i, *aux; 292c9225affSStefano Zampini 2939566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &i)); 2949566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, (const PetscInt **)&aux)); 2959566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), bs, i, aux, PETSC_COPY_VALUES, &is2)); 2969566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, (const PetscInt **)&aux)); 2979566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 298c9225affSStefano Zampini is = is2; 299c9225affSStefano Zampini } 3009566063dSJacob Faibussowitsch PetscCall(ISSetIdentity(is)); 3019566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g)); 3029566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3039566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), A->cmap->n / bs, 0, 1, &is)); 304c9225affSStefano Zampini if (bs > 1) { 305c9225affSStefano Zampini IS is2; 306c9225affSStefano Zampini PetscInt i, *aux; 307c9225affSStefano Zampini 3089566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &i)); 3099566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, (const PetscInt **)&aux)); 3109566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), bs, i, aux, PETSC_COPY_VALUES, &is2)); 3119566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, (const PetscInt **)&aux)); 3129566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 313c9225affSStefano Zampini is = is2; 314c9225affSStefano Zampini } 3159566063dSJacob Faibussowitsch PetscCall(ISSetIdentity(is)); 3169566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g)); 3179566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3189566063dSJacob Faibussowitsch PetscCall(MatCreateIS(PetscObjectComm((PetscObject)A), bs, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N, rl2g, cl2g, &B)); 3199566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 3209566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 3219566063dSJacob Faibussowitsch PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &lB)); 322c9225affSStefano Zampini if (reuse == MAT_INITIAL_MATRIX) *newmat = B; 323c9225affSStefano Zampini } else { 324c9225affSStefano Zampini B = *newmat; 3259566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 326c9225affSStefano Zampini lB = A; 327c9225affSStefano Zampini } 3289566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B, lB)); 3299566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lB)); 3309566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 3319566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 33248a46eb9SPierre Jolivet if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &B)); 333c9225affSStefano Zampini PetscFunctionReturn(0); 334c9225affSStefano Zampini } 335c9225affSStefano Zampini 3369371c9d4SSatish Balay static PetscErrorCode MatISScaleDisassembling_Private(Mat A) { 337c9225affSStefano Zampini Mat_IS *matis = (Mat_IS *)(A->data); 338c9225affSStefano Zampini PetscScalar *aa; 339c9225affSStefano Zampini const PetscInt *ii, *jj; 340c9225affSStefano Zampini PetscInt i, n, m; 341fabe8965SStefano Zampini PetscInt *ecount, **eneighs; 342c9225affSStefano Zampini PetscBool flg; 343c9225affSStefano Zampini 344c9225affSStefano Zampini PetscFunctionBegin; 3459566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(matis->A, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg)); 34608401ef6SPierre Jolivet PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get IJ structure"); 3479566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetNodeInfo(matis->rmapping, &n, &ecount, &eneighs)); 34808401ef6SPierre Jolivet PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, m, n); 3499566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(matis->A, &aa)); 350c9225affSStefano Zampini for (i = 0; i < n; i++) { 351fabe8965SStefano Zampini if (ecount[i] > 1) { 352c9225affSStefano Zampini PetscInt j; 353c9225affSStefano Zampini 354c9225affSStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 355c9225affSStefano Zampini PetscInt i2 = jj[j], p, p2; 356fabe8965SStefano Zampini PetscReal scal = 0.0; 357c9225affSStefano Zampini 358c9225affSStefano Zampini for (p = 0; p < ecount[i]; p++) { 359c9225affSStefano Zampini for (p2 = 0; p2 < ecount[i2]; p2++) { 3609371c9d4SSatish Balay if (eneighs[i][p] == eneighs[i2][p2]) { 3619371c9d4SSatish Balay scal += 1.0; 3629371c9d4SSatish Balay break; 3639371c9d4SSatish Balay } 364c9225affSStefano Zampini } 365c9225affSStefano Zampini } 366fabe8965SStefano Zampini if (scal) aa[j] /= scal; 367c9225affSStefano Zampini } 368c9225affSStefano Zampini } 369c9225affSStefano Zampini } 3709566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(matis->rmapping, &n, &ecount, &eneighs)); 3719566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(matis->A, &aa)); 3729566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(matis->A, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg)); 37308401ef6SPierre Jolivet PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot restore IJ structure"); 374c9225affSStefano Zampini PetscFunctionReturn(0); 375c9225affSStefano Zampini } 376c9225affSStefano Zampini 3779371c9d4SSatish Balay typedef enum { 3789371c9d4SSatish Balay MAT_IS_DISASSEMBLE_L2G_NATURAL, 3799371c9d4SSatish Balay MAT_IS_DISASSEMBLE_L2G_MAT, 3809371c9d4SSatish Balay MAT_IS_DISASSEMBLE_L2G_ND 3819371c9d4SSatish Balay } MatISDisassemblel2gType; 382fabe8965SStefano Zampini 3839371c9d4SSatish Balay static PetscErrorCode MatMPIXAIJComputeLocalToGlobalMapping_Private(Mat A, ISLocalToGlobalMapping *l2g) { 384fabe8965SStefano Zampini Mat Ad, Ao; 385fabe8965SStefano Zampini IS is, ndmap, ndsub; 386c9225affSStefano Zampini MPI_Comm comm; 387fabe8965SStefano Zampini const PetscInt *garray, *ndmapi; 388fabe8965SStefano Zampini PetscInt bs, i, cnt, nl, *ncount, *ndmapc; 389fabe8965SStefano Zampini PetscBool ismpiaij, ismpibaij; 390f4259b30SLisandro Dalcin const char *const MatISDisassemblel2gTypes[] = {"NATURAL", "MAT", "ND", "MatISDisassemblel2gType", "MAT_IS_DISASSEMBLE_L2G_", NULL}; 391fabe8965SStefano Zampini MatISDisassemblel2gType mode = MAT_IS_DISASSEMBLE_L2G_NATURAL; 392fabe8965SStefano Zampini MatPartitioning part; 393fabe8965SStefano Zampini PetscSF sf; 39491d376acSStefano Zampini PetscObject dm; 395c9225affSStefano Zampini 396c9225affSStefano Zampini PetscFunctionBegin; 397d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)A), ((PetscObject)A)->prefix, "MatIS l2g disassembling options", "Mat"); 3989566063dSJacob 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)); 399d0609cedSBarry Smith PetscOptionsEnd(); 400fabe8965SStefano Zampini if (mode == MAT_IS_DISASSEMBLE_L2G_MAT) { 4019566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(A, l2g, NULL)); 402c9225affSStefano Zampini PetscFunctionReturn(0); 403c9225affSStefano Zampini } 4049566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 4059566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 4069566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIBAIJ, &ismpibaij)); 4079566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 408fabe8965SStefano Zampini switch (mode) { 409fabe8965SStefano Zampini case MAT_IS_DISASSEMBLE_L2G_ND: 4109566063dSJacob Faibussowitsch PetscCall(MatPartitioningCreate(comm, &part)); 4119566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetAdjacency(part, A)); 4129566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)part, ((PetscObject)A)->prefix)); 4139566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetFromOptions(part)); 4149566063dSJacob Faibussowitsch PetscCall(MatPartitioningApplyND(part, &ndmap)); 4159566063dSJacob Faibussowitsch PetscCall(MatPartitioningDestroy(&part)); 4169566063dSJacob Faibussowitsch PetscCall(ISBuildTwoSided(ndmap, NULL, &ndsub)); 4179566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetUseScalableIncreaseOverlap(A, PETSC_TRUE)); 4189566063dSJacob Faibussowitsch PetscCall(MatIncreaseOverlap(A, 1, &ndsub, 1)); 4199566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(ndsub, l2g)); 420fabe8965SStefano Zampini 421fabe8965SStefano Zampini /* it may happen that a separator node is not properly shared */ 4229566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetNodeInfo(*l2g, &nl, &ncount, NULL)); 4239566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &sf)); 4249566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(*l2g, &garray)); 4259566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(sf, A->rmap, nl, NULL, PETSC_OWN_POINTER, garray)); 4269566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(*l2g, &garray)); 4279566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(A->rmap->n, &ndmapc)); 4289566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(sf, MPIU_INT, ncount, ndmapc, MPI_REPLACE)); 4299566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(sf, MPIU_INT, ncount, ndmapc, MPI_REPLACE)); 4309566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(*l2g, NULL, &ncount, NULL)); 4319566063dSJacob Faibussowitsch PetscCall(ISGetIndices(ndmap, &ndmapi)); 432fabe8965SStefano Zampini for (i = 0, cnt = 0; i < A->rmap->n; i++) 4339371c9d4SSatish Balay if (ndmapi[i] < 0 && ndmapc[i] < 2) cnt++; 434fabe8965SStefano Zampini 4351c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&cnt, &i, 1, MPIU_INT, MPI_MAX, comm)); 436fabe8965SStefano Zampini if (i) { /* we detected isolated separator nodes */ 437fabe8965SStefano Zampini Mat A2, A3; 438fabe8965SStefano Zampini IS *workis, is2; 439fabe8965SStefano Zampini PetscScalar *vals; 440fabe8965SStefano Zampini PetscInt gcnt = i, *dnz, *onz, j, *lndmapi; 441fabe8965SStefano Zampini ISLocalToGlobalMapping ll2g; 442fabe8965SStefano Zampini PetscBool flg; 443fabe8965SStefano Zampini const PetscInt *ii, *jj; 444fabe8965SStefano Zampini 445fabe8965SStefano Zampini /* communicate global id of separators */ 446d0609cedSBarry Smith MatPreallocateBegin(comm, A->rmap->n, A->cmap->n, dnz, onz); 4479371c9d4SSatish Balay for (i = 0, cnt = 0; i < A->rmap->n; i++) dnz[i] = ndmapi[i] < 0 ? i + A->rmap->rstart : -1; 448fabe8965SStefano Zampini 4499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl, &lndmapi)); 4509566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, dnz, lndmapi, MPI_REPLACE)); 451fabe8965SStefano Zampini 452fabe8965SStefano Zampini /* compute adjacency of isolated separators node */ 4539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(gcnt, &workis)); 454fabe8965SStefano Zampini for (i = 0, cnt = 0; i < A->rmap->n; i++) { 45548a46eb9SPierre Jolivet if (ndmapi[i] < 0 && ndmapc[i] < 2) PetscCall(ISCreateStride(comm, 1, i + A->rmap->rstart, 1, &workis[cnt++])); 456fabe8965SStefano Zampini } 45748a46eb9SPierre Jolivet for (i = cnt; i < gcnt; i++) PetscCall(ISCreateStride(comm, 0, 0, 1, &workis[i])); 458fabe8965SStefano Zampini for (i = 0; i < gcnt; i++) { 4599566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)workis[i], "ISOLATED")); 4609566063dSJacob Faibussowitsch PetscCall(ISViewFromOptions(workis[i], NULL, "-view_isolated_separators")); 461fabe8965SStefano Zampini } 462fabe8965SStefano Zampini 463fabe8965SStefano Zampini /* no communications since all the ISes correspond to locally owned rows */ 4649566063dSJacob Faibussowitsch PetscCall(MatIncreaseOverlap(A, gcnt, workis, 1)); 465fabe8965SStefano Zampini 466fabe8965SStefano Zampini /* end communicate global id of separators */ 4679566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, dnz, lndmapi, MPI_REPLACE)); 468fabe8965SStefano Zampini 469fabe8965SStefano Zampini /* communicate new layers : create a matrix and transpose it */ 4709566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(dnz, A->rmap->n)); 4719566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(onz, A->rmap->n)); 472fabe8965SStefano Zampini for (i = 0, j = 0; i < A->rmap->n; i++) { 473fabe8965SStefano Zampini if (ndmapi[i] < 0 && ndmapc[i] < 2) { 474fabe8965SStefano Zampini const PetscInt *idxs; 475fabe8965SStefano Zampini PetscInt s; 476fabe8965SStefano Zampini 4779566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(workis[j], &s)); 4789566063dSJacob Faibussowitsch PetscCall(ISGetIndices(workis[j], &idxs)); 4799566063dSJacob Faibussowitsch PetscCall(MatPreallocateSet(i + A->rmap->rstart, s, idxs, dnz, onz)); 480fabe8965SStefano Zampini j++; 481fabe8965SStefano Zampini } 482fabe8965SStefano Zampini } 48308401ef6SPierre Jolivet PetscCheck(j == cnt, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected local count %" PetscInt_FMT " != %" PetscInt_FMT, j, cnt); 484fabe8965SStefano Zampini 485fabe8965SStefano Zampini for (i = 0; i < gcnt; i++) { 4869566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)workis[i], "EXTENDED")); 4879566063dSJacob Faibussowitsch PetscCall(ISViewFromOptions(workis[i], NULL, "-view_isolated_separators")); 488fabe8965SStefano Zampini } 489fabe8965SStefano Zampini 490fabe8965SStefano Zampini for (i = 0, j = 0; i < A->rmap->n; i++) j = PetscMax(j, dnz[i] + onz[i]); 4919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(j, &vals)); 492fabe8965SStefano Zampini for (i = 0; i < j; i++) vals[i] = 1.0; 493fabe8965SStefano Zampini 4949566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &A2)); 4959566063dSJacob Faibussowitsch PetscCall(MatSetType(A2, MATMPIAIJ)); 4969566063dSJacob Faibussowitsch PetscCall(MatSetSizes(A2, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N)); 4979566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(A2, 0, dnz, 0, onz)); 4989566063dSJacob Faibussowitsch PetscCall(MatSetOption(A2, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE)); 499fabe8965SStefano Zampini for (i = 0, j = 0; i < A2->rmap->n; i++) { 500fabe8965SStefano Zampini PetscInt row = i + A2->rmap->rstart, s = dnz[i] + onz[i]; 501fabe8965SStefano Zampini const PetscInt *idxs; 502fabe8965SStefano Zampini 503fabe8965SStefano Zampini if (s) { 5049566063dSJacob Faibussowitsch PetscCall(ISGetIndices(workis[j], &idxs)); 5059566063dSJacob Faibussowitsch PetscCall(MatSetValues(A2, 1, &row, s, idxs, vals, INSERT_VALUES)); 5069566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(workis[j], &idxs)); 507fabe8965SStefano Zampini j++; 508fabe8965SStefano Zampini } 509fabe8965SStefano Zampini } 51008401ef6SPierre Jolivet PetscCheck(j == cnt, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected local count %" PetscInt_FMT " != %" PetscInt_FMT, j, cnt); 5119566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 5129566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A2, MAT_FINAL_ASSEMBLY)); 5139566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A2, MAT_FINAL_ASSEMBLY)); 5149566063dSJacob Faibussowitsch PetscCall(MatTranspose(A2, MAT_INPLACE_MATRIX, &A2)); 515fabe8965SStefano Zampini 516fabe8965SStefano Zampini /* extract submatrix corresponding to the coupling "owned separators" x "isolated separators" */ 517fabe8965SStefano Zampini for (i = 0, j = 0; i < nl; i++) 518fabe8965SStefano Zampini if (lndmapi[i] >= 0) lndmapi[j++] = lndmapi[i]; 5199566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, j, lndmapi, PETSC_USE_POINTER, &is)); 5209566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetLocalMatCondensed(A2, MAT_INITIAL_MATRIX, &is, NULL, &A3)); 5219566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 5229566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A2)); 523fabe8965SStefano Zampini 524fabe8965SStefano Zampini /* extend local to global map to include connected isolated separators */ 5259566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)A3, "_petsc_GetLocalMatCondensed_iscol", (PetscObject *)&is)); 52628b400f6SJacob Faibussowitsch PetscCheck(is, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing column map"); 5279566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &ll2g)); 5289566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A3, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &flg)); 52928b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get IJ structure"); 5309566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ii[i], jj, PETSC_COPY_VALUES, &is)); 5319566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A3, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &flg)); 53228b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get IJ structure"); 5339566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(ll2g, is, &is2)); 5349566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 5359566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&ll2g)); 536fabe8965SStefano Zampini 537fabe8965SStefano Zampini /* add new nodes to the local-to-global map */ 5389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(l2g)); 5399566063dSJacob Faibussowitsch PetscCall(ISExpand(ndsub, is2, &is)); 5409566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is2)); 5419566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, l2g)); 5429566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 543fabe8965SStefano Zampini 5449566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A3)); 5459566063dSJacob Faibussowitsch PetscCall(PetscFree(lndmapi)); 546d0609cedSBarry Smith MatPreallocateEnd(dnz, onz); 54748a46eb9SPierre Jolivet for (i = 0; i < gcnt; i++) PetscCall(ISDestroy(&workis[i])); 5489566063dSJacob Faibussowitsch PetscCall(PetscFree(workis)); 549fabe8965SStefano Zampini } 5509566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(ndmap, &ndmapi)); 5519566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 5529566063dSJacob Faibussowitsch PetscCall(PetscFree(ndmapc)); 5539566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ndmap)); 5549566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ndsub)); 5559566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetBlockSize(*l2g, bs)); 5569566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingViewFromOptions(*l2g, NULL, "-matis_nd_l2g_view")); 557fabe8965SStefano Zampini break; 558fabe8965SStefano Zampini case MAT_IS_DISASSEMBLE_L2G_NATURAL: 55991d376acSStefano Zampini PetscCall(PetscObjectQuery((PetscObject)A, "__PETSc_dm", (PetscObject *)&dm)); 56091d376acSStefano Zampini if (dm) { /* if a matrix comes from a DM, most likely we can use the l2gmap if any */ 56191d376acSStefano Zampini PetscCall(MatGetLocalToGlobalMapping(A, l2g, NULL)); 56291d376acSStefano Zampini PetscCall(PetscObjectReference((PetscObject)*l2g)); 56391d376acSStefano Zampini if (*l2g) PetscFunctionReturn(0); 56491d376acSStefano Zampini } 565fabe8965SStefano Zampini if (ismpiaij) { 5669566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(A, &Ad, &Ao, &garray)); 567fabe8965SStefano Zampini } else if (ismpibaij) { 5689566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJGetSeqBAIJ(A, &Ad, &Ao, &garray)); 56998921bdaSJacob Faibussowitsch } else SETERRQ(comm, PETSC_ERR_SUP, "Type %s", ((PetscObject)A)->type_name); 570c9225affSStefano Zampini if (A->rmap->n) { 571fabe8965SStefano Zampini PetscInt dc, oc, stc, *aux; 572c9225affSStefano Zampini 573ebf8cefbSJunchao Zhang PetscCall(MatGetLocalSize(Ad, NULL, &dc)); 5749566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(Ao, NULL, &oc)); 575d0dbe9f7SStefano Zampini PetscCheck(!oc || garray, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "garray not present"); 5769566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(A, &stc, NULL)); 5779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((dc + oc) / bs, &aux)); 578c9225affSStefano Zampini for (i = 0; i < dc / bs; i++) aux[i] = i + stc / bs; 579ebf8cefbSJunchao Zhang for (i = 0; i < oc / bs; i++) aux[i + dc / bs] = (ismpiaij ? garray[i * bs] / bs : garray[i]); 5809566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, bs, (dc + oc) / bs, aux, PETSC_OWN_POINTER, &is)); 581c9225affSStefano Zampini } else { 5829566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, 1, 0, NULL, PETSC_OWN_POINTER, &is)); 583c9225affSStefano Zampini } 5849566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, l2g)); 5859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 586fabe8965SStefano Zampini break; 5879371c9d4SSatish Balay default: SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unsupported l2g disassembling type %d", mode); 588c9225affSStefano Zampini } 589c9225affSStefano Zampini PetscFunctionReturn(0); 590c9225affSStefano Zampini } 591c9225affSStefano Zampini 5929371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat A, MatType type, MatReuse reuse, Mat *newmat) { 593c9225affSStefano Zampini Mat lA, Ad, Ao, B = NULL; 5946989cf23SStefano Zampini ISLocalToGlobalMapping rl2g, cl2g; 5956989cf23SStefano Zampini IS is; 5966989cf23SStefano Zampini MPI_Comm comm; 5976989cf23SStefano Zampini void *ptrs[2]; 5986989cf23SStefano Zampini const char *names[2] = {"_convert_csr_aux", "_convert_csr_data"}; 599c9225affSStefano Zampini const PetscInt *garray; 6006989cf23SStefano Zampini PetscScalar *dd, *od, *aa, *data; 601c9225affSStefano Zampini const PetscInt *di, *dj, *oi, *oj; 602c9225affSStefano Zampini const PetscInt *odi, *odj, *ooi, *ooj; 6036989cf23SStefano Zampini PetscInt *aux, *ii, *jj; 604c9225affSStefano Zampini PetscInt bs, lc, dr, dc, oc, str, stc, nnz, i, jd, jo, cum; 605c9225affSStefano Zampini PetscBool flg, ismpiaij, ismpibaij, was_inplace = PETSC_FALSE; 606c9225affSStefano Zampini PetscMPIInt size; 6076989cf23SStefano Zampini 608ab4d48faSStefano Zampini PetscFunctionBegin; 6099566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 6109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 611c9225affSStefano Zampini if (size == 1) { 6129566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqXAIJ_IS(A, type, reuse, newmat)); 613c9225affSStefano Zampini PetscFunctionReturn(0); 614c9225affSStefano Zampini } 615c9225affSStefano Zampini if (reuse != MAT_REUSE_MATRIX && A->cmap->N == A->rmap->N) { 6169566063dSJacob Faibussowitsch PetscCall(MatMPIXAIJComputeLocalToGlobalMapping_Private(A, &rl2g)); 6179566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &B)); 6189566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATIS)); 6199566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N)); 6209566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B, rl2g, rl2g)); 6219566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 6229566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(B, bs)); 6239566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 624c9225affSStefano Zampini if (reuse == MAT_INPLACE_MATRIX) was_inplace = PETSC_TRUE; 625c9225affSStefano Zampini reuse = MAT_REUSE_MATRIX; 626c9225affSStefano Zampini } 627c9225affSStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 628c9225affSStefano Zampini Mat *newlA, lA; 629c9225affSStefano Zampini IS rows, cols; 630c9225affSStefano Zampini const PetscInt *ridx, *cidx; 631c9225affSStefano Zampini PetscInt rbs, cbs, nr, nc; 632c9225affSStefano Zampini 633c9225affSStefano Zampini if (!B) B = *newmat; 6349566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(B, &rl2g, &cl2g)); 6359566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(rl2g, &ridx)); 6369566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(cl2g, &cidx)); 6379566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(rl2g, &nr)); 6389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(cl2g, &nc)); 6399566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(rl2g, &rbs)); 6409566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(cl2g, &cbs)); 6419566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, rbs, nr / rbs, ridx, PETSC_USE_POINTER, &rows)); 642c9225affSStefano Zampini if (rl2g != cl2g) { 6439566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, cbs, nc / cbs, cidx, PETSC_USE_POINTER, &cols)); 644c9225affSStefano Zampini } else { 6459566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)rows)); 646c9225affSStefano Zampini cols = rows; 647c9225affSStefano Zampini } 6489566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(B, &lA)); 6499566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(A, 1, &rows, &cols, MAT_INITIAL_MATRIX, &newlA)); 6509566063dSJacob Faibussowitsch PetscCall(MatConvert(newlA[0], MATSEQAIJ, MAT_INPLACE_MATRIX, &newlA[0])); 6519566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(rl2g, &ridx)); 6529566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(cl2g, &cidx)); 6539566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rows)); 6549566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cols)); 655c9225affSStefano Zampini if (!lA->preallocated) { /* first time */ 6569566063dSJacob Faibussowitsch PetscCall(MatDuplicate(newlA[0], MAT_COPY_VALUES, &lA)); 6579566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B, lA)); 6589566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)lA)); 659c9225affSStefano Zampini } 6609566063dSJacob Faibussowitsch PetscCall(MatCopy(newlA[0], lA, SAME_NONZERO_PATTERN)); 6619566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrices(1, &newlA)); 6629566063dSJacob Faibussowitsch PetscCall(MatISScaleDisassembling_Private(B)); 6639566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 6649566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 6659566063dSJacob Faibussowitsch if (was_inplace) PetscCall(MatHeaderReplace(A, &B)); 666c9225affSStefano Zampini else *newmat = B; 667c9225affSStefano Zampini PetscFunctionReturn(0); 668c9225affSStefano Zampini } 669c9225affSStefano Zampini /* rectangular case, just compress out the column space */ 6709566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 6719566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIBAIJ, &ismpibaij)); 672c9225affSStefano Zampini if (ismpiaij) { 673c9225affSStefano Zampini bs = 1; 6749566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(A, &Ad, &Ao, &garray)); 675c9225affSStefano Zampini } else if (ismpibaij) { 6769566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 6779566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJGetSeqBAIJ(A, &Ad, &Ao, &garray)); 6789566063dSJacob Faibussowitsch PetscCall(MatConvert(Ad, MATSEQAIJ, MAT_INITIAL_MATRIX, &Ad)); 6799566063dSJacob Faibussowitsch PetscCall(MatConvert(Ao, MATSEQAIJ, MAT_INITIAL_MATRIX, &Ao)); 68098921bdaSJacob Faibussowitsch } else SETERRQ(comm, PETSC_ERR_SUP, "Type %s", ((PetscObject)A)->type_name); 6819566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(Ad, &dd)); 6829566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(Ao, &od)); 68328b400f6SJacob Faibussowitsch PetscCheck(garray, comm, PETSC_ERR_ARG_WRONGSTATE, "garray not present"); 6846989cf23SStefano Zampini 6856989cf23SStefano Zampini /* access relevant information from MPIAIJ */ 6869566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &str, NULL)); 6879566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(A, &stc, NULL)); 6889566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &dr, &dc)); 6899566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(Ao, NULL, &oc)); 6909566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(Ad, 0, PETSC_FALSE, PETSC_FALSE, &i, &di, &dj, &flg)); 69128b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get IJ structure"); 6929566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(Ao, 0, PETSC_FALSE, PETSC_FALSE, &i, &oi, &oj, &flg)); 69328b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get IJ structure"); 694c9225affSStefano Zampini nnz = di[dr] + oi[dr]; 695c9225affSStefano Zampini /* store original pointers to be restored later */ 6969371c9d4SSatish Balay odi = di; 6979371c9d4SSatish Balay odj = dj; 6989371c9d4SSatish Balay ooi = oi; 6999371c9d4SSatish Balay ooj = oj; 7006989cf23SStefano Zampini 7016989cf23SStefano Zampini /* generate l2g maps for rows and cols */ 7029566063dSJacob Faibussowitsch PetscCall(ISCreateStride(comm, dr / bs, str / bs, 1, &is)); 703c9225affSStefano Zampini if (bs > 1) { 704c9225affSStefano Zampini IS is2; 705c9225affSStefano Zampini 7069566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &i)); 7079566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, (const PetscInt **)&aux)); 7089566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, bs, i, aux, PETSC_COPY_VALUES, &is2)); 7099566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, (const PetscInt **)&aux)); 7109566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 711c9225affSStefano Zampini is = is2; 712c9225affSStefano Zampini } 7139566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g)); 7149566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 715e363d98aSStefano Zampini if (dr) { 7169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((dc + oc) / bs, &aux)); 717c9225affSStefano Zampini for (i = 0; i < dc / bs; i++) aux[i] = i + stc / bs; 718c9225affSStefano Zampini for (i = 0; i < oc / bs; i++) aux[i + dc / bs] = garray[i]; 7199566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, bs, (dc + oc) / bs, aux, PETSC_OWN_POINTER, &is)); 720e363d98aSStefano Zampini lc = dc + oc; 721e363d98aSStefano Zampini } else { 7229566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, bs, 0, NULL, PETSC_OWN_POINTER, &is)); 723e363d98aSStefano Zampini lc = 0; 724e363d98aSStefano Zampini } 7259566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g)); 7269566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 7276989cf23SStefano Zampini 7286989cf23SStefano Zampini /* create MATIS object */ 7299566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &B)); 7309566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, dr, dc, PETSC_DECIDE, PETSC_DECIDE)); 7319566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATIS)); 7329566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(B, bs)); 7339566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B, rl2g, cl2g)); 7349566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 7359566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 7366989cf23SStefano Zampini 7376989cf23SStefano Zampini /* merge local matrices */ 7389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz + dr + 1, &aux)); 7399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &data)); 7406989cf23SStefano Zampini ii = aux; 7416989cf23SStefano Zampini jj = aux + dr + 1; 7426989cf23SStefano Zampini aa = data; 7436989cf23SStefano Zampini *ii = *(di++) + *(oi++); 7449371c9d4SSatish Balay for (jd = 0, jo = 0, cum = 0; *ii < nnz; cum++) { 7459371c9d4SSatish Balay for (; jd < *di; jd++) { 7469371c9d4SSatish Balay *jj++ = *dj++; 7479371c9d4SSatish Balay *aa++ = *dd++; 7489371c9d4SSatish Balay } 7499371c9d4SSatish Balay for (; jo < *oi; jo++) { 7509371c9d4SSatish Balay *jj++ = *oj++ + dc; 7519371c9d4SSatish Balay *aa++ = *od++; 7529371c9d4SSatish Balay } 7536989cf23SStefano Zampini *(++ii) = *(di++) + *(oi++); 7546989cf23SStefano Zampini } 7556989cf23SStefano Zampini for (; cum < dr; cum++) *(++ii) = nnz; 756c9225affSStefano Zampini 7579566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(Ad, 0, PETSC_FALSE, PETSC_FALSE, &i, &odi, &odj, &flg)); 75828b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot restore IJ structure"); 7599566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(Ao, 0, PETSC_FALSE, PETSC_FALSE, &i, &ooi, &ooj, &flg)); 76028b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot restore IJ structure"); 7619566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(Ad, &dd)); 7629566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(Ao, &od)); 763c9225affSStefano Zampini 7646989cf23SStefano Zampini ii = aux; 7656989cf23SStefano Zampini jj = aux + dr + 1; 7666989cf23SStefano Zampini aa = data; 7679566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, dr, lc, ii, jj, aa, &lA)); 7686989cf23SStefano Zampini 7696989cf23SStefano Zampini /* create containers to destroy the data */ 7706989cf23SStefano Zampini ptrs[0] = aux; 7716989cf23SStefano Zampini ptrs[1] = data; 7726989cf23SStefano Zampini for (i = 0; i < 2; i++) { 7736989cf23SStefano Zampini PetscContainer c; 7746989cf23SStefano Zampini 7759566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c)); 7769566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(c, ptrs[i])); 7779566063dSJacob Faibussowitsch PetscCall(PetscContainerSetUserDestroy(c, PetscContainerUserDestroyDefault)); 7789566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)lA, names[i], (PetscObject)c)); 7799566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&c)); 7806989cf23SStefano Zampini } 781c9225affSStefano Zampini if (ismpibaij) { /* destroy converted local matrices */ 7829566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Ad)); 7839566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Ao)); 784c9225affSStefano Zampini } 7856989cf23SStefano Zampini 7866989cf23SStefano Zampini /* finalize matrix */ 7879566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B, lA)); 7889566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lA)); 7899566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 7909566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 791c9225affSStefano Zampini if (reuse == MAT_INPLACE_MATRIX) { 7929566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &B)); 793c9225affSStefano Zampini } else *newmat = B; 7946989cf23SStefano Zampini PetscFunctionReturn(0); 7956989cf23SStefano Zampini } 7966989cf23SStefano Zampini 7979371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A, MatType type, MatReuse reuse, Mat *newmat) { 7985e3038f0Sstefano_zampini Mat **nest, *snest, **rnest, lA, B; 7995e3038f0Sstefano_zampini IS *iscol, *isrow, *islrow, *islcol; 8005e3038f0Sstefano_zampini ISLocalToGlobalMapping rl2g, cl2g; 8015e3038f0Sstefano_zampini MPI_Comm comm; 8025b003df0Sstefano_zampini PetscInt *lr, *lc, *l2gidxs; 8035b003df0Sstefano_zampini PetscInt i, j, nr, nc, rbs, cbs; 8049e7b2b25Sstefano_zampini PetscBool convert, lreuse, *istrans; 8055e3038f0Sstefano_zampini 806ab4d48faSStefano Zampini PetscFunctionBegin; 8079566063dSJacob Faibussowitsch PetscCall(MatNestGetSubMats(A, &nr, &nc, &nest)); 8085e3038f0Sstefano_zampini lreuse = PETSC_FALSE; 8095e3038f0Sstefano_zampini rnest = NULL; 8105e3038f0Sstefano_zampini if (reuse == MAT_REUSE_MATRIX) { 8115e3038f0Sstefano_zampini PetscBool ismatis, isnest; 8125e3038f0Sstefano_zampini 8139566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)*newmat, MATIS, &ismatis)); 81428b400f6SJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_USER, "Cannot reuse matrix of type %s", ((PetscObject)(*newmat))->type_name); 8159566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*newmat, &lA)); 8169566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)lA, MATNEST, &isnest)); 8175e3038f0Sstefano_zampini if (isnest) { 8189566063dSJacob Faibussowitsch PetscCall(MatNestGetSubMats(lA, &i, &j, &rnest)); 8195e3038f0Sstefano_zampini lreuse = (PetscBool)(i == nr && j == nc); 8205e3038f0Sstefano_zampini if (!lreuse) rnest = NULL; 8215e3038f0Sstefano_zampini } 8225e3038f0Sstefano_zampini } 8239566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 8249566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(nr, &lr, nc, &lc)); 8259566063dSJacob Faibussowitsch PetscCall(PetscCalloc6(nr, &isrow, nc, &iscol, nr, &islrow, nc, &islcol, nr * nc, &snest, nr * nc, &istrans)); 8269566063dSJacob Faibussowitsch PetscCall(MatNestGetISs(A, isrow, iscol)); 8275e3038f0Sstefano_zampini for (i = 0; i < nr; i++) { 8285e3038f0Sstefano_zampini for (j = 0; j < nc; j++) { 8295e3038f0Sstefano_zampini PetscBool ismatis; 8309e7b2b25Sstefano_zampini PetscInt l1, l2, lb1, lb2, ij = i * nc + j; 8315e3038f0Sstefano_zampini 8325e3038f0Sstefano_zampini /* Null matrix pointers are allowed in MATNEST */ 8335e3038f0Sstefano_zampini if (!nest[i][j]) continue; 8345e3038f0Sstefano_zampini 8355e3038f0Sstefano_zampini /* Nested matrices should be of type MATIS */ 836*013e2dc7SBarry Smith PetscCall(PetscObjectTypeCompare((PetscObject)nest[i][j], MATTRANSPOSEVIRTUAL, &istrans[ij])); 8379e7b2b25Sstefano_zampini if (istrans[ij]) { 8389e7b2b25Sstefano_zampini Mat T, lT; 8399566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(nest[i][j], &T)); 8409566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)T, MATIS, &ismatis)); 84128b400f6SJacob 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); 8429566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(T, &lT)); 8439566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(lT, &snest[ij])); 8449e7b2b25Sstefano_zampini } else { 8459566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)nest[i][j], MATIS, &ismatis)); 84628b400f6SJacob 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); 8479566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(nest[i][j], &snest[ij])); 8489e7b2b25Sstefano_zampini } 8495e3038f0Sstefano_zampini 8505e3038f0Sstefano_zampini /* Check compatibility of local sizes */ 8519566063dSJacob Faibussowitsch PetscCall(MatGetSize(snest[ij], &l1, &l2)); 8529566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(snest[ij], &lb1, &lb2)); 8535e3038f0Sstefano_zampini if (!l1 || !l2) continue; 854aed4548fSBarry 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); 855aed4548fSBarry 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); 8565e3038f0Sstefano_zampini lr[i] = l1; 8575e3038f0Sstefano_zampini lc[j] = l2; 8585e3038f0Sstefano_zampini 8595e3038f0Sstefano_zampini /* check compatibilty for local matrix reusage */ 8605e3038f0Sstefano_zampini if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE; 8615e3038f0Sstefano_zampini } 8625e3038f0Sstefano_zampini } 8635e3038f0Sstefano_zampini 86476bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 8655e3038f0Sstefano_zampini /* Check compatibility of l2g maps for rows */ 8665e3038f0Sstefano_zampini for (i = 0; i < nr; i++) { 8675e3038f0Sstefano_zampini rl2g = NULL; 8685e3038f0Sstefano_zampini for (j = 0; j < nc; j++) { 8695e3038f0Sstefano_zampini PetscInt n1, n2; 8705e3038f0Sstefano_zampini 8715e3038f0Sstefano_zampini if (!nest[i][j]) continue; 8729e7b2b25Sstefano_zampini if (istrans[i * nc + j]) { 8739e7b2b25Sstefano_zampini Mat T; 8749e7b2b25Sstefano_zampini 8759566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(nest[i][j], &T)); 8769566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(T, NULL, &cl2g)); 8779e7b2b25Sstefano_zampini } else { 8789566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(nest[i][j], &cl2g, NULL)); 8799e7b2b25Sstefano_zampini } 8809566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(cl2g, &n1)); 8815e3038f0Sstefano_zampini if (!n1) continue; 8825e3038f0Sstefano_zampini if (!rl2g) { 8835e3038f0Sstefano_zampini rl2g = cl2g; 8845e3038f0Sstefano_zampini } else { 8855e3038f0Sstefano_zampini const PetscInt *idxs1, *idxs2; 8865e3038f0Sstefano_zampini PetscBool same; 8875e3038f0Sstefano_zampini 8889566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(rl2g, &n2)); 88908401ef6SPierre 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); 8909566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(cl2g, &idxs1)); 8919566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(rl2g, &idxs2)); 8929566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(idxs1, idxs2, n1, &same)); 8939566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(cl2g, &idxs1)); 8949566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(rl2g, &idxs2)); 89528b400f6SJacob 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); 8965e3038f0Sstefano_zampini } 8975e3038f0Sstefano_zampini } 8985e3038f0Sstefano_zampini } 8995e3038f0Sstefano_zampini /* Check compatibility of l2g maps for columns */ 9005e3038f0Sstefano_zampini for (i = 0; i < nc; i++) { 9015e3038f0Sstefano_zampini rl2g = NULL; 9025e3038f0Sstefano_zampini for (j = 0; j < nr; j++) { 9035e3038f0Sstefano_zampini PetscInt n1, n2; 9045e3038f0Sstefano_zampini 9055e3038f0Sstefano_zampini if (!nest[j][i]) continue; 9069e7b2b25Sstefano_zampini if (istrans[j * nc + i]) { 9079e7b2b25Sstefano_zampini Mat T; 9089e7b2b25Sstefano_zampini 9099566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(nest[j][i], &T)); 9109566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(T, &cl2g, NULL)); 9119e7b2b25Sstefano_zampini } else { 9129566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(nest[j][i], NULL, &cl2g)); 9139e7b2b25Sstefano_zampini } 9149566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(cl2g, &n1)); 9155e3038f0Sstefano_zampini if (!n1) continue; 9165e3038f0Sstefano_zampini if (!rl2g) { 9175e3038f0Sstefano_zampini rl2g = cl2g; 9185e3038f0Sstefano_zampini } else { 9195e3038f0Sstefano_zampini const PetscInt *idxs1, *idxs2; 9205e3038f0Sstefano_zampini PetscBool same; 9215e3038f0Sstefano_zampini 9229566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(rl2g, &n2)); 92308401ef6SPierre Jolivet PetscCheck(n1 == n2, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") has invalid column l2gmap size %" PetscInt_FMT " != %" PetscInt_FMT, j, i, n1, n2); 9249566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(cl2g, &idxs1)); 9259566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(rl2g, &idxs2)); 9269566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(idxs1, idxs2, n1, &same)); 9279566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(cl2g, &idxs1)); 9289566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(rl2g, &idxs2)); 92928b400f6SJacob Faibussowitsch PetscCheck(same, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") has invalid column l2gmap", j, i); 9305e3038f0Sstefano_zampini } 9315e3038f0Sstefano_zampini } 9325e3038f0Sstefano_zampini } 93376bd3646SJed Brown } 9345e3038f0Sstefano_zampini 9355e3038f0Sstefano_zampini B = NULL; 9365e3038f0Sstefano_zampini if (reuse != MAT_REUSE_MATRIX) { 9375b003df0Sstefano_zampini PetscInt stl; 9385b003df0Sstefano_zampini 9395e3038f0Sstefano_zampini /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */ 9405e3038f0Sstefano_zampini for (i = 0, stl = 0; i < nr; i++) stl += lr[i]; 9419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(stl, &l2gidxs)); 9425b003df0Sstefano_zampini for (i = 0, stl = 0; i < nr; i++) { 9435e3038f0Sstefano_zampini Mat usedmat; 9445e3038f0Sstefano_zampini Mat_IS *matis; 9455e3038f0Sstefano_zampini const PetscInt *idxs; 9465e3038f0Sstefano_zampini 9475e3038f0Sstefano_zampini /* local IS for local NEST */ 9489566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, lr[i], stl, 1, &islrow[i])); 9495e3038f0Sstefano_zampini 9505e3038f0Sstefano_zampini /* l2gmap */ 9515e3038f0Sstefano_zampini j = 0; 9525e3038f0Sstefano_zampini usedmat = nest[i][j]; 9539e7b2b25Sstefano_zampini while (!usedmat && j < nc - 1) usedmat = nest[i][++j]; 95428b400f6SJacob Faibussowitsch PetscCheck(usedmat, comm, PETSC_ERR_SUP, "Cannot find valid row mat"); 9559e7b2b25Sstefano_zampini 9569e7b2b25Sstefano_zampini if (istrans[i * nc + j]) { 9579e7b2b25Sstefano_zampini Mat T; 9589566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(usedmat, &T)); 9599e7b2b25Sstefano_zampini usedmat = T; 9609e7b2b25Sstefano_zampini } 9615e3038f0Sstefano_zampini matis = (Mat_IS *)(usedmat->data); 9629566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isrow[i], &idxs)); 9639e7b2b25Sstefano_zampini if (istrans[i * nc + j]) { 9649566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->csf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 9659566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->csf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 9669e7b2b25Sstefano_zampini } else { 9679566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 9689566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 9699e7b2b25Sstefano_zampini } 9709566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(isrow[i], &idxs)); 9715e3038f0Sstefano_zampini stl += lr[i]; 9725e3038f0Sstefano_zampini } 9739566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(comm, 1, stl, l2gidxs, PETSC_OWN_POINTER, &rl2g)); 9745e3038f0Sstefano_zampini 9755e3038f0Sstefano_zampini /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */ 9765e3038f0Sstefano_zampini for (i = 0, stl = 0; i < nc; i++) stl += lc[i]; 9779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(stl, &l2gidxs)); 9785b003df0Sstefano_zampini for (i = 0, stl = 0; i < nc; i++) { 9795e3038f0Sstefano_zampini Mat usedmat; 9805e3038f0Sstefano_zampini Mat_IS *matis; 9815e3038f0Sstefano_zampini const PetscInt *idxs; 9825e3038f0Sstefano_zampini 9835e3038f0Sstefano_zampini /* local IS for local NEST */ 9849566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, lc[i], stl, 1, &islcol[i])); 9855e3038f0Sstefano_zampini 9865e3038f0Sstefano_zampini /* l2gmap */ 9875e3038f0Sstefano_zampini j = 0; 9885e3038f0Sstefano_zampini usedmat = nest[j][i]; 9899e7b2b25Sstefano_zampini while (!usedmat && j < nr - 1) usedmat = nest[++j][i]; 99028b400f6SJacob Faibussowitsch PetscCheck(usedmat, comm, PETSC_ERR_SUP, "Cannot find valid column mat"); 9919e7b2b25Sstefano_zampini if (istrans[j * nc + i]) { 9929e7b2b25Sstefano_zampini Mat T; 9939566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(usedmat, &T)); 9949e7b2b25Sstefano_zampini usedmat = T; 9959e7b2b25Sstefano_zampini } 9965e3038f0Sstefano_zampini matis = (Mat_IS *)(usedmat->data); 9979566063dSJacob Faibussowitsch PetscCall(ISGetIndices(iscol[i], &idxs)); 9989e7b2b25Sstefano_zampini if (istrans[j * nc + i]) { 9999566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 10009566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 10019e7b2b25Sstefano_zampini } else { 10029566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->csf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 10039566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->csf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 10049e7b2b25Sstefano_zampini } 10059566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(iscol[i], &idxs)); 10065e3038f0Sstefano_zampini stl += lc[i]; 10075e3038f0Sstefano_zampini } 10089566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(comm, 1, stl, l2gidxs, PETSC_OWN_POINTER, &cl2g)); 10095e3038f0Sstefano_zampini 10105e3038f0Sstefano_zampini /* Create MATIS */ 10119566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &B)); 10129566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N)); 10139566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(A, &rbs, &cbs)); 10149566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(B, rbs, cbs)); 10159566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATIS)); 10169566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(B, MATNEST)); 10178546b261SStefano Zampini { /* hack : avoid setup of scatters */ 10188546b261SStefano Zampini Mat_IS *matis = (Mat_IS *)(B->data); 10198546b261SStefano Zampini matis->islocalref = PETSC_TRUE; 10208546b261SStefano Zampini } 10219566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B, rl2g, cl2g)); 10229566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 10239566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 10249566063dSJacob Faibussowitsch PetscCall(MatCreateNest(PETSC_COMM_SELF, nr, islrow, nc, islcol, snest, &lA)); 10259566063dSJacob Faibussowitsch PetscCall(MatNestSetVecType(lA, VECNEST)); 10269e7b2b25Sstefano_zampini for (i = 0; i < nr * nc; i++) { 102748a46eb9SPierre Jolivet if (istrans[i]) PetscCall(MatDestroy(&snest[i])); 10289e7b2b25Sstefano_zampini } 10299566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B, lA)); 10309566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lA)); 10318546b261SStefano Zampini { /* hack : setup of scatters done here */ 10328546b261SStefano Zampini Mat_IS *matis = (Mat_IS *)(B->data); 10338546b261SStefano Zampini 10348546b261SStefano Zampini matis->islocalref = PETSC_FALSE; 10359566063dSJacob Faibussowitsch PetscCall(MatISSetUpScatters_Private(B)); 10368546b261SStefano Zampini } 10379566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 10389566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 10395e3038f0Sstefano_zampini if (reuse == MAT_INPLACE_MATRIX) { 10409566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &B)); 10415e3038f0Sstefano_zampini } else { 10425e3038f0Sstefano_zampini *newmat = B; 10435e3038f0Sstefano_zampini } 10445e3038f0Sstefano_zampini } else { 10455e3038f0Sstefano_zampini if (lreuse) { 10469566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*newmat, &lA)); 10475e3038f0Sstefano_zampini for (i = 0; i < nr; i++) { 10485e3038f0Sstefano_zampini for (j = 0; j < nc; j++) { 10495e3038f0Sstefano_zampini if (snest[i * nc + j]) { 10509566063dSJacob Faibussowitsch PetscCall(MatNestSetSubMat(lA, i, j, snest[i * nc + j])); 105148a46eb9SPierre Jolivet if (istrans[i * nc + j]) PetscCall(MatDestroy(&snest[i * nc + j])); 10525e3038f0Sstefano_zampini } 10535e3038f0Sstefano_zampini } 10545e3038f0Sstefano_zampini } 10555e3038f0Sstefano_zampini } else { 10565b003df0Sstefano_zampini PetscInt stl; 10575b003df0Sstefano_zampini for (i = 0, stl = 0; i < nr; i++) { 10589566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, lr[i], stl, 1, &islrow[i])); 10595b003df0Sstefano_zampini stl += lr[i]; 10605e3038f0Sstefano_zampini } 10615b003df0Sstefano_zampini for (i = 0, stl = 0; i < nc; i++) { 10629566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, lc[i], stl, 1, &islcol[i])); 10635b003df0Sstefano_zampini stl += lc[i]; 10645e3038f0Sstefano_zampini } 10659566063dSJacob Faibussowitsch PetscCall(MatCreateNest(PETSC_COMM_SELF, nr, islrow, nc, islcol, snest, &lA)); 1066ab4d48faSStefano Zampini for (i = 0; i < nr * nc; i++) { 106748a46eb9SPierre Jolivet if (istrans[i]) PetscCall(MatDestroy(&snest[i])); 1068ab4d48faSStefano Zampini } 10699566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*newmat, lA)); 10709566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lA)); 10715e3038f0Sstefano_zampini } 10729566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*newmat, MAT_FINAL_ASSEMBLY)); 10739566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*newmat, MAT_FINAL_ASSEMBLY)); 10745e3038f0Sstefano_zampini } 10755e3038f0Sstefano_zampini 10765b003df0Sstefano_zampini /* Create local matrix in MATNEST format */ 10775b003df0Sstefano_zampini convert = PETSC_FALSE; 10789566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)A)->prefix, "-matis_convert_local_nest", &convert, NULL)); 10795b003df0Sstefano_zampini if (convert) { 10805b003df0Sstefano_zampini Mat M; 10815b003df0Sstefano_zampini MatISLocalFields lf; 10825b003df0Sstefano_zampini PetscContainer c; 10835b003df0Sstefano_zampini 10849566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*newmat, &lA)); 10859566063dSJacob Faibussowitsch PetscCall(MatConvert(lA, MATAIJ, MAT_INITIAL_MATRIX, &M)); 10869566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*newmat, M)); 10879566063dSJacob Faibussowitsch PetscCall(MatDestroy(&M)); 10885b003df0Sstefano_zampini 10895b003df0Sstefano_zampini /* attach local fields to the matrix */ 10909566063dSJacob Faibussowitsch PetscCall(PetscNew(&lf)); 10919566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nr, &lf->rf, nc, &lf->cf)); 10925b003df0Sstefano_zampini for (i = 0; i < nr; i++) { 10935b003df0Sstefano_zampini PetscInt n, st; 10945b003df0Sstefano_zampini 10959566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(islrow[i], &n)); 10969566063dSJacob Faibussowitsch PetscCall(ISStrideGetInfo(islrow[i], &st, NULL)); 10979566063dSJacob Faibussowitsch PetscCall(ISCreateStride(comm, n, st, 1, &lf->rf[i])); 10985b003df0Sstefano_zampini } 10995b003df0Sstefano_zampini for (i = 0; i < nc; i++) { 11005b003df0Sstefano_zampini PetscInt n, st; 11015b003df0Sstefano_zampini 11029566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(islcol[i], &n)); 11039566063dSJacob Faibussowitsch PetscCall(ISStrideGetInfo(islcol[i], &st, NULL)); 11049566063dSJacob Faibussowitsch PetscCall(ISCreateStride(comm, n, st, 1, &lf->cf[i])); 11055b003df0Sstefano_zampini } 11065b003df0Sstefano_zampini lf->nr = nr; 11075b003df0Sstefano_zampini lf->nc = nc; 11089566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)), &c)); 11099566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(c, lf)); 11109566063dSJacob Faibussowitsch PetscCall(PetscContainerSetUserDestroy(c, MatISContainerDestroyFields_Private)); 11119566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)(*newmat), "_convert_nest_lfields", (PetscObject)c)); 11129566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&c)); 11135b003df0Sstefano_zampini } 11145b003df0Sstefano_zampini 11155e3038f0Sstefano_zampini /* Free workspace */ 111648a46eb9SPierre Jolivet for (i = 0; i < nr; i++) PetscCall(ISDestroy(&islrow[i])); 111748a46eb9SPierre Jolivet for (i = 0; i < nc; i++) PetscCall(ISDestroy(&islcol[i])); 11189566063dSJacob Faibussowitsch PetscCall(PetscFree6(isrow, iscol, islrow, islcol, snest, istrans)); 11199566063dSJacob Faibussowitsch PetscCall(PetscFree2(lr, lc)); 11205e3038f0Sstefano_zampini PetscFunctionReturn(0); 11215e3038f0Sstefano_zampini } 11225e3038f0Sstefano_zampini 11239371c9d4SSatish Balay static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r) { 1124ad219c80Sstefano_zampini Mat_IS *matis = (Mat_IS *)A->data; 1125ad219c80Sstefano_zampini Vec ll, rr; 1126ad219c80Sstefano_zampini const PetscScalar *Y, *X; 1127ad219c80Sstefano_zampini PetscScalar *x, *y; 1128ad219c80Sstefano_zampini 1129ad219c80Sstefano_zampini PetscFunctionBegin; 1130ad219c80Sstefano_zampini if (l) { 1131ad219c80Sstefano_zampini ll = matis->y; 11329566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(l, &Y)); 11339566063dSJacob Faibussowitsch PetscCall(VecGetArray(ll, &y)); 11349566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_SCALAR, Y, y, MPI_REPLACE)); 1135ad219c80Sstefano_zampini } else { 1136ad219c80Sstefano_zampini ll = NULL; 1137ad219c80Sstefano_zampini } 1138ad219c80Sstefano_zampini if (r) { 1139ad219c80Sstefano_zampini rr = matis->x; 11409566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(r, &X)); 11419566063dSJacob Faibussowitsch PetscCall(VecGetArray(rr, &x)); 11429566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->csf, MPIU_SCALAR, X, x, MPI_REPLACE)); 1143ad219c80Sstefano_zampini } else { 1144ad219c80Sstefano_zampini rr = NULL; 1145ad219c80Sstefano_zampini } 1146ad219c80Sstefano_zampini if (ll) { 11479566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_SCALAR, Y, y, MPI_REPLACE)); 11489566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(l, &Y)); 11499566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(ll, &y)); 1150ad219c80Sstefano_zampini } 1151ad219c80Sstefano_zampini if (rr) { 11529566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->csf, MPIU_SCALAR, X, x, MPI_REPLACE)); 11539566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(r, &X)); 11549566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(rr, &x)); 1155ad219c80Sstefano_zampini } 11569566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(matis->A, ll, rr)); 1157ad219c80Sstefano_zampini PetscFunctionReturn(0); 1158ad219c80Sstefano_zampini } 1159ad219c80Sstefano_zampini 11609371c9d4SSatish Balay static PetscErrorCode MatGetInfo_IS(Mat A, MatInfoType flag, MatInfo *ginfo) { 11617fa8f2d3SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 11627fa8f2d3SStefano Zampini MatInfo info; 11633966268fSBarry Smith PetscLogDouble isend[6], irecv[6]; 11647fa8f2d3SStefano Zampini PetscInt bs; 11657fa8f2d3SStefano Zampini 11667fa8f2d3SStefano Zampini PetscFunctionBegin; 11679566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 1168a2ccb5f9Sstefano_zampini if (matis->A->ops->getinfo) { 11699566063dSJacob Faibussowitsch PetscCall(MatGetInfo(matis->A, MAT_LOCAL, &info)); 11707fa8f2d3SStefano Zampini isend[0] = info.nz_used; 11717fa8f2d3SStefano Zampini isend[1] = info.nz_allocated; 11727fa8f2d3SStefano Zampini isend[2] = info.nz_unneeded; 11737fa8f2d3SStefano Zampini isend[3] = info.memory; 11747fa8f2d3SStefano Zampini isend[4] = info.mallocs; 1175a2ccb5f9Sstefano_zampini } else { 1176a2ccb5f9Sstefano_zampini isend[0] = 0.; 1177a2ccb5f9Sstefano_zampini isend[1] = 0.; 1178a2ccb5f9Sstefano_zampini isend[2] = 0.; 1179a2ccb5f9Sstefano_zampini isend[3] = 0.; 1180a2ccb5f9Sstefano_zampini isend[4] = 0.; 1181a2ccb5f9Sstefano_zampini } 1182314ce898Sstefano_zampini isend[5] = matis->A->num_ass; 11837fa8f2d3SStefano Zampini if (flag == MAT_LOCAL) { 11847fa8f2d3SStefano Zampini ginfo->nz_used = isend[0]; 11857fa8f2d3SStefano Zampini ginfo->nz_allocated = isend[1]; 11867fa8f2d3SStefano Zampini ginfo->nz_unneeded = isend[2]; 11877fa8f2d3SStefano Zampini ginfo->memory = isend[3]; 11887fa8f2d3SStefano Zampini ginfo->mallocs = isend[4]; 1189314ce898Sstefano_zampini ginfo->assemblies = isend[5]; 11907fa8f2d3SStefano Zampini } else if (flag == MAT_GLOBAL_MAX) { 11911c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(isend, irecv, 6, MPIU_PETSCLOGDOUBLE, MPI_MAX, PetscObjectComm((PetscObject)A))); 11927fa8f2d3SStefano Zampini 11937fa8f2d3SStefano Zampini ginfo->nz_used = irecv[0]; 11947fa8f2d3SStefano Zampini ginfo->nz_allocated = irecv[1]; 11957fa8f2d3SStefano Zampini ginfo->nz_unneeded = irecv[2]; 11967fa8f2d3SStefano Zampini ginfo->memory = irecv[3]; 11977fa8f2d3SStefano Zampini ginfo->mallocs = irecv[4]; 1198314ce898Sstefano_zampini ginfo->assemblies = irecv[5]; 11997fa8f2d3SStefano Zampini } else if (flag == MAT_GLOBAL_SUM) { 12001c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(isend, irecv, 5, MPIU_PETSCLOGDOUBLE, MPI_SUM, 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]; 12077fa8f2d3SStefano Zampini ginfo->assemblies = A->num_ass; 12087fa8f2d3SStefano Zampini } 12097fa8f2d3SStefano Zampini ginfo->block_size = bs; 12107fa8f2d3SStefano Zampini ginfo->fill_ratio_given = 0; 12117fa8f2d3SStefano Zampini ginfo->fill_ratio_needed = 0; 12127fa8f2d3SStefano Zampini ginfo->factor_mallocs = 0; 12135e3038f0Sstefano_zampini PetscFunctionReturn(0); 12145e3038f0Sstefano_zampini } 12155e3038f0Sstefano_zampini 12169371c9d4SSatish Balay static PetscErrorCode MatTranspose_IS(Mat A, MatReuse reuse, Mat *B) { 1217d7f69cd0SStefano Zampini Mat C, lC, lA; 1218d7f69cd0SStefano Zampini 1219d7f69cd0SStefano Zampini PetscFunctionBegin; 12207fb60732SBarry Smith if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *B)); 1221cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) { 1222cf37664fSBarry Smith ISLocalToGlobalMapping rl2g, cl2g; 12239566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 12249566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, A->cmap->n, A->rmap->n, A->cmap->N, A->rmap->N)); 12259566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(C, PetscAbs(A->cmap->bs), PetscAbs(A->rmap->bs))); 12269566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATIS)); 12279566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(A, &rl2g, &cl2g)); 12289566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(C, cl2g, rl2g)); 1229e432b41dSStefano Zampini } else C = *B; 1230d7f69cd0SStefano Zampini 1231d7f69cd0SStefano Zampini /* perform local transposition */ 12329566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A, &lA)); 12339566063dSJacob Faibussowitsch PetscCall(MatTranspose(lA, MAT_INITIAL_MATRIX, &lC)); 12349566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(lC, lA->cmap->mapping, lA->rmap->mapping)); 12359566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(C, lC)); 12369566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lC)); 1237d7f69cd0SStefano Zampini 1238cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) { 1239d7f69cd0SStefano Zampini *B = C; 1240d7f69cd0SStefano Zampini } else { 12419566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(A, &C)); 1242d7f69cd0SStefano Zampini } 12439566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY)); 12449566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY)); 1245d7f69cd0SStefano Zampini PetscFunctionReturn(0); 1246d7f69cd0SStefano Zampini } 1247d7f69cd0SStefano Zampini 12489371c9d4SSatish Balay static PetscErrorCode MatDiagonalSet_IS(Mat A, Vec D, InsertMode insmode) { 12493fd1c9e7SStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 12503fd1c9e7SStefano Zampini 12513fd1c9e7SStefano Zampini PetscFunctionBegin; 12524b89b9cdSStefano Zampini if (D) { /* MatShift_IS pass D = NULL */ 12539566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, D, is->y, INSERT_VALUES, SCATTER_FORWARD)); 12549566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, D, is->y, INSERT_VALUES, SCATTER_FORWARD)); 12553fd1c9e7SStefano Zampini } 12569566063dSJacob Faibussowitsch PetscCall(VecPointwiseDivide(is->y, is->y, is->counter)); 12579566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(is->A, is->y, insmode)); 12583fd1c9e7SStefano Zampini PetscFunctionReturn(0); 12593fd1c9e7SStefano Zampini } 12603fd1c9e7SStefano Zampini 12619371c9d4SSatish Balay static PetscErrorCode MatShift_IS(Mat A, PetscScalar a) { 12624b89b9cdSStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 12633fd1c9e7SStefano Zampini 12643fd1c9e7SStefano Zampini PetscFunctionBegin; 12659566063dSJacob Faibussowitsch PetscCall(VecSet(is->y, a)); 12669566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet_IS(A, NULL, ADD_VALUES)); 12673fd1c9e7SStefano Zampini PetscFunctionReturn(0); 12683fd1c9e7SStefano Zampini } 12693fd1c9e7SStefano Zampini 12709371c9d4SSatish Balay static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) { 1271f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION], cols_l[MATIS_MAX_ENTRIES_INSERTION]; 1272f26d0771SStefano Zampini 1273f26d0771SStefano Zampini PetscFunctionBegin; 1274aed4548fSBarry 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); 12759566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(A->rmap->mapping, m, rows, rows_l)); 12769566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(A->cmap->mapping, n, cols, cols_l)); 12779566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal_IS(A, m, rows_l, n, cols_l, values, addv)); 1278f26d0771SStefano Zampini PetscFunctionReturn(0); 1279f26d0771SStefano Zampini } 1280f26d0771SStefano Zampini 12819371c9d4SSatish Balay static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) { 1282f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION], cols_l[MATIS_MAX_ENTRIES_INSERTION]; 1283f26d0771SStefano Zampini 1284f26d0771SStefano Zampini PetscFunctionBegin; 1285aed4548fSBarry 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); 12869566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(A->rmap->mapping, m, rows, rows_l)); 12879566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(A->cmap->mapping, n, cols, cols_l)); 12889566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlockedLocal_IS(A, m, rows_l, n, cols_l, values, addv)); 1289f26d0771SStefano Zampini PetscFunctionReturn(0); 1290f26d0771SStefano Zampini } 1291f26d0771SStefano Zampini 12929371c9d4SSatish Balay static PetscErrorCode MatCreateSubMatrix_IS(Mat mat, IS irow, IS icol, MatReuse scall, Mat *newmat) { 1293a8116848SStefano Zampini Mat locmat, newlocmat; 1294a8116848SStefano Zampini Mat_IS *newmatis; 1295a8116848SStefano Zampini const PetscInt *idxs; 1296a8116848SStefano Zampini PetscInt i, m, n; 1297a8116848SStefano Zampini 1298a8116848SStefano Zampini PetscFunctionBegin; 1299a8116848SStefano Zampini if (scall == MAT_REUSE_MATRIX) { 1300a8116848SStefano Zampini PetscBool ismatis; 1301a8116848SStefano Zampini 13029566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)*newmat, MATIS, &ismatis)); 130328b400f6SJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_ARG_WRONG, "Cannot reuse matrix! Not of MATIS type"); 1304a8116848SStefano Zampini newmatis = (Mat_IS *)(*newmat)->data; 130528b400f6SJacob Faibussowitsch PetscCheck(newmatis->getsub_ris, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_ARG_WRONG, "Cannot reuse matrix! Misses local row IS"); 130628b400f6SJacob Faibussowitsch PetscCheck(newmatis->getsub_cis, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_ARG_WRONG, "Cannot reuse matrix! Misses local col IS"); 1307a8116848SStefano Zampini } 1308a8116848SStefano Zampini /* irow and icol may not have duplicate entries */ 130976bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 131076bd3646SJed Brown Vec rtest, ltest; 131176bd3646SJed Brown const PetscScalar *array; 131276bd3646SJed Brown 13139566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(mat, <est, &rtest)); 13149566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(irow, &n)); 13159566063dSJacob Faibussowitsch PetscCall(ISGetIndices(irow, &idxs)); 131648a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(VecSetValue(rtest, idxs[i], 1.0, ADD_VALUES)); 13179566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(rtest)); 13189566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(rtest)); 13199566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(rtest, &n)); 13209566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(rtest, &m, NULL)); 13219566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(rtest, &array)); 1322aed4548fSBarry 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])); 13239566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(rtest, &array)); 13249566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(irow, &idxs)); 13259566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(icol, &n)); 13269566063dSJacob Faibussowitsch PetscCall(ISGetIndices(icol, &idxs)); 132748a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(VecSetValue(ltest, idxs[i], 1.0, ADD_VALUES)); 13289566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(ltest)); 13299566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(ltest)); 13309566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(ltest, &n)); 13319566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(ltest, &m, NULL)); 13329566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(ltest, &array)); 1333aed4548fSBarry 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])); 13349566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(ltest, &array)); 13359566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(icol, &idxs)); 13369566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rtest)); 13379566063dSJacob Faibussowitsch PetscCall(VecDestroy(<est)); 133876bd3646SJed Brown } 1339a8116848SStefano Zampini if (scall == MAT_INITIAL_MATRIX) { 1340a8116848SStefano Zampini Mat_IS *matis = (Mat_IS *)mat->data; 1341a8116848SStefano Zampini ISLocalToGlobalMapping rl2g; 1342a8116848SStefano Zampini IS is; 1343a8116848SStefano Zampini PetscInt *lidxs, *lgidxs, *newgidxs; 1344306cf5c7SStefano Zampini PetscInt ll, newloc, irbs, icbs, arbs, acbs, rbs, cbs; 134594342113SStefano Zampini PetscBool cong; 1346a8116848SStefano Zampini MPI_Comm comm; 1347a8116848SStefano Zampini 13489566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 13499566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(mat, &arbs, &acbs)); 13509566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(irow, &irbs)); 13519566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(icol, &icbs)); 1352306cf5c7SStefano Zampini rbs = arbs == irbs ? irbs : 1; 1353306cf5c7SStefano Zampini cbs = acbs == icbs ? icbs : 1; 13549566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(irow, &m)); 13559566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(icol, &n)); 13569566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, newmat)); 13579566063dSJacob Faibussowitsch PetscCall(MatSetType(*newmat, MATIS)); 13589566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*newmat, m, n, PETSC_DECIDE, PETSC_DECIDE)); 13599566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(*newmat, rbs, cbs)); 1360a8116848SStefano Zampini /* communicate irow to their owners in the layout */ 13619566063dSJacob Faibussowitsch PetscCall(ISGetIndices(irow, &idxs)); 13629566063dSJacob Faibussowitsch PetscCall(PetscLayoutMapLocal(mat->rmap, m, idxs, &ll, &lidxs, &lgidxs)); 13639566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(irow, &idxs)); 13649566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata, matis->sf->nroots)); 1365a8116848SStefano Zampini for (i = 0; i < ll; i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i] + 1; 13669566063dSJacob Faibussowitsch PetscCall(PetscFree(lidxs)); 13679566063dSJacob Faibussowitsch PetscCall(PetscFree(lgidxs)); 13689566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 13699566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 13709371c9d4SSatish Balay for (i = 0, newloc = 0; i < matis->sf->nleaves; i++) 13719371c9d4SSatish Balay if (matis->sf_leafdata[i]) newloc++; 13729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newloc, &newgidxs)); 13739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newloc, &lidxs)); 13743d996552SStefano Zampini for (i = 0, newloc = 0; i < matis->sf->nleaves; i++) 1375a8116848SStefano Zampini if (matis->sf_leafdata[i]) { 1376a8116848SStefano Zampini lidxs[newloc] = i; 1377a8116848SStefano Zampini newgidxs[newloc++] = matis->sf_leafdata[i] - 1; 1378a8116848SStefano Zampini } 13799566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, newloc, newgidxs, PETSC_OWN_POINTER, &is)); 13809566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g)); 13819566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetBlockSize(rl2g, rbs)); 13829566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 1383a8116848SStefano Zampini /* local is to extract local submatrix */ 1384a8116848SStefano Zampini newmatis = (Mat_IS *)(*newmat)->data; 13859566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, newloc, lidxs, PETSC_OWN_POINTER, &newmatis->getsub_ris)); 13869566063dSJacob Faibussowitsch PetscCall(MatHasCongruentLayouts(mat, &cong)); 138794342113SStefano Zampini if (cong && irow == icol && matis->csf == matis->sf) { 13889566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*newmat, rl2g, rl2g)); 13899566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)newmatis->getsub_ris)); 1390a8116848SStefano Zampini newmatis->getsub_cis = newmatis->getsub_ris; 1391a8116848SStefano Zampini } else { 1392a8116848SStefano Zampini ISLocalToGlobalMapping cl2g; 1393a8116848SStefano Zampini 1394a8116848SStefano Zampini /* communicate icol to their owners in the layout */ 13959566063dSJacob Faibussowitsch PetscCall(ISGetIndices(icol, &idxs)); 13969566063dSJacob Faibussowitsch PetscCall(PetscLayoutMapLocal(mat->cmap, n, idxs, &ll, &lidxs, &lgidxs)); 13979566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(icol, &idxs)); 13989566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->csf_rootdata, matis->csf->nroots)); 1399a8116848SStefano Zampini for (i = 0; i < ll; i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i] + 1; 14009566063dSJacob Faibussowitsch PetscCall(PetscFree(lidxs)); 14019566063dSJacob Faibussowitsch PetscCall(PetscFree(lgidxs)); 14029566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->csf, MPIU_INT, matis->csf_rootdata, matis->csf_leafdata, MPI_REPLACE)); 14039566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->csf, MPIU_INT, matis->csf_rootdata, matis->csf_leafdata, MPI_REPLACE)); 14049371c9d4SSatish Balay for (i = 0, newloc = 0; i < matis->csf->nleaves; i++) 14059371c9d4SSatish Balay if (matis->csf_leafdata[i]) newloc++; 14069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newloc, &newgidxs)); 14079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newloc, &lidxs)); 14083d996552SStefano Zampini for (i = 0, newloc = 0; i < matis->csf->nleaves; i++) 1409a8116848SStefano Zampini if (matis->csf_leafdata[i]) { 1410a8116848SStefano Zampini lidxs[newloc] = i; 1411a8116848SStefano Zampini newgidxs[newloc++] = matis->csf_leafdata[i] - 1; 1412a8116848SStefano Zampini } 14139566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, newloc, newgidxs, PETSC_OWN_POINTER, &is)); 14149566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g)); 14159566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetBlockSize(cl2g, cbs)); 14169566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 1417a8116848SStefano Zampini /* local is to extract local submatrix */ 14189566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, newloc, lidxs, PETSC_OWN_POINTER, &newmatis->getsub_cis)); 14199566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*newmat, rl2g, cl2g)); 14209566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 1421a8116848SStefano Zampini } 14229566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 1423a8116848SStefano Zampini } else { 14249566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*newmat, &newlocmat)); 1425a8116848SStefano Zampini } 14269566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(mat, &locmat)); 1427a8116848SStefano Zampini newmatis = (Mat_IS *)(*newmat)->data; 14289566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(locmat, newmatis->getsub_ris, newmatis->getsub_cis, scall, &newlocmat)); 1429a8116848SStefano Zampini if (scall == MAT_INITIAL_MATRIX) { 14309566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*newmat, newlocmat)); 14319566063dSJacob Faibussowitsch PetscCall(MatDestroy(&newlocmat)); 1432a8116848SStefano Zampini } 14339566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*newmat, MAT_FINAL_ASSEMBLY)); 14349566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*newmat, MAT_FINAL_ASSEMBLY)); 1435a8116848SStefano Zampini PetscFunctionReturn(0); 1436a8116848SStefano Zampini } 1437a8116848SStefano Zampini 14389371c9d4SSatish Balay static PetscErrorCode MatCopy_IS(Mat A, Mat B, MatStructure str) { 14392b404112SStefano Zampini Mat_IS *a = (Mat_IS *)A->data, *b; 14402b404112SStefano Zampini PetscBool ismatis; 14412b404112SStefano Zampini 14422b404112SStefano Zampini PetscFunctionBegin; 14439566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)B, MATIS, &ismatis)); 144428b400f6SJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Need to be implemented"); 14452b404112SStefano Zampini b = (Mat_IS *)B->data; 14469566063dSJacob Faibussowitsch PetscCall(MatCopy(a->A, b->A, str)); 14479566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)B)); 14482b404112SStefano Zampini PetscFunctionReturn(0); 14492b404112SStefano Zampini } 14502b404112SStefano Zampini 14519371c9d4SSatish Balay static PetscErrorCode MatMissingDiagonal_IS(Mat A, PetscBool *missing, PetscInt *d) { 1452527b2640SStefano Zampini Vec v; 1453527b2640SStefano Zampini const PetscScalar *array; 1454527b2640SStefano Zampini PetscInt i, n; 14556bd84002SStefano Zampini 14566bd84002SStefano Zampini PetscFunctionBegin; 1457527b2640SStefano Zampini *missing = PETSC_FALSE; 14589566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, NULL, &v)); 14599566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(A, v)); 14609566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 14619566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &array)); 14629371c9d4SSatish Balay for (i = 0; i < n; i++) 14639371c9d4SSatish Balay if (array[i] == 0.) break; 14649566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &array)); 14659566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 1466527b2640SStefano Zampini if (i != n) *missing = PETSC_TRUE; 1467527b2640SStefano Zampini if (d) { 1468527b2640SStefano Zampini *d = -1; 1469527b2640SStefano Zampini if (*missing) { 1470527b2640SStefano Zampini PetscInt rstart; 14719566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rstart, NULL)); 1472527b2640SStefano Zampini *d = i + rstart; 1473527b2640SStefano Zampini } 1474527b2640SStefano Zampini } 14756bd84002SStefano Zampini PetscFunctionReturn(0); 14766bd84002SStefano Zampini } 14776bd84002SStefano Zampini 14789371c9d4SSatish Balay static PetscErrorCode MatISSetUpSF_IS(Mat B) { 147928f4e0baSStefano Zampini Mat_IS *matis = (Mat_IS *)(B->data); 148028f4e0baSStefano Zampini const PetscInt *gidxs; 14814f2d7cafSStefano Zampini PetscInt nleaves; 148228f4e0baSStefano Zampini 148328f4e0baSStefano Zampini PetscFunctionBegin; 14844f2d7cafSStefano Zampini if (matis->sf) PetscFunctionReturn(0); 14859566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)B), &matis->sf)); 14869566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->rmapping, &gidxs)); 14879566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->rmapping, &nleaves)); 14889566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(matis->sf, B->rmap, nleaves, NULL, PETSC_OWN_POINTER, gidxs)); 14899566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->rmapping, &gidxs)); 14909566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(matis->sf->nroots, &matis->sf_rootdata, matis->sf->nleaves, &matis->sf_leafdata)); 1491e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { /* setup SF for columns */ 14929566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->cmapping, &nleaves)); 14939566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)B), &matis->csf)); 14949566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->cmapping, &gidxs)); 14959566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(matis->csf, B->cmap, nleaves, NULL, PETSC_OWN_POINTER, gidxs)); 14969566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->cmapping, &gidxs)); 14979566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(matis->csf->nroots, &matis->csf_rootdata, matis->csf->nleaves, &matis->csf_leafdata)); 1498a8116848SStefano Zampini } else { 1499a8116848SStefano Zampini matis->csf = matis->sf; 1500a8116848SStefano Zampini matis->csf_leafdata = matis->sf_leafdata; 1501a8116848SStefano Zampini matis->csf_rootdata = matis->sf_rootdata; 1502a8116848SStefano Zampini } 150328f4e0baSStefano Zampini PetscFunctionReturn(0); 150428f4e0baSStefano Zampini } 15052e1947a5SStefano Zampini 1506eb82efa4SStefano Zampini /*@ 150711a5261eSBarry Smith MatISStoreL2L - Store local-to-local operators during the Galerkin process of computing MatPtAP. 150875d48cdbSStefano Zampini 1509d083f849SBarry Smith Collective 151075d48cdbSStefano Zampini 151175d48cdbSStefano Zampini Input Parameters: 151275d48cdbSStefano Zampini + A - the matrix 151375d48cdbSStefano Zampini - store - the boolean flag 151475d48cdbSStefano Zampini 151575d48cdbSStefano Zampini Level: advanced 151675d48cdbSStefano Zampini 1517db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateIS()`, `MatISSetPreallocation()`, `MatPtAP()` 151875d48cdbSStefano Zampini @*/ 15199371c9d4SSatish Balay PetscErrorCode MatISStoreL2L(Mat A, PetscBool store) { 152075d48cdbSStefano Zampini PetscFunctionBegin; 152175d48cdbSStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 152275d48cdbSStefano Zampini PetscValidType(A, 1); 152375d48cdbSStefano Zampini PetscValidLogicalCollectiveBool(A, store, 2); 1524cac4c232SBarry Smith PetscTryMethod(A, "MatISStoreL2L_C", (Mat, PetscBool), (A, store)); 152575d48cdbSStefano Zampini PetscFunctionReturn(0); 152675d48cdbSStefano Zampini } 152775d48cdbSStefano Zampini 15289371c9d4SSatish Balay static PetscErrorCode MatISStoreL2L_IS(Mat A, PetscBool store) { 152975d48cdbSStefano Zampini Mat_IS *matis = (Mat_IS *)(A->data); 153075d48cdbSStefano Zampini 153175d48cdbSStefano Zampini PetscFunctionBegin; 153275d48cdbSStefano Zampini matis->storel2l = store; 153348a46eb9SPierre Jolivet if (!store) PetscCall(PetscObjectCompose((PetscObject)(A), "_MatIS_PtAP_l2l", NULL)); 153475d48cdbSStefano Zampini PetscFunctionReturn(0); 153575d48cdbSStefano Zampini } 153675d48cdbSStefano Zampini 153775d48cdbSStefano Zampini /*@ 1538f03112d0SStefano Zampini MatISFixLocalEmpty - Compress out zero local rows from the local matrices 1539f03112d0SStefano Zampini 1540d083f849SBarry Smith Collective 1541f03112d0SStefano Zampini 1542f03112d0SStefano Zampini Input Parameters: 1543f03112d0SStefano Zampini + A - the matrix 1544f03112d0SStefano Zampini - fix - the boolean flag 1545f03112d0SStefano Zampini 1546f03112d0SStefano Zampini Level: advanced 1547f03112d0SStefano Zampini 154811a5261eSBarry Smith Note: 154911a5261eSBarry Smith When fix is true, new local matrices and l2g maps are generated during the final assembly process. 1550f03112d0SStefano Zampini 155111a5261eSBarry Smith .seealso: `MATIS`, `MatCreate()`, `MatCreateIS()`, `MatISSetPreallocation()`, `MatAssemblyEnd()`, `MAT_FINAL_ASSEMBLY` 1552f03112d0SStefano Zampini @*/ 15539371c9d4SSatish Balay PetscErrorCode MatISFixLocalEmpty(Mat A, PetscBool fix) { 1554f03112d0SStefano Zampini PetscFunctionBegin; 1555f03112d0SStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1556f03112d0SStefano Zampini PetscValidType(A, 1); 1557f03112d0SStefano Zampini PetscValidLogicalCollectiveBool(A, fix, 2); 1558cac4c232SBarry Smith PetscTryMethod(A, "MatISFixLocalEmpty_C", (Mat, PetscBool), (A, fix)); 1559f03112d0SStefano Zampini PetscFunctionReturn(0); 1560f03112d0SStefano Zampini } 1561f03112d0SStefano Zampini 15629371c9d4SSatish Balay static PetscErrorCode MatISFixLocalEmpty_IS(Mat A, PetscBool fix) { 1563f03112d0SStefano Zampini Mat_IS *matis = (Mat_IS *)(A->data); 1564f03112d0SStefano Zampini 1565f03112d0SStefano Zampini PetscFunctionBegin; 1566f03112d0SStefano Zampini matis->locempty = fix; 1567f03112d0SStefano Zampini PetscFunctionReturn(0); 1568f03112d0SStefano Zampini } 1569f03112d0SStefano Zampini 1570f03112d0SStefano Zampini /*@ 157111a5261eSBarry Smith MatISSetPreallocation - Preallocates memory for a `MATIS` parallel matrix. 1572a88811baSStefano Zampini 1573d083f849SBarry Smith Collective 1574a88811baSStefano Zampini 1575a88811baSStefano Zampini Input Parameters: 1576a88811baSStefano Zampini + B - the matrix 1577a88811baSStefano Zampini . d_nz - number of nonzeros per row in DIAGONAL portion of local submatrix 1578a88811baSStefano Zampini (same value is used for all local rows) 1579a88811baSStefano Zampini . d_nnz - array containing the number of nonzeros in the various rows of the 1580a88811baSStefano Zampini DIAGONAL portion of the local submatrix (possibly different for each row) 1581a88811baSStefano Zampini or NULL, if d_nz is used to specify the nonzero structure. 1582a88811baSStefano Zampini The size of this array is equal to the number of local rows, i.e 'm'. 1583a88811baSStefano Zampini For matrices that will be factored, you must leave room for (and set) 1584a88811baSStefano Zampini the diagonal entry even if it is zero. 1585a88811baSStefano Zampini . o_nz - number of nonzeros per row in the OFF-DIAGONAL portion of local 1586a88811baSStefano Zampini submatrix (same value is used for all local rows). 1587a88811baSStefano Zampini - o_nnz - array containing the number of nonzeros in the various rows of the 1588a88811baSStefano Zampini OFF-DIAGONAL portion of the local submatrix (possibly different for 1589a88811baSStefano Zampini each row) or NULL, if o_nz is used to specify the nonzero 1590a88811baSStefano Zampini structure. The size of this array is equal to the number 1591a88811baSStefano Zampini of local rows, i.e 'm'. 1592a88811baSStefano Zampini 1593a88811baSStefano Zampini If the *_nnz parameter is given then the *_nz parameter is ignored 1594a88811baSStefano Zampini 1595a88811baSStefano Zampini Level: intermediate 1596a88811baSStefano Zampini 159711a5261eSBarry Smith Note: 159811a5261eSBarry Smith This function has the same interface as the `MATMPIAIJ` preallocation routine in order to simplify the transition 159911a5261eSBarry Smith from the asssembled format to the unassembled one. It overestimates the preallocation of `MATIS` local 1600a88811baSStefano Zampini matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects. 1601a88811baSStefano Zampini 1602db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateIS()`, `MatMPIAIJSetPreallocation()`, `MatISGetLocalMat()`, `MATIS` 1603a88811baSStefano Zampini @*/ 16049371c9d4SSatish Balay PetscErrorCode MatISSetPreallocation(Mat B, PetscInt d_nz, const PetscInt d_nnz[], PetscInt o_nz, const PetscInt o_nnz[]) { 16052e1947a5SStefano Zampini PetscFunctionBegin; 16062e1947a5SStefano Zampini PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 16072e1947a5SStefano Zampini PetscValidType(B, 1); 1608cac4c232SBarry Smith PetscTryMethod(B, "MatISSetPreallocation_C", (Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]), (B, d_nz, d_nnz, o_nz, o_nnz)); 16092e1947a5SStefano Zampini PetscFunctionReturn(0); 16102e1947a5SStefano Zampini } 16112e1947a5SStefano Zampini 1612844bd0d7SStefano Zampini /* this is used by DMDA */ 16139371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatISSetPreallocation_IS(Mat B, PetscInt d_nz, const PetscInt d_nnz[], PetscInt o_nz, const PetscInt o_nnz[]) { 16142e1947a5SStefano Zampini Mat_IS *matis = (Mat_IS *)(B->data); 161528f4e0baSStefano Zampini PetscInt bs, i, nlocalcols; 16162e1947a5SStefano Zampini 16172e1947a5SStefano Zampini PetscFunctionBegin; 16189566063dSJacob Faibussowitsch PetscCall(MatSetUp(B)); 16199371c9d4SSatish Balay if (!d_nnz) 16209371c9d4SSatish Balay for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] = d_nz; 16219371c9d4SSatish Balay else 16229371c9d4SSatish Balay for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] = d_nnz[i]; 16234f2d7cafSStefano Zampini 16249371c9d4SSatish Balay if (!o_nnz) 16259371c9d4SSatish Balay for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] += o_nz; 16269371c9d4SSatish Balay else 16279371c9d4SSatish Balay for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] += o_nnz[i]; 16284f2d7cafSStefano Zampini 16299566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 16309566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, NULL, &nlocalcols)); 16319566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(matis->A, &bs)); 16329566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 16334f2d7cafSStefano Zampini 16344f2d7cafSStefano Zampini for (i = 0; i < matis->sf->nleaves; i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i], nlocalcols); 16359566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(matis->A, 0, matis->sf_leafdata)); 16360f2f62c7SStefano Zampini #if defined(PETSC_HAVE_HYPRE) 16379566063dSJacob Faibussowitsch PetscCall(MatHYPRESetPreallocation(matis->A, 0, matis->sf_leafdata, 0, NULL)); 16380f2f62c7SStefano Zampini #endif 16394f2d7cafSStefano Zampini 1640fc989267SStefano Zampini for (i = 0; i < matis->sf->nleaves / bs; i++) { 1641fc989267SStefano Zampini PetscInt b; 1642fc989267SStefano Zampini 1643fc989267SStefano Zampini matis->sf_leafdata[i] = matis->sf_leafdata[i * bs] / bs; 1644ad540459SPierre Jolivet for (b = 1; b < bs; b++) matis->sf_leafdata[i] = PetscMax(matis->sf_leafdata[i], matis->sf_leafdata[i * bs + b] / bs); 1645fc989267SStefano Zampini } 16469566063dSJacob Faibussowitsch PetscCall(MatSeqBAIJSetPreallocation(matis->A, bs, 0, matis->sf_leafdata)); 16474f2d7cafSStefano Zampini 164800a59248SStefano Zampini nlocalcols /= bs; 164900a59248SStefano Zampini for (i = 0; i < matis->sf->nleaves / bs; i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i], nlocalcols - i); 16509566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(matis->A, bs, 0, matis->sf_leafdata)); 16510f2f62c7SStefano Zampini 16520f2f62c7SStefano Zampini /* for other matrix types */ 16539566063dSJacob Faibussowitsch PetscCall(MatSetUp(matis->A)); 16542e1947a5SStefano Zampini PetscFunctionReturn(0); 16552e1947a5SStefano Zampini } 1656b4319ba4SBarry Smith 16579371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce) { 16583927de2eSStefano Zampini Mat_IS *matis = (Mat_IS *)(A->data); 16593927de2eSStefano Zampini PetscInt *my_dnz, *my_onz, *dnz, *onz, *mat_ranges, *row_ownership; 1660ecf5a873SStefano Zampini const PetscInt *global_indices_r, *global_indices_c; 16613927de2eSStefano Zampini PetscInt i, j, bs, rows, cols; 16623927de2eSStefano Zampini PetscInt lrows, lcols; 16633927de2eSStefano Zampini PetscInt local_rows, local_cols; 1664f03112d0SStefano Zampini PetscMPIInt size; 16653927de2eSStefano Zampini PetscBool isdense, issbaij; 16663927de2eSStefano Zampini 16673927de2eSStefano Zampini PetscFunctionBegin; 16689566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 16699566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &rows, &cols)); 16709566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 16719566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, &local_rows, &local_cols)); 16729566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQDENSE, &isdense)); 16739566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQSBAIJ, &issbaij)); 16749566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->rmapping, &global_indices_r)); 1675e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { 16769566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->cmapping, &global_indices_c)); 16770dfc91b7SStefano Zampini } else global_indices_c = global_indices_r; 1678ecf5a873SStefano Zampini 16799566063dSJacob Faibussowitsch if (issbaij) PetscCall(MatGetRowUpperTriangular(matis->A)); 16803927de2eSStefano Zampini /* 1681ecf5a873SStefano Zampini An SF reduce is needed to sum up properly on shared rows. 16823927de2eSStefano Zampini Note that generally preallocation is not exact, since it overestimates nonzeros 16833927de2eSStefano Zampini */ 16849566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &lrows, &lcols)); 1685d0609cedSBarry Smith MatPreallocateBegin(PetscObjectComm((PetscObject)A), lrows, lcols, dnz, onz); 16863927de2eSStefano Zampini /* All processes need to compute entire row ownership */ 16879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rows, &row_ownership)); 16889566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRanges(A, (const PetscInt **)&mat_ranges)); 1689f03112d0SStefano Zampini for (i = 0; i < size; i++) { 16905f80ce2aSJacob Faibussowitsch for (j = mat_ranges[i]; j < mat_ranges[i + 1]; j++) row_ownership[j] = i; 16913927de2eSStefano Zampini } 16929566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangesColumn(A, (const PetscInt **)&mat_ranges)); 16933927de2eSStefano Zampini 16943927de2eSStefano Zampini /* 16953927de2eSStefano Zampini my_dnz and my_onz contains exact contribution to preallocation from each local mat 16963927de2eSStefano Zampini then, they will be summed up properly. This way, preallocation is always sufficient 16973927de2eSStefano Zampini */ 16989566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(local_rows, &my_dnz, local_rows, &my_onz)); 16993927de2eSStefano Zampini /* preallocation as a MATAIJ */ 17003927de2eSStefano Zampini if (isdense) { /* special case for dense local matrices */ 17013927de2eSStefano Zampini for (i = 0; i < local_rows; i++) { 170212dfadf8SStefano Zampini PetscInt owner = row_ownership[global_indices_r[i]]; 170312dfadf8SStefano Zampini for (j = 0; j < local_cols; j++) { 1704ecf5a873SStefano Zampini PetscInt index_col = global_indices_c[j]; 17053927de2eSStefano Zampini if (index_col > mat_ranges[owner] - 1 && index_col < mat_ranges[owner + 1]) { /* diag block */ 17063927de2eSStefano Zampini my_dnz[i] += 1; 17073927de2eSStefano Zampini } else { /* offdiag block */ 17083927de2eSStefano Zampini my_onz[i] += 1; 17093927de2eSStefano Zampini } 17103927de2eSStefano Zampini } 17113927de2eSStefano Zampini } 1712bb1015c3SStefano Zampini } else if (matis->A->ops->getrowij) { 1713bb1015c3SStefano Zampini const PetscInt *ii, *jj, *jptr; 1714bb1015c3SStefano Zampini PetscBool done; 17159566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(matis->A, 0, PETSC_FALSE, PETSC_FALSE, &local_rows, &ii, &jj, &done)); 17165f80ce2aSJacob Faibussowitsch PetscCheck(done, PetscObjectComm((PetscObject)(matis->A)), PETSC_ERR_PLIB, "Error in MatGetRowIJ"); 1717bb1015c3SStefano Zampini jptr = jj; 1718bb1015c3SStefano Zampini for (i = 0; i < local_rows; i++) { 1719bb1015c3SStefano Zampini PetscInt index_row = global_indices_r[i]; 1720bb1015c3SStefano Zampini for (j = 0; j < ii[i + 1] - ii[i]; j++, jptr++) { 1721bb1015c3SStefano Zampini PetscInt owner = row_ownership[index_row]; 1722bb1015c3SStefano Zampini PetscInt index_col = global_indices_c[*jptr]; 1723bb1015c3SStefano Zampini if (index_col > mat_ranges[owner] - 1 && index_col < mat_ranges[owner + 1]) { /* diag block */ 1724bb1015c3SStefano Zampini my_dnz[i] += 1; 1725bb1015c3SStefano Zampini } else { /* offdiag block */ 1726bb1015c3SStefano Zampini my_onz[i] += 1; 1727bb1015c3SStefano Zampini } 1728bb1015c3SStefano Zampini /* same as before, interchanging rows and cols */ 1729bb1015c3SStefano Zampini if (issbaij && index_col != index_row) { 1730bb1015c3SStefano Zampini owner = row_ownership[index_col]; 1731bb1015c3SStefano Zampini if (index_row > mat_ranges[owner] - 1 && index_row < mat_ranges[owner + 1]) { 1732bb1015c3SStefano Zampini my_dnz[*jptr] += 1; 1733bb1015c3SStefano Zampini } else { 1734bb1015c3SStefano Zampini my_onz[*jptr] += 1; 1735bb1015c3SStefano Zampini } 1736bb1015c3SStefano Zampini } 1737bb1015c3SStefano Zampini } 1738bb1015c3SStefano Zampini } 17399566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(matis->A, 0, PETSC_FALSE, PETSC_FALSE, &local_rows, &ii, &jj, &done)); 17405f80ce2aSJacob Faibussowitsch PetscCheck(done, PetscObjectComm((PetscObject)(matis->A)), PETSC_ERR_PLIB, "Error in MatRestoreRowIJ"); 1741bb1015c3SStefano Zampini } else { /* loop over rows and use MatGetRow */ 17423927de2eSStefano Zampini for (i = 0; i < local_rows; i++) { 17433927de2eSStefano Zampini const PetscInt *cols; 1744ecf5a873SStefano Zampini PetscInt ncols, index_row = global_indices_r[i]; 17459566063dSJacob Faibussowitsch PetscCall(MatGetRow(matis->A, i, &ncols, &cols, NULL)); 17463927de2eSStefano Zampini for (j = 0; j < ncols; j++) { 17473927de2eSStefano Zampini PetscInt owner = row_ownership[index_row]; 1748ecf5a873SStefano Zampini PetscInt index_col = global_indices_c[cols[j]]; 17493927de2eSStefano Zampini if (index_col > mat_ranges[owner] - 1 && index_col < mat_ranges[owner + 1]) { /* diag block */ 17503927de2eSStefano Zampini my_dnz[i] += 1; 17513927de2eSStefano Zampini } else { /* offdiag block */ 17523927de2eSStefano Zampini my_onz[i] += 1; 17533927de2eSStefano Zampini } 17543927de2eSStefano Zampini /* same as before, interchanging rows and cols */ 1755d9a9e74cSStefano Zampini if (issbaij && index_col != index_row) { 17563927de2eSStefano Zampini owner = row_ownership[index_col]; 17573927de2eSStefano Zampini if (index_row > mat_ranges[owner] - 1 && index_row < mat_ranges[owner + 1]) { 1758d9a9e74cSStefano Zampini my_dnz[cols[j]] += 1; 17593927de2eSStefano Zampini } else { 1760d9a9e74cSStefano Zampini my_onz[cols[j]] += 1; 17613927de2eSStefano Zampini } 17623927de2eSStefano Zampini } 17633927de2eSStefano Zampini } 17649566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(matis->A, i, &ncols, &cols, NULL)); 17653927de2eSStefano Zampini } 17663927de2eSStefano Zampini } 176748a46eb9SPierre Jolivet if (global_indices_c != global_indices_r) PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->cmapping, &global_indices_c)); 17689566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->rmapping, &global_indices_r)); 17699566063dSJacob Faibussowitsch PetscCall(PetscFree(row_ownership)); 1770ecf5a873SStefano Zampini 1771ecf5a873SStefano Zampini /* Reduce my_dnz and my_onz */ 17723927de2eSStefano Zampini if (maxreduce) { 17739566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, my_dnz, dnz, MPI_MAX)); 17749566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, my_onz, onz, MPI_MAX)); 17759566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, my_dnz, dnz, MPI_MAX)); 17769566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, my_onz, onz, MPI_MAX)); 17773927de2eSStefano Zampini } else { 17789566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, my_dnz, dnz, MPI_SUM)); 17799566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, my_onz, onz, MPI_SUM)); 17809566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, my_dnz, dnz, MPI_SUM)); 17819566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, my_onz, onz, MPI_SUM)); 17823927de2eSStefano Zampini } 17839566063dSJacob Faibussowitsch PetscCall(PetscFree2(my_dnz, my_onz)); 17843927de2eSStefano Zampini 17853927de2eSStefano Zampini /* Resize preallocation if overestimated */ 17863927de2eSStefano Zampini for (i = 0; i < lrows; i++) { 17873927de2eSStefano Zampini dnz[i] = PetscMin(dnz[i], lcols); 17883927de2eSStefano Zampini onz[i] = PetscMin(onz[i], cols - lcols); 17893927de2eSStefano Zampini } 17901670daf9Sstefano_zampini 17911670daf9Sstefano_zampini /* Set preallocation */ 17929566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B, A, A)); 17939566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B, 0, dnz)); 17949566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(B, 0, dnz, 0, onz)); 179553b44cf5SStefano Zampini for (i = 0; i < lrows; i += bs) { 179653b44cf5SStefano Zampini PetscInt b, d = dnz[i], o = onz[i]; 179753b44cf5SStefano Zampini 179853b44cf5SStefano Zampini for (b = 1; b < bs; b++) { 179953b44cf5SStefano Zampini d = PetscMax(d, dnz[i + b]); 180053b44cf5SStefano Zampini o = PetscMax(o, onz[i + b]); 180153b44cf5SStefano Zampini } 180253b44cf5SStefano Zampini dnz[i / bs] = PetscMin(d / bs + d % bs, lcols / bs); 180353b44cf5SStefano Zampini onz[i / bs] = PetscMin(o / bs + o % bs, (cols - lcols) / bs); 18043927de2eSStefano Zampini } 18059566063dSJacob Faibussowitsch PetscCall(MatSeqBAIJSetPreallocation(B, bs, 0, dnz)); 18069566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJSetPreallocation(B, bs, 0, dnz, 0, onz)); 18079566063dSJacob Faibussowitsch PetscCall(MatMPISBAIJSetPreallocation(B, bs, 0, dnz, 0, onz)); 1808d0609cedSBarry Smith MatPreallocateEnd(dnz, onz); 18099566063dSJacob Faibussowitsch if (issbaij) PetscCall(MatRestoreRowUpperTriangular(matis->A)); 18109566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 18113927de2eSStefano Zampini PetscFunctionReturn(0); 18123927de2eSStefano Zampini } 18133927de2eSStefano Zampini 18149371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatConvert_IS_XAIJ(Mat mat, MatType mtype, MatReuse reuse, Mat *M) { 1815b7ce53b6SStefano Zampini Mat_IS *matis = (Mat_IS *)(mat->data); 1816487b449aSStefano Zampini Mat local_mat, MT; 181753b44cf5SStefano Zampini PetscInt rbs, cbs, rows, cols, lrows, lcols; 1818b7ce53b6SStefano Zampini PetscInt local_rows, local_cols; 1819b9ed4604SStefano Zampini PetscBool isseqdense, isseqsbaij, isseqaij, isseqbaij; 1820f03112d0SStefano Zampini PetscMPIInt size; 18211683a169SBarry Smith const PetscScalar *array; 1822b7ce53b6SStefano Zampini 1823b7ce53b6SStefano Zampini PetscFunctionBegin; 18249566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1825f03112d0SStefano Zampini if (size == 1 && mat->rmap->N == matis->A->rmap->N && mat->cmap->N == matis->A->cmap->N) { 18261670daf9Sstefano_zampini Mat B; 182753b44cf5SStefano Zampini IS irows = NULL, icols = NULL; 1828487b449aSStefano Zampini PetscInt rbs, cbs; 18291670daf9Sstefano_zampini 18309566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->rmapping, &rbs)); 18319566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->cmapping, &cbs)); 183253b44cf5SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { /* check if l2g maps are one-to-one */ 183353b44cf5SStefano Zampini IS rows, cols; 183453b44cf5SStefano Zampini const PetscInt *ridxs, *cidxs; 183553b44cf5SStefano Zampini PetscInt i, nw, *work; 183653b44cf5SStefano Zampini 18379566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(matis->rmapping, &ridxs)); 18389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->rmapping, &nw)); 183953b44cf5SStefano Zampini nw = nw / rbs; 18409566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nw, &work)); 184153b44cf5SStefano Zampini for (i = 0; i < nw; i++) work[ridxs[i]] += 1; 18429371c9d4SSatish Balay for (i = 0; i < nw; i++) 18439371c9d4SSatish Balay if (!work[i] || work[i] > 1) break; 184453b44cf5SStefano Zampini if (i == nw) { 18459566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF, rbs, nw, ridxs, PETSC_USE_POINTER, &rows)); 18469566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(rows)); 18479566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(rows, PETSC_DECIDE, &irows)); 18489566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rows)); 184953b44cf5SStefano Zampini } 18509566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(matis->rmapping, &ridxs)); 18519566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 1852e432b41dSStefano Zampini if (irows && matis->rmapping != matis->cmapping) { 18539566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(matis->cmapping, &cidxs)); 18549566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->cmapping, &nw)); 185553b44cf5SStefano Zampini nw = nw / cbs; 18569566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nw, &work)); 185753b44cf5SStefano Zampini for (i = 0; i < nw; i++) work[cidxs[i]] += 1; 18589371c9d4SSatish Balay for (i = 0; i < nw; i++) 18599371c9d4SSatish Balay if (!work[i] || work[i] > 1) break; 186053b44cf5SStefano Zampini if (i == nw) { 18619566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF, cbs, nw, cidxs, PETSC_USE_POINTER, &cols)); 18629566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(cols)); 18639566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(cols, PETSC_DECIDE, &icols)); 18649566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cols)); 186553b44cf5SStefano Zampini } 18669566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(matis->cmapping, &cidxs)); 18679566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 186853b44cf5SStefano Zampini } else if (irows) { 18699566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)irows)); 187053b44cf5SStefano Zampini icols = irows; 187153b44cf5SStefano Zampini } 187253b44cf5SStefano Zampini } else { 18739566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)(*M), "_MatIS_IS_XAIJ_irows", (PetscObject *)&irows)); 18749566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)(*M), "_MatIS_IS_XAIJ_icols", (PetscObject *)&icols)); 18759566063dSJacob Faibussowitsch if (irows) PetscCall(PetscObjectReference((PetscObject)irows)); 18769566063dSJacob Faibussowitsch if (icols) PetscCall(PetscObjectReference((PetscObject)icols)); 187753b44cf5SStefano Zampini } 187853b44cf5SStefano Zampini if (!irows || !icols) { 18799566063dSJacob Faibussowitsch PetscCall(ISDestroy(&icols)); 18809566063dSJacob Faibussowitsch PetscCall(ISDestroy(&irows)); 188153b44cf5SStefano Zampini goto general_assembly; 188253b44cf5SStefano Zampini } 18839566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, mtype, MAT_INITIAL_MATRIX, &B)); 1884487b449aSStefano Zampini if (reuse != MAT_INPLACE_MATRIX) { 18859566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(B, irows, icols, reuse, M)); 18869566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)(*M), "_MatIS_IS_XAIJ_irows", (PetscObject)irows)); 18879566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)(*M), "_MatIS_IS_XAIJ_icols", (PetscObject)icols)); 1888487b449aSStefano Zampini } else { 1889487b449aSStefano Zampini Mat C; 1890487b449aSStefano Zampini 18919566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(B, irows, icols, MAT_INITIAL_MATRIX, &C)); 18929566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(mat, &C)); 1893487b449aSStefano Zampini } 18949566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 18959566063dSJacob Faibussowitsch PetscCall(ISDestroy(&icols)); 18969566063dSJacob Faibussowitsch PetscCall(ISDestroy(&irows)); 18977c03b4e8SStefano Zampini PetscFunctionReturn(0); 18987c03b4e8SStefano Zampini } 189953b44cf5SStefano Zampini general_assembly: 19009566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &rows, &cols)); 19019566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->rmapping, &rbs)); 19029566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->cmapping, &cbs)); 19039566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mat, &lrows, &lcols)); 19049566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, &local_rows, &local_cols)); 19059566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQDENSE, &isseqdense)); 19069566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQAIJ, &isseqaij)); 19079566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQBAIJ, &isseqbaij)); 19089566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQSBAIJ, &isseqsbaij)); 1909aed4548fSBarry Smith PetscCheck(isseqdense || isseqaij || isseqbaij || isseqsbaij, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)(matis->A))->type_name); 191076bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 191176bd3646SJed Brown PetscBool lb[4], bb[4]; 191276bd3646SJed Brown 1913b9ed4604SStefano Zampini lb[0] = isseqdense; 1914b9ed4604SStefano Zampini lb[1] = isseqaij; 1915b9ed4604SStefano Zampini lb[2] = isseqbaij; 1916b9ed4604SStefano Zampini lb[3] = isseqsbaij; 19171c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lb, bb, 4, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)mat))); 1918aed4548fSBarry Smith PetscCheck(bb[0] || bb[1] || bb[2] || bb[3], PETSC_COMM_SELF, PETSC_ERR_SUP, "Local matrices must have the same type"); 191976bd3646SJed Brown } 1920b7ce53b6SStefano Zampini 1921487b449aSStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 19229566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &MT)); 19239566063dSJacob Faibussowitsch PetscCall(MatSetSizes(MT, lrows, lcols, rows, cols)); 19249566063dSJacob Faibussowitsch PetscCall(MatSetType(MT, mtype)); 19259566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(MT, rbs, cbs)); 19269566063dSJacob Faibussowitsch PetscCall(MatISSetMPIXAIJPreallocation_Private(mat, MT, PETSC_FALSE)); 1927b7ce53b6SStefano Zampini } else { 192853b44cf5SStefano Zampini PetscInt mrbs, mcbs, mrows, mcols, mlrows, mlcols; 1929487b449aSStefano Zampini 1930b7ce53b6SStefano Zampini /* some checks */ 1931487b449aSStefano Zampini MT = *M; 19329566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(MT, &mrbs, &mcbs)); 19339566063dSJacob Faibussowitsch PetscCall(MatGetSize(MT, &mrows, &mcols)); 19349566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(MT, &mlrows, &mlcols)); 193508401ef6SPierre Jolivet PetscCheck(mrows == rows, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of rows (%" PetscInt_FMT " != %" PetscInt_FMT ")", rows, mrows); 193608401ef6SPierre Jolivet PetscCheck(mcols == cols, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of cols (%" PetscInt_FMT " != %" PetscInt_FMT ")", cols, mcols); 193708401ef6SPierre Jolivet PetscCheck(mlrows == lrows, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of local rows (%" PetscInt_FMT " != %" PetscInt_FMT ")", lrows, mlrows); 193808401ef6SPierre Jolivet PetscCheck(mlcols == lcols, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of local cols (%" PetscInt_FMT " != %" PetscInt_FMT ")", lcols, mlcols); 193908401ef6SPierre Jolivet PetscCheck(mrbs == rbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong row block size (%" PetscInt_FMT " != %" PetscInt_FMT ")", rbs, mrbs); 194008401ef6SPierre Jolivet PetscCheck(mcbs == cbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong col block size (%" PetscInt_FMT " != %" PetscInt_FMT ")", cbs, mcbs); 19419566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(MT)); 1942b7ce53b6SStefano Zampini } 1943d9a9e74cSStefano Zampini 19448546b261SStefano Zampini if (isseqsbaij || isseqbaij) { 19459566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &local_mat)); 19468546b261SStefano Zampini isseqaij = PETSC_TRUE; 1947d9a9e74cSStefano Zampini } else { 19489566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)matis->A)); 1949d9a9e74cSStefano Zampini local_mat = matis->A; 1950d9a9e74cSStefano Zampini } 1951686e3a49SStefano Zampini 1952b7ce53b6SStefano Zampini /* Set values */ 19539566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(MT, matis->rmapping, matis->cmapping)); 1954b9ed4604SStefano Zampini if (isseqdense) { /* special case for dense local matrices */ 195565066ba5SStefano Zampini PetscInt i, *dummy; 1956ecf5a873SStefano Zampini 19579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(PetscMax(local_rows, local_cols), &dummy)); 195865066ba5SStefano Zampini for (i = 0; i < PetscMax(local_rows, local_cols); i++) dummy[i] = i; 19599566063dSJacob Faibussowitsch PetscCall(MatSetOption(MT, MAT_ROW_ORIENTED, PETSC_FALSE)); 19609566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(local_mat, &array)); 19619566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(MT, local_rows, dummy, local_cols, dummy, array, ADD_VALUES)); 19629566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(local_mat, &array)); 19639566063dSJacob Faibussowitsch PetscCall(PetscFree(dummy)); 1964686e3a49SStefano Zampini } else if (isseqaij) { 19656afe12f5SStefano Zampini const PetscInt *blocks; 19666afe12f5SStefano Zampini PetscInt i, nvtxs, *xadj, *adjncy, nb; 1967686e3a49SStefano Zampini PetscBool done; 19681683a169SBarry Smith PetscScalar *sarray; 1969686e3a49SStefano Zampini 19709566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(local_mat, 0, PETSC_FALSE, PETSC_FALSE, &nvtxs, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &done)); 197128b400f6SJacob Faibussowitsch PetscCheck(done, PetscObjectComm((PetscObject)local_mat), PETSC_ERR_PLIB, "Error in MatGetRowIJ"); 19729566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(local_mat, &sarray)); 19739566063dSJacob Faibussowitsch PetscCall(MatGetVariableBlockSizes(local_mat, &nb, &blocks)); 19746afe12f5SStefano Zampini if (nb) { /* speed up assembly for special blocked matrices (used by BDDC) */ 19756afe12f5SStefano Zampini PetscInt sum; 19766afe12f5SStefano Zampini 19776afe12f5SStefano Zampini for (i = 0, sum = 0; i < nb; i++) sum += blocks[i]; 19786afe12f5SStefano Zampini if (sum == nvtxs) { 19796afe12f5SStefano Zampini PetscInt r; 19806afe12f5SStefano Zampini 19816afe12f5SStefano Zampini for (i = 0, r = 0; i < nb; i++) { 19826bdcaf15SBarry 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]); 19839566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(MT, blocks[i], adjncy + xadj[r], blocks[i], adjncy + xadj[r], sarray + xadj[r], ADD_VALUES)); 19846afe12f5SStefano Zampini r += blocks[i]; 19856afe12f5SStefano Zampini } 19866afe12f5SStefano Zampini } else { 198748a46eb9SPierre 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)); 19886afe12f5SStefano Zampini } 19896afe12f5SStefano Zampini } else { 199048a46eb9SPierre 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)); 19916afe12f5SStefano Zampini } 19929566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(local_mat, 0, PETSC_FALSE, PETSC_FALSE, &nvtxs, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &done)); 199328b400f6SJacob Faibussowitsch PetscCheck(done, PetscObjectComm((PetscObject)local_mat), PETSC_ERR_PLIB, "Error in MatRestoreRowIJ"); 19949566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(local_mat, &sarray)); 1995686e3a49SStefano Zampini } else { /* very basic values insertion for all other matrix types */ 1996ecf5a873SStefano Zampini PetscInt i; 1997c0962df8SStefano Zampini 1998686e3a49SStefano Zampini for (i = 0; i < local_rows; i++) { 1999686e3a49SStefano Zampini PetscInt j; 2000ecf5a873SStefano Zampini const PetscInt *local_indices_cols; 2001686e3a49SStefano Zampini 20029566063dSJacob Faibussowitsch PetscCall(MatGetRow(local_mat, i, &j, &local_indices_cols, &array)); 20039566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(MT, 1, &i, j, local_indices_cols, array, ADD_VALUES)); 20049566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(local_mat, i, &j, &local_indices_cols, &array)); 2005686e3a49SStefano Zampini } 2006b7ce53b6SStefano Zampini } 20079566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(MT, MAT_FINAL_ASSEMBLY)); 20089566063dSJacob Faibussowitsch PetscCall(MatDestroy(&local_mat)); 20099566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(MT, MAT_FINAL_ASSEMBLY)); 20101baa6e33SBarry Smith if (isseqdense) PetscCall(MatSetOption(MT, MAT_ROW_ORIENTED, PETSC_TRUE)); 2011487b449aSStefano Zampini if (reuse == MAT_INPLACE_MATRIX) { 20129566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(mat, &MT)); 2013487b449aSStefano Zampini } else if (reuse == MAT_INITIAL_MATRIX) { 2014487b449aSStefano Zampini *M = MT; 2015b7ce53b6SStefano Zampini } 2016b7ce53b6SStefano Zampini PetscFunctionReturn(0); 2017b7ce53b6SStefano Zampini } 2018b7ce53b6SStefano Zampini 2019b7ce53b6SStefano Zampini /*@ 202011a5261eSBarry Smith MatISGetMPIXAIJ - Converts `MATIS` matrix into a parallel `MATAIJ` format 2021b7ce53b6SStefano Zampini 2022d8d19677SJose E. Roman Input Parameters: 202311a5261eSBarry Smith + mat - the matrix (should be of type `MATIS`) 202411a5261eSBarry Smith - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 2025b7ce53b6SStefano Zampini 2026b7ce53b6SStefano Zampini Output Parameter: 202711a5261eSBarry Smith . newmat - the matrix in `MATAIJ` format 2028b7ce53b6SStefano Zampini 2029b7ce53b6SStefano Zampini Level: developer 2030b7ce53b6SStefano Zampini 203111a5261eSBarry Smith Note: 203211a5261eSBarry Smith This function has been deprecated and it will be removed in future releases. Update your code to use the `MatConvert()` interface. 2033b7ce53b6SStefano Zampini 2034db781477SPatrick Sanan .seealso: `MATIS`, `MatConvert()` 2035b7ce53b6SStefano Zampini @*/ 20369371c9d4SSatish Balay PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat) { 2037b7ce53b6SStefano Zampini PetscFunctionBegin; 2038b7ce53b6SStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2039b7ce53b6SStefano Zampini PetscValidLogicalCollectiveEnum(mat, reuse, 2); 2040b7ce53b6SStefano Zampini PetscValidPointer(newmat, 3); 2041487b449aSStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 2042b7ce53b6SStefano Zampini PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 3); 2043b7ce53b6SStefano Zampini PetscCheckSameComm(mat, 1, *newmat, 3); 204408401ef6SPierre Jolivet PetscCheck(mat != *newmat, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse the same matrix"); 2045b7ce53b6SStefano Zampini } 2046cac4c232SBarry Smith PetscUseMethod(mat, "MatISGetMPIXAIJ_C", (Mat, MatType, MatReuse, Mat *), (mat, MATAIJ, reuse, newmat)); 2047b7ce53b6SStefano Zampini PetscFunctionReturn(0); 2048b7ce53b6SStefano Zampini } 2049b7ce53b6SStefano Zampini 20509371c9d4SSatish Balay static PetscErrorCode MatDuplicate_IS(Mat mat, MatDuplicateOption op, Mat *newmat) { 2051ad6194a2SStefano Zampini Mat_IS *matis = (Mat_IS *)(mat->data); 2052c9225affSStefano Zampini PetscInt rbs, cbs, m, n, M, N; 2053ad6194a2SStefano Zampini Mat B, localmat; 2054ad6194a2SStefano Zampini 2055ad6194a2SStefano Zampini PetscFunctionBegin; 20569566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &rbs)); 20579566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &cbs)); 20589566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &M, &N)); 20599566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mat, &m, &n)); 20609566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 20619566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, m, n, M, N)); 20629566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(B, rbs == cbs ? rbs : 1)); 20639566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATIS)); 20649566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(B, matis->lmattype)); 20659566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B, mat->rmap->mapping, mat->cmap->mapping)); 20669566063dSJacob Faibussowitsch PetscCall(MatDuplicate(matis->A, op, &localmat)); 20679566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(localmat, matis->A->rmap->mapping, matis->A->cmap->mapping)); 20689566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B, localmat)); 20699566063dSJacob Faibussowitsch PetscCall(MatDestroy(&localmat)); 20709566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 20719566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 2072ad6194a2SStefano Zampini *newmat = B; 2073ad6194a2SStefano Zampini PetscFunctionReturn(0); 2074ad6194a2SStefano Zampini } 2075ad6194a2SStefano Zampini 20769371c9d4SSatish Balay static PetscErrorCode MatIsHermitian_IS(Mat A, PetscReal tol, PetscBool *flg) { 207769796d55SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 207869796d55SStefano Zampini PetscBool local_sym; 207969796d55SStefano Zampini 208069796d55SStefano Zampini PetscFunctionBegin; 20819566063dSJacob Faibussowitsch PetscCall(MatIsHermitian(matis->A, tol, &local_sym)); 20821c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&local_sym, flg, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 208369796d55SStefano Zampini PetscFunctionReturn(0); 208469796d55SStefano Zampini } 208569796d55SStefano Zampini 20869371c9d4SSatish Balay static PetscErrorCode MatIsSymmetric_IS(Mat A, PetscReal tol, PetscBool *flg) { 208769796d55SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 208869796d55SStefano Zampini PetscBool local_sym; 208969796d55SStefano Zampini 209069796d55SStefano Zampini PetscFunctionBegin; 2091e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { 2092e432b41dSStefano Zampini *flg = PETSC_FALSE; 2093e432b41dSStefano Zampini PetscFunctionReturn(0); 2094e432b41dSStefano Zampini } 20959566063dSJacob Faibussowitsch PetscCall(MatIsSymmetric(matis->A, tol, &local_sym)); 20961c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&local_sym, flg, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 209769796d55SStefano Zampini PetscFunctionReturn(0); 209869796d55SStefano Zampini } 209969796d55SStefano Zampini 21009371c9d4SSatish Balay static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A, PetscBool *flg) { 210145471136SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 210245471136SStefano Zampini PetscBool local_sym; 210345471136SStefano Zampini 210445471136SStefano Zampini PetscFunctionBegin; 2105e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { 210645471136SStefano Zampini *flg = PETSC_FALSE; 210745471136SStefano Zampini PetscFunctionReturn(0); 210845471136SStefano Zampini } 21099566063dSJacob Faibussowitsch PetscCall(MatIsStructurallySymmetric(matis->A, &local_sym)); 21101c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&local_sym, flg, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 211145471136SStefano Zampini PetscFunctionReturn(0); 211245471136SStefano Zampini } 211345471136SStefano Zampini 21149371c9d4SSatish Balay static PetscErrorCode MatDestroy_IS(Mat A) { 2115b4319ba4SBarry Smith Mat_IS *b = (Mat_IS *)A->data; 2116b4319ba4SBarry Smith 2117b4319ba4SBarry Smith PetscFunctionBegin; 21189566063dSJacob Faibussowitsch PetscCall(PetscFree(b->bdiag)); 21199566063dSJacob Faibussowitsch PetscCall(PetscFree(b->lmattype)); 21209566063dSJacob Faibussowitsch PetscCall(MatDestroy(&b->A)); 21219566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&b->cctx)); 21229566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&b->rctx)); 21239566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->x)); 21249566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->y)); 21259566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->counter)); 21269566063dSJacob Faibussowitsch PetscCall(ISDestroy(&b->getsub_ris)); 21279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&b->getsub_cis)); 2128a8116848SStefano Zampini if (b->sf != b->csf) { 21299566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&b->csf)); 21309566063dSJacob Faibussowitsch PetscCall(PetscFree2(b->csf_rootdata, b->csf_leafdata)); 2131f03112d0SStefano Zampini } else b->csf = NULL; 21329566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&b->sf)); 21339566063dSJacob Faibussowitsch PetscCall(PetscFree2(b->sf_rootdata, b->sf_leafdata)); 21349566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&b->rmapping)); 21359566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&b->cmapping)); 2136d0dbe9f7SStefano Zampini PetscCall(MatDestroy(&b->dA)); 2137d0dbe9f7SStefano Zampini PetscCall(MatDestroy(&b->assembledA)); 21389566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 21399566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, NULL)); 21409566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMatType_C", NULL)); 21419566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalMat_C", NULL)); 21429566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMat_C", NULL)); 21432e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISRestoreLocalMat_C", NULL)); 21449566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetMPIXAIJ_C", NULL)); 21459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetPreallocation_C", NULL)); 21469566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISStoreL2L_C", NULL)); 21479566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISFixLocalEmpty_C", NULL)); 21489566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalToGlobalMapping_C", NULL)); 21499566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpiaij_C", NULL)); 21509566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpibaij_C", NULL)); 21519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpisbaij_C", NULL)); 21529566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqaij_C", NULL)); 21539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqbaij_C", NULL)); 21549566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqsbaij_C", NULL)); 21559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_aij_C", NULL)); 21569566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOOLocal_C", NULL)); 21579566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL)); 21589566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL)); 2159b4319ba4SBarry Smith PetscFunctionReturn(0); 2160b4319ba4SBarry Smith } 2161b4319ba4SBarry Smith 21629371c9d4SSatish Balay static PetscErrorCode MatMult_IS(Mat A, Vec x, Vec y) { 2163b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)A->data; 2164b4319ba4SBarry Smith PetscScalar zero = 0.0; 2165b4319ba4SBarry Smith 2166b4319ba4SBarry Smith PetscFunctionBegin; 2167b4319ba4SBarry Smith /* scatter the global vector x into the local work vector */ 21689566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->cctx, x, is->x, INSERT_VALUES, SCATTER_FORWARD)); 21699566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->cctx, x, is->x, INSERT_VALUES, SCATTER_FORWARD)); 2170b4319ba4SBarry Smith 2171b4319ba4SBarry Smith /* multiply the local matrix */ 21729566063dSJacob Faibussowitsch PetscCall(MatMult(is->A, is->x, is->y)); 2173b4319ba4SBarry Smith 2174b4319ba4SBarry Smith /* scatter product back into global memory */ 21759566063dSJacob Faibussowitsch PetscCall(VecSet(y, zero)); 21769566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, is->y, y, ADD_VALUES, SCATTER_REVERSE)); 21779566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, is->y, y, ADD_VALUES, SCATTER_REVERSE)); 2178b4319ba4SBarry Smith PetscFunctionReturn(0); 2179b4319ba4SBarry Smith } 2180b4319ba4SBarry Smith 21819371c9d4SSatish Balay static PetscErrorCode MatMultAdd_IS(Mat A, Vec v1, Vec v2, Vec v3) { 2182650997f4SStefano Zampini Vec temp_vec; 21832e74eeadSLisandro Dalcin 21842e74eeadSLisandro Dalcin PetscFunctionBegin; /* v3 = v2 + A * v1.*/ 2185650997f4SStefano Zampini if (v3 != v2) { 21869566063dSJacob Faibussowitsch PetscCall(MatMult(A, v1, v3)); 21879566063dSJacob Faibussowitsch PetscCall(VecAXPY(v3, 1.0, v2)); 2188650997f4SStefano Zampini } else { 21899566063dSJacob Faibussowitsch PetscCall(VecDuplicate(v2, &temp_vec)); 21909566063dSJacob Faibussowitsch PetscCall(MatMult(A, v1, temp_vec)); 21919566063dSJacob Faibussowitsch PetscCall(VecAXPY(temp_vec, 1.0, v2)); 21929566063dSJacob Faibussowitsch PetscCall(VecCopy(temp_vec, v3)); 21939566063dSJacob Faibussowitsch PetscCall(VecDestroy(&temp_vec)); 2194650997f4SStefano Zampini } 21952e74eeadSLisandro Dalcin PetscFunctionReturn(0); 21962e74eeadSLisandro Dalcin } 21972e74eeadSLisandro Dalcin 21989371c9d4SSatish Balay static PetscErrorCode MatMultTranspose_IS(Mat A, Vec y, Vec x) { 21992e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS *)A->data; 22002e74eeadSLisandro Dalcin 2201e176bc59SStefano Zampini PetscFunctionBegin; 22022e74eeadSLisandro Dalcin /* scatter the global vector x into the local work vector */ 22039566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, y, is->y, INSERT_VALUES, SCATTER_FORWARD)); 22049566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, y, is->y, INSERT_VALUES, SCATTER_FORWARD)); 22052e74eeadSLisandro Dalcin 22062e74eeadSLisandro Dalcin /* multiply the local matrix */ 22079566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(is->A, is->y, is->x)); 22082e74eeadSLisandro Dalcin 22092e74eeadSLisandro Dalcin /* scatter product back into global vector */ 22109566063dSJacob Faibussowitsch PetscCall(VecSet(x, 0)); 22119566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->cctx, is->x, x, ADD_VALUES, SCATTER_REVERSE)); 22129566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->cctx, is->x, x, ADD_VALUES, SCATTER_REVERSE)); 22132e74eeadSLisandro Dalcin PetscFunctionReturn(0); 22142e74eeadSLisandro Dalcin } 22152e74eeadSLisandro Dalcin 22169371c9d4SSatish Balay static PetscErrorCode MatMultTransposeAdd_IS(Mat A, Vec v1, Vec v2, Vec v3) { 2217650997f4SStefano Zampini Vec temp_vec; 22182e74eeadSLisandro Dalcin 22192e74eeadSLisandro Dalcin PetscFunctionBegin; /* v3 = v2 + A' * v1.*/ 2220650997f4SStefano Zampini if (v3 != v2) { 22219566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(A, v1, v3)); 22229566063dSJacob Faibussowitsch PetscCall(VecAXPY(v3, 1.0, v2)); 2223650997f4SStefano Zampini } else { 22249566063dSJacob Faibussowitsch PetscCall(VecDuplicate(v2, &temp_vec)); 22259566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(A, v1, temp_vec)); 22269566063dSJacob Faibussowitsch PetscCall(VecAXPY(temp_vec, 1.0, v2)); 22279566063dSJacob Faibussowitsch PetscCall(VecCopy(temp_vec, v3)); 22289566063dSJacob Faibussowitsch PetscCall(VecDestroy(&temp_vec)); 2229650997f4SStefano Zampini } 22302e74eeadSLisandro Dalcin PetscFunctionReturn(0); 22312e74eeadSLisandro Dalcin } 22322e74eeadSLisandro Dalcin 22339371c9d4SSatish Balay static PetscErrorCode MatView_IS(Mat A, PetscViewer viewer) { 2234b4319ba4SBarry Smith Mat_IS *a = (Mat_IS *)A->data; 2235b4319ba4SBarry Smith PetscViewer sviewer; 2236ee2491ecSStefano Zampini PetscBool isascii, view = PETSC_TRUE; 2237b4319ba4SBarry Smith 2238b4319ba4SBarry Smith PetscFunctionBegin; 22399566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 2240ee2491ecSStefano Zampini if (isascii) { 2241ee2491ecSStefano Zampini PetscViewerFormat format; 2242ee2491ecSStefano Zampini 22439566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2244ee2491ecSStefano Zampini if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE; 2245ee2491ecSStefano Zampini } 2246ee2491ecSStefano Zampini if (!view) PetscFunctionReturn(0); 22479566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 22489566063dSJacob Faibussowitsch PetscCall(MatView(a->A, sviewer)); 22499566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 22509566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 2251b4319ba4SBarry Smith PetscFunctionReturn(0); 2252b4319ba4SBarry Smith } 2253b4319ba4SBarry Smith 22549371c9d4SSatish Balay static PetscErrorCode MatInvertBlockDiagonal_IS(Mat mat, const PetscScalar **values) { 2255b89f26deSStefano Zampini Mat_IS *is = (Mat_IS *)mat->data; 2256b89f26deSStefano Zampini MPI_Datatype nodeType; 2257b89f26deSStefano Zampini const PetscScalar *lv; 2258b89f26deSStefano Zampini PetscInt bs; 2259b89f26deSStefano Zampini 2260b89f26deSStefano Zampini PetscFunctionBegin; 22619566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(mat, &bs)); 22629566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(is->A, bs)); 22639566063dSJacob Faibussowitsch PetscCall(MatInvertBlockDiagonal(is->A, &lv)); 226448a46eb9SPierre Jolivet if (!is->bdiag) PetscCall(PetscMalloc1(bs * mat->rmap->n, &is->bdiag)); 22659566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(bs, MPIU_SCALAR, &nodeType)); 22669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&nodeType)); 22679566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(is->sf, nodeType, lv, is->bdiag, MPI_REPLACE)); 22689566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(is->sf, nodeType, lv, is->bdiag, MPI_REPLACE)); 22699566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&nodeType)); 2270b89f26deSStefano Zampini if (values) *values = is->bdiag; 2271b89f26deSStefano Zampini PetscFunctionReturn(0); 2272b89f26deSStefano Zampini } 2273b89f26deSStefano Zampini 22749371c9d4SSatish Balay static PetscErrorCode MatISSetUpScatters_Private(Mat A) { 2275e176bc59SStefano Zampini Vec cglobal, rglobal; 22768546b261SStefano Zampini IS from; 22778546b261SStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 2278b89f26deSStefano Zampini PetscScalar sum; 22798546b261SStefano Zampini const PetscInt *garray; 22808546b261SStefano Zampini PetscInt nr, rbs, nc, cbs; 2281e432b41dSStefano Zampini VecType rtype; 2282b4319ba4SBarry Smith 2283b4319ba4SBarry Smith PetscFunctionBegin; 22849566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->rmapping, &nr)); 22859566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->rmapping, &rbs)); 22869566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->cmapping, &nc)); 22879566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->cmapping, &cbs)); 22889566063dSJacob Faibussowitsch PetscCall(VecDestroy(&is->x)); 22899566063dSJacob Faibussowitsch PetscCall(VecDestroy(&is->y)); 22909566063dSJacob Faibussowitsch PetscCall(VecDestroy(&is->counter)); 22919566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&is->rctx)); 22929566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&is->cctx)); 22939566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(is->A, &is->x, &is->y)); 22949566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->y, PETSC_TRUE)); 22959566063dSJacob Faibussowitsch PetscCall(VecGetRootType_Private(is->y, &rtype)); 22969566063dSJacob Faibussowitsch PetscCall(PetscFree(A->defaultvectype)); 22979566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(rtype, &A->defaultvectype)); 22989566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, &cglobal, &rglobal)); 22999566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(rglobal, PETSC_TRUE)); 23009566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->rmapping, &garray)); 23019566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), rbs, nr / rbs, garray, PETSC_USE_POINTER, &from)); 23029566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(rglobal, from, is->y, NULL, &is->rctx)); 23039566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->rmapping, &garray)); 23049566063dSJacob Faibussowitsch PetscCall(ISDestroy(&from)); 2305e432b41dSStefano Zampini if (is->rmapping != is->cmapping) { 23069566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->cmapping, &garray)); 23079566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), cbs, nc / cbs, garray, PETSC_USE_POINTER, &from)); 23089566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(cglobal, from, is->x, NULL, &is->cctx)); 23099566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->cmapping, &garray)); 23109566063dSJacob Faibussowitsch PetscCall(ISDestroy(&from)); 23118546b261SStefano Zampini } else { 23129566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->rctx)); 23138546b261SStefano Zampini is->cctx = is->rctx; 23148546b261SStefano Zampini } 23159566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cglobal)); 2316b89f26deSStefano Zampini 23178546b261SStefano Zampini /* interface counter vector (local) */ 23189566063dSJacob Faibussowitsch PetscCall(VecDuplicate(is->y, &is->counter)); 23199566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->counter, PETSC_TRUE)); 23209566063dSJacob Faibussowitsch PetscCall(VecSet(is->y, 1.)); 23219566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, is->y, rglobal, ADD_VALUES, SCATTER_REVERSE)); 23229566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, is->y, rglobal, ADD_VALUES, SCATTER_REVERSE)); 23239566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, rglobal, is->counter, INSERT_VALUES, SCATTER_FORWARD)); 23249566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, rglobal, is->counter, INSERT_VALUES, SCATTER_FORWARD)); 23259566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->y, PETSC_FALSE)); 23269566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->counter, PETSC_FALSE)); 2327b89f26deSStefano Zampini 2328b89f26deSStefano Zampini /* special functions for block-diagonal matrices */ 23299566063dSJacob Faibussowitsch PetscCall(VecSum(rglobal, &sum)); 2330b89f26deSStefano Zampini A->ops->invertblockdiagonal = NULL; 2331e432b41dSStefano Zampini if ((PetscInt)(PetscRealPart(sum)) == A->rmap->N && A->rmap->N == A->cmap->N && is->rmapping == is->cmapping) A->ops->invertblockdiagonal = MatInvertBlockDiagonal_IS; 23329566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rglobal)); 2333b0cc1f67SStefano Zampini 2334b0cc1f67SStefano Zampini /* setup SF for general purpose shared indices based communications */ 23359566063dSJacob Faibussowitsch PetscCall(MatISSetUpSF_IS(A)); 23368546b261SStefano Zampini PetscFunctionReturn(0); 23378546b261SStefano Zampini } 23388546b261SStefano Zampini 23399371c9d4SSatish Balay static PetscErrorCode MatISFilterL2GMap(Mat A, ISLocalToGlobalMapping map, ISLocalToGlobalMapping *nmap, ISLocalToGlobalMapping *lmap) { 2340e432b41dSStefano Zampini IS is; 2341e432b41dSStefano Zampini ISLocalToGlobalMappingType l2gtype; 2342e432b41dSStefano Zampini const PetscInt *idxs; 2343e432b41dSStefano Zampini PetscHSetI ht; 2344e432b41dSStefano Zampini PetscInt *nidxs; 2345e432b41dSStefano Zampini PetscInt i, n, bs, c; 2346e432b41dSStefano Zampini PetscBool flg[] = {PETSC_FALSE, PETSC_FALSE}; 2347e432b41dSStefano Zampini 2348e432b41dSStefano Zampini PetscFunctionBegin; 23499566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(map, &n)); 23509566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(map, &bs)); 23519566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(map, &idxs)); 23529566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&ht)); 23539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n / bs, &nidxs)); 2354e432b41dSStefano Zampini for (i = 0, c = 0; i < n / bs; i++) { 2355e432b41dSStefano Zampini PetscBool missing; 23569371c9d4SSatish Balay if (idxs[i] < 0) { 23579371c9d4SSatish Balay flg[0] = PETSC_TRUE; 23589371c9d4SSatish Balay continue; 23599371c9d4SSatish Balay } 23609566063dSJacob Faibussowitsch PetscCall(PetscHSetIQueryAdd(ht, idxs[i], &missing)); 2361e432b41dSStefano Zampini if (!missing) flg[1] = PETSC_TRUE; 2362e432b41dSStefano Zampini else nidxs[c++] = idxs[i]; 2363e432b41dSStefano Zampini } 23649566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&ht)); 23651c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(MPI_IN_PLACE, flg, 2, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A))); 2366e432b41dSStefano Zampini if (!flg[0] && !flg[1]) { /* Entries are all non negative and unique */ 2367e432b41dSStefano Zampini *nmap = NULL; 2368e432b41dSStefano Zampini *lmap = NULL; 23699566063dSJacob Faibussowitsch PetscCall(PetscFree(nidxs)); 23709566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(map, &idxs)); 2371e432b41dSStefano Zampini PetscFunctionReturn(0); 2372e432b41dSStefano Zampini } 2373e432b41dSStefano Zampini 2374e432b41dSStefano Zampini /* New l2g map without negative or repeated indices */ 23759566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), bs, c, nidxs, PETSC_USE_POINTER, &is)); 23769566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, nmap)); 23779566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 23789566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetType(map, &l2gtype)); 23799566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(*nmap, l2gtype)); 2380e432b41dSStefano Zampini 2381e432b41dSStefano Zampini /* New local l2g map for repeated indices */ 23829566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(*nmap, IS_GTOLM_MASK, n / bs, idxs, NULL, nidxs)); 23839566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF, bs, n / bs, nidxs, PETSC_USE_POINTER, &is)); 23849566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, lmap)); 23859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2386e432b41dSStefano Zampini 23879566063dSJacob Faibussowitsch PetscCall(PetscFree(nidxs)); 23889566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(map, &idxs)); 2389e432b41dSStefano Zampini PetscFunctionReturn(0); 2390e432b41dSStefano Zampini } 2391e432b41dSStefano Zampini 23929371c9d4SSatish Balay static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) { 23938546b261SStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 2394e432b41dSStefano Zampini ISLocalToGlobalMapping localrmapping = NULL, localcmapping = NULL; 2395e432b41dSStefano Zampini PetscBool cong, freem[] = {PETSC_FALSE, PETSC_FALSE}; 2396e432b41dSStefano Zampini PetscInt nr, rbs, nc, cbs; 23978546b261SStefano Zampini 23988546b261SStefano Zampini PetscFunctionBegin; 2399fc989267SStefano Zampini if (rmapping) PetscCheckSameComm(A, 1, rmapping, 2); 2400fc989267SStefano Zampini if (cmapping) PetscCheckSameComm(A, 1, cmapping, 3); 2401e432b41dSStefano Zampini 24029566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&is->rmapping)); 24039566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&is->cmapping)); 24049566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 24059566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 24069566063dSJacob Faibussowitsch PetscCall(MatHasCongruentLayouts(A, &cong)); 2407e432b41dSStefano Zampini 2408fc989267SStefano Zampini /* If NULL, local space matches global space */ 2409fc989267SStefano Zampini if (!rmapping) { 2410fc989267SStefano Zampini IS is; 2411fc989267SStefano Zampini 24129566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), A->rmap->N, 0, 1, &is)); 24139566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rmapping)); 24149566063dSJacob Faibussowitsch if (A->rmap->bs > 0) PetscCall(ISLocalToGlobalMappingSetBlockSize(rmapping, A->rmap->bs)); 24159566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2416e432b41dSStefano Zampini freem[0] = PETSC_TRUE; 2417e432b41dSStefano Zampini if (!cmapping && cong && A->rmap->bs == A->cmap->bs) cmapping = rmapping; 2418e432b41dSStefano Zampini } else if (!is->islocalref) { /* check if the l2g map has negative or repeated entries */ 24199566063dSJacob Faibussowitsch PetscCall(MatISFilterL2GMap(A, rmapping, &is->rmapping, &localrmapping)); 2420e432b41dSStefano Zampini if (rmapping == cmapping) { 24219566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->rmapping)); 2422e432b41dSStefano Zampini is->cmapping = is->rmapping; 24239566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)localrmapping)); 2424e432b41dSStefano Zampini localcmapping = localrmapping; 2425fc989267SStefano Zampini } 2426fc989267SStefano Zampini } 2427fc989267SStefano Zampini if (!cmapping) { 2428fc989267SStefano Zampini IS is; 2429fc989267SStefano Zampini 24309566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), A->cmap->N, 0, 1, &is)); 24319566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cmapping)); 24329566063dSJacob Faibussowitsch if (A->cmap->bs > 0) PetscCall(ISLocalToGlobalMappingSetBlockSize(cmapping, A->cmap->bs)); 24339566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2434e432b41dSStefano Zampini freem[1] = PETSC_TRUE; 2435e432b41dSStefano Zampini } else if (cmapping != rmapping && !is->islocalref) { /* check if the l2g map has negative or repeated entries */ 24369566063dSJacob Faibussowitsch PetscCall(MatISFilterL2GMap(A, cmapping, &is->cmapping, &localcmapping)); 2437e432b41dSStefano Zampini } 2438e432b41dSStefano Zampini if (!is->rmapping) { 24399566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)rmapping)); 2440e432b41dSStefano Zampini is->rmapping = rmapping; 2441e432b41dSStefano Zampini } 2442e432b41dSStefano Zampini if (!is->cmapping) { 24439566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)cmapping)); 2444e432b41dSStefano Zampini is->cmapping = cmapping; 2445fc989267SStefano Zampini } 2446fc989267SStefano Zampini 2447fc989267SStefano Zampini /* Clean up */ 24489566063dSJacob Faibussowitsch PetscCall(MatDestroy(&is->A)); 2449872cf891SStefano Zampini if (is->csf != is->sf) { 24509566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&is->csf)); 24519566063dSJacob Faibussowitsch PetscCall(PetscFree2(is->csf_rootdata, is->csf_leafdata)); 2452f03112d0SStefano Zampini } else is->csf = NULL; 24539566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&is->sf)); 24549566063dSJacob Faibussowitsch PetscCall(PetscFree2(is->sf_rootdata, is->sf_leafdata)); 24559566063dSJacob Faibussowitsch PetscCall(PetscFree(is->bdiag)); 24563bbff08aSStefano Zampini 2457fc989267SStefano Zampini /* check if the two mappings are actually the same for square matrices since MATIS has some optimization for this case 2458fc989267SStefano Zampini (DOLFIN passes 2 different objects) */ 24599566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->rmapping, &nr)); 24609566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->rmapping, &rbs)); 24619566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->cmapping, &nc)); 24629566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->cmapping, &cbs)); 2463e432b41dSStefano Zampini if (is->rmapping != is->cmapping && cong) { 2464e432b41dSStefano Zampini PetscBool same = PETSC_FALSE; 24656625354bSStefano Zampini if (nr == nc && cbs == rbs) { 24666625354bSStefano Zampini const PetscInt *idxs1, *idxs2; 24676625354bSStefano Zampini 24689566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->rmapping, &idxs1)); 24699566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->cmapping, &idxs2)); 24709566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(idxs1, idxs2, nr / rbs, &same)); 24719566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->rmapping, &idxs1)); 24729566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->cmapping, &idxs2)); 24736625354bSStefano Zampini } 24741c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(MPI_IN_PLACE, &same, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 2475e432b41dSStefano Zampini if (same) { 24769566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&is->cmapping)); 24779566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->rmapping)); 2478e432b41dSStefano Zampini is->cmapping = is->rmapping; 2479e432b41dSStefano Zampini } 24806625354bSStefano Zampini } 24819566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(A->rmap, rbs)); 24829566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(A->cmap, cbs)); 2483e432b41dSStefano Zampini /* Pass the user defined maps to the layout */ 24849566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetISLocalToGlobalMapping(A->rmap, rmapping)); 24859566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetISLocalToGlobalMapping(A->cmap, cmapping)); 24869566063dSJacob Faibussowitsch if (freem[0]) PetscCall(ISLocalToGlobalMappingDestroy(&rmapping)); 24879566063dSJacob Faibussowitsch if (freem[1]) PetscCall(ISLocalToGlobalMappingDestroy(&cmapping)); 24886625354bSStefano Zampini 24896625354bSStefano Zampini /* Create the local matrix A */ 24909566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &is->A)); 24919566063dSJacob Faibussowitsch PetscCall(MatSetType(is->A, is->lmattype)); 24929566063dSJacob Faibussowitsch PetscCall(MatSetSizes(is->A, nr, nc, nr, nc)); 24939566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(is->A, rbs, cbs)); 24949566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(is->A, "is_")); 24959566063dSJacob Faibussowitsch PetscCall(MatAppendOptionsPrefix(is->A, ((PetscObject)A)->prefix)); 24969566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(is->A->rmap)); 24979566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(is->A->cmap)); 24989566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(is->A, localrmapping, localcmapping)); 24999566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&localrmapping)); 25009566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&localcmapping)); 2501b4319ba4SBarry Smith 2502fc989267SStefano Zampini /* setup scatters and local vectors for MatMult */ 25039566063dSJacob Faibussowitsch if (!is->islocalref) PetscCall(MatISSetUpScatters_Private(A)); 2504fc989267SStefano Zampini A->preallocated = PETSC_TRUE; 2505fc989267SStefano Zampini PetscFunctionReturn(0); 2506fc989267SStefano Zampini } 2507fc989267SStefano Zampini 25089371c9d4SSatish Balay static PetscErrorCode MatSetUp_IS(Mat A) { 2509fc989267SStefano Zampini ISLocalToGlobalMapping rmap, cmap; 2510fc989267SStefano Zampini 2511fc989267SStefano Zampini PetscFunctionBegin; 25129566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(A, &rmap, &cmap)); 251348a46eb9SPierre Jolivet if (!rmap && !cmap) PetscCall(MatSetLocalToGlobalMapping(A, NULL, NULL)); 2514b4319ba4SBarry Smith PetscFunctionReturn(0); 2515b4319ba4SBarry Smith } 2516b4319ba4SBarry Smith 25179371c9d4SSatish Balay static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) { 25182e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS *)mat->data; 2519f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION], cols_l[MATIS_MAX_ENTRIES_INSERTION]; 25202e74eeadSLisandro Dalcin 25212e74eeadSLisandro Dalcin PetscFunctionBegin; 25229566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(is->rmapping, IS_GTOLM_MASK, m, rows, &m, rows_l)); 2523e432b41dSStefano Zampini if (m != n || rows != cols || is->cmapping != is->rmapping) { 25249566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(is->cmapping, IS_GTOLM_MASK, n, cols, &n, cols_l)); 25259566063dSJacob Faibussowitsch PetscCall(MatSetValues(is->A, m, rows_l, n, cols_l, values, addv)); 2526e432b41dSStefano Zampini } else { 25279566063dSJacob Faibussowitsch PetscCall(MatSetValues(is->A, m, rows_l, m, rows_l, values, addv)); 2528e432b41dSStefano Zampini } 25292e74eeadSLisandro Dalcin PetscFunctionReturn(0); 25302e74eeadSLisandro Dalcin } 25312e74eeadSLisandro Dalcin 25329371c9d4SSatish Balay static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) { 253397563a80SStefano Zampini Mat_IS *is = (Mat_IS *)mat->data; 2534f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION], cols_l[MATIS_MAX_ENTRIES_INSERTION]; 253597563a80SStefano Zampini 253697563a80SStefano Zampini PetscFunctionBegin; 25379566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(is->rmapping, IS_GTOLM_MASK, m, rows, &m, rows_l)); 2538e432b41dSStefano Zampini if (m != n || rows != cols || is->cmapping != is->rmapping) { 25399566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(is->cmapping, IS_GTOLM_MASK, n, cols, &n, cols_l)); 25409566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked(is->A, m, rows_l, n, cols_l, values, addv)); 2541e432b41dSStefano Zampini } else { 25429566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked(is->A, m, rows_l, n, rows_l, values, addv)); 2543e432b41dSStefano Zampini } 254497563a80SStefano Zampini PetscFunctionReturn(0); 254597563a80SStefano Zampini } 254697563a80SStefano Zampini 25479371c9d4SSatish Balay static PetscErrorCode MatSetValuesLocal_IS(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) { 2548b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)A->data; 2549b4319ba4SBarry Smith 2550b4319ba4SBarry Smith PetscFunctionBegin; 2551e432b41dSStefano Zampini if (is->A->rmap->mapping || is->A->cmap->mapping) { 25529566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(is->A, m, rows, n, cols, values, addv)); 2553872cf891SStefano Zampini } else { 25549566063dSJacob Faibussowitsch PetscCall(MatSetValues(is->A, m, rows, n, cols, values, addv)); 2555872cf891SStefano Zampini } 2556b4319ba4SBarry Smith PetscFunctionReturn(0); 2557b4319ba4SBarry Smith } 2558b4319ba4SBarry Smith 25599371c9d4SSatish Balay static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) { 2560f0006bf2SLisandro Dalcin Mat_IS *is = (Mat_IS *)A->data; 2561f0006bf2SLisandro Dalcin 2562f0006bf2SLisandro Dalcin PetscFunctionBegin; 2563e432b41dSStefano Zampini if (is->A->rmap->mapping || is->A->cmap->mapping) { 25649566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlockedLocal(is->A, m, rows, n, cols, values, addv)); 2565b4f971dfSStefano Zampini } else { 25669566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked(is->A, m, rows, n, cols, values, addv)); 2567b4f971dfSStefano Zampini } 2568f0006bf2SLisandro Dalcin PetscFunctionReturn(0); 2569f0006bf2SLisandro Dalcin } 2570f0006bf2SLisandro Dalcin 25719371c9d4SSatish Balay static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, PetscBool columns) { 2572f0ae7da4SStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 2573f0ae7da4SStefano Zampini 2574f0ae7da4SStefano Zampini PetscFunctionBegin; 2575f0ae7da4SStefano Zampini if (!n) { 2576f0ae7da4SStefano Zampini is->pure_neumann = PETSC_TRUE; 2577f0ae7da4SStefano Zampini } else { 2578f0ae7da4SStefano Zampini PetscInt i; 2579f0ae7da4SStefano Zampini is->pure_neumann = PETSC_FALSE; 2580f0ae7da4SStefano Zampini 2581f0ae7da4SStefano Zampini if (columns) { 25829566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns(is->A, n, rows, diag, NULL, NULL)); 2583f0ae7da4SStefano Zampini } else { 25849566063dSJacob Faibussowitsch PetscCall(MatZeroRows(is->A, n, rows, diag, NULL, NULL)); 2585f0ae7da4SStefano Zampini } 2586f0ae7da4SStefano Zampini if (diag != 0.) { 2587f0ae7da4SStefano Zampini const PetscScalar *array; 25889566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(is->counter, &array)); 258948a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(MatSetValue(is->A, rows[i], rows[i], diag / (array[rows[i]]), INSERT_VALUES)); 25909566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(is->counter, &array)); 2591f0ae7da4SStefano Zampini } 25929566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(is->A, MAT_FINAL_ASSEMBLY)); 25939566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(is->A, MAT_FINAL_ASSEMBLY)); 2594f0ae7da4SStefano Zampini } 2595f0ae7da4SStefano Zampini PetscFunctionReturn(0); 2596f0ae7da4SStefano Zampini } 2597f0ae7da4SStefano Zampini 25989371c9d4SSatish Balay static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, Vec x, Vec b, PetscBool columns) { 25996e520ac8SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 26006e520ac8SStefano Zampini PetscInt nr, nl, len, i; 26016e520ac8SStefano Zampini PetscInt *lrows; 26022e74eeadSLisandro Dalcin 26032e74eeadSLisandro Dalcin PetscFunctionBegin; 2604cf9c20a2SJed Brown if (PetscUnlikelyDebug(columns || diag != 0. || (x && b))) { 2605f0ae7da4SStefano Zampini PetscBool cong; 260626b0207aSStefano Zampini 26079566063dSJacob Faibussowitsch PetscCall(PetscLayoutCompare(A->rmap, A->cmap, &cong)); 260826b0207aSStefano Zampini cong = (PetscBool)(cong && matis->sf == matis->csf); 260908401ef6SPierre 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"); 2610aed4548fSBarry 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"); 2611aed4548fSBarry 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"); 2612f0ae7da4SStefano Zampini } 26136e520ac8SStefano Zampini /* get locally owned rows */ 26149566063dSJacob Faibussowitsch PetscCall(PetscLayoutMapLocal(A->rmap, n, rows, &len, &lrows, NULL)); 26156e520ac8SStefano Zampini /* fix right hand side if needed */ 26166e520ac8SStefano Zampini if (x && b) { 26176e520ac8SStefano Zampini const PetscScalar *xx; 26186e520ac8SStefano Zampini PetscScalar *bb; 26196e520ac8SStefano Zampini 26209566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &xx)); 26219566063dSJacob Faibussowitsch PetscCall(VecGetArray(b, &bb)); 26226e520ac8SStefano Zampini for (i = 0; i < len; ++i) bb[lrows[i]] = diag * xx[lrows[i]]; 26239566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &xx)); 26249566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(b, &bb)); 26252e74eeadSLisandro Dalcin } 26266e520ac8SStefano Zampini /* get rows associated to the local matrices */ 26279566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, &nl, NULL)); 26289566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_leafdata, nl)); 26299566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata, A->rmap->n)); 26306e520ac8SStefano Zampini for (i = 0; i < len; i++) matis->sf_rootdata[lrows[i]] = 1; 26319566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 26329566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 26339566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 26349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl, &lrows)); 26359371c9d4SSatish Balay for (i = 0, nr = 0; i < nl; i++) 26369371c9d4SSatish Balay if (matis->sf_leafdata[i]) lrows[nr++] = i; 26379566063dSJacob Faibussowitsch PetscCall(MatISZeroRowsColumnsLocal_Private(A, nr, lrows, diag, columns)); 26389566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 2639d0dbe9f7SStefano Zampini PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 2640d0dbe9f7SStefano Zampini PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 26412e74eeadSLisandro Dalcin PetscFunctionReturn(0); 26422e74eeadSLisandro Dalcin } 26432e74eeadSLisandro Dalcin 26449371c9d4SSatish Balay static PetscErrorCode MatZeroRows_IS(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) { 2645b4319ba4SBarry Smith PetscFunctionBegin; 26469566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns_Private_IS(A, n, rows, diag, x, b, PETSC_FALSE)); 2647f0ae7da4SStefano Zampini PetscFunctionReturn(0); 2648f0ae7da4SStefano Zampini } 26492205254eSKarl Rupp 26509371c9d4SSatish Balay static PetscErrorCode MatZeroRowsColumns_IS(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) { 2651f0ae7da4SStefano Zampini PetscFunctionBegin; 26529566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns_Private_IS(A, n, rows, diag, x, b, PETSC_TRUE)); 2653b4319ba4SBarry Smith PetscFunctionReturn(0); 2654b4319ba4SBarry Smith } 2655b4319ba4SBarry Smith 26569371c9d4SSatish Balay static PetscErrorCode MatAssemblyBegin_IS(Mat A, MatAssemblyType type) { 2657b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)A->data; 2658b4319ba4SBarry Smith 2659b4319ba4SBarry Smith PetscFunctionBegin; 26609566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(is->A, type)); 2661b4319ba4SBarry Smith PetscFunctionReturn(0); 2662b4319ba4SBarry Smith } 2663b4319ba4SBarry Smith 26649371c9d4SSatish Balay static PetscErrorCode MatAssemblyEnd_IS(Mat A, MatAssemblyType type) { 2665b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)A->data; 2666d0dbe9f7SStefano Zampini PetscBool lnnz; 2667b4319ba4SBarry Smith 2668b4319ba4SBarry Smith PetscFunctionBegin; 26699566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(is->A, type)); 2670872cf891SStefano Zampini /* fix for local empty rows/cols */ 2671872cf891SStefano Zampini if (is->locempty && type == MAT_FINAL_ASSEMBLY) { 2672872cf891SStefano Zampini Mat newlA; 2673f03112d0SStefano Zampini ISLocalToGlobalMapping rl2g, cl2g; 2674f03112d0SStefano Zampini IS nzr, nzc; 2675f03112d0SStefano Zampini PetscInt nr, nc, nnzr, nnzc; 2676f03112d0SStefano Zampini PetscBool lnewl2g, newl2g; 2677872cf891SStefano Zampini 26789566063dSJacob Faibussowitsch PetscCall(MatGetSize(is->A, &nr, &nc)); 26799566063dSJacob Faibussowitsch PetscCall(MatFindNonzeroRowsOrCols_Basic(is->A, PETSC_FALSE, PETSC_SMALL, &nzr)); 268048a46eb9SPierre Jolivet if (!nzr) PetscCall(ISCreateStride(PetscObjectComm((PetscObject)is->A), nr, 0, 1, &nzr)); 26819566063dSJacob Faibussowitsch PetscCall(MatFindNonzeroRowsOrCols_Basic(is->A, PETSC_TRUE, PETSC_SMALL, &nzc)); 268248a46eb9SPierre Jolivet if (!nzc) PetscCall(ISCreateStride(PetscObjectComm((PetscObject)is->A), nc, 0, 1, &nzc)); 26839566063dSJacob Faibussowitsch PetscCall(ISGetSize(nzr, &nnzr)); 26849566063dSJacob Faibussowitsch PetscCall(ISGetSize(nzc, &nnzc)); 2685e432b41dSStefano Zampini if (nnzr != nr || nnzc != nc) { /* need new global l2g map */ 2686f03112d0SStefano Zampini lnewl2g = PETSC_TRUE; 26879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&lnewl2g, &newl2g, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A))); 2688f03112d0SStefano Zampini 2689872cf891SStefano Zampini /* extract valid submatrix */ 26909566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(is->A, nzr, nzc, MAT_INITIAL_MATRIX, &newlA)); 2691f03112d0SStefano Zampini } else { /* local matrix fully populated */ 2692f03112d0SStefano Zampini lnewl2g = PETSC_FALSE; 26939566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&lnewl2g, &newl2g, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A))); 26949566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->A)); 2695f03112d0SStefano Zampini newlA = is->A; 2696f03112d0SStefano Zampini } 2697e432b41dSStefano Zampini 2698f03112d0SStefano Zampini /* attach new global l2g map if needed */ 2699f03112d0SStefano Zampini if (newl2g) { 2700e432b41dSStefano Zampini IS zr, zc; 2701e432b41dSStefano Zampini const PetscInt *ridxs, *cidxs, *zridxs, *zcidxs; 2702e432b41dSStefano Zampini PetscInt *nidxs, i; 2703f03112d0SStefano Zampini 27049566063dSJacob Faibussowitsch PetscCall(ISComplement(nzr, 0, nr, &zr)); 27059566063dSJacob Faibussowitsch PetscCall(ISComplement(nzc, 0, nc, &zc)); 27069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(PetscMax(nr, nc), &nidxs)); 27079566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(is->rmapping, &ridxs)); 27089566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(is->cmapping, &cidxs)); 27099566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zr, &zridxs)); 27109566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zc, &zcidxs)); 27119566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zr, &nnzr)); 27129566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zc, &nnzc)); 2713e432b41dSStefano Zampini 27149566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(nidxs, ridxs, nr)); 2715e432b41dSStefano Zampini for (i = 0; i < nnzr; i++) nidxs[zridxs[i]] = -1; 27169566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A), 1, nr, nidxs, PETSC_COPY_VALUES, &rl2g)); 27179566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(nidxs, cidxs, nc)); 2718e432b41dSStefano Zampini for (i = 0; i < nnzc; i++) nidxs[zcidxs[i]] = -1; 27199566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A), 1, nc, nidxs, PETSC_COPY_VALUES, &cl2g)); 2720e432b41dSStefano Zampini 27219566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zr, &zridxs)); 27229566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zc, &zcidxs)); 27239566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(is->rmapping, &ridxs)); 27249566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(is->cmapping, &cidxs)); 27259566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzr)); 27269566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzc)); 27279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zr)); 27289566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zc)); 27299566063dSJacob Faibussowitsch PetscCall(PetscFree(nidxs)); 27309566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(A, rl2g, cl2g)); 27319566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 27329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 2733f03112d0SStefano Zampini } 27349566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(A, newlA)); 27359566063dSJacob Faibussowitsch PetscCall(MatDestroy(&newlA)); 27369566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzr)); 27379566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzc)); 2738872cf891SStefano Zampini is->locempty = PETSC_FALSE; 2739f03112d0SStefano Zampini } 2740d0dbe9f7SStefano Zampini lnnz = (PetscBool)(is->A->nonzerostate == is->lnnzstate); 2741d0dbe9f7SStefano Zampini is->lnnzstate = is->A->nonzerostate; 2742d0dbe9f7SStefano Zampini PetscCall(MPIU_Allreduce(MPI_IN_PLACE, &lnnz, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A))); 2743d0dbe9f7SStefano Zampini if (lnnz) A->nonzerostate++; 2744b4319ba4SBarry Smith PetscFunctionReturn(0); 2745b4319ba4SBarry Smith } 2746b4319ba4SBarry Smith 27479371c9d4SSatish Balay static PetscErrorCode MatISGetLocalMat_IS(Mat mat, Mat *local) { 2748b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)mat->data; 2749b4319ba4SBarry Smith 2750b4319ba4SBarry Smith PetscFunctionBegin; 2751b4319ba4SBarry Smith *local = is->A; 2752b4319ba4SBarry Smith PetscFunctionReturn(0); 2753b4319ba4SBarry Smith } 2754b4319ba4SBarry Smith 27559371c9d4SSatish Balay static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat, Mat *local) { 27563b3b1effSJed Brown PetscFunctionBegin; 27573b3b1effSJed Brown *local = NULL; 27583b3b1effSJed Brown PetscFunctionReturn(0); 27593b3b1effSJed Brown } 27603b3b1effSJed Brown 2761b4319ba4SBarry Smith /*@ 276211a5261eSBarry Smith MatISGetLocalMat - Gets the local matrix stored inside a `MATIS` matrix. 2763b4319ba4SBarry Smith 2764b4319ba4SBarry Smith Input Parameter: 2765b4319ba4SBarry Smith . mat - the matrix 2766b4319ba4SBarry Smith 2767b4319ba4SBarry Smith Output Parameter: 2768eb82efa4SStefano Zampini . local - the local matrix 2769b4319ba4SBarry Smith 2770b4319ba4SBarry Smith Level: advanced 2771b4319ba4SBarry Smith 2772b4319ba4SBarry Smith Notes: 2773b4319ba4SBarry Smith This can be called if you have precomputed the nonzero structure of the 2774b4319ba4SBarry Smith matrix and want to provide it to the inner matrix object to improve the performance 277511a5261eSBarry Smith of the `MatSetValues()` operation. 2776b4319ba4SBarry Smith 277711a5261eSBarry Smith Call `MatISRestoreLocalMat()` when finished with the local matrix. 277896a6f129SJed Brown 277911a5261eSBarry Smith .seealso: `MATIS`, `MatISRestoreLocalMat()` 2780b4319ba4SBarry Smith @*/ 27819371c9d4SSatish Balay PetscErrorCode MatISGetLocalMat(Mat mat, Mat *local) { 2782b4319ba4SBarry Smith PetscFunctionBegin; 27830700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2784b4319ba4SBarry Smith PetscValidPointer(local, 2); 2785cac4c232SBarry Smith PetscUseMethod(mat, "MatISGetLocalMat_C", (Mat, Mat *), (mat, local)); 2786b4319ba4SBarry Smith PetscFunctionReturn(0); 2787b4319ba4SBarry Smith } 2788b4319ba4SBarry Smith 27893b3b1effSJed Brown /*@ 279011a5261eSBarry Smith MatISRestoreLocalMat - Restores the local matrix obtained with `MatISGetLocalMat()` 27913b3b1effSJed Brown 27923b3b1effSJed Brown Input Parameter: 27933b3b1effSJed Brown . mat - the matrix 27943b3b1effSJed Brown 27953b3b1effSJed Brown Output Parameter: 27963b3b1effSJed Brown . local - the local matrix 27973b3b1effSJed Brown 27983b3b1effSJed Brown Level: advanced 27993b3b1effSJed Brown 280011a5261eSBarry Smith .seealso: `MATIS`, `MatISGetLocalMat()` 28013b3b1effSJed Brown @*/ 28029371c9d4SSatish Balay PetscErrorCode MatISRestoreLocalMat(Mat mat, Mat *local) { 28033b3b1effSJed Brown PetscFunctionBegin; 28043b3b1effSJed Brown PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 28053b3b1effSJed Brown PetscValidPointer(local, 2); 2806cac4c232SBarry Smith PetscUseMethod(mat, "MatISRestoreLocalMat_C", (Mat, Mat *), (mat, local)); 28073b3b1effSJed Brown PetscFunctionReturn(0); 28083b3b1effSJed Brown } 28093b3b1effSJed Brown 28109371c9d4SSatish Balay static PetscErrorCode MatISSetLocalMatType_IS(Mat mat, MatType mtype) { 28118546b261SStefano Zampini Mat_IS *is = (Mat_IS *)mat->data; 28128546b261SStefano Zampini 28138546b261SStefano Zampini PetscFunctionBegin; 28141baa6e33SBarry Smith if (is->A) PetscCall(MatSetType(is->A, mtype)); 28159566063dSJacob Faibussowitsch PetscCall(PetscFree(is->lmattype)); 28169566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(mtype, &is->lmattype)); 28178546b261SStefano Zampini PetscFunctionReturn(0); 28188546b261SStefano Zampini } 28198546b261SStefano Zampini 28208546b261SStefano Zampini /*@ 282111a5261eSBarry Smith MatISSetLocalMatType - Specifies the type of local matrix inside the `MATIS` 28228546b261SStefano Zampini 2823d8d19677SJose E. Roman Input Parameters: 2824a2b725a8SWilliam Gropp + mat - the matrix 2825a2b725a8SWilliam Gropp - mtype - the local matrix type 28268546b261SStefano Zampini 28278546b261SStefano Zampini Level: advanced 28288546b261SStefano Zampini 2829db781477SPatrick Sanan .seealso: `MATIS`, `MatSetType()`, `MatType` 28308546b261SStefano Zampini @*/ 28319371c9d4SSatish Balay PetscErrorCode MatISSetLocalMatType(Mat mat, MatType mtype) { 28328546b261SStefano Zampini PetscFunctionBegin; 28338546b261SStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2834cac4c232SBarry Smith PetscUseMethod(mat, "MatISSetLocalMatType_C", (Mat, MatType), (mat, mtype)); 28358546b261SStefano Zampini PetscFunctionReturn(0); 28368546b261SStefano Zampini } 28378546b261SStefano Zampini 28389371c9d4SSatish Balay static PetscErrorCode MatISSetLocalMat_IS(Mat mat, Mat local) { 28393b03a366Sstefano_zampini Mat_IS *is = (Mat_IS *)mat->data; 28403b03a366Sstefano_zampini PetscInt nrows, ncols, orows, ocols; 28418546b261SStefano Zampini MatType mtype, otype; 28428546b261SStefano Zampini PetscBool sametype = PETSC_TRUE; 28433b03a366Sstefano_zampini 28443b03a366Sstefano_zampini PetscFunctionBegin; 2845e432b41dSStefano Zampini if (is->A && !is->islocalref) { 28469566063dSJacob Faibussowitsch PetscCall(MatGetSize(is->A, &orows, &ocols)); 28479566063dSJacob Faibussowitsch PetscCall(MatGetSize(local, &nrows, &ncols)); 2848aed4548fSBarry Smith PetscCheck(orows == nrows && ocols == ncols, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Local MATIS matrix should be of size %" PetscInt_FMT "x%" PetscInt_FMT " (you passed a %" PetscInt_FMT "x%" PetscInt_FMT " matrix)", orows, ocols, nrows, ncols); 28499566063dSJacob Faibussowitsch PetscCall(MatGetType(local, &mtype)); 28509566063dSJacob Faibussowitsch PetscCall(MatGetType(is->A, &otype)); 28519566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, otype, &sametype)); 28524e4c7dbeSStefano Zampini } 28539566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)local)); 28549566063dSJacob Faibussowitsch PetscCall(MatDestroy(&is->A)); 28553b03a366Sstefano_zampini is->A = local; 28569566063dSJacob Faibussowitsch PetscCall(MatGetType(is->A, &mtype)); 28579566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(mat, mtype)); 285848a46eb9SPierre Jolivet if (!sametype && !is->islocalref) PetscCall(MatISSetUpScatters_Private(mat)); 28593b03a366Sstefano_zampini PetscFunctionReturn(0); 28603b03a366Sstefano_zampini } 28613b03a366Sstefano_zampini 28623b03a366Sstefano_zampini /*@ 286311a5261eSBarry Smith MatISSetLocalMat - Replace the local matrix stored inside a `MATIS` object. 28643b03a366Sstefano_zampini 28658546b261SStefano Zampini Collective on Mat 28668546b261SStefano Zampini 2867d8d19677SJose E. Roman Input Parameters: 2868a2b725a8SWilliam Gropp + mat - the matrix 2869a2b725a8SWilliam Gropp - local - the local matrix 28703b03a366Sstefano_zampini 28713b03a366Sstefano_zampini Level: advanced 28723b03a366Sstefano_zampini 28733b03a366Sstefano_zampini Notes: 287411a5261eSBarry Smith Any previous matrix within the `MATIS` has its reference count decreased by one. 28753b03a366Sstefano_zampini 287611a5261eSBarry Smith This can be called if you have precomputed the local matrix and 287711a5261eSBarry Smith want to provide it to the matrix object `MATIS`. 287811a5261eSBarry Smith 287911a5261eSBarry Smith .seealso: `MATIS`, `MatISSetLocalMatType`, `MatISGetLocalMat()` 28803b03a366Sstefano_zampini @*/ 28819371c9d4SSatish Balay PetscErrorCode MatISSetLocalMat(Mat mat, Mat local) { 28823b03a366Sstefano_zampini PetscFunctionBegin; 28833b03a366Sstefano_zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2884b7ce53b6SStefano Zampini PetscValidHeaderSpecific(local, MAT_CLASSID, 2); 2885cac4c232SBarry Smith PetscUseMethod(mat, "MatISSetLocalMat_C", (Mat, Mat), (mat, local)); 28863b03a366Sstefano_zampini PetscFunctionReturn(0); 28873b03a366Sstefano_zampini } 28883b03a366Sstefano_zampini 28899371c9d4SSatish Balay static PetscErrorCode MatZeroEntries_IS(Mat A) { 28906726f965SBarry Smith Mat_IS *a = (Mat_IS *)A->data; 28916726f965SBarry Smith 28926726f965SBarry Smith PetscFunctionBegin; 28939566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(a->A)); 28946726f965SBarry Smith PetscFunctionReturn(0); 28956726f965SBarry Smith } 28966726f965SBarry Smith 28979371c9d4SSatish Balay static PetscErrorCode MatScale_IS(Mat A, PetscScalar a) { 28982e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS *)A->data; 28992e74eeadSLisandro Dalcin 29002e74eeadSLisandro Dalcin PetscFunctionBegin; 29019566063dSJacob Faibussowitsch PetscCall(MatScale(is->A, a)); 29022e74eeadSLisandro Dalcin PetscFunctionReturn(0); 29032e74eeadSLisandro Dalcin } 29042e74eeadSLisandro Dalcin 29059371c9d4SSatish Balay static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v) { 29062e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS *)A->data; 29072e74eeadSLisandro Dalcin 29082e74eeadSLisandro Dalcin PetscFunctionBegin; 29092e74eeadSLisandro Dalcin /* get diagonal of the local matrix */ 29109566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(is->A, is->y)); 29112e74eeadSLisandro Dalcin 29122e74eeadSLisandro Dalcin /* scatter diagonal back into global vector */ 29139566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0)); 29149566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, is->y, v, ADD_VALUES, SCATTER_REVERSE)); 29159566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, is->y, v, ADD_VALUES, SCATTER_REVERSE)); 29162e74eeadSLisandro Dalcin PetscFunctionReturn(0); 29172e74eeadSLisandro Dalcin } 29182e74eeadSLisandro Dalcin 29199371c9d4SSatish Balay static PetscErrorCode MatSetOption_IS(Mat A, MatOption op, PetscBool flg) { 29206726f965SBarry Smith Mat_IS *a = (Mat_IS *)A->data; 29216726f965SBarry Smith 29226726f965SBarry Smith PetscFunctionBegin; 29239566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg)); 29246726f965SBarry Smith PetscFunctionReturn(0); 29256726f965SBarry Smith } 29266726f965SBarry Smith 29279371c9d4SSatish Balay static PetscErrorCode MatAXPY_IS(Mat Y, PetscScalar a, Mat X, MatStructure str) { 2928f26d0771SStefano Zampini Mat_IS *y = (Mat_IS *)Y->data; 2929f26d0771SStefano Zampini Mat_IS *x; 2930f26d0771SStefano Zampini 2931f26d0771SStefano Zampini PetscFunctionBegin; 293276bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 293376bd3646SJed Brown PetscBool ismatis; 29349566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)X, MATIS, &ismatis)); 293528b400f6SJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)Y), PETSC_ERR_SUP, "Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS"); 293676bd3646SJed Brown } 2937f26d0771SStefano Zampini x = (Mat_IS *)X->data; 29389566063dSJacob Faibussowitsch PetscCall(MatAXPY(y->A, a, x->A, str)); 2939f26d0771SStefano Zampini PetscFunctionReturn(0); 2940f26d0771SStefano Zampini } 2941f26d0771SStefano Zampini 29429371c9d4SSatish Balay static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A, IS row, IS col, Mat *submat) { 2943f26d0771SStefano Zampini Mat lA; 2944e432b41dSStefano Zampini Mat_IS *matis = (Mat_IS *)(A->data); 2945f26d0771SStefano Zampini ISLocalToGlobalMapping rl2g, cl2g; 2946f26d0771SStefano Zampini IS is; 2947f26d0771SStefano Zampini const PetscInt *rg, *rl; 2948f26d0771SStefano Zampini PetscInt nrg; 2949f26d0771SStefano Zampini PetscInt N, M, nrl, i, *idxs; 2950f26d0771SStefano Zampini 2951f26d0771SStefano Zampini PetscFunctionBegin; 29529566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(A->rmap->mapping, &rg)); 29539566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(row, &nrl)); 29549566063dSJacob Faibussowitsch PetscCall(ISGetIndices(row, &rl)); 29559566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(A->rmap->mapping, &nrg)); 295676bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 295708401ef6SPierre 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); 295876bd3646SJed Brown } 29599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nrg, &idxs)); 2960f26d0771SStefano Zampini /* map from [0,nrl) to row */ 2961f26d0771SStefano Zampini for (i = 0; i < nrl; i++) idxs[i] = rl[i]; 2962f26d0771SStefano Zampini for (i = nrl; i < nrg; i++) idxs[i] = -1; 29639566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(row, &rl)); 29649566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping, &rg)); 29659566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A), nrg, idxs, PETSC_OWN_POINTER, &is)); 29669566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g)); 29679566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2968f26d0771SStefano Zampini /* compute new l2g map for columns */ 2969e432b41dSStefano Zampini if (col != row || matis->rmapping != matis->cmapping || matis->A->rmap->mapping != matis->A->cmap->mapping) { 2970f26d0771SStefano Zampini const PetscInt *cg, *cl; 2971f26d0771SStefano Zampini PetscInt ncg; 2972f26d0771SStefano Zampini PetscInt ncl; 2973f26d0771SStefano Zampini 29749566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(A->cmap->mapping, &cg)); 29759566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(col, &ncl)); 29769566063dSJacob Faibussowitsch PetscCall(ISGetIndices(col, &cl)); 29779566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(A->cmap->mapping, &ncg)); 297876bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 297908401ef6SPierre 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); 298076bd3646SJed Brown } 29819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncg, &idxs)); 2982f26d0771SStefano Zampini /* map from [0,ncl) to col */ 2983f26d0771SStefano Zampini for (i = 0; i < ncl; i++) idxs[i] = cl[i]; 2984f26d0771SStefano Zampini for (i = ncl; i < ncg; i++) idxs[i] = -1; 29859566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(col, &cl)); 29869566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping, &cg)); 29879566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A), ncg, idxs, PETSC_OWN_POINTER, &is)); 29889566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g)); 29899566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2990f26d0771SStefano Zampini } else { 29919566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)rl2g)); 2992f26d0771SStefano Zampini cl2g = rl2g; 2993f26d0771SStefano Zampini } 2994f26d0771SStefano Zampini /* create the MATIS submatrix */ 29959566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, &N)); 29969566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), submat)); 29979566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*submat, PETSC_DECIDE, PETSC_DECIDE, M, N)); 29989566063dSJacob Faibussowitsch PetscCall(MatSetType(*submat, MATIS)); 2999b0aa3428SStefano Zampini matis = (Mat_IS *)((*submat)->data); 3000f26d0771SStefano Zampini matis->islocalref = PETSC_TRUE; 30019566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*submat, rl2g, cl2g)); 30029566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A, &lA)); 30039566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*submat, lA)); 30049566063dSJacob Faibussowitsch PetscCall(MatSetUp(*submat)); 30059566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*submat, MAT_FINAL_ASSEMBLY)); 30069566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*submat, MAT_FINAL_ASSEMBLY)); 30079566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 30089566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 3009e432b41dSStefano Zampini 3010f26d0771SStefano Zampini /* remove unsupported ops */ 30119566063dSJacob Faibussowitsch PetscCall(PetscMemzero((*submat)->ops, sizeof(struct _MatOps))); 3012f26d0771SStefano Zampini (*submat)->ops->destroy = MatDestroy_IS; 3013f26d0771SStefano Zampini (*submat)->ops->setvalueslocal = MatSetValuesLocal_SubMat_IS; 3014f26d0771SStefano Zampini (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS; 3015f26d0771SStefano Zampini (*submat)->ops->assemblybegin = MatAssemblyBegin_IS; 3016f26d0771SStefano Zampini (*submat)->ops->assemblyend = MatAssemblyEnd_IS; 3017f26d0771SStefano Zampini PetscFunctionReturn(0); 3018f26d0771SStefano Zampini } 3019f26d0771SStefano Zampini 30209371c9d4SSatish Balay static PetscErrorCode MatSetFromOptions_IS(Mat A, PetscOptionItems *PetscOptionsObject) { 3021872cf891SStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 30228546b261SStefano Zampini char type[256]; 30238546b261SStefano Zampini PetscBool flg; 3024872cf891SStefano Zampini 3025872cf891SStefano Zampini PetscFunctionBegin; 3026d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "MATIS options"); 3027d0dbe9f7SStefano Zampini PetscCall(PetscOptionsBool("-matis_keepassembled", "Store an assembled version if needed", "MatISKeepAssembled", a->keepassembled, &a->keepassembled, NULL)); 30289566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-matis_fixempty", "Fix local matrices in case of empty local rows/columns", "MatISFixLocalEmpty", a->locempty, &a->locempty, NULL)); 30299566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-matis_storel2l", "Store local-to-local matrices generated from PtAP operations", "MatISStoreL2L", a->storel2l, &a->storel2l, NULL)); 30309566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-matis_localmat_type", "Matrix type", "MatISSetLocalMatType", MatList, a->lmattype, type, 256, &flg)); 30311baa6e33SBarry Smith if (flg) PetscCall(MatISSetLocalMatType(A, type)); 30321baa6e33SBarry Smith if (a->A) PetscCall(MatSetFromOptions(a->A)); 3033d0609cedSBarry Smith PetscOptionsHeadEnd(); 3034872cf891SStefano Zampini PetscFunctionReturn(0); 3035872cf891SStefano Zampini } 3036872cf891SStefano Zampini 3037284134d9SBarry Smith /*@ 303811a5261eSBarry Smith MatCreateIS - Creates a "process" unassembled matrix, `MATIS`, assembled on each 3039284134d9SBarry Smith process but not across processes. 3040284134d9SBarry Smith 3041284134d9SBarry Smith Input Parameters: 3042284134d9SBarry Smith + comm - MPI communicator that will share the matrix 3043e176bc59SStefano Zampini . bs - block size of the matrix 3044df3898eeSBarry Smith . m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products 3045e176bc59SStefano Zampini . rmap - local to global map for rows 3046e176bc59SStefano Zampini - cmap - local to global map for cols 3047284134d9SBarry Smith 3048284134d9SBarry Smith Output Parameter: 3049284134d9SBarry Smith . A - the resulting matrix 3050284134d9SBarry Smith 30518e6c10adSSatish Balay Level: advanced 30528e6c10adSSatish Balay 305395452b02SPatrick Sanan Notes: 3054fc989267SStefano Zampini m and n are NOT related to the size of the map; they represent the size of the local parts of the distributed vectors 305511a5261eSBarry Smith used in `MatMult()` operations. The sizes of rmap and cmap define the size of the local matrices. 305611a5261eSBarry Smith 3057fc989267SStefano Zampini If rmap (cmap) is NULL, then the local row (column) spaces matches the global space. 3058284134d9SBarry Smith 3059db781477SPatrick Sanan .seealso: `MATIS`, `MatSetLocalToGlobalMapping()` 3060284134d9SBarry Smith @*/ 30619371c9d4SSatish Balay PetscErrorCode MatCreateIS(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt M, PetscInt N, ISLocalToGlobalMapping rmap, ISLocalToGlobalMapping cmap, Mat *A) { 3062284134d9SBarry Smith PetscFunctionBegin; 30639566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, A)); 30649566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A, m, n, M, N)); 306548a46eb9SPierre Jolivet if (bs > 0) PetscCall(MatSetBlockSize(*A, bs)); 30669566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATIS)); 30679566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*A, rmap, cmap)); 3068284134d9SBarry Smith PetscFunctionReturn(0); 3069284134d9SBarry Smith } 3070284134d9SBarry Smith 30719371c9d4SSatish Balay static PetscErrorCode MatHasOperation_IS(Mat A, MatOperation op, PetscBool *has) { 30728b9382cfSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3073e26763e4SStefano Zampini MatOperation tobefiltered[] = {MATOP_MULT_ADD, MATOP_MULT_TRANSPOSE_ADD, MATOP_GET_DIAGONAL_BLOCK, MATOP_INCREASE_OVERLAP}; 30748b9382cfSStefano Zampini 30758b9382cfSStefano Zampini PetscFunctionBegin; 30768b9382cfSStefano Zampini *has = PETSC_FALSE; 3077e26763e4SStefano Zampini if (!((void **)A->ops)[op] || !a->A) PetscFunctionReturn(0); 3078d0dbe9f7SStefano Zampini *has = PETSC_TRUE; 30799371c9d4SSatish Balay for (PetscInt i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(tobefiltered); i++) 30809371c9d4SSatish Balay if (op == tobefiltered[i]) PetscFunctionReturn(0); 30819566063dSJacob Faibussowitsch PetscCall(MatHasOperation(a->A, op, has)); 30828b9382cfSStefano Zampini PetscFunctionReturn(0); 30838b9382cfSStefano Zampini } 30848b9382cfSStefano Zampini 30859371c9d4SSatish Balay static PetscErrorCode MatSetValuesCOO_IS(Mat A, const PetscScalar v[], InsertMode imode) { 3086e432b41dSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3087e432b41dSStefano Zampini 3088e432b41dSStefano Zampini PetscFunctionBegin; 30899566063dSJacob Faibussowitsch PetscCall(MatSetValuesCOO(a->A, v, imode)); 30909566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 30919566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 3092e432b41dSStefano Zampini PetscFunctionReturn(0); 3093e432b41dSStefano Zampini } 3094e432b41dSStefano Zampini 30959371c9d4SSatish Balay static PetscErrorCode MatSetPreallocationCOOLocal_IS(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[]) { 3096e432b41dSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3097e432b41dSStefano Zampini 3098e432b41dSStefano Zampini PetscFunctionBegin; 3099e432b41dSStefano Zampini PetscCheck(a->A, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Need to provide l2g map first via MatSetLocalToGlobalMapping"); 3100e432b41dSStefano Zampini if (a->A->rmap->mapping || a->A->cmap->mapping) { 31019566063dSJacob Faibussowitsch PetscCall(MatSetPreallocationCOOLocal(a->A, ncoo, coo_i, coo_j)); 3102e432b41dSStefano Zampini } else { 31039566063dSJacob Faibussowitsch PetscCall(MatSetPreallocationCOO(a->A, ncoo, coo_i, coo_j)); 3104e432b41dSStefano Zampini } 31059566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", MatSetValuesCOO_IS)); 3106e432b41dSStefano Zampini A->preallocated = PETSC_TRUE; 3107e432b41dSStefano Zampini PetscFunctionReturn(0); 3108e432b41dSStefano Zampini } 3109e432b41dSStefano Zampini 31109371c9d4SSatish Balay static PetscErrorCode MatSetPreallocationCOO_IS(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[]) { 3111e432b41dSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3112e432b41dSStefano Zampini 3113e432b41dSStefano Zampini PetscFunctionBegin; 3114e432b41dSStefano Zampini PetscCheck(a->A, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Need to provide l2g map first via MatSetLocalToGlobalMapping"); 3115e432b41dSStefano Zampini PetscCheck(ncoo <= PETSC_MAX_INT, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "ncoo %" PetscCount_FMT " overflowed PetscInt; configure --with-64-bit-indices or request support", ncoo); 3116e8729f6fSJunchao Zhang PetscCall(ISGlobalToLocalMappingApply(a->rmapping, IS_GTOLM_MASK, ncoo, coo_i, NULL, coo_i)); 3117e8729f6fSJunchao Zhang PetscCall(ISGlobalToLocalMappingApply(a->cmapping, IS_GTOLM_MASK, ncoo, coo_j, NULL, coo_j)); 3118e8729f6fSJunchao Zhang PetscCall(MatSetPreallocationCOO(a->A, ncoo, coo_i, coo_j)); 31199566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", MatSetValuesCOO_IS)); 3120e432b41dSStefano Zampini A->preallocated = PETSC_TRUE; 3121e432b41dSStefano Zampini PetscFunctionReturn(0); 3122e432b41dSStefano Zampini } 3123e432b41dSStefano Zampini 31249371c9d4SSatish Balay static PetscErrorCode MatISGetAssembled_Private(Mat A, Mat *tA) { 3125d0dbe9f7SStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3126d0dbe9f7SStefano Zampini PetscObjectState Astate, aAstate = PETSC_MIN_INT; 3127d0dbe9f7SStefano Zampini PetscObjectState Annzstate, aAnnzstate = PETSC_MIN_INT; 3128d0dbe9f7SStefano Zampini 3129d0dbe9f7SStefano Zampini PetscFunctionBegin; 3130d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateGet((PetscObject)A, &Astate)); 3131d0dbe9f7SStefano Zampini Annzstate = A->nonzerostate; 3132d0dbe9f7SStefano Zampini if (a->assembledA) { 3133d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateGet((PetscObject)a->assembledA, &aAstate)); 3134d0dbe9f7SStefano Zampini aAnnzstate = a->assembledA->nonzerostate; 3135d0dbe9f7SStefano Zampini } 3136d0dbe9f7SStefano Zampini if (aAnnzstate != Annzstate) PetscCall(MatDestroy(&a->assembledA)); 3137d0dbe9f7SStefano Zampini if (Astate != aAstate || !a->assembledA) { 3138d0dbe9f7SStefano Zampini MatType aAtype; 3139d0dbe9f7SStefano Zampini PetscMPIInt size; 3140d0dbe9f7SStefano Zampini PetscInt rbs, cbs, bs; 3141d0dbe9f7SStefano Zampini 3142d0dbe9f7SStefano Zampini /* the assembled form is used as temporary storage for parallel operations 3143d0dbe9f7SStefano Zampini like createsubmatrices and the like, do not waste device memory */ 3144d0dbe9f7SStefano Zampini PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 3145d0dbe9f7SStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockSize(a->cmapping, &cbs)); 3146d0dbe9f7SStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockSize(a->rmapping, &rbs)); 3147d0dbe9f7SStefano Zampini bs = rbs == cbs ? rbs : 1; 3148d0dbe9f7SStefano Zampini if (a->assembledA) PetscCall(MatGetType(a->assembledA, &aAtype)); 3149d0dbe9f7SStefano Zampini else if (size > 1) aAtype = bs > 1 ? MATMPIBAIJ : MATMPIAIJ; 3150d0dbe9f7SStefano Zampini else aAtype = bs > 1 ? MATSEQBAIJ : MATSEQAIJ; 3151d0dbe9f7SStefano Zampini 3152d0dbe9f7SStefano Zampini PetscCall(MatConvert(A, aAtype, a->assembledA ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX, &a->assembledA)); 3153d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateSet((PetscObject)a->assembledA, Astate)); 3154d0dbe9f7SStefano Zampini a->assembledA->nonzerostate = Annzstate; 3155d0dbe9f7SStefano Zampini } 3156d0dbe9f7SStefano Zampini PetscCall(PetscObjectReference((PetscObject)a->assembledA)); 3157d0dbe9f7SStefano Zampini *tA = a->assembledA; 3158d0dbe9f7SStefano Zampini if (!a->keepassembled) PetscCall(MatDestroy(&a->assembledA)); 3159d0dbe9f7SStefano Zampini PetscFunctionReturn(0); 3160d0dbe9f7SStefano Zampini } 3161d0dbe9f7SStefano Zampini 31629371c9d4SSatish Balay static PetscErrorCode MatISRestoreAssembled_Private(Mat A, Mat *tA) { 3163d0dbe9f7SStefano Zampini PetscFunctionBegin; 3164d0dbe9f7SStefano Zampini PetscCall(MatDestroy(tA)); 3165d0dbe9f7SStefano Zampini *tA = NULL; 3166d0dbe9f7SStefano Zampini PetscFunctionReturn(0); 3167d0dbe9f7SStefano Zampini } 3168d0dbe9f7SStefano Zampini 31699371c9d4SSatish Balay static PetscErrorCode MatGetDiagonalBlock_IS(Mat A, Mat *dA) { 3170d0dbe9f7SStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3171d0dbe9f7SStefano Zampini PetscObjectState Astate, dAstate = PETSC_MIN_INT; 3172d0dbe9f7SStefano Zampini 3173d0dbe9f7SStefano Zampini PetscFunctionBegin; 3174d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateGet((PetscObject)A, &Astate)); 3175d0dbe9f7SStefano Zampini if (a->dA) PetscCall(PetscObjectStateGet((PetscObject)a->dA, &dAstate)); 3176d0dbe9f7SStefano Zampini if (Astate != dAstate) { 3177d0dbe9f7SStefano Zampini Mat tA; 3178d0dbe9f7SStefano Zampini MatType ltype; 3179d0dbe9f7SStefano Zampini 3180d0dbe9f7SStefano Zampini PetscCall(MatDestroy(&a->dA)); 3181d0dbe9f7SStefano Zampini PetscCall(MatISGetAssembled_Private(A, &tA)); 3182d0dbe9f7SStefano Zampini PetscCall(MatGetDiagonalBlock(tA, &a->dA)); 3183d0dbe9f7SStefano Zampini PetscCall(MatPropagateSymmetryOptions(tA, a->dA)); 3184d0dbe9f7SStefano Zampini PetscCall(MatGetType(a->A, <ype)); 3185d0dbe9f7SStefano Zampini PetscCall(MatConvert(a->dA, ltype, MAT_INPLACE_MATRIX, &a->dA)); 3186d0dbe9f7SStefano Zampini PetscCall(PetscObjectReference((PetscObject)a->dA)); 3187d0dbe9f7SStefano Zampini PetscCall(MatISRestoreAssembled_Private(A, &tA)); 3188d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateSet((PetscObject)a->dA, Astate)); 3189d0dbe9f7SStefano Zampini } 3190d0dbe9f7SStefano Zampini *dA = a->dA; 3191d0dbe9f7SStefano Zampini PetscFunctionReturn(0); 3192d0dbe9f7SStefano Zampini } 3193d0dbe9f7SStefano Zampini 31949371c9d4SSatish Balay static PetscErrorCode MatCreateSubMatrices_IS(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse reuse, Mat *submat[]) { 3195d0dbe9f7SStefano Zampini Mat tA; 3196d0dbe9f7SStefano Zampini 3197d0dbe9f7SStefano Zampini PetscFunctionBegin; 3198d0dbe9f7SStefano Zampini PetscCall(MatISGetAssembled_Private(A, &tA)); 3199d0dbe9f7SStefano Zampini PetscCall(MatCreateSubMatrices(tA, n, irow, icol, reuse, submat)); 3200d0dbe9f7SStefano Zampini /* MatCreateSubMatrices_MPIAIJ is a mess at the moment */ 3201d0dbe9f7SStefano Zampini #if 0 3202d0dbe9f7SStefano Zampini { 3203d0dbe9f7SStefano Zampini Mat_IS *a = (Mat_IS*)A->data; 3204d0dbe9f7SStefano Zampini MatType ltype; 3205d0dbe9f7SStefano Zampini VecType vtype; 3206d0dbe9f7SStefano Zampini char *flg; 3207d0dbe9f7SStefano Zampini 3208d0dbe9f7SStefano Zampini PetscCall(MatGetType(a->A,<ype)); 3209d0dbe9f7SStefano Zampini PetscCall(MatGetVecType(a->A,&vtype)); 3210d0dbe9f7SStefano Zampini PetscCall(PetscStrstr(vtype,"cuda",&flg)); 3211d0dbe9f7SStefano Zampini if (!flg) PetscCall(PetscStrstr(vtype,"hip",&flg)); 3212d0dbe9f7SStefano Zampini if (!flg) PetscCall(PetscStrstr(vtype,"kokkos",&flg)); 3213d0dbe9f7SStefano Zampini if (flg) { 3214d0dbe9f7SStefano Zampini for (PetscInt i = 0; i < n; i++) { 3215d0dbe9f7SStefano Zampini Mat sA = (*submat)[i]; 3216d0dbe9f7SStefano Zampini 3217d0dbe9f7SStefano Zampini PetscCall(MatConvert(sA,ltype,MAT_INPLACE_MATRIX,&sA)); 3218d0dbe9f7SStefano Zampini (*submat)[i] = sA; 3219d0dbe9f7SStefano Zampini } 3220d0dbe9f7SStefano Zampini } 3221d0dbe9f7SStefano Zampini } 3222d0dbe9f7SStefano Zampini #endif 3223d0dbe9f7SStefano Zampini PetscCall(MatISRestoreAssembled_Private(A, &tA)); 3224d0dbe9f7SStefano Zampini PetscFunctionReturn(0); 3225d0dbe9f7SStefano Zampini } 3226d0dbe9f7SStefano Zampini 32279371c9d4SSatish Balay static PetscErrorCode MatIncreaseOverlap_IS(Mat A, PetscInt n, IS is[], PetscInt ov) { 3228d0dbe9f7SStefano Zampini Mat tA; 3229d0dbe9f7SStefano Zampini 3230d0dbe9f7SStefano Zampini PetscFunctionBegin; 3231d0dbe9f7SStefano Zampini PetscCall(MatISGetAssembled_Private(A, &tA)); 3232d0dbe9f7SStefano Zampini PetscCall(MatIncreaseOverlap(tA, n, is, ov)); 3233d0dbe9f7SStefano Zampini PetscCall(MatISRestoreAssembled_Private(A, &tA)); 3234d0dbe9f7SStefano Zampini PetscFunctionReturn(0); 3235d0dbe9f7SStefano Zampini } 3236d0dbe9f7SStefano Zampini 3237e432b41dSStefano Zampini /*@ 323811a5261eSBarry Smith MatISGetLocalToGlobalMapping - Gets the local-to-global numbering of the `MATIS` object 3239e432b41dSStefano Zampini 3240e432b41dSStefano Zampini Not Collective 3241e432b41dSStefano Zampini 3242e432b41dSStefano Zampini Input Parameter: 3243e432b41dSStefano Zampini . A - the matrix 3244e432b41dSStefano Zampini 3245e432b41dSStefano Zampini Output Parameters: 3246e432b41dSStefano Zampini + rmapping - row mapping 3247e432b41dSStefano Zampini - cmapping - column mapping 3248e432b41dSStefano Zampini 324911a5261eSBarry Smith Note: 325011a5261eSBarry 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. 3251e432b41dSStefano Zampini 3252e432b41dSStefano Zampini Level: advanced 3253e432b41dSStefano Zampini 325411a5261eSBarry Smith .seealso: `MatIS`, `MatSetLocalToGlobalMapping()` 3255e432b41dSStefano Zampini @*/ 32569371c9d4SSatish Balay PetscErrorCode MatISGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) { 3257e432b41dSStefano Zampini PetscFunctionBegin; 3258e432b41dSStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3259e432b41dSStefano Zampini PetscValidType(A, 1); 3260e432b41dSStefano Zampini if (rmapping) PetscValidPointer(rmapping, 2); 3261e432b41dSStefano Zampini if (cmapping) PetscValidPointer(cmapping, 3); 3262cac4c232SBarry Smith PetscUseMethod(A, "MatISGetLocalToGlobalMapping_C", (Mat, ISLocalToGlobalMapping *, ISLocalToGlobalMapping *), (A, rmapping, cmapping)); 3263e432b41dSStefano Zampini PetscFunctionReturn(0); 3264e432b41dSStefano Zampini } 3265e432b41dSStefano Zampini 32669371c9d4SSatish Balay static PetscErrorCode MatISGetLocalToGlobalMapping_IS(Mat A, ISLocalToGlobalMapping *r, ISLocalToGlobalMapping *c) { 3267e432b41dSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3268e432b41dSStefano Zampini 3269e432b41dSStefano Zampini PetscFunctionBegin; 3270e432b41dSStefano Zampini if (r) *r = a->rmapping; 3271e432b41dSStefano Zampini if (c) *c = a->cmapping; 3272e432b41dSStefano Zampini PetscFunctionReturn(0); 3273e432b41dSStefano Zampini } 3274e432b41dSStefano Zampini 3275b4319ba4SBarry Smith /*MC 327611a5261eSBarry Smith MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. `PCBDDC` or `KSPFETIDP`). 3277b89f26deSStefano Zampini This stores the matrices in globally unassembled form. Each processor assembles only its local Neumann problem and the parallel matrix vector 3278b4319ba4SBarry Smith product is handled "implicitly". 3279b4319ba4SBarry Smith 3280b4319ba4SBarry Smith Options Database Keys: 328175d48cdbSStefano Zampini + -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions() 328275d48cdbSStefano Zampini . -matis_fixempty - Fixes local matrices in case of empty local rows/columns. 328375d48cdbSStefano Zampini - -matis_storel2l - stores the local-to-local operators generated by the Galerkin process of MatPtAP(). 3284b4319ba4SBarry Smith 328595452b02SPatrick Sanan Notes: 328695452b02SPatrick Sanan Options prefix for the inner matrix are given by -is_mat_xxx 3287b4319ba4SBarry Smith 328811a5261eSBarry Smith You must call `MatSetLocalToGlobalMapping()` before using this matrix type. 3289b4319ba4SBarry Smith 3290b4319ba4SBarry Smith You can do matrix preallocation on the local matrix after you obtain it with 329111a5261eSBarry Smith `MatISGetLocalMat()`; otherwise, you could use `MatISSetPreallocation()` 3292b4319ba4SBarry Smith 3293b4319ba4SBarry Smith Level: advanced 3294b4319ba4SBarry Smith 329511a5261eSBarry Smith .seealso: `MATIS`, `Mat`, `MatISGetLocalMat()`, `MatSetLocalToGlobalMapping()`, `MatISSetPreallocation()`, `MatCreateIS()`, `PCBDDC`, `KSPFETIDP` 3296b4319ba4SBarry Smith M*/ 32979371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A) { 3298e432b41dSStefano Zampini Mat_IS *a; 3299b4319ba4SBarry Smith 3300b4319ba4SBarry Smith PetscFunctionBegin; 33019566063dSJacob Faibussowitsch PetscCall(PetscNewLog(A, &a)); 33029566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATAIJ, &a->lmattype)); 3303e432b41dSStefano Zampini A->data = (void *)a; 3304b4319ba4SBarry Smith 3305e176bc59SStefano Zampini /* matrix ops */ 33069566063dSJacob Faibussowitsch PetscCall(PetscMemzero(A->ops, sizeof(struct _MatOps))); 3307b4319ba4SBarry Smith A->ops->mult = MatMult_IS; 33082e74eeadSLisandro Dalcin A->ops->multadd = MatMultAdd_IS; 33092e74eeadSLisandro Dalcin A->ops->multtranspose = MatMultTranspose_IS; 33102e74eeadSLisandro Dalcin A->ops->multtransposeadd = MatMultTransposeAdd_IS; 3311b4319ba4SBarry Smith A->ops->destroy = MatDestroy_IS; 3312b4319ba4SBarry Smith A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS; 33132e74eeadSLisandro Dalcin A->ops->setvalues = MatSetValues_IS; 331498921651SStefano Zampini A->ops->setvaluesblocked = MatSetValuesBlocked_IS; 3315b4319ba4SBarry Smith A->ops->setvalueslocal = MatSetValuesLocal_IS; 3316f0006bf2SLisandro Dalcin A->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_IS; 33172e74eeadSLisandro Dalcin A->ops->zerorows = MatZeroRows_IS; 3318f0ae7da4SStefano Zampini A->ops->zerorowscolumns = MatZeroRowsColumns_IS; 3319b4319ba4SBarry Smith A->ops->assemblybegin = MatAssemblyBegin_IS; 3320b4319ba4SBarry Smith A->ops->assemblyend = MatAssemblyEnd_IS; 3321b4319ba4SBarry Smith A->ops->view = MatView_IS; 33226726f965SBarry Smith A->ops->zeroentries = MatZeroEntries_IS; 33232e74eeadSLisandro Dalcin A->ops->scale = MatScale_IS; 33242e74eeadSLisandro Dalcin A->ops->getdiagonal = MatGetDiagonal_IS; 33256726f965SBarry Smith A->ops->setoption = MatSetOption_IS; 332669796d55SStefano Zampini A->ops->ishermitian = MatIsHermitian_IS; 332769796d55SStefano Zampini A->ops->issymmetric = MatIsSymmetric_IS; 332845471136SStefano Zampini A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS; 3329ad6194a2SStefano Zampini A->ops->duplicate = MatDuplicate_IS; 33306bd84002SStefano Zampini A->ops->missingdiagonal = MatMissingDiagonal_IS; 33312b404112SStefano Zampini A->ops->copy = MatCopy_IS; 3332659959c5SStefano Zampini A->ops->getlocalsubmatrix = MatGetLocalSubMatrix_IS; 33337dae84e0SHong Zhang A->ops->createsubmatrix = MatCreateSubMatrix_IS; 3334f26d0771SStefano Zampini A->ops->axpy = MatAXPY_IS; 33353fd1c9e7SStefano Zampini A->ops->diagonalset = MatDiagonalSet_IS; 33363fd1c9e7SStefano Zampini A->ops->shift = MatShift_IS; 3337d7f69cd0SStefano Zampini A->ops->transpose = MatTranspose_IS; 33387fa8f2d3SStefano Zampini A->ops->getinfo = MatGetInfo_IS; 3339ad219c80Sstefano_zampini A->ops->diagonalscale = MatDiagonalScale_IS; 3340872cf891SStefano Zampini A->ops->setfromoptions = MatSetFromOptions_IS; 3341fc989267SStefano Zampini A->ops->setup = MatSetUp_IS; 33428b9382cfSStefano Zampini A->ops->hasoperation = MatHasOperation_IS; 3343d0dbe9f7SStefano Zampini A->ops->getdiagonalblock = MatGetDiagonalBlock_IS; 3344d0dbe9f7SStefano Zampini A->ops->createsubmatrices = MatCreateSubMatrices_IS; 3345d0dbe9f7SStefano Zampini A->ops->increaseoverlap = MatIncreaseOverlap_IS; 3346b4319ba4SBarry Smith 3347b7ce53b6SStefano Zampini /* special MATIS functions */ 33489566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMatType_C", MatISSetLocalMatType_IS)); 33499566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalMat_C", MatISGetLocalMat_IS)); 33509566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISRestoreLocalMat_C", MatISRestoreLocalMat_IS)); 33519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMat_C", MatISSetLocalMat_IS)); 33529566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetMPIXAIJ_C", MatConvert_IS_XAIJ)); 33539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetPreallocation_C", MatISSetPreallocation_IS)); 33549566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISStoreL2L_C", MatISStoreL2L_IS)); 33559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISFixLocalEmpty_C", MatISFixLocalEmpty_IS)); 33569566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalToGlobalMapping_C", MatISGetLocalToGlobalMapping_IS)); 33579566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpiaij_C", MatConvert_IS_XAIJ)); 33589566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpibaij_C", MatConvert_IS_XAIJ)); 33599566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpisbaij_C", MatConvert_IS_XAIJ)); 33609566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqaij_C", MatConvert_IS_XAIJ)); 33619566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqbaij_C", MatConvert_IS_XAIJ)); 33629566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqsbaij_C", MatConvert_IS_XAIJ)); 33639566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_aij_C", MatConvert_IS_XAIJ)); 33649566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOOLocal_C", MatSetPreallocationCOOLocal_IS)); 33659566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_IS)); 33669566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, MATIS)); 3367b4319ba4SBarry Smith PetscFunctionReturn(0); 3368b4319ba4SBarry Smith } 3369