1b4319ba4SBarry Smith /* 2b4319ba4SBarry Smith Creates a matrix class for using the Neumann-Neumann type preconditioners. 3b4319ba4SBarry Smith This stores the matrices in globally unassembled form. Each processor 4b4319ba4SBarry Smith assembles only its local Neumann problem and the parallel matrix vector 5b4319ba4SBarry Smith product is handled "implicitly". 6b4319ba4SBarry Smith 7b4319ba4SBarry Smith Currently this allows for only one subdomain per processor. 8b4319ba4SBarry Smith */ 9b4319ba4SBarry Smith 10d0dbe9f7SStefano Zampini #include <petsc/private/matisimpl.h> /*I "petscmat.h" I*/ 115042aa92SStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h> 124f2d7cafSStefano Zampini #include <petsc/private/sfimpl.h> 13a72d46e8SStefano Zampini #include <petsc/private/vecimpl.h> 14e432b41dSStefano Zampini #include <petsc/private/hashseti.h> 1528f4e0baSStefano Zampini 16f26d0771SStefano Zampini #define MATIS_MAX_ENTRIES_INSERTION 2048 17b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat, PetscInt, const PetscInt *, PetscInt, const PetscInt *, const PetscScalar *, InsertMode); 18b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat, PetscInt, const PetscInt *, PetscInt, const PetscInt *, const PetscScalar *, InsertMode); 198546b261SStefano Zampini static PetscErrorCode MatISSetUpScatters_Private(Mat); 20f26d0771SStefano Zampini 2149abdd8aSBarry Smith static PetscErrorCode MatISContainerDestroyPtAP_Private(void **ptr) 22d71ae5a4SJacob Faibussowitsch { 2349abdd8aSBarry Smith MatISPtAP ptap = (MatISPtAP)*ptr; 2475d48cdbSStefano Zampini 2575d48cdbSStefano Zampini PetscFunctionBegin; 269566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrices(ptap->ris1 ? 2 : 1, &ptap->lP)); 279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ptap->cis0)); 289566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ptap->cis1)); 299566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ptap->ris0)); 309566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ptap->ris1)); 319566063dSJacob Faibussowitsch PetscCall(PetscFree(ptap)); 323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3375d48cdbSStefano Zampini } 3475d48cdbSStefano Zampini 35d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_IS_XAIJ(Mat A, Mat P, Mat C) 36d71ae5a4SJacob Faibussowitsch { 3775d48cdbSStefano Zampini MatISPtAP ptap; 3875d48cdbSStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 3975d48cdbSStefano Zampini Mat lA, lC; 4075d48cdbSStefano Zampini MatReuse reuse; 4175d48cdbSStefano Zampini IS ris[2], cis[2]; 4275d48cdbSStefano Zampini PetscContainer c; 4375d48cdbSStefano Zampini PetscInt n; 4475d48cdbSStefano Zampini 4575d48cdbSStefano Zampini PetscFunctionBegin; 469566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)C, "_MatIS_PtAP", (PetscObject *)&c)); 4728b400f6SJacob Faibussowitsch PetscCheck(c, PetscObjectComm((PetscObject)C), PETSC_ERR_PLIB, "Missing PtAP information"); 489566063dSJacob Faibussowitsch PetscCall(PetscContainerGetPointer(c, (void **)&ptap)); 4975d48cdbSStefano Zampini ris[0] = ptap->ris0; 5075d48cdbSStefano Zampini ris[1] = ptap->ris1; 5175d48cdbSStefano Zampini cis[0] = ptap->cis0; 5275d48cdbSStefano Zampini cis[1] = ptap->cis1; 5375d48cdbSStefano Zampini n = ptap->ris1 ? 2 : 1; 5475d48cdbSStefano Zampini reuse = ptap->lP ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX; 559566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(P, n, ris, cis, reuse, &ptap->lP)); 5675d48cdbSStefano Zampini 579566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A, &lA)); 589566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(C, &lC)); 5975d48cdbSStefano Zampini if (ptap->ris1) { /* unsymmetric A mapping */ 6075d48cdbSStefano Zampini Mat lPt; 6175d48cdbSStefano Zampini 629566063dSJacob Faibussowitsch PetscCall(MatTranspose(ptap->lP[1], MAT_INITIAL_MATRIX, &lPt)); 639566063dSJacob Faibussowitsch PetscCall(MatMatMatMult(lPt, lA, ptap->lP[0], reuse, ptap->fill, &lC)); 6457508eceSPierre Jolivet if (matis->storel2l) PetscCall(PetscObjectCompose((PetscObject)A, "_MatIS_PtAP_l2l", (PetscObject)lPt)); 659566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lPt)); 6675d48cdbSStefano Zampini } else { 679566063dSJacob Faibussowitsch PetscCall(MatPtAP(lA, ptap->lP[0], reuse, ptap->fill, &lC)); 6848a46eb9SPierre Jolivet if (matis->storel2l) PetscCall(PetscObjectCompose((PetscObject)C, "_MatIS_PtAP_l2l", (PetscObject)ptap->lP[0])); 6975d48cdbSStefano Zampini } 7075d48cdbSStefano Zampini if (reuse == MAT_INITIAL_MATRIX) { 719566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(C, lC)); 729566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lC)); 7375d48cdbSStefano Zampini } 749566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 759566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7775d48cdbSStefano Zampini } 7875d48cdbSStefano Zampini 79d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetNonzeroColumnsLocal_Private(Mat PT, IS *cis) 80d71ae5a4SJacob Faibussowitsch { 8175d48cdbSStefano Zampini Mat Po, Pd; 8275d48cdbSStefano Zampini IS zd, zo; 8375d48cdbSStefano Zampini const PetscInt *garray; 8475d48cdbSStefano Zampini PetscInt *aux, i, bs; 8575d48cdbSStefano Zampini PetscInt dc, stc, oc, ctd, cto; 8675d48cdbSStefano Zampini PetscBool ismpiaij, ismpibaij, isseqaij, isseqbaij; 8775d48cdbSStefano Zampini MPI_Comm comm; 8875d48cdbSStefano Zampini 8975d48cdbSStefano Zampini PetscFunctionBegin; 9075d48cdbSStefano Zampini PetscValidHeaderSpecific(PT, MAT_CLASSID, 1); 914f572ea9SToby Isaac PetscAssertPointer(cis, 2); 929566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)PT, &comm)); 9375d48cdbSStefano Zampini bs = 1; 949566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)PT, MATMPIAIJ, &ismpiaij)); 959566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)PT, MATMPIBAIJ, &ismpibaij)); 969566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)PT, MATSEQAIJ, &isseqaij)); 979566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)PT, MATSEQBAIJ, &isseqbaij)); 9875d48cdbSStefano Zampini if (isseqaij || isseqbaij) { 9975d48cdbSStefano Zampini Pd = PT; 10075d48cdbSStefano Zampini Po = NULL; 10175d48cdbSStefano Zampini garray = NULL; 10275d48cdbSStefano Zampini } else if (ismpiaij) { 1039566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(PT, &Pd, &Po, &garray)); 10475d48cdbSStefano Zampini } else if (ismpibaij) { 1059566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJGetSeqBAIJ(PT, &Pd, &Po, &garray)); 1069566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(PT, &bs)); 10757508eceSPierre Jolivet } else SETERRQ(comm, PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)PT)->type_name); 10875d48cdbSStefano Zampini 10975d48cdbSStefano Zampini /* identify any null columns in Pd or Po */ 11022f7620eSStefano Zampini /* We use a tolerance comparison since it may happen that, with geometric multigrid, 11122f7620eSStefano Zampini some of the columns are not really zero, but very close to */ 11275d48cdbSStefano Zampini zo = zd = NULL; 11348a46eb9SPierre Jolivet if (Po) PetscCall(MatFindNonzeroRowsOrCols_Basic(Po, PETSC_TRUE, PETSC_SMALL, &zo)); 1149566063dSJacob Faibussowitsch PetscCall(MatFindNonzeroRowsOrCols_Basic(Pd, PETSC_TRUE, PETSC_SMALL, &zd)); 11575d48cdbSStefano Zampini 1169566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(PT, NULL, &dc)); 1179566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(PT, &stc, NULL)); 1189566063dSJacob Faibussowitsch if (Po) PetscCall(MatGetLocalSize(Po, NULL, &oc)); 11975d48cdbSStefano Zampini else oc = 0; 1209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((dc + oc) / bs, &aux)); 12175d48cdbSStefano Zampini if (zd) { 12275d48cdbSStefano Zampini const PetscInt *idxs; 12375d48cdbSStefano Zampini PetscInt nz; 12475d48cdbSStefano Zampini 12575d48cdbSStefano Zampini /* this will throw an error if bs is not valid */ 1269566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(zd, bs)); 1279566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zd, &nz)); 1289566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zd, &idxs)); 12975d48cdbSStefano Zampini ctd = nz / bs; 13075d48cdbSStefano Zampini for (i = 0; i < ctd; i++) aux[i] = (idxs[bs * i] + stc) / bs; 1319566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zd, &idxs)); 13275d48cdbSStefano Zampini } else { 13375d48cdbSStefano Zampini ctd = dc / bs; 13475d48cdbSStefano Zampini for (i = 0; i < ctd; i++) aux[i] = i + stc / bs; 13575d48cdbSStefano Zampini } 13675d48cdbSStefano Zampini if (zo) { 13775d48cdbSStefano Zampini const PetscInt *idxs; 13875d48cdbSStefano Zampini PetscInt nz; 13975d48cdbSStefano Zampini 14075d48cdbSStefano Zampini /* this will throw an error if bs is not valid */ 1419566063dSJacob Faibussowitsch PetscCall(ISSetBlockSize(zo, bs)); 1429566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zo, &nz)); 1439566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zo, &idxs)); 14475d48cdbSStefano Zampini cto = nz / bs; 14575d48cdbSStefano Zampini for (i = 0; i < cto; i++) aux[i + ctd] = garray[idxs[bs * i] / bs]; 1469566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zo, &idxs)); 14775d48cdbSStefano Zampini } else { 14875d48cdbSStefano Zampini cto = oc / bs; 14975d48cdbSStefano Zampini for (i = 0; i < cto; i++) aux[i + ctd] = garray[i]; 15075d48cdbSStefano Zampini } 1519566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, bs, ctd + cto, aux, PETSC_OWN_POINTER, cis)); 1529566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zd)); 1539566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zo)); 1543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 15575d48cdbSStefano Zampini } 15675d48cdbSStefano Zampini 157d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPSymbolic_IS_XAIJ(Mat A, Mat P, PetscReal fill, Mat C) 158d71ae5a4SJacob Faibussowitsch { 1598546b261SStefano Zampini Mat PT, lA; 16075d48cdbSStefano Zampini MatISPtAP ptap; 16175d48cdbSStefano Zampini ISLocalToGlobalMapping Crl2g, Ccl2g, rl2g, cl2g; 16275d48cdbSStefano Zampini PetscContainer c; 1638546b261SStefano Zampini MatType lmtype; 16475d48cdbSStefano Zampini const PetscInt *garray; 16575d48cdbSStefano Zampini PetscInt ibs, N, dc; 16675d48cdbSStefano Zampini MPI_Comm comm; 16775d48cdbSStefano Zampini 16875d48cdbSStefano Zampini PetscFunctionBegin; 1699566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 1709566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATIS)); 1719566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A, &lA)); 1729566063dSJacob Faibussowitsch PetscCall(MatGetType(lA, &lmtype)); 1739566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(C, lmtype)); 1749566063dSJacob Faibussowitsch PetscCall(MatGetSize(P, NULL, &N)); 1759566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(P, NULL, &dc)); 1769566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, dc, dc, N, N)); 17775d48cdbSStefano Zampini /* Not sure about this 1789566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(P,NULL,&ibs)); 1799566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(*C,ibs)); 18075d48cdbSStefano Zampini */ 18175d48cdbSStefano Zampini 1829566063dSJacob Faibussowitsch PetscCall(PetscNew(&ptap)); 1839566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c)); 1849566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(c, ptap)); 18549abdd8aSBarry Smith PetscCall(PetscContainerSetCtxDestroy(c, MatISContainerDestroyPtAP_Private)); 1869566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)C, "_MatIS_PtAP", (PetscObject)c)); 1879566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&c)); 18875d48cdbSStefano Zampini ptap->fill = fill; 18975d48cdbSStefano Zampini 1909566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(A, &rl2g, &cl2g)); 19175d48cdbSStefano Zampini 1929566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(cl2g, &ibs)); 1939566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(cl2g, &N)); 1949566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(cl2g, &garray)); 1959566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, ibs, N / ibs, garray, PETSC_COPY_VALUES, &ptap->ris0)); 1969566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(cl2g, &garray)); 19775d48cdbSStefano Zampini 1989566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(P, ptap->ris0, NULL, MAT_INITIAL_MATRIX, &PT)); 1999566063dSJacob Faibussowitsch PetscCall(MatGetNonzeroColumnsLocal_Private(PT, &ptap->cis0)); 2009566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(ptap->cis0, &Ccl2g)); 2019566063dSJacob Faibussowitsch PetscCall(MatDestroy(&PT)); 20275d48cdbSStefano Zampini 20375d48cdbSStefano Zampini Crl2g = NULL; 20475d48cdbSStefano Zampini if (rl2g != cl2g) { /* unsymmetric A mapping */ 20575d48cdbSStefano Zampini PetscBool same, lsame = PETSC_FALSE; 20675d48cdbSStefano Zampini PetscInt N1, ibs1; 20775d48cdbSStefano Zampini 2089566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(rl2g, &N1)); 2099566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(rl2g, &ibs1)); 2109566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(rl2g, &garray)); 2114f58015eSStefano Zampini PetscCall(ISCreateBlock(comm, ibs, N1 / ibs, garray, PETSC_COPY_VALUES, &ptap->ris1)); 2129566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(rl2g, &garray)); 21375d48cdbSStefano Zampini if (ibs1 == ibs && N1 == N) { /* check if the l2gmaps are the same */ 21475d48cdbSStefano Zampini const PetscInt *i1, *i2; 21575d48cdbSStefano Zampini 2169566063dSJacob Faibussowitsch PetscCall(ISBlockGetIndices(ptap->ris0, &i1)); 2179566063dSJacob Faibussowitsch PetscCall(ISBlockGetIndices(ptap->ris1, &i2)); 2189566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(i1, i2, N, &lsame)); 21975d48cdbSStefano Zampini } 220*5440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&lsame, &same, 1, MPI_C_BOOL, MPI_LAND, comm)); 22175d48cdbSStefano Zampini if (same) { 2229566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ptap->ris1)); 22375d48cdbSStefano Zampini } else { 2249566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(P, ptap->ris1, NULL, MAT_INITIAL_MATRIX, &PT)); 2259566063dSJacob Faibussowitsch PetscCall(MatGetNonzeroColumnsLocal_Private(PT, &ptap->cis1)); 2269566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(ptap->cis1, &Crl2g)); 2279566063dSJacob Faibussowitsch PetscCall(MatDestroy(&PT)); 22875d48cdbSStefano Zampini } 22975d48cdbSStefano Zampini } 23075d48cdbSStefano Zampini /* Not sure about this 23175d48cdbSStefano Zampini if (!Crl2g) { 2329566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(C,&ibs)); 2339566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetBlockSize(Ccl2g,ibs)); 23475d48cdbSStefano Zampini } 23575d48cdbSStefano Zampini */ 2369566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(C, Crl2g ? Crl2g : Ccl2g, Ccl2g)); 2379566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&Crl2g)); 2389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&Ccl2g)); 23975d48cdbSStefano Zampini 2404222ddf1SHong Zhang C->ops->ptapnumeric = MatPtAPNumeric_IS_XAIJ; 2413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24275d48cdbSStefano Zampini } 24375d48cdbSStefano Zampini 244d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_PtAP_IS_XAIJ(Mat C) 245d71ae5a4SJacob Faibussowitsch { 2464222ddf1SHong Zhang Mat_Product *product = C->product; 2474222ddf1SHong Zhang Mat A = product->A, P = product->B; 2484222ddf1SHong Zhang PetscReal fill = product->fill; 24975d48cdbSStefano Zampini 25075d48cdbSStefano Zampini PetscFunctionBegin; 2519566063dSJacob Faibussowitsch PetscCall(MatPtAPSymbolic_IS_XAIJ(A, P, fill, C)); 2524222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_PtAP; 2533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25475d48cdbSStefano Zampini } 25575d48cdbSStefano Zampini 256d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_IS_XAIJ_PtAP(Mat C) 257d71ae5a4SJacob Faibussowitsch { 2584222ddf1SHong Zhang PetscFunctionBegin; 2594222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_PtAP_IS_XAIJ; 2603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2614222ddf1SHong Zhang } 2624222ddf1SHong Zhang 263d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat C) 264d71ae5a4SJacob Faibussowitsch { 2654222ddf1SHong Zhang Mat_Product *product = C->product; 2664222ddf1SHong Zhang 2674222ddf1SHong Zhang PetscFunctionBegin; 26848a46eb9SPierre Jolivet if (product->type == MATPRODUCT_PtAP) PetscCall(MatProductSetFromOptions_IS_XAIJ_PtAP(C)); 2693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2704222ddf1SHong Zhang } 2714222ddf1SHong Zhang 27249abdd8aSBarry Smith static PetscErrorCode MatISContainerDestroyFields_Private(void **ptr) 273d71ae5a4SJacob Faibussowitsch { 27449abdd8aSBarry Smith MatISLocalFields lf = (MatISLocalFields)*ptr; 2755b003df0Sstefano_zampini PetscInt i; 2765b003df0Sstefano_zampini 277ab4d48faSStefano Zampini PetscFunctionBegin; 27848a46eb9SPierre Jolivet for (i = 0; i < lf->nr; i++) PetscCall(ISDestroy(&lf->rf[i])); 27948a46eb9SPierre Jolivet for (i = 0; i < lf->nc; i++) PetscCall(ISDestroy(&lf->cf[i])); 2809566063dSJacob Faibussowitsch PetscCall(PetscFree2(lf->rf, lf->cf)); 2819566063dSJacob Faibussowitsch PetscCall(PetscFree(lf)); 2823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2835b003df0Sstefano_zampini } 284a72627d2SStefano Zampini 285d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_SeqXAIJ_IS(Mat A, MatType type, MatReuse reuse, Mat *newmat) 286d71ae5a4SJacob Faibussowitsch { 287c9225affSStefano Zampini Mat B, lB; 288c9225affSStefano Zampini 289c9225affSStefano Zampini PetscFunctionBegin; 290c9225affSStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 291c9225affSStefano Zampini ISLocalToGlobalMapping rl2g, cl2g; 292c9225affSStefano Zampini PetscInt bs; 293c9225affSStefano Zampini IS is; 294c9225affSStefano Zampini 2959566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 2969566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), A->rmap->n / bs, 0, 1, &is)); 297c9225affSStefano Zampini if (bs > 1) { 298c9225affSStefano Zampini IS is2; 299c9225affSStefano Zampini PetscInt i, *aux; 300c9225affSStefano Zampini 3019566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &i)); 3029566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, (const PetscInt **)&aux)); 3039566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), bs, i, aux, PETSC_COPY_VALUES, &is2)); 3049566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, (const PetscInt **)&aux)); 3059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 306c9225affSStefano Zampini is = is2; 307c9225affSStefano Zampini } 3089566063dSJacob Faibussowitsch PetscCall(ISSetIdentity(is)); 3099566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g)); 3109566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3119566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), A->cmap->n / bs, 0, 1, &is)); 312c9225affSStefano Zampini if (bs > 1) { 313c9225affSStefano Zampini IS is2; 314c9225affSStefano Zampini PetscInt i, *aux; 315c9225affSStefano Zampini 3169566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &i)); 3179566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, (const PetscInt **)&aux)); 3189566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), bs, i, aux, PETSC_COPY_VALUES, &is2)); 3199566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, (const PetscInt **)&aux)); 3209566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 321c9225affSStefano Zampini is = is2; 322c9225affSStefano Zampini } 3239566063dSJacob Faibussowitsch PetscCall(ISSetIdentity(is)); 3249566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g)); 3259566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3269566063dSJacob Faibussowitsch PetscCall(MatCreateIS(PetscObjectComm((PetscObject)A), bs, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N, rl2g, cl2g, &B)); 3279566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 3289566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 3299566063dSJacob Faibussowitsch PetscCall(MatDuplicate(A, MAT_COPY_VALUES, &lB)); 330c9225affSStefano Zampini if (reuse == MAT_INITIAL_MATRIX) *newmat = B; 331c9225affSStefano Zampini } else { 332c9225affSStefano Zampini B = *newmat; 3339566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)A)); 334c9225affSStefano Zampini lB = A; 335c9225affSStefano Zampini } 3369566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B, lB)); 3379566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lB)); 3389566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 3399566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 34048a46eb9SPierre Jolivet if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &B)); 3413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 342c9225affSStefano Zampini } 343c9225affSStefano Zampini 344d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISScaleDisassembling_Private(Mat A) 345d71ae5a4SJacob Faibussowitsch { 346f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)A->data; 347c9225affSStefano Zampini PetscScalar *aa; 348c9225affSStefano Zampini const PetscInt *ii, *jj; 349c9225affSStefano Zampini PetscInt i, n, m; 350fabe8965SStefano Zampini PetscInt *ecount, **eneighs; 351c9225affSStefano Zampini PetscBool flg; 352c9225affSStefano Zampini 353c9225affSStefano Zampini PetscFunctionBegin; 3549566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(matis->A, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg)); 35508401ef6SPierre Jolivet PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get IJ structure"); 3569566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetNodeInfo(matis->rmapping, &n, &ecount, &eneighs)); 35708401ef6SPierre Jolivet PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, m, n); 3589566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(matis->A, &aa)); 359c9225affSStefano Zampini for (i = 0; i < n; i++) { 360fabe8965SStefano Zampini if (ecount[i] > 1) { 361c9225affSStefano Zampini PetscInt j; 362c9225affSStefano Zampini 363c9225affSStefano Zampini for (j = ii[i]; j < ii[i + 1]; j++) { 364c9225affSStefano Zampini PetscInt i2 = jj[j], p, p2; 365fabe8965SStefano Zampini PetscReal scal = 0.0; 366c9225affSStefano Zampini 367c9225affSStefano Zampini for (p = 0; p < ecount[i]; p++) { 368c9225affSStefano Zampini for (p2 = 0; p2 < ecount[i2]; p2++) { 3699371c9d4SSatish Balay if (eneighs[i][p] == eneighs[i2][p2]) { 3709371c9d4SSatish Balay scal += 1.0; 3719371c9d4SSatish Balay break; 3729371c9d4SSatish Balay } 373c9225affSStefano Zampini } 374c9225affSStefano Zampini } 375fabe8965SStefano Zampini if (scal) aa[j] /= scal; 376c9225affSStefano Zampini } 377c9225affSStefano Zampini } 378c9225affSStefano Zampini } 3799566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(matis->rmapping, &n, &ecount, &eneighs)); 3809566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(matis->A, &aa)); 3819566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(matis->A, 0, PETSC_FALSE, PETSC_FALSE, &m, &ii, &jj, &flg)); 38208401ef6SPierre Jolivet PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot restore IJ structure"); 3833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 384c9225affSStefano Zampini } 385c9225affSStefano Zampini 3869371c9d4SSatish Balay typedef enum { 3879371c9d4SSatish Balay MAT_IS_DISASSEMBLE_L2G_NATURAL, 3889371c9d4SSatish Balay MAT_IS_DISASSEMBLE_L2G_MAT, 3899371c9d4SSatish Balay MAT_IS_DISASSEMBLE_L2G_ND 3909371c9d4SSatish Balay } MatISDisassemblel2gType; 391fabe8965SStefano Zampini 392d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMPIXAIJComputeLocalToGlobalMapping_Private(Mat A, ISLocalToGlobalMapping *l2g) 393d71ae5a4SJacob Faibussowitsch { 394fabe8965SStefano Zampini Mat Ad, Ao; 395fabe8965SStefano Zampini IS is, ndmap, ndsub; 396c9225affSStefano Zampini MPI_Comm comm; 397fabe8965SStefano Zampini const PetscInt *garray, *ndmapi; 398fabe8965SStefano Zampini PetscInt bs, i, cnt, nl, *ncount, *ndmapc; 399fabe8965SStefano Zampini PetscBool ismpiaij, ismpibaij; 400f4259b30SLisandro Dalcin const char *const MatISDisassemblel2gTypes[] = {"NATURAL", "MAT", "ND", "MatISDisassemblel2gType", "MAT_IS_DISASSEMBLE_L2G_", NULL}; 401fabe8965SStefano Zampini MatISDisassemblel2gType mode = MAT_IS_DISASSEMBLE_L2G_NATURAL; 402fabe8965SStefano Zampini MatPartitioning part; 403fabe8965SStefano Zampini PetscSF sf; 40491d376acSStefano Zampini PetscObject dm; 405c9225affSStefano Zampini 406c9225affSStefano Zampini PetscFunctionBegin; 407d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)A), ((PetscObject)A)->prefix, "MatIS l2g disassembling options", "Mat"); 4089566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-mat_is_disassemble_l2g_type", "Type of local-to-global mapping to be used for disassembling", "MatISDisassemblel2gType", MatISDisassemblel2gTypes, (PetscEnum)mode, (PetscEnum *)&mode, NULL)); 409d0609cedSBarry Smith PetscOptionsEnd(); 410fabe8965SStefano Zampini if (mode == MAT_IS_DISASSEMBLE_L2G_MAT) { 4119566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(A, l2g, NULL)); 4123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 413c9225affSStefano Zampini } 4149566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 4159566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 4169566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIBAIJ, &ismpibaij)); 4179566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 418fabe8965SStefano Zampini switch (mode) { 419fabe8965SStefano Zampini case MAT_IS_DISASSEMBLE_L2G_ND: 4209566063dSJacob Faibussowitsch PetscCall(MatPartitioningCreate(comm, &part)); 4219566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetAdjacency(part, A)); 4229566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)part, ((PetscObject)A)->prefix)); 4239566063dSJacob Faibussowitsch PetscCall(MatPartitioningSetFromOptions(part)); 4249566063dSJacob Faibussowitsch PetscCall(MatPartitioningApplyND(part, &ndmap)); 4259566063dSJacob Faibussowitsch PetscCall(MatPartitioningDestroy(&part)); 4269566063dSJacob Faibussowitsch PetscCall(ISBuildTwoSided(ndmap, NULL, &ndsub)); 4279566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetUseScalableIncreaseOverlap(A, PETSC_TRUE)); 4289566063dSJacob Faibussowitsch PetscCall(MatIncreaseOverlap(A, 1, &ndsub, 1)); 4299566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(ndsub, l2g)); 430fabe8965SStefano Zampini 431fabe8965SStefano Zampini /* it may happen that a separator node is not properly shared */ 4329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetNodeInfo(*l2g, &nl, &ncount, NULL)); 4339566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(comm, &sf)); 4349566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(*l2g, &garray)); 4359566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(sf, A->rmap, nl, NULL, PETSC_OWN_POINTER, garray)); 4369566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(*l2g, &garray)); 4379566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(A->rmap->n, &ndmapc)); 4389566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(sf, MPIU_INT, ncount, ndmapc, MPI_REPLACE)); 4399566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(sf, MPIU_INT, ncount, ndmapc, MPI_REPLACE)); 4409566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreNodeInfo(*l2g, NULL, &ncount, NULL)); 4419566063dSJacob Faibussowitsch PetscCall(ISGetIndices(ndmap, &ndmapi)); 442fabe8965SStefano Zampini for (i = 0, cnt = 0; i < A->rmap->n; i++) 4439371c9d4SSatish Balay if (ndmapi[i] < 0 && ndmapc[i] < 2) cnt++; 444fabe8965SStefano Zampini 445462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(&cnt, &i, 1, MPIU_INT, MPI_MAX, comm)); 446fabe8965SStefano Zampini if (i) { /* we detected isolated separator nodes */ 447fabe8965SStefano Zampini Mat A2, A3; 448fabe8965SStefano Zampini IS *workis, is2; 449fabe8965SStefano Zampini PetscScalar *vals; 450fabe8965SStefano Zampini PetscInt gcnt = i, *dnz, *onz, j, *lndmapi; 451fabe8965SStefano Zampini ISLocalToGlobalMapping ll2g; 452fabe8965SStefano Zampini PetscBool flg; 453fabe8965SStefano Zampini const PetscInt *ii, *jj; 454fabe8965SStefano Zampini 455fabe8965SStefano Zampini /* communicate global id of separators */ 456d0609cedSBarry Smith MatPreallocateBegin(comm, A->rmap->n, A->cmap->n, dnz, onz); 4579371c9d4SSatish Balay for (i = 0, cnt = 0; i < A->rmap->n; i++) dnz[i] = ndmapi[i] < 0 ? i + A->rmap->rstart : -1; 458fabe8965SStefano Zampini 4599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl, &lndmapi)); 4609566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, dnz, lndmapi, MPI_REPLACE)); 461fabe8965SStefano Zampini 462fabe8965SStefano Zampini /* compute adjacency of isolated separators node */ 4639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(gcnt, &workis)); 464fabe8965SStefano Zampini for (i = 0, cnt = 0; i < A->rmap->n; i++) { 46548a46eb9SPierre Jolivet if (ndmapi[i] < 0 && ndmapc[i] < 2) PetscCall(ISCreateStride(comm, 1, i + A->rmap->rstart, 1, &workis[cnt++])); 466fabe8965SStefano Zampini } 46748a46eb9SPierre Jolivet for (i = cnt; i < gcnt; i++) PetscCall(ISCreateStride(comm, 0, 0, 1, &workis[i])); 468fabe8965SStefano Zampini for (i = 0; i < gcnt; i++) { 4699566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)workis[i], "ISOLATED")); 4709566063dSJacob Faibussowitsch PetscCall(ISViewFromOptions(workis[i], NULL, "-view_isolated_separators")); 471fabe8965SStefano Zampini } 472fabe8965SStefano Zampini 473fabe8965SStefano Zampini /* no communications since all the ISes correspond to locally owned rows */ 4749566063dSJacob Faibussowitsch PetscCall(MatIncreaseOverlap(A, gcnt, workis, 1)); 475fabe8965SStefano Zampini 476fabe8965SStefano Zampini /* end communicate global id of separators */ 4779566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, dnz, lndmapi, MPI_REPLACE)); 478fabe8965SStefano Zampini 479fabe8965SStefano Zampini /* communicate new layers : create a matrix and transpose it */ 4809566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(dnz, A->rmap->n)); 4819566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(onz, A->rmap->n)); 482fabe8965SStefano Zampini for (i = 0, j = 0; i < A->rmap->n; i++) { 483fabe8965SStefano Zampini if (ndmapi[i] < 0 && ndmapc[i] < 2) { 484fabe8965SStefano Zampini const PetscInt *idxs; 485fabe8965SStefano Zampini PetscInt s; 486fabe8965SStefano Zampini 4879566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(workis[j], &s)); 4889566063dSJacob Faibussowitsch PetscCall(ISGetIndices(workis[j], &idxs)); 4899566063dSJacob Faibussowitsch PetscCall(MatPreallocateSet(i + A->rmap->rstart, s, idxs, dnz, onz)); 490fabe8965SStefano Zampini j++; 491fabe8965SStefano Zampini } 492fabe8965SStefano Zampini } 49308401ef6SPierre Jolivet PetscCheck(j == cnt, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected local count %" PetscInt_FMT " != %" PetscInt_FMT, j, cnt); 494fabe8965SStefano Zampini 495fabe8965SStefano Zampini for (i = 0; i < gcnt; i++) { 4969566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)workis[i], "EXTENDED")); 4979566063dSJacob Faibussowitsch PetscCall(ISViewFromOptions(workis[i], NULL, "-view_isolated_separators")); 498fabe8965SStefano Zampini } 499fabe8965SStefano Zampini 500fabe8965SStefano Zampini for (i = 0, j = 0; i < A->rmap->n; i++) j = PetscMax(j, dnz[i] + onz[i]); 5019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(j, &vals)); 502fabe8965SStefano Zampini for (i = 0; i < j; i++) vals[i] = 1.0; 503fabe8965SStefano Zampini 5049566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &A2)); 5059566063dSJacob Faibussowitsch PetscCall(MatSetType(A2, MATMPIAIJ)); 5069566063dSJacob Faibussowitsch PetscCall(MatSetSizes(A2, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N)); 5079566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(A2, 0, dnz, 0, onz)); 5089566063dSJacob Faibussowitsch PetscCall(MatSetOption(A2, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE)); 509fabe8965SStefano Zampini for (i = 0, j = 0; i < A2->rmap->n; i++) { 510fabe8965SStefano Zampini PetscInt row = i + A2->rmap->rstart, s = dnz[i] + onz[i]; 511fabe8965SStefano Zampini const PetscInt *idxs; 512fabe8965SStefano Zampini 513fabe8965SStefano Zampini if (s) { 5149566063dSJacob Faibussowitsch PetscCall(ISGetIndices(workis[j], &idxs)); 5159566063dSJacob Faibussowitsch PetscCall(MatSetValues(A2, 1, &row, s, idxs, vals, INSERT_VALUES)); 5169566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(workis[j], &idxs)); 517fabe8965SStefano Zampini j++; 518fabe8965SStefano Zampini } 519fabe8965SStefano Zampini } 52008401ef6SPierre Jolivet PetscCheck(j == cnt, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected local count %" PetscInt_FMT " != %" PetscInt_FMT, j, cnt); 5219566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 5229566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A2, MAT_FINAL_ASSEMBLY)); 5239566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A2, MAT_FINAL_ASSEMBLY)); 5249566063dSJacob Faibussowitsch PetscCall(MatTranspose(A2, MAT_INPLACE_MATRIX, &A2)); 525fabe8965SStefano Zampini 526fabe8965SStefano Zampini /* extract submatrix corresponding to the coupling "owned separators" x "isolated separators" */ 527fabe8965SStefano Zampini for (i = 0, j = 0; i < nl; i++) 528fabe8965SStefano Zampini if (lndmapi[i] >= 0) lndmapi[j++] = lndmapi[i]; 5299566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, j, lndmapi, PETSC_USE_POINTER, &is)); 5309566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetLocalMatCondensed(A2, MAT_INITIAL_MATRIX, &is, NULL, &A3)); 5319566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 5329566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A2)); 533fabe8965SStefano Zampini 534fabe8965SStefano Zampini /* extend local to global map to include connected isolated separators */ 5359566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)A3, "_petsc_GetLocalMatCondensed_iscol", (PetscObject *)&is)); 53628b400f6SJacob Faibussowitsch PetscCheck(is, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing column map"); 5379566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &ll2g)); 5389566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A3, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &flg)); 53928b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get IJ structure"); 5409566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, ii[i], jj, PETSC_COPY_VALUES, &is)); 5419566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A3, 0, PETSC_FALSE, PETSC_FALSE, &i, &ii, &jj, &flg)); 54228b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get IJ structure"); 5439566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyIS(ll2g, is, &is2)); 5449566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 5459566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&ll2g)); 546fabe8965SStefano Zampini 547fabe8965SStefano Zampini /* add new nodes to the local-to-global map */ 5489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(l2g)); 5499566063dSJacob Faibussowitsch PetscCall(ISExpand(ndsub, is2, &is)); 5509566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is2)); 5519566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, l2g)); 5529566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 553fabe8965SStefano Zampini 5549566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A3)); 5559566063dSJacob Faibussowitsch PetscCall(PetscFree(lndmapi)); 556d0609cedSBarry Smith MatPreallocateEnd(dnz, onz); 55748a46eb9SPierre Jolivet for (i = 0; i < gcnt; i++) PetscCall(ISDestroy(&workis[i])); 5589566063dSJacob Faibussowitsch PetscCall(PetscFree(workis)); 559fabe8965SStefano Zampini } 5609566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(ndmap, &ndmapi)); 5619566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sf)); 5629566063dSJacob Faibussowitsch PetscCall(PetscFree(ndmapc)); 5639566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ndmap)); 5649566063dSJacob Faibussowitsch PetscCall(ISDestroy(&ndsub)); 5659566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetBlockSize(*l2g, bs)); 5664f58015eSStefano Zampini PetscCall(ISLocalToGlobalMappingViewFromOptions(*l2g, NULL, "-mat_is_nd_l2g_view")); 567fabe8965SStefano Zampini break; 568fabe8965SStefano Zampini case MAT_IS_DISASSEMBLE_L2G_NATURAL: 569835f2295SStefano Zampini PetscCall(PetscObjectQuery((PetscObject)A, "__PETSc_dm", &dm)); 57091d376acSStefano Zampini if (dm) { /* if a matrix comes from a DM, most likely we can use the l2gmap if any */ 57191d376acSStefano Zampini PetscCall(MatGetLocalToGlobalMapping(A, l2g, NULL)); 57291d376acSStefano Zampini PetscCall(PetscObjectReference((PetscObject)*l2g)); 5733ba16761SJacob Faibussowitsch if (*l2g) PetscFunctionReturn(PETSC_SUCCESS); 57491d376acSStefano Zampini } 575fabe8965SStefano Zampini if (ismpiaij) { 5769566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(A, &Ad, &Ao, &garray)); 577fabe8965SStefano Zampini } else if (ismpibaij) { 5789566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJGetSeqBAIJ(A, &Ad, &Ao, &garray)); 57998921bdaSJacob Faibussowitsch } else SETERRQ(comm, PETSC_ERR_SUP, "Type %s", ((PetscObject)A)->type_name); 580c9225affSStefano Zampini if (A->rmap->n) { 581fabe8965SStefano Zampini PetscInt dc, oc, stc, *aux; 582c9225affSStefano Zampini 583ebf8cefbSJunchao Zhang PetscCall(MatGetLocalSize(Ad, NULL, &dc)); 5849566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(Ao, NULL, &oc)); 585d0dbe9f7SStefano Zampini PetscCheck(!oc || garray, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "garray not present"); 5869566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(A, &stc, NULL)); 5879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((dc + oc) / bs, &aux)); 588c9225affSStefano Zampini for (i = 0; i < dc / bs; i++) aux[i] = i + stc / bs; 589ebf8cefbSJunchao Zhang for (i = 0; i < oc / bs; i++) aux[i + dc / bs] = (ismpiaij ? garray[i * bs] / bs : garray[i]); 5909566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, bs, (dc + oc) / bs, aux, PETSC_OWN_POINTER, &is)); 591c9225affSStefano Zampini } else { 5929566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, 1, 0, NULL, PETSC_OWN_POINTER, &is)); 593c9225affSStefano Zampini } 5949566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, l2g)); 5959566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 596fabe8965SStefano Zampini break; 597d71ae5a4SJacob Faibussowitsch default: 598d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unsupported l2g disassembling type %d", mode); 599c9225affSStefano Zampini } 6003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 601c9225affSStefano Zampini } 602c9225affSStefano Zampini 603d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat A, MatType type, MatReuse reuse, Mat *newmat) 604d71ae5a4SJacob Faibussowitsch { 605c9225affSStefano Zampini Mat lA, Ad, Ao, B = NULL; 6066989cf23SStefano Zampini ISLocalToGlobalMapping rl2g, cl2g; 6076989cf23SStefano Zampini IS is; 6086989cf23SStefano Zampini MPI_Comm comm; 6096989cf23SStefano Zampini void *ptrs[2]; 6106989cf23SStefano Zampini const char *names[2] = {"_convert_csr_aux", "_convert_csr_data"}; 611c9225affSStefano Zampini const PetscInt *garray; 6126989cf23SStefano Zampini PetscScalar *dd, *od, *aa, *data; 613c9225affSStefano Zampini const PetscInt *di, *dj, *oi, *oj; 614c9225affSStefano Zampini const PetscInt *odi, *odj, *ooi, *ooj; 6156989cf23SStefano Zampini PetscInt *aux, *ii, *jj; 616a50ef18cSStefano Zampini PetscInt rbs, cbs, lc, dr, dc, oc, str, stc, nnz, i, jd, jo, cum; 617a50ef18cSStefano Zampini PetscBool flg, ismpiaij, ismpibaij, was_inplace = PETSC_FALSE, cong; 618c9225affSStefano Zampini PetscMPIInt size; 6196989cf23SStefano Zampini 620ab4d48faSStefano Zampini PetscFunctionBegin; 6219566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 6229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 623c9225affSStefano Zampini if (size == 1) { 6249566063dSJacob Faibussowitsch PetscCall(MatConvert_SeqXAIJ_IS(A, type, reuse, newmat)); 6253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 626c9225affSStefano Zampini } 627a50ef18cSStefano Zampini PetscCall(MatGetBlockSizes(A, &rbs, &cbs)); 628a50ef18cSStefano Zampini PetscCall(MatHasCongruentLayouts(A, &cong)); 629a50ef18cSStefano Zampini if (reuse != MAT_REUSE_MATRIX && cong && rbs == cbs) { 6309566063dSJacob Faibussowitsch PetscCall(MatMPIXAIJComputeLocalToGlobalMapping_Private(A, &rl2g)); 6319566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &B)); 6329566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATIS)); 633a50ef18cSStefano Zampini PetscCall(MatSetSizes(B, A->rmap->n, A->rmap->n, A->rmap->N, A->rmap->N)); 6349566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B, rl2g, rl2g)); 635a50ef18cSStefano Zampini PetscCall(MatSetBlockSizes(B, rbs, rbs)); 6369566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 637c9225affSStefano Zampini if (reuse == MAT_INPLACE_MATRIX) was_inplace = PETSC_TRUE; 638c9225affSStefano Zampini reuse = MAT_REUSE_MATRIX; 639c9225affSStefano Zampini } 640c9225affSStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 641c9225affSStefano Zampini Mat *newlA, lA; 642c9225affSStefano Zampini IS rows, cols; 643c9225affSStefano Zampini const PetscInt *ridx, *cidx; 644a50ef18cSStefano Zampini PetscInt nr, nc; 645c9225affSStefano Zampini 646c9225affSStefano Zampini if (!B) B = *newmat; 6479566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(B, &rl2g, &cl2g)); 6489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(rl2g, &ridx)); 6499566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(cl2g, &cidx)); 6509566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(rl2g, &nr)); 6519566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(cl2g, &nc)); 6529566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(rl2g, &rbs)); 6539566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(cl2g, &cbs)); 6549566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, rbs, nr / rbs, ridx, PETSC_USE_POINTER, &rows)); 655c9225affSStefano Zampini if (rl2g != cl2g) { 6569566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(comm, cbs, nc / cbs, cidx, PETSC_USE_POINTER, &cols)); 657c9225affSStefano Zampini } else { 6589566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)rows)); 659c9225affSStefano Zampini cols = rows; 660c9225affSStefano Zampini } 6619566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(B, &lA)); 6629566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrices(A, 1, &rows, &cols, MAT_INITIAL_MATRIX, &newlA)); 6639566063dSJacob Faibussowitsch PetscCall(MatConvert(newlA[0], MATSEQAIJ, MAT_INPLACE_MATRIX, &newlA[0])); 6649566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(rl2g, &ridx)); 6659566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(cl2g, &cidx)); 6669566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rows)); 6679566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cols)); 668c9225affSStefano Zampini if (!lA->preallocated) { /* first time */ 6699566063dSJacob Faibussowitsch PetscCall(MatDuplicate(newlA[0], MAT_COPY_VALUES, &lA)); 6709566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B, lA)); 6719566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)lA)); 672c9225affSStefano Zampini } 6739566063dSJacob Faibussowitsch PetscCall(MatCopy(newlA[0], lA, SAME_NONZERO_PATTERN)); 6749566063dSJacob Faibussowitsch PetscCall(MatDestroySubMatrices(1, &newlA)); 6759566063dSJacob Faibussowitsch PetscCall(MatISScaleDisassembling_Private(B)); 6769566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 6779566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 6789566063dSJacob Faibussowitsch if (was_inplace) PetscCall(MatHeaderReplace(A, &B)); 679c9225affSStefano Zampini else *newmat = B; 6803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 681c9225affSStefano Zampini } 682a50ef18cSStefano Zampini /* general case, just compress out the column space */ 6839566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 6849566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIBAIJ, &ismpibaij)); 685c9225affSStefano Zampini if (ismpiaij) { 686a50ef18cSStefano Zampini cbs = 1; /* We cannot guarantee the off-process matrix will respect the column block size */ 6879566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(A, &Ad, &Ao, &garray)); 688c9225affSStefano Zampini } else if (ismpibaij) { 6899566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJGetSeqBAIJ(A, &Ad, &Ao, &garray)); 6909566063dSJacob Faibussowitsch PetscCall(MatConvert(Ad, MATSEQAIJ, MAT_INITIAL_MATRIX, &Ad)); 6919566063dSJacob Faibussowitsch PetscCall(MatConvert(Ao, MATSEQAIJ, MAT_INITIAL_MATRIX, &Ao)); 69298921bdaSJacob Faibussowitsch } else SETERRQ(comm, PETSC_ERR_SUP, "Type %s", ((PetscObject)A)->type_name); 6939566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(Ad, &dd)); 6949566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(Ao, &od)); 6956989cf23SStefano Zampini 6966989cf23SStefano Zampini /* access relevant information from MPIAIJ */ 6979566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &str, NULL)); 6989566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(A, &stc, NULL)); 699a50ef18cSStefano Zampini PetscCall(MatGetLocalSize(Ad, &dr, &dc)); 7009566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(Ao, NULL, &oc)); 701d72e20dbSStefano Zampini PetscCheck(!oc || garray, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "garray not present"); 702d72e20dbSStefano Zampini 7039566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(Ad, 0, PETSC_FALSE, PETSC_FALSE, &i, &di, &dj, &flg)); 70428b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get IJ structure"); 7059566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(Ao, 0, PETSC_FALSE, PETSC_FALSE, &i, &oi, &oj, &flg)); 70628b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot get IJ structure"); 707c9225affSStefano Zampini nnz = di[dr] + oi[dr]; 708c9225affSStefano Zampini /* store original pointers to be restored later */ 7099371c9d4SSatish Balay odi = di; 7109371c9d4SSatish Balay odj = dj; 7119371c9d4SSatish Balay ooi = oi; 7129371c9d4SSatish Balay ooj = oj; 7136989cf23SStefano Zampini 7146989cf23SStefano Zampini /* generate l2g maps for rows and cols */ 715a50ef18cSStefano Zampini PetscCall(ISCreateStride(comm, dr / rbs, str / rbs, 1, &is)); 716a50ef18cSStefano Zampini if (rbs > 1) { 717c9225affSStefano Zampini IS is2; 718c9225affSStefano Zampini 7199566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(is, &i)); 7209566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, (const PetscInt **)&aux)); 721a50ef18cSStefano Zampini PetscCall(ISCreateBlock(comm, rbs, i, aux, PETSC_COPY_VALUES, &is2)); 7229566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, (const PetscInt **)&aux)); 7239566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 724c9225affSStefano Zampini is = is2; 725c9225affSStefano Zampini } 7269566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g)); 7279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 728e363d98aSStefano Zampini if (dr) { 729a50ef18cSStefano Zampini PetscCall(PetscMalloc1((dc + oc) / cbs, &aux)); 730a50ef18cSStefano Zampini for (i = 0; i < dc / cbs; i++) aux[i] = i + stc / cbs; 731a50ef18cSStefano Zampini for (i = 0; i < oc / cbs; i++) aux[i + dc / cbs] = garray[i]; 732a50ef18cSStefano Zampini PetscCall(ISCreateBlock(comm, cbs, (dc + oc) / cbs, aux, PETSC_OWN_POINTER, &is)); 733e363d98aSStefano Zampini lc = dc + oc; 734e363d98aSStefano Zampini } else { 735a50ef18cSStefano Zampini PetscCall(ISCreateBlock(comm, cbs, 0, NULL, PETSC_OWN_POINTER, &is)); 736e363d98aSStefano Zampini lc = 0; 737e363d98aSStefano Zampini } 7389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g)); 7399566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 7406989cf23SStefano Zampini 7416989cf23SStefano Zampini /* create MATIS object */ 7429566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &B)); 7439566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, dr, dc, PETSC_DECIDE, PETSC_DECIDE)); 7449566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATIS)); 745a50ef18cSStefano Zampini PetscCall(MatSetBlockSizes(B, rbs, cbs)); 7469566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B, rl2g, cl2g)); 7479566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 7489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 7496989cf23SStefano Zampini 7506989cf23SStefano Zampini /* merge local matrices */ 7519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz + dr + 1, &aux)); 7529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &data)); 7536989cf23SStefano Zampini ii = aux; 7546989cf23SStefano Zampini jj = aux + dr + 1; 7556989cf23SStefano Zampini aa = data; 7566989cf23SStefano Zampini *ii = *(di++) + *(oi++); 7579371c9d4SSatish Balay for (jd = 0, jo = 0, cum = 0; *ii < nnz; cum++) { 7589371c9d4SSatish Balay for (; jd < *di; jd++) { 7599371c9d4SSatish Balay *jj++ = *dj++; 7609371c9d4SSatish Balay *aa++ = *dd++; 7619371c9d4SSatish Balay } 7629371c9d4SSatish Balay for (; jo < *oi; jo++) { 7639371c9d4SSatish Balay *jj++ = *oj++ + dc; 7649371c9d4SSatish Balay *aa++ = *od++; 7659371c9d4SSatish Balay } 7666989cf23SStefano Zampini *(++ii) = *(di++) + *(oi++); 7676989cf23SStefano Zampini } 7686989cf23SStefano Zampini for (; cum < dr; cum++) *(++ii) = nnz; 769c9225affSStefano Zampini 7709566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(Ad, 0, PETSC_FALSE, PETSC_FALSE, &i, &odi, &odj, &flg)); 77128b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot restore IJ structure"); 7729566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(Ao, 0, PETSC_FALSE, PETSC_FALSE, &i, &ooi, &ooj, &flg)); 77328b400f6SJacob Faibussowitsch PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot restore IJ structure"); 7749566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(Ad, &dd)); 7759566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArray(Ao, &od)); 776c9225affSStefano Zampini 7776989cf23SStefano Zampini ii = aux; 7786989cf23SStefano Zampini jj = aux + dr + 1; 7796989cf23SStefano Zampini aa = data; 7809566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, dr, lc, ii, jj, aa, &lA)); 7816989cf23SStefano Zampini 7826989cf23SStefano Zampini /* create containers to destroy the data */ 7836989cf23SStefano Zampini ptrs[0] = aux; 7846989cf23SStefano Zampini ptrs[1] = data; 78549abdd8aSBarry Smith for (i = 0; i < 2; i++) PetscCall(PetscObjectContainerCompose((PetscObject)lA, names[i], ptrs[i], PetscCtxDestroyDefault)); 786c9225affSStefano Zampini if (ismpibaij) { /* destroy converted local matrices */ 7879566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Ad)); 7889566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Ao)); 789c9225affSStefano Zampini } 7906989cf23SStefano Zampini 7916989cf23SStefano Zampini /* finalize matrix */ 7929566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B, lA)); 7939566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lA)); 7949566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 7959566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 796ac530a7eSPierre Jolivet if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &B)); 797ac530a7eSPierre Jolivet else *newmat = B; 7983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7996989cf23SStefano Zampini } 8006989cf23SStefano Zampini 801d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A, MatType type, MatReuse reuse, Mat *newmat) 802d71ae5a4SJacob Faibussowitsch { 8035e3038f0Sstefano_zampini Mat **nest, *snest, **rnest, lA, B; 8045e3038f0Sstefano_zampini IS *iscol, *isrow, *islrow, *islcol; 8055e3038f0Sstefano_zampini ISLocalToGlobalMapping rl2g, cl2g; 8065e3038f0Sstefano_zampini MPI_Comm comm; 8075b003df0Sstefano_zampini PetscInt *lr, *lc, *l2gidxs; 8085b003df0Sstefano_zampini PetscInt i, j, nr, nc, rbs, cbs; 8099e7b2b25Sstefano_zampini PetscBool convert, lreuse, *istrans; 8104f58015eSStefano Zampini PetscBool3 allow_repeated = PETSC_BOOL3_UNKNOWN; 8115e3038f0Sstefano_zampini 812ab4d48faSStefano Zampini PetscFunctionBegin; 8139566063dSJacob Faibussowitsch PetscCall(MatNestGetSubMats(A, &nr, &nc, &nest)); 8145e3038f0Sstefano_zampini lreuse = PETSC_FALSE; 8155e3038f0Sstefano_zampini rnest = NULL; 8165e3038f0Sstefano_zampini if (reuse == MAT_REUSE_MATRIX) { 8175e3038f0Sstefano_zampini PetscBool ismatis, isnest; 8185e3038f0Sstefano_zampini 8199566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)*newmat, MATIS, &ismatis)); 820f4f49eeaSPierre Jolivet PetscCheck(ismatis, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_USER, "Cannot reuse matrix of type %s", ((PetscObject)*newmat)->type_name); 8219566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*newmat, &lA)); 8229566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)lA, MATNEST, &isnest)); 8235e3038f0Sstefano_zampini if (isnest) { 8249566063dSJacob Faibussowitsch PetscCall(MatNestGetSubMats(lA, &i, &j, &rnest)); 8255e3038f0Sstefano_zampini lreuse = (PetscBool)(i == nr && j == nc); 8265e3038f0Sstefano_zampini if (!lreuse) rnest = NULL; 8275e3038f0Sstefano_zampini } 8285e3038f0Sstefano_zampini } 8299566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 8309566063dSJacob Faibussowitsch PetscCall(PetscCalloc2(nr, &lr, nc, &lc)); 8319566063dSJacob Faibussowitsch PetscCall(PetscCalloc6(nr, &isrow, nc, &iscol, nr, &islrow, nc, &islcol, nr * nc, &snest, nr * nc, &istrans)); 8329566063dSJacob Faibussowitsch PetscCall(MatNestGetISs(A, isrow, iscol)); 8335e3038f0Sstefano_zampini for (i = 0; i < nr; i++) { 8345e3038f0Sstefano_zampini for (j = 0; j < nc; j++) { 8354f58015eSStefano Zampini PetscBool ismatis, sallow; 8369e7b2b25Sstefano_zampini PetscInt l1, l2, lb1, lb2, ij = i * nc + j; 8375e3038f0Sstefano_zampini 8385e3038f0Sstefano_zampini /* Null matrix pointers are allowed in MATNEST */ 8395e3038f0Sstefano_zampini if (!nest[i][j]) continue; 8405e3038f0Sstefano_zampini 8415e3038f0Sstefano_zampini /* Nested matrices should be of type MATIS */ 842013e2dc7SBarry Smith PetscCall(PetscObjectTypeCompare((PetscObject)nest[i][j], MATTRANSPOSEVIRTUAL, &istrans[ij])); 8439e7b2b25Sstefano_zampini if (istrans[ij]) { 8449e7b2b25Sstefano_zampini Mat T, lT; 8459566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(nest[i][j], &T)); 8469566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)T, MATIS, &ismatis)); 84728b400f6SJacob 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); 8484f58015eSStefano Zampini PetscCall(MatISGetAllowRepeated(T, &sallow)); 8499566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(T, &lT)); 8509566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(lT, &snest[ij])); 8519e7b2b25Sstefano_zampini } else { 8529566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)nest[i][j], MATIS, &ismatis)); 85328b400f6SJacob 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); 8544f58015eSStefano Zampini PetscCall(MatISGetAllowRepeated(nest[i][j], &sallow)); 8559566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(nest[i][j], &snest[ij])); 8569e7b2b25Sstefano_zampini } 8574f58015eSStefano Zampini if (allow_repeated == PETSC_BOOL3_UNKNOWN) allow_repeated = PetscBoolToBool3(sallow); 8584f58015eSStefano Zampini PetscCheck(sallow == PetscBool3ToBool(allow_repeated), comm, PETSC_ERR_SUP, "Cannot mix repeated and non repeated maps"); 8595e3038f0Sstefano_zampini 8605e3038f0Sstefano_zampini /* Check compatibility of local sizes */ 8619566063dSJacob Faibussowitsch PetscCall(MatGetSize(snest[ij], &l1, &l2)); 8629566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(snest[ij], &lb1, &lb2)); 8635e3038f0Sstefano_zampini if (!l1 || !l2) continue; 864aed4548fSBarry 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); 865aed4548fSBarry 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); 8665e3038f0Sstefano_zampini lr[i] = l1; 8675e3038f0Sstefano_zampini lc[j] = l2; 8685e3038f0Sstefano_zampini 869da81f932SPierre Jolivet /* check compatibility for local matrix reusage */ 8705e3038f0Sstefano_zampini if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE; 8715e3038f0Sstefano_zampini } 8725e3038f0Sstefano_zampini } 8735e3038f0Sstefano_zampini 87476bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 8755e3038f0Sstefano_zampini /* Check compatibility of l2g maps for rows */ 8765e3038f0Sstefano_zampini for (i = 0; i < nr; i++) { 8775e3038f0Sstefano_zampini rl2g = NULL; 8785e3038f0Sstefano_zampini for (j = 0; j < nc; j++) { 8795e3038f0Sstefano_zampini PetscInt n1, n2; 8805e3038f0Sstefano_zampini 8815e3038f0Sstefano_zampini if (!nest[i][j]) continue; 8829e7b2b25Sstefano_zampini if (istrans[i * nc + j]) { 8839e7b2b25Sstefano_zampini Mat T; 8849e7b2b25Sstefano_zampini 8859566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(nest[i][j], &T)); 8869566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(T, NULL, &cl2g)); 8879e7b2b25Sstefano_zampini } else { 8889566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(nest[i][j], &cl2g, NULL)); 8899e7b2b25Sstefano_zampini } 8909566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(cl2g, &n1)); 8915e3038f0Sstefano_zampini if (!n1) continue; 8925e3038f0Sstefano_zampini if (!rl2g) { 8935e3038f0Sstefano_zampini rl2g = cl2g; 8945e3038f0Sstefano_zampini } else { 8955e3038f0Sstefano_zampini const PetscInt *idxs1, *idxs2; 8965e3038f0Sstefano_zampini PetscBool same; 8975e3038f0Sstefano_zampini 8989566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(rl2g, &n2)); 89908401ef6SPierre 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); 9009566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(cl2g, &idxs1)); 9019566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(rl2g, &idxs2)); 9029566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(idxs1, idxs2, n1, &same)); 9039566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(cl2g, &idxs1)); 9049566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(rl2g, &idxs2)); 90528b400f6SJacob 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); 9065e3038f0Sstefano_zampini } 9075e3038f0Sstefano_zampini } 9085e3038f0Sstefano_zampini } 9095e3038f0Sstefano_zampini /* Check compatibility of l2g maps for columns */ 9105e3038f0Sstefano_zampini for (i = 0; i < nc; i++) { 9115e3038f0Sstefano_zampini rl2g = NULL; 9125e3038f0Sstefano_zampini for (j = 0; j < nr; j++) { 9135e3038f0Sstefano_zampini PetscInt n1, n2; 9145e3038f0Sstefano_zampini 9155e3038f0Sstefano_zampini if (!nest[j][i]) continue; 9169e7b2b25Sstefano_zampini if (istrans[j * nc + i]) { 9179e7b2b25Sstefano_zampini Mat T; 9189e7b2b25Sstefano_zampini 9199566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(nest[j][i], &T)); 9209566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(T, &cl2g, NULL)); 9219e7b2b25Sstefano_zampini } else { 9229566063dSJacob Faibussowitsch PetscCall(MatISGetLocalToGlobalMapping(nest[j][i], NULL, &cl2g)); 9239e7b2b25Sstefano_zampini } 9249566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(cl2g, &n1)); 9255e3038f0Sstefano_zampini if (!n1) continue; 9265e3038f0Sstefano_zampini if (!rl2g) { 9275e3038f0Sstefano_zampini rl2g = cl2g; 9285e3038f0Sstefano_zampini } else { 9295e3038f0Sstefano_zampini const PetscInt *idxs1, *idxs2; 9305e3038f0Sstefano_zampini PetscBool same; 9315e3038f0Sstefano_zampini 9329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(rl2g, &n2)); 93308401ef6SPierre 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); 9349566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(cl2g, &idxs1)); 9359566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(rl2g, &idxs2)); 9369566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(idxs1, idxs2, n1, &same)); 9379566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(cl2g, &idxs1)); 9389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(rl2g, &idxs2)); 93928b400f6SJacob 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); 9405e3038f0Sstefano_zampini } 9415e3038f0Sstefano_zampini } 9425e3038f0Sstefano_zampini } 94376bd3646SJed Brown } 9445e3038f0Sstefano_zampini 9455e3038f0Sstefano_zampini B = NULL; 9465e3038f0Sstefano_zampini if (reuse != MAT_REUSE_MATRIX) { 9475b003df0Sstefano_zampini PetscInt stl; 9485b003df0Sstefano_zampini 9495e3038f0Sstefano_zampini /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */ 9505e3038f0Sstefano_zampini for (i = 0, stl = 0; i < nr; i++) stl += lr[i]; 9519566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(stl, &l2gidxs)); 9525b003df0Sstefano_zampini for (i = 0, stl = 0; i < nr; i++) { 9535e3038f0Sstefano_zampini Mat usedmat; 9545e3038f0Sstefano_zampini Mat_IS *matis; 9555e3038f0Sstefano_zampini const PetscInt *idxs; 9565e3038f0Sstefano_zampini 9575e3038f0Sstefano_zampini /* local IS for local NEST */ 9589566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, lr[i], stl, 1, &islrow[i])); 9595e3038f0Sstefano_zampini 9605e3038f0Sstefano_zampini /* l2gmap */ 9615e3038f0Sstefano_zampini j = 0; 9625e3038f0Sstefano_zampini usedmat = nest[i][j]; 9639e7b2b25Sstefano_zampini while (!usedmat && j < nc - 1) usedmat = nest[i][++j]; 96428b400f6SJacob Faibussowitsch PetscCheck(usedmat, comm, PETSC_ERR_SUP, "Cannot find valid row mat"); 9659e7b2b25Sstefano_zampini 9669e7b2b25Sstefano_zampini if (istrans[i * nc + j]) { 9679e7b2b25Sstefano_zampini Mat T; 9689566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(usedmat, &T)); 9699e7b2b25Sstefano_zampini usedmat = T; 9709e7b2b25Sstefano_zampini } 971f4f49eeaSPierre Jolivet matis = (Mat_IS *)usedmat->data; 9729566063dSJacob Faibussowitsch PetscCall(ISGetIndices(isrow[i], &idxs)); 9739e7b2b25Sstefano_zampini if (istrans[i * nc + j]) { 9749566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->csf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 9759566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->csf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 9769e7b2b25Sstefano_zampini } else { 9779566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 9789566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 9799e7b2b25Sstefano_zampini } 9809566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(isrow[i], &idxs)); 9815e3038f0Sstefano_zampini stl += lr[i]; 9825e3038f0Sstefano_zampini } 9839566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(comm, 1, stl, l2gidxs, PETSC_OWN_POINTER, &rl2g)); 9845e3038f0Sstefano_zampini 9855e3038f0Sstefano_zampini /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */ 9865e3038f0Sstefano_zampini for (i = 0, stl = 0; i < nc; i++) stl += lc[i]; 9879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(stl, &l2gidxs)); 9885b003df0Sstefano_zampini for (i = 0, stl = 0; i < nc; i++) { 9895e3038f0Sstefano_zampini Mat usedmat; 9905e3038f0Sstefano_zampini Mat_IS *matis; 9915e3038f0Sstefano_zampini const PetscInt *idxs; 9925e3038f0Sstefano_zampini 9935e3038f0Sstefano_zampini /* local IS for local NEST */ 9949566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, lc[i], stl, 1, &islcol[i])); 9955e3038f0Sstefano_zampini 9965e3038f0Sstefano_zampini /* l2gmap */ 9975e3038f0Sstefano_zampini j = 0; 9985e3038f0Sstefano_zampini usedmat = nest[j][i]; 9999e7b2b25Sstefano_zampini while (!usedmat && j < nr - 1) usedmat = nest[++j][i]; 100028b400f6SJacob Faibussowitsch PetscCheck(usedmat, comm, PETSC_ERR_SUP, "Cannot find valid column mat"); 10019e7b2b25Sstefano_zampini if (istrans[j * nc + i]) { 10029e7b2b25Sstefano_zampini Mat T; 10039566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(usedmat, &T)); 10049e7b2b25Sstefano_zampini usedmat = T; 10059e7b2b25Sstefano_zampini } 1006f4f49eeaSPierre Jolivet matis = (Mat_IS *)usedmat->data; 10079566063dSJacob Faibussowitsch PetscCall(ISGetIndices(iscol[i], &idxs)); 10089e7b2b25Sstefano_zampini if (istrans[j * nc + i]) { 10099566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 10109566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 10119e7b2b25Sstefano_zampini } else { 10129566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->csf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 10139566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->csf, MPIU_INT, idxs, l2gidxs + stl, MPI_REPLACE)); 10149e7b2b25Sstefano_zampini } 10159566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(iscol[i], &idxs)); 10165e3038f0Sstefano_zampini stl += lc[i]; 10175e3038f0Sstefano_zampini } 10189566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(comm, 1, stl, l2gidxs, PETSC_OWN_POINTER, &cl2g)); 10195e3038f0Sstefano_zampini 10205e3038f0Sstefano_zampini /* Create MATIS */ 10219566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &B)); 10229566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N)); 10239566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(A, &rbs, &cbs)); 10249566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(B, rbs, cbs)); 10259566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATIS)); 10269566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(B, MATNEST)); 10274f58015eSStefano Zampini PetscCall(MatISSetAllowRepeated(B, PetscBool3ToBool(allow_repeated))); 10288546b261SStefano Zampini { /* hack : avoid setup of scatters */ 1029f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)B->data; 10308546b261SStefano Zampini matis->islocalref = PETSC_TRUE; 10318546b261SStefano Zampini } 10329566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B, rl2g, cl2g)); 10339566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 10349566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 10359566063dSJacob Faibussowitsch PetscCall(MatCreateNest(PETSC_COMM_SELF, nr, islrow, nc, islcol, snest, &lA)); 10369566063dSJacob Faibussowitsch PetscCall(MatNestSetVecType(lA, VECNEST)); 10379e7b2b25Sstefano_zampini for (i = 0; i < nr * nc; i++) { 103848a46eb9SPierre Jolivet if (istrans[i]) PetscCall(MatDestroy(&snest[i])); 10399e7b2b25Sstefano_zampini } 10409566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B, lA)); 10419566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lA)); 10428546b261SStefano Zampini { /* hack : setup of scatters done here */ 1043f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)B->data; 10448546b261SStefano Zampini 10458546b261SStefano Zampini matis->islocalref = PETSC_FALSE; 10469566063dSJacob Faibussowitsch PetscCall(MatISSetUpScatters_Private(B)); 10478546b261SStefano Zampini } 10489566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 10499566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 10505e3038f0Sstefano_zampini if (reuse == MAT_INPLACE_MATRIX) { 10519566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &B)); 10525e3038f0Sstefano_zampini } else { 10535e3038f0Sstefano_zampini *newmat = B; 10545e3038f0Sstefano_zampini } 10555e3038f0Sstefano_zampini } else { 10565e3038f0Sstefano_zampini if (lreuse) { 10579566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*newmat, &lA)); 10585e3038f0Sstefano_zampini for (i = 0; i < nr; i++) { 10595e3038f0Sstefano_zampini for (j = 0; j < nc; j++) { 10605e3038f0Sstefano_zampini if (snest[i * nc + j]) { 10619566063dSJacob Faibussowitsch PetscCall(MatNestSetSubMat(lA, i, j, snest[i * nc + j])); 106248a46eb9SPierre Jolivet if (istrans[i * nc + j]) PetscCall(MatDestroy(&snest[i * nc + j])); 10635e3038f0Sstefano_zampini } 10645e3038f0Sstefano_zampini } 10655e3038f0Sstefano_zampini } 10665e3038f0Sstefano_zampini } else { 10675b003df0Sstefano_zampini PetscInt stl; 10685b003df0Sstefano_zampini for (i = 0, stl = 0; i < nr; i++) { 10699566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, lr[i], stl, 1, &islrow[i])); 10705b003df0Sstefano_zampini stl += lr[i]; 10715e3038f0Sstefano_zampini } 10725b003df0Sstefano_zampini for (i = 0, stl = 0; i < nc; i++) { 10739566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, lc[i], stl, 1, &islcol[i])); 10745b003df0Sstefano_zampini stl += lc[i]; 10755e3038f0Sstefano_zampini } 10769566063dSJacob Faibussowitsch PetscCall(MatCreateNest(PETSC_COMM_SELF, nr, islrow, nc, islcol, snest, &lA)); 1077ab4d48faSStefano Zampini for (i = 0; i < nr * nc; i++) { 107848a46eb9SPierre Jolivet if (istrans[i]) PetscCall(MatDestroy(&snest[i])); 1079ab4d48faSStefano Zampini } 10809566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*newmat, lA)); 10819566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lA)); 10825e3038f0Sstefano_zampini } 10839566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*newmat, MAT_FINAL_ASSEMBLY)); 10849566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*newmat, MAT_FINAL_ASSEMBLY)); 10855e3038f0Sstefano_zampini } 10865e3038f0Sstefano_zampini 10875b003df0Sstefano_zampini /* Create local matrix in MATNEST format */ 10885b003df0Sstefano_zampini convert = PETSC_FALSE; 10894f58015eSStefano Zampini PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)A)->prefix, "-mat_is_convert_local_nest", &convert, NULL)); 10905b003df0Sstefano_zampini if (convert) { 10915b003df0Sstefano_zampini Mat M; 10925b003df0Sstefano_zampini MatISLocalFields lf; 10935b003df0Sstefano_zampini 10949566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*newmat, &lA)); 10959566063dSJacob Faibussowitsch PetscCall(MatConvert(lA, MATAIJ, MAT_INITIAL_MATRIX, &M)); 10969566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*newmat, M)); 10979566063dSJacob Faibussowitsch PetscCall(MatDestroy(&M)); 10985b003df0Sstefano_zampini 10995b003df0Sstefano_zampini /* attach local fields to the matrix */ 11009566063dSJacob Faibussowitsch PetscCall(PetscNew(&lf)); 11019566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nr, &lf->rf, nc, &lf->cf)); 11025b003df0Sstefano_zampini for (i = 0; i < nr; i++) { 11035b003df0Sstefano_zampini PetscInt n, st; 11045b003df0Sstefano_zampini 11059566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(islrow[i], &n)); 11069566063dSJacob Faibussowitsch PetscCall(ISStrideGetInfo(islrow[i], &st, NULL)); 11079566063dSJacob Faibussowitsch PetscCall(ISCreateStride(comm, n, st, 1, &lf->rf[i])); 11085b003df0Sstefano_zampini } 11095b003df0Sstefano_zampini for (i = 0; i < nc; i++) { 11105b003df0Sstefano_zampini PetscInt n, st; 11115b003df0Sstefano_zampini 11129566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(islcol[i], &n)); 11139566063dSJacob Faibussowitsch PetscCall(ISStrideGetInfo(islcol[i], &st, NULL)); 11149566063dSJacob Faibussowitsch PetscCall(ISCreateStride(comm, n, st, 1, &lf->cf[i])); 11155b003df0Sstefano_zampini } 11165b003df0Sstefano_zampini lf->nr = nr; 11175b003df0Sstefano_zampini lf->nc = nc; 111803e76207SPierre Jolivet PetscCall(PetscObjectContainerCompose((PetscObject)*newmat, "_convert_nest_lfields", lf, MatISContainerDestroyFields_Private)); 11195b003df0Sstefano_zampini } 11205b003df0Sstefano_zampini 11215e3038f0Sstefano_zampini /* Free workspace */ 112248a46eb9SPierre Jolivet for (i = 0; i < nr; i++) PetscCall(ISDestroy(&islrow[i])); 112348a46eb9SPierre Jolivet for (i = 0; i < nc; i++) PetscCall(ISDestroy(&islcol[i])); 11249566063dSJacob Faibussowitsch PetscCall(PetscFree6(isrow, iscol, islrow, islcol, snest, istrans)); 11259566063dSJacob Faibussowitsch PetscCall(PetscFree2(lr, lc)); 11263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11275e3038f0Sstefano_zampini } 11285e3038f0Sstefano_zampini 1129d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r) 1130d71ae5a4SJacob Faibussowitsch { 1131ad219c80Sstefano_zampini Mat_IS *matis = (Mat_IS *)A->data; 1132ad219c80Sstefano_zampini Vec ll, rr; 1133ad219c80Sstefano_zampini const PetscScalar *Y, *X; 1134ad219c80Sstefano_zampini PetscScalar *x, *y; 1135ad219c80Sstefano_zampini 1136ad219c80Sstefano_zampini PetscFunctionBegin; 1137ad219c80Sstefano_zampini if (l) { 1138ad219c80Sstefano_zampini ll = matis->y; 11399566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(l, &Y)); 11409566063dSJacob Faibussowitsch PetscCall(VecGetArray(ll, &y)); 11419566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_SCALAR, Y, y, MPI_REPLACE)); 1142ad219c80Sstefano_zampini } else { 1143ad219c80Sstefano_zampini ll = NULL; 1144ad219c80Sstefano_zampini } 1145ad219c80Sstefano_zampini if (r) { 1146ad219c80Sstefano_zampini rr = matis->x; 11479566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(r, &X)); 11489566063dSJacob Faibussowitsch PetscCall(VecGetArray(rr, &x)); 11499566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->csf, MPIU_SCALAR, X, x, MPI_REPLACE)); 1150ad219c80Sstefano_zampini } else { 1151ad219c80Sstefano_zampini rr = NULL; 1152ad219c80Sstefano_zampini } 1153ad219c80Sstefano_zampini if (ll) { 11549566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_SCALAR, Y, y, MPI_REPLACE)); 11559566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(l, &Y)); 11569566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(ll, &y)); 1157ad219c80Sstefano_zampini } 1158ad219c80Sstefano_zampini if (rr) { 11599566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->csf, MPIU_SCALAR, X, x, MPI_REPLACE)); 11609566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(r, &X)); 11619566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(rr, &x)); 1162ad219c80Sstefano_zampini } 11639566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(matis->A, ll, rr)); 11643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1165ad219c80Sstefano_zampini } 1166ad219c80Sstefano_zampini 1167d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetInfo_IS(Mat A, MatInfoType flag, MatInfo *ginfo) 1168d71ae5a4SJacob Faibussowitsch { 11697fa8f2d3SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 11707fa8f2d3SStefano Zampini MatInfo info; 11713966268fSBarry Smith PetscLogDouble isend[6], irecv[6]; 11727fa8f2d3SStefano Zampini PetscInt bs; 11737fa8f2d3SStefano Zampini 11747fa8f2d3SStefano Zampini PetscFunctionBegin; 11759566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 1176a2ccb5f9Sstefano_zampini if (matis->A->ops->getinfo) { 11779566063dSJacob Faibussowitsch PetscCall(MatGetInfo(matis->A, MAT_LOCAL, &info)); 11787fa8f2d3SStefano Zampini isend[0] = info.nz_used; 11797fa8f2d3SStefano Zampini isend[1] = info.nz_allocated; 11807fa8f2d3SStefano Zampini isend[2] = info.nz_unneeded; 11817fa8f2d3SStefano Zampini isend[3] = info.memory; 11827fa8f2d3SStefano Zampini isend[4] = info.mallocs; 1183a2ccb5f9Sstefano_zampini } else { 1184a2ccb5f9Sstefano_zampini isend[0] = 0.; 1185a2ccb5f9Sstefano_zampini isend[1] = 0.; 1186a2ccb5f9Sstefano_zampini isend[2] = 0.; 1187a2ccb5f9Sstefano_zampini isend[3] = 0.; 1188a2ccb5f9Sstefano_zampini isend[4] = 0.; 1189a2ccb5f9Sstefano_zampini } 1190314ce898Sstefano_zampini isend[5] = matis->A->num_ass; 11917fa8f2d3SStefano Zampini if (flag == MAT_LOCAL) { 11927fa8f2d3SStefano Zampini ginfo->nz_used = isend[0]; 11937fa8f2d3SStefano Zampini ginfo->nz_allocated = isend[1]; 11947fa8f2d3SStefano Zampini ginfo->nz_unneeded = isend[2]; 11957fa8f2d3SStefano Zampini ginfo->memory = isend[3]; 11967fa8f2d3SStefano Zampini ginfo->mallocs = isend[4]; 1197314ce898Sstefano_zampini ginfo->assemblies = isend[5]; 11987fa8f2d3SStefano Zampini } else if (flag == MAT_GLOBAL_MAX) { 1199462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(isend, irecv, 6, MPIU_PETSCLOGDOUBLE, MPI_MAX, PetscObjectComm((PetscObject)A))); 12007fa8f2d3SStefano Zampini 12017fa8f2d3SStefano Zampini ginfo->nz_used = irecv[0]; 12027fa8f2d3SStefano Zampini ginfo->nz_allocated = irecv[1]; 12037fa8f2d3SStefano Zampini ginfo->nz_unneeded = irecv[2]; 12047fa8f2d3SStefano Zampini ginfo->memory = irecv[3]; 12057fa8f2d3SStefano Zampini ginfo->mallocs = irecv[4]; 1206314ce898Sstefano_zampini ginfo->assemblies = irecv[5]; 12077fa8f2d3SStefano Zampini } else if (flag == MAT_GLOBAL_SUM) { 1208462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(isend, irecv, 5, MPIU_PETSCLOGDOUBLE, MPI_SUM, PetscObjectComm((PetscObject)A))); 12097fa8f2d3SStefano Zampini 12107fa8f2d3SStefano Zampini ginfo->nz_used = irecv[0]; 12117fa8f2d3SStefano Zampini ginfo->nz_allocated = irecv[1]; 12127fa8f2d3SStefano Zampini ginfo->nz_unneeded = irecv[2]; 12137fa8f2d3SStefano Zampini ginfo->memory = irecv[3]; 12147fa8f2d3SStefano Zampini ginfo->mallocs = irecv[4]; 12157fa8f2d3SStefano Zampini ginfo->assemblies = A->num_ass; 12167fa8f2d3SStefano Zampini } 12177fa8f2d3SStefano Zampini ginfo->block_size = bs; 12187fa8f2d3SStefano Zampini ginfo->fill_ratio_given = 0; 12197fa8f2d3SStefano Zampini ginfo->fill_ratio_needed = 0; 12207fa8f2d3SStefano Zampini ginfo->factor_mallocs = 0; 12213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12225e3038f0Sstefano_zampini } 12235e3038f0Sstefano_zampini 1224d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatTranspose_IS(Mat A, MatReuse reuse, Mat *B) 1225d71ae5a4SJacob Faibussowitsch { 1226d7f69cd0SStefano Zampini Mat C, lC, lA; 1227d7f69cd0SStefano Zampini 1228d7f69cd0SStefano Zampini PetscFunctionBegin; 12297fb60732SBarry Smith if (reuse == MAT_REUSE_MATRIX) PetscCall(MatTransposeCheckNonzeroState_Private(A, *B)); 1230cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) { 1231cf37664fSBarry Smith ISLocalToGlobalMapping rl2g, cl2g; 12324f58015eSStefano Zampini PetscBool allow_repeated; 12334f58015eSStefano Zampini 12349566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C)); 12359566063dSJacob Faibussowitsch PetscCall(MatSetSizes(C, A->cmap->n, A->rmap->n, A->cmap->N, A->rmap->N)); 123658b7e2c1SStefano Zampini PetscCall(MatSetBlockSizes(C, A->cmap->bs, A->rmap->bs)); 12379566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATIS)); 12384f58015eSStefano Zampini PetscCall(MatISGetAllowRepeated(A, &allow_repeated)); 12394f58015eSStefano Zampini PetscCall(MatISSetAllowRepeated(C, allow_repeated)); 12409566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(A, &rl2g, &cl2g)); 12419566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(C, cl2g, rl2g)); 1242e432b41dSStefano Zampini } else C = *B; 1243d7f69cd0SStefano Zampini 1244d7f69cd0SStefano Zampini /* perform local transposition */ 12459566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A, &lA)); 12469566063dSJacob Faibussowitsch PetscCall(MatTranspose(lA, MAT_INITIAL_MATRIX, &lC)); 12479566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(lC, lA->cmap->mapping, lA->rmap->mapping)); 12489566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(C, lC)); 12499566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lC)); 1250d7f69cd0SStefano Zampini 1251cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) { 1252d7f69cd0SStefano Zampini *B = C; 1253d7f69cd0SStefano Zampini } else { 12549566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(A, &C)); 1255d7f69cd0SStefano Zampini } 12569566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY)); 12579566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY)); 12583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1259d7f69cd0SStefano Zampini } 1260d7f69cd0SStefano Zampini 1261d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDiagonalSet_IS(Mat A, Vec D, InsertMode insmode) 1262d71ae5a4SJacob Faibussowitsch { 12633fd1c9e7SStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 12643fd1c9e7SStefano Zampini 12653fd1c9e7SStefano Zampini PetscFunctionBegin; 12664f58015eSStefano Zampini PetscCheck(!is->allow_repeated || insmode == ADD_VALUES, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "INSERT_VALUES with repeated entries not supported"); 12674b89b9cdSStefano Zampini if (D) { /* MatShift_IS pass D = NULL */ 12689566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, D, is->y, INSERT_VALUES, SCATTER_FORWARD)); 12699566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, D, is->y, INSERT_VALUES, SCATTER_FORWARD)); 12703fd1c9e7SStefano Zampini } 12719566063dSJacob Faibussowitsch PetscCall(VecPointwiseDivide(is->y, is->y, is->counter)); 12729566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet(is->A, is->y, insmode)); 12733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12743fd1c9e7SStefano Zampini } 12753fd1c9e7SStefano Zampini 1276d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatShift_IS(Mat A, PetscScalar a) 1277d71ae5a4SJacob Faibussowitsch { 12784b89b9cdSStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 12793fd1c9e7SStefano Zampini 12803fd1c9e7SStefano Zampini PetscFunctionBegin; 12819566063dSJacob Faibussowitsch PetscCall(VecSet(is->y, a)); 12829566063dSJacob Faibussowitsch PetscCall(MatDiagonalSet_IS(A, NULL, ADD_VALUES)); 12833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12843fd1c9e7SStefano Zampini } 12853fd1c9e7SStefano Zampini 1286d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) 1287d71ae5a4SJacob Faibussowitsch { 1288f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION], cols_l[MATIS_MAX_ENTRIES_INSERTION]; 1289f26d0771SStefano Zampini 1290f26d0771SStefano Zampini PetscFunctionBegin; 1291aed4548fSBarry 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); 12929566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(A->rmap->mapping, m, rows, rows_l)); 12939566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApply(A->cmap->mapping, n, cols, cols_l)); 12949566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal_IS(A, m, rows_l, n, cols_l, values, addv)); 12953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1296f26d0771SStefano Zampini } 1297f26d0771SStefano Zampini 1298d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesBlockedLocal_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 block indices must be <= %d: they are %" PetscInt_FMT " %" PetscInt_FMT, MATIS_MAX_ENTRIES_INSERTION, m, n); 13049566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(A->rmap->mapping, m, rows, rows_l)); 13059566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingApplyBlock(A->cmap->mapping, n, cols, cols_l)); 13069566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlockedLocal_IS(A, m, rows_l, n, cols_l, values, addv)); 13073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1308f26d0771SStefano Zampini } 1309f26d0771SStefano Zampini 1310d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrix_IS(Mat mat, IS irow, IS icol, MatReuse scall, Mat *newmat) 1311d71ae5a4SJacob Faibussowitsch { 1312a8116848SStefano Zampini Mat locmat, newlocmat; 1313a8116848SStefano Zampini Mat_IS *newmatis; 1314a8116848SStefano Zampini const PetscInt *idxs; 1315a8116848SStefano Zampini PetscInt i, m, n; 1316a8116848SStefano Zampini 1317a8116848SStefano Zampini PetscFunctionBegin; 1318a8116848SStefano Zampini if (scall == MAT_REUSE_MATRIX) { 1319a8116848SStefano Zampini PetscBool ismatis; 1320a8116848SStefano Zampini 13219566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)*newmat, MATIS, &ismatis)); 132228b400f6SJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_ARG_WRONG, "Cannot reuse matrix! Not of MATIS type"); 1323a8116848SStefano Zampini newmatis = (Mat_IS *)(*newmat)->data; 132428b400f6SJacob Faibussowitsch PetscCheck(newmatis->getsub_ris, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_ARG_WRONG, "Cannot reuse matrix! Misses local row IS"); 132528b400f6SJacob Faibussowitsch PetscCheck(newmatis->getsub_cis, PetscObjectComm((PetscObject)*newmat), PETSC_ERR_ARG_WRONG, "Cannot reuse matrix! Misses local col IS"); 1326a8116848SStefano Zampini } 1327a8116848SStefano Zampini /* irow and icol may not have duplicate entries */ 132876bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 132976bd3646SJed Brown Vec rtest, ltest; 133076bd3646SJed Brown const PetscScalar *array; 133176bd3646SJed Brown 13329566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(mat, <est, &rtest)); 13339566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(irow, &n)); 13349566063dSJacob Faibussowitsch PetscCall(ISGetIndices(irow, &idxs)); 133548a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(VecSetValue(rtest, idxs[i], 1.0, ADD_VALUES)); 13369566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(rtest)); 13379566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(rtest)); 13389566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(rtest, &n)); 13399566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(rtest, &m, NULL)); 13409566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(rtest, &array)); 1341aed4548fSBarry 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])); 13429566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(rtest, &array)); 13439566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(irow, &idxs)); 13449566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(icol, &n)); 13459566063dSJacob Faibussowitsch PetscCall(ISGetIndices(icol, &idxs)); 134648a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(VecSetValue(ltest, idxs[i], 1.0, ADD_VALUES)); 13479566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(ltest)); 13489566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(ltest)); 13499566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(ltest, &n)); 13509566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(ltest, &m, NULL)); 13519566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(ltest, &array)); 1352aed4548fSBarry 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])); 13539566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(ltest, &array)); 13549566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(icol, &idxs)); 13559566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rtest)); 13569566063dSJacob Faibussowitsch PetscCall(VecDestroy(<est)); 135776bd3646SJed Brown } 1358a8116848SStefano Zampini if (scall == MAT_INITIAL_MATRIX) { 1359a8116848SStefano Zampini Mat_IS *matis = (Mat_IS *)mat->data; 1360a8116848SStefano Zampini ISLocalToGlobalMapping rl2g; 1361a8116848SStefano Zampini IS is; 1362a8116848SStefano Zampini PetscInt *lidxs, *lgidxs, *newgidxs; 1363306cf5c7SStefano Zampini PetscInt ll, newloc, irbs, icbs, arbs, acbs, rbs, cbs; 136494342113SStefano Zampini PetscBool cong; 1365a8116848SStefano Zampini MPI_Comm comm; 1366a8116848SStefano Zampini 13679566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 13689566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(mat, &arbs, &acbs)); 13699566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(irow, &irbs)); 13709566063dSJacob Faibussowitsch PetscCall(ISGetBlockSize(icol, &icbs)); 1371306cf5c7SStefano Zampini rbs = arbs == irbs ? irbs : 1; 1372306cf5c7SStefano Zampini cbs = acbs == icbs ? icbs : 1; 13739566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(irow, &m)); 13749566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(icol, &n)); 13759566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, newmat)); 13769566063dSJacob Faibussowitsch PetscCall(MatSetType(*newmat, MATIS)); 13774f58015eSStefano Zampini PetscCall(MatISSetAllowRepeated(*newmat, matis->allow_repeated)); 13789566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*newmat, m, n, PETSC_DECIDE, PETSC_DECIDE)); 13799566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(*newmat, rbs, cbs)); 1380a8116848SStefano Zampini /* communicate irow to their owners in the layout */ 13819566063dSJacob Faibussowitsch PetscCall(ISGetIndices(irow, &idxs)); 13829566063dSJacob Faibussowitsch PetscCall(PetscLayoutMapLocal(mat->rmap, m, idxs, &ll, &lidxs, &lgidxs)); 13839566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(irow, &idxs)); 13849566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata, matis->sf->nroots)); 1385a8116848SStefano Zampini for (i = 0; i < ll; i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i] + 1; 13869566063dSJacob Faibussowitsch PetscCall(PetscFree(lidxs)); 13879566063dSJacob Faibussowitsch PetscCall(PetscFree(lgidxs)); 13889566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 13899566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 13909371c9d4SSatish Balay for (i = 0, newloc = 0; i < matis->sf->nleaves; i++) 13919371c9d4SSatish Balay if (matis->sf_leafdata[i]) newloc++; 13929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newloc, &newgidxs)); 13939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newloc, &lidxs)); 13943d996552SStefano Zampini for (i = 0, newloc = 0; i < matis->sf->nleaves; i++) 1395a8116848SStefano Zampini if (matis->sf_leafdata[i]) { 1396a8116848SStefano Zampini lidxs[newloc] = i; 1397a8116848SStefano Zampini newgidxs[newloc++] = matis->sf_leafdata[i] - 1; 1398a8116848SStefano Zampini } 13999566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, newloc, newgidxs, PETSC_OWN_POINTER, &is)); 14009566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g)); 14019566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetBlockSize(rl2g, rbs)); 14029566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 1403a8116848SStefano Zampini /* local is to extract local submatrix */ 1404a8116848SStefano Zampini newmatis = (Mat_IS *)(*newmat)->data; 14059566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, newloc, lidxs, PETSC_OWN_POINTER, &newmatis->getsub_ris)); 14069566063dSJacob Faibussowitsch PetscCall(MatHasCongruentLayouts(mat, &cong)); 140794342113SStefano Zampini if (cong && irow == icol && matis->csf == matis->sf) { 14089566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*newmat, rl2g, rl2g)); 14099566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)newmatis->getsub_ris)); 1410a8116848SStefano Zampini newmatis->getsub_cis = newmatis->getsub_ris; 1411a8116848SStefano Zampini } else { 1412a8116848SStefano Zampini ISLocalToGlobalMapping cl2g; 1413a8116848SStefano Zampini 1414a8116848SStefano Zampini /* communicate icol to their owners in the layout */ 14159566063dSJacob Faibussowitsch PetscCall(ISGetIndices(icol, &idxs)); 14169566063dSJacob Faibussowitsch PetscCall(PetscLayoutMapLocal(mat->cmap, n, idxs, &ll, &lidxs, &lgidxs)); 14179566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(icol, &idxs)); 14189566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->csf_rootdata, matis->csf->nroots)); 1419a8116848SStefano Zampini for (i = 0; i < ll; i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i] + 1; 14209566063dSJacob Faibussowitsch PetscCall(PetscFree(lidxs)); 14219566063dSJacob Faibussowitsch PetscCall(PetscFree(lgidxs)); 14229566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->csf, MPIU_INT, matis->csf_rootdata, matis->csf_leafdata, MPI_REPLACE)); 14239566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->csf, MPIU_INT, matis->csf_rootdata, matis->csf_leafdata, MPI_REPLACE)); 14249371c9d4SSatish Balay for (i = 0, newloc = 0; i < matis->csf->nleaves; i++) 14259371c9d4SSatish Balay if (matis->csf_leafdata[i]) newloc++; 14269566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newloc, &newgidxs)); 14279566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(newloc, &lidxs)); 14283d996552SStefano Zampini for (i = 0, newloc = 0; i < matis->csf->nleaves; i++) 1429a8116848SStefano Zampini if (matis->csf_leafdata[i]) { 1430a8116848SStefano Zampini lidxs[newloc] = i; 1431a8116848SStefano Zampini newgidxs[newloc++] = matis->csf_leafdata[i] - 1; 1432a8116848SStefano Zampini } 14339566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, newloc, newgidxs, PETSC_OWN_POINTER, &is)); 14349566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g)); 14359566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetBlockSize(cl2g, cbs)); 14369566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 1437a8116848SStefano Zampini /* local is to extract local submatrix */ 14389566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, newloc, lidxs, PETSC_OWN_POINTER, &newmatis->getsub_cis)); 14399566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*newmat, rl2g, cl2g)); 14409566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 1441a8116848SStefano Zampini } 14429566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 1443a8116848SStefano Zampini } else { 14449566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*newmat, &newlocmat)); 1445a8116848SStefano Zampini } 14469566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(mat, &locmat)); 1447a8116848SStefano Zampini newmatis = (Mat_IS *)(*newmat)->data; 14489566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(locmat, newmatis->getsub_ris, newmatis->getsub_cis, scall, &newlocmat)); 1449a8116848SStefano Zampini if (scall == MAT_INITIAL_MATRIX) { 14509566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*newmat, newlocmat)); 14519566063dSJacob Faibussowitsch PetscCall(MatDestroy(&newlocmat)); 1452a8116848SStefano Zampini } 14539566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*newmat, MAT_FINAL_ASSEMBLY)); 14549566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*newmat, MAT_FINAL_ASSEMBLY)); 14553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1456a8116848SStefano Zampini } 1457a8116848SStefano Zampini 1458d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCopy_IS(Mat A, Mat B, MatStructure str) 1459d71ae5a4SJacob Faibussowitsch { 14602b404112SStefano Zampini Mat_IS *a = (Mat_IS *)A->data, *b; 14612b404112SStefano Zampini PetscBool ismatis; 14622b404112SStefano Zampini 14632b404112SStefano Zampini PetscFunctionBegin; 14649566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)B, MATIS, &ismatis)); 146528b400f6SJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Need to be implemented"); 14662b404112SStefano Zampini b = (Mat_IS *)B->data; 14679566063dSJacob Faibussowitsch PetscCall(MatCopy(a->A, b->A, str)); 14689566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)B)); 14693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14702b404112SStefano Zampini } 14712b404112SStefano Zampini 1472d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_IS(Mat A, PetscBool *missing, PetscInt *d) 1473d71ae5a4SJacob Faibussowitsch { 1474527b2640SStefano Zampini Vec v; 1475527b2640SStefano Zampini const PetscScalar *array; 1476527b2640SStefano Zampini PetscInt i, n; 14776bd84002SStefano Zampini 14786bd84002SStefano Zampini PetscFunctionBegin; 1479527b2640SStefano Zampini *missing = PETSC_FALSE; 14809566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, NULL, &v)); 14819566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(A, v)); 14829566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 14839566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(v, &array)); 14849371c9d4SSatish Balay for (i = 0; i < n; i++) 14859371c9d4SSatish Balay if (array[i] == 0.) break; 14869566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(v, &array)); 14879566063dSJacob Faibussowitsch PetscCall(VecDestroy(&v)); 1488527b2640SStefano Zampini if (i != n) *missing = PETSC_TRUE; 1489527b2640SStefano Zampini if (d) { 1490527b2640SStefano Zampini *d = -1; 1491527b2640SStefano Zampini if (*missing) { 1492527b2640SStefano Zampini PetscInt rstart; 14939566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rstart, NULL)); 1494527b2640SStefano Zampini *d = i + rstart; 1495527b2640SStefano Zampini } 1496527b2640SStefano Zampini } 14973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14986bd84002SStefano Zampini } 14996bd84002SStefano Zampini 1500d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISSetUpSF_IS(Mat B) 1501d71ae5a4SJacob Faibussowitsch { 1502f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)B->data; 150328f4e0baSStefano Zampini const PetscInt *gidxs; 15044f2d7cafSStefano Zampini PetscInt nleaves; 150528f4e0baSStefano Zampini 150628f4e0baSStefano Zampini PetscFunctionBegin; 15073ba16761SJacob Faibussowitsch if (matis->sf) PetscFunctionReturn(PETSC_SUCCESS); 15089566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)B), &matis->sf)); 15099566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->rmapping, &gidxs)); 15109566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->rmapping, &nleaves)); 15119566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(matis->sf, B->rmap, nleaves, NULL, PETSC_OWN_POINTER, gidxs)); 15129566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->rmapping, &gidxs)); 15139566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(matis->sf->nroots, &matis->sf_rootdata, matis->sf->nleaves, &matis->sf_leafdata)); 1514e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { /* setup SF for columns */ 15159566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->cmapping, &nleaves)); 15169566063dSJacob Faibussowitsch PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)B), &matis->csf)); 15179566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(matis->cmapping, &gidxs)); 15189566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraphLayout(matis->csf, B->cmap, nleaves, NULL, PETSC_OWN_POINTER, gidxs)); 15199566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(matis->cmapping, &gidxs)); 15209566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(matis->csf->nroots, &matis->csf_rootdata, matis->csf->nleaves, &matis->csf_leafdata)); 1521a8116848SStefano Zampini } else { 1522a8116848SStefano Zampini matis->csf = matis->sf; 1523a8116848SStefano Zampini matis->csf_leafdata = matis->sf_leafdata; 1524a8116848SStefano Zampini matis->csf_rootdata = matis->sf_rootdata; 1525a8116848SStefano Zampini } 15263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 152728f4e0baSStefano Zampini } 15282e1947a5SStefano Zampini 1529eb82efa4SStefano Zampini /*@ 15304f58015eSStefano Zampini MatISGetAllowRepeated - Get the flag to allow repeated entries in the local to global map 15314f58015eSStefano Zampini 15324f58015eSStefano Zampini Not Collective 15334f58015eSStefano Zampini 15344f58015eSStefano Zampini Input Parameter: 15354f58015eSStefano Zampini . A - the matrix 15364f58015eSStefano Zampini 15374f58015eSStefano Zampini Output Parameter: 15384f58015eSStefano Zampini . flg - the boolean flag 15394f58015eSStefano Zampini 15404f58015eSStefano Zampini Level: intermediate 15414f58015eSStefano Zampini 15424f58015eSStefano Zampini .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateIS()`, `MatSetLocalToGlobalMapping()`, `MatISSetAllowRepeated()` 15434f58015eSStefano Zampini @*/ 15444f58015eSStefano Zampini PetscErrorCode MatISGetAllowRepeated(Mat A, PetscBool *flg) 15454f58015eSStefano Zampini { 15464f58015eSStefano Zampini PetscBool ismatis; 15474f58015eSStefano Zampini 15484f58015eSStefano Zampini PetscFunctionBegin; 15494f58015eSStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 15504f58015eSStefano Zampini PetscAssertPointer(flg, 2); 15514f58015eSStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)A, MATIS, &ismatis)); 15524f58015eSStefano Zampini PetscCheck(ismatis, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)A)->type_name); 15534f58015eSStefano Zampini *flg = ((Mat_IS *)A->data)->allow_repeated; 15544f58015eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 15554f58015eSStefano Zampini } 15564f58015eSStefano Zampini 15574f58015eSStefano Zampini /*@ 15584f58015eSStefano Zampini MatISSetAllowRepeated - Set the flag to allow repeated entries in the local to global map 15594f58015eSStefano Zampini 15604f58015eSStefano Zampini Logically Collective 15614f58015eSStefano Zampini 15624f58015eSStefano Zampini Input Parameters: 15634f58015eSStefano Zampini + A - the matrix 15644f58015eSStefano Zampini - flg - the boolean flag 15654f58015eSStefano Zampini 15664f58015eSStefano Zampini Level: intermediate 15674f58015eSStefano Zampini 15684f58015eSStefano Zampini Notes: 15694f58015eSStefano Zampini The default value is `PETSC_FALSE`. 15704f58015eSStefano Zampini When called AFTER calling `MatSetLocalToGlobalMapping()` it will recreate the local matrices 15714f58015eSStefano Zampini if `flg` is different from the previously set value. 15724f58015eSStefano Zampini Specifically, when `flg` is true it will just recreate the local matrices, while if 15734f58015eSStefano Zampini `flg` is false will assemble the local matrices summing up repeated entries. 15744f58015eSStefano Zampini 15754f58015eSStefano Zampini .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateIS()`, `MatSetLocalToGlobalMapping()`, `MatISGetAllowRepeated()` 15764f58015eSStefano Zampini @*/ 15774f58015eSStefano Zampini PetscErrorCode MatISSetAllowRepeated(Mat A, PetscBool flg) 15784f58015eSStefano Zampini { 15794f58015eSStefano Zampini PetscFunctionBegin; 15804f58015eSStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 15814f58015eSStefano Zampini PetscValidType(A, 1); 15824f58015eSStefano Zampini PetscValidLogicalCollectiveBool(A, flg, 2); 15834f58015eSStefano Zampini PetscTryMethod(A, "MatISSetAllowRepeated_C", (Mat, PetscBool), (A, flg)); 15844f58015eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 15854f58015eSStefano Zampini } 15864f58015eSStefano Zampini 15874f58015eSStefano Zampini static PetscErrorCode MatISSetAllowRepeated_IS(Mat A, PetscBool flg) 15884f58015eSStefano Zampini { 15894f58015eSStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 15904f58015eSStefano Zampini Mat lA = NULL; 15914f58015eSStefano Zampini ISLocalToGlobalMapping lrmap, lcmap; 15924f58015eSStefano Zampini 15934f58015eSStefano Zampini PetscFunctionBegin; 15944f58015eSStefano Zampini if (flg == matis->allow_repeated) PetscFunctionReturn(PETSC_SUCCESS); 15954f58015eSStefano Zampini if (!matis->A) { /* matrix has not been preallocated yet */ 15964f58015eSStefano Zampini matis->allow_repeated = flg; 15974f58015eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 15984f58015eSStefano Zampini } 15994f58015eSStefano Zampini PetscCheck(!matis->islocalref, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not implemented for local references"); 16004f58015eSStefano Zampini if (matis->allow_repeated) { /* we will assemble the old local matrix if needed */ 16014f58015eSStefano Zampini lA = matis->A; 16024f58015eSStefano Zampini PetscCall(PetscObjectReference((PetscObject)lA)); 16034f58015eSStefano Zampini } 16044f58015eSStefano Zampini /* In case flg is True, we only recreate the local matrix */ 16054f58015eSStefano Zampini matis->allow_repeated = flg; 16064f58015eSStefano Zampini PetscCall(MatSetLocalToGlobalMapping(A, A->rmap->mapping, A->cmap->mapping)); 16074f58015eSStefano Zampini if (lA) { /* assemble previous local matrix if needed */ 16084f58015eSStefano Zampini Mat nA = matis->A; 16094f58015eSStefano Zampini 16104f58015eSStefano Zampini PetscCall(MatGetLocalToGlobalMapping(nA, &lrmap, &lcmap)); 16114f58015eSStefano Zampini if (!lrmap && !lcmap) { 16124f58015eSStefano Zampini PetscCall(MatISSetLocalMat(A, lA)); 16134f58015eSStefano Zampini } else { 16144f58015eSStefano Zampini Mat P = NULL, R = NULL; 16154f58015eSStefano Zampini MatProductType ptype; 16164f58015eSStefano Zampini 16174f58015eSStefano Zampini if (lrmap == lcmap) { 16184f58015eSStefano Zampini ptype = MATPRODUCT_PtAP; 16194f58015eSStefano Zampini PetscCall(MatCreateFromISLocalToGlobalMapping(lcmap, nA, PETSC_TRUE, PETSC_FALSE, NULL, &P)); 16204f58015eSStefano Zampini PetscCall(MatProductCreate(lA, P, NULL, &nA)); 16214f58015eSStefano Zampini } else { 16224f58015eSStefano Zampini if (lcmap) PetscCall(MatCreateFromISLocalToGlobalMapping(lcmap, nA, PETSC_TRUE, PETSC_FALSE, NULL, &P)); 16234f58015eSStefano Zampini if (lrmap) PetscCall(MatCreateFromISLocalToGlobalMapping(lrmap, nA, PETSC_FALSE, PETSC_TRUE, NULL, &R)); 16244f58015eSStefano Zampini if (R && P) { 16254f58015eSStefano Zampini ptype = MATPRODUCT_ABC; 16264f58015eSStefano Zampini PetscCall(MatProductCreate(R, lA, P, &nA)); 16274f58015eSStefano Zampini } else if (R) { 16284f58015eSStefano Zampini ptype = MATPRODUCT_AB; 16294f58015eSStefano Zampini PetscCall(MatProductCreate(R, lA, NULL, &nA)); 16304f58015eSStefano Zampini } else { 16314f58015eSStefano Zampini ptype = MATPRODUCT_AB; 16324f58015eSStefano Zampini PetscCall(MatProductCreate(lA, P, NULL, &nA)); 16334f58015eSStefano Zampini } 16344f58015eSStefano Zampini } 16354f58015eSStefano Zampini PetscCall(MatProductSetType(nA, ptype)); 16364f58015eSStefano Zampini PetscCall(MatProductSetFromOptions(nA)); 16374f58015eSStefano Zampini PetscCall(MatProductSymbolic(nA)); 16384f58015eSStefano Zampini PetscCall(MatProductNumeric(nA)); 16394f58015eSStefano Zampini PetscCall(MatProductClear(nA)); 16404f58015eSStefano Zampini PetscCall(MatConvert(nA, matis->lmattype, MAT_INPLACE_MATRIX, &nA)); 16414f58015eSStefano Zampini PetscCall(MatISSetLocalMat(A, nA)); 16424f58015eSStefano Zampini PetscCall(MatDestroy(&nA)); 16434f58015eSStefano Zampini PetscCall(MatDestroy(&P)); 16444f58015eSStefano Zampini PetscCall(MatDestroy(&R)); 16454f58015eSStefano Zampini } 16464f58015eSStefano Zampini } 16474f58015eSStefano Zampini PetscCall(MatDestroy(&lA)); 16484f58015eSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 16494f58015eSStefano Zampini } 16504f58015eSStefano Zampini 16514f58015eSStefano Zampini /*@ 16522ef1f0ffSBarry Smith MatISStoreL2L - Store local-to-local operators during the Galerkin process of computing `MatPtAP()` 165375d48cdbSStefano Zampini 16544f58015eSStefano Zampini Logically Collective 165575d48cdbSStefano Zampini 165675d48cdbSStefano Zampini Input Parameters: 165775d48cdbSStefano Zampini + A - the matrix 165875d48cdbSStefano Zampini - store - the boolean flag 165975d48cdbSStefano Zampini 166075d48cdbSStefano Zampini Level: advanced 166175d48cdbSStefano Zampini 16621cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateIS()`, `MatISSetPreallocation()`, `MatPtAP()` 166375d48cdbSStefano Zampini @*/ 1664d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISStoreL2L(Mat A, PetscBool store) 1665d71ae5a4SJacob Faibussowitsch { 166675d48cdbSStefano Zampini PetscFunctionBegin; 166775d48cdbSStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 166875d48cdbSStefano Zampini PetscValidType(A, 1); 166975d48cdbSStefano Zampini PetscValidLogicalCollectiveBool(A, store, 2); 1670cac4c232SBarry Smith PetscTryMethod(A, "MatISStoreL2L_C", (Mat, PetscBool), (A, store)); 16713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 167275d48cdbSStefano Zampini } 167375d48cdbSStefano Zampini 1674d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISStoreL2L_IS(Mat A, PetscBool store) 1675d71ae5a4SJacob Faibussowitsch { 1676f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)A->data; 167775d48cdbSStefano Zampini 167875d48cdbSStefano Zampini PetscFunctionBegin; 167975d48cdbSStefano Zampini matis->storel2l = store; 168057508eceSPierre Jolivet if (!store) PetscCall(PetscObjectCompose((PetscObject)A, "_MatIS_PtAP_l2l", NULL)); 16813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 168275d48cdbSStefano Zampini } 168375d48cdbSStefano Zampini 168475d48cdbSStefano Zampini /*@ 1685f03112d0SStefano Zampini MatISFixLocalEmpty - Compress out zero local rows from the local matrices 1686f03112d0SStefano Zampini 16874f58015eSStefano Zampini Logically Collective 1688f03112d0SStefano Zampini 1689f03112d0SStefano Zampini Input Parameters: 1690f03112d0SStefano Zampini + A - the matrix 1691f03112d0SStefano Zampini - fix - the boolean flag 1692f03112d0SStefano Zampini 1693f03112d0SStefano Zampini Level: advanced 1694f03112d0SStefano Zampini 169511a5261eSBarry Smith Note: 16962fe279fdSBarry Smith When `fix` is `PETSC_TRUE`, new local matrices and l2g maps are generated during the final assembly process. 1697f03112d0SStefano Zampini 16981cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatCreate()`, `MatCreateIS()`, `MatISSetPreallocation()`, `MatAssemblyEnd()`, `MAT_FINAL_ASSEMBLY` 1699f03112d0SStefano Zampini @*/ 1700d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISFixLocalEmpty(Mat A, PetscBool fix) 1701d71ae5a4SJacob Faibussowitsch { 1702f03112d0SStefano Zampini PetscFunctionBegin; 1703f03112d0SStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1704f03112d0SStefano Zampini PetscValidType(A, 1); 1705f03112d0SStefano Zampini PetscValidLogicalCollectiveBool(A, fix, 2); 1706cac4c232SBarry Smith PetscTryMethod(A, "MatISFixLocalEmpty_C", (Mat, PetscBool), (A, fix)); 17073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1708f03112d0SStefano Zampini } 1709f03112d0SStefano Zampini 1710d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISFixLocalEmpty_IS(Mat A, PetscBool fix) 1711d71ae5a4SJacob Faibussowitsch { 1712f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)A->data; 1713f03112d0SStefano Zampini 1714f03112d0SStefano Zampini PetscFunctionBegin; 1715f03112d0SStefano Zampini matis->locempty = fix; 17163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1717f03112d0SStefano Zampini } 1718f03112d0SStefano Zampini 1719f03112d0SStefano Zampini /*@ 172011a5261eSBarry Smith MatISSetPreallocation - Preallocates memory for a `MATIS` parallel matrix. 1721a88811baSStefano Zampini 1722d083f849SBarry Smith Collective 1723a88811baSStefano Zampini 1724a88811baSStefano Zampini Input Parameters: 1725a88811baSStefano Zampini + B - the matrix 1726a88811baSStefano Zampini . d_nz - number of nonzeros per row in DIAGONAL portion of local submatrix 1727a88811baSStefano Zampini (same value is used for all local rows) 1728a88811baSStefano Zampini . d_nnz - array containing the number of nonzeros in the various rows of the 1729a88811baSStefano Zampini DIAGONAL portion of the local submatrix (possibly different for each row) 17302ef1f0ffSBarry Smith or `NULL`, if `d_nz` is used to specify the nonzero structure. 17312ef1f0ffSBarry Smith The size of this array is equal to the number of local rows, i.e `m`. 1732a88811baSStefano Zampini For matrices that will be factored, you must leave room for (and set) 1733a88811baSStefano Zampini the diagonal entry even if it is zero. 1734a88811baSStefano Zampini . o_nz - number of nonzeros per row in the OFF-DIAGONAL portion of local 1735a88811baSStefano Zampini submatrix (same value is used for all local rows). 1736a88811baSStefano Zampini - o_nnz - array containing the number of nonzeros in the various rows of the 1737a88811baSStefano Zampini OFF-DIAGONAL portion of the local submatrix (possibly different for 17382ef1f0ffSBarry Smith each row) or `NULL`, if `o_nz` is used to specify the nonzero 1739a88811baSStefano Zampini structure. The size of this array is equal to the number 17402ef1f0ffSBarry Smith of local rows, i.e `m`. 1741a88811baSStefano Zampini 1742a88811baSStefano Zampini If the *_nnz parameter is given then the *_nz parameter is ignored 1743a88811baSStefano Zampini 1744a88811baSStefano Zampini Level: intermediate 1745a88811baSStefano Zampini 174611a5261eSBarry Smith Note: 174711a5261eSBarry Smith This function has the same interface as the `MATMPIAIJ` preallocation routine in order to simplify the transition 174811a5261eSBarry Smith from the asssembled format to the unassembled one. It overestimates the preallocation of `MATIS` local 1749a88811baSStefano Zampini matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects. 1750a88811baSStefano Zampini 17511cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateIS()`, `MatMPIAIJSetPreallocation()`, `MatISGetLocalMat()`, `MATIS` 1752a88811baSStefano Zampini @*/ 1753d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISSetPreallocation(Mat B, PetscInt d_nz, const PetscInt d_nnz[], PetscInt o_nz, const PetscInt o_nnz[]) 1754d71ae5a4SJacob Faibussowitsch { 17552e1947a5SStefano Zampini PetscFunctionBegin; 17562e1947a5SStefano Zampini PetscValidHeaderSpecific(B, MAT_CLASSID, 1); 17572e1947a5SStefano Zampini PetscValidType(B, 1); 1758cac4c232SBarry Smith PetscTryMethod(B, "MatISSetPreallocation_C", (Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]), (B, d_nz, d_nnz, o_nz, o_nnz)); 17593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17602e1947a5SStefano Zampini } 17612e1947a5SStefano Zampini 1762523895eeSPierre Jolivet static PetscErrorCode MatISSetPreallocation_IS(Mat B, PetscInt d_nz, const PetscInt d_nnz[], PetscInt o_nz, const PetscInt o_nnz[]) 1763d71ae5a4SJacob Faibussowitsch { 1764f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)B->data; 176528f4e0baSStefano Zampini PetscInt bs, i, nlocalcols; 17662e1947a5SStefano Zampini 17672e1947a5SStefano Zampini PetscFunctionBegin; 17689566063dSJacob Faibussowitsch PetscCall(MatSetUp(B)); 17699371c9d4SSatish Balay if (!d_nnz) 17709371c9d4SSatish Balay for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] = d_nz; 17719371c9d4SSatish Balay else 17729371c9d4SSatish Balay for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] = d_nnz[i]; 17734f2d7cafSStefano Zampini 17749371c9d4SSatish Balay if (!o_nnz) 17759371c9d4SSatish Balay for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] += o_nz; 17769371c9d4SSatish Balay else 17779371c9d4SSatish Balay for (i = 0; i < matis->sf->nroots; i++) matis->sf_rootdata[i] += o_nnz[i]; 17784f2d7cafSStefano Zampini 17799566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 17809566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, NULL, &nlocalcols)); 17819566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(matis->A, &bs)); 17829566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 17834f2d7cafSStefano Zampini 17844f2d7cafSStefano Zampini for (i = 0; i < matis->sf->nleaves; i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i], nlocalcols); 17859566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(matis->A, 0, matis->sf_leafdata)); 17860f2f62c7SStefano Zampini #if defined(PETSC_HAVE_HYPRE) 17879566063dSJacob Faibussowitsch PetscCall(MatHYPRESetPreallocation(matis->A, 0, matis->sf_leafdata, 0, NULL)); 17880f2f62c7SStefano Zampini #endif 17894f2d7cafSStefano Zampini 1790fc989267SStefano Zampini for (i = 0; i < matis->sf->nleaves / bs; i++) { 1791fc989267SStefano Zampini PetscInt b; 1792fc989267SStefano Zampini 1793fc989267SStefano Zampini matis->sf_leafdata[i] = matis->sf_leafdata[i * bs] / bs; 1794ad540459SPierre Jolivet for (b = 1; b < bs; b++) matis->sf_leafdata[i] = PetscMax(matis->sf_leafdata[i], matis->sf_leafdata[i * bs + b] / bs); 1795fc989267SStefano Zampini } 17969566063dSJacob Faibussowitsch PetscCall(MatSeqBAIJSetPreallocation(matis->A, bs, 0, matis->sf_leafdata)); 17974f2d7cafSStefano Zampini 179800a59248SStefano Zampini nlocalcols /= bs; 179900a59248SStefano Zampini for (i = 0; i < matis->sf->nleaves / bs; i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i], nlocalcols - i); 18009566063dSJacob Faibussowitsch PetscCall(MatSeqSBAIJSetPreallocation(matis->A, bs, 0, matis->sf_leafdata)); 18010f2f62c7SStefano Zampini 18020f2f62c7SStefano Zampini /* for other matrix types */ 18039566063dSJacob Faibussowitsch PetscCall(MatSetUp(matis->A)); 18043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18052e1947a5SStefano Zampini } 1806b4319ba4SBarry Smith 1807d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatConvert_IS_XAIJ(Mat mat, MatType mtype, MatReuse reuse, Mat *M) 1808d71ae5a4SJacob Faibussowitsch { 1809f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)mat->data; 1810ac7f1a8bSStefano Zampini Mat local_mat = NULL, MT; 181153b44cf5SStefano Zampini PetscInt rbs, cbs, rows, cols, lrows, lcols; 1812b7ce53b6SStefano Zampini PetscInt local_rows, local_cols; 1813b9ed4604SStefano Zampini PetscBool isseqdense, isseqsbaij, isseqaij, isseqbaij; 1814f03112d0SStefano Zampini PetscMPIInt size; 18151683a169SBarry Smith const PetscScalar *array; 1816b7ce53b6SStefano Zampini 1817b7ce53b6SStefano Zampini PetscFunctionBegin; 18189566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 18194f58015eSStefano Zampini if (size == 1 && mat->rmap->N == matis->A->rmap->N && mat->cmap->N == matis->A->cmap->N && !matis->allow_repeated) { 18201670daf9Sstefano_zampini Mat B; 182153b44cf5SStefano Zampini IS irows = NULL, icols = NULL; 1822487b449aSStefano Zampini PetscInt rbs, cbs; 18231670daf9Sstefano_zampini 18249566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->rmapping, &rbs)); 18259566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->cmapping, &cbs)); 182653b44cf5SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { /* check if l2g maps are one-to-one */ 182753b44cf5SStefano Zampini IS rows, cols; 182853b44cf5SStefano Zampini const PetscInt *ridxs, *cidxs; 18294f58015eSStefano Zampini PetscInt i, nw; 18304f58015eSStefano Zampini PetscBT work; 183153b44cf5SStefano Zampini 18329566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(matis->rmapping, &ridxs)); 18339566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->rmapping, &nw)); 183453b44cf5SStefano Zampini nw = nw / rbs; 18354f58015eSStefano Zampini PetscCall(PetscBTCreate(nw, &work)); 18364f58015eSStefano Zampini for (i = 0; i < nw; i++) PetscCall(PetscBTSet(work, ridxs[i])); 18379371c9d4SSatish Balay for (i = 0; i < nw; i++) 18384f58015eSStefano Zampini if (!PetscBTLookup(work, i)) break; 183953b44cf5SStefano Zampini if (i == nw) { 18409566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF, rbs, nw, ridxs, PETSC_USE_POINTER, &rows)); 18419566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(rows)); 18429566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(rows, PETSC_DECIDE, &irows)); 18439566063dSJacob Faibussowitsch PetscCall(ISDestroy(&rows)); 184453b44cf5SStefano Zampini } 18459566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(matis->rmapping, &ridxs)); 18464f58015eSStefano Zampini PetscCall(PetscBTDestroy(&work)); 1847e432b41dSStefano Zampini if (irows && matis->rmapping != matis->cmapping) { 18489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(matis->cmapping, &cidxs)); 18499566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(matis->cmapping, &nw)); 185053b44cf5SStefano Zampini nw = nw / cbs; 18514f58015eSStefano Zampini PetscCall(PetscBTCreate(nw, &work)); 18524f58015eSStefano Zampini for (i = 0; i < nw; i++) PetscCall(PetscBTSet(work, cidxs[i])); 18539371c9d4SSatish Balay for (i = 0; i < nw; i++) 18544f58015eSStefano Zampini if (!PetscBTLookup(work, i)) break; 185553b44cf5SStefano Zampini if (i == nw) { 18569566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF, cbs, nw, cidxs, PETSC_USE_POINTER, &cols)); 18579566063dSJacob Faibussowitsch PetscCall(ISSetPermutation(cols)); 18589566063dSJacob Faibussowitsch PetscCall(ISInvertPermutation(cols, PETSC_DECIDE, &icols)); 18599566063dSJacob Faibussowitsch PetscCall(ISDestroy(&cols)); 186053b44cf5SStefano Zampini } 18619566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(matis->cmapping, &cidxs)); 18624f58015eSStefano Zampini PetscCall(PetscBTDestroy(&work)); 186353b44cf5SStefano Zampini } else if (irows) { 18649566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)irows)); 186553b44cf5SStefano Zampini icols = irows; 186653b44cf5SStefano Zampini } 186753b44cf5SStefano Zampini } else { 1868f4f49eeaSPierre Jolivet PetscCall(PetscObjectQuery((PetscObject)*M, "_MatIS_IS_XAIJ_irows", (PetscObject *)&irows)); 1869f4f49eeaSPierre Jolivet PetscCall(PetscObjectQuery((PetscObject)*M, "_MatIS_IS_XAIJ_icols", (PetscObject *)&icols)); 18709566063dSJacob Faibussowitsch if (irows) PetscCall(PetscObjectReference((PetscObject)irows)); 18719566063dSJacob Faibussowitsch if (icols) PetscCall(PetscObjectReference((PetscObject)icols)); 187253b44cf5SStefano Zampini } 187353b44cf5SStefano Zampini if (!irows || !icols) { 18749566063dSJacob Faibussowitsch PetscCall(ISDestroy(&icols)); 18759566063dSJacob Faibussowitsch PetscCall(ISDestroy(&irows)); 187653b44cf5SStefano Zampini goto general_assembly; 187753b44cf5SStefano Zampini } 18789566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, mtype, MAT_INITIAL_MATRIX, &B)); 1879487b449aSStefano Zampini if (reuse != MAT_INPLACE_MATRIX) { 18809566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(B, irows, icols, reuse, M)); 1881f4f49eeaSPierre Jolivet PetscCall(PetscObjectCompose((PetscObject)*M, "_MatIS_IS_XAIJ_irows", (PetscObject)irows)); 1882f4f49eeaSPierre Jolivet PetscCall(PetscObjectCompose((PetscObject)*M, "_MatIS_IS_XAIJ_icols", (PetscObject)icols)); 1883487b449aSStefano Zampini } else { 1884487b449aSStefano Zampini Mat C; 1885487b449aSStefano Zampini 18869566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(B, irows, icols, MAT_INITIAL_MATRIX, &C)); 18879566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(mat, &C)); 1888487b449aSStefano Zampini } 18899566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 18909566063dSJacob Faibussowitsch PetscCall(ISDestroy(&icols)); 18919566063dSJacob Faibussowitsch PetscCall(ISDestroy(&irows)); 18923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18937c03b4e8SStefano Zampini } 189453b44cf5SStefano Zampini general_assembly: 18959566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &rows, &cols)); 18969566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->rmapping, &rbs)); 18979566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(matis->cmapping, &cbs)); 18989566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mat, &lrows, &lcols)); 18999566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, &local_rows, &local_cols)); 19009566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQDENSE, &isseqdense)); 19019566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQAIJ, &isseqaij)); 19029566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQBAIJ, &isseqbaij)); 19039566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)matis->A, MATSEQSBAIJ, &isseqsbaij)); 1904f4f49eeaSPierre Jolivet PetscCheck(isseqdense || isseqaij || isseqbaij || isseqsbaij, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not for matrix type %s", ((PetscObject)matis->A)->type_name); 190576bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 190676bd3646SJed Brown PetscBool lb[4], bb[4]; 190776bd3646SJed Brown 1908b9ed4604SStefano Zampini lb[0] = isseqdense; 1909b9ed4604SStefano Zampini lb[1] = isseqaij; 1910b9ed4604SStefano Zampini lb[2] = isseqbaij; 1911b9ed4604SStefano Zampini lb[3] = isseqsbaij; 1912*5440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(lb, bb, 4, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)mat))); 1913aed4548fSBarry Smith PetscCheck(bb[0] || bb[1] || bb[2] || bb[3], PETSC_COMM_SELF, PETSC_ERR_SUP, "Local matrices must have the same type"); 191476bd3646SJed Brown } 1915b7ce53b6SStefano Zampini 1916487b449aSStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 1917ac7f1a8bSStefano Zampini PetscCount ncoo; 1918ac7f1a8bSStefano Zampini PetscInt *coo_i, *coo_j; 1919ac7f1a8bSStefano Zampini 19209566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &MT)); 19219566063dSJacob Faibussowitsch PetscCall(MatSetSizes(MT, lrows, lcols, rows, cols)); 19229566063dSJacob Faibussowitsch PetscCall(MatSetType(MT, mtype)); 19239566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(MT, rbs, cbs)); 1924ac7f1a8bSStefano Zampini if (!isseqaij && !isseqdense) { 1925ac7f1a8bSStefano Zampini PetscCall(MatConvert(matis->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &local_mat)); 1926ac7f1a8bSStefano Zampini } else { 1927ac7f1a8bSStefano Zampini PetscCall(PetscObjectReference((PetscObject)matis->A)); 1928ac7f1a8bSStefano Zampini local_mat = matis->A; 1929ac7f1a8bSStefano Zampini } 1930ac7f1a8bSStefano Zampini PetscCall(MatSetLocalToGlobalMapping(MT, matis->rmapping, matis->cmapping)); 1931ac7f1a8bSStefano Zampini if (isseqdense) { 1932ac7f1a8bSStefano Zampini PetscInt nr, nc; 1933ac7f1a8bSStefano Zampini 1934ac7f1a8bSStefano Zampini PetscCall(MatGetSize(local_mat, &nr, &nc)); 1935ac7f1a8bSStefano Zampini ncoo = nr * nc; 1936ac7f1a8bSStefano Zampini PetscCall(PetscMalloc2(ncoo, &coo_i, ncoo, &coo_j)); 1937ac7f1a8bSStefano Zampini for (PetscInt j = 0; j < nc; j++) { 1938ac7f1a8bSStefano Zampini for (PetscInt i = 0; i < nr; i++) { 1939ac7f1a8bSStefano Zampini coo_i[j * nr + i] = i; 1940ac7f1a8bSStefano Zampini coo_j[j * nr + i] = j; 1941ac7f1a8bSStefano Zampini } 1942ac7f1a8bSStefano Zampini } 1943ac7f1a8bSStefano Zampini } else { 1944ac7f1a8bSStefano Zampini const PetscInt *ii, *jj; 1945ac7f1a8bSStefano Zampini PetscInt nr; 1946ac7f1a8bSStefano Zampini PetscBool done; 1947ac7f1a8bSStefano Zampini 1948ac7f1a8bSStefano Zampini PetscCall(MatGetRowIJ(local_mat, 0, PETSC_FALSE, PETSC_FALSE, &nr, &ii, &jj, &done)); 1949ac7f1a8bSStefano Zampini PetscCheck(done, PetscObjectComm((PetscObject)local_mat), PETSC_ERR_PLIB, "Error in MatGetRowIJ"); 1950ac7f1a8bSStefano Zampini ncoo = ii[nr]; 1951ac7f1a8bSStefano Zampini PetscCall(PetscMalloc2(ncoo, &coo_i, ncoo, &coo_j)); 1952ac7f1a8bSStefano Zampini PetscCall(PetscArraycpy(coo_j, jj, ncoo)); 1953ac7f1a8bSStefano Zampini for (PetscInt i = 0; i < nr; i++) { 1954ac7f1a8bSStefano Zampini for (PetscInt j = ii[i]; j < ii[i + 1]; j++) coo_i[j] = i; 1955ac7f1a8bSStefano Zampini } 1956ac7f1a8bSStefano Zampini PetscCall(MatRestoreRowIJ(local_mat, 0, PETSC_FALSE, PETSC_FALSE, &nr, &ii, &jj, &done)); 1957ac7f1a8bSStefano Zampini PetscCheck(done, PetscObjectComm((PetscObject)local_mat), PETSC_ERR_PLIB, "Error in MatRestoreRowIJ"); 1958ac7f1a8bSStefano Zampini } 1959ac7f1a8bSStefano Zampini PetscCall(MatSetPreallocationCOOLocal(MT, ncoo, coo_i, coo_j)); 1960ac7f1a8bSStefano Zampini PetscCall(PetscFree2(coo_i, coo_j)); 1961b7ce53b6SStefano Zampini } else { 196253b44cf5SStefano Zampini PetscInt mrbs, mcbs, mrows, mcols, mlrows, mlcols; 1963487b449aSStefano Zampini 1964b7ce53b6SStefano Zampini /* some checks */ 1965487b449aSStefano Zampini MT = *M; 19669566063dSJacob Faibussowitsch PetscCall(MatGetBlockSizes(MT, &mrbs, &mcbs)); 19679566063dSJacob Faibussowitsch PetscCall(MatGetSize(MT, &mrows, &mcols)); 19689566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(MT, &mlrows, &mlcols)); 196908401ef6SPierre Jolivet PetscCheck(mrows == rows, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of rows (%" PetscInt_FMT " != %" PetscInt_FMT ")", rows, mrows); 197008401ef6SPierre Jolivet PetscCheck(mcols == cols, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of cols (%" PetscInt_FMT " != %" PetscInt_FMT ")", cols, mcols); 197108401ef6SPierre Jolivet PetscCheck(mlrows == lrows, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of local rows (%" PetscInt_FMT " != %" PetscInt_FMT ")", lrows, mlrows); 197208401ef6SPierre Jolivet PetscCheck(mlcols == lcols, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong number of local cols (%" PetscInt_FMT " != %" PetscInt_FMT ")", lcols, mlcols); 197308401ef6SPierre Jolivet PetscCheck(mrbs == rbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong row block size (%" PetscInt_FMT " != %" PetscInt_FMT ")", rbs, mrbs); 197408401ef6SPierre Jolivet PetscCheck(mcbs == cbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Cannot reuse matrix. Wrong col block size (%" PetscInt_FMT " != %" PetscInt_FMT ")", cbs, mcbs); 19759566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(MT)); 1976ac7f1a8bSStefano Zampini if (!isseqaij && !isseqdense) { 19779566063dSJacob Faibussowitsch PetscCall(MatConvert(matis->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &local_mat)); 1978d9a9e74cSStefano Zampini } else { 19799566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)matis->A)); 1980d9a9e74cSStefano Zampini local_mat = matis->A; 1981d9a9e74cSStefano Zampini } 1982ac7f1a8bSStefano Zampini } 1983686e3a49SStefano Zampini 1984b7ce53b6SStefano Zampini /* Set values */ 1985ac7f1a8bSStefano Zampini if (isseqdense) { 19869566063dSJacob Faibussowitsch PetscCall(MatDenseGetArrayRead(local_mat, &array)); 1987ac7f1a8bSStefano Zampini PetscCall(MatSetValuesCOO(MT, array, INSERT_VALUES)); 19889566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArrayRead(local_mat, &array)); 19896afe12f5SStefano Zampini } else { 1990ac7f1a8bSStefano Zampini PetscCall(MatSeqAIJGetArrayRead(local_mat, &array)); 1991ac7f1a8bSStefano Zampini PetscCall(MatSetValuesCOO(MT, array, INSERT_VALUES)); 1992ac7f1a8bSStefano Zampini PetscCall(MatSeqAIJRestoreArrayRead(local_mat, &array)); 1993b7ce53b6SStefano Zampini } 19949566063dSJacob Faibussowitsch PetscCall(MatDestroy(&local_mat)); 19954f58015eSStefano Zampini PetscCall(MatAssemblyBegin(MT, MAT_FINAL_ASSEMBLY)); 19969566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(MT, MAT_FINAL_ASSEMBLY)); 1997487b449aSStefano Zampini if (reuse == MAT_INPLACE_MATRIX) { 19989566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(mat, &MT)); 1999487b449aSStefano Zampini } else if (reuse == MAT_INITIAL_MATRIX) { 2000487b449aSStefano Zampini *M = MT; 2001b7ce53b6SStefano Zampini } 20023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2003b7ce53b6SStefano Zampini } 2004b7ce53b6SStefano Zampini 2005d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDuplicate_IS(Mat mat, MatDuplicateOption op, Mat *newmat) 2006d71ae5a4SJacob Faibussowitsch { 2007f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)mat->data; 2008c9225affSStefano Zampini PetscInt rbs, cbs, m, n, M, N; 2009ad6194a2SStefano Zampini Mat B, localmat; 2010ad6194a2SStefano Zampini 2011ad6194a2SStefano Zampini PetscFunctionBegin; 20129566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &rbs)); 20139566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &cbs)); 20149566063dSJacob Faibussowitsch PetscCall(MatGetSize(mat, &M, &N)); 20159566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(mat, &m, &n)); 20169566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 20179566063dSJacob Faibussowitsch PetscCall(MatSetSizes(B, m, n, M, N)); 20189566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(B, rbs == cbs ? rbs : 1)); 20199566063dSJacob Faibussowitsch PetscCall(MatSetType(B, MATIS)); 20209566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(B, matis->lmattype)); 20214f58015eSStefano Zampini PetscCall(MatISSetAllowRepeated(B, matis->allow_repeated)); 20229566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(B, mat->rmap->mapping, mat->cmap->mapping)); 20239566063dSJacob Faibussowitsch PetscCall(MatDuplicate(matis->A, op, &localmat)); 20249566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(localmat, matis->A->rmap->mapping, matis->A->cmap->mapping)); 20259566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(B, localmat)); 20269566063dSJacob Faibussowitsch PetscCall(MatDestroy(&localmat)); 20279566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 20289566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 2029ad6194a2SStefano Zampini *newmat = B; 20303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2031ad6194a2SStefano Zampini } 2032ad6194a2SStefano Zampini 2033d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsHermitian_IS(Mat A, PetscReal tol, PetscBool *flg) 2034d71ae5a4SJacob Faibussowitsch { 203569796d55SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 203669796d55SStefano Zampini PetscBool local_sym; 203769796d55SStefano Zampini 203869796d55SStefano Zampini PetscFunctionBegin; 20399566063dSJacob Faibussowitsch PetscCall(MatIsHermitian(matis->A, tol, &local_sym)); 2040*5440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&local_sym, flg, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 20413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 204269796d55SStefano Zampini } 204369796d55SStefano Zampini 2044d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsSymmetric_IS(Mat A, PetscReal tol, PetscBool *flg) 2045d71ae5a4SJacob Faibussowitsch { 204669796d55SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 204769796d55SStefano Zampini PetscBool local_sym; 204869796d55SStefano Zampini 204969796d55SStefano Zampini PetscFunctionBegin; 2050e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { 2051e432b41dSStefano Zampini *flg = PETSC_FALSE; 20523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2053e432b41dSStefano Zampini } 20549566063dSJacob Faibussowitsch PetscCall(MatIsSymmetric(matis->A, tol, &local_sym)); 2055*5440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&local_sym, flg, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 20563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 205769796d55SStefano Zampini } 205869796d55SStefano Zampini 2059d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A, PetscBool *flg) 2060d71ae5a4SJacob Faibussowitsch { 206145471136SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 206245471136SStefano Zampini PetscBool local_sym; 206345471136SStefano Zampini 206445471136SStefano Zampini PetscFunctionBegin; 2065e432b41dSStefano Zampini if (matis->rmapping != matis->cmapping) { 206645471136SStefano Zampini *flg = PETSC_FALSE; 20673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 206845471136SStefano Zampini } 20699566063dSJacob Faibussowitsch PetscCall(MatIsStructurallySymmetric(matis->A, &local_sym)); 2070*5440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&local_sym, flg, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 20713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 207245471136SStefano Zampini } 207345471136SStefano Zampini 2074d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_IS(Mat A) 2075d71ae5a4SJacob Faibussowitsch { 2076b4319ba4SBarry Smith Mat_IS *b = (Mat_IS *)A->data; 2077b4319ba4SBarry Smith 2078b4319ba4SBarry Smith PetscFunctionBegin; 20799566063dSJacob Faibussowitsch PetscCall(PetscFree(b->bdiag)); 20809566063dSJacob Faibussowitsch PetscCall(PetscFree(b->lmattype)); 20819566063dSJacob Faibussowitsch PetscCall(MatDestroy(&b->A)); 20829566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&b->cctx)); 20839566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&b->rctx)); 20849566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->x)); 20859566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->y)); 20869566063dSJacob Faibussowitsch PetscCall(VecDestroy(&b->counter)); 20879566063dSJacob Faibussowitsch PetscCall(ISDestroy(&b->getsub_ris)); 20889566063dSJacob Faibussowitsch PetscCall(ISDestroy(&b->getsub_cis)); 2089a8116848SStefano Zampini if (b->sf != b->csf) { 20909566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&b->csf)); 20919566063dSJacob Faibussowitsch PetscCall(PetscFree2(b->csf_rootdata, b->csf_leafdata)); 2092f03112d0SStefano Zampini } else b->csf = NULL; 20939566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&b->sf)); 20949566063dSJacob Faibussowitsch PetscCall(PetscFree2(b->sf_rootdata, b->sf_leafdata)); 20959566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&b->rmapping)); 20969566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&b->cmapping)); 2097d0dbe9f7SStefano Zampini PetscCall(MatDestroy(&b->dA)); 2098d0dbe9f7SStefano Zampini PetscCall(MatDestroy(&b->assembledA)); 20999566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 21009566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, NULL)); 21019566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMatType_C", NULL)); 21029566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalMat_C", NULL)); 21039566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMat_C", NULL)); 21042e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISRestoreLocalMat_C", NULL)); 21059566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetPreallocation_C", NULL)); 21069566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISStoreL2L_C", NULL)); 21079566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISFixLocalEmpty_C", NULL)); 21089566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalToGlobalMapping_C", NULL)); 21099566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpiaij_C", NULL)); 21109566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpibaij_C", NULL)); 21119566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpisbaij_C", NULL)); 21129566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqaij_C", NULL)); 21139566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqbaij_C", NULL)); 21149566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqsbaij_C", NULL)); 21159566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_aij_C", NULL)); 21169566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOOLocal_C", NULL)); 21179566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL)); 21189566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL)); 21194f58015eSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetAllowRepeated_C", NULL)); 21203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2121b4319ba4SBarry Smith } 2122b4319ba4SBarry Smith 2123d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_IS(Mat A, Vec x, Vec y) 2124d71ae5a4SJacob Faibussowitsch { 2125b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)A->data; 2126b4319ba4SBarry Smith PetscScalar zero = 0.0; 2127b4319ba4SBarry Smith 2128b4319ba4SBarry Smith PetscFunctionBegin; 2129b4319ba4SBarry Smith /* scatter the global vector x into the local work vector */ 21309566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->cctx, x, is->x, INSERT_VALUES, SCATTER_FORWARD)); 21319566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->cctx, x, is->x, INSERT_VALUES, SCATTER_FORWARD)); 2132b4319ba4SBarry Smith 2133b4319ba4SBarry Smith /* multiply the local matrix */ 21349566063dSJacob Faibussowitsch PetscCall(MatMult(is->A, is->x, is->y)); 2135b4319ba4SBarry Smith 2136b4319ba4SBarry Smith /* scatter product back into global memory */ 21379566063dSJacob Faibussowitsch PetscCall(VecSet(y, zero)); 21389566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, is->y, y, ADD_VALUES, SCATTER_REVERSE)); 21399566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, is->y, y, ADD_VALUES, SCATTER_REVERSE)); 21403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2141b4319ba4SBarry Smith } 2142b4319ba4SBarry Smith 2143d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultAdd_IS(Mat A, Vec v1, Vec v2, Vec v3) 2144d71ae5a4SJacob Faibussowitsch { 2145650997f4SStefano Zampini Vec temp_vec; 21462e74eeadSLisandro Dalcin 21472e74eeadSLisandro Dalcin PetscFunctionBegin; /* v3 = v2 + A * v1.*/ 2148650997f4SStefano Zampini if (v3 != v2) { 21499566063dSJacob Faibussowitsch PetscCall(MatMult(A, v1, v3)); 21509566063dSJacob Faibussowitsch PetscCall(VecAXPY(v3, 1.0, v2)); 2151650997f4SStefano Zampini } else { 21529566063dSJacob Faibussowitsch PetscCall(VecDuplicate(v2, &temp_vec)); 21539566063dSJacob Faibussowitsch PetscCall(MatMult(A, v1, temp_vec)); 21549566063dSJacob Faibussowitsch PetscCall(VecAXPY(temp_vec, 1.0, v2)); 21559566063dSJacob Faibussowitsch PetscCall(VecCopy(temp_vec, v3)); 21569566063dSJacob Faibussowitsch PetscCall(VecDestroy(&temp_vec)); 2157650997f4SStefano Zampini } 21583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21592e74eeadSLisandro Dalcin } 21602e74eeadSLisandro Dalcin 2161d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTranspose_IS(Mat A, Vec y, Vec x) 2162d71ae5a4SJacob Faibussowitsch { 21632e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS *)A->data; 21642e74eeadSLisandro Dalcin 2165e176bc59SStefano Zampini PetscFunctionBegin; 21662e74eeadSLisandro Dalcin /* scatter the global vector x into the local work vector */ 21679566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, y, is->y, INSERT_VALUES, SCATTER_FORWARD)); 21689566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, y, is->y, INSERT_VALUES, SCATTER_FORWARD)); 21692e74eeadSLisandro Dalcin 21702e74eeadSLisandro Dalcin /* multiply the local matrix */ 21719566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(is->A, is->y, is->x)); 21722e74eeadSLisandro Dalcin 21732e74eeadSLisandro Dalcin /* scatter product back into global vector */ 21749566063dSJacob Faibussowitsch PetscCall(VecSet(x, 0)); 21759566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->cctx, is->x, x, ADD_VALUES, SCATTER_REVERSE)); 21769566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->cctx, is->x, x, ADD_VALUES, SCATTER_REVERSE)); 21773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21782e74eeadSLisandro Dalcin } 21792e74eeadSLisandro Dalcin 2180d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTransposeAdd_IS(Mat A, Vec v1, Vec v2, Vec v3) 2181d71ae5a4SJacob Faibussowitsch { 2182650997f4SStefano Zampini Vec temp_vec; 21832e74eeadSLisandro Dalcin 21842e74eeadSLisandro Dalcin PetscFunctionBegin; /* v3 = v2 + A' * v1.*/ 2185650997f4SStefano Zampini if (v3 != v2) { 21869566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(A, v1, v3)); 21879566063dSJacob Faibussowitsch PetscCall(VecAXPY(v3, 1.0, v2)); 2188650997f4SStefano Zampini } else { 21899566063dSJacob Faibussowitsch PetscCall(VecDuplicate(v2, &temp_vec)); 21909566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(A, v1, temp_vec)); 21919566063dSJacob Faibussowitsch PetscCall(VecAXPY(temp_vec, 1.0, v2)); 21929566063dSJacob Faibussowitsch PetscCall(VecCopy(temp_vec, v3)); 21939566063dSJacob Faibussowitsch PetscCall(VecDestroy(&temp_vec)); 2194650997f4SStefano Zampini } 21953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21962e74eeadSLisandro Dalcin } 21972e74eeadSLisandro Dalcin 2198a3ef7f04SStefano Zampini static PetscErrorCode ISLocalToGlobalMappingView_Multi(ISLocalToGlobalMapping mapping, PetscInt lsize, PetscInt gsize, const PetscInt vblocks[], PetscViewer viewer) 2199a3ef7f04SStefano Zampini { 2200a3ef7f04SStefano Zampini PetscInt tr[3], n; 2201a3ef7f04SStefano Zampini const PetscInt *indices; 2202a3ef7f04SStefano Zampini 2203a3ef7f04SStefano Zampini PetscFunctionBegin; 2204a3ef7f04SStefano Zampini tr[0] = IS_LTOGM_FILE_CLASSID; 2205a3ef7f04SStefano Zampini tr[1] = 1; 2206a3ef7f04SStefano Zampini tr[2] = gsize; 2207a3ef7f04SStefano Zampini PetscCall(PetscViewerBinaryWrite(viewer, tr, 3, PETSC_INT)); 2208a3ef7f04SStefano Zampini PetscCall(PetscViewerBinaryWriteAll(viewer, vblocks, lsize, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT)); 2209a3ef7f04SStefano Zampini PetscCall(ISLocalToGlobalMappingGetSize(mapping, &n)); 2210a3ef7f04SStefano Zampini PetscCall(ISLocalToGlobalMappingGetIndices(mapping, &indices)); 2211a3ef7f04SStefano Zampini PetscCall(PetscViewerBinaryWriteAll(viewer, indices, n, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_INT)); 2212a3ef7f04SStefano Zampini PetscCall(ISLocalToGlobalMappingRestoreIndices(mapping, &indices)); 2213a3ef7f04SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2214a3ef7f04SStefano Zampini } 2215a3ef7f04SStefano Zampini 2216d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_IS(Mat A, PetscViewer viewer) 2217d71ae5a4SJacob Faibussowitsch { 2218b4319ba4SBarry Smith Mat_IS *a = (Mat_IS *)A->data; 2219b4319ba4SBarry Smith PetscViewer sviewer; 22205042aa92SStefano Zampini PetscBool isascii, isbinary, viewl2g = PETSC_FALSE, native; 22215042aa92SStefano Zampini PetscViewerFormat format; 22225042aa92SStefano Zampini ISLocalToGlobalMapping rmap, cmap; 2223b4319ba4SBarry Smith 2224b4319ba4SBarry Smith PetscFunctionBegin; 22259566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 22265042aa92SStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 22279566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(viewer, &format)); 22285042aa92SStefano Zampini native = (PetscBool)(format == PETSC_VIEWER_NATIVE); 22295042aa92SStefano Zampini if (native) { 22305042aa92SStefano Zampini rmap = A->rmap->mapping; 22315042aa92SStefano Zampini cmap = A->cmap->mapping; 22325042aa92SStefano Zampini } else { 22335042aa92SStefano Zampini rmap = a->rmapping; 22345042aa92SStefano Zampini cmap = a->cmapping; 2235ee2491ecSStefano Zampini } 22365042aa92SStefano Zampini if (isascii) { 22375042aa92SStefano Zampini if (format == PETSC_VIEWER_ASCII_INFO) PetscFunctionReturn(PETSC_SUCCESS); 22385042aa92SStefano Zampini if (format == PETSC_VIEWER_ASCII_INFO_DETAIL || format == PETSC_VIEWER_ASCII_MATLAB) viewl2g = PETSC_TRUE; 22395042aa92SStefano Zampini } else if (isbinary) { 2240a3ef7f04SStefano Zampini PetscInt tr[6], nr, nc, lsize = 0; 22415042aa92SStefano Zampini char lmattype[64] = {'\0'}; 22425042aa92SStefano Zampini PetscMPIInt size; 2243a3ef7f04SStefano Zampini PetscBool skipHeader, vbs = PETSC_FALSE; 22445042aa92SStefano Zampini IS is; 2245a3ef7f04SStefano Zampini const PetscInt *vblocks = NULL; 22465042aa92SStefano Zampini 22475042aa92SStefano Zampini PetscCall(PetscViewerSetUp(viewer)); 2248a3ef7f04SStefano Zampini PetscCall(PetscOptionsGetBool(NULL, ((PetscObject)A)->prefix, "-mat_is_view_variableblocksizes", &vbs, NULL)); 2249a3ef7f04SStefano Zampini if (vbs) { 2250a3ef7f04SStefano Zampini PetscCall(MatGetVariableBlockSizes(a->A, &lsize, &vblocks)); 2251a3ef7f04SStefano Zampini PetscCall(PetscMPIIntCast(lsize, &size)); 2252a3ef7f04SStefano Zampini PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &size, 1, MPI_INT, MPI_SUM, PetscObjectComm((PetscObject)viewer))); 2253a3ef7f04SStefano Zampini } else { 22545042aa92SStefano Zampini PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 2255a3ef7f04SStefano Zampini } 22565042aa92SStefano Zampini tr[0] = MAT_FILE_CLASSID; 22575042aa92SStefano Zampini tr[1] = A->rmap->N; 22585042aa92SStefano Zampini tr[2] = A->cmap->N; 22595042aa92SStefano Zampini tr[3] = -size; /* AIJ stores nnz here */ 22605042aa92SStefano Zampini tr[4] = (PetscInt)(rmap == cmap); 22615042aa92SStefano Zampini tr[5] = a->allow_repeated; 22625042aa92SStefano Zampini PetscCall(PetscSNPrintf(lmattype, sizeof(lmattype), "%s", a->lmattype)); 22635042aa92SStefano Zampini 22645042aa92SStefano Zampini PetscCall(PetscViewerBinaryWrite(viewer, tr, PETSC_STATIC_ARRAY_LENGTH(tr), PETSC_INT)); 22655042aa92SStefano Zampini PetscCall(PetscViewerBinaryWrite(viewer, lmattype, sizeof(lmattype), PETSC_CHAR)); 22665042aa92SStefano Zampini 22675042aa92SStefano Zampini /* first dump l2g info (we need the header for proper loading on different number of processes) */ 22685042aa92SStefano Zampini PetscCall(PetscViewerBinaryGetSkipHeader(viewer, &skipHeader)); 22695042aa92SStefano Zampini PetscCall(PetscViewerBinarySetSkipHeader(viewer, PETSC_FALSE)); 2270a3ef7f04SStefano Zampini if (vbs) { 2271a3ef7f04SStefano Zampini PetscCall(ISLocalToGlobalMappingView_Multi(rmap, lsize, size, vblocks, viewer)); 2272a3ef7f04SStefano Zampini if (cmap != rmap) PetscCall(ISLocalToGlobalMappingView_Multi(cmap, lsize, size, vblocks, viewer)); 2273a3ef7f04SStefano Zampini PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), lsize, vblocks, PETSC_USE_POINTER, &is)); 2274a3ef7f04SStefano Zampini PetscCall(ISView(is, viewer)); 2275a3ef7f04SStefano Zampini PetscCall(ISView(is, viewer)); 2276a3ef7f04SStefano Zampini PetscCall(ISDestroy(&is)); 2277a3ef7f04SStefano Zampini } else { 22785042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingView(rmap, viewer)); 22795042aa92SStefano Zampini if (cmap != rmap) PetscCall(ISLocalToGlobalMappingView(cmap, viewer)); 22805042aa92SStefano Zampini 22815042aa92SStefano Zampini /* then the sizes of the local matrices */ 22825042aa92SStefano Zampini PetscCall(MatGetSize(a->A, &nr, &nc)); 22835042aa92SStefano Zampini PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), 1, &nr, PETSC_USE_POINTER, &is)); 22845042aa92SStefano Zampini PetscCall(ISView(is, viewer)); 22855042aa92SStefano Zampini PetscCall(ISDestroy(&is)); 22865042aa92SStefano Zampini PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), 1, &nc, PETSC_USE_POINTER, &is)); 22875042aa92SStefano Zampini PetscCall(ISView(is, viewer)); 22885042aa92SStefano Zampini PetscCall(ISDestroy(&is)); 2289a3ef7f04SStefano Zampini } 22905042aa92SStefano Zampini PetscCall(PetscViewerBinarySetSkipHeader(viewer, skipHeader)); 22915042aa92SStefano Zampini } 22925042aa92SStefano Zampini if (format == PETSC_VIEWER_ASCII_MATLAB) { 22935042aa92SStefano Zampini char name[64]; 22945042aa92SStefano Zampini PetscMPIInt size, rank; 22955042aa92SStefano Zampini 22965042aa92SStefano Zampini PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 22975042aa92SStefano Zampini PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 22985042aa92SStefano Zampini if (size > 1) PetscCall(PetscSNPrintf(name, sizeof(name), "lmat_%d", rank)); 22995042aa92SStefano Zampini else PetscCall(PetscSNPrintf(name, sizeof(name), "lmat")); 23005042aa92SStefano Zampini PetscCall(PetscObjectSetName((PetscObject)a->A, name)); 23015042aa92SStefano Zampini } 23025042aa92SStefano Zampini 23035042aa92SStefano Zampini /* Dump the local matrices */ 23045042aa92SStefano Zampini if (isbinary) { /* ViewerGetSubViewer does not work in parallel */ 23055042aa92SStefano Zampini PetscBool isaij; 23065042aa92SStefano Zampini PetscInt nr, nc; 23075042aa92SStefano Zampini Mat lA, B; 23085042aa92SStefano Zampini Mat_MPIAIJ *b; 23095042aa92SStefano Zampini 23105042aa92SStefano Zampini /* We create a temporary MPIAIJ matrix that stores the unassembled operator */ 23115042aa92SStefano Zampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)a->A, MATAIJ, &isaij)); 23125042aa92SStefano Zampini if (!isaij) PetscCall(MatConvert(a->A, MATSEQAIJ, MAT_INITIAL_MATRIX, &lA)); 23135042aa92SStefano Zampini else { 23145042aa92SStefano Zampini PetscCall(PetscObjectReference((PetscObject)a->A)); 23155042aa92SStefano Zampini lA = a->A; 23165042aa92SStefano Zampini } 23175042aa92SStefano Zampini PetscCall(MatCreate(PetscObjectComm((PetscObject)viewer), &B)); 23185042aa92SStefano Zampini PetscCall(MatSetType(B, MATMPIAIJ)); 23195042aa92SStefano Zampini PetscCall(MatGetSize(lA, &nr, &nc)); 23205042aa92SStefano Zampini PetscCall(MatSetSizes(B, nr, nc, PETSC_DECIDE, PETSC_DECIDE)); 23215042aa92SStefano Zampini PetscCall(MatMPIAIJSetPreallocation(B, 0, NULL, 0, NULL)); 23225042aa92SStefano Zampini 23235042aa92SStefano Zampini b = (Mat_MPIAIJ *)B->data; 23245042aa92SStefano Zampini PetscCall(MatDestroy(&b->A)); 23255042aa92SStefano Zampini b->A = lA; 23265042aa92SStefano Zampini 23275042aa92SStefano Zampini PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 23285042aa92SStefano Zampini PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 23295042aa92SStefano Zampini PetscCall(MatView(B, viewer)); 23305042aa92SStefano Zampini PetscCall(MatDestroy(&B)); 23315042aa92SStefano Zampini } else { 23329566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 23339566063dSJacob Faibussowitsch PetscCall(MatView(a->A, sviewer)); 23349566063dSJacob Faibussowitsch PetscCall(PetscViewerRestoreSubViewer(viewer, PETSC_COMM_SELF, &sviewer)); 23355042aa92SStefano Zampini } 23365042aa92SStefano Zampini 23375042aa92SStefano Zampini /* with ASCII, we dump the l2gmaps at the end */ 23385042aa92SStefano Zampini if (viewl2g) { 23395042aa92SStefano Zampini if (format == PETSC_VIEWER_ASCII_MATLAB) { 23405042aa92SStefano Zampini PetscCall(PetscObjectSetName((PetscObject)rmap, "row")); 23415042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingView(rmap, viewer)); 23425042aa92SStefano Zampini PetscCall(PetscObjectSetName((PetscObject)cmap, "col")); 23435042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingView(cmap, viewer)); 23445042aa92SStefano Zampini } else { 23455042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingView(rmap, viewer)); 23465042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingView(cmap, viewer)); 23475042aa92SStefano Zampini } 23485042aa92SStefano Zampini } 23495042aa92SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 23505042aa92SStefano Zampini } 23515042aa92SStefano Zampini 2352a3ef7f04SStefano Zampini static PetscErrorCode ISLocalToGlobalMappingHasRepeatedLocal_Private(ISLocalToGlobalMapping map, PetscBool *has) 2353a3ef7f04SStefano Zampini { 2354a3ef7f04SStefano Zampini const PetscInt *idxs; 2355a3ef7f04SStefano Zampini PetscHSetI ht; 2356a3ef7f04SStefano Zampini PetscInt n, bs; 2357a3ef7f04SStefano Zampini 2358a3ef7f04SStefano Zampini PetscFunctionBegin; 2359a3ef7f04SStefano Zampini PetscCall(ISLocalToGlobalMappingGetSize(map, &n)); 2360a3ef7f04SStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockSize(map, &bs)); 2361a3ef7f04SStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockIndices(map, &idxs)); 2362a3ef7f04SStefano Zampini PetscCall(PetscHSetICreate(&ht)); 2363a3ef7f04SStefano Zampini *has = PETSC_FALSE; 2364a3ef7f04SStefano Zampini for (PetscInt i = 0; i < n / bs; i++) { 2365a3ef7f04SStefano Zampini PetscBool missing = PETSC_TRUE; 2366a3ef7f04SStefano Zampini if (idxs[i] < 0) continue; 2367a3ef7f04SStefano Zampini PetscCall(PetscHSetIQueryAdd(ht, idxs[i], &missing)); 2368a3ef7f04SStefano Zampini if (!missing) { 2369a3ef7f04SStefano Zampini *has = PETSC_TRUE; 2370a3ef7f04SStefano Zampini break; 2371a3ef7f04SStefano Zampini } 2372a3ef7f04SStefano Zampini } 2373a3ef7f04SStefano Zampini PetscCall(PetscHSetIDestroy(&ht)); 2374a3ef7f04SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2375a3ef7f04SStefano Zampini } 2376a3ef7f04SStefano Zampini 23775042aa92SStefano Zampini static PetscErrorCode MatLoad_IS(Mat A, PetscViewer viewer) 23785042aa92SStefano Zampini { 23795042aa92SStefano Zampini ISLocalToGlobalMapping rmap, cmap; 23805042aa92SStefano Zampini MPI_Comm comm = PetscObjectComm((PetscObject)A); 23815042aa92SStefano Zampini PetscBool isbinary, samel, allow, isbaij; 23825042aa92SStefano Zampini PetscInt tr[6], M, N, nr, nc, Asize, isn; 23835042aa92SStefano Zampini const PetscInt *idx; 23845042aa92SStefano Zampini PetscMPIInt size; 23855042aa92SStefano Zampini char lmattype[64]; 23865042aa92SStefano Zampini Mat dA, lA; 23875042aa92SStefano Zampini IS is; 23885042aa92SStefano Zampini 23895042aa92SStefano Zampini PetscFunctionBegin; 23905042aa92SStefano Zampini PetscCheckSameComm(A, 1, viewer, 2); 23915042aa92SStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 23925042aa92SStefano Zampini PetscCheck(isbinary, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Invalid viewer of type %s", ((PetscObject)viewer)->type_name); 23935042aa92SStefano Zampini 23945042aa92SStefano Zampini PetscCall(PetscViewerBinaryRead(viewer, tr, PETSC_STATIC_ARRAY_LENGTH(tr), NULL, PETSC_INT)); 23955042aa92SStefano Zampini PetscCheck(tr[0] == MAT_FILE_CLASSID, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a matrix next in file"); 23965042aa92SStefano Zampini PetscCheck(tr[1] >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a IS matrix next in file"); 23975042aa92SStefano Zampini PetscCheck(tr[2] >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a IS matrix next in file"); 23985042aa92SStefano Zampini PetscCheck(tr[3] < 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a IS matrix next in file"); 23995042aa92SStefano Zampini PetscCheck(tr[4] == 0 || tr[4] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a IS matrix next in file"); 24005042aa92SStefano Zampini PetscCheck(tr[5] == 0 || tr[5] == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Not a IS matrix next in file"); 24015042aa92SStefano Zampini M = tr[1]; 24025042aa92SStefano Zampini N = tr[2]; 24035042aa92SStefano Zampini Asize = -tr[3]; 24045042aa92SStefano Zampini samel = (PetscBool)tr[4]; 24055042aa92SStefano Zampini allow = (PetscBool)tr[5]; 24065042aa92SStefano Zampini PetscCall(PetscViewerBinaryRead(viewer, lmattype, sizeof(lmattype), NULL, PETSC_CHAR)); 24075042aa92SStefano Zampini 24085042aa92SStefano Zampini /* if we are loading from a larger set of processes, allow repeated entries */ 24095042aa92SStefano Zampini PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 24105042aa92SStefano Zampini if (Asize > size) allow = PETSC_TRUE; 24115042aa92SStefano Zampini 24125042aa92SStefano Zampini /* set global sizes if not set already */ 24135042aa92SStefano Zampini if (A->rmap->N < 0) A->rmap->N = M; 24145042aa92SStefano Zampini if (A->cmap->N < 0) A->cmap->N = N; 24155042aa92SStefano Zampini PetscCall(PetscLayoutSetUp(A->rmap)); 24165042aa92SStefano Zampini PetscCall(PetscLayoutSetUp(A->cmap)); 24175042aa92SStefano Zampini PetscCheck(M == A->rmap->N, comm, PETSC_ERR_ARG_SIZ, "Matrix rows should be %" PetscInt_FMT ", found %" PetscInt_FMT, M, A->rmap->N); 24185042aa92SStefano Zampini PetscCheck(N == A->cmap->N, comm, PETSC_ERR_ARG_SIZ, "Matrix columns should be %" PetscInt_FMT ", found %" PetscInt_FMT, N, A->cmap->N); 24195042aa92SStefano Zampini 24205042aa92SStefano Zampini /* load l2g maps */ 24215042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingCreate(comm, 0, 0, NULL, PETSC_USE_POINTER, &rmap)); 24225042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingLoad(rmap, viewer)); 24235042aa92SStefano Zampini if (!samel) { 24245042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingCreate(comm, 0, 0, NULL, PETSC_USE_POINTER, &cmap)); 24255042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingLoad(cmap, viewer)); 24265042aa92SStefano Zampini } else { 24275042aa92SStefano Zampini PetscCall(PetscObjectReference((PetscObject)rmap)); 24285042aa92SStefano Zampini cmap = rmap; 24295042aa92SStefano Zampini } 24305042aa92SStefano Zampini 24315042aa92SStefano Zampini /* load sizes of local matrices */ 24325042aa92SStefano Zampini PetscCall(ISCreate(comm, &is)); 24335042aa92SStefano Zampini PetscCall(ISSetType(is, ISGENERAL)); 24345042aa92SStefano Zampini PetscCall(ISLoad(is, viewer)); 24355042aa92SStefano Zampini PetscCall(ISGetLocalSize(is, &isn)); 24365042aa92SStefano Zampini PetscCall(ISGetIndices(is, &idx)); 24375042aa92SStefano Zampini nr = 0; 24385042aa92SStefano Zampini for (PetscInt i = 0; i < isn; i++) nr += idx[i]; 24395042aa92SStefano Zampini PetscCall(ISRestoreIndices(is, &idx)); 24405042aa92SStefano Zampini PetscCall(ISDestroy(&is)); 24415042aa92SStefano Zampini PetscCall(ISCreate(comm, &is)); 24425042aa92SStefano Zampini PetscCall(ISSetType(is, ISGENERAL)); 24435042aa92SStefano Zampini PetscCall(ISLoad(is, viewer)); 24445042aa92SStefano Zampini PetscCall(ISGetLocalSize(is, &isn)); 24455042aa92SStefano Zampini PetscCall(ISGetIndices(is, &idx)); 24465042aa92SStefano Zampini nc = 0; 24475042aa92SStefano Zampini for (PetscInt i = 0; i < isn; i++) nc += idx[i]; 24485042aa92SStefano Zampini PetscCall(ISRestoreIndices(is, &idx)); 24495042aa92SStefano Zampini PetscCall(ISDestroy(&is)); 24505042aa92SStefano Zampini 24515042aa92SStefano Zampini /* now load the unassembled operator */ 24525042aa92SStefano Zampini PetscCall(MatCreate(comm, &dA)); 24535042aa92SStefano Zampini PetscCall(MatSetType(dA, MATMPIAIJ)); 24545042aa92SStefano Zampini PetscCall(MatSetSizes(dA, nr, nc, PETSC_DECIDE, PETSC_DECIDE)); 24555042aa92SStefano Zampini PetscCall(MatLoad(dA, viewer)); 24565042aa92SStefano Zampini PetscCall(MatMPIAIJGetSeqAIJ(dA, &lA, NULL, NULL)); 24575042aa92SStefano Zampini PetscCall(PetscObjectReference((PetscObject)lA)); 24585042aa92SStefano Zampini PetscCall(MatDestroy(&dA)); 24595042aa92SStefano Zampini 24605042aa92SStefano Zampini /* and convert to the desired format */ 24615042aa92SStefano Zampini PetscCall(PetscStrcmpAny(lmattype, &isbaij, MATSBAIJ, MATSEQSBAIJ, "")); 24625042aa92SStefano Zampini if (isbaij) PetscCall(MatSetOption(lA, MAT_SYMMETRIC, PETSC_TRUE)); 24635042aa92SStefano Zampini PetscCall(MatConvert(lA, lmattype, MAT_INPLACE_MATRIX, &lA)); 24645042aa92SStefano Zampini 2465a3ef7f04SStefano Zampini /* check if we actually have repeated entries */ 2466a3ef7f04SStefano Zampini if (allow) { 2467a3ef7f04SStefano Zampini PetscBool rhas, chas, hasrepeated; 2468a3ef7f04SStefano Zampini 2469a3ef7f04SStefano Zampini PetscCall(ISLocalToGlobalMappingHasRepeatedLocal_Private(rmap, &rhas)); 2470a3ef7f04SStefano Zampini if (rmap != cmap) PetscCall(ISLocalToGlobalMappingHasRepeatedLocal_Private(cmap, &chas)); 2471a3ef7f04SStefano Zampini else chas = rhas; 2472a3ef7f04SStefano Zampini hasrepeated = (PetscBool)(rhas || chas); 2473*5440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &hasrepeated, 1, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A))); 2474a3ef7f04SStefano Zampini if (!hasrepeated) allow = PETSC_FALSE; 2475a3ef7f04SStefano Zampini } 2476a3ef7f04SStefano Zampini 24775042aa92SStefano Zampini /* assemble the MATIS object */ 24785042aa92SStefano Zampini PetscCall(MatISSetAllowRepeated(A, allow)); 24795042aa92SStefano Zampini PetscCall(MatSetLocalToGlobalMapping(A, rmap, cmap)); 24805042aa92SStefano Zampini PetscCall(MatISSetLocalMat(A, lA)); 24815042aa92SStefano Zampini PetscCall(MatDestroy(&lA)); 24825042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingDestroy(&rmap)); 24835042aa92SStefano Zampini PetscCall(ISLocalToGlobalMappingDestroy(&cmap)); 24845042aa92SStefano Zampini PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 24855042aa92SStefano Zampini PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 24863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2487b4319ba4SBarry Smith } 2488b4319ba4SBarry Smith 2489d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatInvertBlockDiagonal_IS(Mat mat, const PetscScalar **values) 2490d71ae5a4SJacob Faibussowitsch { 2491b89f26deSStefano Zampini Mat_IS *is = (Mat_IS *)mat->data; 2492b89f26deSStefano Zampini MPI_Datatype nodeType; 2493b89f26deSStefano Zampini const PetscScalar *lv; 2494b89f26deSStefano Zampini PetscInt bs; 2495835f2295SStefano Zampini PetscMPIInt mbs; 2496b89f26deSStefano Zampini 2497b89f26deSStefano Zampini PetscFunctionBegin; 24989566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(mat, &bs)); 24999566063dSJacob Faibussowitsch PetscCall(MatSetBlockSize(is->A, bs)); 25009566063dSJacob Faibussowitsch PetscCall(MatInvertBlockDiagonal(is->A, &lv)); 250148a46eb9SPierre Jolivet if (!is->bdiag) PetscCall(PetscMalloc1(bs * mat->rmap->n, &is->bdiag)); 2502835f2295SStefano Zampini PetscCall(PetscMPIIntCast(bs, &mbs)); 2503835f2295SStefano Zampini PetscCallMPI(MPI_Type_contiguous(mbs, MPIU_SCALAR, &nodeType)); 25049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&nodeType)); 25059566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(is->sf, nodeType, lv, is->bdiag, MPI_REPLACE)); 25069566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(is->sf, nodeType, lv, is->bdiag, MPI_REPLACE)); 25079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&nodeType)); 2508b89f26deSStefano Zampini if (values) *values = is->bdiag; 25093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2510b89f26deSStefano Zampini } 2511b89f26deSStefano Zampini 2512d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISSetUpScatters_Private(Mat A) 2513d71ae5a4SJacob Faibussowitsch { 2514e176bc59SStefano Zampini Vec cglobal, rglobal; 25158546b261SStefano Zampini IS from; 25168546b261SStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 2517b89f26deSStefano Zampini PetscScalar sum; 25188546b261SStefano Zampini const PetscInt *garray; 25198546b261SStefano Zampini PetscInt nr, rbs, nc, cbs; 2520e432b41dSStefano Zampini VecType rtype; 2521b4319ba4SBarry Smith 2522b4319ba4SBarry Smith PetscFunctionBegin; 25239566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->rmapping, &nr)); 25249566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->rmapping, &rbs)); 25259566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->cmapping, &nc)); 25269566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->cmapping, &cbs)); 25279566063dSJacob Faibussowitsch PetscCall(VecDestroy(&is->x)); 25289566063dSJacob Faibussowitsch PetscCall(VecDestroy(&is->y)); 25299566063dSJacob Faibussowitsch PetscCall(VecDestroy(&is->counter)); 25309566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&is->rctx)); 25319566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&is->cctx)); 25329566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(is->A, &is->x, &is->y)); 25339566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->y, PETSC_TRUE)); 25349566063dSJacob Faibussowitsch PetscCall(VecGetRootType_Private(is->y, &rtype)); 25359566063dSJacob Faibussowitsch PetscCall(PetscFree(A->defaultvectype)); 25369566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(rtype, &A->defaultvectype)); 25379566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(A, &cglobal, &rglobal)); 25389566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(rglobal, PETSC_TRUE)); 25399566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->rmapping, &garray)); 25409566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), rbs, nr / rbs, garray, PETSC_USE_POINTER, &from)); 25419566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(rglobal, from, is->y, NULL, &is->rctx)); 25429566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->rmapping, &garray)); 25439566063dSJacob Faibussowitsch PetscCall(ISDestroy(&from)); 2544e432b41dSStefano Zampini if (is->rmapping != is->cmapping) { 25459566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->cmapping, &garray)); 25469566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), cbs, nc / cbs, garray, PETSC_USE_POINTER, &from)); 25479566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(cglobal, from, is->x, NULL, &is->cctx)); 25489566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->cmapping, &garray)); 25499566063dSJacob Faibussowitsch PetscCall(ISDestroy(&from)); 25508546b261SStefano Zampini } else { 25519566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->rctx)); 25528546b261SStefano Zampini is->cctx = is->rctx; 25538546b261SStefano Zampini } 25549566063dSJacob Faibussowitsch PetscCall(VecDestroy(&cglobal)); 2555b89f26deSStefano Zampini 25568546b261SStefano Zampini /* interface counter vector (local) */ 25579566063dSJacob Faibussowitsch PetscCall(VecDuplicate(is->y, &is->counter)); 25589566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->counter, PETSC_TRUE)); 25599566063dSJacob Faibussowitsch PetscCall(VecSet(is->y, 1.)); 25609566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, is->y, rglobal, ADD_VALUES, SCATTER_REVERSE)); 25619566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, is->y, rglobal, ADD_VALUES, SCATTER_REVERSE)); 25629566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, rglobal, is->counter, INSERT_VALUES, SCATTER_FORWARD)); 25639566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, rglobal, is->counter, INSERT_VALUES, SCATTER_FORWARD)); 25649566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->y, PETSC_FALSE)); 25659566063dSJacob Faibussowitsch PetscCall(VecBindToCPU(is->counter, PETSC_FALSE)); 2566b89f26deSStefano Zampini 2567b89f26deSStefano Zampini /* special functions for block-diagonal matrices */ 25689566063dSJacob Faibussowitsch PetscCall(VecSum(rglobal, &sum)); 2569b89f26deSStefano Zampini A->ops->invertblockdiagonal = NULL; 2570e432b41dSStefano Zampini if ((PetscInt)(PetscRealPart(sum)) == A->rmap->N && A->rmap->N == A->cmap->N && is->rmapping == is->cmapping) A->ops->invertblockdiagonal = MatInvertBlockDiagonal_IS; 25719566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rglobal)); 2572b0cc1f67SStefano Zampini 2573b0cc1f67SStefano Zampini /* setup SF for general purpose shared indices based communications */ 25749566063dSJacob Faibussowitsch PetscCall(MatISSetUpSF_IS(A)); 25753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 25768546b261SStefano Zampini } 25778546b261SStefano Zampini 2578d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISFilterL2GMap(Mat A, ISLocalToGlobalMapping map, ISLocalToGlobalMapping *nmap, ISLocalToGlobalMapping *lmap) 2579d71ae5a4SJacob Faibussowitsch { 25804f58015eSStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 2581e432b41dSStefano Zampini IS is; 2582e432b41dSStefano Zampini ISLocalToGlobalMappingType l2gtype; 2583e432b41dSStefano Zampini const PetscInt *idxs; 2584e432b41dSStefano Zampini PetscHSetI ht; 2585e432b41dSStefano Zampini PetscInt *nidxs; 2586e432b41dSStefano Zampini PetscInt i, n, bs, c; 2587e432b41dSStefano Zampini PetscBool flg[] = {PETSC_FALSE, PETSC_FALSE}; 2588e432b41dSStefano Zampini 2589e432b41dSStefano Zampini PetscFunctionBegin; 25909566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(map, &n)); 25919566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(map, &bs)); 25929566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(map, &idxs)); 25939566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&ht)); 25949566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n / bs, &nidxs)); 2595e432b41dSStefano Zampini for (i = 0, c = 0; i < n / bs; i++) { 25964f58015eSStefano Zampini PetscBool missing = PETSC_TRUE; 25979371c9d4SSatish Balay if (idxs[i] < 0) { 25989371c9d4SSatish Balay flg[0] = PETSC_TRUE; 25999371c9d4SSatish Balay continue; 26009371c9d4SSatish Balay } 26014f58015eSStefano Zampini if (!matis->allow_repeated) PetscCall(PetscHSetIQueryAdd(ht, idxs[i], &missing)); 2602e432b41dSStefano Zampini if (!missing) flg[1] = PETSC_TRUE; 2603e432b41dSStefano Zampini else nidxs[c++] = idxs[i]; 2604e432b41dSStefano Zampini } 26059566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&ht)); 2606*5440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, flg, 2, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A))); 2607e432b41dSStefano Zampini if (!flg[0] && !flg[1]) { /* Entries are all non negative and unique */ 2608e432b41dSStefano Zampini *nmap = NULL; 2609e432b41dSStefano Zampini *lmap = NULL; 26109566063dSJacob Faibussowitsch PetscCall(PetscFree(nidxs)); 26119566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(map, &idxs)); 26123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2613e432b41dSStefano Zampini } 2614e432b41dSStefano Zampini 26154f58015eSStefano Zampini /* New l2g map without negative indices (and repeated indices if not allowed) */ 26169566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PetscObjectComm((PetscObject)A), bs, c, nidxs, PETSC_USE_POINTER, &is)); 26179566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, nmap)); 26189566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 26199566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetType(map, &l2gtype)); 26209566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingSetType(*nmap, l2gtype)); 2621e432b41dSStefano Zampini 26224f58015eSStefano Zampini /* New local l2g map for repeated indices if not allowed */ 26239566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(*nmap, IS_GTOLM_MASK, n / bs, idxs, NULL, nidxs)); 26249566063dSJacob Faibussowitsch PetscCall(ISCreateBlock(PETSC_COMM_SELF, bs, n / bs, nidxs, PETSC_USE_POINTER, &is)); 26259566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, lmap)); 26269566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 26279566063dSJacob Faibussowitsch PetscCall(PetscFree(nidxs)); 26289566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(map, &idxs)); 26293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2630e432b41dSStefano Zampini } 2631e432b41dSStefano Zampini 2632d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2633d71ae5a4SJacob Faibussowitsch { 26348546b261SStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 2635e432b41dSStefano Zampini ISLocalToGlobalMapping localrmapping = NULL, localcmapping = NULL; 2636e432b41dSStefano Zampini PetscInt nr, rbs, nc, cbs; 26374f58015eSStefano Zampini PetscBool cong, freem[] = {PETSC_FALSE, PETSC_FALSE}; 26388546b261SStefano Zampini 26398546b261SStefano Zampini PetscFunctionBegin; 2640fc989267SStefano Zampini if (rmapping) PetscCheckSameComm(A, 1, rmapping, 2); 2641fc989267SStefano Zampini if (cmapping) PetscCheckSameComm(A, 1, cmapping, 3); 2642e432b41dSStefano Zampini 26439566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&is->rmapping)); 26449566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&is->cmapping)); 26459566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 26469566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 26479566063dSJacob Faibussowitsch PetscCall(MatHasCongruentLayouts(A, &cong)); 2648e432b41dSStefano Zampini 2649fc989267SStefano Zampini /* If NULL, local space matches global space */ 2650fc989267SStefano Zampini if (!rmapping) { 2651fc989267SStefano Zampini IS is; 2652fc989267SStefano Zampini 26539566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), A->rmap->N, 0, 1, &is)); 26549566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rmapping)); 265558b7e2c1SStefano Zampini PetscCall(ISLocalToGlobalMappingSetBlockSize(rmapping, A->rmap->bs)); 26569566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2657e432b41dSStefano Zampini freem[0] = PETSC_TRUE; 2658e432b41dSStefano Zampini if (!cmapping && cong && A->rmap->bs == A->cmap->bs) cmapping = rmapping; 2659e432b41dSStefano Zampini } else if (!is->islocalref) { /* check if the l2g map has negative or repeated entries */ 26609566063dSJacob Faibussowitsch PetscCall(MatISFilterL2GMap(A, rmapping, &is->rmapping, &localrmapping)); 2661e432b41dSStefano Zampini if (rmapping == cmapping) { 26629566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->rmapping)); 2663e432b41dSStefano Zampini is->cmapping = is->rmapping; 26649566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)localrmapping)); 2665e432b41dSStefano Zampini localcmapping = localrmapping; 2666fc989267SStefano Zampini } 2667fc989267SStefano Zampini } 2668fc989267SStefano Zampini if (!cmapping) { 2669fc989267SStefano Zampini IS is; 2670fc989267SStefano Zampini 26719566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PetscObjectComm((PetscObject)A), A->cmap->N, 0, 1, &is)); 26729566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cmapping)); 267358b7e2c1SStefano Zampini PetscCall(ISLocalToGlobalMappingSetBlockSize(cmapping, A->cmap->bs)); 26749566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2675e432b41dSStefano Zampini freem[1] = PETSC_TRUE; 2676e432b41dSStefano Zampini } else if (cmapping != rmapping && !is->islocalref) { /* check if the l2g map has negative or repeated entries */ 26779566063dSJacob Faibussowitsch PetscCall(MatISFilterL2GMap(A, cmapping, &is->cmapping, &localcmapping)); 2678e432b41dSStefano Zampini } 2679e432b41dSStefano Zampini if (!is->rmapping) { 26809566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)rmapping)); 2681e432b41dSStefano Zampini is->rmapping = rmapping; 2682e432b41dSStefano Zampini } 2683e432b41dSStefano Zampini if (!is->cmapping) { 26849566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)cmapping)); 2685e432b41dSStefano Zampini is->cmapping = cmapping; 2686fc989267SStefano Zampini } 2687fc989267SStefano Zampini 2688fc989267SStefano Zampini /* Clean up */ 26894f58015eSStefano Zampini is->lnnzstate = 0; 26904f58015eSStefano Zampini PetscCall(MatDestroy(&is->dA)); 26914f58015eSStefano Zampini PetscCall(MatDestroy(&is->assembledA)); 26929566063dSJacob Faibussowitsch PetscCall(MatDestroy(&is->A)); 2693872cf891SStefano Zampini if (is->csf != is->sf) { 26949566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&is->csf)); 26959566063dSJacob Faibussowitsch PetscCall(PetscFree2(is->csf_rootdata, is->csf_leafdata)); 2696f03112d0SStefano Zampini } else is->csf = NULL; 26979566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&is->sf)); 26989566063dSJacob Faibussowitsch PetscCall(PetscFree2(is->sf_rootdata, is->sf_leafdata)); 26999566063dSJacob Faibussowitsch PetscCall(PetscFree(is->bdiag)); 27003bbff08aSStefano Zampini 2701fc989267SStefano Zampini /* check if the two mappings are actually the same for square matrices since MATIS has some optimization for this case 2702fc989267SStefano Zampini (DOLFIN passes 2 different objects) */ 27039566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->rmapping, &nr)); 27049566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->rmapping, &rbs)); 27059566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(is->cmapping, &nc)); 27069566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockSize(is->cmapping, &cbs)); 2707e432b41dSStefano Zampini if (is->rmapping != is->cmapping && cong) { 2708e432b41dSStefano Zampini PetscBool same = PETSC_FALSE; 27096625354bSStefano Zampini if (nr == nc && cbs == rbs) { 27106625354bSStefano Zampini const PetscInt *idxs1, *idxs2; 27116625354bSStefano Zampini 27129566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->rmapping, &idxs1)); 27139566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetBlockIndices(is->cmapping, &idxs2)); 27149566063dSJacob Faibussowitsch PetscCall(PetscArraycmp(idxs1, idxs2, nr / rbs, &same)); 27159566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->rmapping, &idxs1)); 27169566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreBlockIndices(is->cmapping, &idxs2)); 27176625354bSStefano Zampini } 2718*5440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &same, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 2719e432b41dSStefano Zampini if (same) { 27209566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&is->cmapping)); 27219566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->rmapping)); 2722e432b41dSStefano Zampini is->cmapping = is->rmapping; 2723e432b41dSStefano Zampini } 27246625354bSStefano Zampini } 27259566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(A->rmap, rbs)); 27269566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(A->cmap, cbs)); 2727e432b41dSStefano Zampini /* Pass the user defined maps to the layout */ 27289566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetISLocalToGlobalMapping(A->rmap, rmapping)); 27299566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetISLocalToGlobalMapping(A->cmap, cmapping)); 27309566063dSJacob Faibussowitsch if (freem[0]) PetscCall(ISLocalToGlobalMappingDestroy(&rmapping)); 27319566063dSJacob Faibussowitsch if (freem[1]) PetscCall(ISLocalToGlobalMappingDestroy(&cmapping)); 27326625354bSStefano Zampini 273339b6f3f9SStefano Zampini if (!is->islocalref) { 27346625354bSStefano Zampini /* Create the local matrix A */ 27359566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_SELF, &is->A)); 27369566063dSJacob Faibussowitsch PetscCall(MatSetType(is->A, is->lmattype)); 27379566063dSJacob Faibussowitsch PetscCall(MatSetSizes(is->A, nr, nc, nr, nc)); 27389566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(is->A, rbs, cbs)); 27399566063dSJacob Faibussowitsch PetscCall(MatSetOptionsPrefix(is->A, "is_")); 27409566063dSJacob Faibussowitsch PetscCall(MatAppendOptionsPrefix(is->A, ((PetscObject)A)->prefix)); 27419566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(is->A->rmap)); 27429566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(is->A->cmap)); 27439566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(is->A, localrmapping, localcmapping)); 27449566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&localrmapping)); 27459566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&localcmapping)); 2746fc989267SStefano Zampini /* setup scatters and local vectors for MatMult */ 274739b6f3f9SStefano Zampini PetscCall(MatISSetUpScatters_Private(A)); 274839b6f3f9SStefano Zampini } 2749fc989267SStefano Zampini A->preallocated = PETSC_TRUE; 27503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2751fc989267SStefano Zampini } 2752fc989267SStefano Zampini 2753d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetUp_IS(Mat A) 2754d71ae5a4SJacob Faibussowitsch { 275529f134acSStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 2756fc989267SStefano Zampini ISLocalToGlobalMapping rmap, cmap; 2757fc989267SStefano Zampini 2758fc989267SStefano Zampini PetscFunctionBegin; 275929f134acSStefano Zampini if (!is->sf) { 27609566063dSJacob Faibussowitsch PetscCall(MatGetLocalToGlobalMapping(A, &rmap, &cmap)); 276129f134acSStefano Zampini PetscCall(MatSetLocalToGlobalMapping(A, rmap, cmap)); 276229f134acSStefano Zampini } 27633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2764b4319ba4SBarry Smith } 2765b4319ba4SBarry Smith 2766d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) 2767d71ae5a4SJacob Faibussowitsch { 27682e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS *)mat->data; 2769f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION], cols_l[MATIS_MAX_ENTRIES_INSERTION]; 27702e74eeadSLisandro Dalcin 27712e74eeadSLisandro Dalcin PetscFunctionBegin; 27729566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(is->rmapping, IS_GTOLM_MASK, m, rows, &m, rows_l)); 2773e432b41dSStefano Zampini if (m != n || rows != cols || is->cmapping != is->rmapping) { 27749566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApply(is->cmapping, IS_GTOLM_MASK, n, cols, &n, cols_l)); 27759566063dSJacob Faibussowitsch PetscCall(MatSetValues(is->A, m, rows_l, n, cols_l, values, addv)); 2776e432b41dSStefano Zampini } else { 27779566063dSJacob Faibussowitsch PetscCall(MatSetValues(is->A, m, rows_l, m, rows_l, values, addv)); 2778e432b41dSStefano Zampini } 27793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 27802e74eeadSLisandro Dalcin } 27812e74eeadSLisandro Dalcin 2782d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) 2783d71ae5a4SJacob Faibussowitsch { 278497563a80SStefano Zampini Mat_IS *is = (Mat_IS *)mat->data; 2785f26d0771SStefano Zampini PetscInt rows_l[MATIS_MAX_ENTRIES_INSERTION], cols_l[MATIS_MAX_ENTRIES_INSERTION]; 278697563a80SStefano Zampini 278797563a80SStefano Zampini PetscFunctionBegin; 27889566063dSJacob Faibussowitsch PetscCall(ISGlobalToLocalMappingApplyBlock(is->rmapping, IS_GTOLM_MASK, m, rows, &m, rows_l)); 2789e432b41dSStefano Zampini if (m != n || rows != cols || is->cmapping != is->rmapping) { 279084a95373SStefano Zampini PetscCall(ISGlobalToLocalMappingApplyBlock(is->cmapping, IS_GTOLM_MASK, n, cols, &n, cols_l)); 27919566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked(is->A, m, rows_l, n, cols_l, values, addv)); 2792e432b41dSStefano Zampini } else { 279384a95373SStefano Zampini PetscCall(MatSetValuesBlocked(is->A, m, rows_l, m, rows_l, values, addv)); 2794e432b41dSStefano Zampini } 27953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 279697563a80SStefano Zampini } 279797563a80SStefano Zampini 2798d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesLocal_IS(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) 2799d71ae5a4SJacob Faibussowitsch { 2800b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)A->data; 2801b4319ba4SBarry Smith 2802b4319ba4SBarry Smith PetscFunctionBegin; 2803e432b41dSStefano Zampini if (is->A->rmap->mapping || is->A->cmap->mapping) { 28049566063dSJacob Faibussowitsch PetscCall(MatSetValuesLocal(is->A, m, rows, n, cols, values, addv)); 2805872cf891SStefano Zampini } else { 28069566063dSJacob Faibussowitsch PetscCall(MatSetValues(is->A, m, rows, n, cols, values, addv)); 2807872cf891SStefano Zampini } 28083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2809b4319ba4SBarry Smith } 2810b4319ba4SBarry Smith 2811d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A, PetscInt m, const PetscInt *rows, PetscInt n, const PetscInt *cols, const PetscScalar *values, InsertMode addv) 2812d71ae5a4SJacob Faibussowitsch { 2813f0006bf2SLisandro Dalcin Mat_IS *is = (Mat_IS *)A->data; 2814f0006bf2SLisandro Dalcin 2815f0006bf2SLisandro Dalcin PetscFunctionBegin; 2816e432b41dSStefano Zampini if (is->A->rmap->mapping || is->A->cmap->mapping) { 28179566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlockedLocal(is->A, m, rows, n, cols, values, addv)); 2818b4f971dfSStefano Zampini } else { 28199566063dSJacob Faibussowitsch PetscCall(MatSetValuesBlocked(is->A, m, rows, n, cols, values, addv)); 2820b4f971dfSStefano Zampini } 28213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2822f0006bf2SLisandro Dalcin } 2823f0006bf2SLisandro Dalcin 2824d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, PetscBool columns) 2825d71ae5a4SJacob Faibussowitsch { 2826f0ae7da4SStefano Zampini Mat_IS *is = (Mat_IS *)A->data; 2827f0ae7da4SStefano Zampini 2828f0ae7da4SStefano Zampini PetscFunctionBegin; 2829f0ae7da4SStefano Zampini if (!n) { 2830f0ae7da4SStefano Zampini is->pure_neumann = PETSC_TRUE; 2831f0ae7da4SStefano Zampini } else { 2832f0ae7da4SStefano Zampini PetscInt i; 2833f0ae7da4SStefano Zampini is->pure_neumann = PETSC_FALSE; 2834f0ae7da4SStefano Zampini 2835f0ae7da4SStefano Zampini if (columns) { 28369566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns(is->A, n, rows, diag, NULL, NULL)); 2837f0ae7da4SStefano Zampini } else { 28389566063dSJacob Faibussowitsch PetscCall(MatZeroRows(is->A, n, rows, diag, NULL, NULL)); 2839f0ae7da4SStefano Zampini } 2840f0ae7da4SStefano Zampini if (diag != 0.) { 2841f0ae7da4SStefano Zampini const PetscScalar *array; 28429566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(is->counter, &array)); 284348a46eb9SPierre Jolivet for (i = 0; i < n; i++) PetscCall(MatSetValue(is->A, rows[i], rows[i], diag / (array[rows[i]]), INSERT_VALUES)); 28449566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(is->counter, &array)); 2845f0ae7da4SStefano Zampini } 28469566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(is->A, MAT_FINAL_ASSEMBLY)); 28479566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(is->A, MAT_FINAL_ASSEMBLY)); 2848f0ae7da4SStefano Zampini } 28493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2850f0ae7da4SStefano Zampini } 2851f0ae7da4SStefano Zampini 2852d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, Vec x, Vec b, PetscBool columns) 2853d71ae5a4SJacob Faibussowitsch { 28546e520ac8SStefano Zampini Mat_IS *matis = (Mat_IS *)A->data; 28556e520ac8SStefano Zampini PetscInt nr, nl, len, i; 28566e520ac8SStefano Zampini PetscInt *lrows; 28572e74eeadSLisandro Dalcin 28582e74eeadSLisandro Dalcin PetscFunctionBegin; 2859cf9c20a2SJed Brown if (PetscUnlikelyDebug(columns || diag != 0. || (x && b))) { 2860f0ae7da4SStefano Zampini PetscBool cong; 286126b0207aSStefano Zampini 28629566063dSJacob Faibussowitsch PetscCall(PetscLayoutCompare(A->rmap, A->cmap, &cong)); 286326b0207aSStefano Zampini cong = (PetscBool)(cong && matis->sf == matis->csf); 286408401ef6SPierre 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"); 2865aed4548fSBarry 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"); 2866aed4548fSBarry 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"); 2867f0ae7da4SStefano Zampini } 28686e520ac8SStefano Zampini /* get locally owned rows */ 28699566063dSJacob Faibussowitsch PetscCall(PetscLayoutMapLocal(A->rmap, n, rows, &len, &lrows, NULL)); 2870dd8e379bSPierre Jolivet /* fix right-hand side if needed */ 28716e520ac8SStefano Zampini if (x && b) { 28726e520ac8SStefano Zampini const PetscScalar *xx; 28736e520ac8SStefano Zampini PetscScalar *bb; 28746e520ac8SStefano Zampini 28759566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &xx)); 28769566063dSJacob Faibussowitsch PetscCall(VecGetArray(b, &bb)); 28776e520ac8SStefano Zampini for (i = 0; i < len; ++i) bb[lrows[i]] = diag * xx[lrows[i]]; 28789566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &xx)); 28799566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(b, &bb)); 28802e74eeadSLisandro Dalcin } 28816e520ac8SStefano Zampini /* get rows associated to the local matrices */ 28829566063dSJacob Faibussowitsch PetscCall(MatGetSize(matis->A, &nl, NULL)); 28839566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_leafdata, nl)); 28849566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(matis->sf_rootdata, A->rmap->n)); 28856e520ac8SStefano Zampini for (i = 0; i < len; i++) matis->sf_rootdata[lrows[i]] = 1; 28869566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 28879566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 28889566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(matis->sf, MPIU_INT, matis->sf_rootdata, matis->sf_leafdata, MPI_REPLACE)); 28899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nl, &lrows)); 28909371c9d4SSatish Balay for (i = 0, nr = 0; i < nl; i++) 28919371c9d4SSatish Balay if (matis->sf_leafdata[i]) lrows[nr++] = i; 28929566063dSJacob Faibussowitsch PetscCall(MatISZeroRowsColumnsLocal_Private(A, nr, lrows, diag, columns)); 28939566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 2894d0dbe9f7SStefano Zampini PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 2895d0dbe9f7SStefano Zampini PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 28963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 28972e74eeadSLisandro Dalcin } 28982e74eeadSLisandro Dalcin 2899d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_IS(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 2900d71ae5a4SJacob Faibussowitsch { 2901b4319ba4SBarry Smith PetscFunctionBegin; 29029566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns_Private_IS(A, n, rows, diag, x, b, PETSC_FALSE)); 29033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2904f0ae7da4SStefano Zampini } 29052205254eSKarl Rupp 2906d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_IS(Mat A, PetscInt n, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 2907d71ae5a4SJacob Faibussowitsch { 2908f0ae7da4SStefano Zampini PetscFunctionBegin; 29099566063dSJacob Faibussowitsch PetscCall(MatZeroRowsColumns_Private_IS(A, n, rows, diag, x, b, PETSC_TRUE)); 29103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2911b4319ba4SBarry Smith } 2912b4319ba4SBarry Smith 2913d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_IS(Mat A, MatAssemblyType type) 2914d71ae5a4SJacob Faibussowitsch { 2915b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)A->data; 2916b4319ba4SBarry Smith 2917b4319ba4SBarry Smith PetscFunctionBegin; 29189566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(is->A, type)); 29193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2920b4319ba4SBarry Smith } 2921b4319ba4SBarry Smith 2922d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_IS(Mat A, MatAssemblyType type) 2923d71ae5a4SJacob Faibussowitsch { 2924b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)A->data; 2925d0dbe9f7SStefano Zampini PetscBool lnnz; 2926b4319ba4SBarry Smith 2927b4319ba4SBarry Smith PetscFunctionBegin; 29289566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(is->A, type)); 2929872cf891SStefano Zampini /* fix for local empty rows/cols */ 2930872cf891SStefano Zampini if (is->locempty && type == MAT_FINAL_ASSEMBLY) { 2931872cf891SStefano Zampini Mat newlA; 2932f03112d0SStefano Zampini ISLocalToGlobalMapping rl2g, cl2g; 2933f03112d0SStefano Zampini IS nzr, nzc; 2934f03112d0SStefano Zampini PetscInt nr, nc, nnzr, nnzc; 2935f03112d0SStefano Zampini PetscBool lnewl2g, newl2g; 2936872cf891SStefano Zampini 29379566063dSJacob Faibussowitsch PetscCall(MatGetSize(is->A, &nr, &nc)); 29389566063dSJacob Faibussowitsch PetscCall(MatFindNonzeroRowsOrCols_Basic(is->A, PETSC_FALSE, PETSC_SMALL, &nzr)); 293948a46eb9SPierre Jolivet if (!nzr) PetscCall(ISCreateStride(PetscObjectComm((PetscObject)is->A), nr, 0, 1, &nzr)); 29409566063dSJacob Faibussowitsch PetscCall(MatFindNonzeroRowsOrCols_Basic(is->A, PETSC_TRUE, PETSC_SMALL, &nzc)); 294148a46eb9SPierre Jolivet if (!nzc) PetscCall(ISCreateStride(PetscObjectComm((PetscObject)is->A), nc, 0, 1, &nzc)); 29429566063dSJacob Faibussowitsch PetscCall(ISGetSize(nzr, &nnzr)); 29439566063dSJacob Faibussowitsch PetscCall(ISGetSize(nzc, &nnzc)); 2944e432b41dSStefano Zampini if (nnzr != nr || nnzc != nc) { /* need new global l2g map */ 2945f03112d0SStefano Zampini lnewl2g = PETSC_TRUE; 2946*5440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&lnewl2g, &newl2g, 1, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A))); 2947f03112d0SStefano Zampini 2948872cf891SStefano Zampini /* extract valid submatrix */ 29499566063dSJacob Faibussowitsch PetscCall(MatCreateSubMatrix(is->A, nzr, nzc, MAT_INITIAL_MATRIX, &newlA)); 2950f03112d0SStefano Zampini } else { /* local matrix fully populated */ 2951f03112d0SStefano Zampini lnewl2g = PETSC_FALSE; 2952*5440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(&lnewl2g, &newl2g, 1, MPI_C_BOOL, MPI_LOR, PetscObjectComm((PetscObject)A))); 29539566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)is->A)); 2954f03112d0SStefano Zampini newlA = is->A; 2955f03112d0SStefano Zampini } 2956e432b41dSStefano Zampini 2957f03112d0SStefano Zampini /* attach new global l2g map if needed */ 2958f03112d0SStefano Zampini if (newl2g) { 2959e432b41dSStefano Zampini IS zr, zc; 2960e432b41dSStefano Zampini const PetscInt *ridxs, *cidxs, *zridxs, *zcidxs; 2961e432b41dSStefano Zampini PetscInt *nidxs, i; 2962f03112d0SStefano Zampini 29639566063dSJacob Faibussowitsch PetscCall(ISComplement(nzr, 0, nr, &zr)); 29649566063dSJacob Faibussowitsch PetscCall(ISComplement(nzc, 0, nc, &zc)); 29659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(PetscMax(nr, nc), &nidxs)); 29669566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(is->rmapping, &ridxs)); 29679566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(is->cmapping, &cidxs)); 29689566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zr, &zridxs)); 29699566063dSJacob Faibussowitsch PetscCall(ISGetIndices(zc, &zcidxs)); 29709566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zr, &nnzr)); 29719566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(zc, &nnzc)); 2972e432b41dSStefano Zampini 29739566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(nidxs, ridxs, nr)); 2974e432b41dSStefano Zampini for (i = 0; i < nnzr; i++) nidxs[zridxs[i]] = -1; 29759566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A), 1, nr, nidxs, PETSC_COPY_VALUES, &rl2g)); 29769566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(nidxs, cidxs, nc)); 2977e432b41dSStefano Zampini for (i = 0; i < nnzc; i++) nidxs[zcidxs[i]] = -1; 29789566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A), 1, nc, nidxs, PETSC_COPY_VALUES, &cl2g)); 2979e432b41dSStefano Zampini 29809566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zr, &zridxs)); 29819566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(zc, &zcidxs)); 29829566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(is->rmapping, &ridxs)); 29839566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(is->cmapping, &cidxs)); 29849566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzr)); 29859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzc)); 29869566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zr)); 29879566063dSJacob Faibussowitsch PetscCall(ISDestroy(&zc)); 29889566063dSJacob Faibussowitsch PetscCall(PetscFree(nidxs)); 29899566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(A, rl2g, cl2g)); 29909566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 29919566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 2992f03112d0SStefano Zampini } 29939566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(A, newlA)); 29949566063dSJacob Faibussowitsch PetscCall(MatDestroy(&newlA)); 29959566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzr)); 29969566063dSJacob Faibussowitsch PetscCall(ISDestroy(&nzc)); 2997872cf891SStefano Zampini is->locempty = PETSC_FALSE; 2998f03112d0SStefano Zampini } 2999d0dbe9f7SStefano Zampini lnnz = (PetscBool)(is->A->nonzerostate == is->lnnzstate); 3000d0dbe9f7SStefano Zampini is->lnnzstate = is->A->nonzerostate; 3001*5440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &lnnz, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)A))); 30024f58015eSStefano Zampini if (!lnnz) A->nonzerostate++; 30033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3004b4319ba4SBarry Smith } 3005b4319ba4SBarry Smith 3006d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISGetLocalMat_IS(Mat mat, Mat *local) 3007d71ae5a4SJacob Faibussowitsch { 3008b4319ba4SBarry Smith Mat_IS *is = (Mat_IS *)mat->data; 3009b4319ba4SBarry Smith 3010b4319ba4SBarry Smith PetscFunctionBegin; 3011b4319ba4SBarry Smith *local = is->A; 30123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3013b4319ba4SBarry Smith } 3014b4319ba4SBarry Smith 3015d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat, Mat *local) 3016d71ae5a4SJacob Faibussowitsch { 30173b3b1effSJed Brown PetscFunctionBegin; 30183b3b1effSJed Brown *local = NULL; 30193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30203b3b1effSJed Brown } 30213b3b1effSJed Brown 3022b4319ba4SBarry Smith /*@ 302311a5261eSBarry Smith MatISGetLocalMat - Gets the local matrix stored inside a `MATIS` matrix. 3024b4319ba4SBarry Smith 30254f58015eSStefano Zampini Not Collective. 30264f58015eSStefano Zampini 3027b4319ba4SBarry Smith Input Parameter: 3028b4319ba4SBarry Smith . mat - the matrix 3029b4319ba4SBarry Smith 3030b4319ba4SBarry Smith Output Parameter: 3031eb82efa4SStefano Zampini . local - the local matrix 3032b4319ba4SBarry Smith 30334f58015eSStefano Zampini Level: intermediate 3034b4319ba4SBarry Smith 3035b4319ba4SBarry Smith Notes: 3036b4319ba4SBarry Smith This can be called if you have precomputed the nonzero structure of the 3037b4319ba4SBarry Smith matrix and want to provide it to the inner matrix object to improve the performance 303811a5261eSBarry Smith of the `MatSetValues()` operation. 3039b4319ba4SBarry Smith 304011a5261eSBarry Smith Call `MatISRestoreLocalMat()` when finished with the local matrix. 304196a6f129SJed Brown 30421cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatISRestoreLocalMat()` 3043b4319ba4SBarry Smith @*/ 3044d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISGetLocalMat(Mat mat, Mat *local) 3045d71ae5a4SJacob Faibussowitsch { 3046b4319ba4SBarry Smith PetscFunctionBegin; 30470700a824SBarry Smith PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 30484f572ea9SToby Isaac PetscAssertPointer(local, 2); 3049cac4c232SBarry Smith PetscUseMethod(mat, "MatISGetLocalMat_C", (Mat, Mat *), (mat, local)); 30503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3051b4319ba4SBarry Smith } 3052b4319ba4SBarry Smith 30533b3b1effSJed Brown /*@ 305411a5261eSBarry Smith MatISRestoreLocalMat - Restores the local matrix obtained with `MatISGetLocalMat()` 30553b3b1effSJed Brown 30564f58015eSStefano Zampini Not Collective. 30574f58015eSStefano Zampini 30582ef1f0ffSBarry Smith Input Parameters: 30592ef1f0ffSBarry Smith + mat - the matrix 30602ef1f0ffSBarry Smith - local - the local matrix 30613b3b1effSJed Brown 30624f58015eSStefano Zampini Level: intermediate 30633b3b1effSJed Brown 30641cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatISGetLocalMat()` 30653b3b1effSJed Brown @*/ 3066d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISRestoreLocalMat(Mat mat, Mat *local) 3067d71ae5a4SJacob Faibussowitsch { 30683b3b1effSJed Brown PetscFunctionBegin; 30693b3b1effSJed Brown PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 30704f572ea9SToby Isaac PetscAssertPointer(local, 2); 3071cac4c232SBarry Smith PetscUseMethod(mat, "MatISRestoreLocalMat_C", (Mat, Mat *), (mat, local)); 30723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30733b3b1effSJed Brown } 30743b3b1effSJed Brown 3075d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISSetLocalMatType_IS(Mat mat, MatType mtype) 3076d71ae5a4SJacob Faibussowitsch { 30778546b261SStefano Zampini Mat_IS *is = (Mat_IS *)mat->data; 30788546b261SStefano Zampini 30798546b261SStefano Zampini PetscFunctionBegin; 30801baa6e33SBarry Smith if (is->A) PetscCall(MatSetType(is->A, mtype)); 30819566063dSJacob Faibussowitsch PetscCall(PetscFree(is->lmattype)); 30829566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(mtype, &is->lmattype)); 30833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30848546b261SStefano Zampini } 30858546b261SStefano Zampini 30865d83a8b1SBarry Smith /*@ 308711a5261eSBarry Smith MatISSetLocalMatType - Specifies the type of local matrix inside the `MATIS` 30888546b261SStefano Zampini 30894f58015eSStefano Zampini Logically Collective. 30904f58015eSStefano Zampini 3091d8d19677SJose E. Roman Input Parameters: 3092a2b725a8SWilliam Gropp + mat - the matrix 3093a2b725a8SWilliam Gropp - mtype - the local matrix type 30948546b261SStefano Zampini 30954f58015eSStefano Zampini Level: intermediate 30968546b261SStefano Zampini 30971cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatSetType()`, `MatType` 30988546b261SStefano Zampini @*/ 3099d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISSetLocalMatType(Mat mat, MatType mtype) 3100d71ae5a4SJacob Faibussowitsch { 31018546b261SStefano Zampini PetscFunctionBegin; 31028546b261SStefano Zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3103cac4c232SBarry Smith PetscUseMethod(mat, "MatISSetLocalMatType_C", (Mat, MatType), (mat, mtype)); 31043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31058546b261SStefano Zampini } 31068546b261SStefano Zampini 3107d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISSetLocalMat_IS(Mat mat, Mat local) 3108d71ae5a4SJacob Faibussowitsch { 31093b03a366Sstefano_zampini Mat_IS *is = (Mat_IS *)mat->data; 31103b03a366Sstefano_zampini PetscInt nrows, ncols, orows, ocols; 31118546b261SStefano Zampini MatType mtype, otype; 31128546b261SStefano Zampini PetscBool sametype = PETSC_TRUE; 31133b03a366Sstefano_zampini 31143b03a366Sstefano_zampini PetscFunctionBegin; 3115e432b41dSStefano Zampini if (is->A && !is->islocalref) { 31169566063dSJacob Faibussowitsch PetscCall(MatGetSize(is->A, &orows, &ocols)); 31179566063dSJacob Faibussowitsch PetscCall(MatGetSize(local, &nrows, &ncols)); 31185042aa92SStefano Zampini PetscCheck(orows == nrows && ocols == ncols, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Local MATIS matrix should be of size %" PetscInt_FMT "x%" PetscInt_FMT " (passed a %" PetscInt_FMT "x%" PetscInt_FMT " matrix)", orows, ocols, nrows, ncols); 31199566063dSJacob Faibussowitsch PetscCall(MatGetType(local, &mtype)); 31209566063dSJacob Faibussowitsch PetscCall(MatGetType(is->A, &otype)); 31219566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, otype, &sametype)); 31224e4c7dbeSStefano Zampini } 31239566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)local)); 31249566063dSJacob Faibussowitsch PetscCall(MatDestroy(&is->A)); 31253b03a366Sstefano_zampini is->A = local; 31269566063dSJacob Faibussowitsch PetscCall(MatGetType(is->A, &mtype)); 31279566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMatType(mat, mtype)); 312848a46eb9SPierre Jolivet if (!sametype && !is->islocalref) PetscCall(MatISSetUpScatters_Private(mat)); 31294f58015eSStefano Zampini is->lnnzstate = 0; 31303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31313b03a366Sstefano_zampini } 31323b03a366Sstefano_zampini 31333b03a366Sstefano_zampini /*@ 313411a5261eSBarry Smith MatISSetLocalMat - Replace the local matrix stored inside a `MATIS` object. 31353b03a366Sstefano_zampini 31364f58015eSStefano Zampini Not Collective 31378546b261SStefano Zampini 3138d8d19677SJose E. Roman Input Parameters: 3139a2b725a8SWilliam Gropp + mat - the matrix 3140a2b725a8SWilliam Gropp - local - the local matrix 31413b03a366Sstefano_zampini 31424f58015eSStefano Zampini Level: intermediate 314311a5261eSBarry Smith 31441cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatISSetLocalMatType`, `MatISGetLocalMat()` 31453b03a366Sstefano_zampini @*/ 3146d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISSetLocalMat(Mat mat, Mat local) 3147d71ae5a4SJacob Faibussowitsch { 31483b03a366Sstefano_zampini PetscFunctionBegin; 31493b03a366Sstefano_zampini PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3150b7ce53b6SStefano Zampini PetscValidHeaderSpecific(local, MAT_CLASSID, 2); 3151cac4c232SBarry Smith PetscUseMethod(mat, "MatISSetLocalMat_C", (Mat, Mat), (mat, local)); 31523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31533b03a366Sstefano_zampini } 31543b03a366Sstefano_zampini 3155d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroEntries_IS(Mat A) 3156d71ae5a4SJacob Faibussowitsch { 31576726f965SBarry Smith Mat_IS *a = (Mat_IS *)A->data; 31586726f965SBarry Smith 31596726f965SBarry Smith PetscFunctionBegin; 31609566063dSJacob Faibussowitsch PetscCall(MatZeroEntries(a->A)); 31613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31626726f965SBarry Smith } 31636726f965SBarry Smith 3164d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatScale_IS(Mat A, PetscScalar a) 3165d71ae5a4SJacob Faibussowitsch { 31662e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS *)A->data; 31672e74eeadSLisandro Dalcin 31682e74eeadSLisandro Dalcin PetscFunctionBegin; 31699566063dSJacob Faibussowitsch PetscCall(MatScale(is->A, a)); 31703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31712e74eeadSLisandro Dalcin } 31722e74eeadSLisandro Dalcin 3173d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v) 3174d71ae5a4SJacob Faibussowitsch { 31752e74eeadSLisandro Dalcin Mat_IS *is = (Mat_IS *)A->data; 31762e74eeadSLisandro Dalcin 31772e74eeadSLisandro Dalcin PetscFunctionBegin; 31782e74eeadSLisandro Dalcin /* get diagonal of the local matrix */ 31799566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(is->A, is->y)); 31802e74eeadSLisandro Dalcin 31812e74eeadSLisandro Dalcin /* scatter diagonal back into global vector */ 31829566063dSJacob Faibussowitsch PetscCall(VecSet(v, 0)); 31839566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(is->rctx, is->y, v, ADD_VALUES, SCATTER_REVERSE)); 31849566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(is->rctx, is->y, v, ADD_VALUES, SCATTER_REVERSE)); 31853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31862e74eeadSLisandro Dalcin } 31872e74eeadSLisandro Dalcin 3188d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_IS(Mat A, MatOption op, PetscBool flg) 3189d71ae5a4SJacob Faibussowitsch { 31906726f965SBarry Smith Mat_IS *a = (Mat_IS *)A->data; 31916726f965SBarry Smith 31926726f965SBarry Smith PetscFunctionBegin; 31939566063dSJacob Faibussowitsch PetscCall(MatSetOption(a->A, op, flg)); 31943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31956726f965SBarry Smith } 31966726f965SBarry Smith 3197d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAXPY_IS(Mat Y, PetscScalar a, Mat X, MatStructure str) 3198d71ae5a4SJacob Faibussowitsch { 3199f26d0771SStefano Zampini Mat_IS *y = (Mat_IS *)Y->data; 3200f26d0771SStefano Zampini Mat_IS *x; 3201f26d0771SStefano Zampini 3202f26d0771SStefano Zampini PetscFunctionBegin; 320376bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 320476bd3646SJed Brown PetscBool ismatis; 32059566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)X, MATIS, &ismatis)); 320628b400f6SJacob Faibussowitsch PetscCheck(ismatis, PetscObjectComm((PetscObject)Y), PETSC_ERR_SUP, "Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS"); 320776bd3646SJed Brown } 3208f26d0771SStefano Zampini x = (Mat_IS *)X->data; 32099566063dSJacob Faibussowitsch PetscCall(MatAXPY(y->A, a, x->A, str)); 32103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3211f26d0771SStefano Zampini } 3212f26d0771SStefano Zampini 3213d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A, IS row, IS col, Mat *submat) 3214d71ae5a4SJacob Faibussowitsch { 3215f26d0771SStefano Zampini Mat lA; 3216f4f49eeaSPierre Jolivet Mat_IS *matis = (Mat_IS *)A->data; 3217f26d0771SStefano Zampini ISLocalToGlobalMapping rl2g, cl2g; 3218f26d0771SStefano Zampini IS is; 3219f26d0771SStefano Zampini const PetscInt *rg, *rl; 3220f26d0771SStefano Zampini PetscInt nrg; 3221f26d0771SStefano Zampini PetscInt N, M, nrl, i, *idxs; 3222f26d0771SStefano Zampini 3223f26d0771SStefano Zampini PetscFunctionBegin; 32249566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(A->rmap->mapping, &rg)); 32259566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(row, &nrl)); 32269566063dSJacob Faibussowitsch PetscCall(ISGetIndices(row, &rl)); 32279566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(A->rmap->mapping, &nrg)); 322876bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3229e87b5d96SPierre Jolivet for (i = 0; i < nrl; i++) PetscCheck(rl[i] < nrg, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Local row index %" PetscInt_FMT " -> %" PetscInt_FMT " greater than maximum possible %" PetscInt_FMT, i, rl[i], nrg); 323076bd3646SJed Brown } 32319566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nrg, &idxs)); 3232f26d0771SStefano Zampini /* map from [0,nrl) to row */ 3233f26d0771SStefano Zampini for (i = 0; i < nrl; i++) idxs[i] = rl[i]; 3234f26d0771SStefano Zampini for (i = nrl; i < nrg; i++) idxs[i] = -1; 32359566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(row, &rl)); 32369566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping, &rg)); 32379566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A), nrg, idxs, PETSC_OWN_POINTER, &is)); 32389566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g)); 32399566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3240f26d0771SStefano Zampini /* compute new l2g map for columns */ 3241e432b41dSStefano Zampini if (col != row || matis->rmapping != matis->cmapping || matis->A->rmap->mapping != matis->A->cmap->mapping) { 3242f26d0771SStefano Zampini const PetscInt *cg, *cl; 3243f26d0771SStefano Zampini PetscInt ncg; 3244f26d0771SStefano Zampini PetscInt ncl; 3245f26d0771SStefano Zampini 32469566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(A->cmap->mapping, &cg)); 32479566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(col, &ncl)); 32489566063dSJacob Faibussowitsch PetscCall(ISGetIndices(col, &cl)); 32499566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetSize(A->cmap->mapping, &ncg)); 325076bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 3251e87b5d96SPierre Jolivet for (i = 0; i < ncl; i++) PetscCheck(cl[i] < ncg, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Local column index %" PetscInt_FMT " -> %" PetscInt_FMT " greater than maximum possible %" PetscInt_FMT, i, cl[i], ncg); 325276bd3646SJed Brown } 32539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ncg, &idxs)); 3254f26d0771SStefano Zampini /* map from [0,ncl) to col */ 3255f26d0771SStefano Zampini for (i = 0; i < ncl; i++) idxs[i] = cl[i]; 3256f26d0771SStefano Zampini for (i = ncl; i < ncg; i++) idxs[i] = -1; 32579566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(col, &cl)); 32589566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping, &cg)); 32599566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)A), ncg, idxs, PETSC_OWN_POINTER, &is)); 32609566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g)); 32619566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3262f26d0771SStefano Zampini } else { 32639566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)rl2g)); 3264f26d0771SStefano Zampini cl2g = rl2g; 3265f26d0771SStefano Zampini } 3266f26d0771SStefano Zampini /* create the MATIS submatrix */ 32679566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &M, &N)); 32689566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)A), submat)); 32699566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*submat, PETSC_DECIDE, PETSC_DECIDE, M, N)); 32709566063dSJacob Faibussowitsch PetscCall(MatSetType(*submat, MATIS)); 3271b0aa3428SStefano Zampini matis = (Mat_IS *)((*submat)->data); 3272f26d0771SStefano Zampini matis->islocalref = PETSC_TRUE; 32739566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*submat, rl2g, cl2g)); 32749566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(A, &lA)); 32759566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*submat, lA)); 32769566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 32779566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 3278e432b41dSStefano Zampini 3279f26d0771SStefano Zampini /* remove unsupported ops */ 32809566063dSJacob Faibussowitsch PetscCall(PetscMemzero((*submat)->ops, sizeof(struct _MatOps))); 3281f26d0771SStefano Zampini (*submat)->ops->destroy = MatDestroy_IS; 3282f26d0771SStefano Zampini (*submat)->ops->setvalueslocal = MatSetValuesLocal_SubMat_IS; 3283f26d0771SStefano Zampini (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS; 328439b6f3f9SStefano Zampini (*submat)->ops->getlocalsubmatrix = MatGetLocalSubMatrix_IS; 32853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3286f26d0771SStefano Zampini } 3287f26d0771SStefano Zampini 3288ce78bad3SBarry Smith static PetscErrorCode MatSetFromOptions_IS(Mat A, PetscOptionItems PetscOptionsObject) 3289d71ae5a4SJacob Faibussowitsch { 3290872cf891SStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 32918546b261SStefano Zampini char type[256]; 32928546b261SStefano Zampini PetscBool flg; 3293872cf891SStefano Zampini 3294872cf891SStefano Zampini PetscFunctionBegin; 3295d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "MATIS options"); 32964f58015eSStefano Zampini PetscCall(PetscOptionsDeprecated("-matis_keepassembled", "-mat_is_keepassembled", "3.21", NULL)); 32974f58015eSStefano Zampini PetscCall(PetscOptionsDeprecated("-matis_fixempty", "-mat_is_fixempty", "3.21", NULL)); 32984f58015eSStefano Zampini PetscCall(PetscOptionsDeprecated("-matis_storel2l", "-mat_is_storel2l", "3.21", NULL)); 32994f58015eSStefano Zampini PetscCall(PetscOptionsDeprecated("-matis_localmat_type", "-mat_is_localmat_type", "3.21", NULL)); 33004f58015eSStefano Zampini PetscCall(PetscOptionsBool("-mat_is_keepassembled", "Store an assembled version if needed", NULL, a->keepassembled, &a->keepassembled, NULL)); 33014f58015eSStefano Zampini PetscCall(PetscOptionsBool("-mat_is_fixempty", "Fix local matrices in case of empty local rows/columns", "MatISFixLocalEmpty", a->locempty, &a->locempty, NULL)); 33024f58015eSStefano Zampini PetscCall(PetscOptionsBool("-mat_is_storel2l", "Store local-to-local matrices generated from PtAP operations", "MatISStoreL2L", a->storel2l, &a->storel2l, NULL)); 33034f58015eSStefano Zampini PetscCall(PetscOptionsBool("-mat_is_allow_repeated", "Allow local repeated entries", "MatISSetAllowRepeated", a->allow_repeated, &a->allow_repeated, NULL)); 33044f58015eSStefano Zampini PetscCall(PetscOptionsFList("-mat_is_localmat_type", "Matrix type", "MatISSetLocalMatType", MatList, a->lmattype, type, 256, &flg)); 33051baa6e33SBarry Smith if (flg) PetscCall(MatISSetLocalMatType(A, type)); 33061baa6e33SBarry Smith if (a->A) PetscCall(MatSetFromOptions(a->A)); 3307d0609cedSBarry Smith PetscOptionsHeadEnd(); 33083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3309872cf891SStefano Zampini } 3310872cf891SStefano Zampini 3311284134d9SBarry Smith /*@ 33124f58015eSStefano Zampini MatCreateIS - Creates a "process" unassembled matrix. 33134f58015eSStefano Zampini 33144f58015eSStefano Zampini Collective. 3315284134d9SBarry Smith 3316284134d9SBarry Smith Input Parameters: 3317284134d9SBarry Smith + comm - MPI communicator that will share the matrix 3318e176bc59SStefano Zampini . bs - block size of the matrix 33192920cce0SJacob Faibussowitsch . m - local size of left vector used in matrix vector products 33202920cce0SJacob Faibussowitsch . n - local size of right vector used in matrix vector products 33212920cce0SJacob Faibussowitsch . M - global size of left vector used in matrix vector products 33222920cce0SJacob Faibussowitsch . N - global size of right vector used in matrix vector products 3323e176bc59SStefano Zampini . rmap - local to global map for rows 3324e176bc59SStefano Zampini - cmap - local to global map for cols 3325284134d9SBarry Smith 3326284134d9SBarry Smith Output Parameter: 3327284134d9SBarry Smith . A - the resulting matrix 3328284134d9SBarry Smith 33294f58015eSStefano Zampini Level: intermediate 33308e6c10adSSatish Balay 333195452b02SPatrick Sanan Notes: 33322ef1f0ffSBarry 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 33334f58015eSStefano Zampini used in `MatMult()` operations. The local sizes of `rmap` and `cmap` define the size of the local matrices. 333411a5261eSBarry Smith 33352ef1f0ffSBarry Smith If `rmap` (`cmap`) is `NULL`, then the local row (column) spaces matches the global space. 3336284134d9SBarry Smith 33371cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatSetLocalToGlobalMapping()` 3338284134d9SBarry Smith @*/ 3339d71ae5a4SJacob Faibussowitsch PetscErrorCode MatCreateIS(MPI_Comm comm, PetscInt bs, PetscInt m, PetscInt n, PetscInt M, PetscInt N, ISLocalToGlobalMapping rmap, ISLocalToGlobalMapping cmap, Mat *A) 3340d71ae5a4SJacob Faibussowitsch { 3341284134d9SBarry Smith PetscFunctionBegin; 33429566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, A)); 33439566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*A, m, n, M, N)); 334448a46eb9SPierre Jolivet if (bs > 0) PetscCall(MatSetBlockSize(*A, bs)); 33459566063dSJacob Faibussowitsch PetscCall(MatSetType(*A, MATIS)); 33469566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*A, rmap, cmap)); 33473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3348284134d9SBarry Smith } 3349284134d9SBarry Smith 3350d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHasOperation_IS(Mat A, MatOperation op, PetscBool *has) 3351d71ae5a4SJacob Faibussowitsch { 33528b9382cfSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3353e26763e4SStefano Zampini MatOperation tobefiltered[] = {MATOP_MULT_ADD, MATOP_MULT_TRANSPOSE_ADD, MATOP_GET_DIAGONAL_BLOCK, MATOP_INCREASE_OVERLAP}; 33548b9382cfSStefano Zampini 33558b9382cfSStefano Zampini PetscFunctionBegin; 33568b9382cfSStefano Zampini *has = PETSC_FALSE; 33573ba16761SJacob Faibussowitsch if (!((void **)A->ops)[op] || !a->A) PetscFunctionReturn(PETSC_SUCCESS); 3358d0dbe9f7SStefano Zampini *has = PETSC_TRUE; 33599371c9d4SSatish Balay for (PetscInt i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(tobefiltered); i++) 33603ba16761SJacob Faibussowitsch if (op == tobefiltered[i]) PetscFunctionReturn(PETSC_SUCCESS); 33619566063dSJacob Faibussowitsch PetscCall(MatHasOperation(a->A, op, has)); 33623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 33638b9382cfSStefano Zampini } 33648b9382cfSStefano Zampini 3365d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesCOO_IS(Mat A, const PetscScalar v[], InsertMode imode) 3366d71ae5a4SJacob Faibussowitsch { 3367e432b41dSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3368e432b41dSStefano Zampini 3369e432b41dSStefano Zampini PetscFunctionBegin; 33709566063dSJacob Faibussowitsch PetscCall(MatSetValuesCOO(a->A, v, imode)); 33719566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 33729566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 33733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3374e432b41dSStefano Zampini } 3375e432b41dSStefano Zampini 3376d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetPreallocationCOOLocal_IS(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[]) 3377d71ae5a4SJacob Faibussowitsch { 3378e432b41dSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3379e432b41dSStefano Zampini 3380e432b41dSStefano Zampini PetscFunctionBegin; 3381e432b41dSStefano Zampini PetscCheck(a->A, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Need to provide l2g map first via MatSetLocalToGlobalMapping"); 3382e432b41dSStefano Zampini if (a->A->rmap->mapping || a->A->cmap->mapping) { 33839566063dSJacob Faibussowitsch PetscCall(MatSetPreallocationCOOLocal(a->A, ncoo, coo_i, coo_j)); 3384e432b41dSStefano Zampini } else { 33859566063dSJacob Faibussowitsch PetscCall(MatSetPreallocationCOO(a->A, ncoo, coo_i, coo_j)); 3386e432b41dSStefano Zampini } 33879566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", MatSetValuesCOO_IS)); 3388e432b41dSStefano Zampini A->preallocated = PETSC_TRUE; 33893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3390e432b41dSStefano Zampini } 3391e432b41dSStefano Zampini 3392d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetPreallocationCOO_IS(Mat A, PetscCount ncoo, PetscInt coo_i[], PetscInt coo_j[]) 3393d71ae5a4SJacob Faibussowitsch { 3394e432b41dSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3395835f2295SStefano Zampini PetscInt ncoo_i; 3396e432b41dSStefano Zampini 3397e432b41dSStefano Zampini PetscFunctionBegin; 3398e432b41dSStefano Zampini PetscCheck(a->A, PetscObjectComm((PetscObject)A), PETSC_ERR_ORDER, "Need to provide l2g map first via MatSetLocalToGlobalMapping"); 3399835f2295SStefano Zampini PetscCall(PetscIntCast(ncoo, &ncoo_i)); 3400835f2295SStefano Zampini PetscCall(ISGlobalToLocalMappingApply(a->rmapping, IS_GTOLM_MASK, ncoo_i, coo_i, NULL, coo_i)); 3401835f2295SStefano Zampini PetscCall(ISGlobalToLocalMappingApply(a->cmapping, IS_GTOLM_MASK, ncoo_i, coo_j, NULL, coo_j)); 3402e8729f6fSJunchao Zhang PetscCall(MatSetPreallocationCOO(a->A, ncoo, coo_i, coo_j)); 34039566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", MatSetValuesCOO_IS)); 3404e432b41dSStefano Zampini A->preallocated = PETSC_TRUE; 34053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3406e432b41dSStefano Zampini } 3407e432b41dSStefano Zampini 3408d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISGetAssembled_Private(Mat A, Mat *tA) 3409d71ae5a4SJacob Faibussowitsch { 3410d0dbe9f7SStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 34111690c2aeSBarry Smith PetscObjectState Astate, aAstate = PETSC_INT_MIN; 34121690c2aeSBarry Smith PetscObjectState Annzstate, aAnnzstate = PETSC_INT_MIN; 3413d0dbe9f7SStefano Zampini 3414d0dbe9f7SStefano Zampini PetscFunctionBegin; 3415d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateGet((PetscObject)A, &Astate)); 3416d0dbe9f7SStefano Zampini Annzstate = A->nonzerostate; 3417d0dbe9f7SStefano Zampini if (a->assembledA) { 3418d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateGet((PetscObject)a->assembledA, &aAstate)); 3419d0dbe9f7SStefano Zampini aAnnzstate = a->assembledA->nonzerostate; 3420d0dbe9f7SStefano Zampini } 3421d0dbe9f7SStefano Zampini if (aAnnzstate != Annzstate) PetscCall(MatDestroy(&a->assembledA)); 3422d0dbe9f7SStefano Zampini if (Astate != aAstate || !a->assembledA) { 3423d0dbe9f7SStefano Zampini MatType aAtype; 3424d0dbe9f7SStefano Zampini PetscMPIInt size; 3425d0dbe9f7SStefano Zampini PetscInt rbs, cbs, bs; 3426d0dbe9f7SStefano Zampini 3427d0dbe9f7SStefano Zampini /* the assembled form is used as temporary storage for parallel operations 3428d0dbe9f7SStefano Zampini like createsubmatrices and the like, do not waste device memory */ 3429d0dbe9f7SStefano Zampini PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 3430d0dbe9f7SStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockSize(a->cmapping, &cbs)); 3431d0dbe9f7SStefano Zampini PetscCall(ISLocalToGlobalMappingGetBlockSize(a->rmapping, &rbs)); 3432d0dbe9f7SStefano Zampini bs = rbs == cbs ? rbs : 1; 3433d0dbe9f7SStefano Zampini if (a->assembledA) PetscCall(MatGetType(a->assembledA, &aAtype)); 3434d0dbe9f7SStefano Zampini else if (size > 1) aAtype = bs > 1 ? MATMPIBAIJ : MATMPIAIJ; 3435d0dbe9f7SStefano Zampini else aAtype = bs > 1 ? MATSEQBAIJ : MATSEQAIJ; 3436d0dbe9f7SStefano Zampini 3437d0dbe9f7SStefano Zampini PetscCall(MatConvert(A, aAtype, a->assembledA ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX, &a->assembledA)); 3438d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateSet((PetscObject)a->assembledA, Astate)); 3439d0dbe9f7SStefano Zampini a->assembledA->nonzerostate = Annzstate; 3440d0dbe9f7SStefano Zampini } 3441d0dbe9f7SStefano Zampini PetscCall(PetscObjectReference((PetscObject)a->assembledA)); 3442d0dbe9f7SStefano Zampini *tA = a->assembledA; 3443d0dbe9f7SStefano Zampini if (!a->keepassembled) PetscCall(MatDestroy(&a->assembledA)); 34443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3445d0dbe9f7SStefano Zampini } 3446d0dbe9f7SStefano Zampini 3447d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISRestoreAssembled_Private(Mat A, Mat *tA) 3448d71ae5a4SJacob Faibussowitsch { 3449d0dbe9f7SStefano Zampini PetscFunctionBegin; 3450d0dbe9f7SStefano Zampini PetscCall(MatDestroy(tA)); 3451d0dbe9f7SStefano Zampini *tA = NULL; 34523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3453d0dbe9f7SStefano Zampini } 3454d0dbe9f7SStefano Zampini 3455d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonalBlock_IS(Mat A, Mat *dA) 3456d71ae5a4SJacob Faibussowitsch { 3457d0dbe9f7SStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 34581690c2aeSBarry Smith PetscObjectState Astate, dAstate = PETSC_INT_MIN; 3459d0dbe9f7SStefano Zampini 3460d0dbe9f7SStefano Zampini PetscFunctionBegin; 3461d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateGet((PetscObject)A, &Astate)); 3462d0dbe9f7SStefano Zampini if (a->dA) PetscCall(PetscObjectStateGet((PetscObject)a->dA, &dAstate)); 3463d0dbe9f7SStefano Zampini if (Astate != dAstate) { 3464d0dbe9f7SStefano Zampini Mat tA; 3465d0dbe9f7SStefano Zampini MatType ltype; 3466d0dbe9f7SStefano Zampini 3467d0dbe9f7SStefano Zampini PetscCall(MatDestroy(&a->dA)); 3468d0dbe9f7SStefano Zampini PetscCall(MatISGetAssembled_Private(A, &tA)); 3469d0dbe9f7SStefano Zampini PetscCall(MatGetDiagonalBlock(tA, &a->dA)); 3470d0dbe9f7SStefano Zampini PetscCall(MatPropagateSymmetryOptions(tA, a->dA)); 3471d0dbe9f7SStefano Zampini PetscCall(MatGetType(a->A, <ype)); 3472d0dbe9f7SStefano Zampini PetscCall(MatConvert(a->dA, ltype, MAT_INPLACE_MATRIX, &a->dA)); 3473d0dbe9f7SStefano Zampini PetscCall(PetscObjectReference((PetscObject)a->dA)); 3474d0dbe9f7SStefano Zampini PetscCall(MatISRestoreAssembled_Private(A, &tA)); 3475d0dbe9f7SStefano Zampini PetscCall(PetscObjectStateSet((PetscObject)a->dA, Astate)); 3476d0dbe9f7SStefano Zampini } 3477d0dbe9f7SStefano Zampini *dA = a->dA; 34783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3479d0dbe9f7SStefano Zampini } 3480d0dbe9f7SStefano Zampini 3481d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCreateSubMatrices_IS(Mat A, PetscInt n, const IS irow[], const IS icol[], MatReuse reuse, Mat *submat[]) 3482d71ae5a4SJacob Faibussowitsch { 3483d0dbe9f7SStefano Zampini Mat tA; 3484d0dbe9f7SStefano Zampini 3485d0dbe9f7SStefano Zampini PetscFunctionBegin; 3486d0dbe9f7SStefano Zampini PetscCall(MatISGetAssembled_Private(A, &tA)); 3487d0dbe9f7SStefano Zampini PetscCall(MatCreateSubMatrices(tA, n, irow, icol, reuse, submat)); 3488d0dbe9f7SStefano Zampini /* MatCreateSubMatrices_MPIAIJ is a mess at the moment */ 3489d0dbe9f7SStefano Zampini #if 0 3490d0dbe9f7SStefano Zampini { 3491d0dbe9f7SStefano Zampini Mat_IS *a = (Mat_IS*)A->data; 3492d0dbe9f7SStefano Zampini MatType ltype; 3493d0dbe9f7SStefano Zampini VecType vtype; 3494d0dbe9f7SStefano Zampini char *flg; 3495d0dbe9f7SStefano Zampini 3496d0dbe9f7SStefano Zampini PetscCall(MatGetType(a->A,<ype)); 3497d0dbe9f7SStefano Zampini PetscCall(MatGetVecType(a->A,&vtype)); 3498d0dbe9f7SStefano Zampini PetscCall(PetscStrstr(vtype,"cuda",&flg)); 3499d0dbe9f7SStefano Zampini if (!flg) PetscCall(PetscStrstr(vtype,"hip",&flg)); 3500d0dbe9f7SStefano Zampini if (!flg) PetscCall(PetscStrstr(vtype,"kokkos",&flg)); 3501d0dbe9f7SStefano Zampini if (flg) { 3502d0dbe9f7SStefano Zampini for (PetscInt i = 0; i < n; i++) { 3503d0dbe9f7SStefano Zampini Mat sA = (*submat)[i]; 3504d0dbe9f7SStefano Zampini 3505d0dbe9f7SStefano Zampini PetscCall(MatConvert(sA,ltype,MAT_INPLACE_MATRIX,&sA)); 3506d0dbe9f7SStefano Zampini (*submat)[i] = sA; 3507d0dbe9f7SStefano Zampini } 3508d0dbe9f7SStefano Zampini } 3509d0dbe9f7SStefano Zampini } 3510d0dbe9f7SStefano Zampini #endif 3511d0dbe9f7SStefano Zampini PetscCall(MatISRestoreAssembled_Private(A, &tA)); 35123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3513d0dbe9f7SStefano Zampini } 3514d0dbe9f7SStefano Zampini 3515d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatIncreaseOverlap_IS(Mat A, PetscInt n, IS is[], PetscInt ov) 3516d71ae5a4SJacob Faibussowitsch { 3517d0dbe9f7SStefano Zampini Mat tA; 3518d0dbe9f7SStefano Zampini 3519d0dbe9f7SStefano Zampini PetscFunctionBegin; 3520d0dbe9f7SStefano Zampini PetscCall(MatISGetAssembled_Private(A, &tA)); 3521d0dbe9f7SStefano Zampini PetscCall(MatIncreaseOverlap(tA, n, is, ov)); 3522d0dbe9f7SStefano Zampini PetscCall(MatISRestoreAssembled_Private(A, &tA)); 35233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3524d0dbe9f7SStefano Zampini } 3525d0dbe9f7SStefano Zampini 3526e432b41dSStefano Zampini /*@ 352711a5261eSBarry Smith MatISGetLocalToGlobalMapping - Gets the local-to-global numbering of the `MATIS` object 3528e432b41dSStefano Zampini 3529e432b41dSStefano Zampini Not Collective 3530e432b41dSStefano Zampini 3531e432b41dSStefano Zampini Input Parameter: 3532e432b41dSStefano Zampini . A - the matrix 3533e432b41dSStefano Zampini 3534e432b41dSStefano Zampini Output Parameters: 3535e432b41dSStefano Zampini + rmapping - row mapping 3536e432b41dSStefano Zampini - cmapping - column mapping 3537e432b41dSStefano Zampini 35382ef1f0ffSBarry Smith Level: advanced 35392ef1f0ffSBarry Smith 354011a5261eSBarry Smith Note: 354111a5261eSBarry 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. 3542e432b41dSStefano Zampini 3543bfe80ac4SPierre Jolivet .seealso: [](ch_matrices), `Mat`, `MATIS`, `MatSetLocalToGlobalMapping()` 3544e432b41dSStefano Zampini @*/ 3545d71ae5a4SJacob Faibussowitsch PetscErrorCode MatISGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 3546d71ae5a4SJacob Faibussowitsch { 3547e432b41dSStefano Zampini PetscFunctionBegin; 3548e432b41dSStefano Zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3549e432b41dSStefano Zampini PetscValidType(A, 1); 35504f572ea9SToby Isaac if (rmapping) PetscAssertPointer(rmapping, 2); 35514f572ea9SToby Isaac if (cmapping) PetscAssertPointer(cmapping, 3); 3552cac4c232SBarry Smith PetscUseMethod(A, "MatISGetLocalToGlobalMapping_C", (Mat, ISLocalToGlobalMapping *, ISLocalToGlobalMapping *), (A, rmapping, cmapping)); 35533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3554e432b41dSStefano Zampini } 3555e432b41dSStefano Zampini 3556d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatISGetLocalToGlobalMapping_IS(Mat A, ISLocalToGlobalMapping *r, ISLocalToGlobalMapping *c) 3557d71ae5a4SJacob Faibussowitsch { 3558e432b41dSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3559e432b41dSStefano Zampini 3560e432b41dSStefano Zampini PetscFunctionBegin; 3561e432b41dSStefano Zampini if (r) *r = a->rmapping; 3562e432b41dSStefano Zampini if (c) *c = a->cmapping; 35633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3564e432b41dSStefano Zampini } 3565e432b41dSStefano Zampini 3566a50ef18cSStefano Zampini static PetscErrorCode MatSetBlockSizes_IS(Mat A, PetscInt rbs, PetscInt cbs) 3567a50ef18cSStefano Zampini { 3568a50ef18cSStefano Zampini Mat_IS *a = (Mat_IS *)A->data; 3569a50ef18cSStefano Zampini 3570a50ef18cSStefano Zampini PetscFunctionBegin; 3571a50ef18cSStefano Zampini if (a->A) PetscCall(MatSetBlockSizes(a->A, rbs, cbs)); 3572a50ef18cSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 3573a50ef18cSStefano Zampini } 3574a50ef18cSStefano Zampini 3575b4319ba4SBarry Smith /*MC 35764f58015eSStefano Zampini MATIS - MATIS = "is" - A matrix type to be used for non-overlapping domain decomposition methods (e.g. `PCBDDC` or `KSPFETIDP`). 35774f58015eSStefano Zampini This stores the matrices in globally unassembled form and the parallel matrix vector product is handled "implicitly". 3578b4319ba4SBarry Smith 3579b4319ba4SBarry Smith Options Database Keys: 35804f58015eSStefano Zampini + -mat_type is - Set the matrix type to `MATIS`. 35814f58015eSStefano Zampini . -mat_is_allow_repeated - Allow repeated entries in the local part of the local to global maps. 35824f58015eSStefano Zampini . -mat_is_fixempty - Fix local matrices in case of empty local rows/columns. 35834f58015eSStefano Zampini - -mat_is_storel2l - Store the local-to-local operators generated by the Galerkin process of `MatPtAP()`. 35842ef1f0ffSBarry Smith 35854f58015eSStefano Zampini Level: intermediate 3586b4319ba4SBarry Smith 358795452b02SPatrick Sanan Notes: 35882ef1f0ffSBarry Smith Options prefix for the inner matrix are given by `-is_mat_xxx` 3589b4319ba4SBarry Smith 359011a5261eSBarry Smith You must call `MatSetLocalToGlobalMapping()` before using this matrix type. 3591b4319ba4SBarry Smith 3592b4319ba4SBarry Smith You can do matrix preallocation on the local matrix after you obtain it with 35934f58015eSStefano Zampini `MatISGetLocalMat()`; otherwise, you could use `MatISSetPreallocation()` or `MatXAIJSetPreallocation()` 3594b4319ba4SBarry Smith 35951cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MATIS`, `Mat`, `MatISGetLocalMat()`, `MatSetLocalToGlobalMapping()`, `MatISSetPreallocation()`, `MatCreateIS()`, `PCBDDC`, `KSPFETIDP` 3596b4319ba4SBarry Smith M*/ 3597d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A) 3598d71ae5a4SJacob Faibussowitsch { 3599e432b41dSStefano Zampini Mat_IS *a; 3600b4319ba4SBarry Smith 3601b4319ba4SBarry Smith PetscFunctionBegin; 36024dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&a)); 36039566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(MATAIJ, &a->lmattype)); 3604e432b41dSStefano Zampini A->data = (void *)a; 3605b4319ba4SBarry Smith 3606e176bc59SStefano Zampini /* matrix ops */ 36079566063dSJacob Faibussowitsch PetscCall(PetscMemzero(A->ops, sizeof(struct _MatOps))); 3608b4319ba4SBarry Smith A->ops->mult = MatMult_IS; 36092e74eeadSLisandro Dalcin A->ops->multadd = MatMultAdd_IS; 36102e74eeadSLisandro Dalcin A->ops->multtranspose = MatMultTranspose_IS; 36112e74eeadSLisandro Dalcin A->ops->multtransposeadd = MatMultTransposeAdd_IS; 3612b4319ba4SBarry Smith A->ops->destroy = MatDestroy_IS; 3613b4319ba4SBarry Smith A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS; 36142e74eeadSLisandro Dalcin A->ops->setvalues = MatSetValues_IS; 361598921651SStefano Zampini A->ops->setvaluesblocked = MatSetValuesBlocked_IS; 3616b4319ba4SBarry Smith A->ops->setvalueslocal = MatSetValuesLocal_IS; 3617f0006bf2SLisandro Dalcin A->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_IS; 36182e74eeadSLisandro Dalcin A->ops->zerorows = MatZeroRows_IS; 3619f0ae7da4SStefano Zampini A->ops->zerorowscolumns = MatZeroRowsColumns_IS; 3620b4319ba4SBarry Smith A->ops->assemblybegin = MatAssemblyBegin_IS; 3621b4319ba4SBarry Smith A->ops->assemblyend = MatAssemblyEnd_IS; 3622b4319ba4SBarry Smith A->ops->view = MatView_IS; 36235042aa92SStefano Zampini A->ops->load = MatLoad_IS; 36246726f965SBarry Smith A->ops->zeroentries = MatZeroEntries_IS; 36252e74eeadSLisandro Dalcin A->ops->scale = MatScale_IS; 36262e74eeadSLisandro Dalcin A->ops->getdiagonal = MatGetDiagonal_IS; 36276726f965SBarry Smith A->ops->setoption = MatSetOption_IS; 362869796d55SStefano Zampini A->ops->ishermitian = MatIsHermitian_IS; 362969796d55SStefano Zampini A->ops->issymmetric = MatIsSymmetric_IS; 363045471136SStefano Zampini A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS; 3631ad6194a2SStefano Zampini A->ops->duplicate = MatDuplicate_IS; 36326bd84002SStefano Zampini A->ops->missingdiagonal = MatMissingDiagonal_IS; 36332b404112SStefano Zampini A->ops->copy = MatCopy_IS; 3634659959c5SStefano Zampini A->ops->getlocalsubmatrix = MatGetLocalSubMatrix_IS; 36357dae84e0SHong Zhang A->ops->createsubmatrix = MatCreateSubMatrix_IS; 3636f26d0771SStefano Zampini A->ops->axpy = MatAXPY_IS; 36373fd1c9e7SStefano Zampini A->ops->diagonalset = MatDiagonalSet_IS; 36383fd1c9e7SStefano Zampini A->ops->shift = MatShift_IS; 3639d7f69cd0SStefano Zampini A->ops->transpose = MatTranspose_IS; 36407fa8f2d3SStefano Zampini A->ops->getinfo = MatGetInfo_IS; 3641ad219c80Sstefano_zampini A->ops->diagonalscale = MatDiagonalScale_IS; 3642872cf891SStefano Zampini A->ops->setfromoptions = MatSetFromOptions_IS; 3643fc989267SStefano Zampini A->ops->setup = MatSetUp_IS; 36448b9382cfSStefano Zampini A->ops->hasoperation = MatHasOperation_IS; 3645d0dbe9f7SStefano Zampini A->ops->getdiagonalblock = MatGetDiagonalBlock_IS; 3646d0dbe9f7SStefano Zampini A->ops->createsubmatrices = MatCreateSubMatrices_IS; 3647d0dbe9f7SStefano Zampini A->ops->increaseoverlap = MatIncreaseOverlap_IS; 3648a50ef18cSStefano Zampini A->ops->setblocksizes = MatSetBlockSizes_IS; 3649b4319ba4SBarry Smith 3650b7ce53b6SStefano Zampini /* special MATIS functions */ 36519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMatType_C", MatISSetLocalMatType_IS)); 36529566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalMat_C", MatISGetLocalMat_IS)); 36539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISRestoreLocalMat_C", MatISRestoreLocalMat_IS)); 36549566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetLocalMat_C", MatISSetLocalMat_IS)); 36559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetPreallocation_C", MatISSetPreallocation_IS)); 36564f58015eSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISSetAllowRepeated_C", MatISSetAllowRepeated_IS)); 36579566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISStoreL2L_C", MatISStoreL2L_IS)); 36589566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISFixLocalEmpty_C", MatISFixLocalEmpty_IS)); 36599566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatISGetLocalToGlobalMapping_C", MatISGetLocalToGlobalMapping_IS)); 36609566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpiaij_C", MatConvert_IS_XAIJ)); 36619566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpibaij_C", MatConvert_IS_XAIJ)); 36629566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_mpisbaij_C", MatConvert_IS_XAIJ)); 36639566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqaij_C", MatConvert_IS_XAIJ)); 36649566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqbaij_C", MatConvert_IS_XAIJ)); 36659566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_seqsbaij_C", MatConvert_IS_XAIJ)); 36669566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_is_aij_C", MatConvert_IS_XAIJ)); 36679566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOOLocal_C", MatSetPreallocationCOOLocal_IS)); 36689566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_IS)); 36699566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)A, MATIS)); 36703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3671b4319ba4SBarry Smith } 3672