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)); 61*48a46eb9SPierre 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)); 65*48a46eb9SPierre 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; 109*48a46eb9SPierre 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; 261*48a46eb9SPierre 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; 271*48a46eb9SPierre Jolivet for (i = 0; i < lf->nr; i++) PetscCall(ISDestroy(&lf->rf[i])); 272*48a46eb9SPierre 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)); 332*48a46eb9SPierre 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++) { 455*48a46eb9SPierre Jolivet if (ndmapi[i] < 0 && ndmapc[i] < 2) PetscCall(ISCreateStride(comm, 1, i + A->rmap->rstart, 1, &workis[cnt++])); 456fabe8965SStefano Zampini } 457*48a46eb9SPierre 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); 547*48a46eb9SPierre 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 */ 8369566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)nest[i][j], MATTRANSPOSEMAT, &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++) { 1027*48a46eb9SPierre 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])); 1051*48a46eb9SPierre 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++) { 1067*48a46eb9SPierre 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 */ 1116*48a46eb9SPierre Jolivet for (i = 0; i < nr; i++) PetscCall(ISDestroy(&islrow[i])); 1117*48a46eb9SPierre 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)); 1316*48a46eb9SPierre 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)); 1327*48a46eb9SPierre 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 /*@ 150775d48cdbSStefano Zampini MatISStoreL2L - Store local-to-local operators during the Galerkin process of 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 151775d48cdbSStefano Zampini Notes: 151875d48cdbSStefano Zampini 1519db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateIS()`, `MatISSetPreallocation()`, `MatPtAP()` 152075d48cdbSStefano Zampini @*/ 15219371c9d4SSatish Balay PetscErrorCode MatISStoreL2L(Mat A, PetscBool store) { 152275d48cdbSStefano Zampini PetscFunctionBegin; 152375d48cdbSStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 152475d48cdbSStefano Zampini PetscValidType(A, 1); 152575d48cdbSStefano Zampini PetscValidLogicalCollectiveBool(A, store, 2); 1526cac4c232SBarry Smith PetscTryMethod(A, "MatISStoreL2L_C", (Mat, PetscBool), (A, store)); 152775d48cdbSStefano Zampini PetscFunctionReturn(0); 152875d48cdbSStefano Zampini } 152975d48cdbSStefano Zampini 15309371c9d4SSatish Balay static PetscErrorCode MatISStoreL2L_IS(Mat A, PetscBool store) { 153175d48cdbSStefano Zampini Mat_IS *matis = (Mat_IS *)(A->data); 153275d48cdbSStefano Zampini 153375d48cdbSStefano Zampini PetscFunctionBegin; 153475d48cdbSStefano Zampini matis->storel2l = store; 1535*48a46eb9SPierre Jolivet if (!store) PetscCall(PetscObjectCompose((PetscObject)(A), "_MatIS_PtAP_l2l", NULL)); 153675d48cdbSStefano Zampini PetscFunctionReturn(0); 153775d48cdbSStefano Zampini } 153875d48cdbSStefano Zampini 153975d48cdbSStefano Zampini /*@ 1540f03112d0SStefano Zampini MatISFixLocalEmpty - Compress out zero local rows from the local matrices 1541f03112d0SStefano Zampini 1542d083f849SBarry Smith Collective 1543f03112d0SStefano Zampini 1544f03112d0SStefano Zampini Input Parameters: 1545f03112d0SStefano Zampini + A - the matrix 1546f03112d0SStefano Zampini - fix - the boolean flag 1547f03112d0SStefano Zampini 1548f03112d0SStefano Zampini Level: advanced 1549f03112d0SStefano Zampini 1550f03112d0SStefano Zampini Notes: When fix is true, new local matrices and l2g maps are generated during the final assembly process. 1551f03112d0SStefano Zampini 1552db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateIS()`, `MatISSetPreallocation()`, `MatAssemblyEnd()`, `MAT_FINAL_ASSEMBLY` 1553f03112d0SStefano Zampini @*/ 15549371c9d4SSatish Balay PetscErrorCode MatISFixLocalEmpty(Mat A, PetscBool fix) { 1555f03112d0SStefano Zampini PetscFunctionBegin; 1556f03112d0SStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1557f03112d0SStefano Zampini PetscValidType(A, 1); 1558f03112d0SStefano Zampini PetscValidLogicalCollectiveBool(A, fix, 2); 1559cac4c232SBarry Smith PetscTryMethod(A, "MatISFixLocalEmpty_C", (Mat, PetscBool), (A, fix)); 1560f03112d0SStefano Zampini PetscFunctionReturn(0); 1561f03112d0SStefano Zampini } 1562f03112d0SStefano Zampini 15639371c9d4SSatish Balay static PetscErrorCode MatISFixLocalEmpty_IS(Mat A, PetscBool fix) { 1564f03112d0SStefano Zampini Mat_IS *matis = (Mat_IS *)(A->data); 1565f03112d0SStefano Zampini 1566f03112d0SStefano Zampini PetscFunctionBegin; 1567f03112d0SStefano Zampini matis->locempty = fix; 1568f03112d0SStefano Zampini PetscFunctionReturn(0); 1569f03112d0SStefano Zampini } 1570f03112d0SStefano Zampini 1571f03112d0SStefano Zampini /*@ 1572a88811baSStefano Zampini MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix. 1573a88811baSStefano Zampini 1574d083f849SBarry Smith Collective 1575a88811baSStefano Zampini 1576a88811baSStefano Zampini Input Parameters: 1577a88811baSStefano Zampini + B - the matrix 1578a88811baSStefano Zampini . d_nz - number of nonzeros per row in DIAGONAL portion of local submatrix 1579a88811baSStefano Zampini (same value is used for all local rows) 1580a88811baSStefano Zampini . d_nnz - array containing the number of nonzeros in the various rows of the 1581a88811baSStefano Zampini DIAGONAL portion of the local submatrix (possibly different for each row) 1582a88811baSStefano Zampini or NULL, if d_nz is used to specify the nonzero structure. 1583a88811baSStefano Zampini The size of this array is equal to the number of local rows, i.e 'm'. 1584a88811baSStefano Zampini For matrices that will be factored, you must leave room for (and set) 1585a88811baSStefano Zampini the diagonal entry even if it is zero. 1586a88811baSStefano Zampini . o_nz - number of nonzeros per row in the OFF-DIAGONAL portion of local 1587a88811baSStefano Zampini submatrix (same value is used for all local rows). 1588a88811baSStefano Zampini - o_nnz - array containing the number of nonzeros in the various rows of the 1589a88811baSStefano Zampini OFF-DIAGONAL portion of the local submatrix (possibly different for 1590a88811baSStefano Zampini each row) or NULL, if o_nz is used to specify the nonzero 1591a88811baSStefano Zampini structure. The size of this array is equal to the number 1592a88811baSStefano Zampini of local rows, i.e 'm'. 1593a88811baSStefano Zampini 1594a88811baSStefano Zampini If the *_nnz parameter is given then the *_nz parameter is ignored 1595a88811baSStefano Zampini 1596a88811baSStefano Zampini Level: intermediate 1597a88811baSStefano Zampini 159895452b02SPatrick Sanan Notes: 159995452b02SPatrick Sanan This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition 1600a88811baSStefano Zampini from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local 1601a88811baSStefano Zampini matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects. 1602a88811baSStefano Zampini 1603db781477SPatrick Sanan .seealso: `MatCreate()`, `MatCreateIS()`, `MatMPIAIJSetPreallocation()`, `MatISGetLocalMat()`, `MATIS` 1604a88811baSStefano Zampini @*/ 16059371c9d4SSatish Balay PetscErrorCode MatISSetPreallocation(Mat B, PetscInt d_nz, const PetscInt d_nnz[], PetscInt o_nz, const PetscInt o_nnz[]) { 16062e1947a5SStefano Zampini PetscFunctionBegin; 16072e1947a5SStefano Zampini PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 16082e1947a5SStefano Zampini PetscValidType(B, 1); 1609cac4c232SBarry Smith PetscTryMethod(B, "MatISSetPreallocation_C", (Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]), (B, d_nz, d_nnz, o_nz, o_nnz)); 16102e1947a5SStefano Zampini PetscFunctionReturn(0); 16112e1947a5SStefano Zampini } 16122e1947a5SStefano Zampini 1613844bd0d7SStefano Zampini /* this is used by DMDA */ 16149371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatISSetPreallocation_IS(Mat B, PetscInt d_nz, const PetscInt d_nnz[], PetscInt o_nz, const PetscInt o_nnz[]) { 16152e1947a5SStefano Zampini Mat_IS *matis = (Mat_IS *)(B->data); 161628f4e0baSStefano Zampini PetscInt bs, i, nlocalcols; 16172e1947a5SStefano Zampini 16182e1947a5SStefano Zampini PetscFunctionBegin; 16199566063dSJacob Faibussowitsch PetscCall(MatSetUp(B)); 16209371c9d4SSatish Balay if (!d_nnz) 16219371c9d4SSatish Balay for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] = d_nz; 16229371c9d4SSatish Balay else 16239371c9d4SSatish Balay for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] = d_nnz[i]; 16244f2d7cafSStefano Zampini 16259371c9d4SSatish Balay if (!o_nnz) 16269371c9d4SSatish Balay for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] += o_nz; 16279371c9d4SSatish Balay else 16289371c9d4SSatish Balay for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] += o_nnz[i]; 16294f2d7cafSStefano Zampini 16309566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 16319566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, NULL, &nlocalcols)); 16329566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(matis->A, &bs)); 16339566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 16344f2d7cafSStefano Zampini 16354f2d7cafSStefano Zampini for (i = 0; i < matis->sf->nleaves; i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i], nlocalcols); 16369566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(matis->A, 0, matis->sf_leafdata)); 16370f2f62c7SStefano Zampini #if defined(PETSC_HAVE_HYPRE) 16389566063dSJacob Faibussowitsch PetscCall(MatHYPRESetPreallocation(matis->A, 0, matis->sf_leafdata, 0, NULL)); 16390f2f62c7SStefano Zampini #endif 16404f2d7cafSStefano Zampini 1641fc989267SStefano Zampini for (i = 0; i < matis->sf->nleaves / bs; i++) { 1642fc989267SStefano Zampini PetscInt b; 1643fc989267SStefano Zampini 1644fc989267SStefano Zampini matis->sf_leafdata[i] = matis->sf_leafdata[i * bs] / bs; 16459371c9d4SSatish Balay for (b = 1; b < bs; b++) { matis->sf_leafdata[i] = PetscMax(matis->sf_leafdata[i], matis->sf_leafdata[i * bs + b] / bs); } 1646fc989267SStefano Zampini } 16479566063dSJacob Faibussowitsch PetscCall(MatSeqBAIJSetPreallocation(matis->A, bs, 0, matis->sf_leafdata)); 16484f2d7cafSStefano Zampini 164900a59248SStefano Zampini nlocalcols /= bs; 165000a59248SStefano Zampini for (i = 0; i < matis->sf->nleaves / bs; i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i], nlocalcols - i); 16519566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(matis->A, bs, 0, matis->sf_leafdata)); 16520f2f62c7SStefano Zampini 16530f2f62c7SStefano Zampini /* for other matrix types */ 16549566063dSJacob Faibussowitsch PetscCall(MatSetUp(matis->A)); 16552e1947a5SStefano Zampini PetscFunctionReturn(0); 16562e1947a5SStefano Zampini } 1657b4319ba4SBarry Smith 16589371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce) { 16593927de2eSStefano Zampini Mat_IS *matis = (Mat_IS *)(A->data); 16603927de2eSStefano Zampini PetscInt *my_dnz, *my_onz, *dnz, *onz, *mat_ranges, *row_ownership; 1661ecf5a873SStefano Zampini const PetscInt *global_indices_r, *global_indices_c; 16623927de2eSStefano Zampini PetscInt i, j, bs, rows, cols; 16633927de2eSStefano Zampini PetscInt lrows, lcols; 16643927de2eSStefano Zampini PetscInt local_rows, local_cols; 1665f03112d0SStefano Zampini PetscMPIInt size; 16663927de2eSStefano Zampini PetscBool isdense, issbaij; 16673927de2eSStefano Zampini 16683927de2eSStefano Zampini PetscFunctionBegin; 16699566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 16709566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &rows, &cols)); 16719566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 16729566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, &local_rows, &local_cols)); 16739566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQDENSE, &isdense)); 16749566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQSBAIJ, &issbaij)); 16759566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->rmapping, &global_indices_r)); 1676e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { 16779566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->cmapping, &global_indices_c)); 16780dfc91b7SStefano Zampini } else global_indices_c = global_indices_r; 1679ecf5a873SStefano Zampini 16809566063dSJacob Faibussowitsch if (issbaij) PetscCall(MatGetRowUpperTriangular(matis->A)); 16813927de2eSStefano Zampini /* 1682ecf5a873SStefano Zampini An SF reduce is needed to sum up properly on shared rows. 16833927de2eSStefano Zampini Note that generally preallocation is not exact, since it overestimates nonzeros 16843927de2eSStefano Zampini */ 16859566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &lrows, &lcols)); 1686d0609cedSBarry Smith MatPreallocateBegin(PetscObjectComm((PetscObject)A), lrows, lcols, dnz, onz); 16873927de2eSStefano Zampini /* All processes need to compute entire row ownership */ 16889566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rows, &row_ownership)); 16899566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRanges(A, (const PetscInt **)&mat_ranges)); 1690f03112d0SStefano Zampini for (i = 0; i < size; i++) { 16915f80ce2aSJacob Faibussowitsch for (j = mat_ranges[i]; j < mat_ranges[i + 1]; j++) row_ownership[j] = i; 16923927de2eSStefano Zampini } 16939566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangesColumn(A, (const PetscInt **)&mat_ranges)); 16943927de2eSStefano Zampini 16953927de2eSStefano Zampini /* 16963927de2eSStefano Zampini my_dnz and my_onz contains exact contribution to preallocation from each local mat 16973927de2eSStefano Zampini then, they will be summed up properly. This way, preallocation is always sufficient 16983927de2eSStefano Zampini */ 16999566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(local_rows, &my_dnz, local_rows, &my_onz)); 17003927de2eSStefano Zampini /* preallocation as a MATAIJ */ 17013927de2eSStefano Zampini if (isdense) { /* special case for dense local matrices */ 17023927de2eSStefano Zampini for (i = 0; i < local_rows; i++) { 170312dfadf8SStefano Zampini PetscInt owner = row_ownership[global_indices_r[i]]; 170412dfadf8SStefano Zampini for (j = 0; j < local_cols; j++) { 1705ecf5a873SStefano Zampini PetscInt index_col = global_indices_c[j]; 17063927de2eSStefano Zampini if (index_col > mat_ranges[owner] - 1 && index_col < mat_ranges[owner + 1]) { /* diag block */ 17073927de2eSStefano Zampini my_dnz[i] += 1; 17083927de2eSStefano Zampini } else { /* offdiag block */ 17093927de2eSStefano Zampini my_onz[i] += 1; 17103927de2eSStefano Zampini } 17113927de2eSStefano Zampini } 17123927de2eSStefano Zampini } 1713bb1015c3SStefano Zampini } else if (matis->A->ops->getrowij) { 1714bb1015c3SStefano Zampini const PetscInt *ii, *jj, *jptr; 1715bb1015c3SStefano Zampini PetscBool done; 17169566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(matis->A, 0, PETSC_FALSE, PETSC_FALSE, &local_rows, &ii, &jj, &done)); 17175f80ce2aSJacob Faibussowitsch PetscCheck(done, PetscObjectComm((PetscObject)(matis->A)), PETSC_ERR_PLIB, "Error in MatGetRowIJ"); 1718bb1015c3SStefano Zampini jptr = jj; 1719bb1015c3SStefano Zampini for (i = 0; i < local_rows; i++) { 1720bb1015c3SStefano Zampini PetscInt index_row = global_indices_r[i]; 1721bb1015c3SStefano Zampini for (j = 0; j < ii[i + 1] - ii[i]; j++, jptr++) { 1722bb1015c3SStefano Zampini PetscInt owner = row_ownership[index_row]; 1723bb1015c3SStefano Zampini PetscInt index_col = global_indices_c[*jptr]; 1724bb1015c3SStefano Zampini if (index_col > mat_ranges[owner] - 1 && index_col < mat_ranges[owner + 1]) { /* diag block */ 1725bb1015c3SStefano Zampini my_dnz[i] += 1; 1726bb1015c3SStefano Zampini } else { /* offdiag block */ 1727bb1015c3SStefano Zampini my_onz[i] += 1; 1728bb1015c3SStefano Zampini } 1729bb1015c3SStefano Zampini /* same as before, interchanging rows and cols */ 1730bb1015c3SStefano Zampini if (issbaij && index_col != index_row) { 1731bb1015c3SStefano Zampini owner = row_ownership[index_col]; 1732bb1015c3SStefano Zampini if (index_row > mat_ranges[owner] - 1 && index_row < mat_ranges[owner + 1]) { 1733bb1015c3SStefano Zampini my_dnz[*jptr] += 1; 1734bb1015c3SStefano Zampini } else { 1735bb1015c3SStefano Zampini my_onz[*jptr] += 1; 1736bb1015c3SStefano Zampini } 1737bb1015c3SStefano Zampini } 1738bb1015c3SStefano Zampini } 1739bb1015c3SStefano Zampini } 17409566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(matis->A, 0, PETSC_FALSE, PETSC_FALSE, &local_rows, &ii, &jj, &done)); 17415f80ce2aSJacob Faibussowitsch PetscCheck(done, PetscObjectComm((PetscObject)(matis->A)), PETSC_ERR_PLIB, "Error in MatRestoreRowIJ"); 1742bb1015c3SStefano Zampini } else { /* loop over rows and use MatGetRow */ 17433927de2eSStefano Zampini for (i = 0; i < local_rows; i++) { 17443927de2eSStefano Zampini const PetscInt *cols; 1745ecf5a873SStefano Zampini PetscInt ncols, index_row = global_indices_r[i]; 17469566063dSJacob Faibussowitsch PetscCall(MatGetRow(matis->A, i, &ncols, &cols, NULL)); 17473927de2eSStefano Zampini for (j = 0; j < ncols; j++) { 17483927de2eSStefano Zampini PetscInt owner = row_ownership[index_row]; 1749ecf5a873SStefano Zampini PetscInt index_col = global_indices_c[cols[j]]; 17503927de2eSStefano Zampini if (index_col > mat_ranges[owner] - 1 && index_col < mat_ranges[owner + 1]) { /* diag block */ 17513927de2eSStefano Zampini my_dnz[i] += 1; 17523927de2eSStefano Zampini } else { /* offdiag block */ 17533927de2eSStefano Zampini my_onz[i] += 1; 17543927de2eSStefano Zampini } 17553927de2eSStefano Zampini /* same as before, interchanging rows and cols */ 1756d9a9e74cSStefano Zampini if (issbaij && index_col != index_row) { 17573927de2eSStefano Zampini owner = row_ownership[index_col]; 17583927de2eSStefano Zampini if (index_row > mat_ranges[owner] - 1 && index_row < mat_ranges[owner + 1]) { 1759d9a9e74cSStefano Zampini my_dnz[cols[j]] += 1; 17603927de2eSStefano Zampini } else { 1761d9a9e74cSStefano Zampini my_onz[cols[j]] += 1; 17623927de2eSStefano Zampini } 17633927de2eSStefano Zampini } 17643927de2eSStefano Zampini } 17659566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(matis->A, i, &ncols, &cols, NULL)); 17663927de2eSStefano Zampini } 17673927de2eSStefano Zampini } 1768*48a46eb9SPierre Jolivet if (global_indices_c != global_indices_r) PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->cmapping, &global_indices_c)); 17699566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->rmapping, &global_indices_r)); 17709566063dSJacob Faibussowitsch PetscCall(PetscFree(row_ownership)); 1771ecf5a873SStefano Zampini 1772ecf5a873SStefano Zampini /* Reduce my_dnz and my_onz */ 17733927de2eSStefano Zampini if (maxreduce) { 17749566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, my_dnz, dnz, MPI_MAX)); 17759566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, my_onz, onz, MPI_MAX)); 17769566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, my_dnz, dnz, MPI_MAX)); 17779566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, my_onz, onz, MPI_MAX)); 17783927de2eSStefano Zampini } else { 17799566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, my_dnz, dnz, MPI_SUM)); 17809566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, my_onz, onz, MPI_SUM)); 17819566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, my_dnz, dnz, MPI_SUM)); 17829566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, my_onz, onz, MPI_SUM)); 17833927de2eSStefano Zampini } 17849566063dSJacob Faibussowitsch PetscCall(PetscFree2(my_dnz, my_onz)); 17853927de2eSStefano Zampini 17863927de2eSStefano Zampini /* Resize preallocation if overestimated */ 17873927de2eSStefano Zampini for (i = 0; i < lrows; i++) { 17883927de2eSStefano Zampini dnz[i] = PetscMin(dnz[i], lcols); 17893927de2eSStefano Zampini onz[i] = PetscMin(onz[i], cols - lcols); 17903927de2eSStefano Zampini } 17911670daf9Sstefano_zampini 17921670daf9Sstefano_zampini /* Set preallocation */ 17939566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B, A, A)); 17949566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B, 0, dnz)); 17959566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(B, 0, dnz, 0, onz)); 179653b44cf5SStefano Zampini for (i = 0; i < lrows; i += bs) { 179753b44cf5SStefano Zampini PetscInt b, d = dnz[i], o = onz[i]; 179853b44cf5SStefano Zampini 179953b44cf5SStefano Zampini for (b = 1; b < bs; b++) { 180053b44cf5SStefano Zampini d = PetscMax(d, dnz[i + b]); 180153b44cf5SStefano Zampini o = PetscMax(o, onz[i + b]); 180253b44cf5SStefano Zampini } 180353b44cf5SStefano Zampini dnz[i / bs] = PetscMin(d / bs + d % bs, lcols / bs); 180453b44cf5SStefano Zampini onz[i / bs] = PetscMin(o / bs + o % bs, (cols - lcols) / bs); 18053927de2eSStefano Zampini } 18069566063dSJacob Faibussowitsch PetscCall(MatSeqBAIJSetPreallocation(B, bs, 0, dnz)); 18079566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJSetPreallocation(B, bs, 0, dnz, 0, onz)); 18089566063dSJacob Faibussowitsch PetscCall(MatMPISBAIJSetPreallocation(B, bs, 0, dnz, 0, onz)); 1809d0609cedSBarry Smith MatPreallocateEnd(dnz, onz); 18109566063dSJacob Faibussowitsch if (issbaij) PetscCall(MatRestoreRowUpperTriangular(matis->A)); 18119566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 18123927de2eSStefano Zampini PetscFunctionReturn(0); 18133927de2eSStefano Zampini } 18143927de2eSStefano Zampini 18159371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatConvert_IS_XAIJ(Mat mat, MatType mtype, MatReuse reuse, Mat *M) { 1816b7ce53b6SStefano Zampini Mat_IS *matis = (Mat_IS *)(mat->data); 1817487b449aSStefano Zampini Mat local_mat, MT; 181853b44cf5SStefano Zampini PetscInt rbs, cbs, rows, cols, lrows, lcols; 1819b7ce53b6SStefano Zampini PetscInt local_rows, local_cols; 1820b9ed4604SStefano Zampini PetscBool isseqdense, isseqsbaij, isseqaij, isseqbaij; 1821f03112d0SStefano Zampini PetscMPIInt size; 18221683a169SBarry Smith const PetscScalar *array; 1823b7ce53b6SStefano Zampini 1824b7ce53b6SStefano Zampini PetscFunctionBegin; 18259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1826f03112d0SStefano Zampini if (size == 1 && mat->rmap->N == matis->A->rmap->N && mat->cmap->N == matis->A->cmap->N) { 18271670daf9Sstefano_zampini Mat B; 182853b44cf5SStefano Zampini IS irows = NULL, icols = NULL; 1829487b449aSStefano Zampini PetscInt rbs, cbs; 18301670daf9Sstefano_zampini 18319566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->rmapping, &rbs)); 18329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->cmapping, &cbs)); 183353b44cf5SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { /* check if l2g maps are one-to-one */ 183453b44cf5SStefano Zampini IS rows, cols; 183553b44cf5SStefano Zampini const PetscInt *ridxs, *cidxs; 183653b44cf5SStefano Zampini PetscInt i, nw, *work; 183753b44cf5SStefano Zampini 18389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(matis->rmapping, &ridxs)); 18399566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->rmapping, &nw)); 184053b44cf5SStefano Zampini nw = nw / rbs; 18419566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nw, &work)); 184253b44cf5SStefano Zampini for (i = 0; i < nw; i++) work[ridxs[i]] += 1; 18439371c9d4SSatish Balay for (i = 0; i < nw; i++) 18449371c9d4SSatish Balay if (!work[i] || work[i] > 1) break; 184553b44cf5SStefano Zampini if (i == nw) { 18469566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF, rbs, nw, ridxs, PETSC_USE_POINTER, &rows)); 18479566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(rows)); 18489566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(rows, PETSC_DECIDE, &irows)); 18499566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rows)); 185053b44cf5SStefano Zampini } 18519566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(matis->rmapping, &ridxs)); 18529566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 1853e432b41dSStefano Zampini if (irows && matis->rmapping != matis->cmapping) { 18549566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(matis->cmapping, &cidxs)); 18559566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->cmapping, &nw)); 185653b44cf5SStefano Zampini nw = nw / cbs; 18579566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nw, &work)); 185853b44cf5SStefano Zampini for (i = 0; i < nw; i++) work[cidxs[i]] += 1; 18599371c9d4SSatish Balay for (i = 0; i < nw; i++) 18609371c9d4SSatish Balay if (!work[i] || work[i] > 1) break; 186153b44cf5SStefano Zampini if (i == nw) { 18629566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF, cbs, nw, cidxs, PETSC_USE_POINTER, &cols)); 18639566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(cols)); 18649566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(cols, PETSC_DECIDE, &icols)); 18659566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cols)); 186653b44cf5SStefano Zampini } 18679566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(matis->cmapping, &cidxs)); 18689566063dSJacob Faibussowitsch PetscCall(PetscFree(work)); 186953b44cf5SStefano Zampini } else if (irows) { 18709566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)irows)); 187153b44cf5SStefano Zampini icols = irows; 187253b44cf5SStefano Zampini } 187353b44cf5SStefano Zampini } else { 18749566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)(*M), "_MatIS_IS_XAIJ_irows", (PetscObject *)&irows)); 18759566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)(*M), "_MatIS_IS_XAIJ_icols", (PetscObject *)&icols)); 18769566063dSJacob Faibussowitsch if (irows) PetscCall(PetscObjectReference((PetscObject)irows)); 18779566063dSJacob Faibussowitsch if (icols) PetscCall(PetscObjectReference((PetscObject)icols)); 187853b44cf5SStefano Zampini } 187953b44cf5SStefano Zampini if (!irows || !icols) { 18809566063dSJacob Faibussowitsch PetscCall(ISDestroy(&icols)); 18819566063dSJacob Faibussowitsch PetscCall(ISDestroy(&irows)); 188253b44cf5SStefano Zampini goto general_assembly; 188353b44cf5SStefano Zampini } 18849566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, mtype, MAT_INITIAL_MATRIX, &B)); 1885487b449aSStefano Zampini if (reuse != MAT_INPLACE_MATRIX) { 18869566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(B, irows, icols, reuse, M)); 18879566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)(*M), "_MatIS_IS_XAIJ_irows", (PetscObject)irows)); 18889566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)(*M), "_MatIS_IS_XAIJ_icols", (PetscObject)icols)); 1889487b449aSStefano Zampini } else { 1890487b449aSStefano Zampini Mat C; 1891487b449aSStefano Zampini 18929566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(B, irows, icols, MAT_INITIAL_MATRIX, &C)); 18939566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(mat, &C)); 1894487b449aSStefano Zampini } 18959566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 18969566063dSJacob Faibussowitsch PetscCall(ISDestroy(&icols)); 18979566063dSJacob Faibussowitsch PetscCall(ISDestroy(&irows)); 18987c03b4e8SStefano Zampini PetscFunctionReturn(0); 18997c03b4e8SStefano Zampini } 190053b44cf5SStefano Zampini general_assembly: 19019566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &rows, &cols)); 19029566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->rmapping, &rbs)); 19039566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->cmapping, &cbs)); 19049566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mat, &lrows, &lcols)); 19059566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, &local_rows, &local_cols)); 19069566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQDENSE, &isseqdense)); 19079566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQAIJ, &isseqaij)); 19089566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQBAIJ, &isseqbaij)); 19099566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQSBAIJ, &isseqsbaij)); 1910aed4548fSBarry Smith PetscCheck(isseqdense || isseqaij || isseqbaij || isseqsbaij, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)(matis->A))->type_name); 191176bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 191276bd3646SJed Brown PetscBool lb[4], bb[4]; 191376bd3646SJed Brown 1914b9ed4604SStefano Zampini lb[0] = isseqdense; 1915b9ed4604SStefano Zampini lb[1] = isseqaij; 1916b9ed4604SStefano Zampini lb[2] = isseqbaij; 1917b9ed4604SStefano Zampini lb[3] = isseqsbaij; 19181c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lb, bb, 4, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)mat))); 1919aed4548fSBarry Smith PetscCheck(bb[0] || bb[1] || bb[2] || bb[3], PETSC_COMM_SELF, PETSC_ERR_SUP, "Local matrices must have the same type"); 192076bd3646SJed Brown } 1921b7ce53b6SStefano Zampini 1922487b449aSStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 19239566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &MT)); 19249566063dSJacob Faibussowitsch PetscCall(MatSetSizes(MT, lrows, lcols, rows, cols)); 19259566063dSJacob Faibussowitsch PetscCall(MatSetType(MT, mtype)); 19269566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(MT, rbs, cbs)); 19279566063dSJacob Faibussowitsch PetscCall(MatISSetMPIXAIJPreallocation_Private(mat, MT, PETSC_FALSE)); 1928b7ce53b6SStefano Zampini } else { 192953b44cf5SStefano Zampini PetscInt mrbs, mcbs, mrows, mcols, mlrows, mlcols; 1930487b449aSStefano Zampini 1931b7ce53b6SStefano Zampini /* some checks */ 1932487b449aSStefano Zampini MT = *M; 19339566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(MT, &mrbs, &mcbs)); 19349566063dSJacob Faibussowitsch PetscCall(MatGetSize(MT, &mrows, &mcols)); 19359566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(MT, &mlrows, &mlcols)); 193608401ef6SPierre Jolivet PetscCheck(mrows == rows, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of rows (%" PetscInt_FMT " != %" PetscInt_FMT ")", rows, mrows); 193708401ef6SPierre Jolivet PetscCheck(mcols == cols, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of cols (%" PetscInt_FMT " != %" PetscInt_FMT ")", cols, mcols); 193808401ef6SPierre Jolivet PetscCheck(mlrows == lrows, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of local rows (%" PetscInt_FMT " != %" PetscInt_FMT ")", lrows, mlrows); 193908401ef6SPierre Jolivet PetscCheck(mlcols == lcols, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of local cols (%" PetscInt_FMT " != %" PetscInt_FMT ")", lcols, mlcols); 194008401ef6SPierre Jolivet PetscCheck(mrbs == rbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong row block size (%" PetscInt_FMT " != %" PetscInt_FMT ")", rbs, mrbs); 194108401ef6SPierre Jolivet PetscCheck(mcbs == cbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong col block size (%" PetscInt_FMT " != %" PetscInt_FMT ")", cbs, mcbs); 19429566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(MT)); 1943b7ce53b6SStefano Zampini } 1944d9a9e74cSStefano Zampini 19458546b261SStefano Zampini if (isseqsbaij || isseqbaij) { 19469566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &local_mat)); 19478546b261SStefano Zampini isseqaij = PETSC_TRUE; 1948d9a9e74cSStefano Zampini } else { 19499566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)matis->A)); 1950d9a9e74cSStefano Zampini local_mat = matis->A; 1951d9a9e74cSStefano Zampini } 1952686e3a49SStefano Zampini 1953b7ce53b6SStefano Zampini /* Set values */ 19549566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(MT, matis->rmapping, matis->cmapping)); 1955b9ed4604SStefano Zampini if (isseqdense) { /* special case for dense local matrices */ 195665066ba5SStefano Zampini PetscInt i, *dummy; 1957ecf5a873SStefano Zampini 19589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(PetscMax(local_rows, local_cols), &dummy)); 195965066ba5SStefano Zampini for (i = 0; i < PetscMax(local_rows, local_cols); i++) dummy[i] = i; 19609566063dSJacob Faibussowitsch PetscCall(MatSetOption(MT, MAT_ROW_ORIENTED, PETSC_FALSE)); 19619566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(local_mat, &array)); 19629566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(MT, local_rows, dummy, local_cols, dummy, array, ADD_VALUES)); 19639566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(local_mat, &array)); 19649566063dSJacob Faibussowitsch PetscCall(PetscFree(dummy)); 1965686e3a49SStefano Zampini } else if (isseqaij) { 19666afe12f5SStefano Zampini const PetscInt *blocks; 19676afe12f5SStefano Zampini PetscInt i, nvtxs, *xadj, *adjncy, nb; 1968686e3a49SStefano Zampini PetscBool done; 19691683a169SBarry Smith PetscScalar *sarray; 1970686e3a49SStefano Zampini 19719566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(local_mat, 0, PETSC_FALSE, PETSC_FALSE, &nvtxs, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &done)); 197228b400f6SJacob Faibussowitsch PetscCheck(done, PetscObjectComm((PetscObject)local_mat), PETSC_ERR_PLIB, "Error in MatGetRowIJ"); 19739566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(local_mat, &sarray)); 19749566063dSJacob Faibussowitsch PetscCall(MatGetVariableBlockSizes(local_mat, &nb, &blocks)); 19756afe12f5SStefano Zampini if (nb) { /* speed up assembly for special blocked matrices (used by BDDC) */ 19766afe12f5SStefano Zampini PetscInt sum; 19776afe12f5SStefano Zampini 19786afe12f5SStefano Zampini for (i = 0, sum = 0; i < nb; i++) sum += blocks[i]; 19796afe12f5SStefano Zampini if (sum == nvtxs) { 19806afe12f5SStefano Zampini PetscInt r; 19816afe12f5SStefano Zampini 19826afe12f5SStefano Zampini for (i = 0, r = 0; i < nb; i++) { 19836bdcaf15SBarry 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]); 19849566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(MT, blocks[i], adjncy + xadj[r], blocks[i], adjncy + xadj[r], sarray + xadj[r], ADD_VALUES)); 19856afe12f5SStefano Zampini r += blocks[i]; 19866afe12f5SStefano Zampini } 19876afe12f5SStefano Zampini } else { 1988*48a46eb9SPierre 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)); 19896afe12f5SStefano Zampini } 19906afe12f5SStefano Zampini } else { 1991*48a46eb9SPierre 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)); 19926afe12f5SStefano Zampini } 19939566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(local_mat, 0, PETSC_FALSE, PETSC_FALSE, &nvtxs, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &done)); 199428b400f6SJacob Faibussowitsch PetscCheck(done, PetscObjectComm((PetscObject)local_mat), PETSC_ERR_PLIB, "Error in MatRestoreRowIJ"); 19959566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(local_mat, &sarray)); 1996686e3a49SStefano Zampini } else { /* very basic values insertion for all other matrix types */ 1997ecf5a873SStefano Zampini PetscInt i; 1998c0962df8SStefano Zampini 1999686e3a49SStefano Zampini for (i = 0; i < local_rows; i++) { 2000686e3a49SStefano Zampini PetscInt j; 2001ecf5a873SStefano Zampini const PetscInt *local_indices_cols; 2002686e3a49SStefano Zampini 20039566063dSJacob Faibussowitsch PetscCall(MatGetRow(local_mat, i, &j, &local_indices_cols, &array)); 20049566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(MT, 1, &i, j, local_indices_cols, array, ADD_VALUES)); 20059566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(local_mat, i, &j, &local_indices_cols, &array)); 2006686e3a49SStefano Zampini } 2007b7ce53b6SStefano Zampini } 20089566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(MT, MAT_FINAL_ASSEMBLY)); 20099566063dSJacob Faibussowitsch PetscCall(MatDestroy(&local_mat)); 20109566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(MT, MAT_FINAL_ASSEMBLY)); 20111baa6e33SBarry Smith if (isseqdense) PetscCall(MatSetOption(MT, MAT_ROW_ORIENTED, PETSC_TRUE)); 2012487b449aSStefano Zampini if (reuse == MAT_INPLACE_MATRIX) { 20139566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(mat, &MT)); 2014487b449aSStefano Zampini } else if (reuse == MAT_INITIAL_MATRIX) { 2015487b449aSStefano Zampini *M = MT; 2016b7ce53b6SStefano Zampini } 2017b7ce53b6SStefano Zampini PetscFunctionReturn(0); 2018b7ce53b6SStefano Zampini } 2019b7ce53b6SStefano Zampini 2020b7ce53b6SStefano Zampini /*@ 2021b7ce53b6SStefano Zampini MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format 2022b7ce53b6SStefano Zampini 2023d8d19677SJose E. Roman Input Parameters: 2024a2b725a8SWilliam Gropp + mat - the matrix (should be of type MATIS) 2025a2b725a8SWilliam Gropp - reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 2026b7ce53b6SStefano Zampini 2027b7ce53b6SStefano Zampini Output Parameter: 2028b7ce53b6SStefano Zampini . newmat - the matrix in AIJ format 2029b7ce53b6SStefano Zampini 2030b7ce53b6SStefano Zampini Level: developer 2031b7ce53b6SStefano Zampini 203295452b02SPatrick Sanan Notes: 2033487b449aSStefano Zampini This function has been deprecated and it will be removed in future releases. Update your code to use the MatConvert() interface. 2034b7ce53b6SStefano Zampini 2035db781477SPatrick Sanan .seealso: `MATIS`, `MatConvert()` 2036b7ce53b6SStefano Zampini @*/ 20379371c9d4SSatish Balay PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat) { 2038b7ce53b6SStefano Zampini PetscFunctionBegin; 2039b7ce53b6SStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2040b7ce53b6SStefano Zampini PetscValidLogicalCollectiveEnum(mat, reuse, 2); 2041b7ce53b6SStefano Zampini PetscValidPointer(newmat, 3); 2042487b449aSStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 2043b7ce53b6SStefano Zampini PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 3); 2044b7ce53b6SStefano Zampini PetscCheckSameComm(mat, 1, *newmat, 3); 204508401ef6SPierre Jolivet PetscCheck(mat != *newmat, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse the same matrix"); 2046b7ce53b6SStefano Zampini } 2047cac4c232SBarry Smith PetscUseMethod(mat, "MatISGetMPIXAIJ_C", (Mat, MatType, MatReuse, Mat *), (mat, MATAIJ, reuse, newmat)); 2048b7ce53b6SStefano Zampini PetscFunctionReturn(0); 2049b7ce53b6SStefano Zampini } 2050b7ce53b6SStefano Zampini 20519371c9d4SSatish Balay static PetscErrorCode MatDuplicate_IS(Mat mat, MatDuplicateOption op, Mat *newmat) { 2052ad6194a2SStefano Zampini Mat_IS *matis = (Mat_IS *)(mat->data); 2053c9225affSStefano Zampini PetscInt rbs, cbs, m, n, M, N; 2054ad6194a2SStefano Zampini Mat B, localmat; 2055ad6194a2SStefano Zampini 2056ad6194a2SStefano Zampini PetscFunctionBegin; 20579566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &rbs)); 20589566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &cbs)); 20599566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &M, &N)); 20609566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mat, &m, &n)); 20619566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 20629566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, m, n, M, N)); 20639566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(B, rbs == cbs ? rbs : 1)); 20649566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATIS)); 20659566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(B, matis->lmattype)); 20669566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B, mat->rmap->mapping, mat->cmap->mapping)); 20679566063dSJacob Faibussowitsch PetscCall(MatDuplicate(matis->A, op, &localmat)); 20689566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(localmat, matis->A->rmap->mapping, matis->A->cmap->mapping)); 20699566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B, localmat)); 20709566063dSJacob Faibussowitsch PetscCall(MatDestroy(&localmat)); 20719566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 20729566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 2073ad6194a2SStefano Zampini *newmat = B; 2074ad6194a2SStefano Zampini PetscFunctionReturn(0); 2075ad6194a2SStefano Zampini } 2076ad6194a2SStefano Zampini 20779371c9d4SSatish Balay static PetscErrorCode MatIsHermitian_IS(Mat A, PetscReal tol, PetscBool *flg) { 207869796d55SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 207969796d55SStefano Zampini PetscBool local_sym; 208069796d55SStefano Zampini 208169796d55SStefano Zampini PetscFunctionBegin; 20829566063dSJacob Faibussowitsch PetscCall(MatIsHermitian(matis->A, tol, &local_sym)); 20831c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&local_sym, flg, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 208469796d55SStefano Zampini PetscFunctionReturn(0); 208569796d55SStefano Zampini } 208669796d55SStefano Zampini 20879371c9d4SSatish Balay static PetscErrorCode MatIsSymmetric_IS(Mat A, PetscReal tol, PetscBool *flg) { 208869796d55SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 208969796d55SStefano Zampini PetscBool local_sym; 209069796d55SStefano Zampini 209169796d55SStefano Zampini PetscFunctionBegin; 2092e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { 2093e432b41dSStefano Zampini *flg = PETSC_FALSE; 2094e432b41dSStefano Zampini PetscFunctionReturn(0); 2095e432b41dSStefano Zampini } 20969566063dSJacob Faibussowitsch PetscCall(MatIsSymmetric(matis->A, tol, &local_sym)); 20971c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&local_sym, flg, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 209869796d55SStefano Zampini PetscFunctionReturn(0); 209969796d55SStefano Zampini } 210069796d55SStefano Zampini 21019371c9d4SSatish Balay static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A, PetscBool *flg) { 210245471136SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 210345471136SStefano Zampini PetscBool local_sym; 210445471136SStefano Zampini 210545471136SStefano Zampini PetscFunctionBegin; 2106e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { 210745471136SStefano Zampini *flg = PETSC_FALSE; 210845471136SStefano Zampini PetscFunctionReturn(0); 210945471136SStefano Zampini } 21109566063dSJacob Faibussowitsch PetscCall(MatIsStructurallySymmetric(matis->A, &local_sym)); 21111c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&local_sym, flg, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 211245471136SStefano Zampini PetscFunctionReturn(0); 211345471136SStefano Zampini } 211445471136SStefano Zampini 21159371c9d4SSatish Balay static PetscErrorCode MatDestroy_IS(Mat A) { 2116b4319ba4SBarry Smith Mat_IS *b = (Mat_IS *)A->data; 2117b4319ba4SBarry Smith 2118b4319ba4SBarry Smith PetscFunctionBegin; 21199566063dSJacob Faibussowitsch PetscCall(PetscFree(b->bdiag)); 21209566063dSJacob Faibussowitsch PetscCall(PetscFree(b->lmattype)); 21219566063dSJacob Faibussowitsch PetscCall(MatDestroy(&b->A)); 21229566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&b->cctx)); 21239566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&b->rctx)); 21249566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->x)); 21259566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->y)); 21269566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->counter)); 21279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&b->getsub_ris)); 21289566063dSJacob Faibussowitsch PetscCall(ISDestroy(&b->getsub_cis)); 2129a8116848SStefano Zampini if (b->sf != b->csf) { 21309566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&b->csf)); 21319566063dSJacob Faibussowitsch PetscCall(PetscFree2(b->csf_rootdata, b->csf_leafdata)); 2132f03112d0SStefano Zampini } else b->csf = NULL; 21339566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&b->sf)); 21349566063dSJacob Faibussowitsch PetscCall(PetscFree2(b->sf_rootdata, b->sf_leafdata)); 21359566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&b->rmapping)); 21369566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&b->cmapping)); 2137d0dbe9f7SStefano Zampini PetscCall(MatDestroy(&b->dA)); 2138d0dbe9f7SStefano Zampini PetscCall(MatDestroy(&b->assembledA)); 21399566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 21409566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, NULL)); 21419566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMatType_C", NULL)); 21429566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalMat_C", NULL)); 21439566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMat_C", NULL)); 21442e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISRestoreLocalMat_C", NULL)); 21459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetMPIXAIJ_C", NULL)); 21469566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetPreallocation_C", NULL)); 21479566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISStoreL2L_C", NULL)); 21489566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISFixLocalEmpty_C", NULL)); 21499566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalToGlobalMapping_C", NULL)); 21509566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpiaij_C", NULL)); 21519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpibaij_C", NULL)); 21529566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpisbaij_C", NULL)); 21539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqaij_C", NULL)); 21549566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqbaij_C", NULL)); 21559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqsbaij_C", NULL)); 21569566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_aij_C", NULL)); 21579566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOOLocal_C", NULL)); 21589566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL)); 21599566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL)); 2160b4319ba4SBarry Smith PetscFunctionReturn(0); 2161b4319ba4SBarry Smith } 2162b4319ba4SBarry Smith 21639371c9d4SSatish Balay static PetscErrorCode MatMult_IS(Mat A, Vec x, Vec y) { 2164b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)A->data; 2165b4319ba4SBarry Smith PetscScalar zero = 0.0; 2166b4319ba4SBarry Smith 2167b4319ba4SBarry Smith PetscFunctionBegin; 2168b4319ba4SBarry Smith /* scatter the global vector x into the local work vector */ 21699566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->cctx, x, is->x, INSERT_VALUES, SCATTER_FORWARD)); 21709566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->cctx, x, is->x, INSERT_VALUES, SCATTER_FORWARD)); 2171b4319ba4SBarry Smith 2172b4319ba4SBarry Smith /* multiply the local matrix */ 21739566063dSJacob Faibussowitsch PetscCall(MatMult(is->A, is->x, is->y)); 2174b4319ba4SBarry Smith 2175b4319ba4SBarry Smith /* scatter product back into global memory */ 21769566063dSJacob Faibussowitsch PetscCall(VecSet(y, zero)); 21779566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, is->y, y, ADD_VALUES, SCATTER_REVERSE)); 21789566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, is->y, y, ADD_VALUES, SCATTER_REVERSE)); 2179b4319ba4SBarry Smith PetscFunctionReturn(0); 2180b4319ba4SBarry Smith } 2181b4319ba4SBarry Smith 21829371c9d4SSatish Balay static PetscErrorCode MatMultAdd_IS(Mat A, Vec v1, Vec v2, Vec v3) { 2183650997f4SStefano Zampini Vec temp_vec; 21842e74eeadSLisandro Dalcin 21852e74eeadSLisandro Dalcin PetscFunctionBegin; /* v3 = v2 + A * v1.*/ 2186650997f4SStefano Zampini if (v3 != v2) { 21879566063dSJacob Faibussowitsch PetscCall(MatMult(A, v1, v3)); 21889566063dSJacob Faibussowitsch PetscCall(VecAXPY(v3, 1.0, v2)); 2189650997f4SStefano Zampini } else { 21909566063dSJacob Faibussowitsch PetscCall(VecDuplicate(v2, &temp_vec)); 21919566063dSJacob Faibussowitsch PetscCall(MatMult(A, v1, temp_vec)); 21929566063dSJacob Faibussowitsch PetscCall(VecAXPY(temp_vec, 1.0, v2)); 21939566063dSJacob Faibussowitsch PetscCall(VecCopy(temp_vec, v3)); 21949566063dSJacob Faibussowitsch PetscCall(VecDestroy(&temp_vec)); 2195650997f4SStefano Zampini } 21962e74eeadSLisandro Dalcin PetscFunctionReturn(0); 21972e74eeadSLisandro Dalcin } 21982e74eeadSLisandro Dalcin 21999371c9d4SSatish Balay static PetscErrorCode MatMultTranspose_IS(Mat A, Vec y, Vec x) { 22002e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS *)A->data; 22012e74eeadSLisandro Dalcin 2202e176bc59SStefano Zampini PetscFunctionBegin; 22032e74eeadSLisandro Dalcin /* scatter the global vector x into the local work vector */ 22049566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, y, is->y, INSERT_VALUES, SCATTER_FORWARD)); 22059566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, y, is->y, INSERT_VALUES, SCATTER_FORWARD)); 22062e74eeadSLisandro Dalcin 22072e74eeadSLisandro Dalcin /* multiply the local matrix */ 22089566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(is->A, is->y, is->x)); 22092e74eeadSLisandro Dalcin 22102e74eeadSLisandro Dalcin /* scatter product back into global vector */ 22119566063dSJacob Faibussowitsch PetscCall(VecSet(x, 0)); 22129566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->cctx, is->x, x, ADD_VALUES, SCATTER_REVERSE)); 22139566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->cctx, is->x, x, ADD_VALUES, SCATTER_REVERSE)); 22142e74eeadSLisandro Dalcin PetscFunctionReturn(0); 22152e74eeadSLisandro Dalcin } 22162e74eeadSLisandro Dalcin 22179371c9d4SSatish Balay static PetscErrorCode MatMultTransposeAdd_IS(Mat A, Vec v1, Vec v2, Vec v3) { 2218650997f4SStefano Zampini Vec temp_vec; 22192e74eeadSLisandro Dalcin 22202e74eeadSLisandro Dalcin PetscFunctionBegin; /* v3 = v2 + A' * v1.*/ 2221650997f4SStefano Zampini if (v3 != v2) { 22229566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(A, v1, v3)); 22239566063dSJacob Faibussowitsch PetscCall(VecAXPY(v3, 1.0, v2)); 2224650997f4SStefano Zampini } else { 22259566063dSJacob Faibussowitsch PetscCall(VecDuplicate(v2, &temp_vec)); 22269566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(A, v1, temp_vec)); 22279566063dSJacob Faibussowitsch PetscCall(VecAXPY(temp_vec, 1.0, v2)); 22289566063dSJacob Faibussowitsch PetscCall(VecCopy(temp_vec, v3)); 22299566063dSJacob Faibussowitsch PetscCall(VecDestroy(&temp_vec)); 2230650997f4SStefano Zampini } 22312e74eeadSLisandro Dalcin PetscFunctionReturn(0); 22322e74eeadSLisandro Dalcin } 22332e74eeadSLisandro Dalcin 22349371c9d4SSatish Balay static PetscErrorCode MatView_IS(Mat A, PetscViewer viewer) { 2235b4319ba4SBarry Smith Mat_IS *a = (Mat_IS *)A->data; 2236b4319ba4SBarry Smith PetscViewer sviewer; 2237ee2491ecSStefano Zampini PetscBool isascii, view = PETSC_TRUE; 2238b4319ba4SBarry Smith 2239b4319ba4SBarry Smith PetscFunctionBegin; 22409566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 2241ee2491ecSStefano Zampini if (isascii) { 2242ee2491ecSStefano Zampini PetscViewerFormat format; 2243ee2491ecSStefano Zampini 22449566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2245ee2491ecSStefano Zampini if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE; 2246ee2491ecSStefano Zampini } 2247ee2491ecSStefano Zampini if (!view) PetscFunctionReturn(0); 22489566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 22499566063dSJacob Faibussowitsch PetscCall(MatView(a->A, sviewer)); 22509566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 22519566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(viewer)); 2252b4319ba4SBarry Smith PetscFunctionReturn(0); 2253b4319ba4SBarry Smith } 2254b4319ba4SBarry Smith 22559371c9d4SSatish Balay static PetscErrorCode MatInvertBlockDiagonal_IS(Mat mat, const PetscScalar **values) { 2256b89f26deSStefano Zampini Mat_IS *is = (Mat_IS *)mat->data; 2257b89f26deSStefano Zampini MPI_Datatype nodeType; 2258b89f26deSStefano Zampini const PetscScalar *lv; 2259b89f26deSStefano Zampini PetscInt bs; 2260b89f26deSStefano Zampini 2261b89f26deSStefano Zampini PetscFunctionBegin; 22629566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(mat, &bs)); 22639566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(is->A, bs)); 22649566063dSJacob Faibussowitsch PetscCall(MatInvertBlockDiagonal(is->A, &lv)); 2265*48a46eb9SPierre Jolivet if (!is->bdiag) PetscCall(PetscMalloc1(bs * mat->rmap->n, &is->bdiag)); 22669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(bs, MPIU_SCALAR, &nodeType)); 22679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&nodeType)); 22689566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(is->sf, nodeType, lv, is->bdiag, MPI_REPLACE)); 22699566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(is->sf, nodeType, lv, is->bdiag, MPI_REPLACE)); 22709566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&nodeType)); 2271b89f26deSStefano Zampini if (values) *values = is->bdiag; 2272b89f26deSStefano Zampini PetscFunctionReturn(0); 2273b89f26deSStefano Zampini } 2274b89f26deSStefano Zampini 22759371c9d4SSatish Balay static PetscErrorCode MatISSetUpScatters_Private(Mat A) { 2276e176bc59SStefano Zampini Vec cglobal, rglobal; 22778546b261SStefano Zampini IS from; 22788546b261SStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 2279b89f26deSStefano Zampini PetscScalar sum; 22808546b261SStefano Zampini const PetscInt *garray; 22818546b261SStefano Zampini PetscInt nr, rbs, nc, cbs; 2282e432b41dSStefano Zampini VecType rtype; 2283b4319ba4SBarry Smith 2284b4319ba4SBarry Smith PetscFunctionBegin; 22859566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->rmapping, &nr)); 22869566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->rmapping, &rbs)); 22879566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->cmapping, &nc)); 22889566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->cmapping, &cbs)); 22899566063dSJacob Faibussowitsch PetscCall(VecDestroy(&is->x)); 22909566063dSJacob Faibussowitsch PetscCall(VecDestroy(&is->y)); 22919566063dSJacob Faibussowitsch PetscCall(VecDestroy(&is->counter)); 22929566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&is->rctx)); 22939566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&is->cctx)); 22949566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(is->A, &is->x, &is->y)); 22959566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->y, PETSC_TRUE)); 22969566063dSJacob Faibussowitsch PetscCall(VecGetRootType_Private(is->y, &rtype)); 22979566063dSJacob Faibussowitsch PetscCall(PetscFree(A->defaultvectype)); 22989566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(rtype, &A->defaultvectype)); 22999566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, &cglobal, &rglobal)); 23009566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(rglobal, PETSC_TRUE)); 23019566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->rmapping, &garray)); 23029566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), rbs, nr / rbs, garray, PETSC_USE_POINTER, &from)); 23039566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(rglobal, from, is->y, NULL, &is->rctx)); 23049566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->rmapping, &garray)); 23059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&from)); 2306e432b41dSStefano Zampini if (is->rmapping != is->cmapping) { 23079566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->cmapping, &garray)); 23089566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), cbs, nc / cbs, garray, PETSC_USE_POINTER, &from)); 23099566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(cglobal, from, is->x, NULL, &is->cctx)); 23109566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->cmapping, &garray)); 23119566063dSJacob Faibussowitsch PetscCall(ISDestroy(&from)); 23128546b261SStefano Zampini } else { 23139566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->rctx)); 23148546b261SStefano Zampini is->cctx = is->rctx; 23158546b261SStefano Zampini } 23169566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cglobal)); 2317b89f26deSStefano Zampini 23188546b261SStefano Zampini /* interface counter vector (local) */ 23199566063dSJacob Faibussowitsch PetscCall(VecDuplicate(is->y, &is->counter)); 23209566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->counter, PETSC_TRUE)); 23219566063dSJacob Faibussowitsch PetscCall(VecSet(is->y, 1.)); 23229566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, is->y, rglobal, ADD_VALUES, SCATTER_REVERSE)); 23239566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, is->y, rglobal, ADD_VALUES, SCATTER_REVERSE)); 23249566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, rglobal, is->counter, INSERT_VALUES, SCATTER_FORWARD)); 23259566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, rglobal, is->counter, INSERT_VALUES, SCATTER_FORWARD)); 23269566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->y, PETSC_FALSE)); 23279566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->counter, PETSC_FALSE)); 2328b89f26deSStefano Zampini 2329b89f26deSStefano Zampini /* special functions for block-diagonal matrices */ 23309566063dSJacob Faibussowitsch PetscCall(VecSum(rglobal, &sum)); 2331b89f26deSStefano Zampini A->ops->invertblockdiagonal = NULL; 2332e432b41dSStefano Zampini if ((PetscInt)(PetscRealPart(sum)) == A->rmap->N && A->rmap->N == A->cmap->N && is->rmapping == is->cmapping) A->ops->invertblockdiagonal = MatInvertBlockDiagonal_IS; 23339566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rglobal)); 2334b0cc1f67SStefano Zampini 2335b0cc1f67SStefano Zampini /* setup SF for general purpose shared indices based communications */ 23369566063dSJacob Faibussowitsch PetscCall(MatISSetUpSF_IS(A)); 23378546b261SStefano Zampini PetscFunctionReturn(0); 23388546b261SStefano Zampini } 23398546b261SStefano Zampini 23409371c9d4SSatish Balay static PetscErrorCode MatISFilterL2GMap(Mat A, ISLocalToGlobalMapping map, ISLocalToGlobalMapping *nmap, ISLocalToGlobalMapping *lmap) { 2341e432b41dSStefano Zampini IS is; 2342e432b41dSStefano Zampini ISLocalToGlobalMappingType l2gtype; 2343e432b41dSStefano Zampini const PetscInt *idxs; 2344e432b41dSStefano Zampini PetscHSetI ht; 2345e432b41dSStefano Zampini PetscInt *nidxs; 2346e432b41dSStefano Zampini PetscInt i, n, bs, c; 2347e432b41dSStefano Zampini PetscBool flg[] = {PETSC_FALSE, PETSC_FALSE}; 2348e432b41dSStefano Zampini 2349e432b41dSStefano Zampini PetscFunctionBegin; 23509566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(map, &n)); 23519566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(map, &bs)); 23529566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(map, &idxs)); 23539566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&ht)); 23549566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n / bs, &nidxs)); 2355e432b41dSStefano Zampini for (i = 0, c = 0; i < n / bs; i++) { 2356e432b41dSStefano Zampini PetscBool missing; 23579371c9d4SSatish Balay if (idxs[i] < 0) { 23589371c9d4SSatish Balay flg[0] = PETSC_TRUE; 23599371c9d4SSatish Balay continue; 23609371c9d4SSatish Balay } 23619566063dSJacob Faibussowitsch PetscCall(PetscHSetIQueryAdd(ht, idxs[i], &missing)); 2362e432b41dSStefano Zampini if (!missing) flg[1] = PETSC_TRUE; 2363e432b41dSStefano Zampini else nidxs[c++] = idxs[i]; 2364e432b41dSStefano Zampini } 23659566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&ht)); 23661c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(MPI_IN_PLACE, flg, 2, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A))); 2367e432b41dSStefano Zampini if (!flg[0] && !flg[1]) { /* Entries are all non negative and unique */ 2368e432b41dSStefano Zampini *nmap = NULL; 2369e432b41dSStefano Zampini *lmap = NULL; 23709566063dSJacob Faibussowitsch PetscCall(PetscFree(nidxs)); 23719566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(map, &idxs)); 2372e432b41dSStefano Zampini PetscFunctionReturn(0); 2373e432b41dSStefano Zampini } 2374e432b41dSStefano Zampini 2375e432b41dSStefano Zampini /* New l2g map without negative or repeated indices */ 23769566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), bs, c, nidxs, PETSC_USE_POINTER, &is)); 23779566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, nmap)); 23789566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 23799566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetType(map, &l2gtype)); 23809566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(*nmap, l2gtype)); 2381e432b41dSStefano Zampini 2382e432b41dSStefano Zampini /* New local l2g map for repeated indices */ 23839566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(*nmap, IS_GTOLM_MASK, n / bs, idxs, NULL, nidxs)); 23849566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF, bs, n / bs, nidxs, PETSC_USE_POINTER, &is)); 23859566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, lmap)); 23869566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2387e432b41dSStefano Zampini 23889566063dSJacob Faibussowitsch PetscCall(PetscFree(nidxs)); 23899566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(map, &idxs)); 2390e432b41dSStefano Zampini PetscFunctionReturn(0); 2391e432b41dSStefano Zampini } 2392e432b41dSStefano Zampini 23939371c9d4SSatish Balay static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) { 23948546b261SStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 2395e432b41dSStefano Zampini ISLocalToGlobalMapping localrmapping = NULL, localcmapping = NULL; 2396e432b41dSStefano Zampini PetscBool cong, freem[] = {PETSC_FALSE, PETSC_FALSE}; 2397e432b41dSStefano Zampini PetscInt nr, rbs, nc, cbs; 23988546b261SStefano Zampini 23998546b261SStefano Zampini PetscFunctionBegin; 2400fc989267SStefano Zampini if (rmapping) PetscCheckSameComm(A, 1, rmapping, 2); 2401fc989267SStefano Zampini if (cmapping) PetscCheckSameComm(A, 1, cmapping, 3); 2402e432b41dSStefano Zampini 24039566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&is->rmapping)); 24049566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&is->cmapping)); 24059566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 24069566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 24079566063dSJacob Faibussowitsch PetscCall(MatHasCongruentLayouts(A, &cong)); 2408e432b41dSStefano Zampini 2409fc989267SStefano Zampini /* If NULL, local space matches global space */ 2410fc989267SStefano Zampini if (!rmapping) { 2411fc989267SStefano Zampini IS is; 2412fc989267SStefano Zampini 24139566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), A->rmap->N, 0, 1, &is)); 24149566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rmapping)); 24159566063dSJacob Faibussowitsch if (A->rmap->bs > 0) PetscCall(ISLocalToGlobalMappingSetBlockSize(rmapping, A->rmap->bs)); 24169566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2417e432b41dSStefano Zampini freem[0] = PETSC_TRUE; 2418e432b41dSStefano Zampini if (!cmapping && cong && A->rmap->bs == A->cmap->bs) cmapping = rmapping; 2419e432b41dSStefano Zampini } else if (!is->islocalref) { /* check if the l2g map has negative or repeated entries */ 24209566063dSJacob Faibussowitsch PetscCall(MatISFilterL2GMap(A, rmapping, &is->rmapping, &localrmapping)); 2421e432b41dSStefano Zampini if (rmapping == cmapping) { 24229566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->rmapping)); 2423e432b41dSStefano Zampini is->cmapping = is->rmapping; 24249566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)localrmapping)); 2425e432b41dSStefano Zampini localcmapping = localrmapping; 2426fc989267SStefano Zampini } 2427fc989267SStefano Zampini } 2428fc989267SStefano Zampini if (!cmapping) { 2429fc989267SStefano Zampini IS is; 2430fc989267SStefano Zampini 24319566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), A->cmap->N, 0, 1, &is)); 24329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cmapping)); 24339566063dSJacob Faibussowitsch if (A->cmap->bs > 0) PetscCall(ISLocalToGlobalMappingSetBlockSize(cmapping, A->cmap->bs)); 24349566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2435e432b41dSStefano Zampini freem[1] = PETSC_TRUE; 2436e432b41dSStefano Zampini } else if (cmapping != rmapping && !is->islocalref) { /* check if the l2g map has negative or repeated entries */ 24379566063dSJacob Faibussowitsch PetscCall(MatISFilterL2GMap(A, cmapping, &is->cmapping, &localcmapping)); 2438e432b41dSStefano Zampini } 2439e432b41dSStefano Zampini if (!is->rmapping) { 24409566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)rmapping)); 2441e432b41dSStefano Zampini is->rmapping = rmapping; 2442e432b41dSStefano Zampini } 2443e432b41dSStefano Zampini if (!is->cmapping) { 24449566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)cmapping)); 2445e432b41dSStefano Zampini is->cmapping = cmapping; 2446fc989267SStefano Zampini } 2447fc989267SStefano Zampini 2448fc989267SStefano Zampini /* Clean up */ 24499566063dSJacob Faibussowitsch PetscCall(MatDestroy(&is->A)); 2450872cf891SStefano Zampini if (is->csf != is->sf) { 24519566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&is->csf)); 24529566063dSJacob Faibussowitsch PetscCall(PetscFree2(is->csf_rootdata, is->csf_leafdata)); 2453f03112d0SStefano Zampini } else is->csf = NULL; 24549566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&is->sf)); 24559566063dSJacob Faibussowitsch PetscCall(PetscFree2(is->sf_rootdata, is->sf_leafdata)); 24569566063dSJacob Faibussowitsch PetscCall(PetscFree(is->bdiag)); 24573bbff08aSStefano Zampini 2458fc989267SStefano Zampini /* check if the two mappings are actually the same for square matrices since MATIS has some optimization for this case 2459fc989267SStefano Zampini (DOLFIN passes 2 different objects) */ 24609566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->rmapping, &nr)); 24619566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->rmapping, &rbs)); 24629566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->cmapping, &nc)); 24639566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->cmapping, &cbs)); 2464e432b41dSStefano Zampini if (is->rmapping != is->cmapping && cong) { 2465e432b41dSStefano Zampini PetscBool same = PETSC_FALSE; 24666625354bSStefano Zampini if (nr == nc && cbs == rbs) { 24676625354bSStefano Zampini const PetscInt *idxs1, *idxs2; 24686625354bSStefano Zampini 24699566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->rmapping, &idxs1)); 24709566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->cmapping, &idxs2)); 24719566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(idxs1, idxs2, nr / rbs, &same)); 24729566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->rmapping, &idxs1)); 24739566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->cmapping, &idxs2)); 24746625354bSStefano Zampini } 24751c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(MPI_IN_PLACE, &same, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 2476e432b41dSStefano Zampini if (same) { 24779566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&is->cmapping)); 24789566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->rmapping)); 2479e432b41dSStefano Zampini is->cmapping = is->rmapping; 2480e432b41dSStefano Zampini } 24816625354bSStefano Zampini } 24829566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(A->rmap, rbs)); 24839566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(A->cmap, cbs)); 2484e432b41dSStefano Zampini /* Pass the user defined maps to the layout */ 24859566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetISLocalToGlobalMapping(A->rmap, rmapping)); 24869566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetISLocalToGlobalMapping(A->cmap, cmapping)); 24879566063dSJacob Faibussowitsch if (freem[0]) PetscCall(ISLocalToGlobalMappingDestroy(&rmapping)); 24889566063dSJacob Faibussowitsch if (freem[1]) PetscCall(ISLocalToGlobalMappingDestroy(&cmapping)); 24896625354bSStefano Zampini 24906625354bSStefano Zampini /* Create the local matrix A */ 24919566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &is->A)); 24929566063dSJacob Faibussowitsch PetscCall(MatSetType(is->A, is->lmattype)); 24939566063dSJacob Faibussowitsch PetscCall(MatSetSizes(is->A, nr, nc, nr, nc)); 24949566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(is->A, rbs, cbs)); 24959566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(is->A, "is_")); 24969566063dSJacob Faibussowitsch PetscCall(MatAppendOptionsPrefix(is->A, ((PetscObject)A)->prefix)); 24979566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(is->A->rmap)); 24989566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(is->A->cmap)); 24999566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(is->A, localrmapping, localcmapping)); 25009566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&localrmapping)); 25019566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&localcmapping)); 2502b4319ba4SBarry Smith 2503fc989267SStefano Zampini /* setup scatters and local vectors for MatMult */ 25049566063dSJacob Faibussowitsch if (!is->islocalref) PetscCall(MatISSetUpScatters_Private(A)); 2505fc989267SStefano Zampini A->preallocated = PETSC_TRUE; 2506fc989267SStefano Zampini PetscFunctionReturn(0); 2507fc989267SStefano Zampini } 2508fc989267SStefano Zampini 25099371c9d4SSatish Balay static PetscErrorCode MatSetUp_IS(Mat A) { 2510fc989267SStefano Zampini ISLocalToGlobalMapping rmap, cmap; 2511fc989267SStefano Zampini 2512fc989267SStefano Zampini PetscFunctionBegin; 25139566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(A, &rmap, &cmap)); 2514*48a46eb9SPierre Jolivet if (!rmap && !cmap) PetscCall(MatSetLocalToGlobalMapping(A, NULL, NULL)); 2515b4319ba4SBarry Smith PetscFunctionReturn(0); 2516b4319ba4SBarry Smith } 2517b4319ba4SBarry Smith 25189371c9d4SSatish Balay static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) { 25192e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS *)mat->data; 2520f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION], cols_l[MATIS_MAX_ENTRIES_INSERTION]; 25212e74eeadSLisandro Dalcin 25222e74eeadSLisandro Dalcin PetscFunctionBegin; 25239566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(is->rmapping, IS_GTOLM_MASK, m, rows, &m, rows_l)); 2524e432b41dSStefano Zampini if (m != n || rows != cols || is->cmapping != is->rmapping) { 25259566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(is->cmapping, IS_GTOLM_MASK, n, cols, &n, cols_l)); 25269566063dSJacob Faibussowitsch PetscCall(MatSetValues(is->A, m, rows_l, n, cols_l, values, addv)); 2527e432b41dSStefano Zampini } else { 25289566063dSJacob Faibussowitsch PetscCall(MatSetValues(is->A, m, rows_l, m, rows_l, values, addv)); 2529e432b41dSStefano Zampini } 25302e74eeadSLisandro Dalcin PetscFunctionReturn(0); 25312e74eeadSLisandro Dalcin } 25322e74eeadSLisandro Dalcin 25339371c9d4SSatish Balay static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) { 253497563a80SStefano Zampini Mat_IS *is = (Mat_IS *)mat->data; 2535f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION], cols_l[MATIS_MAX_ENTRIES_INSERTION]; 253697563a80SStefano Zampini 253797563a80SStefano Zampini PetscFunctionBegin; 25389566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(is->rmapping, IS_GTOLM_MASK, m, rows, &m, rows_l)); 2539e432b41dSStefano Zampini if (m != n || rows != cols || is->cmapping != is->rmapping) { 25409566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(is->cmapping, IS_GTOLM_MASK, n, cols, &n, cols_l)); 25419566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked(is->A, m, rows_l, n, cols_l, values, addv)); 2542e432b41dSStefano Zampini } else { 25439566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked(is->A, m, rows_l, n, rows_l, values, addv)); 2544e432b41dSStefano Zampini } 254597563a80SStefano Zampini PetscFunctionReturn(0); 254697563a80SStefano Zampini } 254797563a80SStefano Zampini 25489371c9d4SSatish Balay static PetscErrorCode MatSetValuesLocal_IS(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) { 2549b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)A->data; 2550b4319ba4SBarry Smith 2551b4319ba4SBarry Smith PetscFunctionBegin; 2552e432b41dSStefano Zampini if (is->A->rmap->mapping || is->A->cmap->mapping) { 25539566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(is->A, m, rows, n, cols, values, addv)); 2554872cf891SStefano Zampini } else { 25559566063dSJacob Faibussowitsch PetscCall(MatSetValues(is->A, m, rows, n, cols, values, addv)); 2556872cf891SStefano Zampini } 2557b4319ba4SBarry Smith PetscFunctionReturn(0); 2558b4319ba4SBarry Smith } 2559b4319ba4SBarry Smith 25609371c9d4SSatish Balay static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) { 2561f0006bf2SLisandro Dalcin Mat_IS *is = (Mat_IS *)A->data; 2562f0006bf2SLisandro Dalcin 2563f0006bf2SLisandro Dalcin PetscFunctionBegin; 2564e432b41dSStefano Zampini if (is->A->rmap->mapping || is->A->cmap->mapping) { 25659566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlockedLocal(is->A, m, rows, n, cols, values, addv)); 2566b4f971dfSStefano Zampini } else { 25679566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked(is->A, m, rows, n, cols, values, addv)); 2568b4f971dfSStefano Zampini } 2569f0006bf2SLisandro Dalcin PetscFunctionReturn(0); 2570f0006bf2SLisandro Dalcin } 2571f0006bf2SLisandro Dalcin 25729371c9d4SSatish Balay static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, PetscBool columns) { 2573f0ae7da4SStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 2574f0ae7da4SStefano Zampini 2575f0ae7da4SStefano Zampini PetscFunctionBegin; 2576f0ae7da4SStefano Zampini if (!n) { 2577f0ae7da4SStefano Zampini is->pure_neumann = PETSC_TRUE; 2578f0ae7da4SStefano Zampini } else { 2579f0ae7da4SStefano Zampini PetscInt i; 2580f0ae7da4SStefano Zampini is->pure_neumann = PETSC_FALSE; 2581f0ae7da4SStefano Zampini 2582f0ae7da4SStefano Zampini if (columns) { 25839566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns(is->A, n, rows, diag, NULL, NULL)); 2584f0ae7da4SStefano Zampini } else { 25859566063dSJacob Faibussowitsch PetscCall(MatZeroRows(is->A, n, rows, diag, NULL, NULL)); 2586f0ae7da4SStefano Zampini } 2587f0ae7da4SStefano Zampini if (diag != 0.) { 2588f0ae7da4SStefano Zampini const PetscScalar *array; 25899566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(is->counter, &array)); 2590*48a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(MatSetValue(is->A, rows[i], rows[i], diag / (array[rows[i]]), INSERT_VALUES)); 25919566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(is->counter, &array)); 2592f0ae7da4SStefano Zampini } 25939566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(is->A, MAT_FINAL_ASSEMBLY)); 25949566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(is->A, MAT_FINAL_ASSEMBLY)); 2595f0ae7da4SStefano Zampini } 2596f0ae7da4SStefano Zampini PetscFunctionReturn(0); 2597f0ae7da4SStefano Zampini } 2598f0ae7da4SStefano Zampini 25999371c9d4SSatish Balay static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, Vec x, Vec b, PetscBool columns) { 26006e520ac8SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 26016e520ac8SStefano Zampini PetscInt nr, nl, len, i; 26026e520ac8SStefano Zampini PetscInt *lrows; 26032e74eeadSLisandro Dalcin 26042e74eeadSLisandro Dalcin PetscFunctionBegin; 2605cf9c20a2SJed Brown if (PetscUnlikelyDebug(columns || diag != 0. || (x && b))) { 2606f0ae7da4SStefano Zampini PetscBool cong; 260726b0207aSStefano Zampini 26089566063dSJacob Faibussowitsch PetscCall(PetscLayoutCompare(A->rmap, A->cmap, &cong)); 260926b0207aSStefano Zampini cong = (PetscBool)(cong && matis->sf == matis->csf); 261008401ef6SPierre 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"); 2611aed4548fSBarry 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"); 2612aed4548fSBarry 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"); 2613f0ae7da4SStefano Zampini } 26146e520ac8SStefano Zampini /* get locally owned rows */ 26159566063dSJacob Faibussowitsch PetscCall(PetscLayoutMapLocal(A->rmap, n, rows, &len, &lrows, NULL)); 26166e520ac8SStefano Zampini /* fix right hand side if needed */ 26176e520ac8SStefano Zampini if (x && b) { 26186e520ac8SStefano Zampini const PetscScalar *xx; 26196e520ac8SStefano Zampini PetscScalar *bb; 26206e520ac8SStefano Zampini 26219566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &xx)); 26229566063dSJacob Faibussowitsch PetscCall(VecGetArray(b, &bb)); 26236e520ac8SStefano Zampini for (i = 0; i < len; ++i) bb[lrows[i]] = diag * xx[lrows[i]]; 26249566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &xx)); 26259566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(b, &bb)); 26262e74eeadSLisandro Dalcin } 26276e520ac8SStefano Zampini /* get rows associated to the local matrices */ 26289566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, &nl, NULL)); 26299566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_leafdata, nl)); 26309566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata, A->rmap->n)); 26316e520ac8SStefano Zampini for (i = 0; i < len; i++) matis->sf_rootdata[lrows[i]] = 1; 26329566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 26339566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 26349566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 26359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl, &lrows)); 26369371c9d4SSatish Balay for (i = 0, nr = 0; i < nl; i++) 26379371c9d4SSatish Balay if (matis->sf_leafdata[i]) lrows[nr++] = i; 26389566063dSJacob Faibussowitsch PetscCall(MatISZeroRowsColumnsLocal_Private(A, nr, lrows, diag, columns)); 26399566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 2640d0dbe9f7SStefano Zampini PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 2641d0dbe9f7SStefano Zampini PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 26422e74eeadSLisandro Dalcin PetscFunctionReturn(0); 26432e74eeadSLisandro Dalcin } 26442e74eeadSLisandro Dalcin 26459371c9d4SSatish Balay static PetscErrorCode MatZeroRows_IS(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) { 2646b4319ba4SBarry Smith PetscFunctionBegin; 26479566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns_Private_IS(A, n, rows, diag, x, b, PETSC_FALSE)); 2648f0ae7da4SStefano Zampini PetscFunctionReturn(0); 2649f0ae7da4SStefano Zampini } 26502205254eSKarl Rupp 26519371c9d4SSatish Balay static PetscErrorCode MatZeroRowsColumns_IS(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) { 2652f0ae7da4SStefano Zampini PetscFunctionBegin; 26539566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns_Private_IS(A, n, rows, diag, x, b, PETSC_TRUE)); 2654b4319ba4SBarry Smith PetscFunctionReturn(0); 2655b4319ba4SBarry Smith } 2656b4319ba4SBarry Smith 26579371c9d4SSatish Balay static PetscErrorCode MatAssemblyBegin_IS(Mat A, MatAssemblyType type) { 2658b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)A->data; 2659b4319ba4SBarry Smith 2660b4319ba4SBarry Smith PetscFunctionBegin; 26619566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(is->A, type)); 2662b4319ba4SBarry Smith PetscFunctionReturn(0); 2663b4319ba4SBarry Smith } 2664b4319ba4SBarry Smith 26659371c9d4SSatish Balay static PetscErrorCode MatAssemblyEnd_IS(Mat A, MatAssemblyType type) { 2666b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)A->data; 2667d0dbe9f7SStefano Zampini PetscBool lnnz; 2668b4319ba4SBarry Smith 2669b4319ba4SBarry Smith PetscFunctionBegin; 26709566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(is->A, type)); 2671872cf891SStefano Zampini /* fix for local empty rows/cols */ 2672872cf891SStefano Zampini if (is->locempty && type == MAT_FINAL_ASSEMBLY) { 2673872cf891SStefano Zampini Mat newlA; 2674f03112d0SStefano Zampini ISLocalToGlobalMapping rl2g, cl2g; 2675f03112d0SStefano Zampini IS nzr, nzc; 2676f03112d0SStefano Zampini PetscInt nr, nc, nnzr, nnzc; 2677f03112d0SStefano Zampini PetscBool lnewl2g, newl2g; 2678872cf891SStefano Zampini 26799566063dSJacob Faibussowitsch PetscCall(MatGetSize(is->A, &nr, &nc)); 26809566063dSJacob Faibussowitsch PetscCall(MatFindNonzeroRowsOrCols_Basic(is->A, PETSC_FALSE, PETSC_SMALL, &nzr)); 2681*48a46eb9SPierre Jolivet if (!nzr) PetscCall(ISCreateStride(PetscObjectComm((PetscObject)is->A), nr, 0, 1, &nzr)); 26829566063dSJacob Faibussowitsch PetscCall(MatFindNonzeroRowsOrCols_Basic(is->A, PETSC_TRUE, PETSC_SMALL, &nzc)); 2683*48a46eb9SPierre Jolivet if (!nzc) PetscCall(ISCreateStride(PetscObjectComm((PetscObject)is->A), nc, 0, 1, &nzc)); 26849566063dSJacob Faibussowitsch PetscCall(ISGetSize(nzr, &nnzr)); 26859566063dSJacob Faibussowitsch PetscCall(ISGetSize(nzc, &nnzc)); 2686e432b41dSStefano Zampini if (nnzr != nr || nnzc != nc) { /* need new global l2g map */ 2687f03112d0SStefano Zampini lnewl2g = PETSC_TRUE; 26889566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&lnewl2g, &newl2g, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A))); 2689f03112d0SStefano Zampini 2690872cf891SStefano Zampini /* extract valid submatrix */ 26919566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(is->A, nzr, nzc, MAT_INITIAL_MATRIX, &newlA)); 2692f03112d0SStefano Zampini } else { /* local matrix fully populated */ 2693f03112d0SStefano Zampini lnewl2g = PETSC_FALSE; 26949566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(&lnewl2g, &newl2g, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A))); 26959566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->A)); 2696f03112d0SStefano Zampini newlA = is->A; 2697f03112d0SStefano Zampini } 2698e432b41dSStefano Zampini 2699f03112d0SStefano Zampini /* attach new global l2g map if needed */ 2700f03112d0SStefano Zampini if (newl2g) { 2701e432b41dSStefano Zampini IS zr, zc; 2702e432b41dSStefano Zampini const PetscInt *ridxs, *cidxs, *zridxs, *zcidxs; 2703e432b41dSStefano Zampini PetscInt *nidxs, i; 2704f03112d0SStefano Zampini 27059566063dSJacob Faibussowitsch PetscCall(ISComplement(nzr, 0, nr, &zr)); 27069566063dSJacob Faibussowitsch PetscCall(ISComplement(nzc, 0, nc, &zc)); 27079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(PetscMax(nr, nc), &nidxs)); 27089566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(is->rmapping, &ridxs)); 27099566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(is->cmapping, &cidxs)); 27109566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zr, &zridxs)); 27119566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zc, &zcidxs)); 27129566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zr, &nnzr)); 27139566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zc, &nnzc)); 2714e432b41dSStefano Zampini 27159566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(nidxs, ridxs, nr)); 2716e432b41dSStefano Zampini for (i = 0; i < nnzr; i++) nidxs[zridxs[i]] = -1; 27179566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A), 1, nr, nidxs, PETSC_COPY_VALUES, &rl2g)); 27189566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(nidxs, cidxs, nc)); 2719e432b41dSStefano Zampini for (i = 0; i < nnzc; i++) nidxs[zcidxs[i]] = -1; 27209566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A), 1, nc, nidxs, PETSC_COPY_VALUES, &cl2g)); 2721e432b41dSStefano Zampini 27229566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zr, &zridxs)); 27239566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zc, &zcidxs)); 27249566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(is->rmapping, &ridxs)); 27259566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(is->cmapping, &cidxs)); 27269566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzr)); 27279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzc)); 27289566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zr)); 27299566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zc)); 27309566063dSJacob Faibussowitsch PetscCall(PetscFree(nidxs)); 27319566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(A, rl2g, cl2g)); 27329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 27339566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 2734f03112d0SStefano Zampini } 27359566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(A, newlA)); 27369566063dSJacob Faibussowitsch PetscCall(MatDestroy(&newlA)); 27379566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzr)); 27389566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzc)); 2739872cf891SStefano Zampini is->locempty = PETSC_FALSE; 2740f03112d0SStefano Zampini } 2741d0dbe9f7SStefano Zampini lnnz = (PetscBool)(is->A->nonzerostate == is->lnnzstate); 2742d0dbe9f7SStefano Zampini is->lnnzstate = is->A->nonzerostate; 2743d0dbe9f7SStefano Zampini PetscCall(MPIU_Allreduce(MPI_IN_PLACE, &lnnz, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A))); 2744d0dbe9f7SStefano Zampini if (lnnz) A->nonzerostate++; 2745b4319ba4SBarry Smith PetscFunctionReturn(0); 2746b4319ba4SBarry Smith } 2747b4319ba4SBarry Smith 27489371c9d4SSatish Balay static PetscErrorCode MatISGetLocalMat_IS(Mat mat, Mat *local) { 2749b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)mat->data; 2750b4319ba4SBarry Smith 2751b4319ba4SBarry Smith PetscFunctionBegin; 2752b4319ba4SBarry Smith *local = is->A; 2753b4319ba4SBarry Smith PetscFunctionReturn(0); 2754b4319ba4SBarry Smith } 2755b4319ba4SBarry Smith 27569371c9d4SSatish Balay static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat, Mat *local) { 27573b3b1effSJed Brown PetscFunctionBegin; 27583b3b1effSJed Brown *local = NULL; 27593b3b1effSJed Brown PetscFunctionReturn(0); 27603b3b1effSJed Brown } 27613b3b1effSJed Brown 2762b4319ba4SBarry Smith /*@ 2763b4319ba4SBarry Smith MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix. 2764b4319ba4SBarry Smith 2765b4319ba4SBarry Smith Input Parameter: 2766b4319ba4SBarry Smith . mat - the matrix 2767b4319ba4SBarry Smith 2768b4319ba4SBarry Smith Output Parameter: 2769eb82efa4SStefano Zampini . local - the local matrix 2770b4319ba4SBarry Smith 2771b4319ba4SBarry Smith Level: advanced 2772b4319ba4SBarry Smith 2773b4319ba4SBarry Smith Notes: 2774b4319ba4SBarry Smith This can be called if you have precomputed the nonzero structure of the 2775b4319ba4SBarry Smith matrix and want to provide it to the inner matrix object to improve the performance 2776b4319ba4SBarry Smith of the MatSetValues() operation. 2777b4319ba4SBarry Smith 27783b3b1effSJed Brown Call MatISRestoreLocalMat() when finished with the local matrix. 277996a6f129SJed Brown 2780db781477SPatrick Sanan .seealso: `MATIS` 2781b4319ba4SBarry Smith @*/ 27829371c9d4SSatish Balay PetscErrorCode MatISGetLocalMat(Mat mat, Mat *local) { 2783b4319ba4SBarry Smith PetscFunctionBegin; 27840700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2785b4319ba4SBarry Smith PetscValidPointer(local, 2); 2786cac4c232SBarry Smith PetscUseMethod(mat, "MatISGetLocalMat_C", (Mat, Mat *), (mat, local)); 2787b4319ba4SBarry Smith PetscFunctionReturn(0); 2788b4319ba4SBarry Smith } 2789b4319ba4SBarry Smith 27903b3b1effSJed Brown /*@ 27913b3b1effSJed Brown MatISRestoreLocalMat - Restores the local matrix obtained with MatISGetLocalMat() 27923b3b1effSJed Brown 27933b3b1effSJed Brown Input Parameter: 27943b3b1effSJed Brown . mat - the matrix 27953b3b1effSJed Brown 27963b3b1effSJed Brown Output Parameter: 27973b3b1effSJed Brown . local - the local matrix 27983b3b1effSJed Brown 27993b3b1effSJed Brown Level: advanced 28003b3b1effSJed Brown 2801db781477SPatrick Sanan .seealso: `MATIS` 28023b3b1effSJed Brown @*/ 28039371c9d4SSatish Balay PetscErrorCode MatISRestoreLocalMat(Mat mat, Mat *local) { 28043b3b1effSJed Brown PetscFunctionBegin; 28053b3b1effSJed Brown PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 28063b3b1effSJed Brown PetscValidPointer(local, 2); 2807cac4c232SBarry Smith PetscUseMethod(mat, "MatISRestoreLocalMat_C", (Mat, Mat *), (mat, local)); 28083b3b1effSJed Brown PetscFunctionReturn(0); 28093b3b1effSJed Brown } 28103b3b1effSJed Brown 28119371c9d4SSatish Balay static PetscErrorCode MatISSetLocalMatType_IS(Mat mat, MatType mtype) { 28128546b261SStefano Zampini Mat_IS *is = (Mat_IS *)mat->data; 28138546b261SStefano Zampini 28148546b261SStefano Zampini PetscFunctionBegin; 28151baa6e33SBarry Smith if (is->A) PetscCall(MatSetType(is->A, mtype)); 28169566063dSJacob Faibussowitsch PetscCall(PetscFree(is->lmattype)); 28179566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(mtype, &is->lmattype)); 28188546b261SStefano Zampini PetscFunctionReturn(0); 28198546b261SStefano Zampini } 28208546b261SStefano Zampini 28218546b261SStefano Zampini /*@ 28228546b261SStefano Zampini MatISSetLocalMatType - Specifies the type of local matrix 28238546b261SStefano Zampini 2824d8d19677SJose E. Roman Input Parameters: 2825a2b725a8SWilliam Gropp + mat - the matrix 2826a2b725a8SWilliam Gropp - mtype - the local matrix type 28278546b261SStefano Zampini 28288546b261SStefano Zampini Output Parameter: 28298546b261SStefano Zampini 28308546b261SStefano Zampini Level: advanced 28318546b261SStefano Zampini 2832db781477SPatrick Sanan .seealso: `MATIS`, `MatSetType()`, `MatType` 28338546b261SStefano Zampini @*/ 28349371c9d4SSatish Balay PetscErrorCode MatISSetLocalMatType(Mat mat, MatType mtype) { 28358546b261SStefano Zampini PetscFunctionBegin; 28368546b261SStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2837cac4c232SBarry Smith PetscUseMethod(mat, "MatISSetLocalMatType_C", (Mat, MatType), (mat, mtype)); 28388546b261SStefano Zampini PetscFunctionReturn(0); 28398546b261SStefano Zampini } 28408546b261SStefano Zampini 28419371c9d4SSatish Balay static PetscErrorCode MatISSetLocalMat_IS(Mat mat, Mat local) { 28423b03a366Sstefano_zampini Mat_IS *is = (Mat_IS *)mat->data; 28433b03a366Sstefano_zampini PetscInt nrows, ncols, orows, ocols; 28448546b261SStefano Zampini MatType mtype, otype; 28458546b261SStefano Zampini PetscBool sametype = PETSC_TRUE; 28463b03a366Sstefano_zampini 28473b03a366Sstefano_zampini PetscFunctionBegin; 2848e432b41dSStefano Zampini if (is->A && !is->islocalref) { 28499566063dSJacob Faibussowitsch PetscCall(MatGetSize(is->A, &orows, &ocols)); 28509566063dSJacob Faibussowitsch PetscCall(MatGetSize(local, &nrows, &ncols)); 2851aed4548fSBarry 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); 28529566063dSJacob Faibussowitsch PetscCall(MatGetType(local, &mtype)); 28539566063dSJacob Faibussowitsch PetscCall(MatGetType(is->A, &otype)); 28549566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, otype, &sametype)); 28554e4c7dbeSStefano Zampini } 28569566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)local)); 28579566063dSJacob Faibussowitsch PetscCall(MatDestroy(&is->A)); 28583b03a366Sstefano_zampini is->A = local; 28599566063dSJacob Faibussowitsch PetscCall(MatGetType(is->A, &mtype)); 28609566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(mat, mtype)); 2861*48a46eb9SPierre Jolivet if (!sametype && !is->islocalref) PetscCall(MatISSetUpScatters_Private(mat)); 28623b03a366Sstefano_zampini PetscFunctionReturn(0); 28633b03a366Sstefano_zampini } 28643b03a366Sstefano_zampini 28653b03a366Sstefano_zampini /*@ 2866eb82efa4SStefano Zampini MatISSetLocalMat - Replace the local matrix stored inside a MATIS object. 28673b03a366Sstefano_zampini 28688546b261SStefano Zampini Collective on Mat 28698546b261SStefano Zampini 2870d8d19677SJose E. Roman Input Parameters: 2871a2b725a8SWilliam Gropp + mat - the matrix 2872a2b725a8SWilliam Gropp - local - the local matrix 28733b03a366Sstefano_zampini 28743b03a366Sstefano_zampini Output Parameter: 28753b03a366Sstefano_zampini 28763b03a366Sstefano_zampini Level: advanced 28773b03a366Sstefano_zampini 28783b03a366Sstefano_zampini Notes: 28793b03a366Sstefano_zampini This can be called if you have precomputed the local matrix and 28803b03a366Sstefano_zampini want to provide it to the matrix object MATIS. 28813b03a366Sstefano_zampini 2882db781477SPatrick Sanan .seealso: `MATIS` 28833b03a366Sstefano_zampini @*/ 28849371c9d4SSatish Balay PetscErrorCode MatISSetLocalMat(Mat mat, Mat local) { 28853b03a366Sstefano_zampini PetscFunctionBegin; 28863b03a366Sstefano_zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2887b7ce53b6SStefano Zampini PetscValidHeaderSpecific(local, MAT_CLASSID, 2); 2888cac4c232SBarry Smith PetscUseMethod(mat, "MatISSetLocalMat_C", (Mat, Mat), (mat, local)); 28893b03a366Sstefano_zampini PetscFunctionReturn(0); 28903b03a366Sstefano_zampini } 28913b03a366Sstefano_zampini 28929371c9d4SSatish Balay static PetscErrorCode MatZeroEntries_IS(Mat A) { 28936726f965SBarry Smith Mat_IS *a = (Mat_IS *)A->data; 28946726f965SBarry Smith 28956726f965SBarry Smith PetscFunctionBegin; 28969566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(a->A)); 28976726f965SBarry Smith PetscFunctionReturn(0); 28986726f965SBarry Smith } 28996726f965SBarry Smith 29009371c9d4SSatish Balay static PetscErrorCode MatScale_IS(Mat A, PetscScalar a) { 29012e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS *)A->data; 29022e74eeadSLisandro Dalcin 29032e74eeadSLisandro Dalcin PetscFunctionBegin; 29049566063dSJacob Faibussowitsch PetscCall(MatScale(is->A, a)); 29052e74eeadSLisandro Dalcin PetscFunctionReturn(0); 29062e74eeadSLisandro Dalcin } 29072e74eeadSLisandro Dalcin 29089371c9d4SSatish Balay static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v) { 29092e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS *)A->data; 29102e74eeadSLisandro Dalcin 29112e74eeadSLisandro Dalcin PetscFunctionBegin; 29122e74eeadSLisandro Dalcin /* get diagonal of the local matrix */ 29139566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(is->A, is->y)); 29142e74eeadSLisandro Dalcin 29152e74eeadSLisandro Dalcin /* scatter diagonal back into global vector */ 29169566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0)); 29179566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, is->y, v, ADD_VALUES, SCATTER_REVERSE)); 29189566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, is->y, v, ADD_VALUES, SCATTER_REVERSE)); 29192e74eeadSLisandro Dalcin PetscFunctionReturn(0); 29202e74eeadSLisandro Dalcin } 29212e74eeadSLisandro Dalcin 29229371c9d4SSatish Balay static PetscErrorCode MatSetOption_IS(Mat A, MatOption op, PetscBool flg) { 29236726f965SBarry Smith Mat_IS *a = (Mat_IS *)A->data; 29246726f965SBarry Smith 29256726f965SBarry Smith PetscFunctionBegin; 29269566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg)); 29276726f965SBarry Smith PetscFunctionReturn(0); 29286726f965SBarry Smith } 29296726f965SBarry Smith 29309371c9d4SSatish Balay static PetscErrorCode MatAXPY_IS(Mat Y, PetscScalar a, Mat X, MatStructure str) { 2931f26d0771SStefano Zampini Mat_IS *y = (Mat_IS *)Y->data; 2932f26d0771SStefano Zampini Mat_IS *x; 2933f26d0771SStefano Zampini 2934f26d0771SStefano Zampini PetscFunctionBegin; 293576bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 293676bd3646SJed Brown PetscBool ismatis; 29379566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)X, MATIS, &ismatis)); 293828b400f6SJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)Y), PETSC_ERR_SUP, "Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS"); 293976bd3646SJed Brown } 2940f26d0771SStefano Zampini x = (Mat_IS *)X->data; 29419566063dSJacob Faibussowitsch PetscCall(MatAXPY(y->A, a, x->A, str)); 2942f26d0771SStefano Zampini PetscFunctionReturn(0); 2943f26d0771SStefano Zampini } 2944f26d0771SStefano Zampini 29459371c9d4SSatish Balay static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A, IS row, IS col, Mat *submat) { 2946f26d0771SStefano Zampini Mat lA; 2947e432b41dSStefano Zampini Mat_IS *matis = (Mat_IS *)(A->data); 2948f26d0771SStefano Zampini ISLocalToGlobalMapping rl2g, cl2g; 2949f26d0771SStefano Zampini IS is; 2950f26d0771SStefano Zampini const PetscInt *rg, *rl; 2951f26d0771SStefano Zampini PetscInt nrg; 2952f26d0771SStefano Zampini PetscInt N, M, nrl, i, *idxs; 2953f26d0771SStefano Zampini 2954f26d0771SStefano Zampini PetscFunctionBegin; 29559566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(A->rmap->mapping, &rg)); 29569566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(row, &nrl)); 29579566063dSJacob Faibussowitsch PetscCall(ISGetIndices(row, &rl)); 29589566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(A->rmap->mapping, &nrg)); 295976bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 296008401ef6SPierre 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); 296176bd3646SJed Brown } 29629566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nrg, &idxs)); 2963f26d0771SStefano Zampini /* map from [0,nrl) to row */ 2964f26d0771SStefano Zampini for (i = 0; i < nrl; i++) idxs[i] = rl[i]; 2965f26d0771SStefano Zampini for (i = nrl; i < nrg; i++) idxs[i] = -1; 29669566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(row, &rl)); 29679566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping, &rg)); 29689566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A), nrg, idxs, PETSC_OWN_POINTER, &is)); 29699566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g)); 29709566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2971f26d0771SStefano Zampini /* compute new l2g map for columns */ 2972e432b41dSStefano Zampini if (col != row || matis->rmapping != matis->cmapping || matis->A->rmap->mapping != matis->A->cmap->mapping) { 2973f26d0771SStefano Zampini const PetscInt *cg, *cl; 2974f26d0771SStefano Zampini PetscInt ncg; 2975f26d0771SStefano Zampini PetscInt ncl; 2976f26d0771SStefano Zampini 29779566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(A->cmap->mapping, &cg)); 29789566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(col, &ncl)); 29799566063dSJacob Faibussowitsch PetscCall(ISGetIndices(col, &cl)); 29809566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(A->cmap->mapping, &ncg)); 298176bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 298208401ef6SPierre 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); 298376bd3646SJed Brown } 29849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncg, &idxs)); 2985f26d0771SStefano Zampini /* map from [0,ncl) to col */ 2986f26d0771SStefano Zampini for (i = 0; i < ncl; i++) idxs[i] = cl[i]; 2987f26d0771SStefano Zampini for (i = ncl; i < ncg; i++) idxs[i] = -1; 29889566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(col, &cl)); 29899566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping, &cg)); 29909566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A), ncg, idxs, PETSC_OWN_POINTER, &is)); 29919566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g)); 29929566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2993f26d0771SStefano Zampini } else { 29949566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)rl2g)); 2995f26d0771SStefano Zampini cl2g = rl2g; 2996f26d0771SStefano Zampini } 2997f26d0771SStefano Zampini /* create the MATIS submatrix */ 29989566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, &N)); 29999566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), submat)); 30009566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*submat, PETSC_DECIDE, PETSC_DECIDE, M, N)); 30019566063dSJacob Faibussowitsch PetscCall(MatSetType(*submat, MATIS)); 3002b0aa3428SStefano Zampini matis = (Mat_IS *)((*submat)->data); 3003f26d0771SStefano Zampini matis->islocalref = PETSC_TRUE; 30049566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*submat, rl2g, cl2g)); 30059566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A, &lA)); 30069566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*submat, lA)); 30079566063dSJacob Faibussowitsch PetscCall(MatSetUp(*submat)); 30089566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*submat, MAT_FINAL_ASSEMBLY)); 30099566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*submat, MAT_FINAL_ASSEMBLY)); 30109566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 30119566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 3012e432b41dSStefano Zampini 3013f26d0771SStefano Zampini /* remove unsupported ops */ 30149566063dSJacob Faibussowitsch PetscCall(PetscMemzero((*submat)->ops, sizeof(struct _MatOps))); 3015f26d0771SStefano Zampini (*submat)->ops->destroy = MatDestroy_IS; 3016f26d0771SStefano Zampini (*submat)->ops->setvalueslocal = MatSetValuesLocal_SubMat_IS; 3017f26d0771SStefano Zampini (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS; 3018f26d0771SStefano Zampini (*submat)->ops->assemblybegin = MatAssemblyBegin_IS; 3019f26d0771SStefano Zampini (*submat)->ops->assemblyend = MatAssemblyEnd_IS; 3020f26d0771SStefano Zampini PetscFunctionReturn(0); 3021f26d0771SStefano Zampini } 3022f26d0771SStefano Zampini 30239371c9d4SSatish Balay static PetscErrorCode MatSetFromOptions_IS(Mat A, PetscOptionItems *PetscOptionsObject) { 3024872cf891SStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 30258546b261SStefano Zampini char type[256]; 30268546b261SStefano Zampini PetscBool flg; 3027872cf891SStefano Zampini 3028872cf891SStefano Zampini PetscFunctionBegin; 3029d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "MATIS options"); 3030d0dbe9f7SStefano Zampini PetscCall(PetscOptionsBool("-matis_keepassembled", "Store an assembled version if needed", "MatISKeepAssembled", a->keepassembled, &a->keepassembled, NULL)); 30319566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-matis_fixempty", "Fix local matrices in case of empty local rows/columns", "MatISFixLocalEmpty", a->locempty, &a->locempty, NULL)); 30329566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-matis_storel2l", "Store local-to-local matrices generated from PtAP operations", "MatISStoreL2L", a->storel2l, &a->storel2l, NULL)); 30339566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-matis_localmat_type", "Matrix type", "MatISSetLocalMatType", MatList, a->lmattype, type, 256, &flg)); 30341baa6e33SBarry Smith if (flg) PetscCall(MatISSetLocalMatType(A, type)); 30351baa6e33SBarry Smith if (a->A) PetscCall(MatSetFromOptions(a->A)); 3036d0609cedSBarry Smith PetscOptionsHeadEnd(); 3037872cf891SStefano Zampini PetscFunctionReturn(0); 3038872cf891SStefano Zampini } 3039872cf891SStefano Zampini 3040284134d9SBarry Smith /*@ 30413c212e90SHong Zhang MatCreateIS - Creates a "process" unassembled matrix, assembled on each 3042284134d9SBarry Smith process but not across processes. 3043284134d9SBarry Smith 3044284134d9SBarry Smith Input Parameters: 3045284134d9SBarry Smith + comm - MPI communicator that will share the matrix 3046e176bc59SStefano Zampini . bs - block size of the matrix 3047df3898eeSBarry Smith . m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products 3048e176bc59SStefano Zampini . rmap - local to global map for rows 3049e176bc59SStefano Zampini - cmap - local to global map for cols 3050284134d9SBarry Smith 3051284134d9SBarry Smith Output Parameter: 3052284134d9SBarry Smith . A - the resulting matrix 3053284134d9SBarry Smith 30548e6c10adSSatish Balay Level: advanced 30558e6c10adSSatish Balay 305695452b02SPatrick Sanan Notes: 305795452b02SPatrick Sanan See MATIS for more details. 3058fc989267SStefano 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 30596fdf41d1SStefano Zampini used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices. 3060fc989267SStefano Zampini If rmap (cmap) is NULL, then the local row (column) spaces matches the global space. 3061284134d9SBarry Smith 3062db781477SPatrick Sanan .seealso: `MATIS`, `MatSetLocalToGlobalMapping()` 3063284134d9SBarry Smith @*/ 30649371c9d4SSatish Balay PetscErrorCode MatCreateIS(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt M, PetscInt N, ISLocalToGlobalMapping rmap, ISLocalToGlobalMapping cmap, Mat *A) { 3065284134d9SBarry Smith PetscFunctionBegin; 30669566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, A)); 30679566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A, m, n, M, N)); 3068*48a46eb9SPierre Jolivet if (bs > 0) PetscCall(MatSetBlockSize(*A, bs)); 30699566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATIS)); 30709566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*A, rmap, cmap)); 3071284134d9SBarry Smith PetscFunctionReturn(0); 3072284134d9SBarry Smith } 3073284134d9SBarry Smith 30749371c9d4SSatish Balay static PetscErrorCode MatHasOperation_IS(Mat A, MatOperation op, PetscBool *has) { 30758b9382cfSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3076e26763e4SStefano Zampini MatOperation tobefiltered[] = {MATOP_MULT_ADD, MATOP_MULT_TRANSPOSE_ADD, MATOP_GET_DIAGONAL_BLOCK, MATOP_INCREASE_OVERLAP}; 30778b9382cfSStefano Zampini 30788b9382cfSStefano Zampini PetscFunctionBegin; 30798b9382cfSStefano Zampini *has = PETSC_FALSE; 3080e26763e4SStefano Zampini if (!((void **)A->ops)[op] || !a->A) PetscFunctionReturn(0); 3081d0dbe9f7SStefano Zampini *has = PETSC_TRUE; 30829371c9d4SSatish Balay for (PetscInt i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(tobefiltered); i++) 30839371c9d4SSatish Balay if (op == tobefiltered[i]) PetscFunctionReturn(0); 30849566063dSJacob Faibussowitsch PetscCall(MatHasOperation(a->A, op, has)); 30858b9382cfSStefano Zampini PetscFunctionReturn(0); 30868b9382cfSStefano Zampini } 30878b9382cfSStefano Zampini 30889371c9d4SSatish Balay static PetscErrorCode MatSetValuesCOO_IS(Mat A, const PetscScalar v[], InsertMode imode) { 3089e432b41dSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3090e432b41dSStefano Zampini 3091e432b41dSStefano Zampini PetscFunctionBegin; 30929566063dSJacob Faibussowitsch PetscCall(MatSetValuesCOO(a->A, v, imode)); 30939566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 30949566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 3095e432b41dSStefano Zampini PetscFunctionReturn(0); 3096e432b41dSStefano Zampini } 3097e432b41dSStefano Zampini 30989371c9d4SSatish Balay static PetscErrorCode MatSetPreallocationCOOLocal_IS(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[]) { 3099e432b41dSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3100e432b41dSStefano Zampini 3101e432b41dSStefano Zampini PetscFunctionBegin; 3102e432b41dSStefano Zampini PetscCheck(a->A, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Need to provide l2g map first via MatSetLocalToGlobalMapping"); 3103e432b41dSStefano Zampini if (a->A->rmap->mapping || a->A->cmap->mapping) { 31049566063dSJacob Faibussowitsch PetscCall(MatSetPreallocationCOOLocal(a->A, ncoo, coo_i, coo_j)); 3105e432b41dSStefano Zampini } else { 31069566063dSJacob Faibussowitsch PetscCall(MatSetPreallocationCOO(a->A, ncoo, coo_i, coo_j)); 3107e432b41dSStefano Zampini } 31089566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", MatSetValuesCOO_IS)); 3109e432b41dSStefano Zampini A->preallocated = PETSC_TRUE; 3110e432b41dSStefano Zampini PetscFunctionReturn(0); 3111e432b41dSStefano Zampini } 3112e432b41dSStefano Zampini 31139371c9d4SSatish Balay static PetscErrorCode MatSetPreallocationCOO_IS(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[]) { 3114e432b41dSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3115e432b41dSStefano Zampini 3116e432b41dSStefano Zampini PetscFunctionBegin; 3117e432b41dSStefano Zampini PetscCheck(a->A, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Need to provide l2g map first via MatSetLocalToGlobalMapping"); 3118e432b41dSStefano 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); 3119e8729f6fSJunchao Zhang PetscCall(ISGlobalToLocalMappingApply(a->rmapping, IS_GTOLM_MASK, ncoo, coo_i, NULL, coo_i)); 3120e8729f6fSJunchao Zhang PetscCall(ISGlobalToLocalMappingApply(a->cmapping, IS_GTOLM_MASK, ncoo, coo_j, NULL, coo_j)); 3121e8729f6fSJunchao Zhang PetscCall(MatSetPreallocationCOO(a->A, ncoo, coo_i, coo_j)); 31229566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", MatSetValuesCOO_IS)); 3123e432b41dSStefano Zampini A->preallocated = PETSC_TRUE; 3124e432b41dSStefano Zampini PetscFunctionReturn(0); 3125e432b41dSStefano Zampini } 3126e432b41dSStefano Zampini 31279371c9d4SSatish Balay static PetscErrorCode MatISGetAssembled_Private(Mat A, Mat *tA) { 3128d0dbe9f7SStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3129d0dbe9f7SStefano Zampini PetscObjectState Astate, aAstate = PETSC_MIN_INT; 3130d0dbe9f7SStefano Zampini PetscObjectState Annzstate, aAnnzstate = PETSC_MIN_INT; 3131d0dbe9f7SStefano Zampini 3132d0dbe9f7SStefano Zampini PetscFunctionBegin; 3133d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateGet((PetscObject)A, &Astate)); 3134d0dbe9f7SStefano Zampini Annzstate = A->nonzerostate; 3135d0dbe9f7SStefano Zampini if (a->assembledA) { 3136d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateGet((PetscObject)a->assembledA, &aAstate)); 3137d0dbe9f7SStefano Zampini aAnnzstate = a->assembledA->nonzerostate; 3138d0dbe9f7SStefano Zampini } 3139d0dbe9f7SStefano Zampini if (aAnnzstate != Annzstate) PetscCall(MatDestroy(&a->assembledA)); 3140d0dbe9f7SStefano Zampini if (Astate != aAstate || !a->assembledA) { 3141d0dbe9f7SStefano Zampini MatType aAtype; 3142d0dbe9f7SStefano Zampini PetscMPIInt size; 3143d0dbe9f7SStefano Zampini PetscInt rbs, cbs, bs; 3144d0dbe9f7SStefano Zampini 3145d0dbe9f7SStefano Zampini /* the assembled form is used as temporary storage for parallel operations 3146d0dbe9f7SStefano Zampini like createsubmatrices and the like, do not waste device memory */ 3147d0dbe9f7SStefano Zampini PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 3148d0dbe9f7SStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockSize(a->cmapping, &cbs)); 3149d0dbe9f7SStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockSize(a->rmapping, &rbs)); 3150d0dbe9f7SStefano Zampini bs = rbs == cbs ? rbs : 1; 3151d0dbe9f7SStefano Zampini if (a->assembledA) PetscCall(MatGetType(a->assembledA, &aAtype)); 3152d0dbe9f7SStefano Zampini else if (size > 1) aAtype = bs > 1 ? MATMPIBAIJ : MATMPIAIJ; 3153d0dbe9f7SStefano Zampini else aAtype = bs > 1 ? MATSEQBAIJ : MATSEQAIJ; 3154d0dbe9f7SStefano Zampini 3155d0dbe9f7SStefano Zampini PetscCall(MatConvert(A, aAtype, a->assembledA ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX, &a->assembledA)); 3156d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateSet((PetscObject)a->assembledA, Astate)); 3157d0dbe9f7SStefano Zampini a->assembledA->nonzerostate = Annzstate; 3158d0dbe9f7SStefano Zampini } 3159d0dbe9f7SStefano Zampini PetscCall(PetscObjectReference((PetscObject)a->assembledA)); 3160d0dbe9f7SStefano Zampini *tA = a->assembledA; 3161d0dbe9f7SStefano Zampini if (!a->keepassembled) PetscCall(MatDestroy(&a->assembledA)); 3162d0dbe9f7SStefano Zampini PetscFunctionReturn(0); 3163d0dbe9f7SStefano Zampini } 3164d0dbe9f7SStefano Zampini 31659371c9d4SSatish Balay static PetscErrorCode MatISRestoreAssembled_Private(Mat A, Mat *tA) { 3166d0dbe9f7SStefano Zampini PetscFunctionBegin; 3167d0dbe9f7SStefano Zampini PetscCall(MatDestroy(tA)); 3168d0dbe9f7SStefano Zampini *tA = NULL; 3169d0dbe9f7SStefano Zampini PetscFunctionReturn(0); 3170d0dbe9f7SStefano Zampini } 3171d0dbe9f7SStefano Zampini 31729371c9d4SSatish Balay static PetscErrorCode MatGetDiagonalBlock_IS(Mat A, Mat *dA) { 3173d0dbe9f7SStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3174d0dbe9f7SStefano Zampini PetscObjectState Astate, dAstate = PETSC_MIN_INT; 3175d0dbe9f7SStefano Zampini 3176d0dbe9f7SStefano Zampini PetscFunctionBegin; 3177d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateGet((PetscObject)A, &Astate)); 3178d0dbe9f7SStefano Zampini if (a->dA) PetscCall(PetscObjectStateGet((PetscObject)a->dA, &dAstate)); 3179d0dbe9f7SStefano Zampini if (Astate != dAstate) { 3180d0dbe9f7SStefano Zampini Mat tA; 3181d0dbe9f7SStefano Zampini MatType ltype; 3182d0dbe9f7SStefano Zampini 3183d0dbe9f7SStefano Zampini PetscCall(MatDestroy(&a->dA)); 3184d0dbe9f7SStefano Zampini PetscCall(MatISGetAssembled_Private(A, &tA)); 3185d0dbe9f7SStefano Zampini PetscCall(MatGetDiagonalBlock(tA, &a->dA)); 3186d0dbe9f7SStefano Zampini PetscCall(MatPropagateSymmetryOptions(tA, a->dA)); 3187d0dbe9f7SStefano Zampini PetscCall(MatGetType(a->A, <ype)); 3188d0dbe9f7SStefano Zampini PetscCall(MatConvert(a->dA, ltype, MAT_INPLACE_MATRIX, &a->dA)); 3189d0dbe9f7SStefano Zampini PetscCall(PetscObjectReference((PetscObject)a->dA)); 3190d0dbe9f7SStefano Zampini PetscCall(MatISRestoreAssembled_Private(A, &tA)); 3191d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateSet((PetscObject)a->dA, Astate)); 3192d0dbe9f7SStefano Zampini } 3193d0dbe9f7SStefano Zampini *dA = a->dA; 3194d0dbe9f7SStefano Zampini PetscFunctionReturn(0); 3195d0dbe9f7SStefano Zampini } 3196d0dbe9f7SStefano Zampini 31979371c9d4SSatish Balay static PetscErrorCode MatCreateSubMatrices_IS(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse reuse, Mat *submat[]) { 3198d0dbe9f7SStefano Zampini Mat tA; 3199d0dbe9f7SStefano Zampini 3200d0dbe9f7SStefano Zampini PetscFunctionBegin; 3201d0dbe9f7SStefano Zampini PetscCall(MatISGetAssembled_Private(A, &tA)); 3202d0dbe9f7SStefano Zampini PetscCall(MatCreateSubMatrices(tA, n, irow, icol, reuse, submat)); 3203d0dbe9f7SStefano Zampini /* MatCreateSubMatrices_MPIAIJ is a mess at the moment */ 3204d0dbe9f7SStefano Zampini #if 0 3205d0dbe9f7SStefano Zampini { 3206d0dbe9f7SStefano Zampini Mat_IS *a = (Mat_IS*)A->data; 3207d0dbe9f7SStefano Zampini MatType ltype; 3208d0dbe9f7SStefano Zampini VecType vtype; 3209d0dbe9f7SStefano Zampini char *flg; 3210d0dbe9f7SStefano Zampini 3211d0dbe9f7SStefano Zampini PetscCall(MatGetType(a->A,<ype)); 3212d0dbe9f7SStefano Zampini PetscCall(MatGetVecType(a->A,&vtype)); 3213d0dbe9f7SStefano Zampini PetscCall(PetscStrstr(vtype,"cuda",&flg)); 3214d0dbe9f7SStefano Zampini if (!flg) PetscCall(PetscStrstr(vtype,"hip",&flg)); 3215d0dbe9f7SStefano Zampini if (!flg) PetscCall(PetscStrstr(vtype,"kokkos",&flg)); 3216d0dbe9f7SStefano Zampini if (flg) { 3217d0dbe9f7SStefano Zampini for (PetscInt i = 0; i < n; i++) { 3218d0dbe9f7SStefano Zampini Mat sA = (*submat)[i]; 3219d0dbe9f7SStefano Zampini 3220d0dbe9f7SStefano Zampini PetscCall(MatConvert(sA,ltype,MAT_INPLACE_MATRIX,&sA)); 3221d0dbe9f7SStefano Zampini (*submat)[i] = sA; 3222d0dbe9f7SStefano Zampini } 3223d0dbe9f7SStefano Zampini } 3224d0dbe9f7SStefano Zampini } 3225d0dbe9f7SStefano Zampini #endif 3226d0dbe9f7SStefano Zampini PetscCall(MatISRestoreAssembled_Private(A, &tA)); 3227d0dbe9f7SStefano Zampini PetscFunctionReturn(0); 3228d0dbe9f7SStefano Zampini } 3229d0dbe9f7SStefano Zampini 32309371c9d4SSatish Balay static PetscErrorCode MatIncreaseOverlap_IS(Mat A, PetscInt n, IS is[], PetscInt ov) { 3231d0dbe9f7SStefano Zampini Mat tA; 3232d0dbe9f7SStefano Zampini 3233d0dbe9f7SStefano Zampini PetscFunctionBegin; 3234d0dbe9f7SStefano Zampini PetscCall(MatISGetAssembled_Private(A, &tA)); 3235d0dbe9f7SStefano Zampini PetscCall(MatIncreaseOverlap(tA, n, is, ov)); 3236d0dbe9f7SStefano Zampini PetscCall(MatISRestoreAssembled_Private(A, &tA)); 3237d0dbe9f7SStefano Zampini PetscFunctionReturn(0); 3238d0dbe9f7SStefano Zampini } 3239d0dbe9f7SStefano Zampini 3240e432b41dSStefano Zampini /*@ 3241e432b41dSStefano Zampini MatISGetLocalToGlobalMapping - Gets the local-to-global numbering of the MATIS object 3242e432b41dSStefano Zampini 3243e432b41dSStefano Zampini Not Collective 3244e432b41dSStefano Zampini 3245e432b41dSStefano Zampini Input Parameter: 3246e432b41dSStefano Zampini . A - the matrix 3247e432b41dSStefano Zampini 3248e432b41dSStefano Zampini Output Parameters: 3249e432b41dSStefano Zampini + rmapping - row mapping 3250e432b41dSStefano Zampini - cmapping - column mapping 3251e432b41dSStefano Zampini 3252e432b41dSStefano Zampini Notes: The returned map can be different from the one used to construct the MATIS object, since it will not contain negative or repeated indices. 3253e432b41dSStefano Zampini 3254e432b41dSStefano Zampini Level: advanced 3255e432b41dSStefano Zampini 3256db781477SPatrick Sanan .seealso: `MatSetLocalToGlobalMapping()` 3257e432b41dSStefano Zampini @*/ 32589371c9d4SSatish Balay PetscErrorCode MatISGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) { 3259e432b41dSStefano Zampini PetscFunctionBegin; 3260e432b41dSStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3261e432b41dSStefano Zampini PetscValidType(A, 1); 3262e432b41dSStefano Zampini if (rmapping) PetscValidPointer(rmapping, 2); 3263e432b41dSStefano Zampini if (cmapping) PetscValidPointer(cmapping, 3); 3264cac4c232SBarry Smith PetscUseMethod(A, "MatISGetLocalToGlobalMapping_C", (Mat, ISLocalToGlobalMapping *, ISLocalToGlobalMapping *), (A, rmapping, cmapping)); 3265e432b41dSStefano Zampini PetscFunctionReturn(0); 3266e432b41dSStefano Zampini } 3267e432b41dSStefano Zampini 32689371c9d4SSatish Balay static PetscErrorCode MatISGetLocalToGlobalMapping_IS(Mat A, ISLocalToGlobalMapping *r, ISLocalToGlobalMapping *c) { 3269e432b41dSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3270e432b41dSStefano Zampini 3271e432b41dSStefano Zampini PetscFunctionBegin; 3272e432b41dSStefano Zampini if (r) *r = a->rmapping; 3273e432b41dSStefano Zampini if (c) *c = a->cmapping; 3274e432b41dSStefano Zampini PetscFunctionReturn(0); 3275e432b41dSStefano Zampini } 3276e432b41dSStefano Zampini 3277b4319ba4SBarry Smith /*MC 3278f26d0771SStefano Zampini MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP). 3279b89f26deSStefano Zampini This stores the matrices in globally unassembled form. Each processor assembles only its local Neumann problem and the parallel matrix vector 3280b4319ba4SBarry Smith product is handled "implicitly". 3281b4319ba4SBarry Smith 3282b4319ba4SBarry Smith Options Database Keys: 328375d48cdbSStefano Zampini + -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions() 328475d48cdbSStefano Zampini . -matis_fixempty - Fixes local matrices in case of empty local rows/columns. 328575d48cdbSStefano Zampini - -matis_storel2l - stores the local-to-local operators generated by the Galerkin process of MatPtAP(). 3286b4319ba4SBarry Smith 328795452b02SPatrick Sanan Notes: 328895452b02SPatrick Sanan Options prefix for the inner matrix are given by -is_mat_xxx 3289b4319ba4SBarry Smith 3290b4319ba4SBarry Smith You must call MatSetLocalToGlobalMapping() before using this matrix type. 3291b4319ba4SBarry Smith 3292b4319ba4SBarry Smith You can do matrix preallocation on the local matrix after you obtain it with 3293eb82efa4SStefano Zampini MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation() 3294b4319ba4SBarry Smith 3295b4319ba4SBarry Smith Level: advanced 3296b4319ba4SBarry Smith 3297db781477SPatrick Sanan .seealso: `Mat`, `MatISGetLocalMat()`, `MatSetLocalToGlobalMapping()`, `MatISSetPreallocation()`, `MatCreateIS()`, `PCBDDC`, `KSPFETIDP` 3298b4319ba4SBarry Smith 3299b4319ba4SBarry Smith M*/ 33009371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A) { 3301e432b41dSStefano Zampini Mat_IS *a; 3302b4319ba4SBarry Smith 3303b4319ba4SBarry Smith PetscFunctionBegin; 33049566063dSJacob Faibussowitsch PetscCall(PetscNewLog(A, &a)); 33059566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATAIJ, &a->lmattype)); 3306e432b41dSStefano Zampini A->data = (void *)a; 3307b4319ba4SBarry Smith 3308e176bc59SStefano Zampini /* matrix ops */ 33099566063dSJacob Faibussowitsch PetscCall(PetscMemzero(A->ops, sizeof(struct _MatOps))); 3310b4319ba4SBarry Smith A->ops->mult = MatMult_IS; 33112e74eeadSLisandro Dalcin A->ops->multadd = MatMultAdd_IS; 33122e74eeadSLisandro Dalcin A->ops->multtranspose = MatMultTranspose_IS; 33132e74eeadSLisandro Dalcin A->ops->multtransposeadd = MatMultTransposeAdd_IS; 3314b4319ba4SBarry Smith A->ops->destroy = MatDestroy_IS; 3315b4319ba4SBarry Smith A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS; 33162e74eeadSLisandro Dalcin A->ops->setvalues = MatSetValues_IS; 331798921651SStefano Zampini A->ops->setvaluesblocked = MatSetValuesBlocked_IS; 3318b4319ba4SBarry Smith A->ops->setvalueslocal = MatSetValuesLocal_IS; 3319f0006bf2SLisandro Dalcin A->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_IS; 33202e74eeadSLisandro Dalcin A->ops->zerorows = MatZeroRows_IS; 3321f0ae7da4SStefano Zampini A->ops->zerorowscolumns = MatZeroRowsColumns_IS; 3322b4319ba4SBarry Smith A->ops->assemblybegin = MatAssemblyBegin_IS; 3323b4319ba4SBarry Smith A->ops->assemblyend = MatAssemblyEnd_IS; 3324b4319ba4SBarry Smith A->ops->view = MatView_IS; 33256726f965SBarry Smith A->ops->zeroentries = MatZeroEntries_IS; 33262e74eeadSLisandro Dalcin A->ops->scale = MatScale_IS; 33272e74eeadSLisandro Dalcin A->ops->getdiagonal = MatGetDiagonal_IS; 33286726f965SBarry Smith A->ops->setoption = MatSetOption_IS; 332969796d55SStefano Zampini A->ops->ishermitian = MatIsHermitian_IS; 333069796d55SStefano Zampini A->ops->issymmetric = MatIsSymmetric_IS; 333145471136SStefano Zampini A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS; 3332ad6194a2SStefano Zampini A->ops->duplicate = MatDuplicate_IS; 33336bd84002SStefano Zampini A->ops->missingdiagonal = MatMissingDiagonal_IS; 33342b404112SStefano Zampini A->ops->copy = MatCopy_IS; 3335659959c5SStefano Zampini A->ops->getlocalsubmatrix = MatGetLocalSubMatrix_IS; 33367dae84e0SHong Zhang A->ops->createsubmatrix = MatCreateSubMatrix_IS; 3337f26d0771SStefano Zampini A->ops->axpy = MatAXPY_IS; 33383fd1c9e7SStefano Zampini A->ops->diagonalset = MatDiagonalSet_IS; 33393fd1c9e7SStefano Zampini A->ops->shift = MatShift_IS; 3340d7f69cd0SStefano Zampini A->ops->transpose = MatTranspose_IS; 33417fa8f2d3SStefano Zampini A->ops->getinfo = MatGetInfo_IS; 3342ad219c80Sstefano_zampini A->ops->diagonalscale = MatDiagonalScale_IS; 3343872cf891SStefano Zampini A->ops->setfromoptions = MatSetFromOptions_IS; 3344fc989267SStefano Zampini A->ops->setup = MatSetUp_IS; 33458b9382cfSStefano Zampini A->ops->hasoperation = MatHasOperation_IS; 3346d0dbe9f7SStefano Zampini A->ops->getdiagonalblock = MatGetDiagonalBlock_IS; 3347d0dbe9f7SStefano Zampini A->ops->createsubmatrices = MatCreateSubMatrices_IS; 3348d0dbe9f7SStefano Zampini A->ops->increaseoverlap = MatIncreaseOverlap_IS; 3349b4319ba4SBarry Smith 3350b7ce53b6SStefano Zampini /* special MATIS functions */ 33519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMatType_C", MatISSetLocalMatType_IS)); 33529566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalMat_C", MatISGetLocalMat_IS)); 33539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISRestoreLocalMat_C", MatISRestoreLocalMat_IS)); 33549566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMat_C", MatISSetLocalMat_IS)); 33559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetMPIXAIJ_C", MatConvert_IS_XAIJ)); 33569566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetPreallocation_C", MatISSetPreallocation_IS)); 33579566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISStoreL2L_C", MatISStoreL2L_IS)); 33589566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISFixLocalEmpty_C", MatISFixLocalEmpty_IS)); 33599566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalToGlobalMapping_C", MatISGetLocalToGlobalMapping_IS)); 33609566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpiaij_C", MatConvert_IS_XAIJ)); 33619566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpibaij_C", MatConvert_IS_XAIJ)); 33629566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpisbaij_C", MatConvert_IS_XAIJ)); 33639566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqaij_C", MatConvert_IS_XAIJ)); 33649566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqbaij_C", MatConvert_IS_XAIJ)); 33659566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqsbaij_C", MatConvert_IS_XAIJ)); 33669566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_aij_C", MatConvert_IS_XAIJ)); 33679566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOOLocal_C", MatSetPreallocationCOOLocal_IS)); 33689566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_IS)); 33699566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, MATIS)); 3370b4319ba4SBarry Smith PetscFunctionReturn(0); 3371b4319ba4SBarry Smith } 3372