163c07aadSStefano Zampini /* 263c07aadSStefano Zampini Creates hypre ijmatrix from PETSc matrix 363c07aadSStefano Zampini */ 4225daaf8SStefano Zampini 5c6698e78SStefano Zampini #include <petscpkg_version.h> 639accc25SStefano Zampini #include <petsc/private/petschypre.h> 7dd9c0a25Sstefano_zampini #include <petscmathypre.h> 863c07aadSStefano Zampini #include <petsc/private/matimpl.h> 9a4af0ceeSJacob Faibussowitsch #include <petsc/private/deviceimpl.h> 1063c07aadSStefano Zampini #include <../src/mat/impls/hypre/mhypre.h> 1163c07aadSStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h> 1258968eb6SStefano Zampini #include <../src/vec/vec/impls/hypre/vhyp.h> 1358968eb6SStefano Zampini #include <HYPRE.h> 14c1a070e6SStefano Zampini #include <HYPRE_utilities.h> 15cd8bc7baSStefano Zampini #include <_hypre_parcsr_ls.h> 1668ec7858SStefano Zampini #include <_hypre_sstruct_ls.h> 1763c07aadSStefano Zampini 180e6427aaSSatish Balay #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0) 190e6427aaSSatish Balay #define hypre_ParCSRMatrixClone(A, B) hypre_ParCSRMatrixCompleteClone(A) 200e6427aaSSatish Balay #endif 210e6427aaSSatish Balay 2263c07aadSStefano Zampini static PetscErrorCode MatHYPRE_CreateFromMat(Mat, Mat_HYPRE *); 2363c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat, Mat, HYPRE_IJMatrix); 24b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_MPIAIJ(Mat, HYPRE_IJMatrix); 25b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_SeqAIJ(Mat, HYPRE_IJMatrix); 2639accc25SStefano Zampini static PetscErrorCode MatHYPRE_MultKernel_Private(Mat, HYPRE_Complex, Vec, HYPRE_Complex, Vec, PetscBool); 276ea7df73SStefano Zampini static PetscErrorCode MatSetValues_HYPRE(Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[], const PetscScalar[], InsertMode ins); 2863c07aadSStefano Zampini 29d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat A_d, Mat A_o, HYPRE_IJMatrix ij) 30d71ae5a4SJacob Faibussowitsch { 3163c07aadSStefano Zampini PetscInt i, n_d, n_o; 3263c07aadSStefano Zampini const PetscInt *ia_d, *ia_o; 3363c07aadSStefano Zampini PetscBool done_d = PETSC_FALSE, done_o = PETSC_FALSE; 342cf14000SStefano Zampini HYPRE_Int *nnz_d = NULL, *nnz_o = NULL; 3563c07aadSStefano Zampini 3663c07aadSStefano Zampini PetscFunctionBegin; 3763c07aadSStefano Zampini if (A_d) { /* determine number of nonzero entries in local diagonal part */ 389566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A_d, 0, PETSC_FALSE, PETSC_FALSE, &n_d, &ia_d, NULL, &done_d)); 3963c07aadSStefano Zampini if (done_d) { 409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_d, &nnz_d)); 41ad540459SPierre Jolivet for (i = 0; i < n_d; i++) nnz_d[i] = ia_d[i + 1] - ia_d[i]; 4263c07aadSStefano Zampini } 439566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A_d, 0, PETSC_FALSE, PETSC_FALSE, NULL, &ia_d, NULL, &done_d)); 4463c07aadSStefano Zampini } 4563c07aadSStefano Zampini if (A_o) { /* determine number of nonzero entries in local off-diagonal part */ 469566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A_o, 0, PETSC_FALSE, PETSC_FALSE, &n_o, &ia_o, NULL, &done_o)); 4763c07aadSStefano Zampini if (done_o) { 489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_o, &nnz_o)); 49ad540459SPierre Jolivet for (i = 0; i < n_o; i++) nnz_o[i] = ia_o[i + 1] - ia_o[i]; 5063c07aadSStefano Zampini } 519566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A_o, 0, PETSC_FALSE, PETSC_FALSE, &n_o, &ia_o, NULL, &done_o)); 5263c07aadSStefano Zampini } 5363c07aadSStefano Zampini if (done_d) { /* set number of nonzeros in HYPRE IJ matrix */ 5463c07aadSStefano Zampini if (!done_o) { /* only diagonal part */ 559566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n_d, &nnz_o)); 5663c07aadSStefano Zampini } 57c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0) 58c6698e78SStefano Zampini { /* If we don't do this, the columns of the matrix will be all zeros! */ 59c6698e78SStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 60c6698e78SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij); 61c6698e78SStefano Zampini hypre_AuxParCSRMatrixDestroy(aux_matrix); 62c6698e78SStefano Zampini hypre_IJMatrixTranslator(ij) = NULL; 63792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, ij, nnz_d, nnz_o); 6422235d61SPierre Jolivet /* it seems they partially fixed it in 2.19.0 */ 6522235d61SPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 66c6698e78SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij); 67c6698e78SStefano Zampini hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1; 6822235d61SPierre Jolivet #endif 69c6698e78SStefano Zampini } 70c6698e78SStefano Zampini #else 71792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, ij, nnz_d, nnz_o); 72c6698e78SStefano Zampini #endif 739566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz_d)); 749566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz_o)); 7563c07aadSStefano Zampini } 763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7763c07aadSStefano Zampini } 7863c07aadSStefano Zampini 79d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_CreateFromMat(Mat A, Mat_HYPRE *hA) 80d71ae5a4SJacob Faibussowitsch { 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; 90ea9ee2c1SPierre Jolivet PetscHYPREInitialize(); 91651b1cf9SStefano Zampini if (hA->ij) { 92651b1cf9SStefano Zampini if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL; 93651b1cf9SStefano Zampini PetscCallExternal(HYPRE_IJMatrixDestroy, hA->ij); 94651b1cf9SStefano Zampini } 95792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rstart, rend - 1, cstart, cend - 1, &hA->ij); 96792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR); 9763c07aadSStefano Zampini { 9863c07aadSStefano Zampini PetscBool same; 9963c07aadSStefano Zampini Mat A_d, A_o; 10063c07aadSStefano Zampini const PetscInt *colmap; 1019566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &same)); 10263c07aadSStefano Zampini if (same) { 1039566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(A, &A_d, &A_o, &colmap)); 1049566063dSJacob Faibussowitsch PetscCall(MatHYPRE_IJMatrixPreallocate(A_d, A_o, hA->ij)); 1053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10663c07aadSStefano Zampini } 1079566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIBAIJ, &same)); 10863c07aadSStefano Zampini if (same) { 1099566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJGetSeqBAIJ(A, &A_d, &A_o, &colmap)); 1109566063dSJacob Faibussowitsch PetscCall(MatHYPRE_IJMatrixPreallocate(A_d, A_o, hA->ij)); 1113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11263c07aadSStefano Zampini } 1139566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &same)); 11463c07aadSStefano Zampini if (same) { 1159566063dSJacob Faibussowitsch PetscCall(MatHYPRE_IJMatrixPreallocate(A, NULL, hA->ij)); 1163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11763c07aadSStefano Zampini } 1189566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQBAIJ, &same)); 11963c07aadSStefano Zampini if (same) { 1209566063dSJacob Faibussowitsch PetscCall(MatHYPRE_IJMatrixPreallocate(A, NULL, hA->ij)); 1213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12263c07aadSStefano Zampini } 12363c07aadSStefano Zampini } 1243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12563c07aadSStefano Zampini } 12663c07aadSStefano Zampini 127b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ(Mat A, HYPRE_IJMatrix ij) 128d71ae5a4SJacob Faibussowitsch { 12963c07aadSStefano Zampini PetscBool flg; 13063c07aadSStefano Zampini 13163c07aadSStefano Zampini PetscFunctionBegin; 1326ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 133792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize, ij); 1346ea7df73SStefano Zampini #else 135792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize_v2, ij, HYPRE_MEMORY_HOST); 1366ea7df73SStefano Zampini #endif 1379566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &flg)); 138b73e3080SStefano Zampini if (flg) { 139b73e3080SStefano Zampini PetscCall(MatHYPRE_IJMatrixCopyIJ_MPIAIJ(A, ij)); 1403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14163c07aadSStefano Zampini } 1429566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &flg)); 14363c07aadSStefano Zampini if (flg) { 144b73e3080SStefano Zampini PetscCall(MatHYPRE_IJMatrixCopyIJ_SeqAIJ(A, ij)); 1453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14663c07aadSStefano Zampini } 147b73e3080SStefano Zampini PetscCheck(PETSC_FALSE, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "No support for matrix type %s", ((PetscObject)A)->type_name); 14887ef5fa6SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 14963c07aadSStefano Zampini } 15063c07aadSStefano Zampini 151b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_SeqAIJ(Mat A, HYPRE_IJMatrix ij) 152d71ae5a4SJacob Faibussowitsch { 15363c07aadSStefano Zampini Mat_SeqAIJ *pdiag = (Mat_SeqAIJ *)A->data; 15458968eb6SStefano Zampini HYPRE_Int type; 15563c07aadSStefano Zampini hypre_ParCSRMatrix *par_matrix; 15663c07aadSStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 15763c07aadSStefano Zampini hypre_CSRMatrix *hdiag; 1582cf14000SStefano Zampini PetscBool sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int)); 15963c07aadSStefano Zampini 16063c07aadSStefano Zampini PetscFunctionBegin; 161792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type); 16208401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 163792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix); 16463c07aadSStefano Zampini hdiag = hypre_ParCSRMatrixDiag(par_matrix); 16563c07aadSStefano Zampini /* 16663c07aadSStefano Zampini this is the Hack part where we monkey directly with the hypre datastructures 16763c07aadSStefano Zampini */ 1682cf14000SStefano Zampini if (sameint) { 1699566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hdiag->i, pdiag->i, A->rmap->n + 1)); 1709566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hdiag->j, pdiag->j, pdiag->nz)); 1712cf14000SStefano Zampini } else { 1722cf14000SStefano Zampini PetscInt i; 1732cf14000SStefano Zampini 1742cf14000SStefano Zampini for (i = 0; i < A->rmap->n + 1; i++) hdiag->i[i] = (HYPRE_Int)pdiag->i[i]; 1752cf14000SStefano Zampini for (i = 0; i < pdiag->nz; i++) hdiag->j[i] = (HYPRE_Int)pdiag->j[i]; 1762cf14000SStefano Zampini } 1776ea7df73SStefano Zampini 178ea9daf28SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij); 17963c07aadSStefano Zampini hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0; 1803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18163c07aadSStefano Zampini } 18263c07aadSStefano Zampini 183b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_MPIAIJ(Mat A, HYPRE_IJMatrix ij) 184d71ae5a4SJacob Faibussowitsch { 18563c07aadSStefano Zampini Mat_MPIAIJ *pA = (Mat_MPIAIJ *)A->data; 18663c07aadSStefano Zampini Mat_SeqAIJ *pdiag, *poffd; 18763c07aadSStefano Zampini PetscInt i, *garray = pA->garray, *jj, cstart, *pjj; 1882cf14000SStefano Zampini HYPRE_Int *hjj, type; 18963c07aadSStefano Zampini hypre_ParCSRMatrix *par_matrix; 19063c07aadSStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 19163c07aadSStefano Zampini hypre_CSRMatrix *hdiag, *hoffd; 1922cf14000SStefano Zampini PetscBool sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int)); 19363c07aadSStefano Zampini 19463c07aadSStefano Zampini PetscFunctionBegin; 19563c07aadSStefano Zampini pdiag = (Mat_SeqAIJ *)pA->A->data; 19663c07aadSStefano Zampini poffd = (Mat_SeqAIJ *)pA->B->data; 197da81f932SPierre Jolivet /* cstart is only valid for square MPIAIJ laid out in the usual way */ 1989566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &cstart, NULL)); 19963c07aadSStefano Zampini 200792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type); 20108401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 202792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix); 20363c07aadSStefano Zampini hdiag = hypre_ParCSRMatrixDiag(par_matrix); 20463c07aadSStefano Zampini hoffd = hypre_ParCSRMatrixOffd(par_matrix); 20563c07aadSStefano Zampini 2062cf14000SStefano Zampini if (sameint) { 2079566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hdiag->i, pdiag->i, pA->A->rmap->n + 1)); 2082cf14000SStefano Zampini } else { 209f4f49eeaSPierre Jolivet for (i = 0; i < pA->A->rmap->n + 1; i++) hdiag->i[i] = (HYPRE_Int)pdiag->i[i]; 2102cf14000SStefano Zampini } 211b73e3080SStefano Zampini 2122cf14000SStefano Zampini hjj = hdiag->j; 2132cf14000SStefano Zampini pjj = pdiag->j; 214c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0) 2152cf14000SStefano Zampini for (i = 0; i < pdiag->nz; i++) hjj[i] = pjj[i]; 216c6698e78SStefano Zampini #else 2172cf14000SStefano Zampini for (i = 0; i < pdiag->nz; i++) hjj[i] = cstart + pjj[i]; 218c6698e78SStefano Zampini #endif 2192cf14000SStefano Zampini if (sameint) { 2209566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hoffd->i, poffd->i, pA->A->rmap->n + 1)); 2212cf14000SStefano Zampini } else { 222f4f49eeaSPierre Jolivet for (i = 0; i < pA->A->rmap->n + 1; i++) hoffd->i[i] = (HYPRE_Int)poffd->i[i]; 2232cf14000SStefano Zampini } 2242cf14000SStefano Zampini 22506977982Sstefanozampini jj = (PetscInt *)hoffd->j; 226c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0) 227792fecdfSBarry Smith PetscCallExternal(hypre_CSRMatrixBigInitialize, hoffd); 228c6698e78SStefano Zampini jj = (PetscInt *)hoffd->big_j; 229c6698e78SStefano Zampini #endif 2302cf14000SStefano Zampini pjj = poffd->j; 23163c07aadSStefano Zampini for (i = 0; i < poffd->nz; i++) jj[i] = garray[pjj[i]]; 232c6698e78SStefano Zampini 233ea9daf28SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij); 23463c07aadSStefano Zampini hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0; 2353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23663c07aadSStefano Zampini } 23763c07aadSStefano Zampini 238d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_HYPRE_IS(Mat A, MatType mtype, MatReuse reuse, Mat *B) 239d71ae5a4SJacob Faibussowitsch { 240f4f49eeaSPierre Jolivet Mat_HYPRE *mhA = (Mat_HYPRE *)A->data; 2412df22349SStefano Zampini Mat lA; 2422df22349SStefano Zampini ISLocalToGlobalMapping rl2g, cl2g; 2432df22349SStefano Zampini IS is; 2442df22349SStefano Zampini hypre_ParCSRMatrix *hA; 2452df22349SStefano Zampini hypre_CSRMatrix *hdiag, *hoffd; 2462df22349SStefano Zampini MPI_Comm comm; 24739accc25SStefano Zampini HYPRE_Complex *hdd, *hod, *aa; 24839accc25SStefano Zampini PetscScalar *data; 2492cf14000SStefano Zampini HYPRE_BigInt *col_map_offd; 2502cf14000SStefano Zampini HYPRE_Int *hdi, *hdj, *hoi, *hoj; 2512df22349SStefano Zampini PetscInt *ii, *jj, *iptr, *jptr; 2522df22349SStefano Zampini PetscInt cum, dr, dc, oc, str, stc, nnz, i, jd, jo, M, N; 25358968eb6SStefano Zampini HYPRE_Int type; 25406977982Sstefanozampini MatType lmattype = NULL; 25506977982Sstefanozampini PetscBool freeparcsr = PETSC_FALSE; 2562df22349SStefano Zampini 2572df22349SStefano Zampini PetscFunctionBegin; 258a1787963SStefano Zampini comm = PetscObjectComm((PetscObject)A); 259792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, mhA->ij, &type); 26008401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 261792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, mhA->ij, (void **)&hA); 26206977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 26306977982Sstefanozampini if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(mhA->ij)) { 26406977982Sstefanozampini /* Support by copying back on the host and copy to GPU 26506977982Sstefanozampini Kind of inefficient, but this is the best we can do now */ 26606977982Sstefanozampini #if defined(HYPRE_USING_HIP) 26706977982Sstefanozampini lmattype = MATSEQAIJHIPSPARSE; 26806977982Sstefanozampini #elif defined(HYPRE_USING_CUDA) 26906977982Sstefanozampini lmattype = MATSEQAIJCUSPARSE; 27006977982Sstefanozampini #endif 27106977982Sstefanozampini hA = hypre_ParCSRMatrixClone_v2(hA, 1, HYPRE_MEMORY_HOST); 27206977982Sstefanozampini freeparcsr = PETSC_TRUE; 27306977982Sstefanozampini } 27406977982Sstefanozampini #endif 2752df22349SStefano Zampini M = hypre_ParCSRMatrixGlobalNumRows(hA); 2762df22349SStefano Zampini N = hypre_ParCSRMatrixGlobalNumCols(hA); 2772df22349SStefano Zampini str = hypre_ParCSRMatrixFirstRowIndex(hA); 2782df22349SStefano Zampini stc = hypre_ParCSRMatrixFirstColDiag(hA); 2792df22349SStefano Zampini hdiag = hypre_ParCSRMatrixDiag(hA); 2802df22349SStefano Zampini hoffd = hypre_ParCSRMatrixOffd(hA); 2812df22349SStefano Zampini dr = hypre_CSRMatrixNumRows(hdiag); 2822df22349SStefano Zampini dc = hypre_CSRMatrixNumCols(hdiag); 2832df22349SStefano Zampini nnz = hypre_CSRMatrixNumNonzeros(hdiag); 2842df22349SStefano Zampini hdi = hypre_CSRMatrixI(hdiag); 2852df22349SStefano Zampini hdj = hypre_CSRMatrixJ(hdiag); 2862df22349SStefano Zampini hdd = hypre_CSRMatrixData(hdiag); 2872df22349SStefano Zampini oc = hypre_CSRMatrixNumCols(hoffd); 2882df22349SStefano Zampini nnz += hypre_CSRMatrixNumNonzeros(hoffd); 2892df22349SStefano Zampini hoi = hypre_CSRMatrixI(hoffd); 2902df22349SStefano Zampini hoj = hypre_CSRMatrixJ(hoffd); 2912df22349SStefano Zampini hod = hypre_CSRMatrixData(hoffd); 2922df22349SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 2932df22349SStefano Zampini PetscInt *aux; 2942df22349SStefano Zampini 2952df22349SStefano Zampini /* generate l2g maps for rows and cols */ 2969566063dSJacob Faibussowitsch PetscCall(ISCreateStride(comm, dr, str, 1, &is)); 2979566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g)); 2989566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2992df22349SStefano Zampini col_map_offd = hypre_ParCSRMatrixColMapOffd(hA); 3009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dc + oc, &aux)); 3012df22349SStefano Zampini for (i = 0; i < dc; i++) aux[i] = i + stc; 3022df22349SStefano Zampini for (i = 0; i < oc; i++) aux[i + dc] = col_map_offd[i]; 3039566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, dc + oc, aux, PETSC_OWN_POINTER, &is)); 3049566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g)); 3059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3062df22349SStefano Zampini /* create MATIS object */ 3079566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, B)); 3089566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, dr, dc, M, N)); 3099566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, MATIS)); 3109566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*B, rl2g, cl2g)); 3119566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 3129566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 3132df22349SStefano Zampini 3142df22349SStefano Zampini /* allocate CSR for local matrix */ 3159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dr + 1, &iptr)); 3169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &jptr)); 3179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &data)); 3182df22349SStefano Zampini } else { 3192df22349SStefano Zampini PetscInt nr; 3202df22349SStefano Zampini PetscBool done; 3219566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*B, &lA)); 3229566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lA, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&iptr, (const PetscInt **)&jptr, &done)); 32308401ef6SPierre 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); 32408401ef6SPierre 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); 32506977982Sstefanozampini PetscCall(MatSeqAIJGetArrayWrite(lA, &data)); 3262df22349SStefano Zampini } 3272df22349SStefano Zampini /* merge local matrices */ 3282df22349SStefano Zampini ii = iptr; 3292df22349SStefano Zampini jj = jptr; 33039accc25SStefano 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++ */ 3312df22349SStefano Zampini *ii = *(hdi++) + *(hoi++); 3322df22349SStefano Zampini for (jd = 0, jo = 0, cum = 0; *ii < nnz; cum++) { 33339accc25SStefano Zampini PetscScalar *aold = (PetscScalar *)aa; 3342df22349SStefano Zampini PetscInt *jold = jj, nc = jd + jo; 3359371c9d4SSatish Balay for (; jd < *hdi; jd++) { 3369371c9d4SSatish Balay *jj++ = *hdj++; 3379371c9d4SSatish Balay *aa++ = *hdd++; 3389371c9d4SSatish Balay } 3399371c9d4SSatish Balay for (; jo < *hoi; jo++) { 3409371c9d4SSatish Balay *jj++ = *hoj++ + dc; 3419371c9d4SSatish Balay *aa++ = *hod++; 3429371c9d4SSatish Balay } 3432df22349SStefano Zampini *(++ii) = *(hdi++) + *(hoi++); 3449566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithScalarArray(jd + jo - nc, jold, aold)); 3452df22349SStefano Zampini } 3462df22349SStefano Zampini for (; cum < dr; cum++) *(++ii) = nnz; 3472df22349SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 348a033916dSStefano Zampini Mat_SeqAIJ *a; 349a033916dSStefano Zampini 3509566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, dr, dc + oc, iptr, jptr, data, &lA)); 351a033916dSStefano Zampini /* hack SeqAIJ */ 352f4f49eeaSPierre Jolivet a = (Mat_SeqAIJ *)lA->data; 353a033916dSStefano Zampini a->free_a = PETSC_TRUE; 354a033916dSStefano Zampini a->free_ij = PETSC_TRUE; 35506977982Sstefanozampini if (lmattype) PetscCall(MatConvert(lA, lmattype, MAT_INPLACE_MATRIX, &lA)); 35606977982Sstefanozampini PetscCall(MatISSetLocalMat(*B, lA)); 3579566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lA)); 35806977982Sstefanozampini } else { 35906977982Sstefanozampini PetscCall(MatSeqAIJRestoreArrayWrite(lA, &data)); 3602df22349SStefano Zampini } 3619566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY)); 3629566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY)); 36348a46eb9SPierre Jolivet if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, B)); 36406977982Sstefanozampini if (freeparcsr) PetscCallExternal(hypre_ParCSRMatrixDestroy, hA); 3653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3662df22349SStefano Zampini } 3672df22349SStefano Zampini 36806977982Sstefanozampini static PetscErrorCode MatHYPRE_DestroyCOOMat(Mat mat) 369d71ae5a4SJacob Faibussowitsch { 37006977982Sstefanozampini Mat_HYPRE *hA = (Mat_HYPRE *)mat->data; 37163c07aadSStefano Zampini 37263c07aadSStefano Zampini PetscFunctionBegin; 37306977982Sstefanozampini if (hA->cooMat) { /* If cooMat is present we need to destroy the column indices */ 37406977982Sstefanozampini PetscCall(MatDestroy(&hA->cooMat)); 37506977982Sstefanozampini if (hA->cooMatAttached) { 37606977982Sstefanozampini hypre_CSRMatrix *csr; 37706977982Sstefanozampini hypre_ParCSRMatrix *parcsr; 37806977982Sstefanozampini HYPRE_MemoryLocation mem; 37906977982Sstefanozampini 38006977982Sstefanozampini PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr); 38106977982Sstefanozampini csr = hypre_ParCSRMatrixDiag(parcsr); 38206977982Sstefanozampini if (csr) { 38306977982Sstefanozampini mem = hypre_CSRMatrixMemoryLocation(csr); 38406977982Sstefanozampini PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixJ(csr), mem)); 38506977982Sstefanozampini PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixBigJ(csr), mem)); 386b73e3080SStefano Zampini } 38706977982Sstefanozampini csr = hypre_ParCSRMatrixOffd(parcsr); 38806977982Sstefanozampini if (csr) { 38906977982Sstefanozampini mem = hypre_CSRMatrixMemoryLocation(csr); 39006977982Sstefanozampini PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixJ(csr), mem)); 39106977982Sstefanozampini PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixBigJ(csr), mem)); 392b73e3080SStefano Zampini } 393b73e3080SStefano Zampini } 39406977982Sstefanozampini } 39506977982Sstefanozampini hA->cooMatAttached = PETSC_FALSE; 396b73e3080SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 397b73e3080SStefano Zampini } 398b73e3080SStefano Zampini 39906977982Sstefanozampini static PetscErrorCode MatHYPRE_CreateCOOMat(Mat mat) 400b73e3080SStefano Zampini { 40106977982Sstefanozampini MPI_Comm comm; 40206977982Sstefanozampini PetscMPIInt size; 40306977982Sstefanozampini PetscLayout rmap, cmap; 40406977982Sstefanozampini Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data; 40506977982Sstefanozampini MatType matType = MATAIJ; /* default type of cooMat */ 406b73e3080SStefano Zampini 407b73e3080SStefano Zampini PetscFunctionBegin; 40806977982Sstefanozampini /* Build an agent matrix cooMat with AIJ format 40906977982Sstefanozampini It has the same sparsity pattern as mat, and also shares the data array with mat. We use cooMat to do the COO work. 41006977982Sstefanozampini */ 41106977982Sstefanozampini PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 41206977982Sstefanozampini PetscCallMPI(MPI_Comm_size(comm, &size)); 41306977982Sstefanozampini PetscCall(PetscLayoutSetUp(mat->rmap)); 41406977982Sstefanozampini PetscCall(PetscLayoutSetUp(mat->cmap)); 41506977982Sstefanozampini PetscCall(MatGetLayouts(mat, &rmap, &cmap)); 416b73e3080SStefano Zampini 41706977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 41806977982Sstefanozampini if (!mat->boundtocpu) { /* mat will be on device, so will cooMat */ 41906977982Sstefanozampini #if defined(HYPRE_USING_HIP) 42006977982Sstefanozampini matType = MATAIJHIPSPARSE; 42106977982Sstefanozampini #elif defined(HYPRE_USING_CUDA) 42206977982Sstefanozampini matType = MATAIJCUSPARSE; 42306977982Sstefanozampini #else 42406977982Sstefanozampini SETERRQ(comm, PETSC_ERR_SUP, "Do not know the HYPRE device"); 42506977982Sstefanozampini #endif 426b73e3080SStefano Zampini } 42706977982Sstefanozampini #endif 42806977982Sstefanozampini 42906977982Sstefanozampini /* Do COO preallocation through cooMat */ 43006977982Sstefanozampini PetscCall(MatHYPRE_DestroyCOOMat(mat)); 43106977982Sstefanozampini PetscCall(MatCreate(comm, &hmat->cooMat)); 43206977982Sstefanozampini PetscCall(MatSetType(hmat->cooMat, matType)); 43306977982Sstefanozampini PetscCall(MatSetLayouts(hmat->cooMat, rmap, cmap)); 43406977982Sstefanozampini 43506977982Sstefanozampini /* allocate local matrices if needed */ 43606977982Sstefanozampini PetscCall(MatMPIAIJSetPreallocation(hmat->cooMat, 0, NULL, 0, NULL)); 43706977982Sstefanozampini PetscFunctionReturn(PETSC_SUCCESS); 43806977982Sstefanozampini } 43906977982Sstefanozampini 44006977982Sstefanozampini /* Attach cooMat data array to hypre matrix. 44106977982Sstefanozampini When AIJCUPMSPARSE will support raw device pointers and not THRUSTARRAY 44206977982Sstefanozampini we should swap the arrays: i.e., attach hypre matrix array to cooMat 44306977982Sstefanozampini This is because hypre should be in charge of handling the memory, 44406977982Sstefanozampini cooMat is only a way to reuse PETSc COO code. 44506977982Sstefanozampini attaching the memory will then be done at MatSetValuesCOO time and it will dynamically 44606977982Sstefanozampini support hypre matrix migrating to host. 44706977982Sstefanozampini */ 44806977982Sstefanozampini static PetscErrorCode MatHYPRE_AttachCOOMat(Mat mat) 44906977982Sstefanozampini { 45006977982Sstefanozampini Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data; 45106977982Sstefanozampini hypre_CSRMatrix *diag, *offd; 45206977982Sstefanozampini hypre_ParCSRMatrix *parCSR; 45306977982Sstefanozampini HYPRE_MemoryLocation hmem = HYPRE_MEMORY_HOST; 45406977982Sstefanozampini PetscMemType pmem; 45506977982Sstefanozampini Mat A, B; 45606977982Sstefanozampini PetscScalar *a; 45706977982Sstefanozampini PetscMPIInt size; 45806977982Sstefanozampini MPI_Comm comm; 45906977982Sstefanozampini 46006977982Sstefanozampini PetscFunctionBegin; 46106977982Sstefanozampini PetscCheck(hmat->cooMat, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet"); 46206977982Sstefanozampini if (hmat->cooMatAttached) PetscFunctionReturn(PETSC_SUCCESS); 46306977982Sstefanozampini PetscCheck(hmat->cooMat->preallocated, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix is not preallocated"); 46406977982Sstefanozampini PetscCall(PetscObjectSetName((PetscObject)hmat->cooMat, "_internal_COO_mat_for_hypre")); 46506977982Sstefanozampini PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 46606977982Sstefanozampini PetscCallMPI(MPI_Comm_size(comm, &size)); 46706977982Sstefanozampini 46806977982Sstefanozampini /* Alias cooMat's data array to IJMatrix's */ 46906977982Sstefanozampini PetscCallExternal(HYPRE_IJMatrixGetObject, hmat->ij, (void **)&parCSR); 47006977982Sstefanozampini diag = hypre_ParCSRMatrixDiag(parCSR); 47106977982Sstefanozampini offd = hypre_ParCSRMatrixOffd(parCSR); 47206977982Sstefanozampini 47306977982Sstefanozampini A = (size == 1) ? hmat->cooMat : ((Mat_MPIAIJ *)hmat->cooMat->data)->A; 47406977982Sstefanozampini B = (size == 1) ? NULL : ((Mat_MPIAIJ *)hmat->cooMat->data)->B; 47506977982Sstefanozampini 47606977982Sstefanozampini PetscCall(PetscObjectSetName((PetscObject)A, "_internal_COO_mat_for_hypre")); 47706977982Sstefanozampini hmem = hypre_CSRMatrixMemoryLocation(diag); 47806977982Sstefanozampini PetscCall(MatSeqAIJGetCSRAndMemType(A, NULL, NULL, &a, &pmem)); 47906977982Sstefanozampini PetscAssert((PetscMemTypeHost(pmem) && hmem == HYPRE_MEMORY_HOST) || (PetscMemTypeDevice(pmem) && hmem == HYPRE_MEMORY_DEVICE), comm, PETSC_ERR_PLIB, "PETSc and hypre's memory types mismatch"); 48006977982Sstefanozampini PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(diag), hmem)); 48106977982Sstefanozampini hypre_CSRMatrixData(diag) = (HYPRE_Complex *)a; 48206977982Sstefanozampini hypre_CSRMatrixOwnsData(diag) = 0; /* Take ownership of (j,a) away from hypre. As a result, we need to free them on our own */ 48306977982Sstefanozampini 48406977982Sstefanozampini if (B) { 48506977982Sstefanozampini hmem = hypre_CSRMatrixMemoryLocation(offd); 48606977982Sstefanozampini PetscCall(MatSeqAIJGetCSRAndMemType(B, NULL, NULL, &a, &pmem)); 48706977982Sstefanozampini PetscAssert((PetscMemTypeHost(pmem) && hmem == HYPRE_MEMORY_HOST) || (PetscMemTypeDevice(pmem) && hmem == HYPRE_MEMORY_DEVICE), comm, PETSC_ERR_PLIB, "PETSc and hypre's memory types mismatch"); 48806977982Sstefanozampini PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(offd), hmem)); 48906977982Sstefanozampini hypre_CSRMatrixData(offd) = (HYPRE_Complex *)a; 49006977982Sstefanozampini hypre_CSRMatrixOwnsData(offd) = 0; 49106977982Sstefanozampini } 49206977982Sstefanozampini hmat->cooMatAttached = PETSC_TRUE; 49306977982Sstefanozampini PetscFunctionReturn(PETSC_SUCCESS); 49406977982Sstefanozampini } 49506977982Sstefanozampini 4961c265611SJunchao Zhang // Build COO's coordinate list i[], j[] based on CSR's i[], j[] arrays and the number of local rows 'n' 49706977982Sstefanozampini static PetscErrorCode CSRtoCOO_Private(PetscInt n, const PetscInt ii[], const PetscInt jj[], PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j) 49806977982Sstefanozampini { 49906977982Sstefanozampini PetscInt *cooi, *cooj; 50006977982Sstefanozampini 50106977982Sstefanozampini PetscFunctionBegin; 50206977982Sstefanozampini *ncoo = ii[n]; 50306977982Sstefanozampini PetscCall(PetscMalloc2(*ncoo, &cooi, *ncoo, &cooj)); 50406977982Sstefanozampini for (PetscInt i = 0; i < n; i++) { 50506977982Sstefanozampini for (PetscInt j = ii[i]; j < ii[i + 1]; j++) cooi[j] = i; 50606977982Sstefanozampini } 50706977982Sstefanozampini PetscCall(PetscArraycpy(cooj, jj, *ncoo)); 50806977982Sstefanozampini *coo_i = cooi; 50906977982Sstefanozampini *coo_j = cooj; 51006977982Sstefanozampini PetscFunctionReturn(PETSC_SUCCESS); 51106977982Sstefanozampini } 51206977982Sstefanozampini 5131c265611SJunchao Zhang // Similar to CSRtoCOO_Private, but the CSR's i[], j[] are of type HYPRE_Int 51406977982Sstefanozampini static PetscErrorCode CSRtoCOO_HYPRE_Int_Private(PetscInt n, const HYPRE_Int ii[], const HYPRE_Int jj[], PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j) 51506977982Sstefanozampini { 51606977982Sstefanozampini PetscInt *cooi, *cooj; 51706977982Sstefanozampini 51806977982Sstefanozampini PetscFunctionBegin; 51906977982Sstefanozampini *ncoo = ii[n]; 52006977982Sstefanozampini PetscCall(PetscMalloc2(*ncoo, &cooi, *ncoo, &cooj)); 52106977982Sstefanozampini for (PetscInt i = 0; i < n; i++) { 52206977982Sstefanozampini for (HYPRE_Int j = ii[i]; j < ii[i + 1]; j++) cooi[j] = i; 52306977982Sstefanozampini } 52406977982Sstefanozampini for (PetscCount i = 0; i < *ncoo; i++) cooj[i] = jj[i]; 52506977982Sstefanozampini *coo_i = cooi; 52606977982Sstefanozampini *coo_j = cooj; 52706977982Sstefanozampini PetscFunctionReturn(PETSC_SUCCESS); 52806977982Sstefanozampini } 52906977982Sstefanozampini 5301c265611SJunchao Zhang // Build a COO data structure for the seqaij matrix, as if the nonzeros are laid out in the same order as in the CSR 53106977982Sstefanozampini static PetscErrorCode MatSeqAIJGetCOO_Private(Mat A, PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j) 53206977982Sstefanozampini { 53306977982Sstefanozampini PetscInt n; 53406977982Sstefanozampini const PetscInt *ii, *jj; 53506977982Sstefanozampini PetscBool done; 53606977982Sstefanozampini 53706977982Sstefanozampini PetscFunctionBegin; 53806977982Sstefanozampini PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &done)); 53906977982Sstefanozampini PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Failure for MatGetRowIJ"); 54006977982Sstefanozampini PetscCall(CSRtoCOO_Private(n, ii, jj, ncoo, coo_i, coo_j)); 54106977982Sstefanozampini PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &done)); 54206977982Sstefanozampini PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Failure for MatRestoreRowIJ"); 54306977982Sstefanozampini PetscFunctionReturn(PETSC_SUCCESS); 54406977982Sstefanozampini } 54506977982Sstefanozampini 5461c265611SJunchao Zhang // Build a COO data structure for the hypreCSRMatrix, as if the nonzeros are laid out in the same order as in the hypreCSRMatrix 54706977982Sstefanozampini static PetscErrorCode hypreCSRMatrixGetCOO_Private(hypre_CSRMatrix *A, PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j) 54806977982Sstefanozampini { 54906977982Sstefanozampini PetscInt n = hypre_CSRMatrixNumRows(A); 55006977982Sstefanozampini HYPRE_Int *ii, *jj; 55106977982Sstefanozampini HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST; 55206977982Sstefanozampini 55306977982Sstefanozampini PetscFunctionBegin; 55406977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 55506977982Sstefanozampini mem = hypre_CSRMatrixMemoryLocation(A); 55606977982Sstefanozampini if (mem != HYPRE_MEMORY_HOST) { 55706977982Sstefanozampini PetscCount nnz = hypre_CSRMatrixNumNonzeros(A); 55806977982Sstefanozampini PetscCall(PetscMalloc2(n + 1, &ii, nnz, &jj)); 55906977982Sstefanozampini hypre_TMemcpy(ii, hypre_CSRMatrixI(A), HYPRE_Int, n + 1, HYPRE_MEMORY_HOST, mem); 56006977982Sstefanozampini hypre_TMemcpy(jj, hypre_CSRMatrixJ(A), HYPRE_Int, nnz, HYPRE_MEMORY_HOST, mem); 56106977982Sstefanozampini } else { 56206977982Sstefanozampini #else 56306977982Sstefanozampini { 56406977982Sstefanozampini #endif 56506977982Sstefanozampini ii = hypre_CSRMatrixI(A); 56606977982Sstefanozampini jj = hypre_CSRMatrixJ(A); 56706977982Sstefanozampini } 56806977982Sstefanozampini PetscCall(CSRtoCOO_HYPRE_Int_Private(n, ii, jj, ncoo, coo_i, coo_j)); 56906977982Sstefanozampini if (mem != HYPRE_MEMORY_HOST) PetscCall(PetscFree2(ii, jj)); 57006977982Sstefanozampini PetscFunctionReturn(PETSC_SUCCESS); 57106977982Sstefanozampini } 57206977982Sstefanozampini 57306977982Sstefanozampini static PetscErrorCode MatSetValuesCOOFromCSRMatrix_Private(Mat A, hypre_CSRMatrix *H) 57406977982Sstefanozampini { 57506977982Sstefanozampini PetscBool iscpu = PETSC_TRUE; 57606977982Sstefanozampini PetscScalar *a; 57706977982Sstefanozampini HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST; 57806977982Sstefanozampini 57906977982Sstefanozampini PetscFunctionBegin; 58006977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 58106977982Sstefanozampini mem = hypre_CSRMatrixMemoryLocation(H); 58206977982Sstefanozampini PetscCall(PetscObjectTypeCompare((PetscObject)A, MATSEQAIJ, &iscpu)); 58306977982Sstefanozampini #endif 58406977982Sstefanozampini if (iscpu && mem != HYPRE_MEMORY_HOST) { 58506977982Sstefanozampini PetscCount nnz = hypre_CSRMatrixNumNonzeros(H); 58606977982Sstefanozampini PetscCall(PetscMalloc1(nnz, &a)); 58706977982Sstefanozampini hypre_TMemcpy(a, hypre_CSRMatrixData(H), PetscScalar, nnz, HYPRE_MEMORY_HOST, mem); 58806977982Sstefanozampini } else { 58906977982Sstefanozampini a = (PetscScalar *)hypre_CSRMatrixData(H); 59006977982Sstefanozampini } 59106977982Sstefanozampini PetscCall(MatSetValuesCOO(A, a, INSERT_VALUES)); 59206977982Sstefanozampini if (iscpu && mem != HYPRE_MEMORY_HOST) PetscCall(PetscFree(a)); 593b73e3080SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 594b73e3080SStefano Zampini } 595b73e3080SStefano Zampini 596b73e3080SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType type, MatReuse reuse, Mat *B) 597b73e3080SStefano Zampini { 598b73e3080SStefano Zampini MPI_Comm comm = PetscObjectComm((PetscObject)A); 59906977982Sstefanozampini Mat M = NULL, dH = NULL, oH = NULL, dA = NULL, oA = NULL; 600*d7185485SAlex Lindsay PetscBool ismpiaij, issbaij, isbaij, boundtocpu = PETSC_TRUE; 601b73e3080SStefano Zampini Mat_HYPRE *hA; 602*d7185485SAlex Lindsay PetscMemType memtype = PETSC_MEMTYPE_HOST; 603b73e3080SStefano Zampini 604b73e3080SStefano Zampini PetscFunctionBegin; 605*d7185485SAlex Lindsay if (PetscDefined(HAVE_HYPRE_DEVICE)) { 606*d7185485SAlex Lindsay PetscCall(MatGetCurrentMemType(A, &memtype)); 607*d7185485SAlex Lindsay PetscHYPREInitialize(); 608*d7185485SAlex Lindsay boundtocpu = PetscMemTypeHost(memtype) ? PETSC_TRUE : PETSC_FALSE; 609*d7185485SAlex Lindsay PetscCallExternal(HYPRE_SetMemoryLocation, boundtocpu ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE); 610*d7185485SAlex Lindsay } 611*d7185485SAlex Lindsay 612b73e3080SStefano Zampini PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &issbaij, MATSEQSBAIJ, MATMPIBAIJ, "")); 613b73e3080SStefano Zampini PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &isbaij, MATSEQBAIJ, MATMPIBAIJ, "")); 614b73e3080SStefano Zampini if (isbaij || issbaij) { /* handle BAIJ and SBAIJ */ 615b73e3080SStefano Zampini PetscBool ismpi; 616b73e3080SStefano Zampini MatType newtype; 617b73e3080SStefano Zampini 618b73e3080SStefano Zampini PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &ismpi, MATMPISBAIJ, MATMPIBAIJ, "")); 619b73e3080SStefano Zampini newtype = ismpi ? MATMPIAIJ : MATSEQAIJ; 62063c07aadSStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 621b73e3080SStefano Zampini PetscCall(MatConvert(*B, newtype, MAT_INPLACE_MATRIX, B)); 622b73e3080SStefano Zampini PetscCall(MatConvert(A, newtype, MAT_REUSE_MATRIX, B)); 623b73e3080SStefano Zampini PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B)); 624b73e3080SStefano Zampini } else if (reuse == MAT_INITIAL_MATRIX) { 625b73e3080SStefano Zampini PetscCall(MatConvert(A, newtype, MAT_INITIAL_MATRIX, B)); 626b73e3080SStefano Zampini PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B)); 62763c07aadSStefano Zampini } else { 628b73e3080SStefano Zampini PetscCall(MatConvert(A, newtype, MAT_INPLACE_MATRIX, &A)); 629b73e3080SStefano Zampini PetscCall(MatConvert(A, MATHYPRE, MAT_INPLACE_MATRIX, &A)); 630b73e3080SStefano Zampini } 631*d7185485SAlex Lindsay #if defined(PETSC_HAVE_DEVICE) 632*d7185485SAlex Lindsay (*B)->boundtocpu = boundtocpu; 633*d7185485SAlex Lindsay #endif 634b73e3080SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 635b73e3080SStefano Zampini } 63606977982Sstefanozampini 63706977982Sstefanozampini dA = A; 638b73e3080SStefano Zampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 639b73e3080SStefano Zampini if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(A, &dA, &oA, NULL)); 64006977982Sstefanozampini 641b73e3080SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 64206977982Sstefanozampini PetscCount coo_n; 64306977982Sstefanozampini PetscInt *coo_i, *coo_j; 64406977982Sstefanozampini 6459566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &M)); 6469566063dSJacob Faibussowitsch PetscCall(MatSetType(M, MATHYPRE)); 6479566063dSJacob Faibussowitsch PetscCall(MatSetSizes(M, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N)); 648b73e3080SStefano Zampini PetscCall(MatSetOption(M, MAT_SORTED_FULL, PETSC_TRUE)); 649b73e3080SStefano Zampini PetscCall(MatSetOption(M, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE)); 650b73e3080SStefano Zampini 651b73e3080SStefano Zampini hA = (Mat_HYPRE *)M->data; 65206977982Sstefanozampini PetscCall(MatHYPRE_CreateFromMat(A, hA)); 65306977982Sstefanozampini PetscCall(MatHYPRE_IJMatrixCopyIJ(A, hA->ij)); 65406977982Sstefanozampini 65506977982Sstefanozampini PetscCall(MatHYPRE_CreateCOOMat(M)); 65606977982Sstefanozampini 65706977982Sstefanozampini dH = hA->cooMat; 65806977982Sstefanozampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)hA->cooMat, MATMPIAIJ, &ismpiaij)); 65906977982Sstefanozampini if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(hA->cooMat, &dH, &oH, NULL)); 66006977982Sstefanozampini 66106977982Sstefanozampini PetscCall(PetscObjectSetName((PetscObject)dH, "_internal_COO_mat_for_hypre")); 66206977982Sstefanozampini PetscCall(MatSeqAIJGetCOO_Private(dA, &coo_n, &coo_i, &coo_j)); 66306977982Sstefanozampini PetscCall(MatSetPreallocationCOO(dH, coo_n, coo_i, coo_j)); 66406977982Sstefanozampini PetscCall(PetscFree2(coo_i, coo_j)); 66506977982Sstefanozampini if (oH) { 66606977982Sstefanozampini PetscCall(PetscLayoutDestroy(&oH->cmap)); 66706977982Sstefanozampini PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)oH), oA->cmap->n, oA->cmap->n, 1, &oH->cmap)); 66806977982Sstefanozampini PetscCall(MatSeqAIJGetCOO_Private(oA, &coo_n, &coo_i, &coo_j)); 66906977982Sstefanozampini PetscCall(MatSetPreallocationCOO(oH, coo_n, coo_i, coo_j)); 67006977982Sstefanozampini PetscCall(PetscFree2(coo_i, coo_j)); 67106977982Sstefanozampini } 67206977982Sstefanozampini hA->cooMat->assembled = PETSC_TRUE; 67306977982Sstefanozampini 674b73e3080SStefano Zampini M->preallocated = PETSC_TRUE; 67506977982Sstefanozampini PetscCall(MatAssemblyBegin(M, MAT_FINAL_ASSEMBLY)); 67606977982Sstefanozampini PetscCall(MatAssemblyEnd(M, MAT_FINAL_ASSEMBLY)); 67706977982Sstefanozampini 67806977982Sstefanozampini PetscCall(MatHYPRE_AttachCOOMat(M)); 67984d4e069SStefano Zampini if (reuse == MAT_INITIAL_MATRIX) *B = M; 680b73e3080SStefano Zampini } else M = *B; 681b73e3080SStefano Zampini 682b73e3080SStefano Zampini hA = (Mat_HYPRE *)M->data; 68306977982Sstefanozampini PetscCheck(hA->cooMat, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet"); 68406977982Sstefanozampini 68506977982Sstefanozampini dH = hA->cooMat; 68606977982Sstefanozampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)hA->cooMat, MATMPIAIJ, &ismpiaij)); 68706977982Sstefanozampini if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(hA->cooMat, &dH, &oH, NULL)); 68806977982Sstefanozampini 68906977982Sstefanozampini PetscScalar *a; 69006977982Sstefanozampini PetscCall(MatSeqAIJGetCSRAndMemType(dA, NULL, NULL, &a, NULL)); 69106977982Sstefanozampini PetscCall(MatSetValuesCOO(dH, a, INSERT_VALUES)); 69206977982Sstefanozampini if (oH) { 69306977982Sstefanozampini PetscCall(MatSeqAIJGetCSRAndMemType(oA, NULL, NULL, &a, NULL)); 69406977982Sstefanozampini PetscCall(MatSetValuesCOO(oH, a, INSERT_VALUES)); 69506977982Sstefanozampini } 696b73e3080SStefano Zampini 69748a46eb9SPierre Jolivet if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &M)); 698*d7185485SAlex Lindsay #if defined(PETSC_HAVE_DEVICE) 699*d7185485SAlex Lindsay (*B)->boundtocpu = boundtocpu; 700*d7185485SAlex Lindsay #endif 7013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 70263c07aadSStefano Zampini } 70363c07aadSStefano Zampini 704d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_HYPRE_AIJ(Mat A, MatType mtype, MatReuse reuse, Mat *B) 705d71ae5a4SJacob Faibussowitsch { 70606977982Sstefanozampini Mat M, dA = NULL, oA = NULL; 70763c07aadSStefano Zampini hypre_ParCSRMatrix *parcsr; 70806977982Sstefanozampini hypre_CSRMatrix *dH, *oH; 70963c07aadSStefano Zampini MPI_Comm comm; 71006977982Sstefanozampini PetscBool ismpiaij, isseqaij; 71163c07aadSStefano Zampini 71263c07aadSStefano Zampini PetscFunctionBegin; 71363c07aadSStefano Zampini comm = PetscObjectComm((PetscObject)A); 71463c07aadSStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 7159566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATMPIAIJ, &ismpiaij)); 7169566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATSEQAIJ, &isseqaij)); 71706977982Sstefanozampini PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Only MATMPIAIJ or MATSEQAIJ base types are supported"); 71863c07aadSStefano Zampini } 71906977982Sstefanozampini PetscCall(MatHYPREGetParCSR(A, &parcsr)); 7206ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 72106977982Sstefanozampini if (HYPRE_MEMORY_DEVICE == hypre_ParCSRMatrixMemoryLocation(parcsr)) { 72206977982Sstefanozampini PetscBool isaij; 72306977982Sstefanozampini 72406977982Sstefanozampini PetscCall(PetscStrcmp(mtype, MATAIJ, &isaij)); 72506977982Sstefanozampini if (isaij) { 72606977982Sstefanozampini PetscMPIInt size; 72706977982Sstefanozampini 7289566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 72906977982Sstefanozampini #if defined(HYPRE_USING_HIP) 73006977982Sstefanozampini mtype = size > 1 ? MATMPIAIJHIPSPARSE : MATSEQAIJHIPSPARSE; 73106977982Sstefanozampini #elif defined(HYPRE_USING_CUDA) 73206977982Sstefanozampini mtype = size > 1 ? MATMPIAIJCUSPARSE : MATSEQAIJCUSPARSE; 73306977982Sstefanozampini #else 73406977982Sstefanozampini mtype = size > 1 ? MATMPIAIJ : MATSEQAIJ; 73506977982Sstefanozampini #endif 73663c07aadSStefano Zampini } 73763c07aadSStefano Zampini } 73806977982Sstefanozampini #endif 73906977982Sstefanozampini dH = hypre_ParCSRMatrixDiag(parcsr); 74006977982Sstefanozampini oH = hypre_ParCSRMatrixOffd(parcsr); 7419371c9d4SSatish Balay if (reuse != MAT_REUSE_MATRIX) { 74206977982Sstefanozampini PetscCount coo_n; 74306977982Sstefanozampini PetscInt *coo_i, *coo_j; 74463c07aadSStefano Zampini 74506977982Sstefanozampini PetscCall(MatCreate(comm, &M)); 74606977982Sstefanozampini PetscCall(MatSetType(M, mtype)); 74706977982Sstefanozampini PetscCall(MatSetSizes(M, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N)); 74806977982Sstefanozampini PetscCall(MatMPIAIJSetPreallocation(M, 0, NULL, 0, NULL)); 74963c07aadSStefano Zampini 75006977982Sstefanozampini dA = M; 75106977982Sstefanozampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)M, MATMPIAIJ, &ismpiaij)); 75206977982Sstefanozampini if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(M, &dA, &oA, NULL)); 753a16187a7SStefano Zampini 75406977982Sstefanozampini PetscCall(hypreCSRMatrixGetCOO_Private(dH, &coo_n, &coo_i, &coo_j)); 75506977982Sstefanozampini PetscCall(MatSetPreallocationCOO(dA, coo_n, coo_i, coo_j)); 75606977982Sstefanozampini PetscCall(PetscFree2(coo_i, coo_j)); 75706977982Sstefanozampini if (ismpiaij) { 75806977982Sstefanozampini HYPRE_Int nc = hypre_CSRMatrixNumCols(oH); 759a16187a7SStefano Zampini 76006977982Sstefanozampini PetscCall(PetscLayoutDestroy(&oA->cmap)); 76106977982Sstefanozampini PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)oA), nc, nc, 1, &oA->cmap)); 76206977982Sstefanozampini PetscCall(hypreCSRMatrixGetCOO_Private(oH, &coo_n, &coo_i, &coo_j)); 76306977982Sstefanozampini PetscCall(MatSetPreallocationCOO(oA, coo_n, coo_i, coo_j)); 76406977982Sstefanozampini PetscCall(PetscFree2(coo_i, coo_j)); 765a16187a7SStefano Zampini 76606977982Sstefanozampini /* garray */ 767f4f49eeaSPierre Jolivet Mat_MPIAIJ *aij = (Mat_MPIAIJ *)M->data; 76806977982Sstefanozampini HYPRE_BigInt *harray = hypre_ParCSRMatrixColMapOffd(parcsr); 76906977982Sstefanozampini PetscInt *garray; 77006977982Sstefanozampini 77106977982Sstefanozampini PetscCall(PetscFree(aij->garray)); 77206977982Sstefanozampini PetscCall(PetscMalloc1(nc, &garray)); 77306977982Sstefanozampini for (HYPRE_Int i = 0; i < nc; i++) garray[i] = (PetscInt)harray[i]; 77406977982Sstefanozampini aij->garray = garray; 77506977982Sstefanozampini PetscCall(MatSetUpMultiply_MPIAIJ(M)); 776a16187a7SStefano Zampini } 77706977982Sstefanozampini if (reuse == MAT_INITIAL_MATRIX) *B = M; 77806977982Sstefanozampini } else M = *B; 779225daaf8SStefano Zampini 78006977982Sstefanozampini dA = M; 78106977982Sstefanozampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)M, MATMPIAIJ, &ismpiaij)); 78206977982Sstefanozampini if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(M, &dA, &oA, NULL)); 78306977982Sstefanozampini PetscCall(MatSetValuesCOOFromCSRMatrix_Private(dA, dH)); 78406977982Sstefanozampini if (oA) PetscCall(MatSetValuesCOOFromCSRMatrix_Private(oA, oH)); 78506977982Sstefanozampini M->assembled = PETSC_TRUE; 78606977982Sstefanozampini if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &M)); 7873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 78863c07aadSStefano Zampini } 78963c07aadSStefano Zampini 790d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJGetParCSR_Private(Mat A, hypre_ParCSRMatrix **hA) 791d71ae5a4SJacob Faibussowitsch { 792613e5ff0Sstefano_zampini hypre_ParCSRMatrix *tA; 793c1a070e6SStefano Zampini hypre_CSRMatrix *hdiag, *hoffd; 794c1a070e6SStefano Zampini Mat_SeqAIJ *diag, *offd; 7952cf14000SStefano Zampini PetscInt *garray, i, noffd, dnnz, onnz, *row_starts, *col_starts; 796c1a070e6SStefano Zampini MPI_Comm comm = PetscObjectComm((PetscObject)A); 797613e5ff0Sstefano_zampini PetscBool ismpiaij, isseqaij; 7982cf14000SStefano Zampini PetscBool sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int)); 7996ea7df73SStefano Zampini HYPRE_Int *hdi = NULL, *hdj = NULL, *hoi = NULL, *hoj = NULL; 8005c97c10fSStefano Zampini PetscInt *pdi = NULL, *pdj = NULL, *poi = NULL, *poj = NULL; 80106977982Sstefanozampini PetscBool iscuda, iship; 80206977982Sstefanozampini #if defined(PETSC_HAVE_DEVICE) && defined(PETSC_HAVE_HYPRE_DEVICE) 80306977982Sstefanozampini PetscBool boundtocpu = A->boundtocpu; 80406977982Sstefanozampini #else 80506977982Sstefanozampini PetscBool boundtocpu = PETSC_TRUE; 8066ea7df73SStefano Zampini #endif 807c1a070e6SStefano Zampini 808c1a070e6SStefano Zampini PetscFunctionBegin; 8099566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 8109566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isseqaij)); 81108401ef6SPierre Jolivet PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Unsupported type %s", ((PetscObject)A)->type_name); 812b655ebf8SZach Atkins PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, "")); 813b655ebf8SZach Atkins PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iship, MATSEQAIJHIPSPARSE, MATMPIAIJHIPSPARSE, "")); 814ea9ee2c1SPierre Jolivet PetscHYPREInitialize(); 815c1a070e6SStefano Zampini if (ismpiaij) { 816f4f49eeaSPierre Jolivet Mat_MPIAIJ *a = (Mat_MPIAIJ *)A->data; 817c1a070e6SStefano Zampini 818c1a070e6SStefano Zampini diag = (Mat_SeqAIJ *)a->A->data; 819c1a070e6SStefano Zampini offd = (Mat_SeqAIJ *)a->B->data; 82006977982Sstefanozampini if (!boundtocpu && (iscuda || iship)) { 82106977982Sstefanozampini #if defined(HYPRE_USING_CUDA) && defined(PETSC_HAVE_CUDA) 82206977982Sstefanozampini if (iscuda) { 8236ea7df73SStefano Zampini sameint = PETSC_TRUE; 8249566063dSJacob Faibussowitsch PetscCall(MatSeqAIJCUSPARSEGetIJ(a->A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj)); 8259566063dSJacob Faibussowitsch PetscCall(MatSeqAIJCUSPARSEGetIJ(a->B, PETSC_FALSE, (const HYPRE_Int **)&hoi, (const HYPRE_Int **)&hoj)); 82606977982Sstefanozampini } 8276ea7df73SStefano Zampini #endif 82806977982Sstefanozampini #if defined(HYPRE_USING_HIP) && defined(PETSC_HAVE_HIP) 82906977982Sstefanozampini if (iship) { 83006977982Sstefanozampini sameint = PETSC_TRUE; 83106977982Sstefanozampini PetscCall(MatSeqAIJHIPSPARSEGetIJ(a->A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj)); 83206977982Sstefanozampini PetscCall(MatSeqAIJHIPSPARSEGetIJ(a->B, PETSC_FALSE, (const HYPRE_Int **)&hoi, (const HYPRE_Int **)&hoj)); 83306977982Sstefanozampini } 83406977982Sstefanozampini #endif 83506977982Sstefanozampini } else { 83606977982Sstefanozampini boundtocpu = PETSC_TRUE; 8376ea7df73SStefano Zampini pdi = diag->i; 8386ea7df73SStefano Zampini pdj = diag->j; 8396ea7df73SStefano Zampini poi = offd->i; 8406ea7df73SStefano Zampini poj = offd->j; 8416ea7df73SStefano Zampini if (sameint) { 8426ea7df73SStefano Zampini hdi = (HYPRE_Int *)pdi; 8436ea7df73SStefano Zampini hdj = (HYPRE_Int *)pdj; 8446ea7df73SStefano Zampini hoi = (HYPRE_Int *)poi; 8456ea7df73SStefano Zampini hoj = (HYPRE_Int *)poj; 8466ea7df73SStefano Zampini } 8476ea7df73SStefano Zampini } 848c1a070e6SStefano Zampini garray = a->garray; 849c1a070e6SStefano Zampini noffd = a->B->cmap->N; 850c1a070e6SStefano Zampini dnnz = diag->nz; 851c1a070e6SStefano Zampini onnz = offd->nz; 852c1a070e6SStefano Zampini } else { 853c1a070e6SStefano Zampini diag = (Mat_SeqAIJ *)A->data; 854c1a070e6SStefano Zampini offd = NULL; 85506977982Sstefanozampini if (!boundtocpu && (iscuda || iship)) { 85606977982Sstefanozampini #if defined(HYPRE_USING_CUDA) && defined(PETSC_HAVE_CUDA) 85706977982Sstefanozampini if (iscuda) { 8586ea7df73SStefano Zampini sameint = PETSC_TRUE; 8599566063dSJacob Faibussowitsch PetscCall(MatSeqAIJCUSPARSEGetIJ(A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj)); 86006977982Sstefanozampini } 8616ea7df73SStefano Zampini #endif 86206977982Sstefanozampini #if defined(HYPRE_USING_HIP) && defined(PETSC_HAVE_HIP) 86306977982Sstefanozampini if (iship) { 86406977982Sstefanozampini sameint = PETSC_TRUE; 86506977982Sstefanozampini PetscCall(MatSeqAIJHIPSPARSEGetIJ(A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj)); 86606977982Sstefanozampini } 86706977982Sstefanozampini #endif 86806977982Sstefanozampini } else { 86906977982Sstefanozampini boundtocpu = PETSC_TRUE; 8706ea7df73SStefano Zampini pdi = diag->i; 8716ea7df73SStefano Zampini pdj = diag->j; 8726ea7df73SStefano Zampini if (sameint) { 8736ea7df73SStefano Zampini hdi = (HYPRE_Int *)pdi; 8746ea7df73SStefano Zampini hdj = (HYPRE_Int *)pdj; 8756ea7df73SStefano Zampini } 8766ea7df73SStefano Zampini } 877c1a070e6SStefano Zampini garray = NULL; 878c1a070e6SStefano Zampini noffd = 0; 879c1a070e6SStefano Zampini dnnz = diag->nz; 880c1a070e6SStefano Zampini onnz = 0; 881c1a070e6SStefano Zampini } 882225daaf8SStefano Zampini 883c1a070e6SStefano Zampini /* create a temporary ParCSR */ 884c1a070e6SStefano Zampini if (HYPRE_AssumedPartitionCheck()) { 885c1a070e6SStefano Zampini PetscMPIInt myid; 886c1a070e6SStefano Zampini 8879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &myid)); 888c1a070e6SStefano Zampini row_starts = A->rmap->range + myid; 889c1a070e6SStefano Zampini col_starts = A->cmap->range + myid; 890c1a070e6SStefano Zampini } else { 891c1a070e6SStefano Zampini row_starts = A->rmap->range; 892c1a070e6SStefano Zampini col_starts = A->cmap->range; 893c1a070e6SStefano Zampini } 8942cf14000SStefano Zampini tA = hypre_ParCSRMatrixCreate(comm, A->rmap->N, A->cmap->N, (HYPRE_BigInt *)row_starts, (HYPRE_BigInt *)col_starts, noffd, dnnz, onnz); 895a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 896c1a070e6SStefano Zampini hypre_ParCSRMatrixSetRowStartsOwner(tA, 0); 897c1a070e6SStefano Zampini hypre_ParCSRMatrixSetColStartsOwner(tA, 0); 898a1d2239cSSatish Balay #endif 899c1a070e6SStefano Zampini 900225daaf8SStefano Zampini /* set diagonal part */ 901c1a070e6SStefano Zampini hdiag = hypre_ParCSRMatrixDiag(tA); 9026ea7df73SStefano Zampini if (!sameint) { /* malloc CSR pointers */ 9039566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(A->rmap->n + 1, &hdi, dnnz, &hdj)); 904f4f49eeaSPierre Jolivet for (i = 0; i < A->rmap->n + 1; i++) hdi[i] = (HYPRE_Int)pdi[i]; 905f4f49eeaSPierre Jolivet for (i = 0; i < dnnz; i++) hdj[i] = (HYPRE_Int)pdj[i]; 9062cf14000SStefano Zampini } 9076ea7df73SStefano Zampini hypre_CSRMatrixI(hdiag) = hdi; 9086ea7df73SStefano Zampini hypre_CSRMatrixJ(hdiag) = hdj; 90939accc25SStefano Zampini hypre_CSRMatrixData(hdiag) = (HYPRE_Complex *)diag->a; 910c1a070e6SStefano Zampini hypre_CSRMatrixNumNonzeros(hdiag) = diag->nz; 911c1a070e6SStefano Zampini hypre_CSRMatrixSetRownnz(hdiag); 912c1a070e6SStefano Zampini hypre_CSRMatrixSetDataOwner(hdiag, 0); 913c1a070e6SStefano Zampini 9144cf0e950SBarry Smith /* set off-diagonal part */ 915c1a070e6SStefano Zampini hoffd = hypre_ParCSRMatrixOffd(tA); 916c1a070e6SStefano Zampini if (offd) { 9176ea7df73SStefano Zampini if (!sameint) { /* malloc CSR pointers */ 9189566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(A->rmap->n + 1, &hoi, onnz, &hoj)); 919f4f49eeaSPierre Jolivet for (i = 0; i < A->rmap->n + 1; i++) hoi[i] = (HYPRE_Int)poi[i]; 920f4f49eeaSPierre Jolivet for (i = 0; i < onnz; i++) hoj[i] = (HYPRE_Int)poj[i]; 9212cf14000SStefano Zampini } 9226ea7df73SStefano Zampini hypre_CSRMatrixI(hoffd) = hoi; 9236ea7df73SStefano Zampini hypre_CSRMatrixJ(hoffd) = hoj; 92439accc25SStefano Zampini hypre_CSRMatrixData(hoffd) = (HYPRE_Complex *)offd->a; 925c1a070e6SStefano Zampini hypre_CSRMatrixNumNonzeros(hoffd) = offd->nz; 926c1a070e6SStefano Zampini hypre_CSRMatrixSetRownnz(hoffd); 927c1a070e6SStefano Zampini hypre_CSRMatrixSetDataOwner(hoffd, 0); 9286ea7df73SStefano Zampini } 9296ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 93006977982Sstefanozampini PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, !boundtocpu ? HYPRE_MEMORY_DEVICE : HYPRE_MEMORY_HOST); 9316ea7df73SStefano Zampini #else 9326ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0) 933792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixInitialize, tA); 9346ea7df73SStefano Zampini #else 935792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, HYPRE_MEMORY_HOST); 9366ea7df73SStefano Zampini #endif 9376ea7df73SStefano Zampini #endif 9386ea7df73SStefano Zampini hypre_TFree(hypre_ParCSRMatrixColMapOffd(tA), HYPRE_MEMORY_HOST); 939c1a070e6SStefano Zampini hypre_ParCSRMatrixSetNumNonzeros(tA); 9402cf14000SStefano Zampini hypre_ParCSRMatrixColMapOffd(tA) = (HYPRE_BigInt *)garray; 941792fecdfSBarry Smith if (!hypre_ParCSRMatrixCommPkg(tA)) PetscCallExternal(hypre_MatvecCommPkgCreate, tA); 942613e5ff0Sstefano_zampini *hA = tA; 9433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 944613e5ff0Sstefano_zampini } 945c1a070e6SStefano Zampini 946d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJRestoreParCSR_Private(Mat A, hypre_ParCSRMatrix **hA) 947d71ae5a4SJacob Faibussowitsch { 948613e5ff0Sstefano_zampini hypre_CSRMatrix *hdiag, *hoffd; 9496ea7df73SStefano Zampini PetscBool ismpiaij, sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int)); 950b655ebf8SZach Atkins PetscBool iscuda, iship; 951c1a070e6SStefano Zampini 952613e5ff0Sstefano_zampini PetscFunctionBegin; 9539566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 9549566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, "")); 955b655ebf8SZach Atkins PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iship, MATSEQAIJHIPSPARSE, MATMPIAIJHIPSPARSE, "")); 956b655ebf8SZach Atkins #if defined(HYPRE_USING_CUDA) && defined(PETSC_HAVE_CUDA) 9576ea7df73SStefano Zampini if (iscuda) sameint = PETSC_TRUE; 958b655ebf8SZach Atkins #elif defined(HYPRE_USING_HIP) && defined(PETSC_HAVE_HIP) 959b655ebf8SZach Atkins if (iship) sameint = PETSC_TRUE; 9606ea7df73SStefano Zampini #endif 961613e5ff0Sstefano_zampini hdiag = hypre_ParCSRMatrixDiag(*hA); 962613e5ff0Sstefano_zampini hoffd = hypre_ParCSRMatrixOffd(*hA); 9636ea7df73SStefano Zampini /* free temporary memory allocated by PETSc 9646ea7df73SStefano Zampini set pointers to NULL before destroying tA */ 9652cf14000SStefano Zampini if (!sameint) { 9662cf14000SStefano Zampini HYPRE_Int *hi, *hj; 9672cf14000SStefano Zampini 9682cf14000SStefano Zampini hi = hypre_CSRMatrixI(hdiag); 9692cf14000SStefano Zampini hj = hypre_CSRMatrixJ(hdiag); 9709566063dSJacob Faibussowitsch PetscCall(PetscFree2(hi, hj)); 9716ea7df73SStefano Zampini if (ismpiaij) { 9722cf14000SStefano Zampini hi = hypre_CSRMatrixI(hoffd); 9732cf14000SStefano Zampini hj = hypre_CSRMatrixJ(hoffd); 9749566063dSJacob Faibussowitsch PetscCall(PetscFree2(hi, hj)); 9752cf14000SStefano Zampini } 9762cf14000SStefano Zampini } 977c1a070e6SStefano Zampini hypre_CSRMatrixI(hdiag) = NULL; 978c1a070e6SStefano Zampini hypre_CSRMatrixJ(hdiag) = NULL; 979c1a070e6SStefano Zampini hypre_CSRMatrixData(hdiag) = NULL; 9806ea7df73SStefano Zampini if (ismpiaij) { 981c1a070e6SStefano Zampini hypre_CSRMatrixI(hoffd) = NULL; 982c1a070e6SStefano Zampini hypre_CSRMatrixJ(hoffd) = NULL; 983c1a070e6SStefano Zampini hypre_CSRMatrixData(hoffd) = NULL; 9846ea7df73SStefano Zampini } 985613e5ff0Sstefano_zampini hypre_ParCSRMatrixColMapOffd(*hA) = NULL; 986613e5ff0Sstefano_zampini hypre_ParCSRMatrixDestroy(*hA); 987613e5ff0Sstefano_zampini *hA = NULL; 9883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 989613e5ff0Sstefano_zampini } 990613e5ff0Sstefano_zampini 991613e5ff0Sstefano_zampini /* calls RAP from BoomerAMG: 9923dad0653Sstefano_zampini the resulting ParCSR will not own the column and row starts 9936ea7df73SStefano Zampini It looks like we don't need to have the diagonal entries ordered first */ 994d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_RAP(hypre_ParCSRMatrix *hR, hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hP, hypre_ParCSRMatrix **hRAP) 995d71ae5a4SJacob Faibussowitsch { 996a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 997613e5ff0Sstefano_zampini HYPRE_Int P_owns_col_starts, R_owns_row_starts; 998a1d2239cSSatish Balay #endif 999613e5ff0Sstefano_zampini 1000613e5ff0Sstefano_zampini PetscFunctionBegin; 1001a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 1002613e5ff0Sstefano_zampini P_owns_col_starts = hypre_ParCSRMatrixOwnsColStarts(hP); 1003613e5ff0Sstefano_zampini R_owns_row_starts = hypre_ParCSRMatrixOwnsRowStarts(hR); 1004a1d2239cSSatish Balay #endif 10056ea7df73SStefano Zampini /* can be replaced by version test later */ 10066ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 1007792fecdfSBarry Smith PetscStackPushExternal("hypre_ParCSRMatrixRAP"); 10086ea7df73SStefano Zampini *hRAP = hypre_ParCSRMatrixRAP(hR, hA, hP); 10096ea7df73SStefano Zampini PetscStackPop; 10106ea7df73SStefano Zampini #else 1011792fecdfSBarry Smith PetscCallExternal(hypre_BoomerAMGBuildCoarseOperator, hR, hA, hP, hRAP); 1012792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixSetNumNonzeros, *hRAP); 10136ea7df73SStefano Zampini #endif 1014613e5ff0Sstefano_zampini /* hypre_BoomerAMGBuildCoarseOperator steals the col_starts from P and the row_starts from R */ 1015a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 1016613e5ff0Sstefano_zampini hypre_ParCSRMatrixSetRowStartsOwner(*hRAP, 0); 1017613e5ff0Sstefano_zampini hypre_ParCSRMatrixSetColStartsOwner(*hRAP, 0); 1018613e5ff0Sstefano_zampini if (P_owns_col_starts) hypre_ParCSRMatrixSetColStartsOwner(hP, 1); 1019613e5ff0Sstefano_zampini if (R_owns_row_starts) hypre_ParCSRMatrixSetRowStartsOwner(hR, 1); 1020a1d2239cSSatish Balay #endif 10213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1022613e5ff0Sstefano_zampini } 1023613e5ff0Sstefano_zampini 1024d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat P, Mat C) 1025d71ae5a4SJacob Faibussowitsch { 10266f231fbdSstefano_zampini Mat B; 10276abb4441SStefano Zampini hypre_ParCSRMatrix *hA, *hP, *hPtAP = NULL; 10284222ddf1SHong Zhang Mat_Product *product = C->product; 1029613e5ff0Sstefano_zampini 1030613e5ff0Sstefano_zampini PetscFunctionBegin; 10319566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(A, &hA)); 10329566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(P, &hP)); 10339566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_RAP(hP, hA, hP, &hPtAP)); 10349566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(hPtAP, MATAIJ, PETSC_OWN_POINTER, &B)); 10354222ddf1SHong Zhang 10369566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(C, &B)); 10374222ddf1SHong Zhang C->product = product; 10384222ddf1SHong Zhang 10399566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(A, &hA)); 10409566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(P, &hP)); 10413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10426f231fbdSstefano_zampini } 10436f231fbdSstefano_zampini 1044d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatPtAPSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat P, PetscReal fill, Mat C) 1045d71ae5a4SJacob Faibussowitsch { 10466f231fbdSstefano_zampini PetscFunctionBegin; 10479566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATAIJ)); 10484222ddf1SHong Zhang C->ops->ptapnumeric = MatPtAPNumeric_AIJ_AIJ_wHYPRE; 10494222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_PtAP; 10503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1051613e5ff0Sstefano_zampini } 1052613e5ff0Sstefano_zampini 1053d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_HYPRE(Mat A, Mat P, Mat C) 1054d71ae5a4SJacob Faibussowitsch { 10554cc28894Sstefano_zampini Mat B; 10564cc28894Sstefano_zampini Mat_HYPRE *hP; 10576abb4441SStefano Zampini hypre_ParCSRMatrix *hA = NULL, *Pparcsr, *ptapparcsr = NULL; 1058613e5ff0Sstefano_zampini HYPRE_Int type; 1059613e5ff0Sstefano_zampini MPI_Comm comm = PetscObjectComm((PetscObject)A); 10604cc28894Sstefano_zampini PetscBool ishypre; 1061613e5ff0Sstefano_zampini 1062613e5ff0Sstefano_zampini PetscFunctionBegin; 10639566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre)); 106428b400f6SJacob Faibussowitsch PetscCheck(ishypre, comm, PETSC_ERR_USER, "P should be of type %s", MATHYPRE); 10654cc28894Sstefano_zampini hP = (Mat_HYPRE *)P->data; 1066792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type); 106708401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 1068792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr); 1069613e5ff0Sstefano_zampini 10709566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(A, &hA)); 10719566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, hA, Pparcsr, &ptapparcsr)); 10729566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(A, &hA)); 1073225daaf8SStefano Zampini 10744cc28894Sstefano_zampini /* create temporary matrix and merge to C */ 10759566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(ptapparcsr, ((PetscObject)C)->type_name, PETSC_OWN_POINTER, &B)); 10769566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(C, &B)); 10773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10784cc28894Sstefano_zampini } 10794cc28894Sstefano_zampini 1080d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_HYPRE_HYPRE(Mat A, Mat P, Mat C) 1081d71ae5a4SJacob Faibussowitsch { 10824cc28894Sstefano_zampini Mat B; 10836abb4441SStefano Zampini hypre_ParCSRMatrix *Aparcsr, *Pparcsr, *ptapparcsr = NULL; 10844cc28894Sstefano_zampini Mat_HYPRE *hA, *hP; 10854cc28894Sstefano_zampini PetscBool ishypre; 10864cc28894Sstefano_zampini HYPRE_Int type; 10874cc28894Sstefano_zampini 10884cc28894Sstefano_zampini PetscFunctionBegin; 10899566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre)); 109028b400f6SJacob Faibussowitsch PetscCheck(ishypre, PetscObjectComm((PetscObject)P), PETSC_ERR_USER, "P should be of type %s", MATHYPRE); 10919566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre)); 109228b400f6SJacob Faibussowitsch PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE); 10934cc28894Sstefano_zampini hA = (Mat_HYPRE *)A->data; 10944cc28894Sstefano_zampini hP = (Mat_HYPRE *)P->data; 1095792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type); 109608401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 1097792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type); 109808401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)P), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 1099792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr); 1100792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr); 11019566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, Aparcsr, Pparcsr, &ptapparcsr)); 11029566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(ptapparcsr, MATHYPRE, PETSC_OWN_POINTER, &B)); 11039566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(C, &B)); 11043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11054cc28894Sstefano_zampini } 11064cc28894Sstefano_zampini 1107d501dc42Sstefano_zampini /* calls hypre_ParMatmul 1108d501dc42Sstefano_zampini hypre_ParMatMul uses hypre_ParMatrixCreate with the communicator of hA 11093dad0653Sstefano_zampini hypre_ParMatrixCreate does not duplicate the communicator 11106ea7df73SStefano Zampini It looks like we don't need to have the diagonal entries ordered first */ 1111d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_MatMatMult(hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hB, hypre_ParCSRMatrix **hAB) 1112d71ae5a4SJacob Faibussowitsch { 1113d501dc42Sstefano_zampini PetscFunctionBegin; 11146ea7df73SStefano Zampini /* can be replaced by version test later */ 11156ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 1116792fecdfSBarry Smith PetscStackPushExternal("hypre_ParCSRMatMat"); 11176ea7df73SStefano Zampini *hAB = hypre_ParCSRMatMat(hA, hB); 11186ea7df73SStefano Zampini #else 1119792fecdfSBarry Smith PetscStackPushExternal("hypre_ParMatmul"); 1120d501dc42Sstefano_zampini *hAB = hypre_ParMatmul(hA, hB); 11216ea7df73SStefano Zampini #endif 1122d501dc42Sstefano_zampini PetscStackPop; 11233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1124d501dc42Sstefano_zampini } 1125d501dc42Sstefano_zampini 1126d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C) 1127d71ae5a4SJacob Faibussowitsch { 11285e5acdf2Sstefano_zampini Mat D; 1129d501dc42Sstefano_zampini hypre_ParCSRMatrix *hA, *hB, *hAB = NULL; 11304222ddf1SHong Zhang Mat_Product *product = C->product; 11315e5acdf2Sstefano_zampini 11325e5acdf2Sstefano_zampini PetscFunctionBegin; 11339566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(A, &hA)); 11349566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(B, &hB)); 11359566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_MatMatMult(hA, hB, &hAB)); 11369566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(hAB, MATAIJ, PETSC_OWN_POINTER, &D)); 11374222ddf1SHong Zhang 11389566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(C, &D)); 11394222ddf1SHong Zhang C->product = product; 11404222ddf1SHong Zhang 11419566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(A, &hA)); 11429566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(B, &hB)); 11433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11445e5acdf2Sstefano_zampini } 11455e5acdf2Sstefano_zampini 1146d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatMatMultSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat B, PetscReal fill, Mat C) 1147d71ae5a4SJacob Faibussowitsch { 11485e5acdf2Sstefano_zampini PetscFunctionBegin; 11499566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATAIJ)); 11504222ddf1SHong Zhang C->ops->matmultnumeric = MatMatMultNumeric_AIJ_AIJ_wHYPRE; 11514222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_AB; 11523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11535e5acdf2Sstefano_zampini } 11545e5acdf2Sstefano_zampini 1155d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_HYPRE_HYPRE(Mat A, Mat B, Mat C) 1156d71ae5a4SJacob Faibussowitsch { 1157d501dc42Sstefano_zampini Mat D; 1158d501dc42Sstefano_zampini hypre_ParCSRMatrix *Aparcsr, *Bparcsr, *ABparcsr = NULL; 1159d501dc42Sstefano_zampini Mat_HYPRE *hA, *hB; 1160d501dc42Sstefano_zampini PetscBool ishypre; 1161d501dc42Sstefano_zampini HYPRE_Int type; 11624222ddf1SHong Zhang Mat_Product *product; 1163d501dc42Sstefano_zampini 1164d501dc42Sstefano_zampini PetscFunctionBegin; 11659566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)B, MATHYPRE, &ishypre)); 116628b400f6SJacob Faibussowitsch PetscCheck(ishypre, PetscObjectComm((PetscObject)B), PETSC_ERR_USER, "B should be of type %s", MATHYPRE); 11679566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre)); 116828b400f6SJacob Faibussowitsch PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE); 1169d501dc42Sstefano_zampini hA = (Mat_HYPRE *)A->data; 1170d501dc42Sstefano_zampini hB = (Mat_HYPRE *)B->data; 1171792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type); 117208401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 1173792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hB->ij, &type); 117408401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 1175792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr); 1176792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hB->ij, (void **)&Bparcsr); 11779566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_MatMatMult(Aparcsr, Bparcsr, &ABparcsr)); 11789566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(ABparcsr, MATHYPRE, PETSC_OWN_POINTER, &D)); 11794222ddf1SHong Zhang 1180d501dc42Sstefano_zampini /* need to use HeaderReplace because HeaderMerge messes up with the communicator */ 11814222ddf1SHong Zhang product = C->product; /* save it from MatHeaderReplace() */ 11824222ddf1SHong Zhang C->product = NULL; 11839566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(C, &D)); 11844222ddf1SHong Zhang C->product = product; 1185d501dc42Sstefano_zampini C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE; 11864222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_AB; 11873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1188d501dc42Sstefano_zampini } 1189d501dc42Sstefano_zampini 1190d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultNumeric_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, Mat D) 1191d71ae5a4SJacob Faibussowitsch { 119220e1dc0dSstefano_zampini Mat E; 11936abb4441SStefano Zampini hypre_ParCSRMatrix *hA, *hB, *hC, *hABC = NULL; 119420e1dc0dSstefano_zampini 119520e1dc0dSstefano_zampini PetscFunctionBegin; 11969566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(A, &hA)); 11979566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(B, &hB)); 11989566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(C, &hC)); 11999566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_RAP(hA, hB, hC, &hABC)); 12009566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(hABC, MATAIJ, PETSC_OWN_POINTER, &E)); 12019566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(D, &E)); 12029566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(A, &hA)); 12039566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(B, &hB)); 12049566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(C, &hC)); 12053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 120620e1dc0dSstefano_zampini } 120720e1dc0dSstefano_zampini 1208d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultSymbolic_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, PetscReal fill, Mat D) 1209d71ae5a4SJacob Faibussowitsch { 121020e1dc0dSstefano_zampini PetscFunctionBegin; 12119566063dSJacob Faibussowitsch PetscCall(MatSetType(D, MATAIJ)); 12123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 121320e1dc0dSstefano_zampini } 121420e1dc0dSstefano_zampini 1215d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_AB_HYPRE(Mat C) 1216d71ae5a4SJacob Faibussowitsch { 12174222ddf1SHong Zhang PetscFunctionBegin; 12184222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_AB; 12193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12204222ddf1SHong Zhang } 12214222ddf1SHong Zhang 1222d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_AB(Mat C) 1223d71ae5a4SJacob Faibussowitsch { 12244222ddf1SHong Zhang Mat_Product *product = C->product; 12254222ddf1SHong Zhang PetscBool Ahypre; 12264222ddf1SHong Zhang 12274222ddf1SHong Zhang PetscFunctionBegin; 12289566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)product->A, MATHYPRE, &Ahypre)); 12294222ddf1SHong Zhang if (Ahypre) { /* A is a Hypre matrix */ 12309566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATHYPRE)); 12314222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_AB_HYPRE; 12324222ddf1SHong Zhang C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE; 12333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12346718818eSStefano Zampini } 12353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12364222ddf1SHong Zhang } 12374222ddf1SHong Zhang 1238d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_PtAP_HYPRE(Mat C) 1239d71ae5a4SJacob Faibussowitsch { 12404222ddf1SHong Zhang PetscFunctionBegin; 12414222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_PtAP; 12423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12434222ddf1SHong Zhang } 12444222ddf1SHong Zhang 1245d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_PtAP(Mat C) 1246d71ae5a4SJacob Faibussowitsch { 12474222ddf1SHong Zhang Mat_Product *product = C->product; 12484222ddf1SHong Zhang PetscBool flg; 12494222ddf1SHong Zhang PetscInt type = 0; 12504222ddf1SHong Zhang const char *outTypes[4] = {"aij", "seqaij", "mpiaij", "hypre"}; 12514222ddf1SHong Zhang PetscInt ntype = 4; 12524222ddf1SHong Zhang Mat A = product->A; 12534222ddf1SHong Zhang PetscBool Ahypre; 12544222ddf1SHong Zhang 12554222ddf1SHong Zhang PetscFunctionBegin; 12569566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &Ahypre)); 12574222ddf1SHong Zhang if (Ahypre) { /* A is a Hypre matrix */ 12589566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATHYPRE)); 12594222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE; 12604222ddf1SHong Zhang C->ops->ptapnumeric = MatPtAPNumeric_HYPRE_HYPRE; 12613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12624222ddf1SHong Zhang } 12634222ddf1SHong Zhang 12644222ddf1SHong Zhang /* A is AIJ, P is Hypre, C = PtAP can be either AIJ or Hypre format */ 12654222ddf1SHong Zhang /* Get runtime option */ 12664222ddf1SHong Zhang if (product->api_user) { 1267d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatPtAP_HYPRE", "Mat"); 12689566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-matptap_hypre_outtype", "MatPtAP outtype", "MatPtAP outtype", outTypes, ntype, outTypes[type], &type, &flg)); 1269d0609cedSBarry Smith PetscOptionsEnd(); 12704222ddf1SHong Zhang } else { 1271d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatProduct_PtAP_HYPRE", "Mat"); 12729566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-mat_product_algorithm_hypre_outtype", "MatProduct_PtAP outtype", "MatProduct_PtAP", outTypes, ntype, outTypes[type], &type, &flg)); 1273d0609cedSBarry Smith PetscOptionsEnd(); 12744222ddf1SHong Zhang } 12754222ddf1SHong Zhang 12764222ddf1SHong Zhang if (type == 0 || type == 1 || type == 2) { 12779566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATAIJ)); 12784222ddf1SHong Zhang } else if (type == 3) { 12799566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATHYPRE)); 12804222ddf1SHong Zhang } else SETERRQ(PetscObjectComm((PetscObject)C), PETSC_ERR_SUP, "MatPtAP outtype is not supported"); 12814222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE; 12824222ddf1SHong Zhang C->ops->ptapnumeric = MatPtAPNumeric_AIJ_HYPRE; 12833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12844222ddf1SHong Zhang } 12854222ddf1SHong Zhang 1286d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE(Mat C) 1287d71ae5a4SJacob Faibussowitsch { 12884222ddf1SHong Zhang Mat_Product *product = C->product; 12894222ddf1SHong Zhang 12904222ddf1SHong Zhang PetscFunctionBegin; 12914222ddf1SHong Zhang switch (product->type) { 1292d71ae5a4SJacob Faibussowitsch case MATPRODUCT_AB: 1293d71ae5a4SJacob Faibussowitsch PetscCall(MatProductSetFromOptions_HYPRE_AB(C)); 1294d71ae5a4SJacob Faibussowitsch break; 1295d71ae5a4SJacob Faibussowitsch case MATPRODUCT_PtAP: 1296d71ae5a4SJacob Faibussowitsch PetscCall(MatProductSetFromOptions_HYPRE_PtAP(C)); 1297d71ae5a4SJacob Faibussowitsch break; 1298d71ae5a4SJacob Faibussowitsch default: 1299d71ae5a4SJacob Faibussowitsch break; 13004222ddf1SHong Zhang } 13013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13024222ddf1SHong Zhang } 13034222ddf1SHong Zhang 1304d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTranspose_HYPRE(Mat A, Vec x, Vec y) 1305d71ae5a4SJacob Faibussowitsch { 130663c07aadSStefano Zampini PetscFunctionBegin; 13079566063dSJacob Faibussowitsch PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_TRUE)); 13083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 130963c07aadSStefano Zampini } 131063c07aadSStefano Zampini 1311d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_HYPRE(Mat A, Vec x, Vec y) 1312d71ae5a4SJacob Faibussowitsch { 131363c07aadSStefano Zampini PetscFunctionBegin; 13149566063dSJacob Faibussowitsch PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_FALSE)); 13153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 131663c07aadSStefano Zampini } 131763c07aadSStefano Zampini 1318d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultAdd_HYPRE(Mat A, Vec x, Vec y, Vec z) 1319d71ae5a4SJacob Faibussowitsch { 1320414bd5c3SStefano Zampini PetscFunctionBegin; 132148a46eb9SPierre Jolivet if (y != z) PetscCall(VecCopy(y, z)); 13229566063dSJacob Faibussowitsch PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_FALSE)); 13233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1324414bd5c3SStefano Zampini } 1325414bd5c3SStefano Zampini 1326d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTransposeAdd_HYPRE(Mat A, Vec x, Vec y, Vec z) 1327d71ae5a4SJacob Faibussowitsch { 1328414bd5c3SStefano Zampini PetscFunctionBegin; 132948a46eb9SPierre Jolivet if (y != z) PetscCall(VecCopy(y, z)); 13309566063dSJacob Faibussowitsch PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_TRUE)); 13313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1332414bd5c3SStefano Zampini } 1333414bd5c3SStefano Zampini 1334414bd5c3SStefano Zampini /* y = a * A * x + b * y or y = a * A^t * x + b * y depending on trans */ 1335d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_MultKernel_Private(Mat A, HYPRE_Complex a, Vec x, HYPRE_Complex b, Vec y, PetscBool trans) 1336d71ae5a4SJacob Faibussowitsch { 133763c07aadSStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 133863c07aadSStefano Zampini hypre_ParCSRMatrix *parcsr; 133963c07aadSStefano Zampini hypre_ParVector *hx, *hy; 134063c07aadSStefano Zampini 134163c07aadSStefano Zampini PetscFunctionBegin; 134263c07aadSStefano Zampini if (trans) { 13439566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorPushVecRead(hA->b, x)); 13449566063dSJacob Faibussowitsch if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->x, y)); 13459566063dSJacob Faibussowitsch else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->x, y)); 1346792fecdfSBarry Smith PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hx); 1347792fecdfSBarry Smith PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hy); 134863c07aadSStefano Zampini } else { 13499566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorPushVecRead(hA->x, x)); 13509566063dSJacob Faibussowitsch if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->b, y)); 13519566063dSJacob Faibussowitsch else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->b, y)); 1352792fecdfSBarry Smith PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hx); 1353792fecdfSBarry Smith PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hy); 135463c07aadSStefano Zampini } 1355792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr); 13566ea7df73SStefano Zampini if (trans) { 1357792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixMatvecT, a, parcsr, hx, b, hy); 13586ea7df73SStefano Zampini } else { 1359792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixMatvec, a, parcsr, hx, b, hy); 13606ea7df73SStefano Zampini } 13619566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorPopVec(hA->x)); 13629566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorPopVec(hA->b)); 13633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 136463c07aadSStefano Zampini } 136563c07aadSStefano Zampini 1366d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_HYPRE(Mat A) 1367d71ae5a4SJacob Faibussowitsch { 136863c07aadSStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 136963c07aadSStefano Zampini 137063c07aadSStefano Zampini PetscFunctionBegin; 13719566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorDestroy(&hA->x)); 13729566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorDestroy(&hA->b)); 137306977982Sstefanozampini PetscCall(MatHYPRE_DestroyCOOMat(A)); /* must be called before destroying the individual CSR */ 1374978814f1SStefano Zampini if (hA->ij) { 1375978814f1SStefano Zampini if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL; 1376792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixDestroy, hA->ij); 1377978814f1SStefano Zampini } 13789566063dSJacob Faibussowitsch if (hA->comm) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)A), &hA->comm)); 1379c69f721fSFande Kong 13809566063dSJacob Faibussowitsch PetscCall(MatStashDestroy_Private(&A->stash)); 13819566063dSJacob Faibussowitsch PetscCall(PetscFree(hA->array)); 1382a32e9c99SJunchao Zhang if (hA->rows_d) PetscStackCallExternalVoid("hypre_Free", hypre_Free(hA->rows_d, HYPRE_MEMORY_DEVICE)); 1383c69f721fSFande Kong 13849566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_aij_C", NULL)); 13859566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_is_C", NULL)); 13869566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_hypre_C", NULL)); 13879566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaij_hypre_C", NULL)); 138806977982Sstefanozampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijhipsparse_hypre_C", NULL)); 138906977982Sstefanozampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaijhipsparse_hypre_C", NULL)); 139006977982Sstefanozampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijcusparse_hypre_C", NULL)); 139106977982Sstefanozampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaijcusparse_hypre_C", NULL)); 13929566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPRESetPreallocation_C", NULL)); 13939566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPREGetParCSR_C", NULL)); 13945fbaff96SJunchao Zhang PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL)); 13955fbaff96SJunchao Zhang PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL)); 13969566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 13973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 139863c07aadSStefano Zampini } 139963c07aadSStefano Zampini 1400d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetUp_HYPRE(Mat A) 1401d71ae5a4SJacob Faibussowitsch { 14024ec6421dSstefano_zampini PetscFunctionBegin; 140306977982Sstefanozampini if (!A->preallocated) PetscCall(MatHYPRESetPreallocation(A, PETSC_DEFAULT, NULL, PETSC_DEFAULT, NULL)); 14043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14054ec6421dSstefano_zampini } 14064ec6421dSstefano_zampini 14076ea7df73SStefano Zampini //TODO FIX hypre_CSRMatrixMatvecOutOfPlace 14086ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 1409d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatBindToCPU_HYPRE(Mat A, PetscBool bind) 1410d71ae5a4SJacob Faibussowitsch { 14116ea7df73SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 14126ea7df73SStefano Zampini HYPRE_MemoryLocation hmem = bind ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE; 14136ea7df73SStefano Zampini 14146ea7df73SStefano Zampini PetscFunctionBegin; 14156ea7df73SStefano Zampini A->boundtocpu = bind; 14165fbaff96SJunchao Zhang if (hA->ij && hypre_IJMatrixAssembleFlag(hA->ij) && hmem != hypre_IJMatrixMemoryLocation(hA->ij)) { 14176ea7df73SStefano Zampini hypre_ParCSRMatrix *parcsr; 1418792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr); 1419792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixMigrate, parcsr, hmem); 14206ea7df73SStefano Zampini } 14219566063dSJacob Faibussowitsch if (hA->x) PetscCall(VecHYPRE_IJBindToCPU(hA->x, bind)); 14229566063dSJacob Faibussowitsch if (hA->b) PetscCall(VecHYPRE_IJBindToCPU(hA->b, bind)); 14233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14246ea7df73SStefano Zampini } 14256ea7df73SStefano Zampini #endif 14266ea7df73SStefano Zampini 1427d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_HYPRE(Mat A, MatAssemblyType mode) 1428d71ae5a4SJacob Faibussowitsch { 142963c07aadSStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1430c69f721fSFande Kong PetscMPIInt n; 1431c69f721fSFande Kong PetscInt i, j, rstart, ncols, flg; 1432c69f721fSFande Kong PetscInt *row, *col; 1433c69f721fSFande Kong PetscScalar *val; 143463c07aadSStefano Zampini 143563c07aadSStefano Zampini PetscFunctionBegin; 143608401ef6SPierre Jolivet PetscCheck(mode != MAT_FLUSH_ASSEMBLY, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_FLUSH_ASSEMBLY currently not supported with MATHYPRE"); 1437c69f721fSFande Kong 1438c69f721fSFande Kong if (!A->nooffprocentries) { 1439c69f721fSFande Kong while (1) { 14409566063dSJacob Faibussowitsch PetscCall(MatStashScatterGetMesg_Private(&A->stash, &n, &row, &col, &val, &flg)); 1441c69f721fSFande Kong if (!flg) break; 1442c69f721fSFande Kong 1443c69f721fSFande Kong for (i = 0; i < n;) { 1444c69f721fSFande Kong /* Now identify the consecutive vals belonging to the same row */ 1445c69f721fSFande Kong for (j = i, rstart = row[j]; j < n; j++) { 1446c69f721fSFande Kong if (row[j] != rstart) break; 1447c69f721fSFande Kong } 1448c69f721fSFande Kong if (j < n) ncols = j - i; 1449c69f721fSFande Kong else ncols = n - i; 1450c69f721fSFande Kong /* Now assemble all these values with a single function call */ 14519566063dSJacob Faibussowitsch PetscCall(MatSetValues_HYPRE(A, 1, row + i, ncols, col + i, val + i, A->insertmode)); 1452c69f721fSFande Kong 1453c69f721fSFande Kong i = j; 1454c69f721fSFande Kong } 1455c69f721fSFande Kong } 14569566063dSJacob Faibussowitsch PetscCall(MatStashScatterEnd_Private(&A->stash)); 1457c69f721fSFande Kong } 1458c69f721fSFande Kong 1459792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixAssemble, hA->ij); 1460336664bdSPierre Jolivet /* The assembly routine destroys the aux_matrix, we recreate it here by calling HYPRE_IJMatrixInitialize */ 1461336664bdSPierre 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 */ 1462651b1cf9SStefano Zampini if (!A->sortedfull) { 1463af1cf968SStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 1464af1cf968SStefano Zampini 1465af1cf968SStefano Zampini /* call destroy just to make sure we do not leak anything */ 1466af1cf968SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij); 1467792fecdfSBarry Smith PetscCallExternal(hypre_AuxParCSRMatrixDestroy, aux_matrix); 1468af1cf968SStefano Zampini hypre_IJMatrixTranslator(hA->ij) = NULL; 1469af1cf968SStefano Zampini 1470af1cf968SStefano Zampini /* Initialize with assembled flag -> it only recreates the aux_par_matrix */ 1471792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij); 1472af1cf968SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij); 14736ea7df73SStefano Zampini if (aux_matrix) { 1474af1cf968SStefano Zampini hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1; /* see comment in MatHYPRESetPreallocation_HYPRE */ 147522235d61SPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 1476792fecdfSBarry Smith PetscCallExternal(hypre_AuxParCSRMatrixInitialize, aux_matrix); 147722235d61SPierre Jolivet #else 1478792fecdfSBarry Smith PetscCallExternal(hypre_AuxParCSRMatrixInitialize_v2, aux_matrix, HYPRE_MEMORY_HOST); 147922235d61SPierre Jolivet #endif 1480af1cf968SStefano Zampini } 14816ea7df73SStefano Zampini } 14826ea7df73SStefano Zampini { 14836ea7df73SStefano Zampini hypre_ParCSRMatrix *parcsr; 14846ea7df73SStefano Zampini 1485792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr); 1486792fecdfSBarry Smith if (!hypre_ParCSRMatrixCommPkg(parcsr)) PetscCallExternal(hypre_MatvecCommPkgCreate, parcsr); 14876ea7df73SStefano Zampini } 14889566063dSJacob Faibussowitsch if (!hA->x) PetscCall(VecHYPRE_IJVectorCreate(A->cmap, &hA->x)); 14899566063dSJacob Faibussowitsch if (!hA->b) PetscCall(VecHYPRE_IJVectorCreate(A->rmap, &hA->b)); 14906ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 14919566063dSJacob Faibussowitsch PetscCall(MatBindToCPU_HYPRE(A, A->boundtocpu)); 14926ea7df73SStefano Zampini #endif 14933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 149463c07aadSStefano Zampini } 149563c07aadSStefano Zampini 1496d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetArray_HYPRE(Mat A, PetscInt size, void **array) 1497d71ae5a4SJacob Faibussowitsch { 1498c69f721fSFande Kong Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1499c69f721fSFande Kong 1500c69f721fSFande Kong PetscFunctionBegin; 1501651b1cf9SStefano Zampini PetscCheck(hA->array_available, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Temporary space is in use"); 1502c69f721fSFande Kong 1503651b1cf9SStefano Zampini if (hA->array_size >= size) { 150439accc25SStefano Zampini *array = hA->array; 150539accc25SStefano Zampini } else { 15069566063dSJacob Faibussowitsch PetscCall(PetscFree(hA->array)); 1507651b1cf9SStefano Zampini hA->array_size = size; 1508651b1cf9SStefano Zampini PetscCall(PetscMalloc(hA->array_size, &hA->array)); 1509c69f721fSFande Kong *array = hA->array; 1510c69f721fSFande Kong } 1511c69f721fSFande Kong 1512651b1cf9SStefano Zampini hA->array_available = PETSC_FALSE; 15133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1514c69f721fSFande Kong } 1515c69f721fSFande Kong 1516d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreArray_HYPRE(Mat A, void **array) 1517d71ae5a4SJacob Faibussowitsch { 1518c69f721fSFande Kong Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1519c69f721fSFande Kong 1520c69f721fSFande Kong PetscFunctionBegin; 1521c69f721fSFande Kong *array = NULL; 1522651b1cf9SStefano Zampini hA->array_available = PETSC_TRUE; 15233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1524c69f721fSFande Kong } 1525c69f721fSFande Kong 1526d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_HYPRE(Mat A, PetscInt nr, const PetscInt rows[], PetscInt nc, const PetscInt cols[], const PetscScalar v[], InsertMode ins) 1527d71ae5a4SJacob Faibussowitsch { 1528d975228cSstefano_zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1529d975228cSstefano_zampini PetscScalar *vals = (PetscScalar *)v; 153039accc25SStefano Zampini HYPRE_Complex *sscr; 1531c69f721fSFande Kong PetscInt *cscr[2]; 1532c69f721fSFande Kong PetscInt i, nzc; 1533651b1cf9SStefano Zampini PetscInt rst = A->rmap->rstart, ren = A->rmap->rend; 153408defe43SFande Kong void *array = NULL; 1535d975228cSstefano_zampini 1536d975228cSstefano_zampini PetscFunctionBegin; 15379566063dSJacob Faibussowitsch PetscCall(MatGetArray_HYPRE(A, sizeof(PetscInt) * (2 * nc) + sizeof(HYPRE_Complex) * nc * nr, &array)); 1538c69f721fSFande Kong cscr[0] = (PetscInt *)array; 1539c69f721fSFande Kong cscr[1] = ((PetscInt *)array) + nc; 154039accc25SStefano Zampini sscr = (HYPRE_Complex *)(((PetscInt *)array) + nc * 2); 1541d975228cSstefano_zampini for (i = 0, nzc = 0; i < nc; i++) { 1542d975228cSstefano_zampini if (cols[i] >= 0) { 1543d975228cSstefano_zampini cscr[0][nzc] = cols[i]; 1544d975228cSstefano_zampini cscr[1][nzc++] = i; 1545d975228cSstefano_zampini } 1546d975228cSstefano_zampini } 1547c69f721fSFande Kong if (!nzc) { 15489566063dSJacob Faibussowitsch PetscCall(MatRestoreArray_HYPRE(A, &array)); 15493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1550c69f721fSFande Kong } 1551d975228cSstefano_zampini 15526ea7df73SStefano Zampini #if 0 //defined(PETSC_HAVE_HYPRE_DEVICE) 15536ea7df73SStefano Zampini if (HYPRE_MEMORY_HOST != hypre_IJMatrixMemoryLocation(hA->ij)) { 15546ea7df73SStefano Zampini hypre_ParCSRMatrix *parcsr; 15556ea7df73SStefano Zampini 1556792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject,hA->ij,(void**)&parcsr); 1557792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixMigrate,parcsr, HYPRE_MEMORY_HOST); 15586ea7df73SStefano Zampini } 15596ea7df73SStefano Zampini #endif 15606ea7df73SStefano Zampini 1561d975228cSstefano_zampini if (ins == ADD_VALUES) { 1562d975228cSstefano_zampini for (i = 0; i < nr; i++) { 15636ea7df73SStefano Zampini if (rows[i] >= 0) { 1564d975228cSstefano_zampini PetscInt j; 15652cf14000SStefano Zampini HYPRE_Int hnc = (HYPRE_Int)nzc; 15662cf14000SStefano Zampini 1567651b1cf9SStefano Zampini if (!nzc) continue; 1568651b1cf9SStefano Zampini /* nonlocal values */ 1569651b1cf9SStefano Zampini if (rows[i] < rst || rows[i] >= ren) { 1570651b1cf9SStefano Zampini PetscCheck(!A->nooffprocentries, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Setting off process row %" PetscInt_FMT " even though MatSetOption(,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE) was set", rows[i]); 1571651b1cf9SStefano Zampini if (hA->donotstash) continue; 1572651b1cf9SStefano Zampini } 1573aed4548fSBarry 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]); 15749566063dSJacob Faibussowitsch for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j])); 1575792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixAddToValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr); 1576d975228cSstefano_zampini } 1577d975228cSstefano_zampini vals += nc; 1578d975228cSstefano_zampini } 1579d975228cSstefano_zampini } else { /* INSERT_VALUES */ 1580d975228cSstefano_zampini for (i = 0; i < nr; i++) { 15816ea7df73SStefano Zampini if (rows[i] >= 0) { 1582d975228cSstefano_zampini PetscInt j; 15832cf14000SStefano Zampini HYPRE_Int hnc = (HYPRE_Int)nzc; 15842cf14000SStefano Zampini 1585651b1cf9SStefano Zampini if (!nzc) continue; 1586aed4548fSBarry 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]); 15879566063dSJacob Faibussowitsch for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j])); 1588c69f721fSFande Kong /* nonlocal values */ 1589651b1cf9SStefano Zampini if (rows[i] < rst || rows[i] >= ren) { 1590651b1cf9SStefano Zampini PetscCheck(!A->nooffprocentries, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Setting off process row %" PetscInt_FMT " even though MatSetOption(,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE) was set", rows[i]); 1591651b1cf9SStefano Zampini if (!hA->donotstash) PetscCall(MatStashValuesRow_Private(&A->stash, rows[i], nzc, cscr[0], (PetscScalar *)sscr, PETSC_FALSE)); 1592651b1cf9SStefano Zampini } 1593c69f721fSFande Kong /* local values */ 1594651b1cf9SStefano Zampini else 1595651b1cf9SStefano Zampini PetscCallExternal(HYPRE_IJMatrixSetValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr); 1596d975228cSstefano_zampini } 1597d975228cSstefano_zampini vals += nc; 1598d975228cSstefano_zampini } 1599d975228cSstefano_zampini } 1600c69f721fSFande Kong 16019566063dSJacob Faibussowitsch PetscCall(MatRestoreArray_HYPRE(A, &array)); 16023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1603d975228cSstefano_zampini } 1604d975228cSstefano_zampini 1605d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRESetPreallocation_HYPRE(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[]) 1606d71ae5a4SJacob Faibussowitsch { 1607d975228cSstefano_zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 16087d968826Sstefano_zampini HYPRE_Int *hdnnz, *honnz; 160906a29025Sstefano_zampini PetscInt i, rs, re, cs, ce, bs; 1610d975228cSstefano_zampini PetscMPIInt size; 1611d975228cSstefano_zampini 1612d975228cSstefano_zampini PetscFunctionBegin; 16139566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 16149566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 1615d975228cSstefano_zampini rs = A->rmap->rstart; 1616d975228cSstefano_zampini re = A->rmap->rend; 1617d975228cSstefano_zampini cs = A->cmap->rstart; 1618d975228cSstefano_zampini ce = A->cmap->rend; 1619d975228cSstefano_zampini if (!hA->ij) { 1620792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rs, re - 1, cs, ce - 1, &hA->ij); 1621792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR); 1622d975228cSstefano_zampini } else { 16232cf14000SStefano Zampini HYPRE_BigInt hrs, hre, hcs, hce; 1624792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetLocalRange, hA->ij, &hrs, &hre, &hcs, &hce); 1625aed4548fSBarry 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); 1626aed4548fSBarry 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); 1627d975228cSstefano_zampini } 162806977982Sstefanozampini PetscCall(MatHYPRE_DestroyCOOMat(A)); 16299566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 163006a29025Sstefano_zampini if (dnz == PETSC_DEFAULT || dnz == PETSC_DECIDE) dnz = 10 * bs; 163106a29025Sstefano_zampini if (onz == PETSC_DEFAULT || onz == PETSC_DECIDE) onz = 10 * bs; 163206a29025Sstefano_zampini 1633d975228cSstefano_zampini if (!dnnz) { 16349566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n, &hdnnz)); 1635d975228cSstefano_zampini for (i = 0; i < A->rmap->n; i++) hdnnz[i] = dnz; 1636d975228cSstefano_zampini } else { 16377d968826Sstefano_zampini hdnnz = (HYPRE_Int *)dnnz; 1638d975228cSstefano_zampini } 16399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 1640d975228cSstefano_zampini if (size > 1) { 1641ddbeb582SStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 1642d975228cSstefano_zampini if (!onnz) { 16439566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n, &honnz)); 1644d975228cSstefano_zampini for (i = 0; i < A->rmap->n; i++) honnz[i] = onz; 164522235d61SPierre Jolivet } else honnz = (HYPRE_Int *)onnz; 1646ddbeb582SStefano Zampini /* SetDiagOffdSizes sets hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0, since it seems 1647ddbeb582SStefano Zampini they assume the user will input the entire row values, properly sorted 1648336664bdSPierre Jolivet In PETSc, we don't make such an assumption and set this flag to 1, 1649336664bdSPierre Jolivet unless the option MAT_SORTED_FULL is set to true. 1650ddbeb582SStefano Zampini Also, to avoid possible memory leaks, we destroy and recreate the translator 1651ddbeb582SStefano Zampini This has to be done here, as HYPRE_IJMatrixInitialize will properly initialize 1652ddbeb582SStefano Zampini the IJ matrix for us */ 1653ddbeb582SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij); 1654ddbeb582SStefano Zampini hypre_AuxParCSRMatrixDestroy(aux_matrix); 1655ddbeb582SStefano Zampini hypre_IJMatrixTranslator(hA->ij) = NULL; 1656792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, hA->ij, hdnnz, honnz); 1657ddbeb582SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij); 1658651b1cf9SStefano Zampini hypre_AuxParCSRMatrixNeedAux(aux_matrix) = !A->sortedfull; 1659d975228cSstefano_zampini } else { 1660d975228cSstefano_zampini honnz = NULL; 1661792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetRowSizes, hA->ij, hdnnz); 1662d975228cSstefano_zampini } 1663ddbeb582SStefano Zampini 1664af1cf968SStefano Zampini /* reset assembled flag and call the initialize method */ 1665af1cf968SStefano Zampini hypre_IJMatrixAssembleFlag(hA->ij) = 0; 16666ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 1667792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij); 16686ea7df73SStefano Zampini #else 1669792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize_v2, hA->ij, HYPRE_MEMORY_HOST); 16706ea7df73SStefano Zampini #endif 167148a46eb9SPierre Jolivet if (!dnnz) PetscCall(PetscFree(hdnnz)); 167248a46eb9SPierre Jolivet if (!onnz && honnz) PetscCall(PetscFree(honnz)); 1673af1cf968SStefano Zampini /* Match AIJ logic */ 167406a29025Sstefano_zampini A->preallocated = PETSC_TRUE; 1675af1cf968SStefano Zampini A->assembled = PETSC_FALSE; 16763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1677d975228cSstefano_zampini } 1678d975228cSstefano_zampini 1679d975228cSstefano_zampini /*@C 1680d975228cSstefano_zampini MatHYPRESetPreallocation - Preallocates memory for a sparse parallel matrix in HYPRE IJ format 1681d975228cSstefano_zampini 1682c3339decSBarry Smith Collective 1683d975228cSstefano_zampini 1684d975228cSstefano_zampini Input Parameters: 1685d975228cSstefano_zampini + A - the matrix 1686d975228cSstefano_zampini . dnz - number of nonzeros per row in DIAGONAL portion of local submatrix 1687d975228cSstefano_zampini (same value is used for all local rows) 1688d975228cSstefano_zampini . dnnz - array containing the number of nonzeros in the various rows of the 1689d975228cSstefano_zampini DIAGONAL portion of the local submatrix (possibly different for each row) 16902ef1f0ffSBarry Smith or `NULL` (`PETSC_NULL_INTEGER` in Fortran), if `d_nz` is used to specify the nonzero structure. 16912ef1f0ffSBarry Smith The size of this array is equal to the number of local rows, i.e `m`. 1692d975228cSstefano_zampini For matrices that will be factored, you must leave room for (and set) 1693d975228cSstefano_zampini the diagonal entry even if it is zero. 1694d975228cSstefano_zampini . onz - number of nonzeros per row in the OFF-DIAGONAL portion of local 1695d975228cSstefano_zampini submatrix (same value is used for all local rows). 1696d975228cSstefano_zampini - onnz - array containing the number of nonzeros in the various rows of the 1697d975228cSstefano_zampini OFF-DIAGONAL portion of the local submatrix (possibly different for 16982ef1f0ffSBarry Smith each row) or `NULL` (`PETSC_NULL_INTEGER` in Fortran), if `o_nz` is used to specify the nonzero 1699d975228cSstefano_zampini structure. The size of this array is equal to the number 17002ef1f0ffSBarry Smith of local rows, i.e `m`. 1701d975228cSstefano_zampini 17022fe279fdSBarry Smith Level: intermediate 17032fe279fdSBarry Smith 170411a5261eSBarry Smith Note: 17052ef1f0ffSBarry Smith If the *nnz parameter is given then the *nz parameter is ignored; for sequential matrices, `onz` and `onnz` are ignored. 1706d975228cSstefano_zampini 17071cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatMPIAIJSetPreallocation()`, `MATHYPRE`, `MATAIJ` 1708d975228cSstefano_zampini @*/ 1709d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHYPRESetPreallocation(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[]) 1710d71ae5a4SJacob Faibussowitsch { 1711d975228cSstefano_zampini PetscFunctionBegin; 1712d975228cSstefano_zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1713d975228cSstefano_zampini PetscValidType(A, 1); 1714cac4c232SBarry Smith PetscTryMethod(A, "MatHYPRESetPreallocation_C", (Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]), (A, dnz, dnnz, onz, onnz)); 17153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1716d975228cSstefano_zampini } 1717d975228cSstefano_zampini 171820f4b53cSBarry Smith /*@C 17192ef1f0ffSBarry Smith MatCreateFromParCSR - Creates a `Mat` from a `hypre_ParCSRMatrix` 1720225daaf8SStefano Zampini 1721225daaf8SStefano Zampini Collective 1722225daaf8SStefano Zampini 1723225daaf8SStefano Zampini Input Parameters: 17242ef1f0ffSBarry Smith + parcsr - the pointer to the `hypre_ParCSRMatrix` 17252ef1f0ffSBarry Smith . mtype - matrix type to be created. Currently `MATAIJ`, `MATIS` and `MATHYPRE` are supported. 172620f4b53cSBarry Smith - copymode - PETSc copying options, see `PetscCopyMode` 1727225daaf8SStefano Zampini 1728225daaf8SStefano Zampini Output Parameter: 1729225daaf8SStefano Zampini . A - the matrix 1730225daaf8SStefano Zampini 1731225daaf8SStefano Zampini Level: intermediate 1732225daaf8SStefano Zampini 1733bfe80ac4SPierre Jolivet .seealso: [](ch_matrices), `Mat`, `MATHYPRE`, `PetscCopyMode` 173420f4b53cSBarry Smith @*/ 1735d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreateFromParCSR(hypre_ParCSRMatrix *parcsr, MatType mtype, PetscCopyMode copymode, Mat *A) 1736d71ae5a4SJacob Faibussowitsch { 1737225daaf8SStefano Zampini Mat T; 1738978814f1SStefano Zampini Mat_HYPRE *hA; 1739978814f1SStefano Zampini MPI_Comm comm; 1740978814f1SStefano Zampini PetscInt rstart, rend, cstart, cend, M, N; 1741d248a85cSRichard Tran Mills PetscBool isseqaij, isseqaijmkl, ismpiaij, isaij, ishyp, isis; 1742978814f1SStefano Zampini 1743978814f1SStefano Zampini PetscFunctionBegin; 1744978814f1SStefano Zampini comm = hypre_ParCSRMatrixComm(parcsr); 17459566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQAIJ, &isseqaij)); 17469566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQAIJMKL, &isseqaijmkl)); 17479566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPIAIJ, &ismpiaij)); 17489566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATAIJ, &isaij)); 17499566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATHYPRE, &ishyp)); 17509566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATIS, &isis)); 1751d248a85cSRichard Tran Mills isaij = (PetscBool)(isseqaij || isseqaijmkl || ismpiaij || isaij); 17526ea7df73SStefano Zampini /* TODO */ 1753aed4548fSBarry 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); 1754978814f1SStefano Zampini /* access ParCSRMatrix */ 1755978814f1SStefano Zampini rstart = hypre_ParCSRMatrixFirstRowIndex(parcsr); 1756978814f1SStefano Zampini rend = hypre_ParCSRMatrixLastRowIndex(parcsr); 1757978814f1SStefano Zampini cstart = hypre_ParCSRMatrixFirstColDiag(parcsr); 1758978814f1SStefano Zampini cend = hypre_ParCSRMatrixLastColDiag(parcsr); 1759978814f1SStefano Zampini M = hypre_ParCSRMatrixGlobalNumRows(parcsr); 1760978814f1SStefano Zampini N = hypre_ParCSRMatrixGlobalNumCols(parcsr); 1761978814f1SStefano Zampini 1762978814f1SStefano Zampini /* create PETSc matrix with MatHYPRE */ 17639566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &T)); 1764c2886e86SStefano Zampini PetscCall(MatSetSizes(T, PetscMax(rend - rstart + 1, 0), PetscMax(cend - cstart + 1, 0), M, N)); 17659566063dSJacob Faibussowitsch PetscCall(MatSetType(T, MATHYPRE)); 1766f4f49eeaSPierre Jolivet hA = (Mat_HYPRE *)T->data; 1767978814f1SStefano Zampini 1768978814f1SStefano Zampini /* create HYPRE_IJMatrix */ 1769c2886e86SStefano Zampini PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rstart, rend, cstart, cend, &hA->ij); 1770792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR); 177145b8d346SStefano Zampini 177245b8d346SStefano Zampini /* create new ParCSR object if needed */ 177345b8d346SStefano Zampini if (ishyp && copymode == PETSC_COPY_VALUES) { 177445b8d346SStefano Zampini hypre_ParCSRMatrix *new_parcsr; 17756ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0) 177645b8d346SStefano Zampini hypre_CSRMatrix *hdiag, *hoffd, *ndiag, *noffd; 177745b8d346SStefano Zampini 17780e6427aaSSatish Balay new_parcsr = hypre_ParCSRMatrixClone(parcsr, 0); 177945b8d346SStefano Zampini hdiag = hypre_ParCSRMatrixDiag(parcsr); 178045b8d346SStefano Zampini hoffd = hypre_ParCSRMatrixOffd(parcsr); 178145b8d346SStefano Zampini ndiag = hypre_ParCSRMatrixDiag(new_parcsr); 178245b8d346SStefano Zampini noffd = hypre_ParCSRMatrixOffd(new_parcsr); 17839566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hypre_CSRMatrixData(ndiag), hypre_CSRMatrixData(hdiag), hypre_CSRMatrixNumNonzeros(hdiag))); 17849566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hypre_CSRMatrixData(noffd), hypre_CSRMatrixData(hoffd), hypre_CSRMatrixNumNonzeros(hoffd))); 17856ea7df73SStefano Zampini #else 17866ea7df73SStefano Zampini new_parcsr = hypre_ParCSRMatrixClone(parcsr, 1); 17876ea7df73SStefano Zampini #endif 178845b8d346SStefano Zampini parcsr = new_parcsr; 178945b8d346SStefano Zampini copymode = PETSC_OWN_POINTER; 179045b8d346SStefano Zampini } 1791978814f1SStefano Zampini 1792978814f1SStefano Zampini /* set ParCSR object */ 1793978814f1SStefano Zampini hypre_IJMatrixObject(hA->ij) = parcsr; 17944ec6421dSstefano_zampini T->preallocated = PETSC_TRUE; 1795978814f1SStefano Zampini 1796978814f1SStefano Zampini /* set assembled flag */ 1797978814f1SStefano Zampini hypre_IJMatrixAssembleFlag(hA->ij) = 1; 17986ea7df73SStefano Zampini #if 0 1799792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize,hA->ij); 18006ea7df73SStefano Zampini #endif 1801225daaf8SStefano Zampini if (ishyp) { 18026d2a658fSstefano_zampini PetscMPIInt myid = 0; 18036d2a658fSstefano_zampini 18046d2a658fSstefano_zampini /* make sure we always have row_starts and col_starts available */ 180548a46eb9SPierre Jolivet if (HYPRE_AssumedPartitionCheck()) PetscCallMPI(MPI_Comm_rank(comm, &myid)); 1806a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 18076d2a658fSstefano_zampini if (!hypre_ParCSRMatrixOwnsColStarts(parcsr)) { 18086d2a658fSstefano_zampini PetscLayout map; 18096d2a658fSstefano_zampini 18109566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(T, NULL, &map)); 18119566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(map)); 18122cf14000SStefano Zampini hypre_ParCSRMatrixColStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid); 18136d2a658fSstefano_zampini } 18146d2a658fSstefano_zampini if (!hypre_ParCSRMatrixOwnsRowStarts(parcsr)) { 18156d2a658fSstefano_zampini PetscLayout map; 18166d2a658fSstefano_zampini 18179566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(T, &map, NULL)); 18189566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(map)); 18192cf14000SStefano Zampini hypre_ParCSRMatrixRowStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid); 18206d2a658fSstefano_zampini } 1821a1d2239cSSatish Balay #endif 1822978814f1SStefano Zampini /* prevent from freeing the pointer */ 1823978814f1SStefano Zampini if (copymode == PETSC_USE_POINTER) hA->inner_free = PETSC_FALSE; 1824225daaf8SStefano Zampini *A = T; 18259566063dSJacob Faibussowitsch PetscCall(MatSetOption(*A, MAT_SORTED_FULL, PETSC_TRUE)); 18269566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*A, MAT_FINAL_ASSEMBLY)); 18279566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*A, MAT_FINAL_ASSEMBLY)); 1828bb4689ddSStefano Zampini } else if (isaij) { 1829bb4689ddSStefano Zampini if (copymode != PETSC_OWN_POINTER) { 1830225daaf8SStefano Zampini /* prevent from freeing the pointer */ 1831225daaf8SStefano Zampini hA->inner_free = PETSC_FALSE; 18329566063dSJacob Faibussowitsch PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INITIAL_MATRIX, A)); 18339566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 1834225daaf8SStefano Zampini } else { /* AIJ return type with PETSC_OWN_POINTER */ 18359566063dSJacob Faibussowitsch PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INPLACE_MATRIX, &T)); 1836225daaf8SStefano Zampini *A = T; 1837225daaf8SStefano Zampini } 1838bb4689ddSStefano Zampini } else if (isis) { 18399566063dSJacob Faibussowitsch PetscCall(MatConvert_HYPRE_IS(T, MATIS, MAT_INITIAL_MATRIX, A)); 18408cfe8d00SStefano Zampini if (copymode != PETSC_OWN_POINTER) hA->inner_free = PETSC_FALSE; 18419566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 1842bb4689ddSStefano Zampini } 18433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1844978814f1SStefano Zampini } 1845978814f1SStefano Zampini 1846d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPREGetParCSR_HYPRE(Mat A, hypre_ParCSRMatrix **parcsr) 1847d71ae5a4SJacob Faibussowitsch { 1848dd9c0a25Sstefano_zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1849dd9c0a25Sstefano_zampini HYPRE_Int type; 1850dd9c0a25Sstefano_zampini 1851dd9c0a25Sstefano_zampini PetscFunctionBegin; 185228b400f6SJacob Faibussowitsch PetscCheck(hA->ij, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "HYPRE_IJMatrix not present"); 1853792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type); 185408401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "HYPRE_IJMatrix is not of type HYPRE_PARCSR"); 1855792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)parcsr); 18563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1857dd9c0a25Sstefano_zampini } 1858dd9c0a25Sstefano_zampini 185920f4b53cSBarry Smith /*@C 1860dd9c0a25Sstefano_zampini MatHYPREGetParCSR - Gets the pointer to the ParCSR matrix 1861dd9c0a25Sstefano_zampini 1862cc4c1da9SBarry Smith Not Collective, No Fortran Support 1863dd9c0a25Sstefano_zampini 186420f4b53cSBarry Smith Input Parameter: 186520f4b53cSBarry Smith . A - the `MATHYPRE` object 1866dd9c0a25Sstefano_zampini 1867dd9c0a25Sstefano_zampini Output Parameter: 18682ef1f0ffSBarry Smith . parcsr - the pointer to the `hypre_ParCSRMatrix` 1869dd9c0a25Sstefano_zampini 1870dd9c0a25Sstefano_zampini Level: intermediate 1871dd9c0a25Sstefano_zampini 1872bfe80ac4SPierre Jolivet .seealso: [](ch_matrices), `Mat`, `MATHYPRE`, `PetscCopyMode` 187320f4b53cSBarry Smith @*/ 1874d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHYPREGetParCSR(Mat A, hypre_ParCSRMatrix **parcsr) 1875d71ae5a4SJacob Faibussowitsch { 1876dd9c0a25Sstefano_zampini PetscFunctionBegin; 1877dd9c0a25Sstefano_zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1878dd9c0a25Sstefano_zampini PetscValidType(A, 1); 1879cac4c232SBarry Smith PetscUseMethod(A, "MatHYPREGetParCSR_C", (Mat, hypre_ParCSRMatrix **), (A, parcsr)); 18803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1881dd9c0a25Sstefano_zampini } 1882dd9c0a25Sstefano_zampini 1883d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_HYPRE(Mat A, PetscBool *missing, PetscInt *dd) 1884d71ae5a4SJacob Faibussowitsch { 188568ec7858SStefano Zampini hypre_ParCSRMatrix *parcsr; 188668ec7858SStefano Zampini hypre_CSRMatrix *ha; 188768ec7858SStefano Zampini PetscInt rst; 188868ec7858SStefano Zampini 188968ec7858SStefano Zampini PetscFunctionBegin; 189008401ef6SPierre Jolivet PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented with non-square diagonal blocks"); 18919566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rst, NULL)); 18929566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 189368ec7858SStefano Zampini if (missing) *missing = PETSC_FALSE; 189468ec7858SStefano Zampini if (dd) *dd = -1; 189568ec7858SStefano Zampini ha = hypre_ParCSRMatrixDiag(parcsr); 189668ec7858SStefano Zampini if (ha) { 189768299464SStefano Zampini PetscInt size, i; 189868299464SStefano Zampini HYPRE_Int *ii, *jj; 189968ec7858SStefano Zampini 190068ec7858SStefano Zampini size = hypre_CSRMatrixNumRows(ha); 190168ec7858SStefano Zampini ii = hypre_CSRMatrixI(ha); 190268ec7858SStefano Zampini jj = hypre_CSRMatrixJ(ha); 190368ec7858SStefano Zampini for (i = 0; i < size; i++) { 190468ec7858SStefano Zampini PetscInt j; 190568ec7858SStefano Zampini PetscBool found = PETSC_FALSE; 190668ec7858SStefano Zampini 19079371c9d4SSatish Balay for (j = ii[i]; j < ii[i + 1] && !found; j++) found = (jj[j] == i) ? PETSC_TRUE : PETSC_FALSE; 190868ec7858SStefano Zampini 190968ec7858SStefano Zampini if (!found) { 19103ba16761SJacob Faibussowitsch PetscCall(PetscInfo(A, "Matrix is missing local diagonal entry %" PetscInt_FMT "\n", i)); 191168ec7858SStefano Zampini if (missing) *missing = PETSC_TRUE; 191268ec7858SStefano Zampini if (dd) *dd = i + rst; 19133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 191468ec7858SStefano Zampini } 191568ec7858SStefano Zampini } 191668ec7858SStefano Zampini if (!size) { 19173ba16761SJacob Faibussowitsch PetscCall(PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n")); 191868ec7858SStefano Zampini if (missing) *missing = PETSC_TRUE; 191968ec7858SStefano Zampini if (dd) *dd = rst; 192068ec7858SStefano Zampini } 192168ec7858SStefano Zampini } else { 19223ba16761SJacob Faibussowitsch PetscCall(PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n")); 192368ec7858SStefano Zampini if (missing) *missing = PETSC_TRUE; 192468ec7858SStefano Zampini if (dd) *dd = rst; 192568ec7858SStefano Zampini } 19263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 192768ec7858SStefano Zampini } 192868ec7858SStefano Zampini 1929d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatScale_HYPRE(Mat A, PetscScalar s) 1930d71ae5a4SJacob Faibussowitsch { 193168ec7858SStefano Zampini hypre_ParCSRMatrix *parcsr; 19326ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 193368ec7858SStefano Zampini hypre_CSRMatrix *ha; 19346ea7df73SStefano Zampini #endif 193539accc25SStefano Zampini HYPRE_Complex hs; 193668ec7858SStefano Zampini 193768ec7858SStefano Zampini PetscFunctionBegin; 19389566063dSJacob Faibussowitsch PetscCall(PetscHYPREScalarCast(s, &hs)); 19399566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 19406ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 19, 0) 1941792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixScale, parcsr, hs); 19426ea7df73SStefano Zampini #else /* diagonal part */ 194368ec7858SStefano Zampini ha = hypre_ParCSRMatrixDiag(parcsr); 194468ec7858SStefano Zampini if (ha) { 194568299464SStefano Zampini PetscInt size, i; 194668299464SStefano Zampini HYPRE_Int *ii; 194739accc25SStefano Zampini HYPRE_Complex *a; 194868ec7858SStefano Zampini 194968ec7858SStefano Zampini size = hypre_CSRMatrixNumRows(ha); 195068ec7858SStefano Zampini a = hypre_CSRMatrixData(ha); 195168ec7858SStefano Zampini ii = hypre_CSRMatrixI(ha); 195239accc25SStefano Zampini for (i = 0; i < ii[size]; i++) a[i] *= hs; 195368ec7858SStefano Zampini } 19544cf0e950SBarry Smith /* off-diagonal part */ 195568ec7858SStefano Zampini ha = hypre_ParCSRMatrixOffd(parcsr); 195668ec7858SStefano Zampini if (ha) { 195768299464SStefano Zampini PetscInt size, i; 195868299464SStefano Zampini HYPRE_Int *ii; 195939accc25SStefano Zampini HYPRE_Complex *a; 196068ec7858SStefano Zampini 196168ec7858SStefano Zampini size = hypre_CSRMatrixNumRows(ha); 196268ec7858SStefano Zampini a = hypre_CSRMatrixData(ha); 196368ec7858SStefano Zampini ii = hypre_CSRMatrixI(ha); 196439accc25SStefano Zampini for (i = 0; i < ii[size]; i++) a[i] *= hs; 196568ec7858SStefano Zampini } 19666ea7df73SStefano Zampini #endif 19673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 196868ec7858SStefano Zampini } 196968ec7858SStefano Zampini 1970d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_HYPRE(Mat A, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 1971d71ae5a4SJacob Faibussowitsch { 197268ec7858SStefano Zampini hypre_ParCSRMatrix *parcsr; 197368299464SStefano Zampini HYPRE_Int *lrows; 197468299464SStefano Zampini PetscInt rst, ren, i; 197568ec7858SStefano Zampini 197668ec7858SStefano Zampini PetscFunctionBegin; 197708401ef6SPierre Jolivet PetscCheck(!x && !b, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "To be implemented"); 19789566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 19799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRows, &lrows)); 19809566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rst, &ren)); 198168ec7858SStefano Zampini for (i = 0; i < numRows; i++) { 19827a46b595SBarry Smith PetscCheck(rows[i] >= rst && rows[i] < ren, PETSC_COMM_SELF, PETSC_ERR_SUP, "Non-local rows not yet supported"); 198368ec7858SStefano Zampini lrows[i] = rows[i] - rst; 198468ec7858SStefano Zampini } 1985792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixEliminateRowsCols, parcsr, numRows, lrows); 19869566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 19873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 198868ec7858SStefano Zampini } 198968ec7858SStefano Zampini 1990d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPRE_CSRMatrix(hypre_CSRMatrix *ha) 1991d71ae5a4SJacob Faibussowitsch { 1992c69f721fSFande Kong PetscFunctionBegin; 1993c69f721fSFande Kong if (ha) { 1994c69f721fSFande Kong HYPRE_Int *ii, size; 1995c69f721fSFande Kong HYPRE_Complex *a; 1996c69f721fSFande Kong 1997c69f721fSFande Kong size = hypre_CSRMatrixNumRows(ha); 1998c69f721fSFande Kong a = hypre_CSRMatrixData(ha); 1999c69f721fSFande Kong ii = hypre_CSRMatrixI(ha); 2000c69f721fSFande Kong 20019566063dSJacob Faibussowitsch if (a) PetscCall(PetscArrayzero(a, ii[size])); 2002c69f721fSFande Kong } 20033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2004c69f721fSFande Kong } 2005c69f721fSFande Kong 200666976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPRE(Mat A) 2007d71ae5a4SJacob Faibussowitsch { 20086ea7df73SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 20096ea7df73SStefano Zampini 20106ea7df73SStefano Zampini PetscFunctionBegin; 20116ea7df73SStefano Zampini if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(hA->ij)) { 2012792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetConstantValues, hA->ij, 0.0); 20136ea7df73SStefano Zampini } else { 2014c69f721fSFande Kong hypre_ParCSRMatrix *parcsr; 2015c69f721fSFande Kong 20169566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 20179566063dSJacob Faibussowitsch PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr))); 20189566063dSJacob Faibussowitsch PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr))); 20196ea7df73SStefano Zampini } 20203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2021c69f721fSFande Kong } 2022c69f721fSFande Kong 2023d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_HYPRE_CSRMatrix(hypre_CSRMatrix *hA, PetscInt N, const PetscInt rows[], HYPRE_Complex diag) 2024d71ae5a4SJacob Faibussowitsch { 202539accc25SStefano Zampini PetscInt ii; 202639accc25SStefano Zampini HYPRE_Int *i, *j; 202739accc25SStefano Zampini HYPRE_Complex *a; 2028c69f721fSFande Kong 2029c69f721fSFande Kong PetscFunctionBegin; 20303ba16761SJacob Faibussowitsch if (!hA) PetscFunctionReturn(PETSC_SUCCESS); 2031c69f721fSFande Kong 203239accc25SStefano Zampini i = hypre_CSRMatrixI(hA); 203339accc25SStefano Zampini j = hypre_CSRMatrixJ(hA); 2034c69f721fSFande Kong a = hypre_CSRMatrixData(hA); 2035a32e9c99SJunchao Zhang #if defined(PETSC_HAVE_HYPRE_DEVICE) 2036a32e9c99SJunchao Zhang if (HYPRE_MEMORY_DEVICE == hypre_CSRMatrixMemoryLocation(hA)) { 2037a32e9c99SJunchao Zhang #if defined(HYPRE_USING_CUDA) 2038a32e9c99SJunchao Zhang MatZeroRows_CUDA(N, rows, i, j, a, diag); 2039a32e9c99SJunchao Zhang #elif defined(HYPRE_USING_HIP) 2040a32e9c99SJunchao Zhang MatZeroRows_HIP(N, rows, i, j, a, diag); 2041a32e9c99SJunchao Zhang #elif defined(PETSC_HAVE_KOKKOS) 2042a32e9c99SJunchao Zhang MatZeroRows_Kokkos(N, rows, i, j, a, diag); 2043a32e9c99SJunchao Zhang #else 2044a32e9c99SJunchao Zhang SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for MatZeroRows on a hypre matrix in this memory location"); 2045a32e9c99SJunchao Zhang #endif 2046a32e9c99SJunchao Zhang } else 2047a32e9c99SJunchao Zhang #endif 2048a32e9c99SJunchao Zhang { 2049c69f721fSFande Kong for (ii = 0; ii < N; ii++) { 205039accc25SStefano Zampini HYPRE_Int jj, ibeg, iend, irow; 205139accc25SStefano Zampini 2052c69f721fSFande Kong irow = rows[ii]; 2053c69f721fSFande Kong ibeg = i[irow]; 2054c69f721fSFande Kong iend = i[irow + 1]; 2055c69f721fSFande Kong for (jj = ibeg; jj < iend; jj++) 2056c69f721fSFande Kong if (j[jj] == irow) a[jj] = diag; 2057c69f721fSFande Kong else a[jj] = 0.0; 2058c69f721fSFande Kong } 2059a32e9c99SJunchao Zhang } 20603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2061c69f721fSFande Kong } 2062c69f721fSFande Kong 2063d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_HYPRE(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 2064d71ae5a4SJacob Faibussowitsch { 2065c69f721fSFande Kong hypre_ParCSRMatrix *parcsr; 2066a32e9c99SJunchao Zhang PetscInt *lrows, len, *lrows2; 206739accc25SStefano Zampini HYPRE_Complex hdiag; 2068c69f721fSFande Kong 2069c69f721fSFande Kong PetscFunctionBegin; 207008401ef6SPierre Jolivet PetscCheck(!x && !b, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Does not support to modify the solution and the right hand size"); 20719566063dSJacob Faibussowitsch PetscCall(PetscHYPREScalarCast(diag, &hdiag)); 2072c69f721fSFande Kong /* retrieve the internal matrix */ 20739566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 2074c69f721fSFande Kong /* get locally owned rows */ 20759566063dSJacob Faibussowitsch PetscCall(MatZeroRowsMapLocal_Private(A, N, rows, &len, &lrows)); 2076a32e9c99SJunchao Zhang 2077a32e9c99SJunchao Zhang #if defined(PETSC_HAVE_HYPRE_DEVICE) 2078a32e9c99SJunchao Zhang if (HYPRE_MEMORY_DEVICE == hypre_CSRMatrixMemoryLocation(hypre_ParCSRMatrixDiag(parcsr))) { 2079a32e9c99SJunchao Zhang Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 2080a32e9c99SJunchao Zhang PetscInt m; 2081a32e9c99SJunchao Zhang PetscCall(MatGetLocalSize(A, &m, NULL)); 2082a32e9c99SJunchao Zhang if (!hA->rows_d) { 2083a32e9c99SJunchao Zhang hA->rows_d = hypre_TAlloc(PetscInt, m, HYPRE_MEMORY_DEVICE); 2084a32e9c99SJunchao Zhang if (m) PetscCheck(hA->rows_d, PETSC_COMM_SELF, PETSC_ERR_MEM, "HYPRE_TAlloc failed"); 2085a32e9c99SJunchao Zhang } 2086a32e9c99SJunchao Zhang PetscCheck(len <= m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Too many rows in rows[]"); 2087a32e9c99SJunchao Zhang PetscStackCallExternalVoid("hypre_Memcpy", hypre_Memcpy(hA->rows_d, lrows, sizeof(PetscInt) * len, HYPRE_MEMORY_DEVICE, HYPRE_MEMORY_HOST)); 2088a32e9c99SJunchao Zhang lrows2 = hA->rows_d; 2089a32e9c99SJunchao Zhang } else 2090a32e9c99SJunchao Zhang #endif 2091a32e9c99SJunchao Zhang { 2092a32e9c99SJunchao Zhang lrows2 = lrows; 2093a32e9c99SJunchao Zhang } 2094a32e9c99SJunchao Zhang 2095c69f721fSFande Kong /* zero diagonal part */ 2096a32e9c99SJunchao Zhang PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr), len, lrows2, hdiag)); 2097c69f721fSFande Kong /* zero off-diagonal part */ 2098a32e9c99SJunchao Zhang PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr), len, lrows2, 0.0)); 2099c69f721fSFande Kong 21009566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 21013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2102c69f721fSFande Kong } 2103c69f721fSFande Kong 2104d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_HYPRE(Mat mat, MatAssemblyType mode) 2105d71ae5a4SJacob Faibussowitsch { 2106c69f721fSFande Kong PetscFunctionBegin; 21073ba16761SJacob Faibussowitsch if (mat->nooffprocentries) PetscFunctionReturn(PETSC_SUCCESS); 2108c69f721fSFande Kong 21099566063dSJacob Faibussowitsch PetscCall(MatStashScatterBegin_Private(mat, &mat->stash, mat->rmap->range)); 21103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2111c69f721fSFande Kong } 2112c69f721fSFande Kong 2113d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) 2114d71ae5a4SJacob Faibussowitsch { 2115c69f721fSFande Kong hypre_ParCSRMatrix *parcsr; 21162cf14000SStefano Zampini HYPRE_Int hnz; 2117c69f721fSFande Kong 2118c69f721fSFande Kong PetscFunctionBegin; 2119c69f721fSFande Kong /* retrieve the internal matrix */ 21209566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 2121c69f721fSFande Kong /* call HYPRE API */ 2122792fecdfSBarry Smith PetscCallExternal(HYPRE_ParCSRMatrixGetRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v); 21232cf14000SStefano Zampini if (nz) *nz = (PetscInt)hnz; 21243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2125c69f721fSFande Kong } 2126c69f721fSFande Kong 2127d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) 2128d71ae5a4SJacob Faibussowitsch { 2129c69f721fSFande Kong hypre_ParCSRMatrix *parcsr; 21302cf14000SStefano Zampini HYPRE_Int hnz; 2131c69f721fSFande Kong 2132c69f721fSFande Kong PetscFunctionBegin; 2133c69f721fSFande Kong /* retrieve the internal matrix */ 21349566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 2135c69f721fSFande Kong /* call HYPRE API */ 21362cf14000SStefano Zampini hnz = nz ? (HYPRE_Int)(*nz) : 0; 2137792fecdfSBarry Smith PetscCallExternal(HYPRE_ParCSRMatrixRestoreRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v); 21383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2139c69f721fSFande Kong } 2140c69f721fSFande Kong 2141d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetValues_HYPRE(Mat A, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2142d71ae5a4SJacob Faibussowitsch { 214345b8d346SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 2144c69f721fSFande Kong PetscInt i; 21451d4906efSStefano Zampini 2146c69f721fSFande Kong PetscFunctionBegin; 21473ba16761SJacob Faibussowitsch if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2148c69f721fSFande Kong /* Ignore negative row indices 2149c69f721fSFande Kong * And negative column indices should be automatically ignored in hypre 2150c69f721fSFande Kong * */ 21512cf14000SStefano Zampini for (i = 0; i < m; i++) { 21522cf14000SStefano Zampini if (idxm[i] >= 0) { 21532cf14000SStefano Zampini HYPRE_Int hn = (HYPRE_Int)n; 2154792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetValues, hA->ij, 1, &hn, (HYPRE_BigInt *)&idxm[i], (HYPRE_BigInt *)idxn, (HYPRE_Complex *)(v + i * n)); 21552cf14000SStefano Zampini } 21562cf14000SStefano Zampini } 21573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2158c69f721fSFande Kong } 2159c69f721fSFande Kong 2160d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_HYPRE(Mat A, MatOption op, PetscBool flg) 2161d71ae5a4SJacob Faibussowitsch { 2162ddbeb582SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 2163ddbeb582SStefano Zampini 2164ddbeb582SStefano Zampini PetscFunctionBegin; 2165c6698e78SStefano Zampini switch (op) { 2166ddbeb582SStefano Zampini case MAT_NO_OFF_PROC_ENTRIES: 216748a46eb9SPierre Jolivet if (flg) PetscCallExternal(HYPRE_IJMatrixSetMaxOffProcElmts, hA->ij, 0); 2168ddbeb582SStefano Zampini break; 2169651b1cf9SStefano Zampini case MAT_IGNORE_OFF_PROC_ENTRIES: 2170651b1cf9SStefano Zampini hA->donotstash = flg; 2171d71ae5a4SJacob Faibussowitsch break; 2172d71ae5a4SJacob Faibussowitsch default: 2173d71ae5a4SJacob Faibussowitsch break; 2174ddbeb582SStefano Zampini } 21753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2176ddbeb582SStefano Zampini } 2177c69f721fSFande Kong 2178d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_HYPRE(Mat A, PetscViewer view) 2179d71ae5a4SJacob Faibussowitsch { 218045b8d346SStefano Zampini PetscViewerFormat format; 218145b8d346SStefano Zampini 218245b8d346SStefano Zampini PetscFunctionBegin; 21839566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(view, &format)); 21843ba16761SJacob Faibussowitsch if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(PETSC_SUCCESS); 218545b8d346SStefano Zampini if (format != PETSC_VIEWER_NATIVE) { 21866ea7df73SStefano Zampini Mat B; 21876ea7df73SStefano Zampini hypre_ParCSRMatrix *parcsr; 21886ea7df73SStefano Zampini PetscErrorCode (*mview)(Mat, PetscViewer) = NULL; 21896ea7df73SStefano Zampini 21909566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 21919566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(parcsr, MATAIJ, PETSC_USE_POINTER, &B)); 21929566063dSJacob Faibussowitsch PetscCall(MatGetOperation(B, MATOP_VIEW, (void (**)(void))&mview)); 219328b400f6SJacob Faibussowitsch PetscCheck(mview, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Missing view operation"); 21949566063dSJacob Faibussowitsch PetscCall((*mview)(B, view)); 21959566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 219645b8d346SStefano Zampini } else { 219745b8d346SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 219845b8d346SStefano Zampini PetscMPIInt size; 219945b8d346SStefano Zampini PetscBool isascii; 220045b8d346SStefano Zampini const char *filename; 220145b8d346SStefano Zampini 220245b8d346SStefano Zampini /* HYPRE uses only text files */ 22039566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERASCII, &isascii)); 220428b400f6SJacob Faibussowitsch PetscCheck(isascii, PetscObjectComm((PetscObject)view), PETSC_ERR_SUP, "PetscViewerType %s: native HYPRE format needs PETSCVIEWERASCII", ((PetscObject)view)->type_name); 22059566063dSJacob Faibussowitsch PetscCall(PetscViewerFileGetName(view, &filename)); 2206792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixPrint, hA->ij, filename); 22079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(hA->comm, &size)); 220845b8d346SStefano Zampini if (size > 1) { 22099566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(view, "Matrix files: %s.%05d ... %s.%05d\n", filename, 0, filename, size - 1)); 221045b8d346SStefano Zampini } else { 22119566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(view, "Matrix file: %s.%05d\n", filename, 0)); 221245b8d346SStefano Zampini } 221345b8d346SStefano Zampini } 22143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 221545b8d346SStefano Zampini } 221645b8d346SStefano Zampini 2217d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCopy_HYPRE(Mat A, Mat B, MatStructure str) 2218d71ae5a4SJacob Faibussowitsch { 2219465edc17SStefano Zampini hypre_ParCSRMatrix *acsr, *bcsr; 2220465edc17SStefano Zampini 2221465edc17SStefano Zampini PetscFunctionBegin; 2222465edc17SStefano Zampini if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) { 22239566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &acsr)); 22249566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(B, &bcsr)); 2225792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixCopy, acsr, bcsr, 1); 22269566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_SORTED_FULL, PETSC_TRUE)); /* "perfect" preallocation, so no need for hypre_AuxParCSRMatrixNeedAux */ 22279566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 22289566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 2229465edc17SStefano Zampini } else { 22309566063dSJacob Faibussowitsch PetscCall(MatCopy_Basic(A, B, str)); 2231465edc17SStefano Zampini } 22323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2233465edc17SStefano Zampini } 2234465edc17SStefano Zampini 2235d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_HYPRE(Mat A, Vec d) 2236d71ae5a4SJacob Faibussowitsch { 22376305df00SStefano Zampini hypre_ParCSRMatrix *parcsr; 22386305df00SStefano Zampini hypre_CSRMatrix *dmat; 223939accc25SStefano Zampini HYPRE_Complex *a; 22406305df00SStefano Zampini PetscBool cong; 22416305df00SStefano Zampini 22426305df00SStefano Zampini PetscFunctionBegin; 22439566063dSJacob Faibussowitsch PetscCall(MatHasCongruentLayouts(A, &cong)); 224428b400f6SJacob Faibussowitsch PetscCheck(cong, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only for square matrices with same local distributions of rows and columns"); 22459566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 22466305df00SStefano Zampini dmat = hypre_ParCSRMatrixDiag(parcsr); 22476305df00SStefano Zampini if (dmat) { 224806977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 224906977982Sstefanozampini HYPRE_MemoryLocation mem = hypre_CSRMatrixMemoryLocation(dmat); 225006977982Sstefanozampini #else 225106977982Sstefanozampini HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST; 225206977982Sstefanozampini #endif 225306977982Sstefanozampini 225406977982Sstefanozampini if (mem != HYPRE_MEMORY_HOST) PetscCall(VecGetArrayWriteAndMemType(d, (PetscScalar **)&a, NULL)); 225506977982Sstefanozampini else PetscCall(VecGetArrayWrite(d, (PetscScalar **)&a)); 225606977982Sstefanozampini hypre_CSRMatrixExtractDiagonal(dmat, a, 0); 225706977982Sstefanozampini if (mem != HYPRE_MEMORY_HOST) PetscCall(VecRestoreArrayWriteAndMemType(d, (PetscScalar **)&a)); 225806977982Sstefanozampini else PetscCall(VecRestoreArrayWrite(d, (PetscScalar **)&a)); 22596305df00SStefano Zampini } 22603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22616305df00SStefano Zampini } 22626305df00SStefano Zampini 2263363d496dSStefano Zampini #include <petscblaslapack.h> 2264363d496dSStefano Zampini 2265d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAXPY_HYPRE(Mat Y, PetscScalar a, Mat X, MatStructure str) 2266d71ae5a4SJacob Faibussowitsch { 2267363d496dSStefano Zampini PetscFunctionBegin; 22686ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 22696ea7df73SStefano Zampini { 22706ea7df73SStefano Zampini Mat B; 22716ea7df73SStefano Zampini hypre_ParCSRMatrix *x, *y, *z; 22726ea7df73SStefano Zampini 22739566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR(Y, &y)); 22749566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR(X, &x)); 2275792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixAdd, 1.0, y, 1.0, x, &z); 22769566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(z, MATHYPRE, PETSC_OWN_POINTER, &B)); 22779566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(Y, &B)); 22786ea7df73SStefano Zampini } 22796ea7df73SStefano Zampini #else 2280363d496dSStefano Zampini if (str == SAME_NONZERO_PATTERN) { 2281363d496dSStefano Zampini hypre_ParCSRMatrix *x, *y; 2282363d496dSStefano Zampini hypre_CSRMatrix *xloc, *yloc; 2283363d496dSStefano Zampini PetscInt xnnz, ynnz; 228439accc25SStefano Zampini HYPRE_Complex *xarr, *yarr; 2285363d496dSStefano Zampini PetscBLASInt one = 1, bnz; 2286363d496dSStefano Zampini 22879566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR(Y, &y)); 22889566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR(X, &x)); 2289363d496dSStefano Zampini 2290363d496dSStefano Zampini /* diagonal block */ 2291363d496dSStefano Zampini xloc = hypre_ParCSRMatrixDiag(x); 2292363d496dSStefano Zampini yloc = hypre_ParCSRMatrixDiag(y); 2293363d496dSStefano Zampini xnnz = 0; 2294363d496dSStefano Zampini ynnz = 0; 2295363d496dSStefano Zampini xarr = NULL; 2296363d496dSStefano Zampini yarr = NULL; 2297363d496dSStefano Zampini if (xloc) { 229839accc25SStefano Zampini xarr = hypre_CSRMatrixData(xloc); 2299363d496dSStefano Zampini xnnz = hypre_CSRMatrixNumNonzeros(xloc); 2300363d496dSStefano Zampini } 2301363d496dSStefano Zampini if (yloc) { 230239accc25SStefano Zampini yarr = hypre_CSRMatrixData(yloc); 2303363d496dSStefano Zampini ynnz = hypre_CSRMatrixNumNonzeros(yloc); 2304363d496dSStefano Zampini } 230508401ef6SPierre Jolivet PetscCheck(xnnz == ynnz, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Different number of nonzeros in diagonal block %" PetscInt_FMT " != %" PetscInt_FMT, xnnz, ynnz); 23069566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(xnnz, &bnz)); 2307792fecdfSBarry Smith PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one)); 2308363d496dSStefano Zampini 2309363d496dSStefano Zampini /* off-diagonal block */ 2310363d496dSStefano Zampini xloc = hypre_ParCSRMatrixOffd(x); 2311363d496dSStefano Zampini yloc = hypre_ParCSRMatrixOffd(y); 2312363d496dSStefano Zampini xnnz = 0; 2313363d496dSStefano Zampini ynnz = 0; 2314363d496dSStefano Zampini xarr = NULL; 2315363d496dSStefano Zampini yarr = NULL; 2316363d496dSStefano Zampini if (xloc) { 231739accc25SStefano Zampini xarr = hypre_CSRMatrixData(xloc); 2318363d496dSStefano Zampini xnnz = hypre_CSRMatrixNumNonzeros(xloc); 2319363d496dSStefano Zampini } 2320363d496dSStefano Zampini if (yloc) { 232139accc25SStefano Zampini yarr = hypre_CSRMatrixData(yloc); 2322363d496dSStefano Zampini ynnz = hypre_CSRMatrixNumNonzeros(yloc); 2323363d496dSStefano Zampini } 232408401ef6SPierre 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); 23259566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(xnnz, &bnz)); 2326792fecdfSBarry Smith PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one)); 2327363d496dSStefano Zampini } else if (str == SUBSET_NONZERO_PATTERN) { 23289566063dSJacob Faibussowitsch PetscCall(MatAXPY_Basic(Y, a, X, str)); 2329363d496dSStefano Zampini } else { 2330363d496dSStefano Zampini Mat B; 2331363d496dSStefano Zampini 23329566063dSJacob Faibussowitsch PetscCall(MatAXPY_Basic_Preallocate(Y, X, &B)); 23339566063dSJacob Faibussowitsch PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str)); 23349566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(Y, &B)); 2335363d496dSStefano Zampini } 23366ea7df73SStefano Zampini #endif 23373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2338363d496dSStefano Zampini } 2339363d496dSStefano Zampini 23402c4ab24aSJunchao Zhang static PetscErrorCode MatDuplicate_HYPRE(Mat A, MatDuplicateOption op, Mat *B) 23412c4ab24aSJunchao Zhang { 23422c4ab24aSJunchao Zhang hypre_ParCSRMatrix *parcsr = NULL; 23432c4ab24aSJunchao Zhang PetscCopyMode cpmode; 23442c4ab24aSJunchao Zhang Mat_HYPRE *hA; 23452c4ab24aSJunchao Zhang 23462c4ab24aSJunchao Zhang PetscFunctionBegin; 23472c4ab24aSJunchao Zhang PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 23482c4ab24aSJunchao Zhang if (op == MAT_DO_NOT_COPY_VALUES || op == MAT_SHARE_NONZERO_PATTERN) { 23492c4ab24aSJunchao Zhang parcsr = hypre_ParCSRMatrixClone(parcsr, 0); 23502c4ab24aSJunchao Zhang cpmode = PETSC_OWN_POINTER; 23512c4ab24aSJunchao Zhang } else { 23522c4ab24aSJunchao Zhang cpmode = PETSC_COPY_VALUES; 23532c4ab24aSJunchao Zhang } 23542c4ab24aSJunchao Zhang PetscCall(MatCreateFromParCSR(parcsr, MATHYPRE, cpmode, B)); 23552c4ab24aSJunchao Zhang hA = (Mat_HYPRE *)A->data; 23562c4ab24aSJunchao Zhang if (hA->cooMat) { 235706977982Sstefanozampini Mat_HYPRE *hB = (Mat_HYPRE *)((*B)->data); 2358b73e3080SStefano Zampini op = (op == MAT_DO_NOT_COPY_VALUES) ? op : MAT_COPY_VALUES; 2359b73e3080SStefano Zampini /* Cannot simply increase the reference count of hA->cooMat, since B needs to share cooMat's data array */ 236006977982Sstefanozampini PetscCall(MatDuplicate(hA->cooMat, op, &hB->cooMat)); 236106977982Sstefanozampini PetscCall(MatHYPRE_AttachCOOMat(*B)); 23622c4ab24aSJunchao Zhang } 23632c4ab24aSJunchao Zhang PetscFunctionReturn(PETSC_SUCCESS); 23642c4ab24aSJunchao Zhang } 23652c4ab24aSJunchao Zhang 2366d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetPreallocationCOO_HYPRE(Mat mat, PetscCount coo_n, PetscInt coo_i[], PetscInt coo_j[]) 2367d71ae5a4SJacob Faibussowitsch { 236806977982Sstefanozampini Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data; 23695fbaff96SJunchao Zhang 23705fbaff96SJunchao Zhang PetscFunctionBegin; 2371651b1cf9SStefano Zampini /* Build an agent matrix cooMat with AIJ format 23725fbaff96SJunchao 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. 23735fbaff96SJunchao Zhang */ 237406977982Sstefanozampini PetscCall(MatHYPRE_CreateCOOMat(mat)); 237506977982Sstefanozampini PetscCall(MatSetOption(hmat->cooMat, MAT_IGNORE_OFF_PROC_ENTRIES, hmat->donotstash)); 237606977982Sstefanozampini PetscCall(MatSetOption(hmat->cooMat, MAT_NO_OFF_PROC_ENTRIES, mat->nooffprocentries)); 2377651b1cf9SStefano Zampini 2378651b1cf9SStefano Zampini /* MatSetPreallocationCOO_SeqAIJ and MatSetPreallocationCOO_MPIAIJ uses this specific 2379651b1cf9SStefano Zampini name to automatically put the diagonal entries first */ 238006977982Sstefanozampini PetscCall(PetscObjectSetName((PetscObject)hmat->cooMat, "_internal_COO_mat_for_hypre")); 238106977982Sstefanozampini PetscCall(MatSetPreallocationCOO(hmat->cooMat, coo_n, coo_i, coo_j)); 238206977982Sstefanozampini hmat->cooMat->assembled = PETSC_TRUE; 23835fbaff96SJunchao Zhang 23845fbaff96SJunchao Zhang /* Copy the sparsity pattern from cooMat to hypre IJMatrix hmat->ij */ 23855fbaff96SJunchao Zhang PetscCall(MatSetOption(mat, MAT_SORTED_FULL, PETSC_TRUE)); 238606977982Sstefanozampini PetscCall(MatHYPRE_CreateFromMat(hmat->cooMat, hmat)); /* Create hmat->ij and preallocate it */ 238706977982Sstefanozampini PetscCall(MatHYPRE_IJMatrixCopyIJ(hmat->cooMat, hmat->ij)); /* Copy A's (i,j) to hmat->ij */ 23885fbaff96SJunchao Zhang 23895fbaff96SJunchao Zhang mat->preallocated = PETSC_TRUE; 23905fbaff96SJunchao Zhang PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 23915fbaff96SJunchao Zhang PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); /* Migrate mat to device if it is bound to. Hypre builds its own SpMV context here */ 23925fbaff96SJunchao Zhang 23932c4ab24aSJunchao Zhang /* Attach cooMat to mat */ 239406977982Sstefanozampini PetscCall(MatHYPRE_AttachCOOMat(mat)); 23953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23965fbaff96SJunchao Zhang } 23975fbaff96SJunchao Zhang 2398d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesCOO_HYPRE(Mat mat, const PetscScalar v[], InsertMode imode) 2399d71ae5a4SJacob Faibussowitsch { 24005fbaff96SJunchao Zhang Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data; 24015fbaff96SJunchao Zhang 24025fbaff96SJunchao Zhang PetscFunctionBegin; 2403b73e3080SStefano Zampini PetscCheck(hmat->cooMat, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet"); 24045fbaff96SJunchao Zhang PetscCall(MatSetValuesCOO(hmat->cooMat, v, imode)); 2405651b1cf9SStefano Zampini PetscCall(MatViewFromOptions(hmat->cooMat, (PetscObject)mat, "-cooMat_view")); 24063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24075fbaff96SJunchao Zhang } 24085fbaff96SJunchao Zhang 240903db1824SAlex Lindsay static PetscErrorCode MatGetCurrentMemType_HYPRE(Mat A, PetscMemType *m) 241003db1824SAlex Lindsay { 241103db1824SAlex Lindsay PetscBool petsconcpu; 241203db1824SAlex Lindsay 241303db1824SAlex Lindsay PetscFunctionBegin; 241403db1824SAlex Lindsay PetscCall(MatBoundToCPU(A, &petsconcpu)); 241503db1824SAlex Lindsay if (PetscDefined(HAVE_HYPRE_DEVICE)) { 241603db1824SAlex Lindsay PetscBool hypreoncpu; 241703db1824SAlex Lindsay HYPRE_MemoryLocation hyprememloc; 241803db1824SAlex Lindsay 241903db1824SAlex Lindsay PetscCallExternal(HYPRE_GetMemoryLocation, &hyprememloc); 242003db1824SAlex Lindsay PetscCheck(hyprememloc != HYPRE_MEMORY_UNDEFINED, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "hypre memory shold already be initialized"); 242103db1824SAlex Lindsay hypreoncpu = hyprememloc == HYPRE_MEMORY_HOST ? PETSC_TRUE : PETSC_FALSE; 242203db1824SAlex Lindsay PetscCheck(petsconcpu == hypreoncpu, PetscObjectComm((PetscObject)A), PETSC_ERR_USER_INPUT, "PETSc and hypre memory location do not agree. This may happen if using multiple hypre matrices with mismatchiing memory locations"); 242303db1824SAlex Lindsay } 242403db1824SAlex Lindsay *m = petsconcpu ? PETSC_MEMTYPE_HOST : PETSC_MEMTYPE_DEVICE; 242503db1824SAlex Lindsay PetscFunctionReturn(PETSC_SUCCESS); 242603db1824SAlex Lindsay } 242703db1824SAlex Lindsay 2428a055b5aaSBarry Smith /*MC 24292ef1f0ffSBarry Smith MATHYPRE - "hypre" - A matrix type to be used for sequential and parallel sparse matrices 2430a055b5aaSBarry Smith based on the hypre IJ interface. 2431a055b5aaSBarry Smith 2432a055b5aaSBarry Smith Level: intermediate 2433a055b5aaSBarry Smith 24341cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatHYPRESetPreallocation` 2435a055b5aaSBarry Smith M*/ 2436d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_HYPRE(Mat B) 2437d71ae5a4SJacob Faibussowitsch { 243863c07aadSStefano Zampini Mat_HYPRE *hB; 2439a9e6c71bSAlex Lindsay #if defined(PETSC_HAVE_HYPRE_DEVICE) 2440a9e6c71bSAlex Lindsay HYPRE_MemoryLocation memory_location; 2441a9e6c71bSAlex Lindsay #endif 244263c07aadSStefano Zampini 244363c07aadSStefano Zampini PetscFunctionBegin; 2444a9e6c71bSAlex Lindsay PetscHYPREInitialize(); 24454dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&hB)); 24466ea7df73SStefano Zampini 2447978814f1SStefano Zampini hB->inner_free = PETSC_TRUE; 2448651b1cf9SStefano Zampini hB->array_available = PETSC_TRUE; 2449978814f1SStefano Zampini 245063c07aadSStefano Zampini B->data = (void *)hB; 245163c07aadSStefano Zampini 24529566063dSJacob Faibussowitsch PetscCall(PetscMemzero(B->ops, sizeof(struct _MatOps))); 245363c07aadSStefano Zampini B->ops->mult = MatMult_HYPRE; 245463c07aadSStefano Zampini B->ops->multtranspose = MatMultTranspose_HYPRE; 2455414bd5c3SStefano Zampini B->ops->multadd = MatMultAdd_HYPRE; 2456414bd5c3SStefano Zampini B->ops->multtransposeadd = MatMultTransposeAdd_HYPRE; 245763c07aadSStefano Zampini B->ops->setup = MatSetUp_HYPRE; 245863c07aadSStefano Zampini B->ops->destroy = MatDestroy_HYPRE; 245963c07aadSStefano Zampini B->ops->assemblyend = MatAssemblyEnd_HYPRE; 2460c69f721fSFande Kong B->ops->assemblybegin = MatAssemblyBegin_HYPRE; 2461d975228cSstefano_zampini B->ops->setvalues = MatSetValues_HYPRE; 246268ec7858SStefano Zampini B->ops->missingdiagonal = MatMissingDiagonal_HYPRE; 246368ec7858SStefano Zampini B->ops->scale = MatScale_HYPRE; 246468ec7858SStefano Zampini B->ops->zerorowscolumns = MatZeroRowsColumns_HYPRE; 2465c69f721fSFande Kong B->ops->zeroentries = MatZeroEntries_HYPRE; 2466c69f721fSFande Kong B->ops->zerorows = MatZeroRows_HYPRE; 2467c69f721fSFande Kong B->ops->getrow = MatGetRow_HYPRE; 2468c69f721fSFande Kong B->ops->restorerow = MatRestoreRow_HYPRE; 2469c69f721fSFande Kong B->ops->getvalues = MatGetValues_HYPRE; 2470ddbeb582SStefano Zampini B->ops->setoption = MatSetOption_HYPRE; 247145b8d346SStefano Zampini B->ops->duplicate = MatDuplicate_HYPRE; 2472465edc17SStefano Zampini B->ops->copy = MatCopy_HYPRE; 247345b8d346SStefano Zampini B->ops->view = MatView_HYPRE; 24746305df00SStefano Zampini B->ops->getdiagonal = MatGetDiagonal_HYPRE; 2475363d496dSStefano Zampini B->ops->axpy = MatAXPY_HYPRE; 24764222ddf1SHong Zhang B->ops->productsetfromoptions = MatProductSetFromOptions_HYPRE; 247703db1824SAlex Lindsay B->ops->getcurrentmemtype = MatGetCurrentMemType_HYPRE; 24786ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 24796ea7df73SStefano Zampini B->ops->bindtocpu = MatBindToCPU_HYPRE; 2480a9e6c71bSAlex Lindsay /* Get hypre's default memory location. Users can control this using the corresponding HYPRE_SetMemoryLocation API */ 2481a9e6c71bSAlex Lindsay PetscCallExternal(HYPRE_GetMemoryLocation, &memory_location); 2482a9e6c71bSAlex Lindsay B->boundtocpu = (memory_location == HYPRE_MEMORY_HOST) ? PETSC_TRUE : PETSC_FALSE; 24836ea7df73SStefano Zampini #endif 248445b8d346SStefano Zampini 248545b8d346SStefano Zampini /* build cache for off array entries formed */ 24869566063dSJacob Faibussowitsch PetscCall(MatStashCreate_Private(PetscObjectComm((PetscObject)B), 1, &B->stash)); 248763c07aadSStefano Zampini 24889566063dSJacob Faibussowitsch PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)B), &hB->comm)); 24899566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRE)); 24909566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_aij_C", MatConvert_HYPRE_AIJ)); 24919566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_is_C", MatConvert_HYPRE_IS)); 24929566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_hypre_C", MatProductSetFromOptions_HYPRE)); 24939566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaij_hypre_C", MatProductSetFromOptions_HYPRE)); 24949566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPRESetPreallocation_C", MatHYPRESetPreallocation_HYPRE)); 24959566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPREGetParCSR_C", MatHYPREGetParCSR_HYPRE)); 24965fbaff96SJunchao Zhang PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_HYPRE)); 24975fbaff96SJunchao Zhang PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetValuesCOO_C", MatSetValuesCOO_HYPRE)); 24986ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 24996ea7df73SStefano Zampini #if defined(HYPRE_USING_HIP) 250006977982Sstefanozampini PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijhipsparse_hypre_C", MatProductSetFromOptions_HYPRE)); 250106977982Sstefanozampini PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaijhipsparse_hypre_C", MatProductSetFromOptions_HYPRE)); 25029566063dSJacob Faibussowitsch PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP)); 25039566063dSJacob Faibussowitsch PetscCall(MatSetVecType(B, VECHIP)); 25046ea7df73SStefano Zampini #endif 25056ea7df73SStefano Zampini #if defined(HYPRE_USING_CUDA) 250606977982Sstefanozampini PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijcusparse_hypre_C", MatProductSetFromOptions_HYPRE)); 250706977982Sstefanozampini PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaijcusparse_hypre_C", MatProductSetFromOptions_HYPRE)); 25089566063dSJacob Faibussowitsch PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA)); 25099566063dSJacob Faibussowitsch PetscCall(MatSetVecType(B, VECCUDA)); 25106ea7df73SStefano Zampini #endif 25116ea7df73SStefano Zampini #endif 25123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 251363c07aadSStefano Zampini } 2514