163c07aadSStefano Zampini 263c07aadSStefano Zampini /* 363c07aadSStefano Zampini Creates hypre ijmatrix from PETSc matrix 463c07aadSStefano Zampini */ 5225daaf8SStefano Zampini 6c6698e78SStefano Zampini #include <petscpkg_version.h> 739accc25SStefano Zampini #include <petsc/private/petschypre.h> 8dd9c0a25Sstefano_zampini #include <petscmathypre.h> 963c07aadSStefano Zampini #include <petsc/private/matimpl.h> 10a4af0ceeSJacob Faibussowitsch #include <petsc/private/deviceimpl.h> 1163c07aadSStefano Zampini #include <../src/mat/impls/hypre/mhypre.h> 1263c07aadSStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h> 1358968eb6SStefano Zampini #include <../src/vec/vec/impls/hypre/vhyp.h> 1458968eb6SStefano Zampini #include <HYPRE.h> 15c1a070e6SStefano Zampini #include <HYPRE_utilities.h> 16cd8bc7baSStefano Zampini #include <_hypre_parcsr_ls.h> 1768ec7858SStefano Zampini #include <_hypre_sstruct_ls.h> 1863c07aadSStefano Zampini 190e6427aaSSatish Balay #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0) 200e6427aaSSatish Balay #define hypre_ParCSRMatrixClone(A, B) hypre_ParCSRMatrixCompleteClone(A) 210e6427aaSSatish Balay #endif 220e6427aaSSatish Balay 2363c07aadSStefano Zampini static PetscErrorCode MatHYPRE_CreateFromMat(Mat, Mat_HYPRE *); 2463c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat, Mat, HYPRE_IJMatrix); 2563c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixFastCopy_MPIAIJ(Mat, HYPRE_IJMatrix); 2663c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixFastCopy_SeqAIJ(Mat, HYPRE_IJMatrix); 2739accc25SStefano Zampini static PetscErrorCode MatHYPRE_MultKernel_Private(Mat, HYPRE_Complex, Vec, HYPRE_Complex, Vec, PetscBool); 28225daaf8SStefano Zampini static PetscErrorCode hypre_array_destroy(void *); 296ea7df73SStefano Zampini static PetscErrorCode MatSetValues_HYPRE(Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[], const PetscScalar[], InsertMode ins); 3063c07aadSStefano Zampini 319371c9d4SSatish Balay static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat A_d, Mat A_o, HYPRE_IJMatrix ij) { 3263c07aadSStefano Zampini PetscInt i, n_d, n_o; 3363c07aadSStefano Zampini const PetscInt *ia_d, *ia_o; 3463c07aadSStefano Zampini PetscBool done_d = PETSC_FALSE, done_o = PETSC_FALSE; 352cf14000SStefano Zampini HYPRE_Int *nnz_d = NULL, *nnz_o = NULL; 3663c07aadSStefano Zampini 3763c07aadSStefano Zampini PetscFunctionBegin; 3863c07aadSStefano Zampini if (A_d) { /* determine number of nonzero entries in local diagonal part */ 399566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A_d, 0, PETSC_FALSE, PETSC_FALSE, &n_d, &ia_d, NULL, &done_d)); 4063c07aadSStefano Zampini if (done_d) { 419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_d, &nnz_d)); 42ad540459SPierre Jolivet for (i = 0; i < n_d; i++) nnz_d[i] = ia_d[i + 1] - ia_d[i]; 4363c07aadSStefano Zampini } 449566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A_d, 0, PETSC_FALSE, PETSC_FALSE, NULL, &ia_d, NULL, &done_d)); 4563c07aadSStefano Zampini } 4663c07aadSStefano Zampini if (A_o) { /* determine number of nonzero entries in local off-diagonal part */ 479566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A_o, 0, PETSC_FALSE, PETSC_FALSE, &n_o, &ia_o, NULL, &done_o)); 4863c07aadSStefano Zampini if (done_o) { 499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_o, &nnz_o)); 50ad540459SPierre Jolivet for (i = 0; i < n_o; i++) nnz_o[i] = ia_o[i + 1] - ia_o[i]; 5163c07aadSStefano Zampini } 529566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A_o, 0, PETSC_FALSE, PETSC_FALSE, &n_o, &ia_o, NULL, &done_o)); 5363c07aadSStefano Zampini } 5463c07aadSStefano Zampini if (done_d) { /* set number of nonzeros in HYPRE IJ matrix */ 5563c07aadSStefano Zampini if (!done_o) { /* only diagonal part */ 569566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n_d, &nnz_o)); 5763c07aadSStefano Zampini } 58c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0) 59c6698e78SStefano Zampini { /* If we don't do this, the columns of the matrix will be all zeros! */ 60c6698e78SStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 61c6698e78SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij); 62c6698e78SStefano Zampini hypre_AuxParCSRMatrixDestroy(aux_matrix); 63c6698e78SStefano Zampini hypre_IJMatrixTranslator(ij) = NULL; 64792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, ij, nnz_d, nnz_o); 6522235d61SPierre Jolivet /* it seems they partially fixed it in 2.19.0 */ 6622235d61SPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 67c6698e78SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij); 68c6698e78SStefano Zampini hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1; 6922235d61SPierre Jolivet #endif 70c6698e78SStefano Zampini } 71c6698e78SStefano Zampini #else 72792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, ij, nnz_d, nnz_o); 73c6698e78SStefano Zampini #endif 749566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz_d)); 759566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz_o)); 7663c07aadSStefano Zampini } 7763c07aadSStefano Zampini PetscFunctionReturn(0); 7863c07aadSStefano Zampini } 7963c07aadSStefano Zampini 809371c9d4SSatish Balay static PetscErrorCode MatHYPRE_CreateFromMat(Mat A, Mat_HYPRE *hA) { 8163c07aadSStefano Zampini PetscInt rstart, rend, cstart, cend; 8263c07aadSStefano Zampini 8363c07aadSStefano Zampini PetscFunctionBegin; 849566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 859566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 8663c07aadSStefano Zampini rstart = A->rmap->rstart; 8763c07aadSStefano Zampini rend = A->rmap->rend; 8863c07aadSStefano Zampini cstart = A->cmap->rstart; 8963c07aadSStefano Zampini cend = A->cmap->rend; 90792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rstart, rend - 1, cstart, cend - 1, &hA->ij); 91792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR); 9263c07aadSStefano Zampini { 9363c07aadSStefano Zampini PetscBool same; 9463c07aadSStefano Zampini Mat A_d, A_o; 9563c07aadSStefano Zampini const PetscInt *colmap; 969566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &same)); 9763c07aadSStefano Zampini if (same) { 989566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(A, &A_d, &A_o, &colmap)); 999566063dSJacob Faibussowitsch PetscCall(MatHYPRE_IJMatrixPreallocate(A_d, A_o, hA->ij)); 10063c07aadSStefano Zampini PetscFunctionReturn(0); 10163c07aadSStefano Zampini } 1029566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIBAIJ, &same)); 10363c07aadSStefano Zampini if (same) { 1049566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJGetSeqBAIJ(A, &A_d, &A_o, &colmap)); 1059566063dSJacob Faibussowitsch PetscCall(MatHYPRE_IJMatrixPreallocate(A_d, A_o, hA->ij)); 10663c07aadSStefano Zampini PetscFunctionReturn(0); 10763c07aadSStefano Zampini } 1089566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &same)); 10963c07aadSStefano Zampini if (same) { 1109566063dSJacob Faibussowitsch PetscCall(MatHYPRE_IJMatrixPreallocate(A, NULL, hA->ij)); 11163c07aadSStefano Zampini PetscFunctionReturn(0); 11263c07aadSStefano Zampini } 1139566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQBAIJ, &same)); 11463c07aadSStefano Zampini if (same) { 1159566063dSJacob Faibussowitsch PetscCall(MatHYPRE_IJMatrixPreallocate(A, NULL, hA->ij)); 11663c07aadSStefano Zampini PetscFunctionReturn(0); 11763c07aadSStefano Zampini } 11863c07aadSStefano Zampini } 11963c07aadSStefano Zampini PetscFunctionReturn(0); 12063c07aadSStefano Zampini } 12163c07aadSStefano Zampini 1229371c9d4SSatish Balay static PetscErrorCode MatHYPRE_IJMatrixCopy(Mat A, HYPRE_IJMatrix ij) { 12363c07aadSStefano Zampini PetscInt i, rstart, rend, ncols, nr, nc; 12463c07aadSStefano Zampini const PetscScalar *values; 12563c07aadSStefano Zampini const PetscInt *cols; 12663c07aadSStefano Zampini PetscBool flg; 12763c07aadSStefano Zampini 12863c07aadSStefano Zampini PetscFunctionBegin; 1296ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 130792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize, ij); 1316ea7df73SStefano Zampini #else 132792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize_v2, ij, HYPRE_MEMORY_HOST); 1336ea7df73SStefano Zampini #endif 1349566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &flg)); 1359566063dSJacob Faibussowitsch PetscCall(MatGetSize(A, &nr, &nc)); 13663c07aadSStefano Zampini if (flg && nr == nc) { 1379566063dSJacob Faibussowitsch PetscCall(MatHYPRE_IJMatrixFastCopy_MPIAIJ(A, ij)); 13863c07aadSStefano Zampini PetscFunctionReturn(0); 13963c07aadSStefano Zampini } 1409566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &flg)); 14163c07aadSStefano Zampini if (flg) { 1429566063dSJacob Faibussowitsch PetscCall(MatHYPRE_IJMatrixFastCopy_SeqAIJ(A, ij)); 14363c07aadSStefano Zampini PetscFunctionReturn(0); 14463c07aadSStefano Zampini } 14563c07aadSStefano Zampini 1465fbaff96SJunchao Zhang /* Do not need Aux since we have done precise i[],j[] allocation in MatHYPRE_CreateFromMat() */ 1475fbaff96SJunchao Zhang hypre_AuxParCSRMatrixNeedAux((hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij)) = 0; 1485fbaff96SJunchao Zhang 1499566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 15063c07aadSStefano Zampini for (i = rstart; i < rend; i++) { 1519566063dSJacob Faibussowitsch PetscCall(MatGetRow(A, i, &ncols, &cols, &values)); 152e3977e59Sstefano_zampini if (ncols) { 1532cf14000SStefano Zampini HYPRE_Int nc = (HYPRE_Int)ncols; 1542cf14000SStefano Zampini 155aed4548fSBarry Smith PetscCheck((PetscInt)nc == ncols, PETSC_COMM_SELF, PETSC_ERR_SUP, "Hypre overflow! number of columns %" PetscInt_FMT " for row %" PetscInt_FMT, ncols, i); 156792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetValues, ij, 1, &nc, (HYPRE_BigInt *)&i, (HYPRE_BigInt *)cols, (HYPRE_Complex *)values); 157e3977e59Sstefano_zampini } 1589566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(A, i, &ncols, &cols, &values)); 15963c07aadSStefano Zampini } 16063c07aadSStefano Zampini PetscFunctionReturn(0); 16163c07aadSStefano Zampini } 16263c07aadSStefano Zampini 1639371c9d4SSatish Balay static PetscErrorCode MatHYPRE_IJMatrixFastCopy_SeqAIJ(Mat A, HYPRE_IJMatrix ij) { 16463c07aadSStefano Zampini Mat_SeqAIJ *pdiag = (Mat_SeqAIJ *)A->data; 16558968eb6SStefano Zampini HYPRE_Int type; 16663c07aadSStefano Zampini hypre_ParCSRMatrix *par_matrix; 16763c07aadSStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 16863c07aadSStefano Zampini hypre_CSRMatrix *hdiag; 1692cf14000SStefano Zampini PetscBool sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int)); 1706ea7df73SStefano Zampini const PetscScalar *pa; 17163c07aadSStefano Zampini 17263c07aadSStefano Zampini PetscFunctionBegin; 173792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type); 17408401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 175792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix); 17663c07aadSStefano Zampini hdiag = hypre_ParCSRMatrixDiag(par_matrix); 17763c07aadSStefano Zampini /* 17863c07aadSStefano Zampini this is the Hack part where we monkey directly with the hypre datastructures 17963c07aadSStefano Zampini */ 1802cf14000SStefano Zampini if (sameint) { 1819566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hdiag->i, pdiag->i, A->rmap->n + 1)); 1829566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hdiag->j, pdiag->j, pdiag->nz)); 1832cf14000SStefano Zampini } else { 1842cf14000SStefano Zampini PetscInt i; 1852cf14000SStefano Zampini 1862cf14000SStefano Zampini for (i = 0; i < A->rmap->n + 1; i++) hdiag->i[i] = (HYPRE_Int)pdiag->i[i]; 1872cf14000SStefano Zampini for (i = 0; i < pdiag->nz; i++) hdiag->j[i] = (HYPRE_Int)pdiag->j[i]; 1882cf14000SStefano Zampini } 1896ea7df73SStefano Zampini 1909566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(A, &pa)); 1919566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hdiag->data, pa, pdiag->nz)); 1929566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(A, &pa)); 193ea9daf28SStefano Zampini 194ea9daf28SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij); 19563c07aadSStefano Zampini hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0; 19663c07aadSStefano Zampini PetscFunctionReturn(0); 19763c07aadSStefano Zampini } 19863c07aadSStefano Zampini 1999371c9d4SSatish Balay static PetscErrorCode MatHYPRE_IJMatrixFastCopy_MPIAIJ(Mat A, HYPRE_IJMatrix ij) { 20063c07aadSStefano Zampini Mat_MPIAIJ *pA = (Mat_MPIAIJ *)A->data; 20163c07aadSStefano Zampini Mat_SeqAIJ *pdiag, *poffd; 20263c07aadSStefano Zampini PetscInt i, *garray = pA->garray, *jj, cstart, *pjj; 2032cf14000SStefano Zampini HYPRE_Int *hjj, type; 20463c07aadSStefano Zampini hypre_ParCSRMatrix *par_matrix; 20563c07aadSStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 20663c07aadSStefano Zampini hypre_CSRMatrix *hdiag, *hoffd; 2072cf14000SStefano Zampini PetscBool sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int)); 2086ea7df73SStefano Zampini const PetscScalar *pa; 20963c07aadSStefano Zampini 21063c07aadSStefano Zampini PetscFunctionBegin; 21163c07aadSStefano Zampini pdiag = (Mat_SeqAIJ *)pA->A->data; 21263c07aadSStefano Zampini poffd = (Mat_SeqAIJ *)pA->B->data; 21363c07aadSStefano Zampini /* cstart is only valid for square MPIAIJ layed out in the usual way */ 2149566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &cstart, NULL)); 21563c07aadSStefano Zampini 216792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type); 21708401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 218792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix); 21963c07aadSStefano Zampini hdiag = hypre_ParCSRMatrixDiag(par_matrix); 22063c07aadSStefano Zampini hoffd = hypre_ParCSRMatrixOffd(par_matrix); 22163c07aadSStefano Zampini 22263c07aadSStefano Zampini /* 22363c07aadSStefano Zampini this is the Hack part where we monkey directly with the hypre datastructures 22463c07aadSStefano Zampini */ 2252cf14000SStefano Zampini if (sameint) { 2269566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hdiag->i, pdiag->i, pA->A->rmap->n + 1)); 2272cf14000SStefano Zampini } else { 2282cf14000SStefano Zampini for (i = 0; i < pA->A->rmap->n + 1; i++) hdiag->i[i] = (HYPRE_Int)(pdiag->i[i]); 2292cf14000SStefano Zampini } 23063c07aadSStefano Zampini /* need to shift the diag column indices (hdiag->j) back to global numbering since hypre is expecting this */ 2312cf14000SStefano Zampini hjj = hdiag->j; 2322cf14000SStefano Zampini pjj = pdiag->j; 233c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0) 2342cf14000SStefano Zampini for (i = 0; i < pdiag->nz; i++) hjj[i] = pjj[i]; 235c6698e78SStefano Zampini #else 2362cf14000SStefano Zampini for (i = 0; i < pdiag->nz; i++) hjj[i] = cstart + pjj[i]; 237c6698e78SStefano Zampini #endif 2389566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(pA->A, &pa)); 2399566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hdiag->data, pa, pdiag->nz)); 2409566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(pA->A, &pa)); 2412cf14000SStefano Zampini if (sameint) { 2429566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hoffd->i, poffd->i, pA->A->rmap->n + 1)); 2432cf14000SStefano Zampini } else { 2442cf14000SStefano Zampini for (i = 0; i < pA->A->rmap->n + 1; i++) hoffd->i[i] = (HYPRE_Int)(poffd->i[i]); 2452cf14000SStefano Zampini } 2462cf14000SStefano Zampini 24763c07aadSStefano Zampini /* need to move the offd column indices (hoffd->j) back to global numbering since hypre is expecting this 24863c07aadSStefano Zampini If we hacked a hypre a bit more we might be able to avoid this step */ 249c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0) 250792fecdfSBarry Smith PetscCallExternal(hypre_CSRMatrixBigInitialize, hoffd); 251c6698e78SStefano Zampini jj = (PetscInt *)hoffd->big_j; 252c6698e78SStefano Zampini #else 25363c07aadSStefano Zampini jj = (PetscInt *)hoffd->j; 254c6698e78SStefano Zampini #endif 2552cf14000SStefano Zampini pjj = poffd->j; 25663c07aadSStefano Zampini for (i = 0; i < poffd->nz; i++) jj[i] = garray[pjj[i]]; 257c6698e78SStefano Zampini 2589566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArrayRead(pA->B, &pa)); 2599566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hoffd->data, pa, poffd->nz)); 2609566063dSJacob Faibussowitsch PetscCall(MatSeqAIJRestoreArrayRead(pA->B, &pa)); 26163c07aadSStefano Zampini 262ea9daf28SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij); 26363c07aadSStefano Zampini hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0; 26463c07aadSStefano Zampini PetscFunctionReturn(0); 26563c07aadSStefano Zampini } 26663c07aadSStefano Zampini 2679371c9d4SSatish Balay static PetscErrorCode MatConvert_HYPRE_IS(Mat A, MatType mtype, MatReuse reuse, Mat *B) { 2682df22349SStefano Zampini Mat_HYPRE *mhA = (Mat_HYPRE *)(A->data); 2692df22349SStefano Zampini Mat lA; 2702df22349SStefano Zampini ISLocalToGlobalMapping rl2g, cl2g; 2712df22349SStefano Zampini IS is; 2722df22349SStefano Zampini hypre_ParCSRMatrix *hA; 2732df22349SStefano Zampini hypre_CSRMatrix *hdiag, *hoffd; 2742df22349SStefano Zampini MPI_Comm comm; 27539accc25SStefano Zampini HYPRE_Complex *hdd, *hod, *aa; 27639accc25SStefano Zampini PetscScalar *data; 2772cf14000SStefano Zampini HYPRE_BigInt *col_map_offd; 2782cf14000SStefano Zampini HYPRE_Int *hdi, *hdj, *hoi, *hoj; 2792df22349SStefano Zampini PetscInt *ii, *jj, *iptr, *jptr; 2802df22349SStefano Zampini PetscInt cum, dr, dc, oc, str, stc, nnz, i, jd, jo, M, N; 28158968eb6SStefano Zampini HYPRE_Int type; 2822df22349SStefano Zampini 2832df22349SStefano Zampini PetscFunctionBegin; 284a1787963SStefano Zampini comm = PetscObjectComm((PetscObject)A); 285792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, mhA->ij, &type); 28608401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 287792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, mhA->ij, (void **)&hA); 2882df22349SStefano Zampini M = hypre_ParCSRMatrixGlobalNumRows(hA); 2892df22349SStefano Zampini N = hypre_ParCSRMatrixGlobalNumCols(hA); 2902df22349SStefano Zampini str = hypre_ParCSRMatrixFirstRowIndex(hA); 2912df22349SStefano Zampini stc = hypre_ParCSRMatrixFirstColDiag(hA); 2922df22349SStefano Zampini hdiag = hypre_ParCSRMatrixDiag(hA); 2932df22349SStefano Zampini hoffd = hypre_ParCSRMatrixOffd(hA); 2942df22349SStefano Zampini dr = hypre_CSRMatrixNumRows(hdiag); 2952df22349SStefano Zampini dc = hypre_CSRMatrixNumCols(hdiag); 2962df22349SStefano Zampini nnz = hypre_CSRMatrixNumNonzeros(hdiag); 2972df22349SStefano Zampini hdi = hypre_CSRMatrixI(hdiag); 2982df22349SStefano Zampini hdj = hypre_CSRMatrixJ(hdiag); 2992df22349SStefano Zampini hdd = hypre_CSRMatrixData(hdiag); 3002df22349SStefano Zampini oc = hypre_CSRMatrixNumCols(hoffd); 3012df22349SStefano Zampini nnz += hypre_CSRMatrixNumNonzeros(hoffd); 3022df22349SStefano Zampini hoi = hypre_CSRMatrixI(hoffd); 3032df22349SStefano Zampini hoj = hypre_CSRMatrixJ(hoffd); 3042df22349SStefano Zampini hod = hypre_CSRMatrixData(hoffd); 3052df22349SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 3062df22349SStefano Zampini PetscInt *aux; 3072df22349SStefano Zampini 3082df22349SStefano Zampini /* generate l2g maps for rows and cols */ 3099566063dSJacob Faibussowitsch PetscCall(ISCreateStride(comm, dr, str, 1, &is)); 3109566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g)); 3119566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3122df22349SStefano Zampini col_map_offd = hypre_ParCSRMatrixColMapOffd(hA); 3139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dc + oc, &aux)); 3142df22349SStefano Zampini for (i = 0; i < dc; i++) aux[i] = i + stc; 3152df22349SStefano Zampini for (i = 0; i < oc; i++) aux[i + dc] = col_map_offd[i]; 3169566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, dc + oc, aux, PETSC_OWN_POINTER, &is)); 3179566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g)); 3189566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3192df22349SStefano Zampini /* create MATIS object */ 3209566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, B)); 3219566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, dr, dc, M, N)); 3229566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, MATIS)); 3239566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*B, rl2g, cl2g)); 3249566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 3259566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 3262df22349SStefano Zampini 3272df22349SStefano Zampini /* allocate CSR for local matrix */ 3289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dr + 1, &iptr)); 3299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &jptr)); 3309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &data)); 3312df22349SStefano Zampini } else { 3322df22349SStefano Zampini PetscInt nr; 3332df22349SStefano Zampini PetscBool done; 3349566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*B, &lA)); 3359566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lA, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&iptr, (const PetscInt **)&jptr, &done)); 33608401ef6SPierre Jolivet PetscCheck(nr == dr, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of rows in local mat! %" PetscInt_FMT " != %" PetscInt_FMT, nr, dr); 33708401ef6SPierre Jolivet PetscCheck(iptr[nr] >= nnz, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of nonzeros in local mat! reuse %" PetscInt_FMT " requested %" PetscInt_FMT, iptr[nr], nnz); 3389566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(lA, &data)); 3392df22349SStefano Zampini } 3402df22349SStefano Zampini /* merge local matrices */ 3412df22349SStefano Zampini ii = iptr; 3422df22349SStefano Zampini jj = jptr; 34339accc25SStefano Zampini aa = (HYPRE_Complex *)data; /* this cast fixes the clang error when doing the assignments below: implicit conversion from 'HYPRE_Complex' (aka '_Complex double') to 'double' is not permitted in C++ */ 3442df22349SStefano Zampini *ii = *(hdi++) + *(hoi++); 3452df22349SStefano Zampini for (jd = 0, jo = 0, cum = 0; *ii < nnz; cum++) { 34639accc25SStefano Zampini PetscScalar *aold = (PetscScalar *)aa; 3472df22349SStefano Zampini PetscInt *jold = jj, nc = jd + jo; 3489371c9d4SSatish Balay for (; jd < *hdi; jd++) { 3499371c9d4SSatish Balay *jj++ = *hdj++; 3509371c9d4SSatish Balay *aa++ = *hdd++; 3519371c9d4SSatish Balay } 3529371c9d4SSatish Balay for (; jo < *hoi; jo++) { 3539371c9d4SSatish Balay *jj++ = *hoj++ + dc; 3549371c9d4SSatish Balay *aa++ = *hod++; 3559371c9d4SSatish Balay } 3562df22349SStefano Zampini *(++ii) = *(hdi++) + *(hoi++); 3579566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithScalarArray(jd + jo - nc, jold, aold)); 3582df22349SStefano Zampini } 3592df22349SStefano Zampini for (; cum < dr; cum++) *(++ii) = nnz; 3602df22349SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 361a033916dSStefano Zampini Mat_SeqAIJ *a; 362a033916dSStefano Zampini 3639566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, dr, dc + oc, iptr, jptr, data, &lA)); 3649566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*B, lA)); 365a033916dSStefano Zampini /* hack SeqAIJ */ 366a033916dSStefano Zampini a = (Mat_SeqAIJ *)(lA->data); 367a033916dSStefano Zampini a->free_a = PETSC_TRUE; 368a033916dSStefano Zampini a->free_ij = PETSC_TRUE; 3699566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lA)); 3702df22349SStefano Zampini } 3719566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY)); 3729566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY)); 37348a46eb9SPierre Jolivet if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, B)); 3742df22349SStefano Zampini PetscFunctionReturn(0); 3752df22349SStefano Zampini } 3762df22349SStefano Zampini 3779371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType type, MatReuse reuse, Mat *B) { 37884d4e069SStefano Zampini Mat M = NULL; 37963c07aadSStefano Zampini Mat_HYPRE *hB; 38063c07aadSStefano Zampini MPI_Comm comm = PetscObjectComm((PetscObject)A); 38163c07aadSStefano Zampini 38263c07aadSStefano Zampini PetscFunctionBegin; 38363c07aadSStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 38463c07aadSStefano Zampini /* always destroy the old matrix and create a new memory; 38563c07aadSStefano Zampini hope this does not churn the memory too much. The problem 38663c07aadSStefano Zampini is I do not know if it is possible to put the matrix back to 38763c07aadSStefano Zampini its initial state so that we can directly copy the values 38863c07aadSStefano Zampini the second time through. */ 38963c07aadSStefano Zampini hB = (Mat_HYPRE *)((*B)->data); 390792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixDestroy, hB->ij); 39163c07aadSStefano Zampini } else { 3929566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &M)); 3939566063dSJacob Faibussowitsch PetscCall(MatSetType(M, MATHYPRE)); 3949566063dSJacob Faibussowitsch PetscCall(MatSetSizes(M, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N)); 39584d4e069SStefano Zampini hB = (Mat_HYPRE *)(M->data); 39684d4e069SStefano Zampini if (reuse == MAT_INITIAL_MATRIX) *B = M; 39763c07aadSStefano Zampini } 3989566063dSJacob Faibussowitsch PetscCall(MatSetOption(*B, MAT_SORTED_FULL, PETSC_TRUE)); /* "perfect" preallocation, so no need for hypre_AuxParCSRMatrixNeedAux */ 3999566063dSJacob Faibussowitsch PetscCall(MatSetOption(*B, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE)); 4009566063dSJacob Faibussowitsch PetscCall(MatHYPRE_CreateFromMat(A, hB)); 4019566063dSJacob Faibussowitsch PetscCall(MatHYPRE_IJMatrixCopy(A, hB->ij)); 40248a46eb9SPierre Jolivet if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &M)); 4034ec6421dSstefano_zampini (*B)->preallocated = PETSC_TRUE; 4049566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY)); 4059566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY)); 40663c07aadSStefano Zampini PetscFunctionReturn(0); 40763c07aadSStefano Zampini } 40863c07aadSStefano Zampini 4099371c9d4SSatish Balay static PetscErrorCode MatConvert_HYPRE_AIJ(Mat A, MatType mtype, MatReuse reuse, Mat *B) { 41063c07aadSStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 41163c07aadSStefano Zampini hypre_ParCSRMatrix *parcsr; 41263c07aadSStefano Zampini hypre_CSRMatrix *hdiag, *hoffd; 41363c07aadSStefano Zampini MPI_Comm comm; 41463c07aadSStefano Zampini PetscScalar *da, *oa, *aptr; 41563c07aadSStefano Zampini PetscInt *dii, *djj, *oii, *ojj, *iptr; 41663c07aadSStefano Zampini PetscInt i, dnnz, onnz, m, n; 41758968eb6SStefano Zampini HYPRE_Int type; 41863c07aadSStefano Zampini PetscMPIInt size; 4192cf14000SStefano Zampini PetscBool sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int)); 42063c07aadSStefano Zampini 42163c07aadSStefano Zampini PetscFunctionBegin; 42263c07aadSStefano Zampini comm = PetscObjectComm((PetscObject)A); 423792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type); 42408401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 42563c07aadSStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 42663c07aadSStefano Zampini PetscBool ismpiaij, isseqaij; 4279566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATMPIAIJ, &ismpiaij)); 4289566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATSEQAIJ, &isseqaij)); 42908401ef6SPierre Jolivet PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Only MATMPIAIJ or MATSEQAIJ are supported"); 43063c07aadSStefano Zampini } 4316ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 43208401ef6SPierre Jolivet PetscCheck(HYPRE_MEMORY_DEVICE != hypre_IJMatrixMemoryLocation(hA->ij), comm, PETSC_ERR_SUP, "Not yet implemented"); 4336ea7df73SStefano Zampini #endif 4349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 43563c07aadSStefano Zampini 436792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr); 43763c07aadSStefano Zampini hdiag = hypre_ParCSRMatrixDiag(parcsr); 43863c07aadSStefano Zampini hoffd = hypre_ParCSRMatrixOffd(parcsr); 43963c07aadSStefano Zampini m = hypre_CSRMatrixNumRows(hdiag); 44063c07aadSStefano Zampini n = hypre_CSRMatrixNumCols(hdiag); 44163c07aadSStefano Zampini dnnz = hypre_CSRMatrixNumNonzeros(hdiag); 44263c07aadSStefano Zampini onnz = hypre_CSRMatrixNumNonzeros(hoffd); 443225daaf8SStefano Zampini if (reuse == MAT_INITIAL_MATRIX) { 4449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &dii)); 4459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dnnz, &djj)); 4469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dnnz, &da)); 447225daaf8SStefano Zampini } else if (reuse == MAT_REUSE_MATRIX) { 44863c07aadSStefano Zampini PetscInt nr; 44963c07aadSStefano Zampini PetscBool done; 45063c07aadSStefano Zampini if (size > 1) { 45163c07aadSStefano Zampini Mat_MPIAIJ *b = (Mat_MPIAIJ *)((*B)->data); 45263c07aadSStefano Zampini 4539566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(b->A, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&dii, (const PetscInt **)&djj, &done)); 45408401ef6SPierre Jolivet PetscCheck(nr == m, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of local rows in diag part! %" PetscInt_FMT " != %" PetscInt_FMT, nr, m); 45508401ef6SPierre Jolivet PetscCheck(dii[nr] >= dnnz, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of nonzeros in diag part! reuse %" PetscInt_FMT " hypre %" PetscInt_FMT, dii[nr], dnnz); 4569566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(b->A, &da)); 45763c07aadSStefano Zampini } else { 4589566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(*B, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&dii, (const PetscInt **)&djj, &done)); 45908401ef6SPierre Jolivet PetscCheck(nr == m, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of local rows! %" PetscInt_FMT " != %" PetscInt_FMT, nr, m); 46008401ef6SPierre Jolivet PetscCheck(dii[nr] >= dnnz, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of nonzeros! reuse %" PetscInt_FMT " hypre %" PetscInt_FMT, dii[nr], dnnz); 4619566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(*B, &da)); 46263c07aadSStefano Zampini } 463225daaf8SStefano Zampini } else { /* MAT_INPLACE_MATRIX */ 4642cf14000SStefano Zampini if (!sameint) { 4659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &dii)); 4669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dnnz, &djj)); 4672cf14000SStefano Zampini } else { 4687d968826Sstefano_zampini dii = (PetscInt *)hypre_CSRMatrixI(hdiag); 4697d968826Sstefano_zampini djj = (PetscInt *)hypre_CSRMatrixJ(hdiag); 47063c07aadSStefano Zampini } 47139accc25SStefano Zampini da = (PetscScalar *)hypre_CSRMatrixData(hdiag); 47263c07aadSStefano Zampini } 4732cf14000SStefano Zampini 4742cf14000SStefano Zampini if (!sameint) { 4759371c9d4SSatish Balay if (reuse != MAT_REUSE_MATRIX) { 4769371c9d4SSatish Balay for (i = 0; i < m + 1; i++) dii[i] = (PetscInt)(hypre_CSRMatrixI(hdiag)[i]); 4779371c9d4SSatish Balay } 4782cf14000SStefano Zampini for (i = 0; i < dnnz; i++) djj[i] = (PetscInt)(hypre_CSRMatrixJ(hdiag)[i]); 4792cf14000SStefano Zampini } else { 4809566063dSJacob Faibussowitsch if (reuse != MAT_REUSE_MATRIX) PetscCall(PetscArraycpy(dii, hypre_CSRMatrixI(hdiag), m + 1)); 4819566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(djj, hypre_CSRMatrixJ(hdiag), dnnz)); 4822cf14000SStefano Zampini } 4839566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(da, hypre_CSRMatrixData(hdiag), dnnz)); 48463c07aadSStefano Zampini iptr = djj; 48563c07aadSStefano Zampini aptr = da; 48663c07aadSStefano Zampini for (i = 0; i < m; i++) { 48763c07aadSStefano Zampini PetscInt nc = dii[i + 1] - dii[i]; 4889566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithScalarArray(nc, iptr, aptr)); 48963c07aadSStefano Zampini iptr += nc; 49063c07aadSStefano Zampini aptr += nc; 49163c07aadSStefano Zampini } 49263c07aadSStefano Zampini if (size > 1) { 4932cf14000SStefano Zampini HYPRE_BigInt *coffd; 4942cf14000SStefano Zampini HYPRE_Int *offdj; 49563c07aadSStefano Zampini 496225daaf8SStefano Zampini if (reuse == MAT_INITIAL_MATRIX) { 4979566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &oii)); 4989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(onnz, &ojj)); 4999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(onnz, &oa)); 500225daaf8SStefano Zampini } else if (reuse == MAT_REUSE_MATRIX) { 50163c07aadSStefano Zampini Mat_MPIAIJ *b = (Mat_MPIAIJ *)((*B)->data); 50263c07aadSStefano Zampini PetscInt nr, hr = hypre_CSRMatrixNumRows(hoffd); 50363c07aadSStefano Zampini PetscBool done; 50463c07aadSStefano Zampini 5059566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(b->B, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&oii, (const PetscInt **)&ojj, &done)); 50608401ef6SPierre Jolivet PetscCheck(nr == hr, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of local rows in offdiag part! %" PetscInt_FMT " != %" PetscInt_FMT, nr, hr); 50708401ef6SPierre Jolivet PetscCheck(oii[nr] >= onnz, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of nonzeros in offdiag part! reuse %" PetscInt_FMT " hypre %" PetscInt_FMT, oii[nr], onnz); 5089566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(b->B, &oa)); 509225daaf8SStefano Zampini } else { /* MAT_INPLACE_MATRIX */ 5102cf14000SStefano Zampini if (!sameint) { 5119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &oii)); 5129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(onnz, &ojj)); 5132cf14000SStefano Zampini } else { 5147d968826Sstefano_zampini oii = (PetscInt *)hypre_CSRMatrixI(hoffd); 5157d968826Sstefano_zampini ojj = (PetscInt *)hypre_CSRMatrixJ(hoffd); 51663c07aadSStefano Zampini } 51739accc25SStefano Zampini oa = (PetscScalar *)hypre_CSRMatrixData(hoffd); 51863c07aadSStefano Zampini } 519a16187a7SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 5202cf14000SStefano Zampini if (!sameint) { 5212cf14000SStefano Zampini for (i = 0; i < m + 1; i++) oii[i] = (PetscInt)(hypre_CSRMatrixI(hoffd)[i]); 5222cf14000SStefano Zampini } else { 5239566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(oii, hypre_CSRMatrixI(hoffd), m + 1)); 5242cf14000SStefano Zampini } 525a16187a7SStefano Zampini } 5269566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(oa, hypre_CSRMatrixData(hoffd), onnz)); 527a16187a7SStefano Zampini 52863c07aadSStefano Zampini offdj = hypre_CSRMatrixJ(hoffd); 52963c07aadSStefano Zampini coffd = hypre_ParCSRMatrixColMapOffd(parcsr); 530a16187a7SStefano Zampini /* we only need the permutation to be computed properly, I don't know if HYPRE 531a16187a7SStefano Zampini messes up with the ordering. Just in case, allocate some memory and free it 532a16187a7SStefano Zampini later */ 533a16187a7SStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 534a16187a7SStefano Zampini Mat_MPIAIJ *b = (Mat_MPIAIJ *)((*B)->data); 535a16187a7SStefano Zampini PetscInt mnz; 536a16187a7SStefano Zampini 5379566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetMaxRowNonzeros(b->B, &mnz)); 5389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mnz, &ojj)); 5399371c9d4SSatish Balay } else 5409371c9d4SSatish Balay for (i = 0; i < onnz; i++) ojj[i] = coffd[offdj[i]]; 54163c07aadSStefano Zampini iptr = ojj; 54263c07aadSStefano Zampini aptr = oa; 54363c07aadSStefano Zampini for (i = 0; i < m; i++) { 54463c07aadSStefano Zampini PetscInt nc = oii[i + 1] - oii[i]; 545a16187a7SStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 546a16187a7SStefano Zampini PetscInt j; 547a16187a7SStefano Zampini 548a16187a7SStefano Zampini iptr = ojj; 549a16187a7SStefano Zampini for (j = 0; j < nc; j++) iptr[j] = coffd[offdj[oii[i] + j]]; 550a16187a7SStefano Zampini } 5519566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithScalarArray(nc, iptr, aptr)); 55263c07aadSStefano Zampini iptr += nc; 55363c07aadSStefano Zampini aptr += nc; 55463c07aadSStefano Zampini } 5559566063dSJacob Faibussowitsch if (reuse == MAT_REUSE_MATRIX) PetscCall(PetscFree(ojj)); 556225daaf8SStefano Zampini if (reuse == MAT_INITIAL_MATRIX) { 55763c07aadSStefano Zampini Mat_MPIAIJ *b; 55863c07aadSStefano Zampini Mat_SeqAIJ *d, *o; 559225daaf8SStefano Zampini 5609566063dSJacob Faibussowitsch PetscCall(MatCreateMPIAIJWithSplitArrays(comm, m, n, PETSC_DECIDE, PETSC_DECIDE, dii, djj, da, oii, ojj, oa, B)); 56163c07aadSStefano Zampini /* hack MPIAIJ */ 56263c07aadSStefano Zampini b = (Mat_MPIAIJ *)((*B)->data); 56363c07aadSStefano Zampini d = (Mat_SeqAIJ *)b->A->data; 56463c07aadSStefano Zampini o = (Mat_SeqAIJ *)b->B->data; 56563c07aadSStefano Zampini d->free_a = PETSC_TRUE; 56663c07aadSStefano Zampini d->free_ij = PETSC_TRUE; 56763c07aadSStefano Zampini o->free_a = PETSC_TRUE; 56863c07aadSStefano Zampini o->free_ij = PETSC_TRUE; 569225daaf8SStefano Zampini } else if (reuse == MAT_INPLACE_MATRIX) { 570225daaf8SStefano Zampini Mat T; 5712cf14000SStefano Zampini 5729566063dSJacob Faibussowitsch PetscCall(MatCreateMPIAIJWithSplitArrays(comm, m, n, PETSC_DECIDE, PETSC_DECIDE, dii, djj, da, oii, ojj, oa, &T)); 5732cf14000SStefano Zampini if (sameint) { /* ownership of CSR pointers is transferred to PETSc */ 574225daaf8SStefano Zampini hypre_CSRMatrixI(hdiag) = NULL; 575225daaf8SStefano Zampini hypre_CSRMatrixJ(hdiag) = NULL; 576225daaf8SStefano Zampini hypre_CSRMatrixI(hoffd) = NULL; 577225daaf8SStefano Zampini hypre_CSRMatrixJ(hoffd) = NULL; 5782cf14000SStefano Zampini } else { /* Hack MPIAIJ -> free ij but not a */ 5792cf14000SStefano Zampini Mat_MPIAIJ *b = (Mat_MPIAIJ *)(T->data); 5802cf14000SStefano Zampini Mat_SeqAIJ *d = (Mat_SeqAIJ *)(b->A->data); 5812cf14000SStefano Zampini Mat_SeqAIJ *o = (Mat_SeqAIJ *)(b->B->data); 5822cf14000SStefano Zampini 5832cf14000SStefano Zampini d->free_ij = PETSC_TRUE; 5842cf14000SStefano Zampini o->free_ij = PETSC_TRUE; 5852cf14000SStefano Zampini } 5862cf14000SStefano Zampini hypre_CSRMatrixData(hdiag) = NULL; 587225daaf8SStefano Zampini hypre_CSRMatrixData(hoffd) = NULL; 5889566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &T)); 58963c07aadSStefano Zampini } 590225daaf8SStefano Zampini } else { 591225daaf8SStefano Zampini oii = NULL; 592225daaf8SStefano Zampini ojj = NULL; 593225daaf8SStefano Zampini oa = NULL; 594225daaf8SStefano Zampini if (reuse == MAT_INITIAL_MATRIX) { 59563c07aadSStefano Zampini Mat_SeqAIJ *b; 5962cf14000SStefano Zampini 5979566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(comm, m, n, dii, djj, da, B)); 59863c07aadSStefano Zampini /* hack SeqAIJ */ 59963c07aadSStefano Zampini b = (Mat_SeqAIJ *)((*B)->data); 60063c07aadSStefano Zampini b->free_a = PETSC_TRUE; 60163c07aadSStefano Zampini b->free_ij = PETSC_TRUE; 602225daaf8SStefano Zampini } else if (reuse == MAT_INPLACE_MATRIX) { 603225daaf8SStefano Zampini Mat T; 6042cf14000SStefano Zampini 6059566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(comm, m, n, dii, djj, da, &T)); 6062cf14000SStefano Zampini if (sameint) { /* ownership of CSR pointers is transferred to PETSc */ 607225daaf8SStefano Zampini hypre_CSRMatrixI(hdiag) = NULL; 608225daaf8SStefano Zampini hypre_CSRMatrixJ(hdiag) = NULL; 6092cf14000SStefano Zampini } else { /* free ij but not a */ 6102cf14000SStefano Zampini Mat_SeqAIJ *b = (Mat_SeqAIJ *)(T->data); 6112cf14000SStefano Zampini 6122cf14000SStefano Zampini b->free_ij = PETSC_TRUE; 6132cf14000SStefano Zampini } 614225daaf8SStefano Zampini hypre_CSRMatrixData(hdiag) = NULL; 6159566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &T)); 61663c07aadSStefano Zampini } 617225daaf8SStefano Zampini } 618225daaf8SStefano Zampini 6192cf14000SStefano Zampini /* we have to use hypre_Tfree to free the HYPRE arrays 6202cf14000SStefano Zampini that PETSc now onws */ 62163c07aadSStefano Zampini if (reuse == MAT_INPLACE_MATRIX) { 6222cf14000SStefano Zampini PetscInt nh; 6232cf14000SStefano Zampini void *ptrs[6] = {da, oa, dii, djj, oii, ojj}; 6249371c9d4SSatish Balay const char *names[6] = {"_hypre_csr_da", "_hypre_csr_oa", "_hypre_csr_dii", "_hypre_csr_djj", "_hypre_csr_oii", "_hypre_csr_ojj"}; 6252cf14000SStefano Zampini nh = sameint ? 6 : 2; 6262cf14000SStefano Zampini for (i = 0; i < nh; i++) { 627225daaf8SStefano Zampini PetscContainer c; 628225daaf8SStefano Zampini 6299566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(comm, &c)); 6309566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(c, ptrs[i])); 6319566063dSJacob Faibussowitsch PetscCall(PetscContainerSetUserDestroy(c, hypre_array_destroy)); 6329566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)(*B), names[i], (PetscObject)c)); 6339566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&c)); 634225daaf8SStefano Zampini } 63563c07aadSStefano Zampini } 63663c07aadSStefano Zampini PetscFunctionReturn(0); 63763c07aadSStefano Zampini } 63863c07aadSStefano Zampini 6399371c9d4SSatish Balay static PetscErrorCode MatAIJGetParCSR_Private(Mat A, hypre_ParCSRMatrix **hA) { 640613e5ff0Sstefano_zampini hypre_ParCSRMatrix *tA; 641c1a070e6SStefano Zampini hypre_CSRMatrix *hdiag, *hoffd; 642c1a070e6SStefano Zampini Mat_SeqAIJ *diag, *offd; 6432cf14000SStefano Zampini PetscInt *garray, i, noffd, dnnz, onnz, *row_starts, *col_starts; 644c1a070e6SStefano Zampini MPI_Comm comm = PetscObjectComm((PetscObject)A); 645613e5ff0Sstefano_zampini PetscBool ismpiaij, isseqaij; 6462cf14000SStefano Zampini PetscBool sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int)); 6476ea7df73SStefano Zampini HYPRE_Int *hdi = NULL, *hdj = NULL, *hoi = NULL, *hoj = NULL; 6485c97c10fSStefano Zampini PetscInt *pdi = NULL, *pdj = NULL, *poi = NULL, *poj = NULL; 6496ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 6506ea7df73SStefano Zampini PetscBool iscuda = PETSC_FALSE; 6516ea7df73SStefano Zampini #endif 652c1a070e6SStefano Zampini 653c1a070e6SStefano Zampini PetscFunctionBegin; 6549566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 6559566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isseqaij)); 65608401ef6SPierre Jolivet PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Unsupported type %s", ((PetscObject)A)->type_name); 657c1a070e6SStefano Zampini if (ismpiaij) { 658c1a070e6SStefano Zampini Mat_MPIAIJ *a = (Mat_MPIAIJ *)(A->data); 659c1a070e6SStefano Zampini 660c1a070e6SStefano Zampini diag = (Mat_SeqAIJ *)a->A->data; 661c1a070e6SStefano Zampini offd = (Mat_SeqAIJ *)a->B->data; 6626ea7df73SStefano Zampini #if defined(PETSC_HAVE_CUDA) && defined(PETSC_HAVE_HYPRE_DEVICE) && defined(HYPRE_USING_CUDA) 6639566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMPIAIJCUSPARSE, &iscuda)); 6646ea7df73SStefano Zampini if (iscuda && !A->boundtocpu) { 6656ea7df73SStefano Zampini sameint = PETSC_TRUE; 6669566063dSJacob Faibussowitsch PetscCall(MatSeqAIJCUSPARSEGetIJ(a->A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj)); 6679566063dSJacob Faibussowitsch PetscCall(MatSeqAIJCUSPARSEGetIJ(a->B, PETSC_FALSE, (const HYPRE_Int **)&hoi, (const HYPRE_Int **)&hoj)); 6686ea7df73SStefano Zampini } else { 6696ea7df73SStefano Zampini #else 6706ea7df73SStefano Zampini { 6716ea7df73SStefano Zampini #endif 6726ea7df73SStefano Zampini pdi = diag->i; 6736ea7df73SStefano Zampini pdj = diag->j; 6746ea7df73SStefano Zampini poi = offd->i; 6756ea7df73SStefano Zampini poj = offd->j; 6766ea7df73SStefano Zampini if (sameint) { 6776ea7df73SStefano Zampini hdi = (HYPRE_Int *)pdi; 6786ea7df73SStefano Zampini hdj = (HYPRE_Int *)pdj; 6796ea7df73SStefano Zampini hoi = (HYPRE_Int *)poi; 6806ea7df73SStefano Zampini hoj = (HYPRE_Int *)poj; 6816ea7df73SStefano Zampini } 6826ea7df73SStefano Zampini } 683c1a070e6SStefano Zampini garray = a->garray; 684c1a070e6SStefano Zampini noffd = a->B->cmap->N; 685c1a070e6SStefano Zampini dnnz = diag->nz; 686c1a070e6SStefano Zampini onnz = offd->nz; 687c1a070e6SStefano Zampini } else { 688c1a070e6SStefano Zampini diag = (Mat_SeqAIJ *)A->data; 689c1a070e6SStefano Zampini offd = NULL; 6906ea7df73SStefano Zampini #if defined(PETSC_HAVE_CUDA) && defined(PETSC_HAVE_HYPRE_DEVICE) 6919566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATSEQAIJCUSPARSE, &iscuda)); 6926ea7df73SStefano Zampini if (iscuda && !A->boundtocpu) { 6936ea7df73SStefano Zampini sameint = PETSC_TRUE; 6949566063dSJacob Faibussowitsch PetscCall(MatSeqAIJCUSPARSEGetIJ(A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj)); 6956ea7df73SStefano Zampini } else { 6966ea7df73SStefano Zampini #else 6976ea7df73SStefano Zampini { 6986ea7df73SStefano Zampini #endif 6996ea7df73SStefano Zampini pdi = diag->i; 7006ea7df73SStefano Zampini pdj = diag->j; 7016ea7df73SStefano Zampini if (sameint) { 7026ea7df73SStefano Zampini hdi = (HYPRE_Int *)pdi; 7036ea7df73SStefano Zampini hdj = (HYPRE_Int *)pdj; 7046ea7df73SStefano Zampini } 7056ea7df73SStefano Zampini } 706c1a070e6SStefano Zampini garray = NULL; 707c1a070e6SStefano Zampini noffd = 0; 708c1a070e6SStefano Zampini dnnz = diag->nz; 709c1a070e6SStefano Zampini onnz = 0; 710c1a070e6SStefano Zampini } 711225daaf8SStefano Zampini 712c1a070e6SStefano Zampini /* create a temporary ParCSR */ 713c1a070e6SStefano Zampini if (HYPRE_AssumedPartitionCheck()) { 714c1a070e6SStefano Zampini PetscMPIInt myid; 715c1a070e6SStefano Zampini 7169566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &myid)); 717c1a070e6SStefano Zampini row_starts = A->rmap->range + myid; 718c1a070e6SStefano Zampini col_starts = A->cmap->range + myid; 719c1a070e6SStefano Zampini } else { 720c1a070e6SStefano Zampini row_starts = A->rmap->range; 721c1a070e6SStefano Zampini col_starts = A->cmap->range; 722c1a070e6SStefano Zampini } 7232cf14000SStefano Zampini tA = hypre_ParCSRMatrixCreate(comm, A->rmap->N, A->cmap->N, (HYPRE_BigInt *)row_starts, (HYPRE_BigInt *)col_starts, noffd, dnnz, onnz); 724a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 725c1a070e6SStefano Zampini hypre_ParCSRMatrixSetRowStartsOwner(tA, 0); 726c1a070e6SStefano Zampini hypre_ParCSRMatrixSetColStartsOwner(tA, 0); 727a1d2239cSSatish Balay #endif 728c1a070e6SStefano Zampini 729225daaf8SStefano Zampini /* set diagonal part */ 730c1a070e6SStefano Zampini hdiag = hypre_ParCSRMatrixDiag(tA); 7316ea7df73SStefano Zampini if (!sameint) { /* malloc CSR pointers */ 7329566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(A->rmap->n + 1, &hdi, dnnz, &hdj)); 7336ea7df73SStefano Zampini for (i = 0; i < A->rmap->n + 1; i++) hdi[i] = (HYPRE_Int)(pdi[i]); 7346ea7df73SStefano Zampini for (i = 0; i < dnnz; i++) hdj[i] = (HYPRE_Int)(pdj[i]); 7352cf14000SStefano Zampini } 7366ea7df73SStefano Zampini hypre_CSRMatrixI(hdiag) = hdi; 7376ea7df73SStefano Zampini hypre_CSRMatrixJ(hdiag) = hdj; 73839accc25SStefano Zampini hypre_CSRMatrixData(hdiag) = (HYPRE_Complex *)diag->a; 739c1a070e6SStefano Zampini hypre_CSRMatrixNumNonzeros(hdiag) = diag->nz; 740c1a070e6SStefano Zampini hypre_CSRMatrixSetRownnz(hdiag); 741c1a070e6SStefano Zampini hypre_CSRMatrixSetDataOwner(hdiag, 0); 742c1a070e6SStefano Zampini 743225daaf8SStefano Zampini /* set offdiagonal part */ 744c1a070e6SStefano Zampini hoffd = hypre_ParCSRMatrixOffd(tA); 745c1a070e6SStefano Zampini if (offd) { 7466ea7df73SStefano Zampini if (!sameint) { /* malloc CSR pointers */ 7479566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(A->rmap->n + 1, &hoi, onnz, &hoj)); 7486ea7df73SStefano Zampini for (i = 0; i < A->rmap->n + 1; i++) hoi[i] = (HYPRE_Int)(poi[i]); 7496ea7df73SStefano Zampini for (i = 0; i < onnz; i++) hoj[i] = (HYPRE_Int)(poj[i]); 7502cf14000SStefano Zampini } 7516ea7df73SStefano Zampini hypre_CSRMatrixI(hoffd) = hoi; 7526ea7df73SStefano Zampini hypre_CSRMatrixJ(hoffd) = hoj; 75339accc25SStefano Zampini hypre_CSRMatrixData(hoffd) = (HYPRE_Complex *)offd->a; 754c1a070e6SStefano Zampini hypre_CSRMatrixNumNonzeros(hoffd) = offd->nz; 755c1a070e6SStefano Zampini hypre_CSRMatrixSetRownnz(hoffd); 756c1a070e6SStefano Zampini hypre_CSRMatrixSetDataOwner(hoffd, 0); 7576ea7df73SStefano Zampini } 7586ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 759792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, iscuda ? HYPRE_MEMORY_DEVICE : HYPRE_MEMORY_HOST); 7606ea7df73SStefano Zampini #else 7616ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0) 762792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixInitialize, tA); 7636ea7df73SStefano Zampini #else 764792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, HYPRE_MEMORY_HOST); 7656ea7df73SStefano Zampini #endif 7666ea7df73SStefano Zampini #endif 7676ea7df73SStefano Zampini hypre_TFree(hypre_ParCSRMatrixColMapOffd(tA), HYPRE_MEMORY_HOST); 768c1a070e6SStefano Zampini hypre_ParCSRMatrixSetNumNonzeros(tA); 7692cf14000SStefano Zampini hypre_ParCSRMatrixColMapOffd(tA) = (HYPRE_BigInt *)garray; 770792fecdfSBarry Smith if (!hypre_ParCSRMatrixCommPkg(tA)) PetscCallExternal(hypre_MatvecCommPkgCreate, tA); 771613e5ff0Sstefano_zampini *hA = tA; 772613e5ff0Sstefano_zampini PetscFunctionReturn(0); 773613e5ff0Sstefano_zampini } 774c1a070e6SStefano Zampini 7759371c9d4SSatish Balay static PetscErrorCode MatAIJRestoreParCSR_Private(Mat A, hypre_ParCSRMatrix **hA) { 776613e5ff0Sstefano_zampini hypre_CSRMatrix *hdiag, *hoffd; 7776ea7df73SStefano Zampini PetscBool ismpiaij, sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int)); 7786ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 7796ea7df73SStefano Zampini PetscBool iscuda = PETSC_FALSE; 7806ea7df73SStefano Zampini #endif 781c1a070e6SStefano Zampini 782613e5ff0Sstefano_zampini PetscFunctionBegin; 7839566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 7846ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 7859566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, "")); 7866ea7df73SStefano Zampini if (iscuda) sameint = PETSC_TRUE; 7876ea7df73SStefano Zampini #endif 788613e5ff0Sstefano_zampini hdiag = hypre_ParCSRMatrixDiag(*hA); 789613e5ff0Sstefano_zampini hoffd = hypre_ParCSRMatrixOffd(*hA); 7906ea7df73SStefano Zampini /* free temporary memory allocated by PETSc 7916ea7df73SStefano Zampini set pointers to NULL before destroying tA */ 7922cf14000SStefano Zampini if (!sameint) { 7932cf14000SStefano Zampini HYPRE_Int *hi, *hj; 7942cf14000SStefano Zampini 7952cf14000SStefano Zampini hi = hypre_CSRMatrixI(hdiag); 7962cf14000SStefano Zampini hj = hypre_CSRMatrixJ(hdiag); 7979566063dSJacob Faibussowitsch PetscCall(PetscFree2(hi, hj)); 7986ea7df73SStefano Zampini if (ismpiaij) { 7992cf14000SStefano Zampini hi = hypre_CSRMatrixI(hoffd); 8002cf14000SStefano Zampini hj = hypre_CSRMatrixJ(hoffd); 8019566063dSJacob Faibussowitsch PetscCall(PetscFree2(hi, hj)); 8022cf14000SStefano Zampini } 8032cf14000SStefano Zampini } 804c1a070e6SStefano Zampini hypre_CSRMatrixI(hdiag) = NULL; 805c1a070e6SStefano Zampini hypre_CSRMatrixJ(hdiag) = NULL; 806c1a070e6SStefano Zampini hypre_CSRMatrixData(hdiag) = NULL; 8076ea7df73SStefano Zampini if (ismpiaij) { 808c1a070e6SStefano Zampini hypre_CSRMatrixI(hoffd) = NULL; 809c1a070e6SStefano Zampini hypre_CSRMatrixJ(hoffd) = NULL; 810c1a070e6SStefano Zampini hypre_CSRMatrixData(hoffd) = NULL; 8116ea7df73SStefano Zampini } 812613e5ff0Sstefano_zampini hypre_ParCSRMatrixColMapOffd(*hA) = NULL; 813613e5ff0Sstefano_zampini hypre_ParCSRMatrixDestroy(*hA); 814613e5ff0Sstefano_zampini *hA = NULL; 815613e5ff0Sstefano_zampini PetscFunctionReturn(0); 816613e5ff0Sstefano_zampini } 817613e5ff0Sstefano_zampini 818613e5ff0Sstefano_zampini /* calls RAP from BoomerAMG: 8193dad0653Sstefano_zampini the resulting ParCSR will not own the column and row starts 8206ea7df73SStefano Zampini It looks like we don't need to have the diagonal entries ordered first */ 8219371c9d4SSatish Balay static PetscErrorCode MatHYPRE_ParCSR_RAP(hypre_ParCSRMatrix *hR, hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hP, hypre_ParCSRMatrix **hRAP) { 822a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 823613e5ff0Sstefano_zampini HYPRE_Int P_owns_col_starts, R_owns_row_starts; 824a1d2239cSSatish Balay #endif 825613e5ff0Sstefano_zampini 826613e5ff0Sstefano_zampini PetscFunctionBegin; 827a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 828613e5ff0Sstefano_zampini P_owns_col_starts = hypre_ParCSRMatrixOwnsColStarts(hP); 829613e5ff0Sstefano_zampini R_owns_row_starts = hypre_ParCSRMatrixOwnsRowStarts(hR); 830a1d2239cSSatish Balay #endif 8316ea7df73SStefano Zampini /* can be replaced by version test later */ 8326ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 833792fecdfSBarry Smith PetscStackPushExternal("hypre_ParCSRMatrixRAP"); 8346ea7df73SStefano Zampini *hRAP = hypre_ParCSRMatrixRAP(hR, hA, hP); 8356ea7df73SStefano Zampini PetscStackPop; 8366ea7df73SStefano Zampini #else 837792fecdfSBarry Smith PetscCallExternal(hypre_BoomerAMGBuildCoarseOperator, hR, hA, hP, hRAP); 838792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixSetNumNonzeros, *hRAP); 8396ea7df73SStefano Zampini #endif 840613e5ff0Sstefano_zampini /* hypre_BoomerAMGBuildCoarseOperator steals the col_starts from P and the row_starts from R */ 841a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 842613e5ff0Sstefano_zampini hypre_ParCSRMatrixSetRowStartsOwner(*hRAP, 0); 843613e5ff0Sstefano_zampini hypre_ParCSRMatrixSetColStartsOwner(*hRAP, 0); 844613e5ff0Sstefano_zampini if (P_owns_col_starts) hypre_ParCSRMatrixSetColStartsOwner(hP, 1); 845613e5ff0Sstefano_zampini if (R_owns_row_starts) hypre_ParCSRMatrixSetRowStartsOwner(hR, 1); 846a1d2239cSSatish Balay #endif 847613e5ff0Sstefano_zampini PetscFunctionReturn(0); 848613e5ff0Sstefano_zampini } 849613e5ff0Sstefano_zampini 8509371c9d4SSatish Balay static PetscErrorCode MatPtAPNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat P, Mat C) { 8516f231fbdSstefano_zampini Mat B; 8526abb4441SStefano Zampini hypre_ParCSRMatrix *hA, *hP, *hPtAP = NULL; 8534222ddf1SHong Zhang Mat_Product *product = C->product; 854613e5ff0Sstefano_zampini 855613e5ff0Sstefano_zampini PetscFunctionBegin; 8569566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(A, &hA)); 8579566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(P, &hP)); 8589566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_RAP(hP, hA, hP, &hPtAP)); 8599566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(hPtAP, MATAIJ, PETSC_OWN_POINTER, &B)); 8604222ddf1SHong Zhang 8619566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(C, &B)); 8624222ddf1SHong Zhang C->product = product; 8634222ddf1SHong Zhang 8649566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(A, &hA)); 8659566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(P, &hP)); 8666f231fbdSstefano_zampini PetscFunctionReturn(0); 8676f231fbdSstefano_zampini } 8686f231fbdSstefano_zampini 8699371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatPtAPSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat P, PetscReal fill, Mat C) { 8706f231fbdSstefano_zampini PetscFunctionBegin; 8719566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATAIJ)); 8724222ddf1SHong Zhang C->ops->ptapnumeric = MatPtAPNumeric_AIJ_AIJ_wHYPRE; 8734222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_PtAP; 874613e5ff0Sstefano_zampini PetscFunctionReturn(0); 875613e5ff0Sstefano_zampini } 876613e5ff0Sstefano_zampini 8779371c9d4SSatish Balay static PetscErrorCode MatPtAPNumeric_AIJ_HYPRE(Mat A, Mat P, Mat C) { 8784cc28894Sstefano_zampini Mat B; 8794cc28894Sstefano_zampini Mat_HYPRE *hP; 8806abb4441SStefano Zampini hypre_ParCSRMatrix *hA = NULL, *Pparcsr, *ptapparcsr = NULL; 881613e5ff0Sstefano_zampini HYPRE_Int type; 882613e5ff0Sstefano_zampini MPI_Comm comm = PetscObjectComm((PetscObject)A); 8834cc28894Sstefano_zampini PetscBool ishypre; 884613e5ff0Sstefano_zampini 885613e5ff0Sstefano_zampini PetscFunctionBegin; 8869566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre)); 88728b400f6SJacob Faibussowitsch PetscCheck(ishypre, comm, PETSC_ERR_USER, "P should be of type %s", MATHYPRE); 8884cc28894Sstefano_zampini hP = (Mat_HYPRE *)P->data; 889792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type); 89008401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 891792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr); 892613e5ff0Sstefano_zampini 8939566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(A, &hA)); 8949566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, hA, Pparcsr, &ptapparcsr)); 8959566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(A, &hA)); 896225daaf8SStefano Zampini 8974cc28894Sstefano_zampini /* create temporary matrix and merge to C */ 8989566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(ptapparcsr, ((PetscObject)C)->type_name, PETSC_OWN_POINTER, &B)); 8999566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(C, &B)); 9004cc28894Sstefano_zampini PetscFunctionReturn(0); 9014cc28894Sstefano_zampini } 9024cc28894Sstefano_zampini 9039371c9d4SSatish Balay static PetscErrorCode MatPtAPNumeric_HYPRE_HYPRE(Mat A, Mat P, Mat C) { 9044cc28894Sstefano_zampini Mat B; 9056abb4441SStefano Zampini hypre_ParCSRMatrix *Aparcsr, *Pparcsr, *ptapparcsr = NULL; 9064cc28894Sstefano_zampini Mat_HYPRE *hA, *hP; 9074cc28894Sstefano_zampini PetscBool ishypre; 9084cc28894Sstefano_zampini HYPRE_Int type; 9094cc28894Sstefano_zampini 9104cc28894Sstefano_zampini PetscFunctionBegin; 9119566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre)); 91228b400f6SJacob Faibussowitsch PetscCheck(ishypre, PetscObjectComm((PetscObject)P), PETSC_ERR_USER, "P should be of type %s", MATHYPRE); 9139566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre)); 91428b400f6SJacob Faibussowitsch PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE); 9154cc28894Sstefano_zampini hA = (Mat_HYPRE *)A->data; 9164cc28894Sstefano_zampini hP = (Mat_HYPRE *)P->data; 917792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type); 91808401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 919792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type); 92008401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)P), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 921792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr); 922792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr); 9239566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, Aparcsr, Pparcsr, &ptapparcsr)); 9249566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(ptapparcsr, MATHYPRE, PETSC_OWN_POINTER, &B)); 9259566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(C, &B)); 9264cc28894Sstefano_zampini PetscFunctionReturn(0); 9274cc28894Sstefano_zampini } 9284cc28894Sstefano_zampini 929d501dc42Sstefano_zampini /* calls hypre_ParMatmul 930d501dc42Sstefano_zampini hypre_ParMatMul uses hypre_ParMatrixCreate with the communicator of hA 9313dad0653Sstefano_zampini hypre_ParMatrixCreate does not duplicate the communicator 9326ea7df73SStefano Zampini It looks like we don't need to have the diagonal entries ordered first */ 9339371c9d4SSatish Balay static PetscErrorCode MatHYPRE_ParCSR_MatMatMult(hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hB, hypre_ParCSRMatrix **hAB) { 934d501dc42Sstefano_zampini PetscFunctionBegin; 9356ea7df73SStefano Zampini /* can be replaced by version test later */ 9366ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 937792fecdfSBarry Smith PetscStackPushExternal("hypre_ParCSRMatMat"); 9386ea7df73SStefano Zampini *hAB = hypre_ParCSRMatMat(hA, hB); 9396ea7df73SStefano Zampini #else 940792fecdfSBarry Smith PetscStackPushExternal("hypre_ParMatmul"); 941d501dc42Sstefano_zampini *hAB = hypre_ParMatmul(hA, hB); 9426ea7df73SStefano Zampini #endif 943d501dc42Sstefano_zampini PetscStackPop; 944d501dc42Sstefano_zampini PetscFunctionReturn(0); 945d501dc42Sstefano_zampini } 946d501dc42Sstefano_zampini 9479371c9d4SSatish Balay static PetscErrorCode MatMatMultNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C) { 9485e5acdf2Sstefano_zampini Mat D; 949d501dc42Sstefano_zampini hypre_ParCSRMatrix *hA, *hB, *hAB = NULL; 9504222ddf1SHong Zhang Mat_Product *product = C->product; 9515e5acdf2Sstefano_zampini 9525e5acdf2Sstefano_zampini PetscFunctionBegin; 9539566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(A, &hA)); 9549566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(B, &hB)); 9559566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_MatMatMult(hA, hB, &hAB)); 9569566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(hAB, MATAIJ, PETSC_OWN_POINTER, &D)); 9574222ddf1SHong Zhang 9589566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(C, &D)); 9594222ddf1SHong Zhang C->product = product; 9604222ddf1SHong Zhang 9619566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(A, &hA)); 9629566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(B, &hB)); 9635e5acdf2Sstefano_zampini PetscFunctionReturn(0); 9645e5acdf2Sstefano_zampini } 9655e5acdf2Sstefano_zampini 9669371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatMatMultSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat B, PetscReal fill, Mat C) { 9675e5acdf2Sstefano_zampini PetscFunctionBegin; 9689566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATAIJ)); 9694222ddf1SHong Zhang C->ops->matmultnumeric = MatMatMultNumeric_AIJ_AIJ_wHYPRE; 9704222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_AB; 9715e5acdf2Sstefano_zampini PetscFunctionReturn(0); 9725e5acdf2Sstefano_zampini } 9735e5acdf2Sstefano_zampini 9749371c9d4SSatish Balay static PetscErrorCode MatMatMultNumeric_HYPRE_HYPRE(Mat A, Mat B, Mat C) { 975d501dc42Sstefano_zampini Mat D; 976d501dc42Sstefano_zampini hypre_ParCSRMatrix *Aparcsr, *Bparcsr, *ABparcsr = NULL; 977d501dc42Sstefano_zampini Mat_HYPRE *hA, *hB; 978d501dc42Sstefano_zampini PetscBool ishypre; 979d501dc42Sstefano_zampini HYPRE_Int type; 9804222ddf1SHong Zhang Mat_Product *product; 981d501dc42Sstefano_zampini 982d501dc42Sstefano_zampini PetscFunctionBegin; 9839566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)B, MATHYPRE, &ishypre)); 98428b400f6SJacob Faibussowitsch PetscCheck(ishypre, PetscObjectComm((PetscObject)B), PETSC_ERR_USER, "B should be of type %s", MATHYPRE); 9859566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre)); 98628b400f6SJacob Faibussowitsch PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE); 987d501dc42Sstefano_zampini hA = (Mat_HYPRE *)A->data; 988d501dc42Sstefano_zampini hB = (Mat_HYPRE *)B->data; 989792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type); 99008401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 991792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hB->ij, &type); 99208401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 993792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr); 994792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hB->ij, (void **)&Bparcsr); 9959566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_MatMatMult(Aparcsr, Bparcsr, &ABparcsr)); 9969566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(ABparcsr, MATHYPRE, PETSC_OWN_POINTER, &D)); 9974222ddf1SHong Zhang 998d501dc42Sstefano_zampini /* need to use HeaderReplace because HeaderMerge messes up with the communicator */ 9994222ddf1SHong Zhang product = C->product; /* save it from MatHeaderReplace() */ 10004222ddf1SHong Zhang C->product = NULL; 10019566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(C, &D)); 10024222ddf1SHong Zhang C->product = product; 1003d501dc42Sstefano_zampini C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE; 10044222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_AB; 1005d501dc42Sstefano_zampini PetscFunctionReturn(0); 1006d501dc42Sstefano_zampini } 1007d501dc42Sstefano_zampini 10089371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatTransposeMatMatMultNumeric_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, Mat D) { 100920e1dc0dSstefano_zampini Mat E; 10106abb4441SStefano Zampini hypre_ParCSRMatrix *hA, *hB, *hC, *hABC = NULL; 101120e1dc0dSstefano_zampini 101220e1dc0dSstefano_zampini PetscFunctionBegin; 10139566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(A, &hA)); 10149566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(B, &hB)); 10159566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(C, &hC)); 10169566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_RAP(hA, hB, hC, &hABC)); 10179566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(hABC, MATAIJ, PETSC_OWN_POINTER, &E)); 10189566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(D, &E)); 10199566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(A, &hA)); 10209566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(B, &hB)); 10219566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(C, &hC)); 102220e1dc0dSstefano_zampini PetscFunctionReturn(0); 102320e1dc0dSstefano_zampini } 102420e1dc0dSstefano_zampini 10259371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatTransposeMatMatMultSymbolic_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, PetscReal fill, Mat D) { 102620e1dc0dSstefano_zampini PetscFunctionBegin; 10279566063dSJacob Faibussowitsch PetscCall(MatSetType(D, MATAIJ)); 102820e1dc0dSstefano_zampini PetscFunctionReturn(0); 102920e1dc0dSstefano_zampini } 103020e1dc0dSstefano_zampini 10314222ddf1SHong Zhang /* ---------------------------------------------------- */ 10329371c9d4SSatish Balay static PetscErrorCode MatProductSymbolic_AB_HYPRE(Mat C) { 10334222ddf1SHong Zhang PetscFunctionBegin; 10344222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_AB; 10354222ddf1SHong Zhang PetscFunctionReturn(0); 10364222ddf1SHong Zhang } 10374222ddf1SHong Zhang 10389371c9d4SSatish Balay static PetscErrorCode MatProductSetFromOptions_HYPRE_AB(Mat C) { 10394222ddf1SHong Zhang Mat_Product *product = C->product; 10404222ddf1SHong Zhang PetscBool Ahypre; 10414222ddf1SHong Zhang 10424222ddf1SHong Zhang PetscFunctionBegin; 10439566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)product->A, MATHYPRE, &Ahypre)); 10444222ddf1SHong Zhang if (Ahypre) { /* A is a Hypre matrix */ 10459566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATHYPRE)); 10464222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_AB_HYPRE; 10474222ddf1SHong Zhang C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE; 10484222ddf1SHong Zhang PetscFunctionReturn(0); 10496718818eSStefano Zampini } 10504222ddf1SHong Zhang PetscFunctionReturn(0); 10514222ddf1SHong Zhang } 10524222ddf1SHong Zhang 10539371c9d4SSatish Balay static PetscErrorCode MatProductSymbolic_PtAP_HYPRE(Mat C) { 10544222ddf1SHong Zhang PetscFunctionBegin; 10554222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_PtAP; 10564222ddf1SHong Zhang PetscFunctionReturn(0); 10574222ddf1SHong Zhang } 10584222ddf1SHong Zhang 10599371c9d4SSatish Balay static PetscErrorCode MatProductSetFromOptions_HYPRE_PtAP(Mat C) { 10604222ddf1SHong Zhang Mat_Product *product = C->product; 10614222ddf1SHong Zhang PetscBool flg; 10624222ddf1SHong Zhang PetscInt type = 0; 10634222ddf1SHong Zhang const char *outTypes[4] = {"aij", "seqaij", "mpiaij", "hypre"}; 10644222ddf1SHong Zhang PetscInt ntype = 4; 10654222ddf1SHong Zhang Mat A = product->A; 10664222ddf1SHong Zhang PetscBool Ahypre; 10674222ddf1SHong Zhang 10684222ddf1SHong Zhang PetscFunctionBegin; 10699566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &Ahypre)); 10704222ddf1SHong Zhang if (Ahypre) { /* A is a Hypre matrix */ 10719566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATHYPRE)); 10724222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE; 10734222ddf1SHong Zhang C->ops->ptapnumeric = MatPtAPNumeric_HYPRE_HYPRE; 10744222ddf1SHong Zhang PetscFunctionReturn(0); 10754222ddf1SHong Zhang } 10764222ddf1SHong Zhang 10774222ddf1SHong Zhang /* A is AIJ, P is Hypre, C = PtAP can be either AIJ or Hypre format */ 10784222ddf1SHong Zhang /* Get runtime option */ 10794222ddf1SHong Zhang if (product->api_user) { 1080d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatPtAP_HYPRE", "Mat"); 10819566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-matptap_hypre_outtype", "MatPtAP outtype", "MatPtAP outtype", outTypes, ntype, outTypes[type], &type, &flg)); 1082d0609cedSBarry Smith PetscOptionsEnd(); 10834222ddf1SHong Zhang } else { 1084d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatProduct_PtAP_HYPRE", "Mat"); 10859566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-mat_product_algorithm_hypre_outtype", "MatProduct_PtAP outtype", "MatProduct_PtAP", outTypes, ntype, outTypes[type], &type, &flg)); 1086d0609cedSBarry Smith PetscOptionsEnd(); 10874222ddf1SHong Zhang } 10884222ddf1SHong Zhang 10894222ddf1SHong Zhang if (type == 0 || type == 1 || type == 2) { 10909566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATAIJ)); 10914222ddf1SHong Zhang } else if (type == 3) { 10929566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATHYPRE)); 10934222ddf1SHong Zhang } else SETERRQ(PetscObjectComm((PetscObject)C), PETSC_ERR_SUP, "MatPtAP outtype is not supported"); 10944222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE; 10954222ddf1SHong Zhang C->ops->ptapnumeric = MatPtAPNumeric_AIJ_HYPRE; 10964222ddf1SHong Zhang PetscFunctionReturn(0); 10974222ddf1SHong Zhang } 10984222ddf1SHong Zhang 10999371c9d4SSatish Balay static PetscErrorCode MatProductSetFromOptions_HYPRE(Mat C) { 11004222ddf1SHong Zhang Mat_Product *product = C->product; 11014222ddf1SHong Zhang 11024222ddf1SHong Zhang PetscFunctionBegin; 11034222ddf1SHong Zhang switch (product->type) { 11049371c9d4SSatish Balay case MATPRODUCT_AB: PetscCall(MatProductSetFromOptions_HYPRE_AB(C)); break; 11059371c9d4SSatish Balay case MATPRODUCT_PtAP: PetscCall(MatProductSetFromOptions_HYPRE_PtAP(C)); break; 11069371c9d4SSatish Balay default: break; 11074222ddf1SHong Zhang } 11084222ddf1SHong Zhang PetscFunctionReturn(0); 11094222ddf1SHong Zhang } 11104222ddf1SHong Zhang 11114222ddf1SHong Zhang /* -------------------------------------------------------- */ 11124222ddf1SHong Zhang 11139371c9d4SSatish Balay static PetscErrorCode MatMultTranspose_HYPRE(Mat A, Vec x, Vec y) { 111463c07aadSStefano Zampini PetscFunctionBegin; 11159566063dSJacob Faibussowitsch PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_TRUE)); 111663c07aadSStefano Zampini PetscFunctionReturn(0); 111763c07aadSStefano Zampini } 111863c07aadSStefano Zampini 11199371c9d4SSatish Balay static PetscErrorCode MatMult_HYPRE(Mat A, Vec x, Vec y) { 112063c07aadSStefano Zampini PetscFunctionBegin; 11219566063dSJacob Faibussowitsch PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_FALSE)); 112263c07aadSStefano Zampini PetscFunctionReturn(0); 112363c07aadSStefano Zampini } 112463c07aadSStefano Zampini 11259371c9d4SSatish Balay static PetscErrorCode MatMultAdd_HYPRE(Mat A, Vec x, Vec y, Vec z) { 1126414bd5c3SStefano Zampini PetscFunctionBegin; 112748a46eb9SPierre Jolivet if (y != z) PetscCall(VecCopy(y, z)); 11289566063dSJacob Faibussowitsch PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_FALSE)); 1129414bd5c3SStefano Zampini PetscFunctionReturn(0); 1130414bd5c3SStefano Zampini } 1131414bd5c3SStefano Zampini 11329371c9d4SSatish Balay static PetscErrorCode MatMultTransposeAdd_HYPRE(Mat A, Vec x, Vec y, Vec z) { 1133414bd5c3SStefano Zampini PetscFunctionBegin; 113448a46eb9SPierre Jolivet if (y != z) PetscCall(VecCopy(y, z)); 11359566063dSJacob Faibussowitsch PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_TRUE)); 1136414bd5c3SStefano Zampini PetscFunctionReturn(0); 1137414bd5c3SStefano Zampini } 1138414bd5c3SStefano Zampini 1139414bd5c3SStefano Zampini /* y = a * A * x + b * y or y = a * A^t * x + b * y depending on trans */ 11409371c9d4SSatish Balay static PetscErrorCode MatHYPRE_MultKernel_Private(Mat A, HYPRE_Complex a, Vec x, HYPRE_Complex b, Vec y, PetscBool trans) { 114163c07aadSStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 114263c07aadSStefano Zampini hypre_ParCSRMatrix *parcsr; 114363c07aadSStefano Zampini hypre_ParVector *hx, *hy; 114463c07aadSStefano Zampini 114563c07aadSStefano Zampini PetscFunctionBegin; 114663c07aadSStefano Zampini if (trans) { 11479566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorPushVecRead(hA->b, x)); 11489566063dSJacob Faibussowitsch if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->x, y)); 11499566063dSJacob Faibussowitsch else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->x, y)); 1150792fecdfSBarry Smith PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hx); 1151792fecdfSBarry Smith PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hy); 115263c07aadSStefano Zampini } else { 11539566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorPushVecRead(hA->x, x)); 11549566063dSJacob Faibussowitsch if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->b, y)); 11559566063dSJacob Faibussowitsch else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->b, y)); 1156792fecdfSBarry Smith PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hx); 1157792fecdfSBarry Smith PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hy); 115863c07aadSStefano Zampini } 1159792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr); 11606ea7df73SStefano Zampini if (trans) { 1161792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixMatvecT, a, parcsr, hx, b, hy); 11626ea7df73SStefano Zampini } else { 1163792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixMatvec, a, parcsr, hx, b, hy); 11646ea7df73SStefano Zampini } 11659566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorPopVec(hA->x)); 11669566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorPopVec(hA->b)); 116763c07aadSStefano Zampini PetscFunctionReturn(0); 116863c07aadSStefano Zampini } 116963c07aadSStefano Zampini 11709371c9d4SSatish Balay static PetscErrorCode MatDestroy_HYPRE(Mat A) { 117163c07aadSStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 117263c07aadSStefano Zampini 117363c07aadSStefano Zampini PetscFunctionBegin; 11749566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorDestroy(&hA->x)); 11759566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorDestroy(&hA->b)); 1176978814f1SStefano Zampini if (hA->ij) { 1177978814f1SStefano Zampini if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL; 1178792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixDestroy, hA->ij); 1179978814f1SStefano Zampini } 11809566063dSJacob Faibussowitsch if (hA->comm) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)A), &hA->comm)); 1181c69f721fSFande Kong 11829566063dSJacob Faibussowitsch PetscCall(MatStashDestroy_Private(&A->stash)); 11839566063dSJacob Faibussowitsch PetscCall(PetscFree(hA->array)); 1184c69f721fSFande Kong 11855fbaff96SJunchao Zhang if (hA->cooMat) { 11865fbaff96SJunchao Zhang PetscCall(MatDestroy(&hA->cooMat)); 1187e77caa6dSBarry Smith PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hA->diagJ, hA->memType)); 1188e77caa6dSBarry Smith PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hA->offdJ, hA->memType)); 1189e77caa6dSBarry Smith PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hA->diag, hA->memType)); 11905fbaff96SJunchao Zhang } 11915fbaff96SJunchao Zhang 11929566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_aij_C", NULL)); 11939566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_is_C", NULL)); 11949566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_hypre_C", NULL)); 11959566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaij_hypre_C", NULL)); 11969566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPRESetPreallocation_C", NULL)); 11979566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPREGetParCSR_C", NULL)); 11985fbaff96SJunchao Zhang PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL)); 11995fbaff96SJunchao Zhang PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL)); 12009566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 120163c07aadSStefano Zampini PetscFunctionReturn(0); 120263c07aadSStefano Zampini } 120363c07aadSStefano Zampini 12049371c9d4SSatish Balay static PetscErrorCode MatSetUp_HYPRE(Mat A) { 12054ec6421dSstefano_zampini PetscFunctionBegin; 12069566063dSJacob Faibussowitsch PetscCall(MatHYPRESetPreallocation(A, PETSC_DEFAULT, NULL, PETSC_DEFAULT, NULL)); 12074ec6421dSstefano_zampini PetscFunctionReturn(0); 12084ec6421dSstefano_zampini } 12094ec6421dSstefano_zampini 12106ea7df73SStefano Zampini //TODO FIX hypre_CSRMatrixMatvecOutOfPlace 12116ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 12129371c9d4SSatish Balay static PetscErrorCode MatBindToCPU_HYPRE(Mat A, PetscBool bind) { 12136ea7df73SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 12146ea7df73SStefano Zampini HYPRE_MemoryLocation hmem = bind ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE; 12156ea7df73SStefano Zampini 12166ea7df73SStefano Zampini PetscFunctionBegin; 12176ea7df73SStefano Zampini A->boundtocpu = bind; 12185fbaff96SJunchao Zhang if (hA->ij && hypre_IJMatrixAssembleFlag(hA->ij) && hmem != hypre_IJMatrixMemoryLocation(hA->ij)) { 12196ea7df73SStefano Zampini hypre_ParCSRMatrix *parcsr; 1220792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr); 1221792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixMigrate, parcsr, hmem); 12226ea7df73SStefano Zampini } 12239566063dSJacob Faibussowitsch if (hA->x) PetscCall(VecHYPRE_IJBindToCPU(hA->x, bind)); 12249566063dSJacob Faibussowitsch if (hA->b) PetscCall(VecHYPRE_IJBindToCPU(hA->b, bind)); 12256ea7df73SStefano Zampini PetscFunctionReturn(0); 12266ea7df73SStefano Zampini } 12276ea7df73SStefano Zampini #endif 12286ea7df73SStefano Zampini 12299371c9d4SSatish Balay static PetscErrorCode MatAssemblyEnd_HYPRE(Mat A, MatAssemblyType mode) { 123063c07aadSStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1231c69f721fSFande Kong PetscMPIInt n; 1232c69f721fSFande Kong PetscInt i, j, rstart, ncols, flg; 1233c69f721fSFande Kong PetscInt *row, *col; 1234c69f721fSFande Kong PetscScalar *val; 123563c07aadSStefano Zampini 123663c07aadSStefano Zampini PetscFunctionBegin; 123708401ef6SPierre Jolivet PetscCheck(mode != MAT_FLUSH_ASSEMBLY, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_FLUSH_ASSEMBLY currently not supported with MATHYPRE"); 1238c69f721fSFande Kong 1239c69f721fSFande Kong if (!A->nooffprocentries) { 1240c69f721fSFande Kong while (1) { 12419566063dSJacob Faibussowitsch PetscCall(MatStashScatterGetMesg_Private(&A->stash, &n, &row, &col, &val, &flg)); 1242c69f721fSFande Kong if (!flg) break; 1243c69f721fSFande Kong 1244c69f721fSFande Kong for (i = 0; i < n;) { 1245c69f721fSFande Kong /* Now identify the consecutive vals belonging to the same row */ 1246c69f721fSFande Kong for (j = i, rstart = row[j]; j < n; j++) { 1247c69f721fSFande Kong if (row[j] != rstart) break; 1248c69f721fSFande Kong } 1249c69f721fSFande Kong if (j < n) ncols = j - i; 1250c69f721fSFande Kong else ncols = n - i; 1251c69f721fSFande Kong /* Now assemble all these values with a single function call */ 12529566063dSJacob Faibussowitsch PetscCall(MatSetValues_HYPRE(A, 1, row + i, ncols, col + i, val + i, A->insertmode)); 1253c69f721fSFande Kong 1254c69f721fSFande Kong i = j; 1255c69f721fSFande Kong } 1256c69f721fSFande Kong } 12579566063dSJacob Faibussowitsch PetscCall(MatStashScatterEnd_Private(&A->stash)); 1258c69f721fSFande Kong } 1259c69f721fSFande Kong 1260792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixAssemble, hA->ij); 1261336664bdSPierre Jolivet /* The assembly routine destroys the aux_matrix, we recreate it here by calling HYPRE_IJMatrixInitialize */ 1262336664bdSPierre Jolivet /* If the option MAT_SORTED_FULL is set to true, the indices and values can be passed to hypre directly, so we don't need the aux_matrix */ 1263336664bdSPierre Jolivet if (!hA->sorted_full) { 1264af1cf968SStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 1265af1cf968SStefano Zampini 1266af1cf968SStefano Zampini /* call destroy just to make sure we do not leak anything */ 1267af1cf968SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij); 1268792fecdfSBarry Smith PetscCallExternal(hypre_AuxParCSRMatrixDestroy, aux_matrix); 1269af1cf968SStefano Zampini hypre_IJMatrixTranslator(hA->ij) = NULL; 1270af1cf968SStefano Zampini 1271af1cf968SStefano Zampini /* Initialize with assembled flag -> it only recreates the aux_par_matrix */ 1272792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij); 1273af1cf968SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij); 12746ea7df73SStefano Zampini if (aux_matrix) { 1275af1cf968SStefano Zampini hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1; /* see comment in MatHYPRESetPreallocation_HYPRE */ 127622235d61SPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 1277792fecdfSBarry Smith PetscCallExternal(hypre_AuxParCSRMatrixInitialize, aux_matrix); 127822235d61SPierre Jolivet #else 1279792fecdfSBarry Smith PetscCallExternal(hypre_AuxParCSRMatrixInitialize_v2, aux_matrix, HYPRE_MEMORY_HOST); 128022235d61SPierre Jolivet #endif 1281af1cf968SStefano Zampini } 12826ea7df73SStefano Zampini } 12836ea7df73SStefano Zampini { 12846ea7df73SStefano Zampini hypre_ParCSRMatrix *parcsr; 12856ea7df73SStefano Zampini 1286792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr); 1287792fecdfSBarry Smith if (!hypre_ParCSRMatrixCommPkg(parcsr)) PetscCallExternal(hypre_MatvecCommPkgCreate, parcsr); 12886ea7df73SStefano Zampini } 12899566063dSJacob Faibussowitsch if (!hA->x) PetscCall(VecHYPRE_IJVectorCreate(A->cmap, &hA->x)); 12909566063dSJacob Faibussowitsch if (!hA->b) PetscCall(VecHYPRE_IJVectorCreate(A->rmap, &hA->b)); 12916ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 12929566063dSJacob Faibussowitsch PetscCall(MatBindToCPU_HYPRE(A, A->boundtocpu)); 12936ea7df73SStefano Zampini #endif 129463c07aadSStefano Zampini PetscFunctionReturn(0); 129563c07aadSStefano Zampini } 129663c07aadSStefano Zampini 12979371c9d4SSatish Balay static PetscErrorCode MatGetArray_HYPRE(Mat A, PetscInt size, void **array) { 1298c69f721fSFande Kong Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1299c69f721fSFande Kong 1300c69f721fSFande Kong PetscFunctionBegin; 130128b400f6SJacob Faibussowitsch PetscCheck(hA->available, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Temporary space is in use"); 1302c69f721fSFande Kong 130339accc25SStefano Zampini if (hA->size >= size) { 130439accc25SStefano Zampini *array = hA->array; 130539accc25SStefano Zampini } else { 13069566063dSJacob Faibussowitsch PetscCall(PetscFree(hA->array)); 1307c69f721fSFande Kong hA->size = size; 13089566063dSJacob Faibussowitsch PetscCall(PetscMalloc(hA->size, &hA->array)); 1309c69f721fSFande Kong *array = hA->array; 1310c69f721fSFande Kong } 1311c69f721fSFande Kong 1312c69f721fSFande Kong hA->available = PETSC_FALSE; 1313c69f721fSFande Kong PetscFunctionReturn(0); 1314c69f721fSFande Kong } 1315c69f721fSFande Kong 13169371c9d4SSatish Balay static PetscErrorCode MatRestoreArray_HYPRE(Mat A, void **array) { 1317c69f721fSFande Kong Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1318c69f721fSFande Kong 1319c69f721fSFande Kong PetscFunctionBegin; 1320c69f721fSFande Kong *array = NULL; 1321c69f721fSFande Kong hA->available = PETSC_TRUE; 1322c69f721fSFande Kong PetscFunctionReturn(0); 1323c69f721fSFande Kong } 1324c69f721fSFande Kong 13259371c9d4SSatish Balay static PetscErrorCode MatSetValues_HYPRE(Mat A, PetscInt nr, const PetscInt rows[], PetscInt nc, const PetscInt cols[], const PetscScalar v[], InsertMode ins) { 1326d975228cSstefano_zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1327d975228cSstefano_zampini PetscScalar *vals = (PetscScalar *)v; 132839accc25SStefano Zampini HYPRE_Complex *sscr; 1329c69f721fSFande Kong PetscInt *cscr[2]; 1330c69f721fSFande Kong PetscInt i, nzc; 133108defe43SFande Kong void *array = NULL; 1332d975228cSstefano_zampini 1333d975228cSstefano_zampini PetscFunctionBegin; 13349566063dSJacob Faibussowitsch PetscCall(MatGetArray_HYPRE(A, sizeof(PetscInt) * (2 * nc) + sizeof(HYPRE_Complex) * nc * nr, &array)); 1335c69f721fSFande Kong cscr[0] = (PetscInt *)array; 1336c69f721fSFande Kong cscr[1] = ((PetscInt *)array) + nc; 133739accc25SStefano Zampini sscr = (HYPRE_Complex *)(((PetscInt *)array) + nc * 2); 1338d975228cSstefano_zampini for (i = 0, nzc = 0; i < nc; i++) { 1339d975228cSstefano_zampini if (cols[i] >= 0) { 1340d975228cSstefano_zampini cscr[0][nzc] = cols[i]; 1341d975228cSstefano_zampini cscr[1][nzc++] = i; 1342d975228cSstefano_zampini } 1343d975228cSstefano_zampini } 1344c69f721fSFande Kong if (!nzc) { 13459566063dSJacob Faibussowitsch PetscCall(MatRestoreArray_HYPRE(A, &array)); 1346c69f721fSFande Kong PetscFunctionReturn(0); 1347c69f721fSFande Kong } 1348d975228cSstefano_zampini 13496ea7df73SStefano Zampini #if 0 //defined(PETSC_HAVE_HYPRE_DEVICE) 13506ea7df73SStefano Zampini if (HYPRE_MEMORY_HOST != hypre_IJMatrixMemoryLocation(hA->ij)) { 13516ea7df73SStefano Zampini hypre_ParCSRMatrix *parcsr; 13526ea7df73SStefano Zampini 1353792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject,hA->ij,(void**)&parcsr); 1354792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixMigrate,parcsr, HYPRE_MEMORY_HOST); 13556ea7df73SStefano Zampini } 13566ea7df73SStefano Zampini #endif 13576ea7df73SStefano Zampini 1358d975228cSstefano_zampini if (ins == ADD_VALUES) { 1359d975228cSstefano_zampini for (i = 0; i < nr; i++) { 13606ea7df73SStefano Zampini if (rows[i] >= 0) { 1361d975228cSstefano_zampini PetscInt j; 13622cf14000SStefano Zampini HYPRE_Int hnc = (HYPRE_Int)nzc; 13632cf14000SStefano Zampini 1364aed4548fSBarry Smith PetscCheck((PetscInt)hnc == nzc, PETSC_COMM_SELF, PETSC_ERR_SUP, "Hypre overflow! number of columns %" PetscInt_FMT " for row %" PetscInt_FMT, nzc, rows[i]); 13659566063dSJacob Faibussowitsch for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j])); 1366792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixAddToValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr); 1367d975228cSstefano_zampini } 1368d975228cSstefano_zampini vals += nc; 1369d975228cSstefano_zampini } 1370d975228cSstefano_zampini } else { /* INSERT_VALUES */ 1371d975228cSstefano_zampini PetscInt rst, ren; 1372c69f721fSFande Kong 13739566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rst, &ren)); 1374d975228cSstefano_zampini for (i = 0; i < nr; i++) { 13756ea7df73SStefano Zampini if (rows[i] >= 0) { 1376d975228cSstefano_zampini PetscInt j; 13772cf14000SStefano Zampini HYPRE_Int hnc = (HYPRE_Int)nzc; 13782cf14000SStefano Zampini 1379aed4548fSBarry Smith PetscCheck((PetscInt)hnc == nzc, PETSC_COMM_SELF, PETSC_ERR_SUP, "Hypre overflow! number of columns %" PetscInt_FMT " for row %" PetscInt_FMT, nzc, rows[i]); 13809566063dSJacob Faibussowitsch for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j])); 1381c69f721fSFande Kong /* nonlocal values */ 13829566063dSJacob Faibussowitsch if (rows[i] < rst || rows[i] >= ren) PetscCall(MatStashValuesRow_Private(&A->stash, rows[i], nzc, cscr[0], (PetscScalar *)sscr, PETSC_FALSE)); 1383c69f721fSFande Kong /* local values */ 1384792fecdfSBarry Smith else PetscCallExternal(HYPRE_IJMatrixSetValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr); 1385d975228cSstefano_zampini } 1386d975228cSstefano_zampini vals += nc; 1387d975228cSstefano_zampini } 1388d975228cSstefano_zampini } 1389c69f721fSFande Kong 13909566063dSJacob Faibussowitsch PetscCall(MatRestoreArray_HYPRE(A, &array)); 1391d975228cSstefano_zampini PetscFunctionReturn(0); 1392d975228cSstefano_zampini } 1393d975228cSstefano_zampini 13949371c9d4SSatish Balay static PetscErrorCode MatHYPRESetPreallocation_HYPRE(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[]) { 1395d975228cSstefano_zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 13967d968826Sstefano_zampini HYPRE_Int *hdnnz, *honnz; 139706a29025Sstefano_zampini PetscInt i, rs, re, cs, ce, bs; 1398d975228cSstefano_zampini PetscMPIInt size; 1399d975228cSstefano_zampini 1400d975228cSstefano_zampini PetscFunctionBegin; 14019566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 14029566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 1403d975228cSstefano_zampini rs = A->rmap->rstart; 1404d975228cSstefano_zampini re = A->rmap->rend; 1405d975228cSstefano_zampini cs = A->cmap->rstart; 1406d975228cSstefano_zampini ce = A->cmap->rend; 1407d975228cSstefano_zampini if (!hA->ij) { 1408792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rs, re - 1, cs, ce - 1, &hA->ij); 1409792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR); 1410d975228cSstefano_zampini } else { 14112cf14000SStefano Zampini HYPRE_BigInt hrs, hre, hcs, hce; 1412792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetLocalRange, hA->ij, &hrs, &hre, &hcs, &hce); 1413aed4548fSBarry Smith PetscCheck(hre - hrs + 1 == re - rs, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent local rows: IJMatrix [%" PetscHYPRE_BigInt_FMT ",%" PetscHYPRE_BigInt_FMT "), PETSc [%" PetscInt_FMT ",%" PetscInt_FMT ")", hrs, hre + 1, rs, re); 1414aed4548fSBarry Smith PetscCheck(hce - hcs + 1 == ce - cs, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent local cols: IJMatrix [%" PetscHYPRE_BigInt_FMT ",%" PetscHYPRE_BigInt_FMT "), PETSc [%" PetscInt_FMT ",%" PetscInt_FMT ")", hcs, hce + 1, cs, ce); 1415d975228cSstefano_zampini } 14169566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 141706a29025Sstefano_zampini if (dnz == PETSC_DEFAULT || dnz == PETSC_DECIDE) dnz = 10 * bs; 141806a29025Sstefano_zampini if (onz == PETSC_DEFAULT || onz == PETSC_DECIDE) onz = 10 * bs; 141906a29025Sstefano_zampini 1420d975228cSstefano_zampini if (!dnnz) { 14219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n, &hdnnz)); 1422d975228cSstefano_zampini for (i = 0; i < A->rmap->n; i++) hdnnz[i] = dnz; 1423d975228cSstefano_zampini } else { 14247d968826Sstefano_zampini hdnnz = (HYPRE_Int *)dnnz; 1425d975228cSstefano_zampini } 14269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 1427d975228cSstefano_zampini if (size > 1) { 1428ddbeb582SStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 1429d975228cSstefano_zampini if (!onnz) { 14309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n, &honnz)); 1431d975228cSstefano_zampini for (i = 0; i < A->rmap->n; i++) honnz[i] = onz; 143222235d61SPierre Jolivet } else honnz = (HYPRE_Int *)onnz; 1433ddbeb582SStefano Zampini /* SetDiagOffdSizes sets hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0, since it seems 1434ddbeb582SStefano Zampini they assume the user will input the entire row values, properly sorted 1435336664bdSPierre Jolivet In PETSc, we don't make such an assumption and set this flag to 1, 1436336664bdSPierre Jolivet unless the option MAT_SORTED_FULL is set to true. 1437ddbeb582SStefano Zampini Also, to avoid possible memory leaks, we destroy and recreate the translator 1438ddbeb582SStefano Zampini This has to be done here, as HYPRE_IJMatrixInitialize will properly initialize 1439ddbeb582SStefano Zampini the IJ matrix for us */ 1440ddbeb582SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij); 1441ddbeb582SStefano Zampini hypre_AuxParCSRMatrixDestroy(aux_matrix); 1442ddbeb582SStefano Zampini hypre_IJMatrixTranslator(hA->ij) = NULL; 1443792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, hA->ij, hdnnz, honnz); 1444ddbeb582SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij); 1445336664bdSPierre Jolivet hypre_AuxParCSRMatrixNeedAux(aux_matrix) = !hA->sorted_full; 1446d975228cSstefano_zampini } else { 1447d975228cSstefano_zampini honnz = NULL; 1448792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetRowSizes, hA->ij, hdnnz); 1449d975228cSstefano_zampini } 1450ddbeb582SStefano Zampini 1451af1cf968SStefano Zampini /* reset assembled flag and call the initialize method */ 1452af1cf968SStefano Zampini hypre_IJMatrixAssembleFlag(hA->ij) = 0; 14536ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 1454792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij); 14556ea7df73SStefano Zampini #else 1456792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize_v2, hA->ij, HYPRE_MEMORY_HOST); 14576ea7df73SStefano Zampini #endif 145848a46eb9SPierre Jolivet if (!dnnz) PetscCall(PetscFree(hdnnz)); 145948a46eb9SPierre Jolivet if (!onnz && honnz) PetscCall(PetscFree(honnz)); 1460af1cf968SStefano Zampini /* Match AIJ logic */ 146106a29025Sstefano_zampini A->preallocated = PETSC_TRUE; 1462af1cf968SStefano Zampini A->assembled = PETSC_FALSE; 1463d975228cSstefano_zampini PetscFunctionReturn(0); 1464d975228cSstefano_zampini } 1465d975228cSstefano_zampini 1466d975228cSstefano_zampini /*@C 1467d975228cSstefano_zampini MatHYPRESetPreallocation - Preallocates memory for a sparse parallel matrix in HYPRE IJ format 1468d975228cSstefano_zampini 146911a5261eSBarry Smith Collective on A 1470d975228cSstefano_zampini 1471d975228cSstefano_zampini Input Parameters: 1472d975228cSstefano_zampini + A - the matrix 1473d975228cSstefano_zampini . dnz - number of nonzeros per row in DIAGONAL portion of local submatrix 1474d975228cSstefano_zampini (same value is used for all local rows) 1475d975228cSstefano_zampini . dnnz - array containing the number of nonzeros in the various rows of the 1476d975228cSstefano_zampini DIAGONAL portion of the local submatrix (possibly different for each row) 147711a5261eSBarry Smith or NULL (`PETSC_NULL_INTEGER` in Fortran), if d_nz is used to specify the nonzero structure. 1478d975228cSstefano_zampini The size of this array is equal to the number of local rows, i.e 'm'. 1479d975228cSstefano_zampini For matrices that will be factored, you must leave room for (and set) 1480d975228cSstefano_zampini the diagonal entry even if it is zero. 1481d975228cSstefano_zampini . onz - number of nonzeros per row in the OFF-DIAGONAL portion of local 1482d975228cSstefano_zampini submatrix (same value is used for all local rows). 1483d975228cSstefano_zampini - onnz - array containing the number of nonzeros in the various rows of the 1484d975228cSstefano_zampini OFF-DIAGONAL portion of the local submatrix (possibly different for 148511a5261eSBarry Smith each row) or NULL (`PETSC_NULL_INTEGER` in Fortran), if o_nz is used to specify the nonzero 1486d975228cSstefano_zampini structure. The size of this array is equal to the number 1487d975228cSstefano_zampini of local rows, i.e 'm'. 1488d975228cSstefano_zampini 148911a5261eSBarry Smith Note: 149095452b02SPatrick Sanan If the *nnz parameter is given then the *nz parameter is ignored; for sequential matrices, onz and onnz are ignored. 1491d975228cSstefano_zampini 1492d975228cSstefano_zampini Level: intermediate 1493d975228cSstefano_zampini 1494db781477SPatrick Sanan .seealso: `MatCreate()`, `MatMPIAIJSetPreallocation()`, `MATHYPRE` 1495d975228cSstefano_zampini @*/ 14969371c9d4SSatish Balay PetscErrorCode MatHYPRESetPreallocation(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[]) { 1497d975228cSstefano_zampini PetscFunctionBegin; 1498d975228cSstefano_zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1499d975228cSstefano_zampini PetscValidType(A, 1); 1500cac4c232SBarry Smith PetscTryMethod(A, "MatHYPRESetPreallocation_C", (Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]), (A, dnz, dnnz, onz, onnz)); 1501d975228cSstefano_zampini PetscFunctionReturn(0); 1502d975228cSstefano_zampini } 1503d975228cSstefano_zampini 1504225daaf8SStefano Zampini /* 1505225daaf8SStefano Zampini MatCreateFromParCSR - Creates a matrix from a hypre_ParCSRMatrix 1506225daaf8SStefano Zampini 1507225daaf8SStefano Zampini Collective 1508225daaf8SStefano Zampini 1509225daaf8SStefano Zampini Input Parameters: 151045b8d346SStefano Zampini + parcsr - the pointer to the hypre_ParCSRMatrix 1511bb4689ddSStefano Zampini . mtype - matrix type to be created. Currently MATAIJ, MATIS and MATHYPRE are supported. 1512225daaf8SStefano Zampini - copymode - PETSc copying options 1513225daaf8SStefano Zampini 1514225daaf8SStefano Zampini Output Parameter: 1515225daaf8SStefano Zampini . A - the matrix 1516225daaf8SStefano Zampini 1517225daaf8SStefano Zampini Level: intermediate 1518225daaf8SStefano Zampini 1519db781477SPatrick Sanan .seealso: `MatHYPRE`, `PetscCopyMode` 1520225daaf8SStefano Zampini */ 15219371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatCreateFromParCSR(hypre_ParCSRMatrix *parcsr, MatType mtype, PetscCopyMode copymode, Mat *A) { 1522225daaf8SStefano Zampini Mat T; 1523978814f1SStefano Zampini Mat_HYPRE *hA; 1524978814f1SStefano Zampini MPI_Comm comm; 1525978814f1SStefano Zampini PetscInt rstart, rend, cstart, cend, M, N; 1526d248a85cSRichard Tran Mills PetscBool isseqaij, isseqaijmkl, ismpiaij, isaij, ishyp, isis; 1527978814f1SStefano Zampini 1528978814f1SStefano Zampini PetscFunctionBegin; 1529978814f1SStefano Zampini comm = hypre_ParCSRMatrixComm(parcsr); 15309566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQAIJ, &isseqaij)); 15319566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQAIJMKL, &isseqaijmkl)); 15329566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPIAIJ, &ismpiaij)); 15339566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATAIJ, &isaij)); 15349566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATHYPRE, &ishyp)); 15359566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATIS, &isis)); 1536d248a85cSRichard Tran Mills isaij = (PetscBool)(isseqaij || isseqaijmkl || ismpiaij || isaij); 15376ea7df73SStefano Zampini /* TODO */ 1538aed4548fSBarry Smith PetscCheck(isaij || ishyp || isis, comm, PETSC_ERR_SUP, "Unsupported MatType %s! Supported types are %s, %s, %s, %s, %s, and %s", mtype, MATAIJ, MATSEQAIJ, MATSEQAIJMKL, MATMPIAIJ, MATIS, MATHYPRE); 1539978814f1SStefano Zampini /* access ParCSRMatrix */ 1540978814f1SStefano Zampini rstart = hypre_ParCSRMatrixFirstRowIndex(parcsr); 1541978814f1SStefano Zampini rend = hypre_ParCSRMatrixLastRowIndex(parcsr); 1542978814f1SStefano Zampini cstart = hypre_ParCSRMatrixFirstColDiag(parcsr); 1543978814f1SStefano Zampini cend = hypre_ParCSRMatrixLastColDiag(parcsr); 1544978814f1SStefano Zampini M = hypre_ParCSRMatrixGlobalNumRows(parcsr); 1545978814f1SStefano Zampini N = hypre_ParCSRMatrixGlobalNumCols(parcsr); 1546978814f1SStefano Zampini 1547fa92c42cSstefano_zampini /* fix for empty local rows/columns */ 1548fa92c42cSstefano_zampini if (rend < rstart) rend = rstart; 1549fa92c42cSstefano_zampini if (cend < cstart) cend = cstart; 1550fa92c42cSstefano_zampini 1551e6471dc9SStefano Zampini /* PETSc convention */ 1552e6471dc9SStefano Zampini rend++; 1553e6471dc9SStefano Zampini cend++; 1554e6471dc9SStefano Zampini rend = PetscMin(rend, M); 1555e6471dc9SStefano Zampini cend = PetscMin(cend, N); 1556e6471dc9SStefano Zampini 1557978814f1SStefano Zampini /* create PETSc matrix with MatHYPRE */ 15589566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &T)); 15599566063dSJacob Faibussowitsch PetscCall(MatSetSizes(T, rend - rstart, cend - cstart, M, N)); 15609566063dSJacob Faibussowitsch PetscCall(MatSetType(T, MATHYPRE)); 1561225daaf8SStefano Zampini hA = (Mat_HYPRE *)(T->data); 1562978814f1SStefano Zampini 1563978814f1SStefano Zampini /* create HYPRE_IJMatrix */ 1564792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rstart, rend - 1, cstart, cend - 1, &hA->ij); 1565792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR); 156645b8d346SStefano Zampini 15676ea7df73SStefano Zampini // TODO DEV 156845b8d346SStefano Zampini /* create new ParCSR object if needed */ 156945b8d346SStefano Zampini if (ishyp && copymode == PETSC_COPY_VALUES) { 157045b8d346SStefano Zampini hypre_ParCSRMatrix *new_parcsr; 15716ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0) 157245b8d346SStefano Zampini hypre_CSRMatrix *hdiag, *hoffd, *ndiag, *noffd; 157345b8d346SStefano Zampini 15740e6427aaSSatish Balay new_parcsr = hypre_ParCSRMatrixClone(parcsr, 0); 157545b8d346SStefano Zampini hdiag = hypre_ParCSRMatrixDiag(parcsr); 157645b8d346SStefano Zampini hoffd = hypre_ParCSRMatrixOffd(parcsr); 157745b8d346SStefano Zampini ndiag = hypre_ParCSRMatrixDiag(new_parcsr); 157845b8d346SStefano Zampini noffd = hypre_ParCSRMatrixOffd(new_parcsr); 15799566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hypre_CSRMatrixData(ndiag), hypre_CSRMatrixData(hdiag), hypre_CSRMatrixNumNonzeros(hdiag))); 15809566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hypre_CSRMatrixData(noffd), hypre_CSRMatrixData(hoffd), hypre_CSRMatrixNumNonzeros(hoffd))); 15816ea7df73SStefano Zampini #else 15826ea7df73SStefano Zampini new_parcsr = hypre_ParCSRMatrixClone(parcsr, 1); 15836ea7df73SStefano Zampini #endif 158445b8d346SStefano Zampini parcsr = new_parcsr; 158545b8d346SStefano Zampini copymode = PETSC_OWN_POINTER; 158645b8d346SStefano Zampini } 1587978814f1SStefano Zampini 1588978814f1SStefano Zampini /* set ParCSR object */ 1589978814f1SStefano Zampini hypre_IJMatrixObject(hA->ij) = parcsr; 15904ec6421dSstefano_zampini T->preallocated = PETSC_TRUE; 1591978814f1SStefano Zampini 1592978814f1SStefano Zampini /* set assembled flag */ 1593978814f1SStefano Zampini hypre_IJMatrixAssembleFlag(hA->ij) = 1; 15946ea7df73SStefano Zampini #if 0 1595792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize,hA->ij); 15966ea7df73SStefano Zampini #endif 1597225daaf8SStefano Zampini if (ishyp) { 15986d2a658fSstefano_zampini PetscMPIInt myid = 0; 15996d2a658fSstefano_zampini 16006d2a658fSstefano_zampini /* make sure we always have row_starts and col_starts available */ 160148a46eb9SPierre Jolivet if (HYPRE_AssumedPartitionCheck()) PetscCallMPI(MPI_Comm_rank(comm, &myid)); 1602a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 16036d2a658fSstefano_zampini if (!hypre_ParCSRMatrixOwnsColStarts(parcsr)) { 16046d2a658fSstefano_zampini PetscLayout map; 16056d2a658fSstefano_zampini 16069566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(T, NULL, &map)); 16079566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(map)); 16082cf14000SStefano Zampini hypre_ParCSRMatrixColStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid); 16096d2a658fSstefano_zampini } 16106d2a658fSstefano_zampini if (!hypre_ParCSRMatrixOwnsRowStarts(parcsr)) { 16116d2a658fSstefano_zampini PetscLayout map; 16126d2a658fSstefano_zampini 16139566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(T, &map, NULL)); 16149566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(map)); 16152cf14000SStefano Zampini hypre_ParCSRMatrixRowStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid); 16166d2a658fSstefano_zampini } 1617a1d2239cSSatish Balay #endif 1618978814f1SStefano Zampini /* prevent from freeing the pointer */ 1619978814f1SStefano Zampini if (copymode == PETSC_USE_POINTER) hA->inner_free = PETSC_FALSE; 1620225daaf8SStefano Zampini *A = T; 16219566063dSJacob Faibussowitsch PetscCall(MatSetOption(*A, MAT_SORTED_FULL, PETSC_TRUE)); 16229566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*A, MAT_FINAL_ASSEMBLY)); 16239566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*A, MAT_FINAL_ASSEMBLY)); 1624bb4689ddSStefano Zampini } else if (isaij) { 1625bb4689ddSStefano Zampini if (copymode != PETSC_OWN_POINTER) { 1626225daaf8SStefano Zampini /* prevent from freeing the pointer */ 1627225daaf8SStefano Zampini hA->inner_free = PETSC_FALSE; 16289566063dSJacob Faibussowitsch PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INITIAL_MATRIX, A)); 16299566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 1630225daaf8SStefano Zampini } else { /* AIJ return type with PETSC_OWN_POINTER */ 16319566063dSJacob Faibussowitsch PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INPLACE_MATRIX, &T)); 1632225daaf8SStefano Zampini *A = T; 1633225daaf8SStefano Zampini } 1634bb4689ddSStefano Zampini } else if (isis) { 16359566063dSJacob Faibussowitsch PetscCall(MatConvert_HYPRE_IS(T, MATIS, MAT_INITIAL_MATRIX, A)); 16368cfe8d00SStefano Zampini if (copymode != PETSC_OWN_POINTER) hA->inner_free = PETSC_FALSE; 16379566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 1638bb4689ddSStefano Zampini } 1639978814f1SStefano Zampini PetscFunctionReturn(0); 1640978814f1SStefano Zampini } 1641978814f1SStefano Zampini 16429371c9d4SSatish Balay static PetscErrorCode MatHYPREGetParCSR_HYPRE(Mat A, hypre_ParCSRMatrix **parcsr) { 1643dd9c0a25Sstefano_zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1644dd9c0a25Sstefano_zampini HYPRE_Int type; 1645dd9c0a25Sstefano_zampini 1646dd9c0a25Sstefano_zampini PetscFunctionBegin; 164728b400f6SJacob Faibussowitsch PetscCheck(hA->ij, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "HYPRE_IJMatrix not present"); 1648792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type); 164908401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "HYPRE_IJMatrix is not of type HYPRE_PARCSR"); 1650792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)parcsr); 1651dd9c0a25Sstefano_zampini PetscFunctionReturn(0); 1652dd9c0a25Sstefano_zampini } 1653dd9c0a25Sstefano_zampini 1654dd9c0a25Sstefano_zampini /* 1655dd9c0a25Sstefano_zampini MatHYPREGetParCSR - Gets the pointer to the ParCSR matrix 1656dd9c0a25Sstefano_zampini 1657dd9c0a25Sstefano_zampini Not collective 1658dd9c0a25Sstefano_zampini 1659dd9c0a25Sstefano_zampini Input Parameters: 1660dd9c0a25Sstefano_zampini + A - the MATHYPRE object 1661dd9c0a25Sstefano_zampini 1662dd9c0a25Sstefano_zampini Output Parameter: 1663dd9c0a25Sstefano_zampini . parcsr - the pointer to the hypre_ParCSRMatrix 1664dd9c0a25Sstefano_zampini 1665dd9c0a25Sstefano_zampini Level: intermediate 1666dd9c0a25Sstefano_zampini 1667db781477SPatrick Sanan .seealso: `MatHYPRE`, `PetscCopyMode` 1668dd9c0a25Sstefano_zampini */ 16699371c9d4SSatish Balay PetscErrorCode MatHYPREGetParCSR(Mat A, hypre_ParCSRMatrix **parcsr) { 1670dd9c0a25Sstefano_zampini PetscFunctionBegin; 1671dd9c0a25Sstefano_zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1672dd9c0a25Sstefano_zampini PetscValidType(A, 1); 1673cac4c232SBarry Smith PetscUseMethod(A, "MatHYPREGetParCSR_C", (Mat, hypre_ParCSRMatrix **), (A, parcsr)); 1674dd9c0a25Sstefano_zampini PetscFunctionReturn(0); 1675dd9c0a25Sstefano_zampini } 1676dd9c0a25Sstefano_zampini 16779371c9d4SSatish Balay static PetscErrorCode MatMissingDiagonal_HYPRE(Mat A, PetscBool *missing, PetscInt *dd) { 167868ec7858SStefano Zampini hypre_ParCSRMatrix *parcsr; 167968ec7858SStefano Zampini hypre_CSRMatrix *ha; 168068ec7858SStefano Zampini PetscInt rst; 168168ec7858SStefano Zampini 168268ec7858SStefano Zampini PetscFunctionBegin; 168308401ef6SPierre Jolivet PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented with non-square diagonal blocks"); 16849566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rst, NULL)); 16859566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 168668ec7858SStefano Zampini if (missing) *missing = PETSC_FALSE; 168768ec7858SStefano Zampini if (dd) *dd = -1; 168868ec7858SStefano Zampini ha = hypre_ParCSRMatrixDiag(parcsr); 168968ec7858SStefano Zampini if (ha) { 169068299464SStefano Zampini PetscInt size, i; 169168299464SStefano Zampini HYPRE_Int *ii, *jj; 169268ec7858SStefano Zampini 169368ec7858SStefano Zampini size = hypre_CSRMatrixNumRows(ha); 169468ec7858SStefano Zampini ii = hypre_CSRMatrixI(ha); 169568ec7858SStefano Zampini jj = hypre_CSRMatrixJ(ha); 169668ec7858SStefano Zampini for (i = 0; i < size; i++) { 169768ec7858SStefano Zampini PetscInt j; 169868ec7858SStefano Zampini PetscBool found = PETSC_FALSE; 169968ec7858SStefano Zampini 17009371c9d4SSatish Balay for (j = ii[i]; j < ii[i + 1] && !found; j++) found = (jj[j] == i) ? PETSC_TRUE : PETSC_FALSE; 170168ec7858SStefano Zampini 170268ec7858SStefano Zampini if (!found) { 17037d3de750SJacob Faibussowitsch PetscInfo(A, "Matrix is missing local diagonal entry %" PetscInt_FMT "\n", i); 170468ec7858SStefano Zampini if (missing) *missing = PETSC_TRUE; 170568ec7858SStefano Zampini if (dd) *dd = i + rst; 170668ec7858SStefano Zampini PetscFunctionReturn(0); 170768ec7858SStefano Zampini } 170868ec7858SStefano Zampini } 170968ec7858SStefano Zampini if (!size) { 171068ec7858SStefano Zampini PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n"); 171168ec7858SStefano Zampini if (missing) *missing = PETSC_TRUE; 171268ec7858SStefano Zampini if (dd) *dd = rst; 171368ec7858SStefano Zampini } 171468ec7858SStefano Zampini } else { 171568ec7858SStefano Zampini PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n"); 171668ec7858SStefano Zampini if (missing) *missing = PETSC_TRUE; 171768ec7858SStefano Zampini if (dd) *dd = rst; 171868ec7858SStefano Zampini } 171968ec7858SStefano Zampini PetscFunctionReturn(0); 172068ec7858SStefano Zampini } 172168ec7858SStefano Zampini 17229371c9d4SSatish Balay static PetscErrorCode MatScale_HYPRE(Mat A, PetscScalar s) { 172368ec7858SStefano Zampini hypre_ParCSRMatrix *parcsr; 17246ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 172568ec7858SStefano Zampini hypre_CSRMatrix *ha; 17266ea7df73SStefano Zampini #endif 172739accc25SStefano Zampini HYPRE_Complex hs; 172868ec7858SStefano Zampini 172968ec7858SStefano Zampini PetscFunctionBegin; 17309566063dSJacob Faibussowitsch PetscCall(PetscHYPREScalarCast(s, &hs)); 17319566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 17326ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 19, 0) 1733792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixScale, parcsr, hs); 17346ea7df73SStefano Zampini #else /* diagonal part */ 173568ec7858SStefano Zampini ha = hypre_ParCSRMatrixDiag(parcsr); 173668ec7858SStefano Zampini if (ha) { 173768299464SStefano Zampini PetscInt size, i; 173868299464SStefano Zampini HYPRE_Int *ii; 173939accc25SStefano Zampini HYPRE_Complex *a; 174068ec7858SStefano Zampini 174168ec7858SStefano Zampini size = hypre_CSRMatrixNumRows(ha); 174268ec7858SStefano Zampini a = hypre_CSRMatrixData(ha); 174368ec7858SStefano Zampini ii = hypre_CSRMatrixI(ha); 174439accc25SStefano Zampini for (i = 0; i < ii[size]; i++) a[i] *= hs; 174568ec7858SStefano Zampini } 174668ec7858SStefano Zampini /* offdiagonal part */ 174768ec7858SStefano Zampini ha = hypre_ParCSRMatrixOffd(parcsr); 174868ec7858SStefano Zampini if (ha) { 174968299464SStefano Zampini PetscInt size, i; 175068299464SStefano Zampini HYPRE_Int *ii; 175139accc25SStefano Zampini HYPRE_Complex *a; 175268ec7858SStefano Zampini 175368ec7858SStefano Zampini size = hypre_CSRMatrixNumRows(ha); 175468ec7858SStefano Zampini a = hypre_CSRMatrixData(ha); 175568ec7858SStefano Zampini ii = hypre_CSRMatrixI(ha); 175639accc25SStefano Zampini for (i = 0; i < ii[size]; i++) a[i] *= hs; 175768ec7858SStefano Zampini } 17586ea7df73SStefano Zampini #endif 175968ec7858SStefano Zampini PetscFunctionReturn(0); 176068ec7858SStefano Zampini } 176168ec7858SStefano Zampini 17629371c9d4SSatish Balay static PetscErrorCode MatZeroRowsColumns_HYPRE(Mat A, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) { 176368ec7858SStefano Zampini hypre_ParCSRMatrix *parcsr; 176468299464SStefano Zampini HYPRE_Int *lrows; 176568299464SStefano Zampini PetscInt rst, ren, i; 176668ec7858SStefano Zampini 176768ec7858SStefano Zampini PetscFunctionBegin; 176808401ef6SPierre Jolivet PetscCheck(!x && !b, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "To be implemented"); 17699566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 17709566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRows, &lrows)); 17719566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rst, &ren)); 177268ec7858SStefano Zampini for (i = 0; i < numRows; i++) { 17737a46b595SBarry Smith PetscCheck(rows[i] >= rst && rows[i] < ren, PETSC_COMM_SELF, PETSC_ERR_SUP, "Non-local rows not yet supported"); 177468ec7858SStefano Zampini lrows[i] = rows[i] - rst; 177568ec7858SStefano Zampini } 1776792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixEliminateRowsCols, parcsr, numRows, lrows); 17779566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 177868ec7858SStefano Zampini PetscFunctionReturn(0); 177968ec7858SStefano Zampini } 178068ec7858SStefano Zampini 17819371c9d4SSatish Balay static PetscErrorCode MatZeroEntries_HYPRE_CSRMatrix(hypre_CSRMatrix *ha) { 1782c69f721fSFande Kong PetscFunctionBegin; 1783c69f721fSFande Kong if (ha) { 1784c69f721fSFande Kong HYPRE_Int *ii, size; 1785c69f721fSFande Kong HYPRE_Complex *a; 1786c69f721fSFande Kong 1787c69f721fSFande Kong size = hypre_CSRMatrixNumRows(ha); 1788c69f721fSFande Kong a = hypre_CSRMatrixData(ha); 1789c69f721fSFande Kong ii = hypre_CSRMatrixI(ha); 1790c69f721fSFande Kong 17919566063dSJacob Faibussowitsch if (a) PetscCall(PetscArrayzero(a, ii[size])); 1792c69f721fSFande Kong } 1793c69f721fSFande Kong PetscFunctionReturn(0); 1794c69f721fSFande Kong } 1795c69f721fSFande Kong 17969371c9d4SSatish Balay PetscErrorCode MatZeroEntries_HYPRE(Mat A) { 17976ea7df73SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 17986ea7df73SStefano Zampini 17996ea7df73SStefano Zampini PetscFunctionBegin; 18006ea7df73SStefano Zampini if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(hA->ij)) { 1801792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetConstantValues, hA->ij, 0.0); 18026ea7df73SStefano Zampini } else { 1803c69f721fSFande Kong hypre_ParCSRMatrix *parcsr; 1804c69f721fSFande Kong 18059566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 18069566063dSJacob Faibussowitsch PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr))); 18079566063dSJacob Faibussowitsch PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr))); 18086ea7df73SStefano Zampini } 1809c69f721fSFande Kong PetscFunctionReturn(0); 1810c69f721fSFande Kong } 1811c69f721fSFande Kong 18129371c9d4SSatish Balay static PetscErrorCode MatZeroRows_HYPRE_CSRMatrix(hypre_CSRMatrix *hA, PetscInt N, const PetscInt rows[], HYPRE_Complex diag) { 181339accc25SStefano Zampini PetscInt ii; 181439accc25SStefano Zampini HYPRE_Int *i, *j; 181539accc25SStefano Zampini HYPRE_Complex *a; 1816c69f721fSFande Kong 1817c69f721fSFande Kong PetscFunctionBegin; 1818c69f721fSFande Kong if (!hA) PetscFunctionReturn(0); 1819c69f721fSFande Kong 182039accc25SStefano Zampini i = hypre_CSRMatrixI(hA); 182139accc25SStefano Zampini j = hypre_CSRMatrixJ(hA); 1822c69f721fSFande Kong a = hypre_CSRMatrixData(hA); 1823c69f721fSFande Kong 1824c69f721fSFande Kong for (ii = 0; ii < N; ii++) { 182539accc25SStefano Zampini HYPRE_Int jj, ibeg, iend, irow; 182639accc25SStefano Zampini 1827c69f721fSFande Kong irow = rows[ii]; 1828c69f721fSFande Kong ibeg = i[irow]; 1829c69f721fSFande Kong iend = i[irow + 1]; 1830c69f721fSFande Kong for (jj = ibeg; jj < iend; jj++) 1831c69f721fSFande Kong if (j[jj] == irow) a[jj] = diag; 1832c69f721fSFande Kong else a[jj] = 0.0; 1833c69f721fSFande Kong } 1834c69f721fSFande Kong PetscFunctionReturn(0); 1835c69f721fSFande Kong } 1836c69f721fSFande Kong 18379371c9d4SSatish Balay static PetscErrorCode MatZeroRows_HYPRE(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) { 1838c69f721fSFande Kong hypre_ParCSRMatrix *parcsr; 1839c69f721fSFande Kong PetscInt *lrows, len; 184039accc25SStefano Zampini HYPRE_Complex hdiag; 1841c69f721fSFande Kong 1842c69f721fSFande Kong PetscFunctionBegin; 184308401ef6SPierre Jolivet PetscCheck(!x && !b, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Does not support to modify the solution and the right hand size"); 18449566063dSJacob Faibussowitsch PetscCall(PetscHYPREScalarCast(diag, &hdiag)); 1845c69f721fSFande Kong /* retrieve the internal matrix */ 18469566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 1847c69f721fSFande Kong /* get locally owned rows */ 18489566063dSJacob Faibussowitsch PetscCall(MatZeroRowsMapLocal_Private(A, N, rows, &len, &lrows)); 1849c69f721fSFande Kong /* zero diagonal part */ 18509566063dSJacob Faibussowitsch PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr), len, lrows, hdiag)); 1851c69f721fSFande Kong /* zero off-diagonal part */ 18529566063dSJacob Faibussowitsch PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr), len, lrows, 0.0)); 1853c69f721fSFande Kong 18549566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 1855c69f721fSFande Kong PetscFunctionReturn(0); 1856c69f721fSFande Kong } 1857c69f721fSFande Kong 18589371c9d4SSatish Balay static PetscErrorCode MatAssemblyBegin_HYPRE(Mat mat, MatAssemblyType mode) { 1859c69f721fSFande Kong PetscFunctionBegin; 1860c69f721fSFande Kong if (mat->nooffprocentries) PetscFunctionReturn(0); 1861c69f721fSFande Kong 18629566063dSJacob Faibussowitsch PetscCall(MatStashScatterBegin_Private(mat, &mat->stash, mat->rmap->range)); 1863c69f721fSFande Kong PetscFunctionReturn(0); 1864c69f721fSFande Kong } 1865c69f721fSFande Kong 18669371c9d4SSatish Balay static PetscErrorCode MatGetRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) { 1867c69f721fSFande Kong hypre_ParCSRMatrix *parcsr; 18682cf14000SStefano Zampini HYPRE_Int hnz; 1869c69f721fSFande Kong 1870c69f721fSFande Kong PetscFunctionBegin; 1871c69f721fSFande Kong /* retrieve the internal matrix */ 18729566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 1873c69f721fSFande Kong /* call HYPRE API */ 1874792fecdfSBarry Smith PetscCallExternal(HYPRE_ParCSRMatrixGetRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v); 18752cf14000SStefano Zampini if (nz) *nz = (PetscInt)hnz; 1876c69f721fSFande Kong PetscFunctionReturn(0); 1877c69f721fSFande Kong } 1878c69f721fSFande Kong 18799371c9d4SSatish Balay static PetscErrorCode MatRestoreRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) { 1880c69f721fSFande Kong hypre_ParCSRMatrix *parcsr; 18812cf14000SStefano Zampini HYPRE_Int hnz; 1882c69f721fSFande Kong 1883c69f721fSFande Kong PetscFunctionBegin; 1884c69f721fSFande Kong /* retrieve the internal matrix */ 18859566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 1886c69f721fSFande Kong /* call HYPRE API */ 18872cf14000SStefano Zampini hnz = nz ? (HYPRE_Int)(*nz) : 0; 1888792fecdfSBarry Smith PetscCallExternal(HYPRE_ParCSRMatrixRestoreRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v); 1889c69f721fSFande Kong PetscFunctionReturn(0); 1890c69f721fSFande Kong } 1891c69f721fSFande Kong 18929371c9d4SSatish Balay static PetscErrorCode MatGetValues_HYPRE(Mat A, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) { 189345b8d346SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1894c69f721fSFande Kong PetscInt i; 18951d4906efSStefano Zampini 1896c69f721fSFande Kong PetscFunctionBegin; 1897c69f721fSFande Kong if (!m || !n) PetscFunctionReturn(0); 1898c69f721fSFande Kong /* Ignore negative row indices 1899c69f721fSFande Kong * And negative column indices should be automatically ignored in hypre 1900c69f721fSFande Kong * */ 19012cf14000SStefano Zampini for (i = 0; i < m; i++) { 19022cf14000SStefano Zampini if (idxm[i] >= 0) { 19032cf14000SStefano Zampini HYPRE_Int hn = (HYPRE_Int)n; 1904792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetValues, hA->ij, 1, &hn, (HYPRE_BigInt *)&idxm[i], (HYPRE_BigInt *)idxn, (HYPRE_Complex *)(v + i * n)); 19052cf14000SStefano Zampini } 19062cf14000SStefano Zampini } 1907c69f721fSFande Kong PetscFunctionReturn(0); 1908c69f721fSFande Kong } 1909c69f721fSFande Kong 19109371c9d4SSatish Balay static PetscErrorCode MatSetOption_HYPRE(Mat A, MatOption op, PetscBool flg) { 1911ddbeb582SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1912ddbeb582SStefano Zampini 1913ddbeb582SStefano Zampini PetscFunctionBegin; 1914c6698e78SStefano Zampini switch (op) { 1915ddbeb582SStefano Zampini case MAT_NO_OFF_PROC_ENTRIES: 191648a46eb9SPierre Jolivet if (flg) PetscCallExternal(HYPRE_IJMatrixSetMaxOffProcElmts, hA->ij, 0); 1917ddbeb582SStefano Zampini break; 19189371c9d4SSatish Balay case MAT_SORTED_FULL: hA->sorted_full = flg; break; 19199371c9d4SSatish Balay default: break; 1920ddbeb582SStefano Zampini } 1921ddbeb582SStefano Zampini PetscFunctionReturn(0); 1922ddbeb582SStefano Zampini } 1923c69f721fSFande Kong 19249371c9d4SSatish Balay static PetscErrorCode MatView_HYPRE(Mat A, PetscViewer view) { 192545b8d346SStefano Zampini PetscViewerFormat format; 192645b8d346SStefano Zampini 192745b8d346SStefano Zampini PetscFunctionBegin; 19289566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(view, &format)); 19296ea7df73SStefano Zampini if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(0); 193045b8d346SStefano Zampini if (format != PETSC_VIEWER_NATIVE) { 19316ea7df73SStefano Zampini Mat B; 19326ea7df73SStefano Zampini hypre_ParCSRMatrix *parcsr; 19336ea7df73SStefano Zampini PetscErrorCode (*mview)(Mat, PetscViewer) = NULL; 19346ea7df73SStefano Zampini 19359566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 19369566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(parcsr, MATAIJ, PETSC_USE_POINTER, &B)); 19379566063dSJacob Faibussowitsch PetscCall(MatGetOperation(B, MATOP_VIEW, (void (**)(void)) & mview)); 193828b400f6SJacob Faibussowitsch PetscCheck(mview, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Missing view operation"); 19399566063dSJacob Faibussowitsch PetscCall((*mview)(B, view)); 19409566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 194145b8d346SStefano Zampini } else { 194245b8d346SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 194345b8d346SStefano Zampini PetscMPIInt size; 194445b8d346SStefano Zampini PetscBool isascii; 194545b8d346SStefano Zampini const char *filename; 194645b8d346SStefano Zampini 194745b8d346SStefano Zampini /* HYPRE uses only text files */ 19489566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERASCII, &isascii)); 194928b400f6SJacob Faibussowitsch PetscCheck(isascii, PetscObjectComm((PetscObject)view), PETSC_ERR_SUP, "PetscViewerType %s: native HYPRE format needs PETSCVIEWERASCII", ((PetscObject)view)->type_name); 19509566063dSJacob Faibussowitsch PetscCall(PetscViewerFileGetName(view, &filename)); 1951792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixPrint, hA->ij, filename); 19529566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(hA->comm, &size)); 195345b8d346SStefano Zampini if (size > 1) { 19549566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(view, "Matrix files: %s.%05d ... %s.%05d\n", filename, 0, filename, size - 1)); 195545b8d346SStefano Zampini } else { 19569566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(view, "Matrix file: %s.%05d\n", filename, 0)); 195745b8d346SStefano Zampini } 195845b8d346SStefano Zampini } 195945b8d346SStefano Zampini PetscFunctionReturn(0); 196045b8d346SStefano Zampini } 196145b8d346SStefano Zampini 19629371c9d4SSatish Balay static PetscErrorCode MatDuplicate_HYPRE(Mat A, MatDuplicateOption op, Mat *B) { 19636abb4441SStefano Zampini hypre_ParCSRMatrix *parcsr = NULL; 196445b8d346SStefano Zampini PetscCopyMode cpmode; 196545b8d346SStefano Zampini 196645b8d346SStefano Zampini PetscFunctionBegin; 19679566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 196845b8d346SStefano Zampini if (op == MAT_DO_NOT_COPY_VALUES || op == MAT_SHARE_NONZERO_PATTERN) { 19690e6427aaSSatish Balay parcsr = hypre_ParCSRMatrixClone(parcsr, 0); 197045b8d346SStefano Zampini cpmode = PETSC_OWN_POINTER; 197145b8d346SStefano Zampini } else { 197245b8d346SStefano Zampini cpmode = PETSC_COPY_VALUES; 197345b8d346SStefano Zampini } 19749566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(parcsr, MATHYPRE, cpmode, B)); 197545b8d346SStefano Zampini PetscFunctionReturn(0); 197645b8d346SStefano Zampini } 197745b8d346SStefano Zampini 19789371c9d4SSatish Balay static PetscErrorCode MatCopy_HYPRE(Mat A, Mat B, MatStructure str) { 1979465edc17SStefano Zampini hypre_ParCSRMatrix *acsr, *bcsr; 1980465edc17SStefano Zampini 1981465edc17SStefano Zampini PetscFunctionBegin; 1982465edc17SStefano Zampini if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) { 19839566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &acsr)); 19849566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(B, &bcsr)); 1985792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixCopy, acsr, bcsr, 1); 19869566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_SORTED_FULL, PETSC_TRUE)); /* "perfect" preallocation, so no need for hypre_AuxParCSRMatrixNeedAux */ 19879566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 19889566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 1989465edc17SStefano Zampini } else { 19909566063dSJacob Faibussowitsch PetscCall(MatCopy_Basic(A, B, str)); 1991465edc17SStefano Zampini } 1992465edc17SStefano Zampini PetscFunctionReturn(0); 1993465edc17SStefano Zampini } 1994465edc17SStefano Zampini 19959371c9d4SSatish Balay static PetscErrorCode MatGetDiagonal_HYPRE(Mat A, Vec d) { 19966305df00SStefano Zampini hypre_ParCSRMatrix *parcsr; 19976305df00SStefano Zampini hypre_CSRMatrix *dmat; 199839accc25SStefano Zampini HYPRE_Complex *a; 199939accc25SStefano Zampini HYPRE_Complex *data = NULL; 20002cf14000SStefano Zampini HYPRE_Int *diag = NULL; 20012cf14000SStefano Zampini PetscInt i; 20026305df00SStefano Zampini PetscBool cong; 20036305df00SStefano Zampini 20046305df00SStefano Zampini PetscFunctionBegin; 20059566063dSJacob Faibussowitsch PetscCall(MatHasCongruentLayouts(A, &cong)); 200628b400f6SJacob Faibussowitsch PetscCheck(cong, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only for square matrices with same local distributions of rows and columns"); 200776bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 20086305df00SStefano Zampini PetscBool miss; 20099566063dSJacob Faibussowitsch PetscCall(MatMissingDiagonal(A, &miss, NULL)); 201008401ef6SPierre Jolivet PetscCheck(!miss || !A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented when diagonal entries are missing"); 20116305df00SStefano Zampini } 20129566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 20136305df00SStefano Zampini dmat = hypre_ParCSRMatrixDiag(parcsr); 20146305df00SStefano Zampini if (dmat) { 201539accc25SStefano Zampini /* this cast fixes the clang error: implicit conversion from 'HYPRE_Complex' (aka '_Complex double') to 'double' is not permitted in C++ */ 20169566063dSJacob Faibussowitsch PetscCall(VecGetArray(d, (PetscScalar **)&a)); 20172cf14000SStefano Zampini diag = hypre_CSRMatrixI(dmat); 201839accc25SStefano Zampini data = hypre_CSRMatrixData(dmat); 20196305df00SStefano Zampini for (i = 0; i < A->rmap->n; i++) a[i] = data[diag[i]]; 20209566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(d, (PetscScalar **)&a)); 20216305df00SStefano Zampini } 20226305df00SStefano Zampini PetscFunctionReturn(0); 20236305df00SStefano Zampini } 20246305df00SStefano Zampini 2025363d496dSStefano Zampini #include <petscblaslapack.h> 2026363d496dSStefano Zampini 20279371c9d4SSatish Balay static PetscErrorCode MatAXPY_HYPRE(Mat Y, PetscScalar a, Mat X, MatStructure str) { 2028363d496dSStefano Zampini PetscFunctionBegin; 20296ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 20306ea7df73SStefano Zampini { 20316ea7df73SStefano Zampini Mat B; 20326ea7df73SStefano Zampini hypre_ParCSRMatrix *x, *y, *z; 20336ea7df73SStefano Zampini 20349566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR(Y, &y)); 20359566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR(X, &x)); 2036792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixAdd, 1.0, y, 1.0, x, &z); 20379566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(z, MATHYPRE, PETSC_OWN_POINTER, &B)); 20389566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(Y, &B)); 20396ea7df73SStefano Zampini } 20406ea7df73SStefano Zampini #else 2041363d496dSStefano Zampini if (str == SAME_NONZERO_PATTERN) { 2042363d496dSStefano Zampini hypre_ParCSRMatrix *x, *y; 2043363d496dSStefano Zampini hypre_CSRMatrix *xloc, *yloc; 2044363d496dSStefano Zampini PetscInt xnnz, ynnz; 204539accc25SStefano Zampini HYPRE_Complex *xarr, *yarr; 2046363d496dSStefano Zampini PetscBLASInt one = 1, bnz; 2047363d496dSStefano Zampini 20489566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR(Y, &y)); 20499566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR(X, &x)); 2050363d496dSStefano Zampini 2051363d496dSStefano Zampini /* diagonal block */ 2052363d496dSStefano Zampini xloc = hypre_ParCSRMatrixDiag(x); 2053363d496dSStefano Zampini yloc = hypre_ParCSRMatrixDiag(y); 2054363d496dSStefano Zampini xnnz = 0; 2055363d496dSStefano Zampini ynnz = 0; 2056363d496dSStefano Zampini xarr = NULL; 2057363d496dSStefano Zampini yarr = NULL; 2058363d496dSStefano Zampini if (xloc) { 205939accc25SStefano Zampini xarr = hypre_CSRMatrixData(xloc); 2060363d496dSStefano Zampini xnnz = hypre_CSRMatrixNumNonzeros(xloc); 2061363d496dSStefano Zampini } 2062363d496dSStefano Zampini if (yloc) { 206339accc25SStefano Zampini yarr = hypre_CSRMatrixData(yloc); 2064363d496dSStefano Zampini ynnz = hypre_CSRMatrixNumNonzeros(yloc); 2065363d496dSStefano Zampini } 206608401ef6SPierre Jolivet PetscCheck(xnnz == ynnz, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Different number of nonzeros in diagonal block %" PetscInt_FMT " != %" PetscInt_FMT, xnnz, ynnz); 20679566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(xnnz, &bnz)); 2068792fecdfSBarry Smith PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one)); 2069363d496dSStefano Zampini 2070363d496dSStefano Zampini /* off-diagonal block */ 2071363d496dSStefano Zampini xloc = hypre_ParCSRMatrixOffd(x); 2072363d496dSStefano Zampini yloc = hypre_ParCSRMatrixOffd(y); 2073363d496dSStefano Zampini xnnz = 0; 2074363d496dSStefano Zampini ynnz = 0; 2075363d496dSStefano Zampini xarr = NULL; 2076363d496dSStefano Zampini yarr = NULL; 2077363d496dSStefano Zampini if (xloc) { 207839accc25SStefano Zampini xarr = hypre_CSRMatrixData(xloc); 2079363d496dSStefano Zampini xnnz = hypre_CSRMatrixNumNonzeros(xloc); 2080363d496dSStefano Zampini } 2081363d496dSStefano Zampini if (yloc) { 208239accc25SStefano Zampini yarr = hypre_CSRMatrixData(yloc); 2083363d496dSStefano Zampini ynnz = hypre_CSRMatrixNumNonzeros(yloc); 2084363d496dSStefano Zampini } 208508401ef6SPierre Jolivet PetscCheck(xnnz == ynnz, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Different number of nonzeros in off-diagonal block %" PetscInt_FMT " != %" PetscInt_FMT, xnnz, ynnz); 20869566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(xnnz, &bnz)); 2087792fecdfSBarry Smith PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one)); 2088363d496dSStefano Zampini } else if (str == SUBSET_NONZERO_PATTERN) { 20899566063dSJacob Faibussowitsch PetscCall(MatAXPY_Basic(Y, a, X, str)); 2090363d496dSStefano Zampini } else { 2091363d496dSStefano Zampini Mat B; 2092363d496dSStefano Zampini 20939566063dSJacob Faibussowitsch PetscCall(MatAXPY_Basic_Preallocate(Y, X, &B)); 20949566063dSJacob Faibussowitsch PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str)); 20959566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(Y, &B)); 2096363d496dSStefano Zampini } 20976ea7df73SStefano Zampini #endif 2098363d496dSStefano Zampini PetscFunctionReturn(0); 2099363d496dSStefano Zampini } 2100363d496dSStefano Zampini 21019371c9d4SSatish Balay static PetscErrorCode MatSetPreallocationCOO_HYPRE(Mat mat, PetscCount coo_n, PetscInt coo_i[], PetscInt coo_j[]) { 21025fbaff96SJunchao Zhang MPI_Comm comm; 21035fbaff96SJunchao Zhang PetscMPIInt size; 21045fbaff96SJunchao Zhang PetscLayout rmap, cmap; 21055fbaff96SJunchao Zhang Mat_HYPRE *hmat; 21065fbaff96SJunchao Zhang hypre_ParCSRMatrix *parCSR; 21075fbaff96SJunchao Zhang hypre_CSRMatrix *diag, *offd; 21085fbaff96SJunchao Zhang Mat A, B, cooMat; 21095fbaff96SJunchao Zhang PetscScalar *Aa, *Ba; 21105fbaff96SJunchao Zhang HYPRE_MemoryLocation hypreMemtype = HYPRE_MEMORY_HOST; 21115fbaff96SJunchao Zhang PetscMemType petscMemtype; 21125fbaff96SJunchao Zhang MatType matType = MATAIJ; /* default type of cooMat */ 21135fbaff96SJunchao Zhang 21145fbaff96SJunchao Zhang PetscFunctionBegin; 21155fbaff96SJunchao Zhang /* Build an agent matrix cooMat whose type is either MATAIJ or MATAIJKOKKOS. 21165fbaff96SJunchao Zhang It has the same sparsity pattern as mat, and also shares the data array with mat. We use cooMat to do the COO work. 21175fbaff96SJunchao Zhang */ 21185fbaff96SJunchao Zhang PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 21195fbaff96SJunchao Zhang PetscCallMPI(MPI_Comm_size(comm, &size)); 21205fbaff96SJunchao Zhang PetscCall(PetscLayoutSetUp(mat->rmap)); 21215fbaff96SJunchao Zhang PetscCall(PetscLayoutSetUp(mat->cmap)); 21225fbaff96SJunchao Zhang PetscCall(MatGetLayouts(mat, &rmap, &cmap)); 21235fbaff96SJunchao Zhang 21245fbaff96SJunchao Zhang /* I do not know how hypre_ParCSRMatrix stores diagonal elements for non-square matrices, so I just give up now */ 21255fbaff96SJunchao Zhang PetscCheck(rmap->N == cmap->N, comm, PETSC_ERR_SUP, "MATHYPRE COO cannot handle non-square matrices"); 21265fbaff96SJunchao Zhang 21275fbaff96SJunchao Zhang #if defined(PETSC_HAVE_DEVICE) 21285fbaff96SJunchao Zhang if (!mat->boundtocpu) { /* mat will be on device, so will cooMat */ 21295fbaff96SJunchao Zhang #if defined(PETSC_HAVE_KOKKOS) 21305fbaff96SJunchao Zhang matType = MATAIJKOKKOS; 21315fbaff96SJunchao Zhang #else 21325fbaff96SJunchao Zhang SETERRQ(comm, PETSC_ERR_SUP, "To support MATHYPRE COO assembly on device, we need Kokkos, e.g., --download-kokkos --download-kokkos-kernels"); 21335fbaff96SJunchao Zhang #endif 21345fbaff96SJunchao Zhang } 21355fbaff96SJunchao Zhang #endif 21365fbaff96SJunchao Zhang 21375fbaff96SJunchao Zhang /* Do COO preallocation through cooMat */ 21385fbaff96SJunchao Zhang hmat = (Mat_HYPRE *)mat->data; 21395fbaff96SJunchao Zhang PetscCall(MatDestroy(&hmat->cooMat)); 21405fbaff96SJunchao Zhang PetscCall(MatCreate(comm, &cooMat)); 21415fbaff96SJunchao Zhang PetscCall(MatSetType(cooMat, matType)); 21425fbaff96SJunchao Zhang PetscCall(MatSetLayouts(cooMat, rmap, cmap)); 21435fbaff96SJunchao Zhang PetscCall(MatSetPreallocationCOO(cooMat, coo_n, coo_i, coo_j)); 21445fbaff96SJunchao Zhang 21455fbaff96SJunchao Zhang /* Copy the sparsity pattern from cooMat to hypre IJMatrix hmat->ij */ 21465fbaff96SJunchao Zhang PetscCall(MatSetOption(mat, MAT_SORTED_FULL, PETSC_TRUE)); 21475fbaff96SJunchao Zhang PetscCall(MatSetOption(mat, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE)); 21485fbaff96SJunchao Zhang PetscCall(MatHYPRE_CreateFromMat(cooMat, hmat)); /* Create hmat->ij and preallocate it */ 21495fbaff96SJunchao Zhang PetscCall(MatHYPRE_IJMatrixCopy(cooMat, hmat->ij)); /* Copy A's (a,i,j) to hmat->ij. To reuse code. Copying 'a' is not really needed */ 21505fbaff96SJunchao Zhang 21515fbaff96SJunchao Zhang mat->preallocated = PETSC_TRUE; 21525fbaff96SJunchao Zhang PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 21535fbaff96SJunchao Zhang PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); /* Migrate mat to device if it is bound to. Hypre builds its own SpMV context here */ 21545fbaff96SJunchao Zhang 21555fbaff96SJunchao Zhang /* Alias cooMat's data array to IJMatrix's */ 2156792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hmat->ij, (void **)&parCSR); 21575fbaff96SJunchao Zhang diag = hypre_ParCSRMatrixDiag(parCSR); 21585fbaff96SJunchao Zhang offd = hypre_ParCSRMatrixOffd(parCSR); 21595fbaff96SJunchao Zhang 21605fbaff96SJunchao Zhang hypreMemtype = hypre_CSRMatrixMemoryLocation(diag); 21615fbaff96SJunchao Zhang A = (size == 1) ? cooMat : ((Mat_MPIAIJ *)cooMat->data)->A; 21625fbaff96SJunchao Zhang PetscCall(MatSeqAIJGetCSRAndMemType(A, NULL, NULL, &Aa, &petscMemtype)); 21639371c9d4SSatish Balay PetscAssert((PetscMemTypeHost(petscMemtype) && hypreMemtype == HYPRE_MEMORY_HOST) || (PetscMemTypeDevice(petscMemtype) && hypreMemtype == HYPRE_MEMORY_DEVICE), comm, PETSC_ERR_PLIB, "PETSc and hypre's memory types mismatch"); 21645fbaff96SJunchao Zhang 21655fbaff96SJunchao Zhang hmat->diagJ = hypre_CSRMatrixJ(diag); 2166e77caa6dSBarry Smith PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(diag), hypreMemtype)); 21675fbaff96SJunchao Zhang hypre_CSRMatrixData(diag) = (HYPRE_Complex *)Aa; 21685fbaff96SJunchao Zhang hypre_CSRMatrixOwnsData(diag) = 0; /* Take ownership of (j,a) away from hypre. As a result, we need to free them on our own */ 21695fbaff96SJunchao Zhang 21705fbaff96SJunchao Zhang /* Copy diagonal pointers of A to device to facilitate MatSeqAIJMoveDiagonalValuesFront_SeqAIJKokkos */ 21715fbaff96SJunchao Zhang if (hypreMemtype == HYPRE_MEMORY_DEVICE) { 2172e77caa6dSBarry Smith PetscStackCallExternalVoid("hypre_TAlloc", hmat->diag = hypre_TAlloc(PetscInt, rmap->n, hypreMemtype)); 21735fbaff96SJunchao Zhang PetscCall(MatMarkDiagonal_SeqAIJ(A)); /* We need updated diagonal positions */ 2174e77caa6dSBarry Smith PetscStackCallExternalVoid("hypre_TMemcpy", hypre_TMemcpy(hmat->diag, ((Mat_SeqAIJ *)A->data)->diag, PetscInt, rmap->n, hypreMemtype, HYPRE_MEMORY_HOST)); 21755fbaff96SJunchao Zhang } 21765fbaff96SJunchao Zhang 21775fbaff96SJunchao Zhang if (size > 1) { 21785fbaff96SJunchao Zhang B = ((Mat_MPIAIJ *)cooMat->data)->B; 21795fbaff96SJunchao Zhang PetscCall(MatSeqAIJGetCSRAndMemType(B, NULL, NULL, &Ba, &petscMemtype)); 21805fbaff96SJunchao Zhang hmat->offdJ = hypre_CSRMatrixJ(offd); 2181e77caa6dSBarry Smith PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(offd), hypreMemtype)); 21825fbaff96SJunchao Zhang hypre_CSRMatrixData(offd) = (HYPRE_Complex *)Ba; 21835fbaff96SJunchao Zhang hypre_CSRMatrixOwnsData(offd) = 0; 21845fbaff96SJunchao Zhang } 21855fbaff96SJunchao Zhang 21865fbaff96SJunchao Zhang /* Record cooMat for use in MatSetValuesCOO_HYPRE */ 21875fbaff96SJunchao Zhang hmat->cooMat = cooMat; 21885fbaff96SJunchao Zhang hmat->memType = hypreMemtype; 21895fbaff96SJunchao Zhang PetscFunctionReturn(0); 21905fbaff96SJunchao Zhang } 21915fbaff96SJunchao Zhang 21929371c9d4SSatish Balay static PetscErrorCode MatSetValuesCOO_HYPRE(Mat mat, const PetscScalar v[], InsertMode imode) { 21935fbaff96SJunchao Zhang Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data; 21945fbaff96SJunchao Zhang PetscMPIInt size; 21955fbaff96SJunchao Zhang Mat A; 21965fbaff96SJunchao Zhang 21975fbaff96SJunchao Zhang PetscFunctionBegin; 21985fbaff96SJunchao Zhang PetscCheck(hmat->cooMat, hmat->comm, PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet"); 21995fbaff96SJunchao Zhang PetscCallMPI(MPI_Comm_size(hmat->comm, &size)); 22005fbaff96SJunchao Zhang PetscCall(MatSetValuesCOO(hmat->cooMat, v, imode)); 22015fbaff96SJunchao Zhang 22025fbaff96SJunchao Zhang /* Move diagonal elements of the diagonal block to the front of their row, as needed by ParCSRMatrix. So damn hacky */ 22035fbaff96SJunchao Zhang A = (size == 1) ? hmat->cooMat : ((Mat_MPIAIJ *)hmat->cooMat->data)->A; 22045fbaff96SJunchao Zhang if (hmat->memType == HYPRE_MEMORY_HOST) { 22055fbaff96SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 22065fbaff96SJunchao Zhang PetscInt i, m, *Ai = aij->i, *Adiag = aij->diag; 22075fbaff96SJunchao Zhang PetscScalar *Aa = aij->a, tmp; 22085fbaff96SJunchao Zhang 22095fbaff96SJunchao Zhang PetscCall(MatGetSize(A, &m, NULL)); 22105fbaff96SJunchao Zhang for (i = 0; i < m; i++) { 22115fbaff96SJunchao Zhang if (Adiag[i] >= Ai[i] && Adiag[i] < Ai[i + 1]) { /* Digonal element of this row exists in a[] and j[] */ 22125fbaff96SJunchao Zhang tmp = Aa[Ai[i]]; 22135fbaff96SJunchao Zhang Aa[Ai[i]] = Aa[Adiag[i]]; 22145fbaff96SJunchao Zhang Aa[Adiag[i]] = tmp; 22155fbaff96SJunchao Zhang } 22165fbaff96SJunchao Zhang } 22175fbaff96SJunchao Zhang } else { 22185fbaff96SJunchao Zhang #if defined(PETSC_HAVE_KOKKOS_KERNELS) 22195fbaff96SJunchao Zhang PetscCall(MatSeqAIJMoveDiagonalValuesFront_SeqAIJKokkos(A, hmat->diag)); 22205fbaff96SJunchao Zhang #endif 22215fbaff96SJunchao Zhang } 22225fbaff96SJunchao Zhang PetscFunctionReturn(0); 22235fbaff96SJunchao Zhang } 22245fbaff96SJunchao Zhang 2225a055b5aaSBarry Smith /*MC 2226a055b5aaSBarry Smith MATHYPRE - MATHYPRE = "hypre" - A matrix type to be used for sequential and parallel sparse matrices 2227a055b5aaSBarry Smith based on the hypre IJ interface. 2228a055b5aaSBarry Smith 2229a055b5aaSBarry Smith Level: intermediate 2230a055b5aaSBarry Smith 223111a5261eSBarry Smith .seealso: `MatCreate()`, `MatHYPRESetPreallocation` 2232a055b5aaSBarry Smith M*/ 2233a055b5aaSBarry Smith 22349371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatCreate_HYPRE(Mat B) { 223563c07aadSStefano Zampini Mat_HYPRE *hB; 223663c07aadSStefano Zampini 223763c07aadSStefano Zampini PetscFunctionBegin; 2238*4dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&hB)); 22396ea7df73SStefano Zampini 2240978814f1SStefano Zampini hB->inner_free = PETSC_TRUE; 2241c69f721fSFande Kong hB->available = PETSC_TRUE; 2242336664bdSPierre Jolivet hB->sorted_full = PETSC_FALSE; /* no assumption whether column indices are sorted or not */ 2243c69f721fSFande Kong hB->size = 0; 2244c69f721fSFande Kong hB->array = NULL; 2245978814f1SStefano Zampini 224663c07aadSStefano Zampini B->data = (void *)hB; 224763c07aadSStefano Zampini B->assembled = PETSC_FALSE; 224863c07aadSStefano Zampini 22499566063dSJacob Faibussowitsch PetscCall(PetscMemzero(B->ops, sizeof(struct _MatOps))); 225063c07aadSStefano Zampini B->ops->mult = MatMult_HYPRE; 225163c07aadSStefano Zampini B->ops->multtranspose = MatMultTranspose_HYPRE; 2252414bd5c3SStefano Zampini B->ops->multadd = MatMultAdd_HYPRE; 2253414bd5c3SStefano Zampini B->ops->multtransposeadd = MatMultTransposeAdd_HYPRE; 225463c07aadSStefano Zampini B->ops->setup = MatSetUp_HYPRE; 225563c07aadSStefano Zampini B->ops->destroy = MatDestroy_HYPRE; 225663c07aadSStefano Zampini B->ops->assemblyend = MatAssemblyEnd_HYPRE; 2257c69f721fSFande Kong B->ops->assemblybegin = MatAssemblyBegin_HYPRE; 2258d975228cSstefano_zampini B->ops->setvalues = MatSetValues_HYPRE; 225968ec7858SStefano Zampini B->ops->missingdiagonal = MatMissingDiagonal_HYPRE; 226068ec7858SStefano Zampini B->ops->scale = MatScale_HYPRE; 226168ec7858SStefano Zampini B->ops->zerorowscolumns = MatZeroRowsColumns_HYPRE; 2262c69f721fSFande Kong B->ops->zeroentries = MatZeroEntries_HYPRE; 2263c69f721fSFande Kong B->ops->zerorows = MatZeroRows_HYPRE; 2264c69f721fSFande Kong B->ops->getrow = MatGetRow_HYPRE; 2265c69f721fSFande Kong B->ops->restorerow = MatRestoreRow_HYPRE; 2266c69f721fSFande Kong B->ops->getvalues = MatGetValues_HYPRE; 2267ddbeb582SStefano Zampini B->ops->setoption = MatSetOption_HYPRE; 226845b8d346SStefano Zampini B->ops->duplicate = MatDuplicate_HYPRE; 2269465edc17SStefano Zampini B->ops->copy = MatCopy_HYPRE; 227045b8d346SStefano Zampini B->ops->view = MatView_HYPRE; 22716305df00SStefano Zampini B->ops->getdiagonal = MatGetDiagonal_HYPRE; 2272363d496dSStefano Zampini B->ops->axpy = MatAXPY_HYPRE; 22734222ddf1SHong Zhang B->ops->productsetfromoptions = MatProductSetFromOptions_HYPRE; 22746ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 22756ea7df73SStefano Zampini B->ops->bindtocpu = MatBindToCPU_HYPRE; 22766ea7df73SStefano Zampini B->boundtocpu = PETSC_FALSE; 22776ea7df73SStefano Zampini #endif 227845b8d346SStefano Zampini 227945b8d346SStefano Zampini /* build cache for off array entries formed */ 22809566063dSJacob Faibussowitsch PetscCall(MatStashCreate_Private(PetscObjectComm((PetscObject)B), 1, &B->stash)); 228163c07aadSStefano Zampini 22829566063dSJacob Faibussowitsch PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)B), &hB->comm)); 22839566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRE)); 22849566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_aij_C", MatConvert_HYPRE_AIJ)); 22859566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_is_C", MatConvert_HYPRE_IS)); 22869566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_hypre_C", MatProductSetFromOptions_HYPRE)); 22879566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaij_hypre_C", MatProductSetFromOptions_HYPRE)); 22889566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPRESetPreallocation_C", MatHYPRESetPreallocation_HYPRE)); 22899566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPREGetParCSR_C", MatHYPREGetParCSR_HYPRE)); 22905fbaff96SJunchao Zhang PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_HYPRE)); 22915fbaff96SJunchao Zhang PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetValuesCOO_C", MatSetValuesCOO_HYPRE)); 22926ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 22936ea7df73SStefano Zampini #if defined(HYPRE_USING_HIP) 22949566063dSJacob Faibussowitsch PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP)); 22959566063dSJacob Faibussowitsch PetscCall(MatSetVecType(B, VECHIP)); 22966ea7df73SStefano Zampini #endif 22976ea7df73SStefano Zampini #if defined(HYPRE_USING_CUDA) 22989566063dSJacob Faibussowitsch PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA)); 22999566063dSJacob Faibussowitsch PetscCall(MatSetVecType(B, VECCUDA)); 23006ea7df73SStefano Zampini #endif 23016ea7df73SStefano Zampini #endif 230263c07aadSStefano Zampini PetscFunctionReturn(0); 230363c07aadSStefano Zampini } 230463c07aadSStefano Zampini 23059371c9d4SSatish Balay static PetscErrorCode hypre_array_destroy(void *ptr) { 2306225daaf8SStefano Zampini PetscFunctionBegin; 2307e6de0934SSatish Balay hypre_TFree(ptr, HYPRE_MEMORY_HOST); 2308225daaf8SStefano Zampini PetscFunctionReturn(0); 2309225daaf8SStefano Zampini } 2310