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 20d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISContainerDestroyPtAP_Private(void *ptr) 21d71ae5a4SJacob Faibussowitsch { 2275d48cdbSStefano Zampini MatISPtAP ptap = (MatISPtAP)ptr; 2375d48cdbSStefano Zampini 2475d48cdbSStefano Zampini PetscFunctionBegin; 259566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrices(ptap->ris1 ? 2 : 1, &ptap->lP)); 269566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ptap->cis0)); 279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ptap->cis1)); 289566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ptap->ris0)); 299566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ptap->ris1)); 309566063dSJacob Faibussowitsch PetscCall(PetscFree(ptap)); 313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3275d48cdbSStefano Zampini } 3375d48cdbSStefano Zampini 34d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_IS_XAIJ(Mat A, Mat P, Mat C) 35d71ae5a4SJacob Faibussowitsch { 3675d48cdbSStefano Zampini MatISPtAP ptap; 3775d48cdbSStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 3875d48cdbSStefano Zampini Mat lA, lC; 3975d48cdbSStefano Zampini MatReuse reuse; 4075d48cdbSStefano Zampini IS ris[2], cis[2]; 4175d48cdbSStefano Zampini PetscContainer c; 4275d48cdbSStefano Zampini PetscInt n; 4375d48cdbSStefano Zampini 4475d48cdbSStefano Zampini PetscFunctionBegin; 459566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)C, "_MatIS_PtAP", (PetscObject *)&c)); 4628b400f6SJacob Faibussowitsch PetscCheck(c, PetscObjectComm((PetscObject)C), PETSC_ERR_PLIB, "Missing PtAP information"); 479566063dSJacob Faibussowitsch PetscCall(PetscContainerGetPointer(c, (void **)&ptap)); 4875d48cdbSStefano Zampini ris[0] = ptap->ris0; 4975d48cdbSStefano Zampini ris[1] = ptap->ris1; 5075d48cdbSStefano Zampini cis[0] = ptap->cis0; 5175d48cdbSStefano Zampini cis[1] = ptap->cis1; 5275d48cdbSStefano Zampini n = ptap->ris1 ? 2 : 1; 5375d48cdbSStefano Zampini reuse = ptap->lP ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX; 549566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(P, n, ris, cis, reuse, &ptap->lP)); 5575d48cdbSStefano Zampini 569566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A, &lA)); 579566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(C, &lC)); 5875d48cdbSStefano Zampini if (ptap->ris1) { /* unsymmetric A mapping */ 5975d48cdbSStefano Zampini Mat lPt; 6075d48cdbSStefano Zampini 619566063dSJacob Faibussowitsch PetscCall(MatTranspose(ptap->lP[1], MAT_INITIAL_MATRIX, &lPt)); 629566063dSJacob Faibussowitsch PetscCall(MatMatMatMult(lPt, lA, ptap->lP[0], reuse, ptap->fill, &lC)); 6348a46eb9SPierre Jolivet if (matis->storel2l) PetscCall(PetscObjectCompose((PetscObject)(A), "_MatIS_PtAP_l2l", (PetscObject)lPt)); 649566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lPt)); 6575d48cdbSStefano Zampini } else { 669566063dSJacob Faibussowitsch PetscCall(MatPtAP(lA, ptap->lP[0], reuse, ptap->fill, &lC)); 6748a46eb9SPierre Jolivet if (matis->storel2l) PetscCall(PetscObjectCompose((PetscObject)C, "_MatIS_PtAP_l2l", (PetscObject)ptap->lP[0])); 6875d48cdbSStefano Zampini } 6975d48cdbSStefano Zampini if (reuse == MAT_INITIAL_MATRIX) { 709566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(C, lC)); 719566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lC)); 7275d48cdbSStefano Zampini } 739566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 749566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7675d48cdbSStefano Zampini } 7775d48cdbSStefano Zampini 78d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetNonzeroColumnsLocal_Private(Mat PT, IS *cis) 79d71ae5a4SJacob Faibussowitsch { 8075d48cdbSStefano Zampini Mat Po, Pd; 8175d48cdbSStefano Zampini IS zd, zo; 8275d48cdbSStefano Zampini const PetscInt *garray; 8375d48cdbSStefano Zampini PetscInt *aux, i, bs; 8475d48cdbSStefano Zampini PetscInt dc, stc, oc, ctd, cto; 8575d48cdbSStefano Zampini PetscBool ismpiaij, ismpibaij, isseqaij, isseqbaij; 8675d48cdbSStefano Zampini MPI_Comm comm; 8775d48cdbSStefano Zampini 8875d48cdbSStefano Zampini PetscFunctionBegin; 8975d48cdbSStefano Zampini PetscValidHeaderSpecific(PT, MAT_CLASSID, 1); 904f572ea9SToby Isaac PetscAssertPointer(cis, 2); 919566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)PT, &comm)); 9275d48cdbSStefano Zampini bs = 1; 939566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)PT, MATMPIAIJ, &ismpiaij)); 949566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)PT, MATMPIBAIJ, &ismpibaij)); 959566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)PT, MATSEQAIJ, &isseqaij)); 969566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)PT, MATSEQBAIJ, &isseqbaij)); 9775d48cdbSStefano Zampini if (isseqaij || isseqbaij) { 9875d48cdbSStefano Zampini Pd = PT; 9975d48cdbSStefano Zampini Po = NULL; 10075d48cdbSStefano Zampini garray = NULL; 10175d48cdbSStefano Zampini } else if (ismpiaij) { 1029566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(PT, &Pd, &Po, &garray)); 10375d48cdbSStefano Zampini } else if (ismpibaij) { 1049566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJGetSeqBAIJ(PT, &Pd, &Po, &garray)); 1059566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(PT, &bs)); 10698921bdaSJacob Faibussowitsch } else SETERRQ(comm, PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)(PT))->type_name); 10775d48cdbSStefano Zampini 10875d48cdbSStefano Zampini /* identify any null columns in Pd or Po */ 10922f7620eSStefano Zampini /* We use a tolerance comparison since it may happen that, with geometric multigrid, 11022f7620eSStefano Zampini some of the columns are not really zero, but very close to */ 11175d48cdbSStefano Zampini zo = zd = NULL; 11248a46eb9SPierre Jolivet if (Po) PetscCall(MatFindNonzeroRowsOrCols_Basic(Po, PETSC_TRUE, PETSC_SMALL, &zo)); 1139566063dSJacob Faibussowitsch PetscCall(MatFindNonzeroRowsOrCols_Basic(Pd, PETSC_TRUE, PETSC_SMALL, &zd)); 11475d48cdbSStefano Zampini 1159566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(PT, NULL, &dc)); 1169566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(PT, &stc, NULL)); 1179566063dSJacob Faibussowitsch if (Po) PetscCall(MatGetLocalSize(Po, NULL, &oc)); 11875d48cdbSStefano Zampini else oc = 0; 1199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((dc + oc) / bs, &aux)); 12075d48cdbSStefano Zampini if (zd) { 12175d48cdbSStefano Zampini const PetscInt *idxs; 12275d48cdbSStefano Zampini PetscInt nz; 12375d48cdbSStefano Zampini 12475d48cdbSStefano Zampini /* this will throw an error if bs is not valid */ 1259566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(zd, bs)); 1269566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zd, &nz)); 1279566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zd, &idxs)); 12875d48cdbSStefano Zampini ctd = nz / bs; 12975d48cdbSStefano Zampini for (i = 0; i < ctd; i++) aux[i] = (idxs[bs * i] + stc) / bs; 1309566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zd, &idxs)); 13175d48cdbSStefano Zampini } else { 13275d48cdbSStefano Zampini ctd = dc / bs; 13375d48cdbSStefano Zampini for (i = 0; i < ctd; i++) aux[i] = i + stc / bs; 13475d48cdbSStefano Zampini } 13575d48cdbSStefano Zampini if (zo) { 13675d48cdbSStefano Zampini const PetscInt *idxs; 13775d48cdbSStefano Zampini PetscInt nz; 13875d48cdbSStefano Zampini 13975d48cdbSStefano Zampini /* this will throw an error if bs is not valid */ 1409566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(zo, bs)); 1419566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zo, &nz)); 1429566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zo, &idxs)); 14375d48cdbSStefano Zampini cto = nz / bs; 14475d48cdbSStefano Zampini for (i = 0; i < cto; i++) aux[i + ctd] = garray[idxs[bs * i] / bs]; 1459566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zo, &idxs)); 14675d48cdbSStefano Zampini } else { 14775d48cdbSStefano Zampini cto = oc / bs; 14875d48cdbSStefano Zampini for (i = 0; i < cto; i++) aux[i + ctd] = garray[i]; 14975d48cdbSStefano Zampini } 1509566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, bs, ctd + cto, aux, PETSC_OWN_POINTER, cis)); 1519566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zd)); 1529566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zo)); 1533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15475d48cdbSStefano Zampini } 15575d48cdbSStefano Zampini 156d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPSymbolic_IS_XAIJ(Mat A, Mat P, PetscReal fill, Mat C) 157d71ae5a4SJacob Faibussowitsch { 1588546b261SStefano Zampini Mat PT, lA; 15975d48cdbSStefano Zampini MatISPtAP ptap; 16075d48cdbSStefano Zampini ISLocalToGlobalMapping Crl2g, Ccl2g, rl2g, cl2g; 16175d48cdbSStefano Zampini PetscContainer c; 1628546b261SStefano Zampini MatType lmtype; 16375d48cdbSStefano Zampini const PetscInt *garray; 16475d48cdbSStefano Zampini PetscInt ibs, N, dc; 16575d48cdbSStefano Zampini MPI_Comm comm; 16675d48cdbSStefano Zampini 16775d48cdbSStefano Zampini PetscFunctionBegin; 1689566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 1699566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATIS)); 1709566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A, &lA)); 1719566063dSJacob Faibussowitsch PetscCall(MatGetType(lA, &lmtype)); 1729566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(C, lmtype)); 1739566063dSJacob Faibussowitsch PetscCall(MatGetSize(P, NULL, &N)); 1749566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(P, NULL, &dc)); 1759566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, dc, dc, N, N)); 17675d48cdbSStefano Zampini /* Not sure about this 1779566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(P,NULL,&ibs)); 1789566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(*C,ibs)); 17975d48cdbSStefano Zampini */ 18075d48cdbSStefano Zampini 1819566063dSJacob Faibussowitsch PetscCall(PetscNew(&ptap)); 1829566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c)); 1839566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(c, ptap)); 1849566063dSJacob Faibussowitsch PetscCall(PetscContainerSetUserDestroy(c, MatISContainerDestroyPtAP_Private)); 1859566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)C, "_MatIS_PtAP", (PetscObject)c)); 1869566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&c)); 18775d48cdbSStefano Zampini ptap->fill = fill; 18875d48cdbSStefano Zampini 1899566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(A, &rl2g, &cl2g)); 19075d48cdbSStefano Zampini 1919566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(cl2g, &ibs)); 1929566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(cl2g, &N)); 1939566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(cl2g, &garray)); 1949566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, ibs, N / ibs, garray, PETSC_COPY_VALUES, &ptap->ris0)); 1959566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(cl2g, &garray)); 19675d48cdbSStefano Zampini 1979566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(P, ptap->ris0, NULL, MAT_INITIAL_MATRIX, &PT)); 1989566063dSJacob Faibussowitsch PetscCall(MatGetNonzeroColumnsLocal_Private(PT, &ptap->cis0)); 1999566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(ptap->cis0, &Ccl2g)); 2009566063dSJacob Faibussowitsch PetscCall(MatDestroy(&PT)); 20175d48cdbSStefano Zampini 20275d48cdbSStefano Zampini Crl2g = NULL; 20375d48cdbSStefano Zampini if (rl2g != cl2g) { /* unsymmetric A mapping */ 20475d48cdbSStefano Zampini PetscBool same, lsame = PETSC_FALSE; 20575d48cdbSStefano Zampini PetscInt N1, ibs1; 20675d48cdbSStefano Zampini 2079566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(rl2g, &N1)); 2089566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(rl2g, &ibs1)); 2099566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(rl2g, &garray)); 210*4f58015eSStefano Zampini PetscCall(ISCreateBlock(comm, ibs, N1 / ibs, garray, PETSC_COPY_VALUES, &ptap->ris1)); 2119566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(rl2g, &garray)); 21275d48cdbSStefano Zampini if (ibs1 == ibs && N1 == N) { /* check if the l2gmaps are the same */ 21375d48cdbSStefano Zampini const PetscInt *i1, *i2; 21475d48cdbSStefano Zampini 2159566063dSJacob Faibussowitsch PetscCall(ISBlockGetIndices(ptap->ris0, &i1)); 2169566063dSJacob Faibussowitsch PetscCall(ISBlockGetIndices(ptap->ris1, &i2)); 2179566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(i1, i2, N, &lsame)); 21875d48cdbSStefano Zampini } 2191c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&lsame, &same, 1, MPIU_BOOL, MPI_LAND, comm)); 22075d48cdbSStefano Zampini if (same) { 2219566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ptap->ris1)); 22275d48cdbSStefano Zampini } else { 2239566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(P, ptap->ris1, NULL, MAT_INITIAL_MATRIX, &PT)); 2249566063dSJacob Faibussowitsch PetscCall(MatGetNonzeroColumnsLocal_Private(PT, &ptap->cis1)); 2259566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(ptap->cis1, &Crl2g)); 2269566063dSJacob Faibussowitsch PetscCall(MatDestroy(&PT)); 22775d48cdbSStefano Zampini } 22875d48cdbSStefano Zampini } 22975d48cdbSStefano Zampini /* Not sure about this 23075d48cdbSStefano Zampini if (!Crl2g) { 2319566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(C,&ibs)); 2329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetBlockSize(Ccl2g,ibs)); 23375d48cdbSStefano Zampini } 23475d48cdbSStefano Zampini */ 2359566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(C, Crl2g ? Crl2g : Ccl2g, Ccl2g)); 2369566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&Crl2g)); 2379566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&Ccl2g)); 23875d48cdbSStefano Zampini 2394222ddf1SHong Zhang C->ops->ptapnumeric = MatPtAPNumeric_IS_XAIJ; 2403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24175d48cdbSStefano Zampini } 24275d48cdbSStefano Zampini 243d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_PtAP_IS_XAIJ(Mat C) 244d71ae5a4SJacob Faibussowitsch { 2454222ddf1SHong Zhang Mat_Product *product = C->product; 2464222ddf1SHong Zhang Mat A = product->A, P = product->B; 2474222ddf1SHong Zhang PetscReal fill = product->fill; 24875d48cdbSStefano Zampini 24975d48cdbSStefano Zampini PetscFunctionBegin; 2509566063dSJacob Faibussowitsch PetscCall(MatPtAPSymbolic_IS_XAIJ(A, P, fill, C)); 2514222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_PtAP; 2523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25375d48cdbSStefano Zampini } 25475d48cdbSStefano Zampini 255d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_IS_XAIJ_PtAP(Mat C) 256d71ae5a4SJacob Faibussowitsch { 2574222ddf1SHong Zhang PetscFunctionBegin; 2584222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_PtAP_IS_XAIJ; 2593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2604222ddf1SHong Zhang } 2614222ddf1SHong Zhang 262d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat C) 263d71ae5a4SJacob Faibussowitsch { 2644222ddf1SHong Zhang Mat_Product *product = C->product; 2654222ddf1SHong Zhang 2664222ddf1SHong Zhang PetscFunctionBegin; 26748a46eb9SPierre Jolivet if (product->type == MATPRODUCT_PtAP) PetscCall(MatProductSetFromOptions_IS_XAIJ_PtAP(C)); 2683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2694222ddf1SHong Zhang } 2704222ddf1SHong Zhang 271d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISContainerDestroyFields_Private(void *ptr) 272d71ae5a4SJacob Faibussowitsch { 2735b003df0Sstefano_zampini MatISLocalFields lf = (MatISLocalFields)ptr; 2745b003df0Sstefano_zampini PetscInt i; 2755b003df0Sstefano_zampini 276ab4d48faSStefano Zampini PetscFunctionBegin; 27748a46eb9SPierre Jolivet for (i = 0; i < lf->nr; i++) PetscCall(ISDestroy(&lf->rf[i])); 27848a46eb9SPierre Jolivet for (i = 0; i < lf->nc; i++) PetscCall(ISDestroy(&lf->cf[i])); 2799566063dSJacob Faibussowitsch PetscCall(PetscFree2(lf->rf, lf->cf)); 2809566063dSJacob Faibussowitsch PetscCall(PetscFree(lf)); 2813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2825b003df0Sstefano_zampini } 283a72627d2SStefano Zampini 284d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_SeqXAIJ_IS(Mat A, MatType type, MatReuse reuse, Mat *newmat) 285d71ae5a4SJacob Faibussowitsch { 286c9225affSStefano Zampini Mat B, lB; 287c9225affSStefano Zampini 288c9225affSStefano Zampini PetscFunctionBegin; 289c9225affSStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 290c9225affSStefano Zampini ISLocalToGlobalMapping rl2g, cl2g; 291c9225affSStefano Zampini PetscInt bs; 292c9225affSStefano Zampini IS is; 293c9225affSStefano Zampini 2949566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 2959566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), A->rmap->n / bs, 0, 1, &is)); 296c9225affSStefano Zampini if (bs > 1) { 297c9225affSStefano Zampini IS is2; 298c9225affSStefano Zampini PetscInt i, *aux; 299c9225affSStefano Zampini 3009566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &i)); 3019566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, (const PetscInt **)&aux)); 3029566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), bs, i, aux, PETSC_COPY_VALUES, &is2)); 3039566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, (const PetscInt **)&aux)); 3049566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 305c9225affSStefano Zampini is = is2; 306c9225affSStefano Zampini } 3079566063dSJacob Faibussowitsch PetscCall(ISSetIdentity(is)); 3089566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g)); 3099566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3109566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), A->cmap->n / bs, 0, 1, &is)); 311c9225affSStefano Zampini if (bs > 1) { 312c9225affSStefano Zampini IS is2; 313c9225affSStefano Zampini PetscInt i, *aux; 314c9225affSStefano Zampini 3159566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &i)); 3169566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, (const PetscInt **)&aux)); 3179566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), bs, i, aux, PETSC_COPY_VALUES, &is2)); 3189566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, (const PetscInt **)&aux)); 3199566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 320c9225affSStefano Zampini is = is2; 321c9225affSStefano Zampini } 3229566063dSJacob Faibussowitsch PetscCall(ISSetIdentity(is)); 3239566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g)); 3249566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3259566063dSJacob Faibussowitsch PetscCall(MatCreateIS(PetscObjectComm((PetscObject)A), bs, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N, rl2g, cl2g, &B)); 3269566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 3279566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 3289566063dSJacob Faibussowitsch PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &lB)); 329c9225affSStefano Zampini if (reuse == MAT_INITIAL_MATRIX) *newmat = B; 330c9225affSStefano Zampini } else { 331c9225affSStefano Zampini B = *newmat; 3329566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 333c9225affSStefano Zampini lB = A; 334c9225affSStefano Zampini } 3359566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B, lB)); 3369566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lB)); 3379566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 3389566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 33948a46eb9SPierre Jolivet if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &B)); 3403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 341c9225affSStefano Zampini } 342c9225affSStefano Zampini 343d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISScaleDisassembling_Private(Mat A) 344d71ae5a4SJacob Faibussowitsch { 345f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)A->data; 346c9225affSStefano Zampini PetscScalar *aa; 347c9225affSStefano Zampini const PetscInt *ii, *jj; 348c9225affSStefano Zampini PetscInt i, n, m; 349fabe8965SStefano Zampini PetscInt *ecount, **eneighs; 350c9225affSStefano Zampini PetscBool flg; 351c9225affSStefano Zampini 352c9225affSStefano Zampini PetscFunctionBegin; 3539566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(matis->A, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg)); 35408401ef6SPierre Jolivet PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get IJ structure"); 3559566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetNodeInfo(matis->rmapping, &n, &ecount, &eneighs)); 35608401ef6SPierre Jolivet PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, m, n); 3579566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(matis->A, &aa)); 358c9225affSStefano Zampini for (i = 0; i < n; i++) { 359fabe8965SStefano Zampini if (ecount[i] > 1) { 360c9225affSStefano Zampini PetscInt j; 361c9225affSStefano Zampini 362c9225affSStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 363c9225affSStefano Zampini PetscInt i2 = jj[j], p, p2; 364fabe8965SStefano Zampini PetscReal scal = 0.0; 365c9225affSStefano Zampini 366c9225affSStefano Zampini for (p = 0; p < ecount[i]; p++) { 367c9225affSStefano Zampini for (p2 = 0; p2 < ecount[i2]; p2++) { 3689371c9d4SSatish Balay if (eneighs[i][p] == eneighs[i2][p2]) { 3699371c9d4SSatish Balay scal += 1.0; 3709371c9d4SSatish Balay break; 3719371c9d4SSatish Balay } 372c9225affSStefano Zampini } 373c9225affSStefano Zampini } 374fabe8965SStefano Zampini if (scal) aa[j] /= scal; 375c9225affSStefano Zampini } 376c9225affSStefano Zampini } 377c9225affSStefano Zampini } 3789566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(matis->rmapping, &n, &ecount, &eneighs)); 3799566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(matis->A, &aa)); 3809566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(matis->A, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg)); 38108401ef6SPierre Jolivet PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot restore IJ structure"); 3823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 383c9225affSStefano Zampini } 384c9225affSStefano Zampini 3859371c9d4SSatish Balay typedef enum { 3869371c9d4SSatish Balay MAT_IS_DISASSEMBLE_L2G_NATURAL, 3879371c9d4SSatish Balay MAT_IS_DISASSEMBLE_L2G_MAT, 3889371c9d4SSatish Balay MAT_IS_DISASSEMBLE_L2G_ND 3899371c9d4SSatish Balay } MatISDisassemblel2gType; 390fabe8965SStefano Zampini 391d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMPIXAIJComputeLocalToGlobalMapping_Private(Mat A, ISLocalToGlobalMapping *l2g) 392d71ae5a4SJacob Faibussowitsch { 393fabe8965SStefano Zampini Mat Ad, Ao; 394fabe8965SStefano Zampini IS is, ndmap, ndsub; 395c9225affSStefano Zampini MPI_Comm comm; 396fabe8965SStefano Zampini const PetscInt *garray, *ndmapi; 397fabe8965SStefano Zampini PetscInt bs, i, cnt, nl, *ncount, *ndmapc; 398fabe8965SStefano Zampini PetscBool ismpiaij, ismpibaij; 399f4259b30SLisandro Dalcin const char *const MatISDisassemblel2gTypes[] = {"NATURAL", "MAT", "ND", "MatISDisassemblel2gType", "MAT_IS_DISASSEMBLE_L2G_", NULL}; 400fabe8965SStefano Zampini MatISDisassemblel2gType mode = MAT_IS_DISASSEMBLE_L2G_NATURAL; 401fabe8965SStefano Zampini MatPartitioning part; 402fabe8965SStefano Zampini PetscSF sf; 40391d376acSStefano Zampini PetscObject dm; 404c9225affSStefano Zampini 405c9225affSStefano Zampini PetscFunctionBegin; 406d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)A), ((PetscObject)A)->prefix, "MatIS l2g disassembling options", "Mat"); 4079566063dSJacob 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)); 408d0609cedSBarry Smith PetscOptionsEnd(); 409fabe8965SStefano Zampini if (mode == MAT_IS_DISASSEMBLE_L2G_MAT) { 4109566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(A, l2g, NULL)); 4113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 412c9225affSStefano Zampini } 4139566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 4149566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 4159566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIBAIJ, &ismpibaij)); 4169566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 417fabe8965SStefano Zampini switch (mode) { 418fabe8965SStefano Zampini case MAT_IS_DISASSEMBLE_L2G_ND: 4199566063dSJacob Faibussowitsch PetscCall(MatPartitioningCreate(comm, &part)); 4209566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetAdjacency(part, A)); 4219566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)part, ((PetscObject)A)->prefix)); 4229566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetFromOptions(part)); 4239566063dSJacob Faibussowitsch PetscCall(MatPartitioningApplyND(part, &ndmap)); 4249566063dSJacob Faibussowitsch PetscCall(MatPartitioningDestroy(&part)); 4259566063dSJacob Faibussowitsch PetscCall(ISBuildTwoSided(ndmap, NULL, &ndsub)); 4269566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetUseScalableIncreaseOverlap(A, PETSC_TRUE)); 4279566063dSJacob Faibussowitsch PetscCall(MatIncreaseOverlap(A, 1, &ndsub, 1)); 4289566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(ndsub, l2g)); 429fabe8965SStefano Zampini 430fabe8965SStefano Zampini /* it may happen that a separator node is not properly shared */ 4319566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetNodeInfo(*l2g, &nl, &ncount, NULL)); 4329566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &sf)); 4339566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(*l2g, &garray)); 4349566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(sf, A->rmap, nl, NULL, PETSC_OWN_POINTER, garray)); 4359566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(*l2g, &garray)); 4369566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(A->rmap->n, &ndmapc)); 4379566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(sf, MPIU_INT, ncount, ndmapc, MPI_REPLACE)); 4389566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(sf, MPIU_INT, ncount, ndmapc, MPI_REPLACE)); 4399566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(*l2g, NULL, &ncount, NULL)); 4409566063dSJacob Faibussowitsch PetscCall(ISGetIndices(ndmap, &ndmapi)); 441fabe8965SStefano Zampini for (i = 0, cnt = 0; i < A->rmap->n; i++) 4429371c9d4SSatish Balay if (ndmapi[i] < 0 && ndmapc[i] < 2) cnt++; 443fabe8965SStefano Zampini 4441c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&cnt, &i, 1, MPIU_INT, MPI_MAX, comm)); 445fabe8965SStefano Zampini if (i) { /* we detected isolated separator nodes */ 446fabe8965SStefano Zampini Mat A2, A3; 447fabe8965SStefano Zampini IS *workis, is2; 448fabe8965SStefano Zampini PetscScalar *vals; 449fabe8965SStefano Zampini PetscInt gcnt = i, *dnz, *onz, j, *lndmapi; 450fabe8965SStefano Zampini ISLocalToGlobalMapping ll2g; 451fabe8965SStefano Zampini PetscBool flg; 452fabe8965SStefano Zampini const PetscInt *ii, *jj; 453fabe8965SStefano Zampini 454fabe8965SStefano Zampini /* communicate global id of separators */ 455d0609cedSBarry Smith MatPreallocateBegin(comm, A->rmap->n, A->cmap->n, dnz, onz); 4569371c9d4SSatish Balay for (i = 0, cnt = 0; i < A->rmap->n; i++) dnz[i] = ndmapi[i] < 0 ? i + A->rmap->rstart : -1; 457fabe8965SStefano Zampini 4589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl, &lndmapi)); 4599566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, dnz, lndmapi, MPI_REPLACE)); 460fabe8965SStefano Zampini 461fabe8965SStefano Zampini /* compute adjacency of isolated separators node */ 4629566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(gcnt, &workis)); 463fabe8965SStefano Zampini for (i = 0, cnt = 0; i < A->rmap->n; i++) { 46448a46eb9SPierre Jolivet if (ndmapi[i] < 0 && ndmapc[i] < 2) PetscCall(ISCreateStride(comm, 1, i + A->rmap->rstart, 1, &workis[cnt++])); 465fabe8965SStefano Zampini } 46648a46eb9SPierre Jolivet for (i = cnt; i < gcnt; i++) PetscCall(ISCreateStride(comm, 0, 0, 1, &workis[i])); 467fabe8965SStefano Zampini for (i = 0; i < gcnt; i++) { 4689566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)workis[i], "ISOLATED")); 4699566063dSJacob Faibussowitsch PetscCall(ISViewFromOptions(workis[i], NULL, "-view_isolated_separators")); 470fabe8965SStefano Zampini } 471fabe8965SStefano Zampini 472fabe8965SStefano Zampini /* no communications since all the ISes correspond to locally owned rows */ 4739566063dSJacob Faibussowitsch PetscCall(MatIncreaseOverlap(A, gcnt, workis, 1)); 474fabe8965SStefano Zampini 475fabe8965SStefano Zampini /* end communicate global id of separators */ 4769566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, dnz, lndmapi, MPI_REPLACE)); 477fabe8965SStefano Zampini 478fabe8965SStefano Zampini /* communicate new layers : create a matrix and transpose it */ 4799566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(dnz, A->rmap->n)); 4809566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(onz, A->rmap->n)); 481fabe8965SStefano Zampini for (i = 0, j = 0; i < A->rmap->n; i++) { 482fabe8965SStefano Zampini if (ndmapi[i] < 0 && ndmapc[i] < 2) { 483fabe8965SStefano Zampini const PetscInt *idxs; 484fabe8965SStefano Zampini PetscInt s; 485fabe8965SStefano Zampini 4869566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(workis[j], &s)); 4879566063dSJacob Faibussowitsch PetscCall(ISGetIndices(workis[j], &idxs)); 4889566063dSJacob Faibussowitsch PetscCall(MatPreallocateSet(i + A->rmap->rstart, s, idxs, dnz, onz)); 489fabe8965SStefano Zampini j++; 490fabe8965SStefano Zampini } 491fabe8965SStefano Zampini } 49208401ef6SPierre Jolivet PetscCheck(j == cnt, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected local count %" PetscInt_FMT " != %" PetscInt_FMT, j, cnt); 493fabe8965SStefano Zampini 494fabe8965SStefano Zampini for (i = 0; i < gcnt; i++) { 4959566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)workis[i], "EXTENDED")); 4969566063dSJacob Faibussowitsch PetscCall(ISViewFromOptions(workis[i], NULL, "-view_isolated_separators")); 497fabe8965SStefano Zampini } 498fabe8965SStefano Zampini 499fabe8965SStefano Zampini for (i = 0, j = 0; i < A->rmap->n; i++) j = PetscMax(j, dnz[i] + onz[i]); 5009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(j, &vals)); 501fabe8965SStefano Zampini for (i = 0; i < j; i++) vals[i] = 1.0; 502fabe8965SStefano Zampini 5039566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &A2)); 5049566063dSJacob Faibussowitsch PetscCall(MatSetType(A2, MATMPIAIJ)); 5059566063dSJacob Faibussowitsch PetscCall(MatSetSizes(A2, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N)); 5069566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(A2, 0, dnz, 0, onz)); 5079566063dSJacob Faibussowitsch PetscCall(MatSetOption(A2, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE)); 508fabe8965SStefano Zampini for (i = 0, j = 0; i < A2->rmap->n; i++) { 509fabe8965SStefano Zampini PetscInt row = i + A2->rmap->rstart, s = dnz[i] + onz[i]; 510fabe8965SStefano Zampini const PetscInt *idxs; 511fabe8965SStefano Zampini 512fabe8965SStefano Zampini if (s) { 5139566063dSJacob Faibussowitsch PetscCall(ISGetIndices(workis[j], &idxs)); 5149566063dSJacob Faibussowitsch PetscCall(MatSetValues(A2, 1, &row, s, idxs, vals, INSERT_VALUES)); 5159566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(workis[j], &idxs)); 516fabe8965SStefano Zampini j++; 517fabe8965SStefano Zampini } 518fabe8965SStefano Zampini } 51908401ef6SPierre Jolivet PetscCheck(j == cnt, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected local count %" PetscInt_FMT " != %" PetscInt_FMT, j, cnt); 5209566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 5219566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A2, MAT_FINAL_ASSEMBLY)); 5229566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A2, MAT_FINAL_ASSEMBLY)); 5239566063dSJacob Faibussowitsch PetscCall(MatTranspose(A2, MAT_INPLACE_MATRIX, &A2)); 524fabe8965SStefano Zampini 525fabe8965SStefano Zampini /* extract submatrix corresponding to the coupling "owned separators" x "isolated separators" */ 526fabe8965SStefano Zampini for (i = 0, j = 0; i < nl; i++) 527fabe8965SStefano Zampini if (lndmapi[i] >= 0) lndmapi[j++] = lndmapi[i]; 5289566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, j, lndmapi, PETSC_USE_POINTER, &is)); 5299566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetLocalMatCondensed(A2, MAT_INITIAL_MATRIX, &is, NULL, &A3)); 5309566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 5319566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A2)); 532fabe8965SStefano Zampini 533fabe8965SStefano Zampini /* extend local to global map to include connected isolated separators */ 5349566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)A3, "_petsc_GetLocalMatCondensed_iscol", (PetscObject *)&is)); 53528b400f6SJacob Faibussowitsch PetscCheck(is, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing column map"); 5369566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &ll2g)); 5379566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A3, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &flg)); 53828b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get IJ structure"); 5399566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ii[i], jj, PETSC_COPY_VALUES, &is)); 5409566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A3, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &flg)); 54128b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get IJ structure"); 5429566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(ll2g, is, &is2)); 5439566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 5449566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&ll2g)); 545fabe8965SStefano Zampini 546fabe8965SStefano Zampini /* add new nodes to the local-to-global map */ 5479566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(l2g)); 5489566063dSJacob Faibussowitsch PetscCall(ISExpand(ndsub, is2, &is)); 5499566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is2)); 5509566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, l2g)); 5519566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 552fabe8965SStefano Zampini 5539566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A3)); 5549566063dSJacob Faibussowitsch PetscCall(PetscFree(lndmapi)); 555d0609cedSBarry Smith MatPreallocateEnd(dnz, onz); 55648a46eb9SPierre Jolivet for (i = 0; i < gcnt; i++) PetscCall(ISDestroy(&workis[i])); 5579566063dSJacob Faibussowitsch PetscCall(PetscFree(workis)); 558fabe8965SStefano Zampini } 5599566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(ndmap, &ndmapi)); 5609566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 5619566063dSJacob Faibussowitsch PetscCall(PetscFree(ndmapc)); 5629566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ndmap)); 5639566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ndsub)); 5649566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetBlockSize(*l2g, bs)); 565*4f58015eSStefano Zampini PetscCall(ISLocalToGlobalMappingViewFromOptions(*l2g, NULL, "-mat_is_nd_l2g_view")); 566fabe8965SStefano Zampini break; 567fabe8965SStefano Zampini case MAT_IS_DISASSEMBLE_L2G_NATURAL: 56891d376acSStefano Zampini PetscCall(PetscObjectQuery((PetscObject)A, "__PETSc_dm", (PetscObject *)&dm)); 56991d376acSStefano Zampini if (dm) { /* if a matrix comes from a DM, most likely we can use the l2gmap if any */ 57091d376acSStefano Zampini PetscCall(MatGetLocalToGlobalMapping(A, l2g, NULL)); 57191d376acSStefano Zampini PetscCall(PetscObjectReference((PetscObject)*l2g)); 5723ba16761SJacob Faibussowitsch if (*l2g) PetscFunctionReturn(PETSC_SUCCESS); 57391d376acSStefano Zampini } 574fabe8965SStefano Zampini if (ismpiaij) { 5759566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(A, &Ad, &Ao, &garray)); 576fabe8965SStefano Zampini } else if (ismpibaij) { 5779566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJGetSeqBAIJ(A, &Ad, &Ao, &garray)); 57898921bdaSJacob Faibussowitsch } else SETERRQ(comm, PETSC_ERR_SUP, "Type %s", ((PetscObject)A)->type_name); 579c9225affSStefano Zampini if (A->rmap->n) { 580fabe8965SStefano Zampini PetscInt dc, oc, stc, *aux; 581c9225affSStefano Zampini 582ebf8cefbSJunchao Zhang PetscCall(MatGetLocalSize(Ad, NULL, &dc)); 5839566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(Ao, NULL, &oc)); 584d0dbe9f7SStefano Zampini PetscCheck(!oc || garray, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "garray not present"); 5859566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(A, &stc, NULL)); 5869566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((dc + oc) / bs, &aux)); 587c9225affSStefano Zampini for (i = 0; i < dc / bs; i++) aux[i] = i + stc / bs; 588ebf8cefbSJunchao Zhang for (i = 0; i < oc / bs; i++) aux[i + dc / bs] = (ismpiaij ? garray[i * bs] / bs : garray[i]); 5899566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, bs, (dc + oc) / bs, aux, PETSC_OWN_POINTER, &is)); 590c9225affSStefano Zampini } else { 5919566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, 1, 0, NULL, PETSC_OWN_POINTER, &is)); 592c9225affSStefano Zampini } 5939566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, l2g)); 5949566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 595fabe8965SStefano Zampini break; 596d71ae5a4SJacob Faibussowitsch default: 597d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unsupported l2g disassembling type %d", mode); 598c9225affSStefano Zampini } 5993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 600c9225affSStefano Zampini } 601c9225affSStefano Zampini 602d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat A, MatType type, MatReuse reuse, Mat *newmat) 603d71ae5a4SJacob Faibussowitsch { 604c9225affSStefano Zampini Mat lA, Ad, Ao, B = NULL; 6056989cf23SStefano Zampini ISLocalToGlobalMapping rl2g, cl2g; 6066989cf23SStefano Zampini IS is; 6076989cf23SStefano Zampini MPI_Comm comm; 6086989cf23SStefano Zampini void *ptrs[2]; 6096989cf23SStefano Zampini const char *names[2] = {"_convert_csr_aux", "_convert_csr_data"}; 610c9225affSStefano Zampini const PetscInt *garray; 6116989cf23SStefano Zampini PetscScalar *dd, *od, *aa, *data; 612c9225affSStefano Zampini const PetscInt *di, *dj, *oi, *oj; 613c9225affSStefano Zampini const PetscInt *odi, *odj, *ooi, *ooj; 6146989cf23SStefano Zampini PetscInt *aux, *ii, *jj; 615c9225affSStefano Zampini PetscInt bs, lc, dr, dc, oc, str, stc, nnz, i, jd, jo, cum; 616c9225affSStefano Zampini PetscBool flg, ismpiaij, ismpibaij, was_inplace = PETSC_FALSE; 617c9225affSStefano Zampini PetscMPIInt size; 6186989cf23SStefano Zampini 619ab4d48faSStefano Zampini PetscFunctionBegin; 6209566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 6219566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 622c9225affSStefano Zampini if (size == 1) { 6239566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqXAIJ_IS(A, type, reuse, newmat)); 6243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 625c9225affSStefano Zampini } 626c9225affSStefano Zampini if (reuse != MAT_REUSE_MATRIX && A->cmap->N == A->rmap->N) { 6279566063dSJacob Faibussowitsch PetscCall(MatMPIXAIJComputeLocalToGlobalMapping_Private(A, &rl2g)); 6289566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &B)); 6299566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATIS)); 6309566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N)); 6319566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B, rl2g, rl2g)); 6329566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 6339566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(B, bs)); 6349566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 635c9225affSStefano Zampini if (reuse == MAT_INPLACE_MATRIX) was_inplace = PETSC_TRUE; 636c9225affSStefano Zampini reuse = MAT_REUSE_MATRIX; 637c9225affSStefano Zampini } 638c9225affSStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 639c9225affSStefano Zampini Mat *newlA, lA; 640c9225affSStefano Zampini IS rows, cols; 641c9225affSStefano Zampini const PetscInt *ridx, *cidx; 642c9225affSStefano Zampini PetscInt rbs, cbs, nr, nc; 643c9225affSStefano Zampini 644c9225affSStefano Zampini if (!B) B = *newmat; 6459566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(B, &rl2g, &cl2g)); 6469566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(rl2g, &ridx)); 6479566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(cl2g, &cidx)); 6489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(rl2g, &nr)); 6499566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(cl2g, &nc)); 6509566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(rl2g, &rbs)); 6519566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(cl2g, &cbs)); 6529566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, rbs, nr / rbs, ridx, PETSC_USE_POINTER, &rows)); 653c9225affSStefano Zampini if (rl2g != cl2g) { 6549566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, cbs, nc / cbs, cidx, PETSC_USE_POINTER, &cols)); 655c9225affSStefano Zampini } else { 6569566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)rows)); 657c9225affSStefano Zampini cols = rows; 658c9225affSStefano Zampini } 6599566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(B, &lA)); 6609566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(A, 1, &rows, &cols, MAT_INITIAL_MATRIX, &newlA)); 6619566063dSJacob Faibussowitsch PetscCall(MatConvert(newlA[0], MATSEQAIJ, MAT_INPLACE_MATRIX, &newlA[0])); 6629566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(rl2g, &ridx)); 6639566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(cl2g, &cidx)); 6649566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rows)); 6659566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cols)); 666c9225affSStefano Zampini if (!lA->preallocated) { /* first time */ 6679566063dSJacob Faibussowitsch PetscCall(MatDuplicate(newlA[0], MAT_COPY_VALUES, &lA)); 6689566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B, lA)); 6699566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)lA)); 670c9225affSStefano Zampini } 6719566063dSJacob Faibussowitsch PetscCall(MatCopy(newlA[0], lA, SAME_NONZERO_PATTERN)); 6729566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrices(1, &newlA)); 6739566063dSJacob Faibussowitsch PetscCall(MatISScaleDisassembling_Private(B)); 6749566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 6759566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 6769566063dSJacob Faibussowitsch if (was_inplace) PetscCall(MatHeaderReplace(A, &B)); 677c9225affSStefano Zampini else *newmat = B; 6783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 679c9225affSStefano Zampini } 680c9225affSStefano Zampini /* rectangular case, just compress out the column space */ 6819566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 6829566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIBAIJ, &ismpibaij)); 683c9225affSStefano Zampini if (ismpiaij) { 684c9225affSStefano Zampini bs = 1; 6859566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(A, &Ad, &Ao, &garray)); 686c9225affSStefano Zampini } else if (ismpibaij) { 6879566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 6889566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJGetSeqBAIJ(A, &Ad, &Ao, &garray)); 6899566063dSJacob Faibussowitsch PetscCall(MatConvert(Ad, MATSEQAIJ, MAT_INITIAL_MATRIX, &Ad)); 6909566063dSJacob Faibussowitsch PetscCall(MatConvert(Ao, MATSEQAIJ, MAT_INITIAL_MATRIX, &Ao)); 69198921bdaSJacob Faibussowitsch } else SETERRQ(comm, PETSC_ERR_SUP, "Type %s", ((PetscObject)A)->type_name); 6929566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(Ad, &dd)); 6939566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(Ao, &od)); 69428b400f6SJacob Faibussowitsch PetscCheck(garray, comm, PETSC_ERR_ARG_WRONGSTATE, "garray not present"); 6956989cf23SStefano Zampini 6966989cf23SStefano Zampini /* access relevant information from MPIAIJ */ 6979566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &str, NULL)); 6989566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(A, &stc, NULL)); 6999566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &dr, &dc)); 7009566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(Ao, NULL, &oc)); 7019566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(Ad, 0, PETSC_FALSE, PETSC_FALSE, &i, &di, &dj, &flg)); 70228b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get IJ structure"); 7039566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(Ao, 0, PETSC_FALSE, PETSC_FALSE, &i, &oi, &oj, &flg)); 70428b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get IJ structure"); 705c9225affSStefano Zampini nnz = di[dr] + oi[dr]; 706c9225affSStefano Zampini /* store original pointers to be restored later */ 7079371c9d4SSatish Balay odi = di; 7089371c9d4SSatish Balay odj = dj; 7099371c9d4SSatish Balay ooi = oi; 7109371c9d4SSatish Balay ooj = oj; 7116989cf23SStefano Zampini 7126989cf23SStefano Zampini /* generate l2g maps for rows and cols */ 7139566063dSJacob Faibussowitsch PetscCall(ISCreateStride(comm, dr / bs, str / bs, 1, &is)); 714c9225affSStefano Zampini if (bs > 1) { 715c9225affSStefano Zampini IS is2; 716c9225affSStefano Zampini 7179566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &i)); 7189566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, (const PetscInt **)&aux)); 7199566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, bs, i, aux, PETSC_COPY_VALUES, &is2)); 7209566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, (const PetscInt **)&aux)); 7219566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 722c9225affSStefano Zampini is = is2; 723c9225affSStefano Zampini } 7249566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g)); 7259566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 726e363d98aSStefano Zampini if (dr) { 7279566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((dc + oc) / bs, &aux)); 728c9225affSStefano Zampini for (i = 0; i < dc / bs; i++) aux[i] = i + stc / bs; 729c9225affSStefano Zampini for (i = 0; i < oc / bs; i++) aux[i + dc / bs] = garray[i]; 7309566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, bs, (dc + oc) / bs, aux, PETSC_OWN_POINTER, &is)); 731e363d98aSStefano Zampini lc = dc + oc; 732e363d98aSStefano Zampini } else { 7339566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, bs, 0, NULL, PETSC_OWN_POINTER, &is)); 734e363d98aSStefano Zampini lc = 0; 735e363d98aSStefano Zampini } 7369566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g)); 7379566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 7386989cf23SStefano Zampini 7396989cf23SStefano Zampini /* create MATIS object */ 7409566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &B)); 7419566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, dr, dc, PETSC_DECIDE, PETSC_DECIDE)); 7429566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATIS)); 7439566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(B, bs)); 7449566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B, rl2g, cl2g)); 7459566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 7469566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 7476989cf23SStefano Zampini 7486989cf23SStefano Zampini /* merge local matrices */ 7499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz + dr + 1, &aux)); 7509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &data)); 7516989cf23SStefano Zampini ii = aux; 7526989cf23SStefano Zampini jj = aux + dr + 1; 7536989cf23SStefano Zampini aa = data; 7546989cf23SStefano Zampini *ii = *(di++) + *(oi++); 7559371c9d4SSatish Balay for (jd = 0, jo = 0, cum = 0; *ii < nnz; cum++) { 7569371c9d4SSatish Balay for (; jd < *di; jd++) { 7579371c9d4SSatish Balay *jj++ = *dj++; 7589371c9d4SSatish Balay *aa++ = *dd++; 7599371c9d4SSatish Balay } 7609371c9d4SSatish Balay for (; jo < *oi; jo++) { 7619371c9d4SSatish Balay *jj++ = *oj++ + dc; 7629371c9d4SSatish Balay *aa++ = *od++; 7639371c9d4SSatish Balay } 7646989cf23SStefano Zampini *(++ii) = *(di++) + *(oi++); 7656989cf23SStefano Zampini } 7666989cf23SStefano Zampini for (; cum < dr; cum++) *(++ii) = nnz; 767c9225affSStefano Zampini 7689566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(Ad, 0, PETSC_FALSE, PETSC_FALSE, &i, &odi, &odj, &flg)); 76928b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot restore IJ structure"); 7709566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(Ao, 0, PETSC_FALSE, PETSC_FALSE, &i, &ooi, &ooj, &flg)); 77128b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot restore IJ structure"); 7729566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(Ad, &dd)); 7739566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(Ao, &od)); 774c9225affSStefano Zampini 7756989cf23SStefano Zampini ii = aux; 7766989cf23SStefano Zampini jj = aux + dr + 1; 7776989cf23SStefano Zampini aa = data; 7789566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, dr, lc, ii, jj, aa, &lA)); 7796989cf23SStefano Zampini 7806989cf23SStefano Zampini /* create containers to destroy the data */ 7816989cf23SStefano Zampini ptrs[0] = aux; 7826989cf23SStefano Zampini ptrs[1] = data; 7836989cf23SStefano Zampini for (i = 0; i < 2; i++) { 7846989cf23SStefano Zampini PetscContainer c; 7856989cf23SStefano Zampini 7869566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c)); 7879566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(c, ptrs[i])); 7889566063dSJacob Faibussowitsch PetscCall(PetscContainerSetUserDestroy(c, PetscContainerUserDestroyDefault)); 7899566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)lA, names[i], (PetscObject)c)); 7909566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&c)); 7916989cf23SStefano Zampini } 792c9225affSStefano Zampini if (ismpibaij) { /* destroy converted local matrices */ 7939566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Ad)); 7949566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Ao)); 795c9225affSStefano Zampini } 7966989cf23SStefano Zampini 7976989cf23SStefano Zampini /* finalize matrix */ 7989566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B, lA)); 7999566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lA)); 8009566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 8019566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 802c9225affSStefano Zampini if (reuse == MAT_INPLACE_MATRIX) { 8039566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &B)); 804c9225affSStefano Zampini } else *newmat = B; 8053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8066989cf23SStefano Zampini } 8076989cf23SStefano Zampini 808d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A, MatType type, MatReuse reuse, Mat *newmat) 809d71ae5a4SJacob Faibussowitsch { 8105e3038f0Sstefano_zampini Mat **nest, *snest, **rnest, lA, B; 8115e3038f0Sstefano_zampini IS *iscol, *isrow, *islrow, *islcol; 8125e3038f0Sstefano_zampini ISLocalToGlobalMapping rl2g, cl2g; 8135e3038f0Sstefano_zampini MPI_Comm comm; 8145b003df0Sstefano_zampini PetscInt *lr, *lc, *l2gidxs; 8155b003df0Sstefano_zampini PetscInt i, j, nr, nc, rbs, cbs; 8169e7b2b25Sstefano_zampini PetscBool convert, lreuse, *istrans; 817*4f58015eSStefano Zampini PetscBool3 allow_repeated = PETSC_BOOL3_UNKNOWN; 8185e3038f0Sstefano_zampini 819ab4d48faSStefano Zampini PetscFunctionBegin; 8209566063dSJacob Faibussowitsch PetscCall(MatNestGetSubMats(A, &nr, &nc, &nest)); 8215e3038f0Sstefano_zampini lreuse = PETSC_FALSE; 8225e3038f0Sstefano_zampini rnest = NULL; 8235e3038f0Sstefano_zampini if (reuse == MAT_REUSE_MATRIX) { 8245e3038f0Sstefano_zampini PetscBool ismatis, isnest; 8255e3038f0Sstefano_zampini 8269566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)*newmat, MATIS, &ismatis)); 827f4f49eeaSPierre Jolivet PetscCheck(ismatis, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_USER, "Cannot reuse matrix of type %s", ((PetscObject)*newmat)->type_name); 8289566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*newmat, &lA)); 8299566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)lA, MATNEST, &isnest)); 8305e3038f0Sstefano_zampini if (isnest) { 8319566063dSJacob Faibussowitsch PetscCall(MatNestGetSubMats(lA, &i, &j, &rnest)); 8325e3038f0Sstefano_zampini lreuse = (PetscBool)(i == nr && j == nc); 8335e3038f0Sstefano_zampini if (!lreuse) rnest = NULL; 8345e3038f0Sstefano_zampini } 8355e3038f0Sstefano_zampini } 8369566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 8379566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(nr, &lr, nc, &lc)); 8389566063dSJacob Faibussowitsch PetscCall(PetscCalloc6(nr, &isrow, nc, &iscol, nr, &islrow, nc, &islcol, nr * nc, &snest, nr * nc, &istrans)); 8399566063dSJacob Faibussowitsch PetscCall(MatNestGetISs(A, isrow, iscol)); 8405e3038f0Sstefano_zampini for (i = 0; i < nr; i++) { 8415e3038f0Sstefano_zampini for (j = 0; j < nc; j++) { 842*4f58015eSStefano Zampini PetscBool ismatis, sallow; 8439e7b2b25Sstefano_zampini PetscInt l1, l2, lb1, lb2, ij = i * nc + j; 8445e3038f0Sstefano_zampini 8455e3038f0Sstefano_zampini /* Null matrix pointers are allowed in MATNEST */ 8465e3038f0Sstefano_zampini if (!nest[i][j]) continue; 8475e3038f0Sstefano_zampini 8485e3038f0Sstefano_zampini /* Nested matrices should be of type MATIS */ 849013e2dc7SBarry Smith PetscCall(PetscObjectTypeCompare((PetscObject)nest[i][j], MATTRANSPOSEVIRTUAL, &istrans[ij])); 8509e7b2b25Sstefano_zampini if (istrans[ij]) { 8519e7b2b25Sstefano_zampini Mat T, lT; 8529566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(nest[i][j], &T)); 8539566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)T, MATIS, &ismatis)); 85428b400f6SJacob 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); 855*4f58015eSStefano Zampini PetscCall(MatISGetAllowRepeated(T, &sallow)); 8569566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(T, &lT)); 8579566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(lT, &snest[ij])); 8589e7b2b25Sstefano_zampini } else { 8599566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)nest[i][j], MATIS, &ismatis)); 86028b400f6SJacob 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); 861*4f58015eSStefano Zampini PetscCall(MatISGetAllowRepeated(nest[i][j], &sallow)); 8629566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(nest[i][j], &snest[ij])); 8639e7b2b25Sstefano_zampini } 864*4f58015eSStefano Zampini if (allow_repeated == PETSC_BOOL3_UNKNOWN) allow_repeated = PetscBoolToBool3(sallow); 865*4f58015eSStefano Zampini PetscCheck(sallow == PetscBool3ToBool(allow_repeated), comm, PETSC_ERR_SUP, "Cannot mix repeated and non repeated maps"); 8665e3038f0Sstefano_zampini 8675e3038f0Sstefano_zampini /* Check compatibility of local sizes */ 8689566063dSJacob Faibussowitsch PetscCall(MatGetSize(snest[ij], &l1, &l2)); 8699566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(snest[ij], &lb1, &lb2)); 8705e3038f0Sstefano_zampini if (!l1 || !l2) continue; 871aed4548fSBarry 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); 872aed4548fSBarry 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); 8735e3038f0Sstefano_zampini lr[i] = l1; 8745e3038f0Sstefano_zampini lc[j] = l2; 8755e3038f0Sstefano_zampini 876da81f932SPierre Jolivet /* check compatibility for local matrix reusage */ 8775e3038f0Sstefano_zampini if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE; 8785e3038f0Sstefano_zampini } 8795e3038f0Sstefano_zampini } 8805e3038f0Sstefano_zampini 88176bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 8825e3038f0Sstefano_zampini /* Check compatibility of l2g maps for rows */ 8835e3038f0Sstefano_zampini for (i = 0; i < nr; i++) { 8845e3038f0Sstefano_zampini rl2g = NULL; 8855e3038f0Sstefano_zampini for (j = 0; j < nc; j++) { 8865e3038f0Sstefano_zampini PetscInt n1, n2; 8875e3038f0Sstefano_zampini 8885e3038f0Sstefano_zampini if (!nest[i][j]) continue; 8899e7b2b25Sstefano_zampini if (istrans[i * nc + j]) { 8909e7b2b25Sstefano_zampini Mat T; 8919e7b2b25Sstefano_zampini 8929566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(nest[i][j], &T)); 8939566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(T, NULL, &cl2g)); 8949e7b2b25Sstefano_zampini } else { 8959566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(nest[i][j], &cl2g, NULL)); 8969e7b2b25Sstefano_zampini } 8979566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(cl2g, &n1)); 8985e3038f0Sstefano_zampini if (!n1) continue; 8995e3038f0Sstefano_zampini if (!rl2g) { 9005e3038f0Sstefano_zampini rl2g = cl2g; 9015e3038f0Sstefano_zampini } else { 9025e3038f0Sstefano_zampini const PetscInt *idxs1, *idxs2; 9035e3038f0Sstefano_zampini PetscBool same; 9045e3038f0Sstefano_zampini 9059566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(rl2g, &n2)); 90608401ef6SPierre 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); 9079566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(cl2g, &idxs1)); 9089566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(rl2g, &idxs2)); 9099566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(idxs1, idxs2, n1, &same)); 9109566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(cl2g, &idxs1)); 9119566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(rl2g, &idxs2)); 91228b400f6SJacob 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); 9135e3038f0Sstefano_zampini } 9145e3038f0Sstefano_zampini } 9155e3038f0Sstefano_zampini } 9165e3038f0Sstefano_zampini /* Check compatibility of l2g maps for columns */ 9175e3038f0Sstefano_zampini for (i = 0; i < nc; i++) { 9185e3038f0Sstefano_zampini rl2g = NULL; 9195e3038f0Sstefano_zampini for (j = 0; j < nr; j++) { 9205e3038f0Sstefano_zampini PetscInt n1, n2; 9215e3038f0Sstefano_zampini 9225e3038f0Sstefano_zampini if (!nest[j][i]) continue; 9239e7b2b25Sstefano_zampini if (istrans[j * nc + i]) { 9249e7b2b25Sstefano_zampini Mat T; 9259e7b2b25Sstefano_zampini 9269566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(nest[j][i], &T)); 9279566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(T, &cl2g, NULL)); 9289e7b2b25Sstefano_zampini } else { 9299566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(nest[j][i], NULL, &cl2g)); 9309e7b2b25Sstefano_zampini } 9319566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(cl2g, &n1)); 9325e3038f0Sstefano_zampini if (!n1) continue; 9335e3038f0Sstefano_zampini if (!rl2g) { 9345e3038f0Sstefano_zampini rl2g = cl2g; 9355e3038f0Sstefano_zampini } else { 9365e3038f0Sstefano_zampini const PetscInt *idxs1, *idxs2; 9375e3038f0Sstefano_zampini PetscBool same; 9385e3038f0Sstefano_zampini 9399566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(rl2g, &n2)); 94008401ef6SPierre 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); 9419566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(cl2g, &idxs1)); 9429566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(rl2g, &idxs2)); 9439566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(idxs1, idxs2, n1, &same)); 9449566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(cl2g, &idxs1)); 9459566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(rl2g, &idxs2)); 94628b400f6SJacob 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); 9475e3038f0Sstefano_zampini } 9485e3038f0Sstefano_zampini } 9495e3038f0Sstefano_zampini } 95076bd3646SJed Brown } 9515e3038f0Sstefano_zampini 9525e3038f0Sstefano_zampini B = NULL; 9535e3038f0Sstefano_zampini if (reuse != MAT_REUSE_MATRIX) { 9545b003df0Sstefano_zampini PetscInt stl; 9555b003df0Sstefano_zampini 9565e3038f0Sstefano_zampini /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */ 9575e3038f0Sstefano_zampini for (i = 0, stl = 0; i < nr; i++) stl += lr[i]; 9589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(stl, &l2gidxs)); 9595b003df0Sstefano_zampini for (i = 0, stl = 0; i < nr; i++) { 9605e3038f0Sstefano_zampini Mat usedmat; 9615e3038f0Sstefano_zampini Mat_IS *matis; 9625e3038f0Sstefano_zampini const PetscInt *idxs; 9635e3038f0Sstefano_zampini 9645e3038f0Sstefano_zampini /* local IS for local NEST */ 9659566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, lr[i], stl, 1, &islrow[i])); 9665e3038f0Sstefano_zampini 9675e3038f0Sstefano_zampini /* l2gmap */ 9685e3038f0Sstefano_zampini j = 0; 9695e3038f0Sstefano_zampini usedmat = nest[i][j]; 9709e7b2b25Sstefano_zampini while (!usedmat && j < nc - 1) usedmat = nest[i][++j]; 97128b400f6SJacob Faibussowitsch PetscCheck(usedmat, comm, PETSC_ERR_SUP, "Cannot find valid row mat"); 9729e7b2b25Sstefano_zampini 9739e7b2b25Sstefano_zampini if (istrans[i * nc + j]) { 9749e7b2b25Sstefano_zampini Mat T; 9759566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(usedmat, &T)); 9769e7b2b25Sstefano_zampini usedmat = T; 9779e7b2b25Sstefano_zampini } 978f4f49eeaSPierre Jolivet matis = (Mat_IS *)usedmat->data; 9799566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isrow[i], &idxs)); 9809e7b2b25Sstefano_zampini if (istrans[i * nc + j]) { 9819566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->csf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 9829566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->csf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 9839e7b2b25Sstefano_zampini } else { 9849566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 9859566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 9869e7b2b25Sstefano_zampini } 9879566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(isrow[i], &idxs)); 9885e3038f0Sstefano_zampini stl += lr[i]; 9895e3038f0Sstefano_zampini } 9909566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(comm, 1, stl, l2gidxs, PETSC_OWN_POINTER, &rl2g)); 9915e3038f0Sstefano_zampini 9925e3038f0Sstefano_zampini /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */ 9935e3038f0Sstefano_zampini for (i = 0, stl = 0; i < nc; i++) stl += lc[i]; 9949566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(stl, &l2gidxs)); 9955b003df0Sstefano_zampini for (i = 0, stl = 0; i < nc; i++) { 9965e3038f0Sstefano_zampini Mat usedmat; 9975e3038f0Sstefano_zampini Mat_IS *matis; 9985e3038f0Sstefano_zampini const PetscInt *idxs; 9995e3038f0Sstefano_zampini 10005e3038f0Sstefano_zampini /* local IS for local NEST */ 10019566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, lc[i], stl, 1, &islcol[i])); 10025e3038f0Sstefano_zampini 10035e3038f0Sstefano_zampini /* l2gmap */ 10045e3038f0Sstefano_zampini j = 0; 10055e3038f0Sstefano_zampini usedmat = nest[j][i]; 10069e7b2b25Sstefano_zampini while (!usedmat && j < nr - 1) usedmat = nest[++j][i]; 100728b400f6SJacob Faibussowitsch PetscCheck(usedmat, comm, PETSC_ERR_SUP, "Cannot find valid column mat"); 10089e7b2b25Sstefano_zampini if (istrans[j * nc + i]) { 10099e7b2b25Sstefano_zampini Mat T; 10109566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(usedmat, &T)); 10119e7b2b25Sstefano_zampini usedmat = T; 10129e7b2b25Sstefano_zampini } 1013f4f49eeaSPierre Jolivet matis = (Mat_IS *)usedmat->data; 10149566063dSJacob Faibussowitsch PetscCall(ISGetIndices(iscol[i], &idxs)); 10159e7b2b25Sstefano_zampini if (istrans[j * nc + i]) { 10169566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 10179566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 10189e7b2b25Sstefano_zampini } else { 10199566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->csf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 10209566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->csf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 10219e7b2b25Sstefano_zampini } 10229566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(iscol[i], &idxs)); 10235e3038f0Sstefano_zampini stl += lc[i]; 10245e3038f0Sstefano_zampini } 10259566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(comm, 1, stl, l2gidxs, PETSC_OWN_POINTER, &cl2g)); 10265e3038f0Sstefano_zampini 10275e3038f0Sstefano_zampini /* Create MATIS */ 10289566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &B)); 10299566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N)); 10309566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(A, &rbs, &cbs)); 10319566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(B, rbs, cbs)); 10329566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATIS)); 10339566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(B, MATNEST)); 1034*4f58015eSStefano Zampini PetscCall(MatISSetAllowRepeated(B, PetscBool3ToBool(allow_repeated))); 10358546b261SStefano Zampini { /* hack : avoid setup of scatters */ 1036f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)B->data; 10378546b261SStefano Zampini matis->islocalref = PETSC_TRUE; 10388546b261SStefano Zampini } 10399566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B, rl2g, cl2g)); 10409566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 10419566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 10429566063dSJacob Faibussowitsch PetscCall(MatCreateNest(PETSC_COMM_SELF, nr, islrow, nc, islcol, snest, &lA)); 10439566063dSJacob Faibussowitsch PetscCall(MatNestSetVecType(lA, VECNEST)); 10449e7b2b25Sstefano_zampini for (i = 0; i < nr * nc; i++) { 104548a46eb9SPierre Jolivet if (istrans[i]) PetscCall(MatDestroy(&snest[i])); 10469e7b2b25Sstefano_zampini } 10479566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B, lA)); 10489566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lA)); 10498546b261SStefano Zampini { /* hack : setup of scatters done here */ 1050f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)B->data; 10518546b261SStefano Zampini 10528546b261SStefano Zampini matis->islocalref = PETSC_FALSE; 10539566063dSJacob Faibussowitsch PetscCall(MatISSetUpScatters_Private(B)); 10548546b261SStefano Zampini } 10559566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 10569566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 10575e3038f0Sstefano_zampini if (reuse == MAT_INPLACE_MATRIX) { 10589566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &B)); 10595e3038f0Sstefano_zampini } else { 10605e3038f0Sstefano_zampini *newmat = B; 10615e3038f0Sstefano_zampini } 10625e3038f0Sstefano_zampini } else { 10635e3038f0Sstefano_zampini if (lreuse) { 10649566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*newmat, &lA)); 10655e3038f0Sstefano_zampini for (i = 0; i < nr; i++) { 10665e3038f0Sstefano_zampini for (j = 0; j < nc; j++) { 10675e3038f0Sstefano_zampini if (snest[i * nc + j]) { 10689566063dSJacob Faibussowitsch PetscCall(MatNestSetSubMat(lA, i, j, snest[i * nc + j])); 106948a46eb9SPierre Jolivet if (istrans[i * nc + j]) PetscCall(MatDestroy(&snest[i * nc + j])); 10705e3038f0Sstefano_zampini } 10715e3038f0Sstefano_zampini } 10725e3038f0Sstefano_zampini } 10735e3038f0Sstefano_zampini } else { 10745b003df0Sstefano_zampini PetscInt stl; 10755b003df0Sstefano_zampini for (i = 0, stl = 0; i < nr; i++) { 10769566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, lr[i], stl, 1, &islrow[i])); 10775b003df0Sstefano_zampini stl += lr[i]; 10785e3038f0Sstefano_zampini } 10795b003df0Sstefano_zampini for (i = 0, stl = 0; i < nc; i++) { 10809566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, lc[i], stl, 1, &islcol[i])); 10815b003df0Sstefano_zampini stl += lc[i]; 10825e3038f0Sstefano_zampini } 10839566063dSJacob Faibussowitsch PetscCall(MatCreateNest(PETSC_COMM_SELF, nr, islrow, nc, islcol, snest, &lA)); 1084ab4d48faSStefano Zampini for (i = 0; i < nr * nc; i++) { 108548a46eb9SPierre Jolivet if (istrans[i]) PetscCall(MatDestroy(&snest[i])); 1086ab4d48faSStefano Zampini } 10879566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*newmat, lA)); 10889566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lA)); 10895e3038f0Sstefano_zampini } 10909566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*newmat, MAT_FINAL_ASSEMBLY)); 10919566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*newmat, MAT_FINAL_ASSEMBLY)); 10925e3038f0Sstefano_zampini } 10935e3038f0Sstefano_zampini 10945b003df0Sstefano_zampini /* Create local matrix in MATNEST format */ 10955b003df0Sstefano_zampini convert = PETSC_FALSE; 1096*4f58015eSStefano Zampini PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)A)->prefix, "-mat_is_convert_local_nest", &convert, NULL)); 10975b003df0Sstefano_zampini if (convert) { 10985b003df0Sstefano_zampini Mat M; 10995b003df0Sstefano_zampini MatISLocalFields lf; 11005b003df0Sstefano_zampini PetscContainer c; 11015b003df0Sstefano_zampini 11029566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*newmat, &lA)); 11039566063dSJacob Faibussowitsch PetscCall(MatConvert(lA, MATAIJ, MAT_INITIAL_MATRIX, &M)); 11049566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*newmat, M)); 11059566063dSJacob Faibussowitsch PetscCall(MatDestroy(&M)); 11065b003df0Sstefano_zampini 11075b003df0Sstefano_zampini /* attach local fields to the matrix */ 11089566063dSJacob Faibussowitsch PetscCall(PetscNew(&lf)); 11099566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nr, &lf->rf, nc, &lf->cf)); 11105b003df0Sstefano_zampini for (i = 0; i < nr; i++) { 11115b003df0Sstefano_zampini PetscInt n, st; 11125b003df0Sstefano_zampini 11139566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(islrow[i], &n)); 11149566063dSJacob Faibussowitsch PetscCall(ISStrideGetInfo(islrow[i], &st, NULL)); 11159566063dSJacob Faibussowitsch PetscCall(ISCreateStride(comm, n, st, 1, &lf->rf[i])); 11165b003df0Sstefano_zampini } 11175b003df0Sstefano_zampini for (i = 0; i < nc; i++) { 11185b003df0Sstefano_zampini PetscInt n, st; 11195b003df0Sstefano_zampini 11209566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(islcol[i], &n)); 11219566063dSJacob Faibussowitsch PetscCall(ISStrideGetInfo(islcol[i], &st, NULL)); 11229566063dSJacob Faibussowitsch PetscCall(ISCreateStride(comm, n, st, 1, &lf->cf[i])); 11235b003df0Sstefano_zampini } 11245b003df0Sstefano_zampini lf->nr = nr; 11255b003df0Sstefano_zampini lf->nc = nc; 1126f4f49eeaSPierre Jolivet PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)*newmat), &c)); 11279566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(c, lf)); 11289566063dSJacob Faibussowitsch PetscCall(PetscContainerSetUserDestroy(c, MatISContainerDestroyFields_Private)); 1129f4f49eeaSPierre Jolivet PetscCall(PetscObjectCompose((PetscObject)*newmat, "_convert_nest_lfields", (PetscObject)c)); 11309566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&c)); 11315b003df0Sstefano_zampini } 11325b003df0Sstefano_zampini 11335e3038f0Sstefano_zampini /* Free workspace */ 113448a46eb9SPierre Jolivet for (i = 0; i < nr; i++) PetscCall(ISDestroy(&islrow[i])); 113548a46eb9SPierre Jolivet for (i = 0; i < nc; i++) PetscCall(ISDestroy(&islcol[i])); 11369566063dSJacob Faibussowitsch PetscCall(PetscFree6(isrow, iscol, islrow, islcol, snest, istrans)); 11379566063dSJacob Faibussowitsch PetscCall(PetscFree2(lr, lc)); 11383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11395e3038f0Sstefano_zampini } 11405e3038f0Sstefano_zampini 1141d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r) 1142d71ae5a4SJacob Faibussowitsch { 1143ad219c80Sstefano_zampini Mat_IS *matis = (Mat_IS *)A->data; 1144ad219c80Sstefano_zampini Vec ll, rr; 1145ad219c80Sstefano_zampini const PetscScalar *Y, *X; 1146ad219c80Sstefano_zampini PetscScalar *x, *y; 1147ad219c80Sstefano_zampini 1148ad219c80Sstefano_zampini PetscFunctionBegin; 1149ad219c80Sstefano_zampini if (l) { 1150ad219c80Sstefano_zampini ll = matis->y; 11519566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(l, &Y)); 11529566063dSJacob Faibussowitsch PetscCall(VecGetArray(ll, &y)); 11539566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_SCALAR, Y, y, MPI_REPLACE)); 1154ad219c80Sstefano_zampini } else { 1155ad219c80Sstefano_zampini ll = NULL; 1156ad219c80Sstefano_zampini } 1157ad219c80Sstefano_zampini if (r) { 1158ad219c80Sstefano_zampini rr = matis->x; 11599566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(r, &X)); 11609566063dSJacob Faibussowitsch PetscCall(VecGetArray(rr, &x)); 11619566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->csf, MPIU_SCALAR, X, x, MPI_REPLACE)); 1162ad219c80Sstefano_zampini } else { 1163ad219c80Sstefano_zampini rr = NULL; 1164ad219c80Sstefano_zampini } 1165ad219c80Sstefano_zampini if (ll) { 11669566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_SCALAR, Y, y, MPI_REPLACE)); 11679566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(l, &Y)); 11689566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(ll, &y)); 1169ad219c80Sstefano_zampini } 1170ad219c80Sstefano_zampini if (rr) { 11719566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->csf, MPIU_SCALAR, X, x, MPI_REPLACE)); 11729566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(r, &X)); 11739566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(rr, &x)); 1174ad219c80Sstefano_zampini } 11759566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(matis->A, ll, rr)); 11763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1177ad219c80Sstefano_zampini } 1178ad219c80Sstefano_zampini 1179d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetInfo_IS(Mat A, MatInfoType flag, MatInfo *ginfo) 1180d71ae5a4SJacob Faibussowitsch { 11817fa8f2d3SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 11827fa8f2d3SStefano Zampini MatInfo info; 11833966268fSBarry Smith PetscLogDouble isend[6], irecv[6]; 11847fa8f2d3SStefano Zampini PetscInt bs; 11857fa8f2d3SStefano Zampini 11867fa8f2d3SStefano Zampini PetscFunctionBegin; 11879566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 1188a2ccb5f9Sstefano_zampini if (matis->A->ops->getinfo) { 11899566063dSJacob Faibussowitsch PetscCall(MatGetInfo(matis->A, MAT_LOCAL, &info)); 11907fa8f2d3SStefano Zampini isend[0] = info.nz_used; 11917fa8f2d3SStefano Zampini isend[1] = info.nz_allocated; 11927fa8f2d3SStefano Zampini isend[2] = info.nz_unneeded; 11937fa8f2d3SStefano Zampini isend[3] = info.memory; 11947fa8f2d3SStefano Zampini isend[4] = info.mallocs; 1195a2ccb5f9Sstefano_zampini } else { 1196a2ccb5f9Sstefano_zampini isend[0] = 0.; 1197a2ccb5f9Sstefano_zampini isend[1] = 0.; 1198a2ccb5f9Sstefano_zampini isend[2] = 0.; 1199a2ccb5f9Sstefano_zampini isend[3] = 0.; 1200a2ccb5f9Sstefano_zampini isend[4] = 0.; 1201a2ccb5f9Sstefano_zampini } 1202314ce898Sstefano_zampini isend[5] = matis->A->num_ass; 12037fa8f2d3SStefano Zampini if (flag == MAT_LOCAL) { 12047fa8f2d3SStefano Zampini ginfo->nz_used = isend[0]; 12057fa8f2d3SStefano Zampini ginfo->nz_allocated = isend[1]; 12067fa8f2d3SStefano Zampini ginfo->nz_unneeded = isend[2]; 12077fa8f2d3SStefano Zampini ginfo->memory = isend[3]; 12087fa8f2d3SStefano Zampini ginfo->mallocs = isend[4]; 1209314ce898Sstefano_zampini ginfo->assemblies = isend[5]; 12107fa8f2d3SStefano Zampini } else if (flag == MAT_GLOBAL_MAX) { 12111c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(isend, irecv, 6, MPIU_PETSCLOGDOUBLE, MPI_MAX, PetscObjectComm((PetscObject)A))); 12127fa8f2d3SStefano Zampini 12137fa8f2d3SStefano Zampini ginfo->nz_used = irecv[0]; 12147fa8f2d3SStefano Zampini ginfo->nz_allocated = irecv[1]; 12157fa8f2d3SStefano Zampini ginfo->nz_unneeded = irecv[2]; 12167fa8f2d3SStefano Zampini ginfo->memory = irecv[3]; 12177fa8f2d3SStefano Zampini ginfo->mallocs = irecv[4]; 1218314ce898Sstefano_zampini ginfo->assemblies = irecv[5]; 12197fa8f2d3SStefano Zampini } else if (flag == MAT_GLOBAL_SUM) { 12201c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(isend, irecv, 5, MPIU_PETSCLOGDOUBLE, MPI_SUM, PetscObjectComm((PetscObject)A))); 12217fa8f2d3SStefano Zampini 12227fa8f2d3SStefano Zampini ginfo->nz_used = irecv[0]; 12237fa8f2d3SStefano Zampini ginfo->nz_allocated = irecv[1]; 12247fa8f2d3SStefano Zampini ginfo->nz_unneeded = irecv[2]; 12257fa8f2d3SStefano Zampini ginfo->memory = irecv[3]; 12267fa8f2d3SStefano Zampini ginfo->mallocs = irecv[4]; 12277fa8f2d3SStefano Zampini ginfo->assemblies = A->num_ass; 12287fa8f2d3SStefano Zampini } 12297fa8f2d3SStefano Zampini ginfo->block_size = bs; 12307fa8f2d3SStefano Zampini ginfo->fill_ratio_given = 0; 12317fa8f2d3SStefano Zampini ginfo->fill_ratio_needed = 0; 12327fa8f2d3SStefano Zampini ginfo->factor_mallocs = 0; 12333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12345e3038f0Sstefano_zampini } 12355e3038f0Sstefano_zampini 1236d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatTranspose_IS(Mat A, MatReuse reuse, Mat *B) 1237d71ae5a4SJacob Faibussowitsch { 1238d7f69cd0SStefano Zampini Mat C, lC, lA; 1239d7f69cd0SStefano Zampini 1240d7f69cd0SStefano Zampini PetscFunctionBegin; 12417fb60732SBarry Smith if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *B)); 1242cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) { 1243cf37664fSBarry Smith ISLocalToGlobalMapping rl2g, cl2g; 1244*4f58015eSStefano Zampini PetscBool allow_repeated; 1245*4f58015eSStefano Zampini 12469566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 12479566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, A->cmap->n, A->rmap->n, A->cmap->N, A->rmap->N)); 12489566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(C, PetscAbs(A->cmap->bs), PetscAbs(A->rmap->bs))); 12499566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATIS)); 1250*4f58015eSStefano Zampini PetscCall(MatISGetAllowRepeated(A, &allow_repeated)); 1251*4f58015eSStefano Zampini PetscCall(MatISSetAllowRepeated(C, allow_repeated)); 12529566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(A, &rl2g, &cl2g)); 12539566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(C, cl2g, rl2g)); 1254e432b41dSStefano Zampini } else C = *B; 1255d7f69cd0SStefano Zampini 1256d7f69cd0SStefano Zampini /* perform local transposition */ 12579566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A, &lA)); 12589566063dSJacob Faibussowitsch PetscCall(MatTranspose(lA, MAT_INITIAL_MATRIX, &lC)); 12599566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(lC, lA->cmap->mapping, lA->rmap->mapping)); 12609566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(C, lC)); 12619566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lC)); 1262d7f69cd0SStefano Zampini 1263cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) { 1264d7f69cd0SStefano Zampini *B = C; 1265d7f69cd0SStefano Zampini } else { 12669566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(A, &C)); 1267d7f69cd0SStefano Zampini } 12689566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY)); 12699566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY)); 12703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1271d7f69cd0SStefano Zampini } 1272d7f69cd0SStefano Zampini 1273d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDiagonalSet_IS(Mat A, Vec D, InsertMode insmode) 1274d71ae5a4SJacob Faibussowitsch { 12753fd1c9e7SStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 12763fd1c9e7SStefano Zampini 12773fd1c9e7SStefano Zampini PetscFunctionBegin; 1278*4f58015eSStefano Zampini PetscCheck(!is->allow_repeated || insmode == ADD_VALUES, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "INSERT_VALUES with repeated entries not supported"); 12794b89b9cdSStefano Zampini if (D) { /* MatShift_IS pass D = NULL */ 12809566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, D, is->y, INSERT_VALUES, SCATTER_FORWARD)); 12819566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, D, is->y, INSERT_VALUES, SCATTER_FORWARD)); 12823fd1c9e7SStefano Zampini } 12839566063dSJacob Faibussowitsch PetscCall(VecPointwiseDivide(is->y, is->y, is->counter)); 12849566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(is->A, is->y, insmode)); 12853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12863fd1c9e7SStefano Zampini } 12873fd1c9e7SStefano Zampini 1288d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatShift_IS(Mat A, PetscScalar a) 1289d71ae5a4SJacob Faibussowitsch { 12904b89b9cdSStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 12913fd1c9e7SStefano Zampini 12923fd1c9e7SStefano Zampini PetscFunctionBegin; 12939566063dSJacob Faibussowitsch PetscCall(VecSet(is->y, a)); 12949566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet_IS(A, NULL, ADD_VALUES)); 12953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12963fd1c9e7SStefano Zampini } 12973fd1c9e7SStefano Zampini 1298d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) 1299d71ae5a4SJacob Faibussowitsch { 1300f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION], cols_l[MATIS_MAX_ENTRIES_INSERTION]; 1301f26d0771SStefano Zampini 1302f26d0771SStefano Zampini PetscFunctionBegin; 1303aed4548fSBarry 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); 13049566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(A->rmap->mapping, m, rows, rows_l)); 13059566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(A->cmap->mapping, n, cols, cols_l)); 13069566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal_IS(A, m, rows_l, n, cols_l, values, addv)); 13073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1308f26d0771SStefano Zampini } 1309f26d0771SStefano Zampini 1310d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) 1311d71ae5a4SJacob Faibussowitsch { 1312f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION], cols_l[MATIS_MAX_ENTRIES_INSERTION]; 1313f26d0771SStefano Zampini 1314f26d0771SStefano Zampini PetscFunctionBegin; 1315aed4548fSBarry 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); 13169566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(A->rmap->mapping, m, rows, rows_l)); 13179566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(A->cmap->mapping, n, cols, cols_l)); 13189566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlockedLocal_IS(A, m, rows_l, n, cols_l, values, addv)); 13193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1320f26d0771SStefano Zampini } 1321f26d0771SStefano Zampini 1322d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrix_IS(Mat mat, IS irow, IS icol, MatReuse scall, Mat *newmat) 1323d71ae5a4SJacob Faibussowitsch { 1324a8116848SStefano Zampini Mat locmat, newlocmat; 1325a8116848SStefano Zampini Mat_IS *newmatis; 1326a8116848SStefano Zampini const PetscInt *idxs; 1327a8116848SStefano Zampini PetscInt i, m, n; 1328a8116848SStefano Zampini 1329a8116848SStefano Zampini PetscFunctionBegin; 1330a8116848SStefano Zampini if (scall == MAT_REUSE_MATRIX) { 1331a8116848SStefano Zampini PetscBool ismatis; 1332a8116848SStefano Zampini 13339566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)*newmat, MATIS, &ismatis)); 133428b400f6SJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_ARG_WRONG, "Cannot reuse matrix! Not of MATIS type"); 1335a8116848SStefano Zampini newmatis = (Mat_IS *)(*newmat)->data; 133628b400f6SJacob Faibussowitsch PetscCheck(newmatis->getsub_ris, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_ARG_WRONG, "Cannot reuse matrix! Misses local row IS"); 133728b400f6SJacob Faibussowitsch PetscCheck(newmatis->getsub_cis, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_ARG_WRONG, "Cannot reuse matrix! Misses local col IS"); 1338a8116848SStefano Zampini } 1339a8116848SStefano Zampini /* irow and icol may not have duplicate entries */ 134076bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 134176bd3646SJed Brown Vec rtest, ltest; 134276bd3646SJed Brown const PetscScalar *array; 134376bd3646SJed Brown 13449566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(mat, <est, &rtest)); 13459566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(irow, &n)); 13469566063dSJacob Faibussowitsch PetscCall(ISGetIndices(irow, &idxs)); 134748a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(VecSetValue(rtest, idxs[i], 1.0, ADD_VALUES)); 13489566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(rtest)); 13499566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(rtest)); 13509566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(rtest, &n)); 13519566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(rtest, &m, NULL)); 13529566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(rtest, &array)); 1353aed4548fSBarry Smith for (i = 0; i < n; i++) PetscCheck(array[i] == 0. || array[i] == 1., PETSC_COMM_SELF, PETSC_ERR_SUP, "Index %" PetscInt_FMT " counted %" PetscInt_FMT " times! Irow may not have duplicate entries", i + m, (PetscInt)PetscRealPart(array[i])); 13549566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(rtest, &array)); 13559566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(irow, &idxs)); 13569566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(icol, &n)); 13579566063dSJacob Faibussowitsch PetscCall(ISGetIndices(icol, &idxs)); 135848a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(VecSetValue(ltest, idxs[i], 1.0, ADD_VALUES)); 13599566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(ltest)); 13609566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(ltest)); 13619566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(ltest, &n)); 13629566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(ltest, &m, NULL)); 13639566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(ltest, &array)); 1364aed4548fSBarry 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])); 13659566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(ltest, &array)); 13669566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(icol, &idxs)); 13679566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rtest)); 13689566063dSJacob Faibussowitsch PetscCall(VecDestroy(<est)); 136976bd3646SJed Brown } 1370a8116848SStefano Zampini if (scall == MAT_INITIAL_MATRIX) { 1371a8116848SStefano Zampini Mat_IS *matis = (Mat_IS *)mat->data; 1372a8116848SStefano Zampini ISLocalToGlobalMapping rl2g; 1373a8116848SStefano Zampini IS is; 1374a8116848SStefano Zampini PetscInt *lidxs, *lgidxs, *newgidxs; 1375306cf5c7SStefano Zampini PetscInt ll, newloc, irbs, icbs, arbs, acbs, rbs, cbs; 137694342113SStefano Zampini PetscBool cong; 1377a8116848SStefano Zampini MPI_Comm comm; 1378a8116848SStefano Zampini 13799566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 13809566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(mat, &arbs, &acbs)); 13819566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(irow, &irbs)); 13829566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(icol, &icbs)); 1383306cf5c7SStefano Zampini rbs = arbs == irbs ? irbs : 1; 1384306cf5c7SStefano Zampini cbs = acbs == icbs ? icbs : 1; 13859566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(irow, &m)); 13869566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(icol, &n)); 13879566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, newmat)); 13889566063dSJacob Faibussowitsch PetscCall(MatSetType(*newmat, MATIS)); 1389*4f58015eSStefano Zampini PetscCall(MatISSetAllowRepeated(*newmat, matis->allow_repeated)); 13909566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*newmat, m, n, PETSC_DECIDE, PETSC_DECIDE)); 13919566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(*newmat, rbs, cbs)); 1392a8116848SStefano Zampini /* communicate irow to their owners in the layout */ 13939566063dSJacob Faibussowitsch PetscCall(ISGetIndices(irow, &idxs)); 13949566063dSJacob Faibussowitsch PetscCall(PetscLayoutMapLocal(mat->rmap, m, idxs, &ll, &lidxs, &lgidxs)); 13959566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(irow, &idxs)); 13969566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata, matis->sf->nroots)); 1397a8116848SStefano Zampini for (i = 0; i < ll; i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i] + 1; 13989566063dSJacob Faibussowitsch PetscCall(PetscFree(lidxs)); 13999566063dSJacob Faibussowitsch PetscCall(PetscFree(lgidxs)); 14009566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 14019566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 14029371c9d4SSatish Balay for (i = 0, newloc = 0; i < matis->sf->nleaves; i++) 14039371c9d4SSatish Balay if (matis->sf_leafdata[i]) newloc++; 14049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newloc, &newgidxs)); 14059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newloc, &lidxs)); 14063d996552SStefano Zampini for (i = 0, newloc = 0; i < matis->sf->nleaves; i++) 1407a8116848SStefano Zampini if (matis->sf_leafdata[i]) { 1408a8116848SStefano Zampini lidxs[newloc] = i; 1409a8116848SStefano Zampini newgidxs[newloc++] = matis->sf_leafdata[i] - 1; 1410a8116848SStefano Zampini } 14119566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, newloc, newgidxs, PETSC_OWN_POINTER, &is)); 14129566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g)); 14139566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetBlockSize(rl2g, rbs)); 14149566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 1415a8116848SStefano Zampini /* local is to extract local submatrix */ 1416a8116848SStefano Zampini newmatis = (Mat_IS *)(*newmat)->data; 14179566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, newloc, lidxs, PETSC_OWN_POINTER, &newmatis->getsub_ris)); 14189566063dSJacob Faibussowitsch PetscCall(MatHasCongruentLayouts(mat, &cong)); 141994342113SStefano Zampini if (cong && irow == icol && matis->csf == matis->sf) { 14209566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*newmat, rl2g, rl2g)); 14219566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)newmatis->getsub_ris)); 1422a8116848SStefano Zampini newmatis->getsub_cis = newmatis->getsub_ris; 1423a8116848SStefano Zampini } else { 1424a8116848SStefano Zampini ISLocalToGlobalMapping cl2g; 1425a8116848SStefano Zampini 1426a8116848SStefano Zampini /* communicate icol to their owners in the layout */ 14279566063dSJacob Faibussowitsch PetscCall(ISGetIndices(icol, &idxs)); 14289566063dSJacob Faibussowitsch PetscCall(PetscLayoutMapLocal(mat->cmap, n, idxs, &ll, &lidxs, &lgidxs)); 14299566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(icol, &idxs)); 14309566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->csf_rootdata, matis->csf->nroots)); 1431a8116848SStefano Zampini for (i = 0; i < ll; i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i] + 1; 14329566063dSJacob Faibussowitsch PetscCall(PetscFree(lidxs)); 14339566063dSJacob Faibussowitsch PetscCall(PetscFree(lgidxs)); 14349566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->csf, MPIU_INT, matis->csf_rootdata, matis->csf_leafdata, MPI_REPLACE)); 14359566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->csf, MPIU_INT, matis->csf_rootdata, matis->csf_leafdata, MPI_REPLACE)); 14369371c9d4SSatish Balay for (i = 0, newloc = 0; i < matis->csf->nleaves; i++) 14379371c9d4SSatish Balay if (matis->csf_leafdata[i]) newloc++; 14389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newloc, &newgidxs)); 14399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newloc, &lidxs)); 14403d996552SStefano Zampini for (i = 0, newloc = 0; i < matis->csf->nleaves; i++) 1441a8116848SStefano Zampini if (matis->csf_leafdata[i]) { 1442a8116848SStefano Zampini lidxs[newloc] = i; 1443a8116848SStefano Zampini newgidxs[newloc++] = matis->csf_leafdata[i] - 1; 1444a8116848SStefano Zampini } 14459566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, newloc, newgidxs, PETSC_OWN_POINTER, &is)); 14469566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g)); 14479566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetBlockSize(cl2g, cbs)); 14489566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 1449a8116848SStefano Zampini /* local is to extract local submatrix */ 14509566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, newloc, lidxs, PETSC_OWN_POINTER, &newmatis->getsub_cis)); 14519566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*newmat, rl2g, cl2g)); 14529566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 1453a8116848SStefano Zampini } 14549566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 1455a8116848SStefano Zampini } else { 14569566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*newmat, &newlocmat)); 1457a8116848SStefano Zampini } 14589566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(mat, &locmat)); 1459a8116848SStefano Zampini newmatis = (Mat_IS *)(*newmat)->data; 14609566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(locmat, newmatis->getsub_ris, newmatis->getsub_cis, scall, &newlocmat)); 1461a8116848SStefano Zampini if (scall == MAT_INITIAL_MATRIX) { 14629566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*newmat, newlocmat)); 14639566063dSJacob Faibussowitsch PetscCall(MatDestroy(&newlocmat)); 1464a8116848SStefano Zampini } 14659566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*newmat, MAT_FINAL_ASSEMBLY)); 14669566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*newmat, MAT_FINAL_ASSEMBLY)); 14673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1468a8116848SStefano Zampini } 1469a8116848SStefano Zampini 1470d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCopy_IS(Mat A, Mat B, MatStructure str) 1471d71ae5a4SJacob Faibussowitsch { 14722b404112SStefano Zampini Mat_IS *a = (Mat_IS *)A->data, *b; 14732b404112SStefano Zampini PetscBool ismatis; 14742b404112SStefano Zampini 14752b404112SStefano Zampini PetscFunctionBegin; 14769566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)B, MATIS, &ismatis)); 147728b400f6SJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Need to be implemented"); 14782b404112SStefano Zampini b = (Mat_IS *)B->data; 14799566063dSJacob Faibussowitsch PetscCall(MatCopy(a->A, b->A, str)); 14809566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)B)); 14813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14822b404112SStefano Zampini } 14832b404112SStefano Zampini 1484d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_IS(Mat A, PetscBool *missing, PetscInt *d) 1485d71ae5a4SJacob Faibussowitsch { 1486527b2640SStefano Zampini Vec v; 1487527b2640SStefano Zampini const PetscScalar *array; 1488527b2640SStefano Zampini PetscInt i, n; 14896bd84002SStefano Zampini 14906bd84002SStefano Zampini PetscFunctionBegin; 1491527b2640SStefano Zampini *missing = PETSC_FALSE; 14929566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, NULL, &v)); 14939566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(A, v)); 14949566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 14959566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &array)); 14969371c9d4SSatish Balay for (i = 0; i < n; i++) 14979371c9d4SSatish Balay if (array[i] == 0.) break; 14989566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &array)); 14999566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 1500527b2640SStefano Zampini if (i != n) *missing = PETSC_TRUE; 1501527b2640SStefano Zampini if (d) { 1502527b2640SStefano Zampini *d = -1; 1503527b2640SStefano Zampini if (*missing) { 1504527b2640SStefano Zampini PetscInt rstart; 15059566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rstart, NULL)); 1506527b2640SStefano Zampini *d = i + rstart; 1507527b2640SStefano Zampini } 1508527b2640SStefano Zampini } 15093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15106bd84002SStefano Zampini } 15116bd84002SStefano Zampini 1512d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISSetUpSF_IS(Mat B) 1513d71ae5a4SJacob Faibussowitsch { 1514f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)B->data; 151528f4e0baSStefano Zampini const PetscInt *gidxs; 15164f2d7cafSStefano Zampini PetscInt nleaves; 151728f4e0baSStefano Zampini 151828f4e0baSStefano Zampini PetscFunctionBegin; 15193ba16761SJacob Faibussowitsch if (matis->sf) PetscFunctionReturn(PETSC_SUCCESS); 15209566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)B), &matis->sf)); 15219566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->rmapping, &gidxs)); 15229566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->rmapping, &nleaves)); 15239566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(matis->sf, B->rmap, nleaves, NULL, PETSC_OWN_POINTER, gidxs)); 15249566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->rmapping, &gidxs)); 15259566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(matis->sf->nroots, &matis->sf_rootdata, matis->sf->nleaves, &matis->sf_leafdata)); 1526e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { /* setup SF for columns */ 15279566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->cmapping, &nleaves)); 15289566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)B), &matis->csf)); 15299566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->cmapping, &gidxs)); 15309566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(matis->csf, B->cmap, nleaves, NULL, PETSC_OWN_POINTER, gidxs)); 15319566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->cmapping, &gidxs)); 15329566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(matis->csf->nroots, &matis->csf_rootdata, matis->csf->nleaves, &matis->csf_leafdata)); 1533a8116848SStefano Zampini } else { 1534a8116848SStefano Zampini matis->csf = matis->sf; 1535a8116848SStefano Zampini matis->csf_leafdata = matis->sf_leafdata; 1536a8116848SStefano Zampini matis->csf_rootdata = matis->sf_rootdata; 1537a8116848SStefano Zampini } 15383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 153928f4e0baSStefano Zampini } 15402e1947a5SStefano Zampini 1541eb82efa4SStefano Zampini /*@ 1542*4f58015eSStefano Zampini MatISGetAllowRepeated - Get the flag to allow repeated entries in the local to global map 1543*4f58015eSStefano Zampini 1544*4f58015eSStefano Zampini Not Collective 1545*4f58015eSStefano Zampini 1546*4f58015eSStefano Zampini Input Parameter: 1547*4f58015eSStefano Zampini . A - the matrix 1548*4f58015eSStefano Zampini 1549*4f58015eSStefano Zampini Output Parameter: 1550*4f58015eSStefano Zampini . flg - the boolean flag 1551*4f58015eSStefano Zampini 1552*4f58015eSStefano Zampini Level: intermediate 1553*4f58015eSStefano Zampini 1554*4f58015eSStefano Zampini .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateIS()`, `MatSetLocalToGlobalMapping()`, `MatISSetAllowRepeated()` 1555*4f58015eSStefano Zampini @*/ 1556*4f58015eSStefano Zampini PetscErrorCode MatISGetAllowRepeated(Mat A, PetscBool *flg) 1557*4f58015eSStefano Zampini { 1558*4f58015eSStefano Zampini PetscBool ismatis; 1559*4f58015eSStefano Zampini 1560*4f58015eSStefano Zampini PetscFunctionBegin; 1561*4f58015eSStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1562*4f58015eSStefano Zampini PetscAssertPointer(flg, 2); 1563*4f58015eSStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)A, MATIS, &ismatis)); 1564*4f58015eSStefano Zampini PetscCheck(ismatis, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)A)->type_name); 1565*4f58015eSStefano Zampini *flg = ((Mat_IS *)A->data)->allow_repeated; 1566*4f58015eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1567*4f58015eSStefano Zampini } 1568*4f58015eSStefano Zampini 1569*4f58015eSStefano Zampini /*@ 1570*4f58015eSStefano Zampini MatISSetAllowRepeated - Set the flag to allow repeated entries in the local to global map 1571*4f58015eSStefano Zampini 1572*4f58015eSStefano Zampini Logically Collective 1573*4f58015eSStefano Zampini 1574*4f58015eSStefano Zampini Input Parameters: 1575*4f58015eSStefano Zampini + A - the matrix 1576*4f58015eSStefano Zampini - flg - the boolean flag 1577*4f58015eSStefano Zampini 1578*4f58015eSStefano Zampini Level: intermediate 1579*4f58015eSStefano Zampini 1580*4f58015eSStefano Zampini Notes: 1581*4f58015eSStefano Zampini The default value is `PETSC_FALSE`. 1582*4f58015eSStefano Zampini When called AFTER calling `MatSetLocalToGlobalMapping()` it will recreate the local matrices 1583*4f58015eSStefano Zampini if `flg` is different from the previously set value. 1584*4f58015eSStefano Zampini Specifically, when `flg` is true it will just recreate the local matrices, while if 1585*4f58015eSStefano Zampini `flg` is false will assemble the local matrices summing up repeated entries. 1586*4f58015eSStefano Zampini 1587*4f58015eSStefano Zampini .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateIS()`, `MatSetLocalToGlobalMapping()`, `MatISGetAllowRepeated()` 1588*4f58015eSStefano Zampini @*/ 1589*4f58015eSStefano Zampini PetscErrorCode MatISSetAllowRepeated(Mat A, PetscBool flg) 1590*4f58015eSStefano Zampini { 1591*4f58015eSStefano Zampini PetscFunctionBegin; 1592*4f58015eSStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1593*4f58015eSStefano Zampini PetscValidType(A, 1); 1594*4f58015eSStefano Zampini PetscValidLogicalCollectiveBool(A, flg, 2); 1595*4f58015eSStefano Zampini PetscTryMethod(A, "MatISSetAllowRepeated_C", (Mat, PetscBool), (A, flg)); 1596*4f58015eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1597*4f58015eSStefano Zampini } 1598*4f58015eSStefano Zampini 1599*4f58015eSStefano Zampini static PetscErrorCode MatISSetAllowRepeated_IS(Mat A, PetscBool flg) 1600*4f58015eSStefano Zampini { 1601*4f58015eSStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 1602*4f58015eSStefano Zampini Mat lA = NULL; 1603*4f58015eSStefano Zampini ISLocalToGlobalMapping lrmap, lcmap; 1604*4f58015eSStefano Zampini 1605*4f58015eSStefano Zampini PetscFunctionBegin; 1606*4f58015eSStefano Zampini if (flg == matis->allow_repeated) PetscFunctionReturn(PETSC_SUCCESS); 1607*4f58015eSStefano Zampini if (!matis->A) { /* matrix has not been preallocated yet */ 1608*4f58015eSStefano Zampini matis->allow_repeated = flg; 1609*4f58015eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1610*4f58015eSStefano Zampini } 1611*4f58015eSStefano Zampini PetscCheck(!matis->islocalref, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not implemented for local references"); 1612*4f58015eSStefano Zampini if (matis->allow_repeated) { /* we will assemble the old local matrix if needed */ 1613*4f58015eSStefano Zampini lA = matis->A; 1614*4f58015eSStefano Zampini PetscCall(PetscObjectReference((PetscObject)lA)); 1615*4f58015eSStefano Zampini } 1616*4f58015eSStefano Zampini /* In case flg is True, we only recreate the local matrix */ 1617*4f58015eSStefano Zampini matis->allow_repeated = flg; 1618*4f58015eSStefano Zampini PetscCall(MatSetLocalToGlobalMapping(A, A->rmap->mapping, A->cmap->mapping)); 1619*4f58015eSStefano Zampini if (lA) { /* assemble previous local matrix if needed */ 1620*4f58015eSStefano Zampini Mat nA = matis->A; 1621*4f58015eSStefano Zampini 1622*4f58015eSStefano Zampini PetscCall(MatGetLocalToGlobalMapping(nA, &lrmap, &lcmap)); 1623*4f58015eSStefano Zampini if (!lrmap && !lcmap) { 1624*4f58015eSStefano Zampini PetscCall(MatISSetLocalMat(A, lA)); 1625*4f58015eSStefano Zampini } else { 1626*4f58015eSStefano Zampini Mat P = NULL, R = NULL; 1627*4f58015eSStefano Zampini MatProductType ptype; 1628*4f58015eSStefano Zampini 1629*4f58015eSStefano Zampini if (lrmap == lcmap) { 1630*4f58015eSStefano Zampini ptype = MATPRODUCT_PtAP; 1631*4f58015eSStefano Zampini PetscCall(MatCreateFromISLocalToGlobalMapping(lcmap, nA, PETSC_TRUE, PETSC_FALSE, NULL, &P)); 1632*4f58015eSStefano Zampini PetscCall(MatProductCreate(lA, P, NULL, &nA)); 1633*4f58015eSStefano Zampini } else { 1634*4f58015eSStefano Zampini if (lcmap) PetscCall(MatCreateFromISLocalToGlobalMapping(lcmap, nA, PETSC_TRUE, PETSC_FALSE, NULL, &P)); 1635*4f58015eSStefano Zampini if (lrmap) PetscCall(MatCreateFromISLocalToGlobalMapping(lrmap, nA, PETSC_FALSE, PETSC_TRUE, NULL, &R)); 1636*4f58015eSStefano Zampini if (R && P) { 1637*4f58015eSStefano Zampini ptype = MATPRODUCT_ABC; 1638*4f58015eSStefano Zampini PetscCall(MatProductCreate(R, lA, P, &nA)); 1639*4f58015eSStefano Zampini } else if (R) { 1640*4f58015eSStefano Zampini ptype = MATPRODUCT_AB; 1641*4f58015eSStefano Zampini PetscCall(MatProductCreate(R, lA, NULL, &nA)); 1642*4f58015eSStefano Zampini } else { 1643*4f58015eSStefano Zampini ptype = MATPRODUCT_AB; 1644*4f58015eSStefano Zampini PetscCall(MatProductCreate(lA, P, NULL, &nA)); 1645*4f58015eSStefano Zampini } 1646*4f58015eSStefano Zampini } 1647*4f58015eSStefano Zampini PetscCall(MatProductSetType(nA, ptype)); 1648*4f58015eSStefano Zampini PetscCall(MatProductSetFromOptions(nA)); 1649*4f58015eSStefano Zampini PetscCall(MatProductSymbolic(nA)); 1650*4f58015eSStefano Zampini PetscCall(MatProductNumeric(nA)); 1651*4f58015eSStefano Zampini PetscCall(MatProductClear(nA)); 1652*4f58015eSStefano Zampini PetscCall(MatConvert(nA, matis->lmattype, MAT_INPLACE_MATRIX, &nA)); 1653*4f58015eSStefano Zampini PetscCall(MatISSetLocalMat(A, nA)); 1654*4f58015eSStefano Zampini PetscCall(MatDestroy(&nA)); 1655*4f58015eSStefano Zampini PetscCall(MatDestroy(&P)); 1656*4f58015eSStefano Zampini PetscCall(MatDestroy(&R)); 1657*4f58015eSStefano Zampini } 1658*4f58015eSStefano Zampini } 1659*4f58015eSStefano Zampini PetscCall(MatDestroy(&lA)); 1660*4f58015eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1661*4f58015eSStefano Zampini } 1662*4f58015eSStefano Zampini 1663*4f58015eSStefano Zampini /*@ 16642ef1f0ffSBarry Smith MatISStoreL2L - Store local-to-local operators during the Galerkin process of computing `MatPtAP()` 166575d48cdbSStefano Zampini 1666*4f58015eSStefano Zampini Logically Collective 166775d48cdbSStefano Zampini 166875d48cdbSStefano Zampini Input Parameters: 166975d48cdbSStefano Zampini + A - the matrix 167075d48cdbSStefano Zampini - store - the boolean flag 167175d48cdbSStefano Zampini 167275d48cdbSStefano Zampini Level: advanced 167375d48cdbSStefano Zampini 16741cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateIS()`, `MatISSetPreallocation()`, `MatPtAP()` 167575d48cdbSStefano Zampini @*/ 1676d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISStoreL2L(Mat A, PetscBool store) 1677d71ae5a4SJacob Faibussowitsch { 167875d48cdbSStefano Zampini PetscFunctionBegin; 167975d48cdbSStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 168075d48cdbSStefano Zampini PetscValidType(A, 1); 168175d48cdbSStefano Zampini PetscValidLogicalCollectiveBool(A, store, 2); 1682cac4c232SBarry Smith PetscTryMethod(A, "MatISStoreL2L_C", (Mat, PetscBool), (A, store)); 16833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 168475d48cdbSStefano Zampini } 168575d48cdbSStefano Zampini 1686d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISStoreL2L_IS(Mat A, PetscBool store) 1687d71ae5a4SJacob Faibussowitsch { 1688f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)A->data; 168975d48cdbSStefano Zampini 169075d48cdbSStefano Zampini PetscFunctionBegin; 169175d48cdbSStefano Zampini matis->storel2l = store; 169248a46eb9SPierre Jolivet if (!store) PetscCall(PetscObjectCompose((PetscObject)(A), "_MatIS_PtAP_l2l", NULL)); 16933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 169475d48cdbSStefano Zampini } 169575d48cdbSStefano Zampini 169675d48cdbSStefano Zampini /*@ 1697f03112d0SStefano Zampini MatISFixLocalEmpty - Compress out zero local rows from the local matrices 1698f03112d0SStefano Zampini 1699*4f58015eSStefano Zampini Logically Collective 1700f03112d0SStefano Zampini 1701f03112d0SStefano Zampini Input Parameters: 1702f03112d0SStefano Zampini + A - the matrix 1703f03112d0SStefano Zampini - fix - the boolean flag 1704f03112d0SStefano Zampini 1705f03112d0SStefano Zampini Level: advanced 1706f03112d0SStefano Zampini 170711a5261eSBarry Smith Note: 17082fe279fdSBarry Smith When `fix` is `PETSC_TRUE`, new local matrices and l2g maps are generated during the final assembly process. 1709f03112d0SStefano Zampini 17101cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatCreate()`, `MatCreateIS()`, `MatISSetPreallocation()`, `MatAssemblyEnd()`, `MAT_FINAL_ASSEMBLY` 1711f03112d0SStefano Zampini @*/ 1712d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISFixLocalEmpty(Mat A, PetscBool fix) 1713d71ae5a4SJacob Faibussowitsch { 1714f03112d0SStefano Zampini PetscFunctionBegin; 1715f03112d0SStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1716f03112d0SStefano Zampini PetscValidType(A, 1); 1717f03112d0SStefano Zampini PetscValidLogicalCollectiveBool(A, fix, 2); 1718cac4c232SBarry Smith PetscTryMethod(A, "MatISFixLocalEmpty_C", (Mat, PetscBool), (A, fix)); 17193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1720f03112d0SStefano Zampini } 1721f03112d0SStefano Zampini 1722d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISFixLocalEmpty_IS(Mat A, PetscBool fix) 1723d71ae5a4SJacob Faibussowitsch { 1724f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)A->data; 1725f03112d0SStefano Zampini 1726f03112d0SStefano Zampini PetscFunctionBegin; 1727f03112d0SStefano Zampini matis->locempty = fix; 17283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1729f03112d0SStefano Zampini } 1730f03112d0SStefano Zampini 1731f03112d0SStefano Zampini /*@ 173211a5261eSBarry Smith MatISSetPreallocation - Preallocates memory for a `MATIS` parallel matrix. 1733a88811baSStefano Zampini 1734d083f849SBarry Smith Collective 1735a88811baSStefano Zampini 1736a88811baSStefano Zampini Input Parameters: 1737a88811baSStefano Zampini + B - the matrix 1738a88811baSStefano Zampini . d_nz - number of nonzeros per row in DIAGONAL portion of local submatrix 1739a88811baSStefano Zampini (same value is used for all local rows) 1740a88811baSStefano Zampini . d_nnz - array containing the number of nonzeros in the various rows of the 1741a88811baSStefano Zampini DIAGONAL portion of the local submatrix (possibly different for each row) 17422ef1f0ffSBarry Smith or `NULL`, if `d_nz` is used to specify the nonzero structure. 17432ef1f0ffSBarry Smith The size of this array is equal to the number of local rows, i.e `m`. 1744a88811baSStefano Zampini For matrices that will be factored, you must leave room for (and set) 1745a88811baSStefano Zampini the diagonal entry even if it is zero. 1746a88811baSStefano Zampini . o_nz - number of nonzeros per row in the OFF-DIAGONAL portion of local 1747a88811baSStefano Zampini submatrix (same value is used for all local rows). 1748a88811baSStefano Zampini - o_nnz - array containing the number of nonzeros in the various rows of the 1749a88811baSStefano Zampini OFF-DIAGONAL portion of the local submatrix (possibly different for 17502ef1f0ffSBarry Smith each row) or `NULL`, if `o_nz` is used to specify the nonzero 1751a88811baSStefano Zampini structure. The size of this array is equal to the number 17522ef1f0ffSBarry Smith of local rows, i.e `m`. 1753a88811baSStefano Zampini 1754a88811baSStefano Zampini If the *_nnz parameter is given then the *_nz parameter is ignored 1755a88811baSStefano Zampini 1756a88811baSStefano Zampini Level: intermediate 1757a88811baSStefano Zampini 175811a5261eSBarry Smith Note: 175911a5261eSBarry Smith This function has the same interface as the `MATMPIAIJ` preallocation routine in order to simplify the transition 176011a5261eSBarry Smith from the asssembled format to the unassembled one. It overestimates the preallocation of `MATIS` local 1761a88811baSStefano Zampini matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects. 1762a88811baSStefano Zampini 17631cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateIS()`, `MatMPIAIJSetPreallocation()`, `MatISGetLocalMat()`, `MATIS` 1764a88811baSStefano Zampini @*/ 1765d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISSetPreallocation(Mat B, PetscInt d_nz, const PetscInt d_nnz[], PetscInt o_nz, const PetscInt o_nnz[]) 1766d71ae5a4SJacob Faibussowitsch { 17672e1947a5SStefano Zampini PetscFunctionBegin; 17682e1947a5SStefano Zampini PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 17692e1947a5SStefano Zampini PetscValidType(B, 1); 1770cac4c232SBarry Smith PetscTryMethod(B, "MatISSetPreallocation_C", (Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]), (B, d_nz, d_nnz, o_nz, o_nnz)); 17713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17722e1947a5SStefano Zampini } 17732e1947a5SStefano Zampini 1774844bd0d7SStefano Zampini /* this is used by DMDA */ 1775d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatISSetPreallocation_IS(Mat B, PetscInt d_nz, const PetscInt d_nnz[], PetscInt o_nz, const PetscInt o_nnz[]) 1776d71ae5a4SJacob Faibussowitsch { 1777f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)B->data; 177828f4e0baSStefano Zampini PetscInt bs, i, nlocalcols; 17792e1947a5SStefano Zampini 17802e1947a5SStefano Zampini PetscFunctionBegin; 17819566063dSJacob Faibussowitsch PetscCall(MatSetUp(B)); 17829371c9d4SSatish Balay if (!d_nnz) 17839371c9d4SSatish Balay for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] = d_nz; 17849371c9d4SSatish Balay else 17859371c9d4SSatish Balay for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] = d_nnz[i]; 17864f2d7cafSStefano Zampini 17879371c9d4SSatish Balay if (!o_nnz) 17889371c9d4SSatish Balay for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] += o_nz; 17899371c9d4SSatish Balay else 17909371c9d4SSatish Balay for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] += o_nnz[i]; 17914f2d7cafSStefano Zampini 17929566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 17939566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, NULL, &nlocalcols)); 17949566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(matis->A, &bs)); 17959566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 17964f2d7cafSStefano Zampini 17974f2d7cafSStefano Zampini for (i = 0; i < matis->sf->nleaves; i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i], nlocalcols); 17989566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(matis->A, 0, matis->sf_leafdata)); 17990f2f62c7SStefano Zampini #if defined(PETSC_HAVE_HYPRE) 18009566063dSJacob Faibussowitsch PetscCall(MatHYPRESetPreallocation(matis->A, 0, matis->sf_leafdata, 0, NULL)); 18010f2f62c7SStefano Zampini #endif 18024f2d7cafSStefano Zampini 1803fc989267SStefano Zampini for (i = 0; i < matis->sf->nleaves / bs; i++) { 1804fc989267SStefano Zampini PetscInt b; 1805fc989267SStefano Zampini 1806fc989267SStefano Zampini matis->sf_leafdata[i] = matis->sf_leafdata[i * bs] / bs; 1807ad540459SPierre Jolivet for (b = 1; b < bs; b++) matis->sf_leafdata[i] = PetscMax(matis->sf_leafdata[i], matis->sf_leafdata[i * bs + b] / bs); 1808fc989267SStefano Zampini } 18099566063dSJacob Faibussowitsch PetscCall(MatSeqBAIJSetPreallocation(matis->A, bs, 0, matis->sf_leafdata)); 18104f2d7cafSStefano Zampini 181100a59248SStefano Zampini nlocalcols /= bs; 181200a59248SStefano Zampini for (i = 0; i < matis->sf->nleaves / bs; i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i], nlocalcols - i); 18139566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(matis->A, bs, 0, matis->sf_leafdata)); 18140f2f62c7SStefano Zampini 18150f2f62c7SStefano Zampini /* for other matrix types */ 18169566063dSJacob Faibussowitsch PetscCall(MatSetUp(matis->A)); 18173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18182e1947a5SStefano Zampini } 1819b4319ba4SBarry Smith 1820d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce) 1821d71ae5a4SJacob Faibussowitsch { 1822f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)A->data; 18233927de2eSStefano Zampini PetscInt *my_dnz, *my_onz, *dnz, *onz, *mat_ranges, *row_ownership; 1824ecf5a873SStefano Zampini const PetscInt *global_indices_r, *global_indices_c; 18253927de2eSStefano Zampini PetscInt i, j, bs, rows, cols; 18263927de2eSStefano Zampini PetscInt lrows, lcols; 18273927de2eSStefano Zampini PetscInt local_rows, local_cols; 1828f03112d0SStefano Zampini PetscMPIInt size; 18293927de2eSStefano Zampini PetscBool isdense, issbaij; 18303927de2eSStefano Zampini 18313927de2eSStefano Zampini PetscFunctionBegin; 18329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 18339566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &rows, &cols)); 18349566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 18359566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, &local_rows, &local_cols)); 18369566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQDENSE, &isdense)); 18379566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQSBAIJ, &issbaij)); 18389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->rmapping, &global_indices_r)); 1839e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { 18409566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->cmapping, &global_indices_c)); 18410dfc91b7SStefano Zampini } else global_indices_c = global_indices_r; 1842ecf5a873SStefano Zampini 18439566063dSJacob Faibussowitsch if (issbaij) PetscCall(MatGetRowUpperTriangular(matis->A)); 18443927de2eSStefano Zampini /* 1845ecf5a873SStefano Zampini An SF reduce is needed to sum up properly on shared rows. 18463927de2eSStefano Zampini Note that generally preallocation is not exact, since it overestimates nonzeros 18473927de2eSStefano Zampini */ 18489566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(A, &lrows, &lcols)); 1849d0609cedSBarry Smith MatPreallocateBegin(PetscObjectComm((PetscObject)A), lrows, lcols, dnz, onz); 18503927de2eSStefano Zampini /* All processes need to compute entire row ownership */ 18519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(rows, &row_ownership)); 18529566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRanges(A, (const PetscInt **)&mat_ranges)); 1853f03112d0SStefano Zampini for (i = 0; i < size; i++) { 18545f80ce2aSJacob Faibussowitsch for (j = mat_ranges[i]; j < mat_ranges[i + 1]; j++) row_ownership[j] = i; 18553927de2eSStefano Zampini } 18569566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangesColumn(A, (const PetscInt **)&mat_ranges)); 18573927de2eSStefano Zampini 18583927de2eSStefano Zampini /* 18593927de2eSStefano Zampini my_dnz and my_onz contains exact contribution to preallocation from each local mat 18603927de2eSStefano Zampini then, they will be summed up properly. This way, preallocation is always sufficient 18613927de2eSStefano Zampini */ 18629566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(local_rows, &my_dnz, local_rows, &my_onz)); 18633927de2eSStefano Zampini /* preallocation as a MATAIJ */ 18643927de2eSStefano Zampini if (isdense) { /* special case for dense local matrices */ 18653927de2eSStefano Zampini for (i = 0; i < local_rows; i++) { 186612dfadf8SStefano Zampini PetscInt owner = row_ownership[global_indices_r[i]]; 186712dfadf8SStefano Zampini for (j = 0; j < local_cols; j++) { 1868ecf5a873SStefano Zampini PetscInt index_col = global_indices_c[j]; 18693927de2eSStefano Zampini if (index_col > mat_ranges[owner] - 1 && index_col < mat_ranges[owner + 1]) { /* diag block */ 18703927de2eSStefano Zampini my_dnz[i] += 1; 18713927de2eSStefano Zampini } else { /* offdiag block */ 18723927de2eSStefano Zampini my_onz[i] += 1; 18733927de2eSStefano Zampini } 18743927de2eSStefano Zampini } 18753927de2eSStefano Zampini } 1876bb1015c3SStefano Zampini } else if (matis->A->ops->getrowij) { 1877bb1015c3SStefano Zampini const PetscInt *ii, *jj, *jptr; 1878bb1015c3SStefano Zampini PetscBool done; 18799566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(matis->A, 0, PETSC_FALSE, PETSC_FALSE, &local_rows, &ii, &jj, &done)); 1880f4f49eeaSPierre Jolivet PetscCheck(done, PetscObjectComm((PetscObject)matis->A), PETSC_ERR_PLIB, "Error in MatGetRowIJ"); 1881bb1015c3SStefano Zampini jptr = jj; 1882bb1015c3SStefano Zampini for (i = 0; i < local_rows; i++) { 1883bb1015c3SStefano Zampini PetscInt index_row = global_indices_r[i]; 1884bb1015c3SStefano Zampini for (j = 0; j < ii[i + 1] - ii[i]; j++, jptr++) { 1885bb1015c3SStefano Zampini PetscInt owner = row_ownership[index_row]; 1886bb1015c3SStefano Zampini PetscInt index_col = global_indices_c[*jptr]; 1887bb1015c3SStefano Zampini if (index_col > mat_ranges[owner] - 1 && index_col < mat_ranges[owner + 1]) { /* diag block */ 1888bb1015c3SStefano Zampini my_dnz[i] += 1; 1889bb1015c3SStefano Zampini } else { /* offdiag block */ 1890bb1015c3SStefano Zampini my_onz[i] += 1; 1891bb1015c3SStefano Zampini } 1892bb1015c3SStefano Zampini /* same as before, interchanging rows and cols */ 1893bb1015c3SStefano Zampini if (issbaij && index_col != index_row) { 1894bb1015c3SStefano Zampini owner = row_ownership[index_col]; 1895bb1015c3SStefano Zampini if (index_row > mat_ranges[owner] - 1 && index_row < mat_ranges[owner + 1]) { 1896bb1015c3SStefano Zampini my_dnz[*jptr] += 1; 1897bb1015c3SStefano Zampini } else { 1898bb1015c3SStefano Zampini my_onz[*jptr] += 1; 1899bb1015c3SStefano Zampini } 1900bb1015c3SStefano Zampini } 1901bb1015c3SStefano Zampini } 1902bb1015c3SStefano Zampini } 19039566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(matis->A, 0, PETSC_FALSE, PETSC_FALSE, &local_rows, &ii, &jj, &done)); 1904f4f49eeaSPierre Jolivet PetscCheck(done, PetscObjectComm((PetscObject)matis->A), PETSC_ERR_PLIB, "Error in MatRestoreRowIJ"); 1905bb1015c3SStefano Zampini } else { /* loop over rows and use MatGetRow */ 19063927de2eSStefano Zampini for (i = 0; i < local_rows; i++) { 19073927de2eSStefano Zampini const PetscInt *cols; 1908ecf5a873SStefano Zampini PetscInt ncols, index_row = global_indices_r[i]; 19099566063dSJacob Faibussowitsch PetscCall(MatGetRow(matis->A, i, &ncols, &cols, NULL)); 19103927de2eSStefano Zampini for (j = 0; j < ncols; j++) { 19113927de2eSStefano Zampini PetscInt owner = row_ownership[index_row]; 1912ecf5a873SStefano Zampini PetscInt index_col = global_indices_c[cols[j]]; 19133927de2eSStefano Zampini if (index_col > mat_ranges[owner] - 1 && index_col < mat_ranges[owner + 1]) { /* diag block */ 19143927de2eSStefano Zampini my_dnz[i] += 1; 19153927de2eSStefano Zampini } else { /* offdiag block */ 19163927de2eSStefano Zampini my_onz[i] += 1; 19173927de2eSStefano Zampini } 19183927de2eSStefano Zampini /* same as before, interchanging rows and cols */ 1919d9a9e74cSStefano Zampini if (issbaij && index_col != index_row) { 19203927de2eSStefano Zampini owner = row_ownership[index_col]; 19213927de2eSStefano Zampini if (index_row > mat_ranges[owner] - 1 && index_row < mat_ranges[owner + 1]) { 1922d9a9e74cSStefano Zampini my_dnz[cols[j]] += 1; 19233927de2eSStefano Zampini } else { 1924d9a9e74cSStefano Zampini my_onz[cols[j]] += 1; 19253927de2eSStefano Zampini } 19263927de2eSStefano Zampini } 19273927de2eSStefano Zampini } 19289566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(matis->A, i, &ncols, &cols, NULL)); 19293927de2eSStefano Zampini } 19303927de2eSStefano Zampini } 193148a46eb9SPierre Jolivet if (global_indices_c != global_indices_r) PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->cmapping, &global_indices_c)); 19329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->rmapping, &global_indices_r)); 19339566063dSJacob Faibussowitsch PetscCall(PetscFree(row_ownership)); 1934ecf5a873SStefano Zampini 1935ecf5a873SStefano Zampini /* Reduce my_dnz and my_onz */ 19363927de2eSStefano Zampini if (maxreduce) { 19379566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, my_dnz, dnz, MPI_MAX)); 19389566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, my_onz, onz, MPI_MAX)); 19399566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, my_dnz, dnz, MPI_MAX)); 19409566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, my_onz, onz, MPI_MAX)); 19413927de2eSStefano Zampini } else { 19429566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, my_dnz, dnz, MPI_SUM)); 19439566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(matis->sf, MPIU_INT, my_onz, onz, MPI_SUM)); 19449566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, my_dnz, dnz, MPI_SUM)); 19459566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(matis->sf, MPIU_INT, my_onz, onz, MPI_SUM)); 19463927de2eSStefano Zampini } 19479566063dSJacob Faibussowitsch PetscCall(PetscFree2(my_dnz, my_onz)); 19483927de2eSStefano Zampini 19493927de2eSStefano Zampini /* Resize preallocation if overestimated */ 19503927de2eSStefano Zampini for (i = 0; i < lrows; i++) { 19513927de2eSStefano Zampini dnz[i] = PetscMin(dnz[i], lcols); 19523927de2eSStefano Zampini onz[i] = PetscMin(onz[i], cols - lcols); 19533927de2eSStefano Zampini } 19541670daf9Sstefano_zampini 19551670daf9Sstefano_zampini /* Set preallocation */ 19569566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizesFromMats(B, A, A)); 19579566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(B, 0, dnz)); 19589566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(B, 0, dnz, 0, onz)); 195953b44cf5SStefano Zampini for (i = 0; i < lrows; i += bs) { 196053b44cf5SStefano Zampini PetscInt b, d = dnz[i], o = onz[i]; 196153b44cf5SStefano Zampini 196253b44cf5SStefano Zampini for (b = 1; b < bs; b++) { 196353b44cf5SStefano Zampini d = PetscMax(d, dnz[i + b]); 196453b44cf5SStefano Zampini o = PetscMax(o, onz[i + b]); 196553b44cf5SStefano Zampini } 196653b44cf5SStefano Zampini dnz[i / bs] = PetscMin(d / bs + d % bs, lcols / bs); 196753b44cf5SStefano Zampini onz[i / bs] = PetscMin(o / bs + o % bs, (cols - lcols) / bs); 19683927de2eSStefano Zampini } 19699566063dSJacob Faibussowitsch PetscCall(MatSeqBAIJSetPreallocation(B, bs, 0, dnz)); 19709566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJSetPreallocation(B, bs, 0, dnz, 0, onz)); 19719566063dSJacob Faibussowitsch PetscCall(MatMPISBAIJSetPreallocation(B, bs, 0, dnz, 0, onz)); 1972d0609cedSBarry Smith MatPreallocateEnd(dnz, onz); 19739566063dSJacob Faibussowitsch if (issbaij) PetscCall(MatRestoreRowUpperTriangular(matis->A)); 19749566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE)); 19753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19763927de2eSStefano Zampini } 19773927de2eSStefano Zampini 1978d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_IS_XAIJ(Mat mat, MatType mtype, MatReuse reuse, Mat *M) 1979d71ae5a4SJacob Faibussowitsch { 1980f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)mat->data; 1981487b449aSStefano Zampini Mat local_mat, MT; 198253b44cf5SStefano Zampini PetscInt rbs, cbs, rows, cols, lrows, lcols; 1983b7ce53b6SStefano Zampini PetscInt local_rows, local_cols; 1984b9ed4604SStefano Zampini PetscBool isseqdense, isseqsbaij, isseqaij, isseqbaij; 1985f03112d0SStefano Zampini PetscMPIInt size; 19861683a169SBarry Smith const PetscScalar *array; 1987b7ce53b6SStefano Zampini 1988b7ce53b6SStefano Zampini PetscFunctionBegin; 19899566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 1990*4f58015eSStefano Zampini if (size == 1 && mat->rmap->N == matis->A->rmap->N && mat->cmap->N == matis->A->cmap->N && !matis->allow_repeated) { 19911670daf9Sstefano_zampini Mat B; 199253b44cf5SStefano Zampini IS irows = NULL, icols = NULL; 1993487b449aSStefano Zampini PetscInt rbs, cbs; 19941670daf9Sstefano_zampini 19959566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->rmapping, &rbs)); 19969566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->cmapping, &cbs)); 199753b44cf5SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { /* check if l2g maps are one-to-one */ 199853b44cf5SStefano Zampini IS rows, cols; 199953b44cf5SStefano Zampini const PetscInt *ridxs, *cidxs; 2000*4f58015eSStefano Zampini PetscInt i, nw; 2001*4f58015eSStefano Zampini PetscBT work; 200253b44cf5SStefano Zampini 20039566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(matis->rmapping, &ridxs)); 20049566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->rmapping, &nw)); 200553b44cf5SStefano Zampini nw = nw / rbs; 2006*4f58015eSStefano Zampini PetscCall(PetscBTCreate(nw, &work)); 2007*4f58015eSStefano Zampini for (i = 0; i < nw; i++) PetscCall(PetscBTSet(work, ridxs[i])); 20089371c9d4SSatish Balay for (i = 0; i < nw; i++) 2009*4f58015eSStefano Zampini if (!PetscBTLookup(work, i)) break; 201053b44cf5SStefano Zampini if (i == nw) { 20119566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF, rbs, nw, ridxs, PETSC_USE_POINTER, &rows)); 20129566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(rows)); 20139566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(rows, PETSC_DECIDE, &irows)); 20149566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rows)); 201553b44cf5SStefano Zampini } 20169566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(matis->rmapping, &ridxs)); 2017*4f58015eSStefano Zampini PetscCall(PetscBTDestroy(&work)); 2018e432b41dSStefano Zampini if (irows && matis->rmapping != matis->cmapping) { 20199566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(matis->cmapping, &cidxs)); 20209566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->cmapping, &nw)); 202153b44cf5SStefano Zampini nw = nw / cbs; 2022*4f58015eSStefano Zampini PetscCall(PetscBTCreate(nw, &work)); 2023*4f58015eSStefano Zampini for (i = 0; i < nw; i++) PetscCall(PetscBTSet(work, cidxs[i])); 20249371c9d4SSatish Balay for (i = 0; i < nw; i++) 2025*4f58015eSStefano Zampini if (!PetscBTLookup(work, i)) break; 202653b44cf5SStefano Zampini if (i == nw) { 20279566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF, cbs, nw, cidxs, PETSC_USE_POINTER, &cols)); 20289566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(cols)); 20299566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(cols, PETSC_DECIDE, &icols)); 20309566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cols)); 203153b44cf5SStefano Zampini } 20329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(matis->cmapping, &cidxs)); 2033*4f58015eSStefano Zampini PetscCall(PetscBTDestroy(&work)); 203453b44cf5SStefano Zampini } else if (irows) { 20359566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)irows)); 203653b44cf5SStefano Zampini icols = irows; 203753b44cf5SStefano Zampini } 203853b44cf5SStefano Zampini } else { 2039f4f49eeaSPierre Jolivet PetscCall(PetscObjectQuery((PetscObject)*M, "_MatIS_IS_XAIJ_irows", (PetscObject *)&irows)); 2040f4f49eeaSPierre Jolivet PetscCall(PetscObjectQuery((PetscObject)*M, "_MatIS_IS_XAIJ_icols", (PetscObject *)&icols)); 20419566063dSJacob Faibussowitsch if (irows) PetscCall(PetscObjectReference((PetscObject)irows)); 20429566063dSJacob Faibussowitsch if (icols) PetscCall(PetscObjectReference((PetscObject)icols)); 204353b44cf5SStefano Zampini } 204453b44cf5SStefano Zampini if (!irows || !icols) { 20459566063dSJacob Faibussowitsch PetscCall(ISDestroy(&icols)); 20469566063dSJacob Faibussowitsch PetscCall(ISDestroy(&irows)); 204753b44cf5SStefano Zampini goto general_assembly; 204853b44cf5SStefano Zampini } 20499566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, mtype, MAT_INITIAL_MATRIX, &B)); 2050487b449aSStefano Zampini if (reuse != MAT_INPLACE_MATRIX) { 20519566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(B, irows, icols, reuse, M)); 2052f4f49eeaSPierre Jolivet PetscCall(PetscObjectCompose((PetscObject)*M, "_MatIS_IS_XAIJ_irows", (PetscObject)irows)); 2053f4f49eeaSPierre Jolivet PetscCall(PetscObjectCompose((PetscObject)*M, "_MatIS_IS_XAIJ_icols", (PetscObject)icols)); 2054487b449aSStefano Zampini } else { 2055487b449aSStefano Zampini Mat C; 2056487b449aSStefano Zampini 20579566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(B, irows, icols, MAT_INITIAL_MATRIX, &C)); 20589566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(mat, &C)); 2059487b449aSStefano Zampini } 20609566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 20619566063dSJacob Faibussowitsch PetscCall(ISDestroy(&icols)); 20629566063dSJacob Faibussowitsch PetscCall(ISDestroy(&irows)); 20633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20647c03b4e8SStefano Zampini } 206553b44cf5SStefano Zampini general_assembly: 20669566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &rows, &cols)); 20679566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->rmapping, &rbs)); 20689566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->cmapping, &cbs)); 20699566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mat, &lrows, &lcols)); 20709566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, &local_rows, &local_cols)); 20719566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQDENSE, &isseqdense)); 20729566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQAIJ, &isseqaij)); 20739566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQBAIJ, &isseqbaij)); 20749566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQSBAIJ, &isseqsbaij)); 2075f4f49eeaSPierre Jolivet PetscCheck(isseqdense || isseqaij || isseqbaij || isseqsbaij, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)matis->A)->type_name); 207676bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 207776bd3646SJed Brown PetscBool lb[4], bb[4]; 207876bd3646SJed Brown 2079b9ed4604SStefano Zampini lb[0] = isseqdense; 2080b9ed4604SStefano Zampini lb[1] = isseqaij; 2081b9ed4604SStefano Zampini lb[2] = isseqbaij; 2082b9ed4604SStefano Zampini lb[3] = isseqsbaij; 20831c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(lb, bb, 4, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)mat))); 2084aed4548fSBarry Smith PetscCheck(bb[0] || bb[1] || bb[2] || bb[3], PETSC_COMM_SELF, PETSC_ERR_SUP, "Local matrices must have the same type"); 208576bd3646SJed Brown } 2086b7ce53b6SStefano Zampini 2087487b449aSStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 20889566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &MT)); 20899566063dSJacob Faibussowitsch PetscCall(MatSetSizes(MT, lrows, lcols, rows, cols)); 20909566063dSJacob Faibussowitsch PetscCall(MatSetType(MT, mtype)); 20919566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(MT, rbs, cbs)); 20929566063dSJacob Faibussowitsch PetscCall(MatISSetMPIXAIJPreallocation_Private(mat, MT, PETSC_FALSE)); 2093b7ce53b6SStefano Zampini } else { 209453b44cf5SStefano Zampini PetscInt mrbs, mcbs, mrows, mcols, mlrows, mlcols; 2095487b449aSStefano Zampini 2096b7ce53b6SStefano Zampini /* some checks */ 2097487b449aSStefano Zampini MT = *M; 20989566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(MT, &mrbs, &mcbs)); 20999566063dSJacob Faibussowitsch PetscCall(MatGetSize(MT, &mrows, &mcols)); 21009566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(MT, &mlrows, &mlcols)); 210108401ef6SPierre Jolivet PetscCheck(mrows == rows, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of rows (%" PetscInt_FMT " != %" PetscInt_FMT ")", rows, mrows); 210208401ef6SPierre Jolivet PetscCheck(mcols == cols, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of cols (%" PetscInt_FMT " != %" PetscInt_FMT ")", cols, mcols); 210308401ef6SPierre Jolivet PetscCheck(mlrows == lrows, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of local rows (%" PetscInt_FMT " != %" PetscInt_FMT ")", lrows, mlrows); 210408401ef6SPierre Jolivet PetscCheck(mlcols == lcols, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of local cols (%" PetscInt_FMT " != %" PetscInt_FMT ")", lcols, mlcols); 210508401ef6SPierre Jolivet PetscCheck(mrbs == rbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong row block size (%" PetscInt_FMT " != %" PetscInt_FMT ")", rbs, mrbs); 210608401ef6SPierre Jolivet PetscCheck(mcbs == cbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong col block size (%" PetscInt_FMT " != %" PetscInt_FMT ")", cbs, mcbs); 21079566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(MT)); 2108b7ce53b6SStefano Zampini } 2109d9a9e74cSStefano Zampini 21108546b261SStefano Zampini if (isseqsbaij || isseqbaij) { 21119566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &local_mat)); 21128546b261SStefano Zampini isseqaij = PETSC_TRUE; 2113d9a9e74cSStefano Zampini } else { 21149566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)matis->A)); 2115d9a9e74cSStefano Zampini local_mat = matis->A; 2116d9a9e74cSStefano Zampini } 2117686e3a49SStefano Zampini 2118b7ce53b6SStefano Zampini /* Set values */ 21199566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(MT, matis->rmapping, matis->cmapping)); 2120b9ed4604SStefano Zampini if (isseqdense) { /* special case for dense local matrices */ 212165066ba5SStefano Zampini PetscInt i, *dummy; 2122ecf5a873SStefano Zampini 21239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(PetscMax(local_rows, local_cols), &dummy)); 212465066ba5SStefano Zampini for (i = 0; i < PetscMax(local_rows, local_cols); i++) dummy[i] = i; 21259566063dSJacob Faibussowitsch PetscCall(MatSetOption(MT, MAT_ROW_ORIENTED, PETSC_FALSE)); 21269566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(local_mat, &array)); 21279566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(MT, local_rows, dummy, local_cols, dummy, array, ADD_VALUES)); 21289566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(local_mat, &array)); 21299566063dSJacob Faibussowitsch PetscCall(PetscFree(dummy)); 2130686e3a49SStefano Zampini } else if (isseqaij) { 21316afe12f5SStefano Zampini const PetscInt *blocks; 21326afe12f5SStefano Zampini PetscInt i, nvtxs, *xadj, *adjncy, nb; 2133686e3a49SStefano Zampini PetscBool done; 21341683a169SBarry Smith PetscScalar *sarray; 2135686e3a49SStefano Zampini 21369566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(local_mat, 0, PETSC_FALSE, PETSC_FALSE, &nvtxs, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &done)); 213728b400f6SJacob Faibussowitsch PetscCheck(done, PetscObjectComm((PetscObject)local_mat), PETSC_ERR_PLIB, "Error in MatGetRowIJ"); 21389566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(local_mat, &sarray)); 21399566063dSJacob Faibussowitsch PetscCall(MatGetVariableBlockSizes(local_mat, &nb, &blocks)); 21406afe12f5SStefano Zampini if (nb) { /* speed up assembly for special blocked matrices (used by BDDC) */ 21416afe12f5SStefano Zampini PetscInt sum; 21426afe12f5SStefano Zampini 21436afe12f5SStefano Zampini for (i = 0, sum = 0; i < nb; i++) sum += blocks[i]; 21446afe12f5SStefano Zampini if (sum == nvtxs) { 21456afe12f5SStefano Zampini PetscInt r; 21466afe12f5SStefano Zampini 21476afe12f5SStefano Zampini for (i = 0, r = 0; i < nb; i++) { 21486bdcaf15SBarry 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]); 21499566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(MT, blocks[i], adjncy + xadj[r], blocks[i], adjncy + xadj[r], sarray + xadj[r], ADD_VALUES)); 21506afe12f5SStefano Zampini r += blocks[i]; 21516afe12f5SStefano Zampini } 21526afe12f5SStefano Zampini } else { 215348a46eb9SPierre 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)); 21546afe12f5SStefano Zampini } 21556afe12f5SStefano Zampini } else { 21568e3a54c0SPierre Jolivet for (i = 0; i < nvtxs; i++) PetscCall(MatSetValuesLocal(MT, 1, &i, xadj[i + 1] - xadj[i], PetscSafePointerPlusOffset(adjncy, xadj[i]), PetscSafePointerPlusOffset(sarray, xadj[i]), ADD_VALUES)); 21576afe12f5SStefano Zampini } 21589566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(local_mat, 0, PETSC_FALSE, PETSC_FALSE, &nvtxs, (const PetscInt **)&xadj, (const PetscInt **)&adjncy, &done)); 215928b400f6SJacob Faibussowitsch PetscCheck(done, PetscObjectComm((PetscObject)local_mat), PETSC_ERR_PLIB, "Error in MatRestoreRowIJ"); 21609566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(local_mat, &sarray)); 2161686e3a49SStefano Zampini } else { /* very basic values insertion for all other matrix types */ 2162*4f58015eSStefano Zampini for (PetscInt i = 0; i < local_rows; i++) { 2163686e3a49SStefano Zampini PetscInt j; 2164ecf5a873SStefano Zampini const PetscInt *local_indices_cols; 2165686e3a49SStefano Zampini 21669566063dSJacob Faibussowitsch PetscCall(MatGetRow(local_mat, i, &j, &local_indices_cols, &array)); 21679566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(MT, 1, &i, j, local_indices_cols, array, ADD_VALUES)); 21689566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(local_mat, i, &j, &local_indices_cols, &array)); 2169686e3a49SStefano Zampini } 2170b7ce53b6SStefano Zampini } 21719566063dSJacob Faibussowitsch PetscCall(MatDestroy(&local_mat)); 2172*4f58015eSStefano Zampini PetscCall(MatAssemblyBegin(MT, MAT_FINAL_ASSEMBLY)); 21739566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(MT, MAT_FINAL_ASSEMBLY)); 21741baa6e33SBarry Smith if (isseqdense) PetscCall(MatSetOption(MT, MAT_ROW_ORIENTED, PETSC_TRUE)); 2175487b449aSStefano Zampini if (reuse == MAT_INPLACE_MATRIX) { 21769566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(mat, &MT)); 2177487b449aSStefano Zampini } else if (reuse == MAT_INITIAL_MATRIX) { 2178487b449aSStefano Zampini *M = MT; 2179b7ce53b6SStefano Zampini } 21803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2181b7ce53b6SStefano Zampini } 2182b7ce53b6SStefano Zampini 2183d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDuplicate_IS(Mat mat, MatDuplicateOption op, Mat *newmat) 2184d71ae5a4SJacob Faibussowitsch { 2185f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)mat->data; 2186c9225affSStefano Zampini PetscInt rbs, cbs, m, n, M, N; 2187ad6194a2SStefano Zampini Mat B, localmat; 2188ad6194a2SStefano Zampini 2189ad6194a2SStefano Zampini PetscFunctionBegin; 21909566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &rbs)); 21919566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &cbs)); 21929566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &M, &N)); 21939566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mat, &m, &n)); 21949566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 21959566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, m, n, M, N)); 21969566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(B, rbs == cbs ? rbs : 1)); 21979566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATIS)); 21989566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(B, matis->lmattype)); 2199*4f58015eSStefano Zampini PetscCall(MatISSetAllowRepeated(B, matis->allow_repeated)); 22009566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B, mat->rmap->mapping, mat->cmap->mapping)); 22019566063dSJacob Faibussowitsch PetscCall(MatDuplicate(matis->A, op, &localmat)); 22029566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(localmat, matis->A->rmap->mapping, matis->A->cmap->mapping)); 22039566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B, localmat)); 22049566063dSJacob Faibussowitsch PetscCall(MatDestroy(&localmat)); 22059566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 22069566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 2207ad6194a2SStefano Zampini *newmat = B; 22083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2209ad6194a2SStefano Zampini } 2210ad6194a2SStefano Zampini 2211d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsHermitian_IS(Mat A, PetscReal tol, PetscBool *flg) 2212d71ae5a4SJacob Faibussowitsch { 221369796d55SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 221469796d55SStefano Zampini PetscBool local_sym; 221569796d55SStefano Zampini 221669796d55SStefano Zampini PetscFunctionBegin; 22179566063dSJacob Faibussowitsch PetscCall(MatIsHermitian(matis->A, tol, &local_sym)); 22181c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&local_sym, flg, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 22193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 222069796d55SStefano Zampini } 222169796d55SStefano Zampini 2222d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsSymmetric_IS(Mat A, PetscReal tol, PetscBool *flg) 2223d71ae5a4SJacob Faibussowitsch { 222469796d55SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 222569796d55SStefano Zampini PetscBool local_sym; 222669796d55SStefano Zampini 222769796d55SStefano Zampini PetscFunctionBegin; 2228e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { 2229e432b41dSStefano Zampini *flg = PETSC_FALSE; 22303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2231e432b41dSStefano Zampini } 22329566063dSJacob Faibussowitsch PetscCall(MatIsSymmetric(matis->A, tol, &local_sym)); 22331c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&local_sym, flg, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 22343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 223569796d55SStefano Zampini } 223669796d55SStefano Zampini 2237d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A, PetscBool *flg) 2238d71ae5a4SJacob Faibussowitsch { 223945471136SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 224045471136SStefano Zampini PetscBool local_sym; 224145471136SStefano Zampini 224245471136SStefano Zampini PetscFunctionBegin; 2243e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { 224445471136SStefano Zampini *flg = PETSC_FALSE; 22453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 224645471136SStefano Zampini } 22479566063dSJacob Faibussowitsch PetscCall(MatIsStructurallySymmetric(matis->A, &local_sym)); 22481c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&local_sym, flg, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 22493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 225045471136SStefano Zampini } 225145471136SStefano Zampini 2252d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_IS(Mat A) 2253d71ae5a4SJacob Faibussowitsch { 2254b4319ba4SBarry Smith Mat_IS *b = (Mat_IS *)A->data; 2255b4319ba4SBarry Smith 2256b4319ba4SBarry Smith PetscFunctionBegin; 22579566063dSJacob Faibussowitsch PetscCall(PetscFree(b->bdiag)); 22589566063dSJacob Faibussowitsch PetscCall(PetscFree(b->lmattype)); 22599566063dSJacob Faibussowitsch PetscCall(MatDestroy(&b->A)); 22609566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&b->cctx)); 22619566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&b->rctx)); 22629566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->x)); 22639566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->y)); 22649566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->counter)); 22659566063dSJacob Faibussowitsch PetscCall(ISDestroy(&b->getsub_ris)); 22669566063dSJacob Faibussowitsch PetscCall(ISDestroy(&b->getsub_cis)); 2267a8116848SStefano Zampini if (b->sf != b->csf) { 22689566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&b->csf)); 22699566063dSJacob Faibussowitsch PetscCall(PetscFree2(b->csf_rootdata, b->csf_leafdata)); 2270f03112d0SStefano Zampini } else b->csf = NULL; 22719566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&b->sf)); 22729566063dSJacob Faibussowitsch PetscCall(PetscFree2(b->sf_rootdata, b->sf_leafdata)); 22739566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&b->rmapping)); 22749566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&b->cmapping)); 2275d0dbe9f7SStefano Zampini PetscCall(MatDestroy(&b->dA)); 2276d0dbe9f7SStefano Zampini PetscCall(MatDestroy(&b->assembledA)); 22779566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 22789566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, NULL)); 22799566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMatType_C", NULL)); 22809566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalMat_C", NULL)); 22819566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMat_C", NULL)); 22822e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISRestoreLocalMat_C", NULL)); 22839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetPreallocation_C", NULL)); 22849566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISStoreL2L_C", NULL)); 22859566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISFixLocalEmpty_C", NULL)); 22869566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalToGlobalMapping_C", NULL)); 22879566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpiaij_C", NULL)); 22889566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpibaij_C", NULL)); 22899566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpisbaij_C", NULL)); 22909566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqaij_C", NULL)); 22919566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqbaij_C", NULL)); 22929566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqsbaij_C", NULL)); 22939566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_aij_C", NULL)); 22949566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOOLocal_C", NULL)); 22959566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL)); 22969566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL)); 2297*4f58015eSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetAllowRepeated_C", NULL)); 22983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2299b4319ba4SBarry Smith } 2300b4319ba4SBarry Smith 2301d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_IS(Mat A, Vec x, Vec y) 2302d71ae5a4SJacob Faibussowitsch { 2303b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)A->data; 2304b4319ba4SBarry Smith PetscScalar zero = 0.0; 2305b4319ba4SBarry Smith 2306b4319ba4SBarry Smith PetscFunctionBegin; 2307b4319ba4SBarry Smith /* scatter the global vector x into the local work vector */ 23089566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->cctx, x, is->x, INSERT_VALUES, SCATTER_FORWARD)); 23099566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->cctx, x, is->x, INSERT_VALUES, SCATTER_FORWARD)); 2310b4319ba4SBarry Smith 2311b4319ba4SBarry Smith /* multiply the local matrix */ 23129566063dSJacob Faibussowitsch PetscCall(MatMult(is->A, is->x, is->y)); 2313b4319ba4SBarry Smith 2314b4319ba4SBarry Smith /* scatter product back into global memory */ 23159566063dSJacob Faibussowitsch PetscCall(VecSet(y, zero)); 23169566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, is->y, y, ADD_VALUES, SCATTER_REVERSE)); 23179566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, is->y, y, ADD_VALUES, SCATTER_REVERSE)); 23183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2319b4319ba4SBarry Smith } 2320b4319ba4SBarry Smith 2321d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultAdd_IS(Mat A, Vec v1, Vec v2, Vec v3) 2322d71ae5a4SJacob Faibussowitsch { 2323650997f4SStefano Zampini Vec temp_vec; 23242e74eeadSLisandro Dalcin 23252e74eeadSLisandro Dalcin PetscFunctionBegin; /* v3 = v2 + A * v1.*/ 2326650997f4SStefano Zampini if (v3 != v2) { 23279566063dSJacob Faibussowitsch PetscCall(MatMult(A, v1, v3)); 23289566063dSJacob Faibussowitsch PetscCall(VecAXPY(v3, 1.0, v2)); 2329650997f4SStefano Zampini } else { 23309566063dSJacob Faibussowitsch PetscCall(VecDuplicate(v2, &temp_vec)); 23319566063dSJacob Faibussowitsch PetscCall(MatMult(A, v1, temp_vec)); 23329566063dSJacob Faibussowitsch PetscCall(VecAXPY(temp_vec, 1.0, v2)); 23339566063dSJacob Faibussowitsch PetscCall(VecCopy(temp_vec, v3)); 23349566063dSJacob Faibussowitsch PetscCall(VecDestroy(&temp_vec)); 2335650997f4SStefano Zampini } 23363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23372e74eeadSLisandro Dalcin } 23382e74eeadSLisandro Dalcin 2339d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTranspose_IS(Mat A, Vec y, Vec x) 2340d71ae5a4SJacob Faibussowitsch { 23412e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS *)A->data; 23422e74eeadSLisandro Dalcin 2343e176bc59SStefano Zampini PetscFunctionBegin; 23442e74eeadSLisandro Dalcin /* scatter the global vector x into the local work vector */ 23459566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, y, is->y, INSERT_VALUES, SCATTER_FORWARD)); 23469566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, y, is->y, INSERT_VALUES, SCATTER_FORWARD)); 23472e74eeadSLisandro Dalcin 23482e74eeadSLisandro Dalcin /* multiply the local matrix */ 23499566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(is->A, is->y, is->x)); 23502e74eeadSLisandro Dalcin 23512e74eeadSLisandro Dalcin /* scatter product back into global vector */ 23529566063dSJacob Faibussowitsch PetscCall(VecSet(x, 0)); 23539566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->cctx, is->x, x, ADD_VALUES, SCATTER_REVERSE)); 23549566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->cctx, is->x, x, ADD_VALUES, SCATTER_REVERSE)); 23553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23562e74eeadSLisandro Dalcin } 23572e74eeadSLisandro Dalcin 2358d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTransposeAdd_IS(Mat A, Vec v1, Vec v2, Vec v3) 2359d71ae5a4SJacob Faibussowitsch { 2360650997f4SStefano Zampini Vec temp_vec; 23612e74eeadSLisandro Dalcin 23622e74eeadSLisandro Dalcin PetscFunctionBegin; /* v3 = v2 + A' * v1.*/ 2363650997f4SStefano Zampini if (v3 != v2) { 23649566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(A, v1, v3)); 23659566063dSJacob Faibussowitsch PetscCall(VecAXPY(v3, 1.0, v2)); 2366650997f4SStefano Zampini } else { 23679566063dSJacob Faibussowitsch PetscCall(VecDuplicate(v2, &temp_vec)); 23689566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(A, v1, temp_vec)); 23699566063dSJacob Faibussowitsch PetscCall(VecAXPY(temp_vec, 1.0, v2)); 23709566063dSJacob Faibussowitsch PetscCall(VecCopy(temp_vec, v3)); 23719566063dSJacob Faibussowitsch PetscCall(VecDestroy(&temp_vec)); 2372650997f4SStefano Zampini } 23733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23742e74eeadSLisandro Dalcin } 23752e74eeadSLisandro Dalcin 2376d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_IS(Mat A, PetscViewer viewer) 2377d71ae5a4SJacob Faibussowitsch { 2378b4319ba4SBarry Smith Mat_IS *a = (Mat_IS *)A->data; 2379b4319ba4SBarry Smith PetscViewer sviewer; 2380ee2491ecSStefano Zampini PetscBool isascii, view = PETSC_TRUE; 2381b4319ba4SBarry Smith 2382b4319ba4SBarry Smith PetscFunctionBegin; 23839566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 2384ee2491ecSStefano Zampini if (isascii) { 2385ee2491ecSStefano Zampini PetscViewerFormat format; 2386ee2491ecSStefano Zampini 23879566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 2388ee2491ecSStefano Zampini if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE; 2389ee2491ecSStefano Zampini } 23903ba16761SJacob Faibussowitsch if (!view) PetscFunctionReturn(PETSC_SUCCESS); 23919566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 23929566063dSJacob Faibussowitsch PetscCall(MatView(a->A, sviewer)); 23939566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 23943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2395b4319ba4SBarry Smith } 2396b4319ba4SBarry Smith 2397d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatInvertBlockDiagonal_IS(Mat mat, const PetscScalar **values) 2398d71ae5a4SJacob Faibussowitsch { 2399b89f26deSStefano Zampini Mat_IS *is = (Mat_IS *)mat->data; 2400b89f26deSStefano Zampini MPI_Datatype nodeType; 2401b89f26deSStefano Zampini const PetscScalar *lv; 2402b89f26deSStefano Zampini PetscInt bs; 2403b89f26deSStefano Zampini 2404b89f26deSStefano Zampini PetscFunctionBegin; 24059566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(mat, &bs)); 24069566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(is->A, bs)); 24079566063dSJacob Faibussowitsch PetscCall(MatInvertBlockDiagonal(is->A, &lv)); 240848a46eb9SPierre Jolivet if (!is->bdiag) PetscCall(PetscMalloc1(bs * mat->rmap->n, &is->bdiag)); 24099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_contiguous(bs, MPIU_SCALAR, &nodeType)); 24109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&nodeType)); 24119566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(is->sf, nodeType, lv, is->bdiag, MPI_REPLACE)); 24129566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(is->sf, nodeType, lv, is->bdiag, MPI_REPLACE)); 24139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&nodeType)); 2414b89f26deSStefano Zampini if (values) *values = is->bdiag; 24153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2416b89f26deSStefano Zampini } 2417b89f26deSStefano Zampini 2418d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISSetUpScatters_Private(Mat A) 2419d71ae5a4SJacob Faibussowitsch { 2420e176bc59SStefano Zampini Vec cglobal, rglobal; 24218546b261SStefano Zampini IS from; 24228546b261SStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 2423b89f26deSStefano Zampini PetscScalar sum; 24248546b261SStefano Zampini const PetscInt *garray; 24258546b261SStefano Zampini PetscInt nr, rbs, nc, cbs; 2426e432b41dSStefano Zampini VecType rtype; 2427b4319ba4SBarry Smith 2428b4319ba4SBarry Smith PetscFunctionBegin; 24299566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->rmapping, &nr)); 24309566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->rmapping, &rbs)); 24319566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->cmapping, &nc)); 24329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->cmapping, &cbs)); 24339566063dSJacob Faibussowitsch PetscCall(VecDestroy(&is->x)); 24349566063dSJacob Faibussowitsch PetscCall(VecDestroy(&is->y)); 24359566063dSJacob Faibussowitsch PetscCall(VecDestroy(&is->counter)); 24369566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&is->rctx)); 24379566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&is->cctx)); 24389566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(is->A, &is->x, &is->y)); 24399566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->y, PETSC_TRUE)); 24409566063dSJacob Faibussowitsch PetscCall(VecGetRootType_Private(is->y, &rtype)); 24419566063dSJacob Faibussowitsch PetscCall(PetscFree(A->defaultvectype)); 24429566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(rtype, &A->defaultvectype)); 24439566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, &cglobal, &rglobal)); 24449566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(rglobal, PETSC_TRUE)); 24459566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->rmapping, &garray)); 24469566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), rbs, nr / rbs, garray, PETSC_USE_POINTER, &from)); 24479566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(rglobal, from, is->y, NULL, &is->rctx)); 24489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->rmapping, &garray)); 24499566063dSJacob Faibussowitsch PetscCall(ISDestroy(&from)); 2450e432b41dSStefano Zampini if (is->rmapping != is->cmapping) { 24519566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->cmapping, &garray)); 24529566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), cbs, nc / cbs, garray, PETSC_USE_POINTER, &from)); 24539566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(cglobal, from, is->x, NULL, &is->cctx)); 24549566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->cmapping, &garray)); 24559566063dSJacob Faibussowitsch PetscCall(ISDestroy(&from)); 24568546b261SStefano Zampini } else { 24579566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->rctx)); 24588546b261SStefano Zampini is->cctx = is->rctx; 24598546b261SStefano Zampini } 24609566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cglobal)); 2461b89f26deSStefano Zampini 24628546b261SStefano Zampini /* interface counter vector (local) */ 24639566063dSJacob Faibussowitsch PetscCall(VecDuplicate(is->y, &is->counter)); 24649566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->counter, PETSC_TRUE)); 24659566063dSJacob Faibussowitsch PetscCall(VecSet(is->y, 1.)); 24669566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, is->y, rglobal, ADD_VALUES, SCATTER_REVERSE)); 24679566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, is->y, rglobal, ADD_VALUES, SCATTER_REVERSE)); 24689566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, rglobal, is->counter, INSERT_VALUES, SCATTER_FORWARD)); 24699566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, rglobal, is->counter, INSERT_VALUES, SCATTER_FORWARD)); 24709566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->y, PETSC_FALSE)); 24719566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->counter, PETSC_FALSE)); 2472b89f26deSStefano Zampini 2473b89f26deSStefano Zampini /* special functions for block-diagonal matrices */ 24749566063dSJacob Faibussowitsch PetscCall(VecSum(rglobal, &sum)); 2475b89f26deSStefano Zampini A->ops->invertblockdiagonal = NULL; 2476e432b41dSStefano Zampini if ((PetscInt)(PetscRealPart(sum)) == A->rmap->N && A->rmap->N == A->cmap->N && is->rmapping == is->cmapping) A->ops->invertblockdiagonal = MatInvertBlockDiagonal_IS; 24779566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rglobal)); 2478b0cc1f67SStefano Zampini 2479b0cc1f67SStefano Zampini /* setup SF for general purpose shared indices based communications */ 24809566063dSJacob Faibussowitsch PetscCall(MatISSetUpSF_IS(A)); 24813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24828546b261SStefano Zampini } 24838546b261SStefano Zampini 2484d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISFilterL2GMap(Mat A, ISLocalToGlobalMapping map, ISLocalToGlobalMapping *nmap, ISLocalToGlobalMapping *lmap) 2485d71ae5a4SJacob Faibussowitsch { 2486*4f58015eSStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 2487e432b41dSStefano Zampini IS is; 2488e432b41dSStefano Zampini ISLocalToGlobalMappingType l2gtype; 2489e432b41dSStefano Zampini const PetscInt *idxs; 2490e432b41dSStefano Zampini PetscHSetI ht; 2491e432b41dSStefano Zampini PetscInt *nidxs; 2492e432b41dSStefano Zampini PetscInt i, n, bs, c; 2493e432b41dSStefano Zampini PetscBool flg[] = {PETSC_FALSE, PETSC_FALSE}; 2494e432b41dSStefano Zampini 2495e432b41dSStefano Zampini PetscFunctionBegin; 24969566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(map, &n)); 24979566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(map, &bs)); 24989566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(map, &idxs)); 24999566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&ht)); 25009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n / bs, &nidxs)); 2501e432b41dSStefano Zampini for (i = 0, c = 0; i < n / bs; i++) { 2502*4f58015eSStefano Zampini PetscBool missing = PETSC_TRUE; 25039371c9d4SSatish Balay if (idxs[i] < 0) { 25049371c9d4SSatish Balay flg[0] = PETSC_TRUE; 25059371c9d4SSatish Balay continue; 25069371c9d4SSatish Balay } 2507*4f58015eSStefano Zampini if (!matis->allow_repeated) PetscCall(PetscHSetIQueryAdd(ht, idxs[i], &missing)); 2508e432b41dSStefano Zampini if (!missing) flg[1] = PETSC_TRUE; 2509e432b41dSStefano Zampini else nidxs[c++] = idxs[i]; 2510e432b41dSStefano Zampini } 25119566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&ht)); 25121c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(MPI_IN_PLACE, flg, 2, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A))); 2513e432b41dSStefano Zampini if (!flg[0] && !flg[1]) { /* Entries are all non negative and unique */ 2514e432b41dSStefano Zampini *nmap = NULL; 2515e432b41dSStefano Zampini *lmap = NULL; 25169566063dSJacob Faibussowitsch PetscCall(PetscFree(nidxs)); 25179566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(map, &idxs)); 25183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2519e432b41dSStefano Zampini } 2520e432b41dSStefano Zampini 2521*4f58015eSStefano Zampini /* New l2g map without negative indices (and repeated indices if not allowed) */ 25229566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), bs, c, nidxs, PETSC_USE_POINTER, &is)); 25239566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, nmap)); 25249566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 25259566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetType(map, &l2gtype)); 25269566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(*nmap, l2gtype)); 2527e432b41dSStefano Zampini 2528*4f58015eSStefano Zampini /* New local l2g map for repeated indices if not allowed */ 25299566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(*nmap, IS_GTOLM_MASK, n / bs, idxs, NULL, nidxs)); 25309566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF, bs, n / bs, nidxs, PETSC_USE_POINTER, &is)); 25319566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, lmap)); 25329566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 25339566063dSJacob Faibussowitsch PetscCall(PetscFree(nidxs)); 25349566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(map, &idxs)); 25353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2536e432b41dSStefano Zampini } 2537e432b41dSStefano Zampini 2538d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2539d71ae5a4SJacob Faibussowitsch { 25408546b261SStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 2541e432b41dSStefano Zampini ISLocalToGlobalMapping localrmapping = NULL, localcmapping = NULL; 2542e432b41dSStefano Zampini PetscInt nr, rbs, nc, cbs; 2543*4f58015eSStefano Zampini PetscBool cong, freem[] = {PETSC_FALSE, PETSC_FALSE}; 25448546b261SStefano Zampini 25458546b261SStefano Zampini PetscFunctionBegin; 2546fc989267SStefano Zampini if (rmapping) PetscCheckSameComm(A, 1, rmapping, 2); 2547fc989267SStefano Zampini if (cmapping) PetscCheckSameComm(A, 1, cmapping, 3); 2548e432b41dSStefano Zampini 25499566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&is->rmapping)); 25509566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&is->cmapping)); 25519566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 25529566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 25539566063dSJacob Faibussowitsch PetscCall(MatHasCongruentLayouts(A, &cong)); 2554e432b41dSStefano Zampini 2555fc989267SStefano Zampini /* If NULL, local space matches global space */ 2556fc989267SStefano Zampini if (!rmapping) { 2557fc989267SStefano Zampini IS is; 2558fc989267SStefano Zampini 25599566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), A->rmap->N, 0, 1, &is)); 25609566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rmapping)); 25619566063dSJacob Faibussowitsch if (A->rmap->bs > 0) PetscCall(ISLocalToGlobalMappingSetBlockSize(rmapping, A->rmap->bs)); 25629566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2563e432b41dSStefano Zampini freem[0] = PETSC_TRUE; 2564e432b41dSStefano Zampini if (!cmapping && cong && A->rmap->bs == A->cmap->bs) cmapping = rmapping; 2565e432b41dSStefano Zampini } else if (!is->islocalref) { /* check if the l2g map has negative or repeated entries */ 25669566063dSJacob Faibussowitsch PetscCall(MatISFilterL2GMap(A, rmapping, &is->rmapping, &localrmapping)); 2567e432b41dSStefano Zampini if (rmapping == cmapping) { 25689566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->rmapping)); 2569e432b41dSStefano Zampini is->cmapping = is->rmapping; 25709566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)localrmapping)); 2571e432b41dSStefano Zampini localcmapping = localrmapping; 2572fc989267SStefano Zampini } 2573fc989267SStefano Zampini } 2574fc989267SStefano Zampini if (!cmapping) { 2575fc989267SStefano Zampini IS is; 2576fc989267SStefano Zampini 25779566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), A->cmap->N, 0, 1, &is)); 25789566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cmapping)); 25799566063dSJacob Faibussowitsch if (A->cmap->bs > 0) PetscCall(ISLocalToGlobalMappingSetBlockSize(cmapping, A->cmap->bs)); 25809566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2581e432b41dSStefano Zampini freem[1] = PETSC_TRUE; 2582e432b41dSStefano Zampini } else if (cmapping != rmapping && !is->islocalref) { /* check if the l2g map has negative or repeated entries */ 25839566063dSJacob Faibussowitsch PetscCall(MatISFilterL2GMap(A, cmapping, &is->cmapping, &localcmapping)); 2584e432b41dSStefano Zampini } 2585e432b41dSStefano Zampini if (!is->rmapping) { 25869566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)rmapping)); 2587e432b41dSStefano Zampini is->rmapping = rmapping; 2588e432b41dSStefano Zampini } 2589e432b41dSStefano Zampini if (!is->cmapping) { 25909566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)cmapping)); 2591e432b41dSStefano Zampini is->cmapping = cmapping; 2592fc989267SStefano Zampini } 2593fc989267SStefano Zampini 2594fc989267SStefano Zampini /* Clean up */ 2595*4f58015eSStefano Zampini is->lnnzstate = 0; 2596*4f58015eSStefano Zampini PetscCall(MatDestroy(&is->dA)); 2597*4f58015eSStefano Zampini PetscCall(MatDestroy(&is->assembledA)); 25989566063dSJacob Faibussowitsch PetscCall(MatDestroy(&is->A)); 2599872cf891SStefano Zampini if (is->csf != is->sf) { 26009566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&is->csf)); 26019566063dSJacob Faibussowitsch PetscCall(PetscFree2(is->csf_rootdata, is->csf_leafdata)); 2602f03112d0SStefano Zampini } else is->csf = NULL; 26039566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&is->sf)); 26049566063dSJacob Faibussowitsch PetscCall(PetscFree2(is->sf_rootdata, is->sf_leafdata)); 26059566063dSJacob Faibussowitsch PetscCall(PetscFree(is->bdiag)); 26063bbff08aSStefano Zampini 2607fc989267SStefano Zampini /* check if the two mappings are actually the same for square matrices since MATIS has some optimization for this case 2608fc989267SStefano Zampini (DOLFIN passes 2 different objects) */ 26099566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->rmapping, &nr)); 26109566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->rmapping, &rbs)); 26119566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->cmapping, &nc)); 26129566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->cmapping, &cbs)); 2613e432b41dSStefano Zampini if (is->rmapping != is->cmapping && cong) { 2614e432b41dSStefano Zampini PetscBool same = PETSC_FALSE; 26156625354bSStefano Zampini if (nr == nc && cbs == rbs) { 26166625354bSStefano Zampini const PetscInt *idxs1, *idxs2; 26176625354bSStefano Zampini 26189566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->rmapping, &idxs1)); 26199566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->cmapping, &idxs2)); 26209566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(idxs1, idxs2, nr / rbs, &same)); 26219566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->rmapping, &idxs1)); 26229566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->cmapping, &idxs2)); 26236625354bSStefano Zampini } 26241c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(MPI_IN_PLACE, &same, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 2625e432b41dSStefano Zampini if (same) { 26269566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&is->cmapping)); 26279566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->rmapping)); 2628e432b41dSStefano Zampini is->cmapping = is->rmapping; 2629e432b41dSStefano Zampini } 26306625354bSStefano Zampini } 26319566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(A->rmap, rbs)); 26329566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(A->cmap, cbs)); 2633e432b41dSStefano Zampini /* Pass the user defined maps to the layout */ 26349566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetISLocalToGlobalMapping(A->rmap, rmapping)); 26359566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetISLocalToGlobalMapping(A->cmap, cmapping)); 26369566063dSJacob Faibussowitsch if (freem[0]) PetscCall(ISLocalToGlobalMappingDestroy(&rmapping)); 26379566063dSJacob Faibussowitsch if (freem[1]) PetscCall(ISLocalToGlobalMappingDestroy(&cmapping)); 26386625354bSStefano Zampini 26396625354bSStefano Zampini /* Create the local matrix A */ 26409566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &is->A)); 26419566063dSJacob Faibussowitsch PetscCall(MatSetType(is->A, is->lmattype)); 26429566063dSJacob Faibussowitsch PetscCall(MatSetSizes(is->A, nr, nc, nr, nc)); 26439566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(is->A, rbs, cbs)); 26449566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(is->A, "is_")); 26459566063dSJacob Faibussowitsch PetscCall(MatAppendOptionsPrefix(is->A, ((PetscObject)A)->prefix)); 26469566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(is->A->rmap)); 26479566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(is->A->cmap)); 26489566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(is->A, localrmapping, localcmapping)); 26499566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&localrmapping)); 26509566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&localcmapping)); 2651b4319ba4SBarry Smith 2652fc989267SStefano Zampini /* setup scatters and local vectors for MatMult */ 26539566063dSJacob Faibussowitsch if (!is->islocalref) PetscCall(MatISSetUpScatters_Private(A)); 2654fc989267SStefano Zampini A->preallocated = PETSC_TRUE; 26553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2656fc989267SStefano Zampini } 2657fc989267SStefano Zampini 2658d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetUp_IS(Mat A) 2659d71ae5a4SJacob Faibussowitsch { 2660fc989267SStefano Zampini ISLocalToGlobalMapping rmap, cmap; 2661fc989267SStefano Zampini 2662fc989267SStefano Zampini PetscFunctionBegin; 26639566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(A, &rmap, &cmap)); 266448a46eb9SPierre Jolivet if (!rmap && !cmap) PetscCall(MatSetLocalToGlobalMapping(A, NULL, NULL)); 26653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2666b4319ba4SBarry Smith } 2667b4319ba4SBarry Smith 2668d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) 2669d71ae5a4SJacob Faibussowitsch { 26702e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS *)mat->data; 2671f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION], cols_l[MATIS_MAX_ENTRIES_INSERTION]; 26722e74eeadSLisandro Dalcin 26732e74eeadSLisandro Dalcin PetscFunctionBegin; 26749566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(is->rmapping, IS_GTOLM_MASK, m, rows, &m, rows_l)); 2675e432b41dSStefano Zampini if (m != n || rows != cols || is->cmapping != is->rmapping) { 26769566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(is->cmapping, IS_GTOLM_MASK, n, cols, &n, cols_l)); 26779566063dSJacob Faibussowitsch PetscCall(MatSetValues(is->A, m, rows_l, n, cols_l, values, addv)); 2678e432b41dSStefano Zampini } else { 26799566063dSJacob Faibussowitsch PetscCall(MatSetValues(is->A, m, rows_l, m, rows_l, values, addv)); 2680e432b41dSStefano Zampini } 26813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 26822e74eeadSLisandro Dalcin } 26832e74eeadSLisandro Dalcin 2684d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) 2685d71ae5a4SJacob Faibussowitsch { 268697563a80SStefano Zampini Mat_IS *is = (Mat_IS *)mat->data; 2687f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION], cols_l[MATIS_MAX_ENTRIES_INSERTION]; 268897563a80SStefano Zampini 268997563a80SStefano Zampini PetscFunctionBegin; 26909566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(is->rmapping, IS_GTOLM_MASK, m, rows, &m, rows_l)); 2691e432b41dSStefano Zampini if (m != n || rows != cols || is->cmapping != is->rmapping) { 26929566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(is->cmapping, IS_GTOLM_MASK, n, cols, &n, cols_l)); 26939566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked(is->A, m, rows_l, n, cols_l, values, addv)); 2694e432b41dSStefano Zampini } else { 26959566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked(is->A, m, rows_l, n, rows_l, values, addv)); 2696e432b41dSStefano Zampini } 26973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 269897563a80SStefano Zampini } 269997563a80SStefano Zampini 2700d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesLocal_IS(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) 2701d71ae5a4SJacob Faibussowitsch { 2702b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)A->data; 2703b4319ba4SBarry Smith 2704b4319ba4SBarry Smith PetscFunctionBegin; 2705e432b41dSStefano Zampini if (is->A->rmap->mapping || is->A->cmap->mapping) { 27069566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(is->A, m, rows, n, cols, values, addv)); 2707872cf891SStefano Zampini } else { 27089566063dSJacob Faibussowitsch PetscCall(MatSetValues(is->A, m, rows, n, cols, values, addv)); 2709872cf891SStefano Zampini } 27103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2711b4319ba4SBarry Smith } 2712b4319ba4SBarry Smith 2713d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) 2714d71ae5a4SJacob Faibussowitsch { 2715f0006bf2SLisandro Dalcin Mat_IS *is = (Mat_IS *)A->data; 2716f0006bf2SLisandro Dalcin 2717f0006bf2SLisandro Dalcin PetscFunctionBegin; 2718e432b41dSStefano Zampini if (is->A->rmap->mapping || is->A->cmap->mapping) { 27199566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlockedLocal(is->A, m, rows, n, cols, values, addv)); 2720b4f971dfSStefano Zampini } else { 27219566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked(is->A, m, rows, n, cols, values, addv)); 2722b4f971dfSStefano Zampini } 27233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2724f0006bf2SLisandro Dalcin } 2725f0006bf2SLisandro Dalcin 2726d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, PetscBool columns) 2727d71ae5a4SJacob Faibussowitsch { 2728f0ae7da4SStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 2729f0ae7da4SStefano Zampini 2730f0ae7da4SStefano Zampini PetscFunctionBegin; 2731f0ae7da4SStefano Zampini if (!n) { 2732f0ae7da4SStefano Zampini is->pure_neumann = PETSC_TRUE; 2733f0ae7da4SStefano Zampini } else { 2734f0ae7da4SStefano Zampini PetscInt i; 2735f0ae7da4SStefano Zampini is->pure_neumann = PETSC_FALSE; 2736f0ae7da4SStefano Zampini 2737f0ae7da4SStefano Zampini if (columns) { 27389566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns(is->A, n, rows, diag, NULL, NULL)); 2739f0ae7da4SStefano Zampini } else { 27409566063dSJacob Faibussowitsch PetscCall(MatZeroRows(is->A, n, rows, diag, NULL, NULL)); 2741f0ae7da4SStefano Zampini } 2742f0ae7da4SStefano Zampini if (diag != 0.) { 2743f0ae7da4SStefano Zampini const PetscScalar *array; 27449566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(is->counter, &array)); 274548a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(MatSetValue(is->A, rows[i], rows[i], diag / (array[rows[i]]), INSERT_VALUES)); 27469566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(is->counter, &array)); 2747f0ae7da4SStefano Zampini } 27489566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(is->A, MAT_FINAL_ASSEMBLY)); 27499566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(is->A, MAT_FINAL_ASSEMBLY)); 2750f0ae7da4SStefano Zampini } 27513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2752f0ae7da4SStefano Zampini } 2753f0ae7da4SStefano Zampini 2754d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, Vec x, Vec b, PetscBool columns) 2755d71ae5a4SJacob Faibussowitsch { 27566e520ac8SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 27576e520ac8SStefano Zampini PetscInt nr, nl, len, i; 27586e520ac8SStefano Zampini PetscInt *lrows; 27592e74eeadSLisandro Dalcin 27602e74eeadSLisandro Dalcin PetscFunctionBegin; 2761cf9c20a2SJed Brown if (PetscUnlikelyDebug(columns || diag != 0. || (x && b))) { 2762f0ae7da4SStefano Zampini PetscBool cong; 276326b0207aSStefano Zampini 27649566063dSJacob Faibussowitsch PetscCall(PetscLayoutCompare(A->rmap, A->cmap, &cong)); 276526b0207aSStefano Zampini cong = (PetscBool)(cong && matis->sf == matis->csf); 276608401ef6SPierre 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"); 2767aed4548fSBarry 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"); 2768aed4548fSBarry 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"); 2769f0ae7da4SStefano Zampini } 27706e520ac8SStefano Zampini /* get locally owned rows */ 27719566063dSJacob Faibussowitsch PetscCall(PetscLayoutMapLocal(A->rmap, n, rows, &len, &lrows, NULL)); 27726e520ac8SStefano Zampini /* fix right hand side if needed */ 27736e520ac8SStefano Zampini if (x && b) { 27746e520ac8SStefano Zampini const PetscScalar *xx; 27756e520ac8SStefano Zampini PetscScalar *bb; 27766e520ac8SStefano Zampini 27779566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &xx)); 27789566063dSJacob Faibussowitsch PetscCall(VecGetArray(b, &bb)); 27796e520ac8SStefano Zampini for (i = 0; i < len; ++i) bb[lrows[i]] = diag * xx[lrows[i]]; 27809566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &xx)); 27819566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(b, &bb)); 27822e74eeadSLisandro Dalcin } 27836e520ac8SStefano Zampini /* get rows associated to the local matrices */ 27849566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, &nl, NULL)); 27859566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_leafdata, nl)); 27869566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata, A->rmap->n)); 27876e520ac8SStefano Zampini for (i = 0; i < len; i++) matis->sf_rootdata[lrows[i]] = 1; 27889566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 27899566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 27909566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 27919566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl, &lrows)); 27929371c9d4SSatish Balay for (i = 0, nr = 0; i < nl; i++) 27939371c9d4SSatish Balay if (matis->sf_leafdata[i]) lrows[nr++] = i; 27949566063dSJacob Faibussowitsch PetscCall(MatISZeroRowsColumnsLocal_Private(A, nr, lrows, diag, columns)); 27959566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 2796d0dbe9f7SStefano Zampini PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 2797d0dbe9f7SStefano Zampini PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 27983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 27992e74eeadSLisandro Dalcin } 28002e74eeadSLisandro Dalcin 2801d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_IS(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 2802d71ae5a4SJacob Faibussowitsch { 2803b4319ba4SBarry Smith PetscFunctionBegin; 28049566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns_Private_IS(A, n, rows, diag, x, b, PETSC_FALSE)); 28053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2806f0ae7da4SStefano Zampini } 28072205254eSKarl Rupp 2808d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_IS(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 2809d71ae5a4SJacob Faibussowitsch { 2810f0ae7da4SStefano Zampini PetscFunctionBegin; 28119566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns_Private_IS(A, n, rows, diag, x, b, PETSC_TRUE)); 28123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2813b4319ba4SBarry Smith } 2814b4319ba4SBarry Smith 2815d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_IS(Mat A, MatAssemblyType type) 2816d71ae5a4SJacob Faibussowitsch { 2817b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)A->data; 2818b4319ba4SBarry Smith 2819b4319ba4SBarry Smith PetscFunctionBegin; 28209566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(is->A, type)); 28213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2822b4319ba4SBarry Smith } 2823b4319ba4SBarry Smith 2824d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_IS(Mat A, MatAssemblyType type) 2825d71ae5a4SJacob Faibussowitsch { 2826b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)A->data; 2827d0dbe9f7SStefano Zampini PetscBool lnnz; 2828b4319ba4SBarry Smith 2829b4319ba4SBarry Smith PetscFunctionBegin; 28309566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(is->A, type)); 2831872cf891SStefano Zampini /* fix for local empty rows/cols */ 2832872cf891SStefano Zampini if (is->locempty && type == MAT_FINAL_ASSEMBLY) { 2833872cf891SStefano Zampini Mat newlA; 2834f03112d0SStefano Zampini ISLocalToGlobalMapping rl2g, cl2g; 2835f03112d0SStefano Zampini IS nzr, nzc; 2836f03112d0SStefano Zampini PetscInt nr, nc, nnzr, nnzc; 2837f03112d0SStefano Zampini PetscBool lnewl2g, newl2g; 2838872cf891SStefano Zampini 28399566063dSJacob Faibussowitsch PetscCall(MatGetSize(is->A, &nr, &nc)); 28409566063dSJacob Faibussowitsch PetscCall(MatFindNonzeroRowsOrCols_Basic(is->A, PETSC_FALSE, PETSC_SMALL, &nzr)); 284148a46eb9SPierre Jolivet if (!nzr) PetscCall(ISCreateStride(PetscObjectComm((PetscObject)is->A), nr, 0, 1, &nzr)); 28429566063dSJacob Faibussowitsch PetscCall(MatFindNonzeroRowsOrCols_Basic(is->A, PETSC_TRUE, PETSC_SMALL, &nzc)); 284348a46eb9SPierre Jolivet if (!nzc) PetscCall(ISCreateStride(PetscObjectComm((PetscObject)is->A), nc, 0, 1, &nzc)); 28449566063dSJacob Faibussowitsch PetscCall(ISGetSize(nzr, &nnzr)); 28459566063dSJacob Faibussowitsch PetscCall(ISGetSize(nzc, &nnzc)); 2846e432b41dSStefano Zampini if (nnzr != nr || nnzc != nc) { /* need new global l2g map */ 2847f03112d0SStefano Zampini lnewl2g = PETSC_TRUE; 2848712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&lnewl2g, &newl2g, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A))); 2849f03112d0SStefano Zampini 2850872cf891SStefano Zampini /* extract valid submatrix */ 28519566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(is->A, nzr, nzc, MAT_INITIAL_MATRIX, &newlA)); 2852f03112d0SStefano Zampini } else { /* local matrix fully populated */ 2853f03112d0SStefano Zampini lnewl2g = PETSC_FALSE; 2854712fec58SPierre Jolivet PetscCall(MPIU_Allreduce(&lnewl2g, &newl2g, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A))); 28559566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->A)); 2856f03112d0SStefano Zampini newlA = is->A; 2857f03112d0SStefano Zampini } 2858e432b41dSStefano Zampini 2859f03112d0SStefano Zampini /* attach new global l2g map if needed */ 2860f03112d0SStefano Zampini if (newl2g) { 2861e432b41dSStefano Zampini IS zr, zc; 2862e432b41dSStefano Zampini const PetscInt *ridxs, *cidxs, *zridxs, *zcidxs; 2863e432b41dSStefano Zampini PetscInt *nidxs, i; 2864f03112d0SStefano Zampini 28659566063dSJacob Faibussowitsch PetscCall(ISComplement(nzr, 0, nr, &zr)); 28669566063dSJacob Faibussowitsch PetscCall(ISComplement(nzc, 0, nc, &zc)); 28679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(PetscMax(nr, nc), &nidxs)); 28689566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(is->rmapping, &ridxs)); 28699566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(is->cmapping, &cidxs)); 28709566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zr, &zridxs)); 28719566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zc, &zcidxs)); 28729566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zr, &nnzr)); 28739566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zc, &nnzc)); 2874e432b41dSStefano Zampini 28759566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(nidxs, ridxs, nr)); 2876e432b41dSStefano Zampini for (i = 0; i < nnzr; i++) nidxs[zridxs[i]] = -1; 28779566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A), 1, nr, nidxs, PETSC_COPY_VALUES, &rl2g)); 28789566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(nidxs, cidxs, nc)); 2879e432b41dSStefano Zampini for (i = 0; i < nnzc; i++) nidxs[zcidxs[i]] = -1; 28809566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A), 1, nc, nidxs, PETSC_COPY_VALUES, &cl2g)); 2881e432b41dSStefano Zampini 28829566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zr, &zridxs)); 28839566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zc, &zcidxs)); 28849566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(is->rmapping, &ridxs)); 28859566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(is->cmapping, &cidxs)); 28869566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzr)); 28879566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzc)); 28889566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zr)); 28899566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zc)); 28909566063dSJacob Faibussowitsch PetscCall(PetscFree(nidxs)); 28919566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(A, rl2g, cl2g)); 28929566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 28939566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 2894f03112d0SStefano Zampini } 28959566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(A, newlA)); 28969566063dSJacob Faibussowitsch PetscCall(MatDestroy(&newlA)); 28979566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzr)); 28989566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzc)); 2899872cf891SStefano Zampini is->locempty = PETSC_FALSE; 2900f03112d0SStefano Zampini } 2901d0dbe9f7SStefano Zampini lnnz = (PetscBool)(is->A->nonzerostate == is->lnnzstate); 2902d0dbe9f7SStefano Zampini is->lnnzstate = is->A->nonzerostate; 2903*4f58015eSStefano Zampini PetscCall(MPIU_Allreduce(MPI_IN_PLACE, &lnnz, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 2904*4f58015eSStefano Zampini if (!lnnz) A->nonzerostate++; 29053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2906b4319ba4SBarry Smith } 2907b4319ba4SBarry Smith 2908d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISGetLocalMat_IS(Mat mat, Mat *local) 2909d71ae5a4SJacob Faibussowitsch { 2910b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)mat->data; 2911b4319ba4SBarry Smith 2912b4319ba4SBarry Smith PetscFunctionBegin; 2913b4319ba4SBarry Smith *local = is->A; 29143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2915b4319ba4SBarry Smith } 2916b4319ba4SBarry Smith 2917d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat, Mat *local) 2918d71ae5a4SJacob Faibussowitsch { 29193b3b1effSJed Brown PetscFunctionBegin; 29203b3b1effSJed Brown *local = NULL; 29213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 29223b3b1effSJed Brown } 29233b3b1effSJed Brown 2924b4319ba4SBarry Smith /*@ 292511a5261eSBarry Smith MatISGetLocalMat - Gets the local matrix stored inside a `MATIS` matrix. 2926b4319ba4SBarry Smith 2927*4f58015eSStefano Zampini Not Collective. 2928*4f58015eSStefano Zampini 2929b4319ba4SBarry Smith Input Parameter: 2930b4319ba4SBarry Smith . mat - the matrix 2931b4319ba4SBarry Smith 2932b4319ba4SBarry Smith Output Parameter: 2933eb82efa4SStefano Zampini . local - the local matrix 2934b4319ba4SBarry Smith 2935*4f58015eSStefano Zampini Level: intermediate 2936b4319ba4SBarry Smith 2937b4319ba4SBarry Smith Notes: 2938b4319ba4SBarry Smith This can be called if you have precomputed the nonzero structure of the 2939b4319ba4SBarry Smith matrix and want to provide it to the inner matrix object to improve the performance 294011a5261eSBarry Smith of the `MatSetValues()` operation. 2941b4319ba4SBarry Smith 294211a5261eSBarry Smith Call `MatISRestoreLocalMat()` when finished with the local matrix. 294396a6f129SJed Brown 29441cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatISRestoreLocalMat()` 2945b4319ba4SBarry Smith @*/ 2946d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISGetLocalMat(Mat mat, Mat *local) 2947d71ae5a4SJacob Faibussowitsch { 2948b4319ba4SBarry Smith PetscFunctionBegin; 29490700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 29504f572ea9SToby Isaac PetscAssertPointer(local, 2); 2951cac4c232SBarry Smith PetscUseMethod(mat, "MatISGetLocalMat_C", (Mat, Mat *), (mat, local)); 29523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2953b4319ba4SBarry Smith } 2954b4319ba4SBarry Smith 29553b3b1effSJed Brown /*@ 295611a5261eSBarry Smith MatISRestoreLocalMat - Restores the local matrix obtained with `MatISGetLocalMat()` 29573b3b1effSJed Brown 2958*4f58015eSStefano Zampini Not Collective. 2959*4f58015eSStefano Zampini 29602ef1f0ffSBarry Smith Input Parameters: 29612ef1f0ffSBarry Smith + mat - the matrix 29622ef1f0ffSBarry Smith - local - the local matrix 29633b3b1effSJed Brown 2964*4f58015eSStefano Zampini Level: intermediate 29653b3b1effSJed Brown 29661cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatISGetLocalMat()` 29673b3b1effSJed Brown @*/ 2968d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISRestoreLocalMat(Mat mat, Mat *local) 2969d71ae5a4SJacob Faibussowitsch { 29703b3b1effSJed Brown PetscFunctionBegin; 29713b3b1effSJed Brown PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 29724f572ea9SToby Isaac PetscAssertPointer(local, 2); 2973cac4c232SBarry Smith PetscUseMethod(mat, "MatISRestoreLocalMat_C", (Mat, Mat *), (mat, local)); 29743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 29753b3b1effSJed Brown } 29763b3b1effSJed Brown 2977d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISSetLocalMatType_IS(Mat mat, MatType mtype) 2978d71ae5a4SJacob Faibussowitsch { 29798546b261SStefano Zampini Mat_IS *is = (Mat_IS *)mat->data; 29808546b261SStefano Zampini 29818546b261SStefano Zampini PetscFunctionBegin; 29821baa6e33SBarry Smith if (is->A) PetscCall(MatSetType(is->A, mtype)); 29839566063dSJacob Faibussowitsch PetscCall(PetscFree(is->lmattype)); 29849566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(mtype, &is->lmattype)); 29853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 29868546b261SStefano Zampini } 29878546b261SStefano Zampini 2988fe59aa6dSJacob Faibussowitsch /*@C 298911a5261eSBarry Smith MatISSetLocalMatType - Specifies the type of local matrix inside the `MATIS` 29908546b261SStefano Zampini 2991*4f58015eSStefano Zampini Logically Collective. 2992*4f58015eSStefano Zampini 2993d8d19677SJose E. Roman Input Parameters: 2994a2b725a8SWilliam Gropp + mat - the matrix 2995a2b725a8SWilliam Gropp - mtype - the local matrix type 29968546b261SStefano Zampini 2997*4f58015eSStefano Zampini Level: intermediate 29988546b261SStefano Zampini 29991cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatSetType()`, `MatType` 30008546b261SStefano Zampini @*/ 3001d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISSetLocalMatType(Mat mat, MatType mtype) 3002d71ae5a4SJacob Faibussowitsch { 30038546b261SStefano Zampini PetscFunctionBegin; 30048546b261SStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3005cac4c232SBarry Smith PetscUseMethod(mat, "MatISSetLocalMatType_C", (Mat, MatType), (mat, mtype)); 30063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30078546b261SStefano Zampini } 30088546b261SStefano Zampini 3009d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISSetLocalMat_IS(Mat mat, Mat local) 3010d71ae5a4SJacob Faibussowitsch { 30113b03a366Sstefano_zampini Mat_IS *is = (Mat_IS *)mat->data; 30123b03a366Sstefano_zampini PetscInt nrows, ncols, orows, ocols; 30138546b261SStefano Zampini MatType mtype, otype; 30148546b261SStefano Zampini PetscBool sametype = PETSC_TRUE; 30153b03a366Sstefano_zampini 30163b03a366Sstefano_zampini PetscFunctionBegin; 3017e432b41dSStefano Zampini if (is->A && !is->islocalref) { 30189566063dSJacob Faibussowitsch PetscCall(MatGetSize(is->A, &orows, &ocols)); 30199566063dSJacob Faibussowitsch PetscCall(MatGetSize(local, &nrows, &ncols)); 3020aed4548fSBarry 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); 30219566063dSJacob Faibussowitsch PetscCall(MatGetType(local, &mtype)); 30229566063dSJacob Faibussowitsch PetscCall(MatGetType(is->A, &otype)); 30239566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, otype, &sametype)); 30244e4c7dbeSStefano Zampini } 30259566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)local)); 30269566063dSJacob Faibussowitsch PetscCall(MatDestroy(&is->A)); 30273b03a366Sstefano_zampini is->A = local; 30289566063dSJacob Faibussowitsch PetscCall(MatGetType(is->A, &mtype)); 30299566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(mat, mtype)); 303048a46eb9SPierre Jolivet if (!sametype && !is->islocalref) PetscCall(MatISSetUpScatters_Private(mat)); 3031*4f58015eSStefano Zampini is->lnnzstate = 0; 30323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30333b03a366Sstefano_zampini } 30343b03a366Sstefano_zampini 30353b03a366Sstefano_zampini /*@ 303611a5261eSBarry Smith MatISSetLocalMat - Replace the local matrix stored inside a `MATIS` object. 30373b03a366Sstefano_zampini 3038*4f58015eSStefano Zampini Not Collective 30398546b261SStefano Zampini 3040d8d19677SJose E. Roman Input Parameters: 3041a2b725a8SWilliam Gropp + mat - the matrix 3042a2b725a8SWilliam Gropp - local - the local matrix 30433b03a366Sstefano_zampini 3044*4f58015eSStefano Zampini Level: intermediate 304511a5261eSBarry Smith 30461cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatISSetLocalMatType`, `MatISGetLocalMat()` 30473b03a366Sstefano_zampini @*/ 3048d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISSetLocalMat(Mat mat, Mat local) 3049d71ae5a4SJacob Faibussowitsch { 30503b03a366Sstefano_zampini PetscFunctionBegin; 30513b03a366Sstefano_zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3052b7ce53b6SStefano Zampini PetscValidHeaderSpecific(local, MAT_CLASSID, 2); 3053cac4c232SBarry Smith PetscUseMethod(mat, "MatISSetLocalMat_C", (Mat, Mat), (mat, local)); 30543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30553b03a366Sstefano_zampini } 30563b03a366Sstefano_zampini 3057d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroEntries_IS(Mat A) 3058d71ae5a4SJacob Faibussowitsch { 30596726f965SBarry Smith Mat_IS *a = (Mat_IS *)A->data; 30606726f965SBarry Smith 30616726f965SBarry Smith PetscFunctionBegin; 30629566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(a->A)); 30633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30646726f965SBarry Smith } 30656726f965SBarry Smith 3066d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatScale_IS(Mat A, PetscScalar a) 3067d71ae5a4SJacob Faibussowitsch { 30682e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS *)A->data; 30692e74eeadSLisandro Dalcin 30702e74eeadSLisandro Dalcin PetscFunctionBegin; 30719566063dSJacob Faibussowitsch PetscCall(MatScale(is->A, a)); 30723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30732e74eeadSLisandro Dalcin } 30742e74eeadSLisandro Dalcin 3075d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v) 3076d71ae5a4SJacob Faibussowitsch { 30772e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS *)A->data; 30782e74eeadSLisandro Dalcin 30792e74eeadSLisandro Dalcin PetscFunctionBegin; 30802e74eeadSLisandro Dalcin /* get diagonal of the local matrix */ 30819566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(is->A, is->y)); 30822e74eeadSLisandro Dalcin 30832e74eeadSLisandro Dalcin /* scatter diagonal back into global vector */ 30849566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0)); 30859566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, is->y, v, ADD_VALUES, SCATTER_REVERSE)); 30869566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, is->y, v, ADD_VALUES, SCATTER_REVERSE)); 30873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30882e74eeadSLisandro Dalcin } 30892e74eeadSLisandro Dalcin 3090d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_IS(Mat A, MatOption op, PetscBool flg) 3091d71ae5a4SJacob Faibussowitsch { 30926726f965SBarry Smith Mat_IS *a = (Mat_IS *)A->data; 30936726f965SBarry Smith 30946726f965SBarry Smith PetscFunctionBegin; 30959566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg)); 30963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30976726f965SBarry Smith } 30986726f965SBarry Smith 3099d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAXPY_IS(Mat Y, PetscScalar a, Mat X, MatStructure str) 3100d71ae5a4SJacob Faibussowitsch { 3101f26d0771SStefano Zampini Mat_IS *y = (Mat_IS *)Y->data; 3102f26d0771SStefano Zampini Mat_IS *x; 3103f26d0771SStefano Zampini 3104f26d0771SStefano Zampini PetscFunctionBegin; 310576bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 310676bd3646SJed Brown PetscBool ismatis; 31079566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)X, MATIS, &ismatis)); 310828b400f6SJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)Y), PETSC_ERR_SUP, "Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS"); 310976bd3646SJed Brown } 3110f26d0771SStefano Zampini x = (Mat_IS *)X->data; 31119566063dSJacob Faibussowitsch PetscCall(MatAXPY(y->A, a, x->A, str)); 31123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3113f26d0771SStefano Zampini } 3114f26d0771SStefano Zampini 3115d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A, IS row, IS col, Mat *submat) 3116d71ae5a4SJacob Faibussowitsch { 3117f26d0771SStefano Zampini Mat lA; 3118f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)A->data; 3119f26d0771SStefano Zampini ISLocalToGlobalMapping rl2g, cl2g; 3120f26d0771SStefano Zampini IS is; 3121f26d0771SStefano Zampini const PetscInt *rg, *rl; 3122f26d0771SStefano Zampini PetscInt nrg; 3123f26d0771SStefano Zampini PetscInt N, M, nrl, i, *idxs; 3124f26d0771SStefano Zampini 3125f26d0771SStefano Zampini PetscFunctionBegin; 31269566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(A->rmap->mapping, &rg)); 31279566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(row, &nrl)); 31289566063dSJacob Faibussowitsch PetscCall(ISGetIndices(row, &rl)); 31299566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(A->rmap->mapping, &nrg)); 313076bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 313108401ef6SPierre 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); 313276bd3646SJed Brown } 31339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nrg, &idxs)); 3134f26d0771SStefano Zampini /* map from [0,nrl) to row */ 3135f26d0771SStefano Zampini for (i = 0; i < nrl; i++) idxs[i] = rl[i]; 3136f26d0771SStefano Zampini for (i = nrl; i < nrg; i++) idxs[i] = -1; 31379566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(row, &rl)); 31389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping, &rg)); 31399566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A), nrg, idxs, PETSC_OWN_POINTER, &is)); 31409566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g)); 31419566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3142f26d0771SStefano Zampini /* compute new l2g map for columns */ 3143e432b41dSStefano Zampini if (col != row || matis->rmapping != matis->cmapping || matis->A->rmap->mapping != matis->A->cmap->mapping) { 3144f26d0771SStefano Zampini const PetscInt *cg, *cl; 3145f26d0771SStefano Zampini PetscInt ncg; 3146f26d0771SStefano Zampini PetscInt ncl; 3147f26d0771SStefano Zampini 31489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(A->cmap->mapping, &cg)); 31499566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(col, &ncl)); 31509566063dSJacob Faibussowitsch PetscCall(ISGetIndices(col, &cl)); 31519566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(A->cmap->mapping, &ncg)); 315276bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 315308401ef6SPierre 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); 315476bd3646SJed Brown } 31559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncg, &idxs)); 3156f26d0771SStefano Zampini /* map from [0,ncl) to col */ 3157f26d0771SStefano Zampini for (i = 0; i < ncl; i++) idxs[i] = cl[i]; 3158f26d0771SStefano Zampini for (i = ncl; i < ncg; i++) idxs[i] = -1; 31599566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(col, &cl)); 31609566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping, &cg)); 31619566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A), ncg, idxs, PETSC_OWN_POINTER, &is)); 31629566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g)); 31639566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3164f26d0771SStefano Zampini } else { 31659566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)rl2g)); 3166f26d0771SStefano Zampini cl2g = rl2g; 3167f26d0771SStefano Zampini } 3168f26d0771SStefano Zampini /* create the MATIS submatrix */ 31699566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, &N)); 31709566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), submat)); 31719566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*submat, PETSC_DECIDE, PETSC_DECIDE, M, N)); 31729566063dSJacob Faibussowitsch PetscCall(MatSetType(*submat, MATIS)); 3173b0aa3428SStefano Zampini matis = (Mat_IS *)((*submat)->data); 3174f26d0771SStefano Zampini matis->islocalref = PETSC_TRUE; 31759566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*submat, rl2g, cl2g)); 31769566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A, &lA)); 31779566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*submat, lA)); 31789566063dSJacob Faibussowitsch PetscCall(MatSetUp(*submat)); 31799566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*submat, MAT_FINAL_ASSEMBLY)); 31809566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*submat, MAT_FINAL_ASSEMBLY)); 31819566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 31829566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 3183e432b41dSStefano Zampini 3184f26d0771SStefano Zampini /* remove unsupported ops */ 31859566063dSJacob Faibussowitsch PetscCall(PetscMemzero((*submat)->ops, sizeof(struct _MatOps))); 3186f26d0771SStefano Zampini (*submat)->ops->destroy = MatDestroy_IS; 3187f26d0771SStefano Zampini (*submat)->ops->setvalueslocal = MatSetValuesLocal_SubMat_IS; 3188f26d0771SStefano Zampini (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS; 3189f26d0771SStefano Zampini (*submat)->ops->assemblybegin = MatAssemblyBegin_IS; 3190f26d0771SStefano Zampini (*submat)->ops->assemblyend = MatAssemblyEnd_IS; 31913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3192f26d0771SStefano Zampini } 3193f26d0771SStefano Zampini 3194d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetFromOptions_IS(Mat A, PetscOptionItems *PetscOptionsObject) 3195d71ae5a4SJacob Faibussowitsch { 3196872cf891SStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 31978546b261SStefano Zampini char type[256]; 31988546b261SStefano Zampini PetscBool flg; 3199872cf891SStefano Zampini 3200872cf891SStefano Zampini PetscFunctionBegin; 3201d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "MATIS options"); 3202*4f58015eSStefano Zampini PetscCall(PetscOptionsDeprecated("-matis_keepassembled", "-mat_is_keepassembled", "3.21", NULL)); 3203*4f58015eSStefano Zampini PetscCall(PetscOptionsDeprecated("-matis_fixempty", "-mat_is_fixempty", "3.21", NULL)); 3204*4f58015eSStefano Zampini PetscCall(PetscOptionsDeprecated("-matis_storel2l", "-mat_is_storel2l", "3.21", NULL)); 3205*4f58015eSStefano Zampini PetscCall(PetscOptionsDeprecated("-matis_localmat_type", "-mat_is_localmat_type", "3.21", NULL)); 3206*4f58015eSStefano Zampini PetscCall(PetscOptionsBool("-mat_is_keepassembled", "Store an assembled version if needed", NULL, a->keepassembled, &a->keepassembled, NULL)); 3207*4f58015eSStefano Zampini PetscCall(PetscOptionsBool("-mat_is_fixempty", "Fix local matrices in case of empty local rows/columns", "MatISFixLocalEmpty", a->locempty, &a->locempty, NULL)); 3208*4f58015eSStefano Zampini PetscCall(PetscOptionsBool("-mat_is_storel2l", "Store local-to-local matrices generated from PtAP operations", "MatISStoreL2L", a->storel2l, &a->storel2l, NULL)); 3209*4f58015eSStefano Zampini PetscCall(PetscOptionsBool("-mat_is_allow_repeated", "Allow local repeated entries", "MatISSetAllowRepeated", a->allow_repeated, &a->allow_repeated, NULL)); 3210*4f58015eSStefano Zampini PetscCall(PetscOptionsFList("-mat_is_localmat_type", "Matrix type", "MatISSetLocalMatType", MatList, a->lmattype, type, 256, &flg)); 32111baa6e33SBarry Smith if (flg) PetscCall(MatISSetLocalMatType(A, type)); 32121baa6e33SBarry Smith if (a->A) PetscCall(MatSetFromOptions(a->A)); 3213d0609cedSBarry Smith PetscOptionsHeadEnd(); 32143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3215872cf891SStefano Zampini } 3216872cf891SStefano Zampini 3217284134d9SBarry Smith /*@ 3218*4f58015eSStefano Zampini MatCreateIS - Creates a "process" unassembled matrix. 3219*4f58015eSStefano Zampini 3220*4f58015eSStefano Zampini Collective. 3221284134d9SBarry Smith 3222284134d9SBarry Smith Input Parameters: 3223284134d9SBarry Smith + comm - MPI communicator that will share the matrix 3224e176bc59SStefano Zampini . bs - block size of the matrix 32252920cce0SJacob Faibussowitsch . m - local size of left vector used in matrix vector products 32262920cce0SJacob Faibussowitsch . n - local size of right vector used in matrix vector products 32272920cce0SJacob Faibussowitsch . M - global size of left vector used in matrix vector products 32282920cce0SJacob Faibussowitsch . N - global size of right vector used in matrix vector products 3229e176bc59SStefano Zampini . rmap - local to global map for rows 3230e176bc59SStefano Zampini - cmap - local to global map for cols 3231284134d9SBarry Smith 3232284134d9SBarry Smith Output Parameter: 3233284134d9SBarry Smith . A - the resulting matrix 3234284134d9SBarry Smith 3235*4f58015eSStefano Zampini Level: intermediate 32368e6c10adSSatish Balay 323795452b02SPatrick Sanan Notes: 32382ef1f0ffSBarry Smith `m` and `n` are NOT related to the size of the map; they represent the size of the local parts of the distributed vectors 3239*4f58015eSStefano Zampini used in `MatMult()` operations. The local sizes of `rmap` and `cmap` define the size of the local matrices. 324011a5261eSBarry Smith 32412ef1f0ffSBarry Smith If `rmap` (`cmap`) is `NULL`, then the local row (column) spaces matches the global space. 3242284134d9SBarry Smith 32431cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatSetLocalToGlobalMapping()` 3244284134d9SBarry Smith @*/ 3245d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateIS(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt M, PetscInt N, ISLocalToGlobalMapping rmap, ISLocalToGlobalMapping cmap, Mat *A) 3246d71ae5a4SJacob Faibussowitsch { 3247284134d9SBarry Smith PetscFunctionBegin; 32489566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, A)); 32499566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A, m, n, M, N)); 325048a46eb9SPierre Jolivet if (bs > 0) PetscCall(MatSetBlockSize(*A, bs)); 32519566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATIS)); 32529566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*A, rmap, cmap)); 32533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3254284134d9SBarry Smith } 3255284134d9SBarry Smith 3256d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHasOperation_IS(Mat A, MatOperation op, PetscBool *has) 3257d71ae5a4SJacob Faibussowitsch { 32588b9382cfSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3259e26763e4SStefano Zampini MatOperation tobefiltered[] = {MATOP_MULT_ADD, MATOP_MULT_TRANSPOSE_ADD, MATOP_GET_DIAGONAL_BLOCK, MATOP_INCREASE_OVERLAP}; 32608b9382cfSStefano Zampini 32618b9382cfSStefano Zampini PetscFunctionBegin; 32628b9382cfSStefano Zampini *has = PETSC_FALSE; 32633ba16761SJacob Faibussowitsch if (!((void **)A->ops)[op] || !a->A) PetscFunctionReturn(PETSC_SUCCESS); 3264d0dbe9f7SStefano Zampini *has = PETSC_TRUE; 32659371c9d4SSatish Balay for (PetscInt i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(tobefiltered); i++) 32663ba16761SJacob Faibussowitsch if (op == tobefiltered[i]) PetscFunctionReturn(PETSC_SUCCESS); 32679566063dSJacob Faibussowitsch PetscCall(MatHasOperation(a->A, op, has)); 32683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 32698b9382cfSStefano Zampini } 32708b9382cfSStefano Zampini 3271d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesCOO_IS(Mat A, const PetscScalar v[], InsertMode imode) 3272d71ae5a4SJacob Faibussowitsch { 3273e432b41dSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3274e432b41dSStefano Zampini 3275e432b41dSStefano Zampini PetscFunctionBegin; 32769566063dSJacob Faibussowitsch PetscCall(MatSetValuesCOO(a->A, v, imode)); 32779566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 32789566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 32793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3280e432b41dSStefano Zampini } 3281e432b41dSStefano Zampini 3282d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetPreallocationCOOLocal_IS(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[]) 3283d71ae5a4SJacob Faibussowitsch { 3284e432b41dSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3285e432b41dSStefano Zampini 3286e432b41dSStefano Zampini PetscFunctionBegin; 3287e432b41dSStefano Zampini PetscCheck(a->A, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Need to provide l2g map first via MatSetLocalToGlobalMapping"); 3288e432b41dSStefano Zampini if (a->A->rmap->mapping || a->A->cmap->mapping) { 32899566063dSJacob Faibussowitsch PetscCall(MatSetPreallocationCOOLocal(a->A, ncoo, coo_i, coo_j)); 3290e432b41dSStefano Zampini } else { 32919566063dSJacob Faibussowitsch PetscCall(MatSetPreallocationCOO(a->A, ncoo, coo_i, coo_j)); 3292e432b41dSStefano Zampini } 32939566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", MatSetValuesCOO_IS)); 3294e432b41dSStefano Zampini A->preallocated = PETSC_TRUE; 32953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3296e432b41dSStefano Zampini } 3297e432b41dSStefano Zampini 3298d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetPreallocationCOO_IS(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[]) 3299d71ae5a4SJacob Faibussowitsch { 3300e432b41dSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3301e432b41dSStefano Zampini 3302e432b41dSStefano Zampini PetscFunctionBegin; 3303e432b41dSStefano Zampini PetscCheck(a->A, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Need to provide l2g map first via MatSetLocalToGlobalMapping"); 3304e432b41dSStefano 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); 3305e8729f6fSJunchao Zhang PetscCall(ISGlobalToLocalMappingApply(a->rmapping, IS_GTOLM_MASK, ncoo, coo_i, NULL, coo_i)); 3306e8729f6fSJunchao Zhang PetscCall(ISGlobalToLocalMappingApply(a->cmapping, IS_GTOLM_MASK, ncoo, coo_j, NULL, coo_j)); 3307e8729f6fSJunchao Zhang PetscCall(MatSetPreallocationCOO(a->A, ncoo, coo_i, coo_j)); 33089566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", MatSetValuesCOO_IS)); 3309e432b41dSStefano Zampini A->preallocated = PETSC_TRUE; 33103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3311e432b41dSStefano Zampini } 3312e432b41dSStefano Zampini 3313d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISGetAssembled_Private(Mat A, Mat *tA) 3314d71ae5a4SJacob Faibussowitsch { 3315d0dbe9f7SStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3316d0dbe9f7SStefano Zampini PetscObjectState Astate, aAstate = PETSC_MIN_INT; 3317d0dbe9f7SStefano Zampini PetscObjectState Annzstate, aAnnzstate = PETSC_MIN_INT; 3318d0dbe9f7SStefano Zampini 3319d0dbe9f7SStefano Zampini PetscFunctionBegin; 3320d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateGet((PetscObject)A, &Astate)); 3321d0dbe9f7SStefano Zampini Annzstate = A->nonzerostate; 3322d0dbe9f7SStefano Zampini if (a->assembledA) { 3323d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateGet((PetscObject)a->assembledA, &aAstate)); 3324d0dbe9f7SStefano Zampini aAnnzstate = a->assembledA->nonzerostate; 3325d0dbe9f7SStefano Zampini } 3326d0dbe9f7SStefano Zampini if (aAnnzstate != Annzstate) PetscCall(MatDestroy(&a->assembledA)); 3327d0dbe9f7SStefano Zampini if (Astate != aAstate || !a->assembledA) { 3328d0dbe9f7SStefano Zampini MatType aAtype; 3329d0dbe9f7SStefano Zampini PetscMPIInt size; 3330d0dbe9f7SStefano Zampini PetscInt rbs, cbs, bs; 3331d0dbe9f7SStefano Zampini 3332d0dbe9f7SStefano Zampini /* the assembled form is used as temporary storage for parallel operations 3333d0dbe9f7SStefano Zampini like createsubmatrices and the like, do not waste device memory */ 3334d0dbe9f7SStefano Zampini PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 3335d0dbe9f7SStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockSize(a->cmapping, &cbs)); 3336d0dbe9f7SStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockSize(a->rmapping, &rbs)); 3337d0dbe9f7SStefano Zampini bs = rbs == cbs ? rbs : 1; 3338d0dbe9f7SStefano Zampini if (a->assembledA) PetscCall(MatGetType(a->assembledA, &aAtype)); 3339d0dbe9f7SStefano Zampini else if (size > 1) aAtype = bs > 1 ? MATMPIBAIJ : MATMPIAIJ; 3340d0dbe9f7SStefano Zampini else aAtype = bs > 1 ? MATSEQBAIJ : MATSEQAIJ; 3341d0dbe9f7SStefano Zampini 3342d0dbe9f7SStefano Zampini PetscCall(MatConvert(A, aAtype, a->assembledA ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX, &a->assembledA)); 3343d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateSet((PetscObject)a->assembledA, Astate)); 3344d0dbe9f7SStefano Zampini a->assembledA->nonzerostate = Annzstate; 3345d0dbe9f7SStefano Zampini } 3346d0dbe9f7SStefano Zampini PetscCall(PetscObjectReference((PetscObject)a->assembledA)); 3347d0dbe9f7SStefano Zampini *tA = a->assembledA; 3348d0dbe9f7SStefano Zampini if (!a->keepassembled) PetscCall(MatDestroy(&a->assembledA)); 33493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3350d0dbe9f7SStefano Zampini } 3351d0dbe9f7SStefano Zampini 3352d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISRestoreAssembled_Private(Mat A, Mat *tA) 3353d71ae5a4SJacob Faibussowitsch { 3354d0dbe9f7SStefano Zampini PetscFunctionBegin; 3355d0dbe9f7SStefano Zampini PetscCall(MatDestroy(tA)); 3356d0dbe9f7SStefano Zampini *tA = NULL; 33573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3358d0dbe9f7SStefano Zampini } 3359d0dbe9f7SStefano Zampini 3360d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonalBlock_IS(Mat A, Mat *dA) 3361d71ae5a4SJacob Faibussowitsch { 3362d0dbe9f7SStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3363d0dbe9f7SStefano Zampini PetscObjectState Astate, dAstate = PETSC_MIN_INT; 3364d0dbe9f7SStefano Zampini 3365d0dbe9f7SStefano Zampini PetscFunctionBegin; 3366d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateGet((PetscObject)A, &Astate)); 3367d0dbe9f7SStefano Zampini if (a->dA) PetscCall(PetscObjectStateGet((PetscObject)a->dA, &dAstate)); 3368d0dbe9f7SStefano Zampini if (Astate != dAstate) { 3369d0dbe9f7SStefano Zampini Mat tA; 3370d0dbe9f7SStefano Zampini MatType ltype; 3371d0dbe9f7SStefano Zampini 3372d0dbe9f7SStefano Zampini PetscCall(MatDestroy(&a->dA)); 3373d0dbe9f7SStefano Zampini PetscCall(MatISGetAssembled_Private(A, &tA)); 3374d0dbe9f7SStefano Zampini PetscCall(MatGetDiagonalBlock(tA, &a->dA)); 3375d0dbe9f7SStefano Zampini PetscCall(MatPropagateSymmetryOptions(tA, a->dA)); 3376d0dbe9f7SStefano Zampini PetscCall(MatGetType(a->A, <ype)); 3377d0dbe9f7SStefano Zampini PetscCall(MatConvert(a->dA, ltype, MAT_INPLACE_MATRIX, &a->dA)); 3378d0dbe9f7SStefano Zampini PetscCall(PetscObjectReference((PetscObject)a->dA)); 3379d0dbe9f7SStefano Zampini PetscCall(MatISRestoreAssembled_Private(A, &tA)); 3380d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateSet((PetscObject)a->dA, Astate)); 3381d0dbe9f7SStefano Zampini } 3382d0dbe9f7SStefano Zampini *dA = a->dA; 33833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3384d0dbe9f7SStefano Zampini } 3385d0dbe9f7SStefano Zampini 3386d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrices_IS(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse reuse, Mat *submat[]) 3387d71ae5a4SJacob Faibussowitsch { 3388d0dbe9f7SStefano Zampini Mat tA; 3389d0dbe9f7SStefano Zampini 3390d0dbe9f7SStefano Zampini PetscFunctionBegin; 3391d0dbe9f7SStefano Zampini PetscCall(MatISGetAssembled_Private(A, &tA)); 3392d0dbe9f7SStefano Zampini PetscCall(MatCreateSubMatrices(tA, n, irow, icol, reuse, submat)); 3393d0dbe9f7SStefano Zampini /* MatCreateSubMatrices_MPIAIJ is a mess at the moment */ 3394d0dbe9f7SStefano Zampini #if 0 3395d0dbe9f7SStefano Zampini { 3396d0dbe9f7SStefano Zampini Mat_IS *a = (Mat_IS*)A->data; 3397d0dbe9f7SStefano Zampini MatType ltype; 3398d0dbe9f7SStefano Zampini VecType vtype; 3399d0dbe9f7SStefano Zampini char *flg; 3400d0dbe9f7SStefano Zampini 3401d0dbe9f7SStefano Zampini PetscCall(MatGetType(a->A,<ype)); 3402d0dbe9f7SStefano Zampini PetscCall(MatGetVecType(a->A,&vtype)); 3403d0dbe9f7SStefano Zampini PetscCall(PetscStrstr(vtype,"cuda",&flg)); 3404d0dbe9f7SStefano Zampini if (!flg) PetscCall(PetscStrstr(vtype,"hip",&flg)); 3405d0dbe9f7SStefano Zampini if (!flg) PetscCall(PetscStrstr(vtype,"kokkos",&flg)); 3406d0dbe9f7SStefano Zampini if (flg) { 3407d0dbe9f7SStefano Zampini for (PetscInt i = 0; i < n; i++) { 3408d0dbe9f7SStefano Zampini Mat sA = (*submat)[i]; 3409d0dbe9f7SStefano Zampini 3410d0dbe9f7SStefano Zampini PetscCall(MatConvert(sA,ltype,MAT_INPLACE_MATRIX,&sA)); 3411d0dbe9f7SStefano Zampini (*submat)[i] = sA; 3412d0dbe9f7SStefano Zampini } 3413d0dbe9f7SStefano Zampini } 3414d0dbe9f7SStefano Zampini } 3415d0dbe9f7SStefano Zampini #endif 3416d0dbe9f7SStefano Zampini PetscCall(MatISRestoreAssembled_Private(A, &tA)); 34173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3418d0dbe9f7SStefano Zampini } 3419d0dbe9f7SStefano Zampini 3420d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIncreaseOverlap_IS(Mat A, PetscInt n, IS is[], PetscInt ov) 3421d71ae5a4SJacob Faibussowitsch { 3422d0dbe9f7SStefano Zampini Mat tA; 3423d0dbe9f7SStefano Zampini 3424d0dbe9f7SStefano Zampini PetscFunctionBegin; 3425d0dbe9f7SStefano Zampini PetscCall(MatISGetAssembled_Private(A, &tA)); 3426d0dbe9f7SStefano Zampini PetscCall(MatIncreaseOverlap(tA, n, is, ov)); 3427d0dbe9f7SStefano Zampini PetscCall(MatISRestoreAssembled_Private(A, &tA)); 34283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3429d0dbe9f7SStefano Zampini } 3430d0dbe9f7SStefano Zampini 3431e432b41dSStefano Zampini /*@ 343211a5261eSBarry Smith MatISGetLocalToGlobalMapping - Gets the local-to-global numbering of the `MATIS` object 3433e432b41dSStefano Zampini 3434e432b41dSStefano Zampini Not Collective 3435e432b41dSStefano Zampini 3436e432b41dSStefano Zampini Input Parameter: 3437e432b41dSStefano Zampini . A - the matrix 3438e432b41dSStefano Zampini 3439e432b41dSStefano Zampini Output Parameters: 3440e432b41dSStefano Zampini + rmapping - row mapping 3441e432b41dSStefano Zampini - cmapping - column mapping 3442e432b41dSStefano Zampini 34432ef1f0ffSBarry Smith Level: advanced 34442ef1f0ffSBarry Smith 344511a5261eSBarry Smith Note: 344611a5261eSBarry Smith The returned map can be different from the one used to construct the `MATIS` object, since it will not contain negative or repeated indices. 3447e432b41dSStefano Zampini 34481cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatIS`, `MatSetLocalToGlobalMapping()` 3449e432b41dSStefano Zampini @*/ 3450d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 3451d71ae5a4SJacob Faibussowitsch { 3452e432b41dSStefano Zampini PetscFunctionBegin; 3453e432b41dSStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3454e432b41dSStefano Zampini PetscValidType(A, 1); 34554f572ea9SToby Isaac if (rmapping) PetscAssertPointer(rmapping, 2); 34564f572ea9SToby Isaac if (cmapping) PetscAssertPointer(cmapping, 3); 3457cac4c232SBarry Smith PetscUseMethod(A, "MatISGetLocalToGlobalMapping_C", (Mat, ISLocalToGlobalMapping *, ISLocalToGlobalMapping *), (A, rmapping, cmapping)); 34583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3459e432b41dSStefano Zampini } 3460e432b41dSStefano Zampini 3461d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISGetLocalToGlobalMapping_IS(Mat A, ISLocalToGlobalMapping *r, ISLocalToGlobalMapping *c) 3462d71ae5a4SJacob Faibussowitsch { 3463e432b41dSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3464e432b41dSStefano Zampini 3465e432b41dSStefano Zampini PetscFunctionBegin; 3466e432b41dSStefano Zampini if (r) *r = a->rmapping; 3467e432b41dSStefano Zampini if (c) *c = a->cmapping; 34683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3469e432b41dSStefano Zampini } 3470e432b41dSStefano Zampini 3471b4319ba4SBarry Smith /*MC 3472*4f58015eSStefano Zampini MATIS - MATIS = "is" - A matrix type to be used for non-overlapping domain decomposition methods (e.g. `PCBDDC` or `KSPFETIDP`). 3473*4f58015eSStefano Zampini This stores the matrices in globally unassembled form and the parallel matrix vector product is handled "implicitly". 3474b4319ba4SBarry Smith 3475b4319ba4SBarry Smith Options Database Keys: 3476*4f58015eSStefano Zampini + -mat_type is - Set the matrix type to `MATIS`. 3477*4f58015eSStefano Zampini . -mat_is_allow_repeated - Allow repeated entries in the local part of the local to global maps. 3478*4f58015eSStefano Zampini . -mat_is_fixempty - Fix local matrices in case of empty local rows/columns. 3479*4f58015eSStefano Zampini - -mat_is_storel2l - Store the local-to-local operators generated by the Galerkin process of `MatPtAP()`. 34802ef1f0ffSBarry Smith 3481*4f58015eSStefano Zampini Level: intermediate 3482b4319ba4SBarry Smith 348395452b02SPatrick Sanan Notes: 34842ef1f0ffSBarry Smith Options prefix for the inner matrix are given by `-is_mat_xxx` 3485b4319ba4SBarry Smith 348611a5261eSBarry Smith You must call `MatSetLocalToGlobalMapping()` before using this matrix type. 3487b4319ba4SBarry Smith 3488b4319ba4SBarry Smith You can do matrix preallocation on the local matrix after you obtain it with 3489*4f58015eSStefano Zampini `MatISGetLocalMat()`; otherwise, you could use `MatISSetPreallocation()` or `MatXAIJSetPreallocation()` 3490b4319ba4SBarry Smith 34911cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `Mat`, `MatISGetLocalMat()`, `MatSetLocalToGlobalMapping()`, `MatISSetPreallocation()`, `MatCreateIS()`, `PCBDDC`, `KSPFETIDP` 3492b4319ba4SBarry Smith M*/ 3493d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A) 3494d71ae5a4SJacob Faibussowitsch { 3495e432b41dSStefano Zampini Mat_IS *a; 3496b4319ba4SBarry Smith 3497b4319ba4SBarry Smith PetscFunctionBegin; 34984dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&a)); 34999566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATAIJ, &a->lmattype)); 3500e432b41dSStefano Zampini A->data = (void *)a; 3501b4319ba4SBarry Smith 3502e176bc59SStefano Zampini /* matrix ops */ 35039566063dSJacob Faibussowitsch PetscCall(PetscMemzero(A->ops, sizeof(struct _MatOps))); 3504b4319ba4SBarry Smith A->ops->mult = MatMult_IS; 35052e74eeadSLisandro Dalcin A->ops->multadd = MatMultAdd_IS; 35062e74eeadSLisandro Dalcin A->ops->multtranspose = MatMultTranspose_IS; 35072e74eeadSLisandro Dalcin A->ops->multtransposeadd = MatMultTransposeAdd_IS; 3508b4319ba4SBarry Smith A->ops->destroy = MatDestroy_IS; 3509b4319ba4SBarry Smith A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS; 35102e74eeadSLisandro Dalcin A->ops->setvalues = MatSetValues_IS; 351198921651SStefano Zampini A->ops->setvaluesblocked = MatSetValuesBlocked_IS; 3512b4319ba4SBarry Smith A->ops->setvalueslocal = MatSetValuesLocal_IS; 3513f0006bf2SLisandro Dalcin A->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_IS; 35142e74eeadSLisandro Dalcin A->ops->zerorows = MatZeroRows_IS; 3515f0ae7da4SStefano Zampini A->ops->zerorowscolumns = MatZeroRowsColumns_IS; 3516b4319ba4SBarry Smith A->ops->assemblybegin = MatAssemblyBegin_IS; 3517b4319ba4SBarry Smith A->ops->assemblyend = MatAssemblyEnd_IS; 3518b4319ba4SBarry Smith A->ops->view = MatView_IS; 35196726f965SBarry Smith A->ops->zeroentries = MatZeroEntries_IS; 35202e74eeadSLisandro Dalcin A->ops->scale = MatScale_IS; 35212e74eeadSLisandro Dalcin A->ops->getdiagonal = MatGetDiagonal_IS; 35226726f965SBarry Smith A->ops->setoption = MatSetOption_IS; 352369796d55SStefano Zampini A->ops->ishermitian = MatIsHermitian_IS; 352469796d55SStefano Zampini A->ops->issymmetric = MatIsSymmetric_IS; 352545471136SStefano Zampini A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS; 3526ad6194a2SStefano Zampini A->ops->duplicate = MatDuplicate_IS; 35276bd84002SStefano Zampini A->ops->missingdiagonal = MatMissingDiagonal_IS; 35282b404112SStefano Zampini A->ops->copy = MatCopy_IS; 3529659959c5SStefano Zampini A->ops->getlocalsubmatrix = MatGetLocalSubMatrix_IS; 35307dae84e0SHong Zhang A->ops->createsubmatrix = MatCreateSubMatrix_IS; 3531f26d0771SStefano Zampini A->ops->axpy = MatAXPY_IS; 35323fd1c9e7SStefano Zampini A->ops->diagonalset = MatDiagonalSet_IS; 35333fd1c9e7SStefano Zampini A->ops->shift = MatShift_IS; 3534d7f69cd0SStefano Zampini A->ops->transpose = MatTranspose_IS; 35357fa8f2d3SStefano Zampini A->ops->getinfo = MatGetInfo_IS; 3536ad219c80Sstefano_zampini A->ops->diagonalscale = MatDiagonalScale_IS; 3537872cf891SStefano Zampini A->ops->setfromoptions = MatSetFromOptions_IS; 3538fc989267SStefano Zampini A->ops->setup = MatSetUp_IS; 35398b9382cfSStefano Zampini A->ops->hasoperation = MatHasOperation_IS; 3540d0dbe9f7SStefano Zampini A->ops->getdiagonalblock = MatGetDiagonalBlock_IS; 3541d0dbe9f7SStefano Zampini A->ops->createsubmatrices = MatCreateSubMatrices_IS; 3542d0dbe9f7SStefano Zampini A->ops->increaseoverlap = MatIncreaseOverlap_IS; 3543b4319ba4SBarry Smith 3544b7ce53b6SStefano Zampini /* special MATIS functions */ 35459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMatType_C", MatISSetLocalMatType_IS)); 35469566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalMat_C", MatISGetLocalMat_IS)); 35479566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISRestoreLocalMat_C", MatISRestoreLocalMat_IS)); 35489566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMat_C", MatISSetLocalMat_IS)); 35499566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetPreallocation_C", MatISSetPreallocation_IS)); 3550*4f58015eSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetAllowRepeated_C", MatISSetAllowRepeated_IS)); 35519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISStoreL2L_C", MatISStoreL2L_IS)); 35529566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISFixLocalEmpty_C", MatISFixLocalEmpty_IS)); 35539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalToGlobalMapping_C", MatISGetLocalToGlobalMapping_IS)); 35549566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpiaij_C", MatConvert_IS_XAIJ)); 35559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpibaij_C", MatConvert_IS_XAIJ)); 35569566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpisbaij_C", MatConvert_IS_XAIJ)); 35579566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqaij_C", MatConvert_IS_XAIJ)); 35589566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqbaij_C", MatConvert_IS_XAIJ)); 35599566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqsbaij_C", MatConvert_IS_XAIJ)); 35609566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_aij_C", MatConvert_IS_XAIJ)); 35619566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOOLocal_C", MatSetPreallocationCOOLocal_IS)); 35629566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_IS)); 35639566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, MATIS)); 35643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3565b4319ba4SBarry Smith } 3566