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; 423*e64794e4SJunchao Zhang #elif defined(HYPRE_USING_SYCL) && defined(PETSC_HAVE_KOKKOS_KERNELS) 424*e64794e4SJunchao Zhang matType = MATAIJKOKKOS; 42506977982Sstefanozampini #else 426*e64794e4SJunchao Zhang SETERRQ(comm, PETSC_ERR_SUP, "No HYPRE device available. Suggest re-installing with Kokkos Kernels"); 42706977982Sstefanozampini #endif 428b73e3080SStefano Zampini } 42906977982Sstefanozampini #endif 43006977982Sstefanozampini 43106977982Sstefanozampini /* Do COO preallocation through cooMat */ 43206977982Sstefanozampini PetscCall(MatHYPRE_DestroyCOOMat(mat)); 43306977982Sstefanozampini PetscCall(MatCreate(comm, &hmat->cooMat)); 43406977982Sstefanozampini PetscCall(MatSetType(hmat->cooMat, matType)); 43506977982Sstefanozampini PetscCall(MatSetLayouts(hmat->cooMat, rmap, cmap)); 43606977982Sstefanozampini 43706977982Sstefanozampini /* allocate local matrices if needed */ 43806977982Sstefanozampini PetscCall(MatMPIAIJSetPreallocation(hmat->cooMat, 0, NULL, 0, NULL)); 43906977982Sstefanozampini PetscFunctionReturn(PETSC_SUCCESS); 44006977982Sstefanozampini } 44106977982Sstefanozampini 44206977982Sstefanozampini /* Attach cooMat data array to hypre matrix. 44306977982Sstefanozampini When AIJCUPMSPARSE will support raw device pointers and not THRUSTARRAY 44406977982Sstefanozampini we should swap the arrays: i.e., attach hypre matrix array to cooMat 44506977982Sstefanozampini This is because hypre should be in charge of handling the memory, 44606977982Sstefanozampini cooMat is only a way to reuse PETSc COO code. 44706977982Sstefanozampini attaching the memory will then be done at MatSetValuesCOO time and it will dynamically 44806977982Sstefanozampini support hypre matrix migrating to host. 44906977982Sstefanozampini */ 45006977982Sstefanozampini static PetscErrorCode MatHYPRE_AttachCOOMat(Mat mat) 45106977982Sstefanozampini { 45206977982Sstefanozampini Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data; 45306977982Sstefanozampini hypre_CSRMatrix *diag, *offd; 45406977982Sstefanozampini hypre_ParCSRMatrix *parCSR; 45506977982Sstefanozampini HYPRE_MemoryLocation hmem = HYPRE_MEMORY_HOST; 45606977982Sstefanozampini PetscMemType pmem; 45706977982Sstefanozampini Mat A, B; 45806977982Sstefanozampini PetscScalar *a; 45906977982Sstefanozampini PetscMPIInt size; 46006977982Sstefanozampini MPI_Comm comm; 46106977982Sstefanozampini 46206977982Sstefanozampini PetscFunctionBegin; 46306977982Sstefanozampini PetscCheck(hmat->cooMat, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet"); 46406977982Sstefanozampini if (hmat->cooMatAttached) PetscFunctionReturn(PETSC_SUCCESS); 46506977982Sstefanozampini PetscCheck(hmat->cooMat->preallocated, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix is not preallocated"); 46606977982Sstefanozampini PetscCall(PetscObjectSetName((PetscObject)hmat->cooMat, "_internal_COO_mat_for_hypre")); 46706977982Sstefanozampini PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 46806977982Sstefanozampini PetscCallMPI(MPI_Comm_size(comm, &size)); 46906977982Sstefanozampini 47006977982Sstefanozampini /* Alias cooMat's data array to IJMatrix's */ 47106977982Sstefanozampini PetscCallExternal(HYPRE_IJMatrixGetObject, hmat->ij, (void **)&parCSR); 47206977982Sstefanozampini diag = hypre_ParCSRMatrixDiag(parCSR); 47306977982Sstefanozampini offd = hypre_ParCSRMatrixOffd(parCSR); 47406977982Sstefanozampini 47506977982Sstefanozampini A = (size == 1) ? hmat->cooMat : ((Mat_MPIAIJ *)hmat->cooMat->data)->A; 47606977982Sstefanozampini B = (size == 1) ? NULL : ((Mat_MPIAIJ *)hmat->cooMat->data)->B; 47706977982Sstefanozampini 47806977982Sstefanozampini PetscCall(PetscObjectSetName((PetscObject)A, "_internal_COO_mat_for_hypre")); 47906977982Sstefanozampini hmem = hypre_CSRMatrixMemoryLocation(diag); 48006977982Sstefanozampini PetscCall(MatSeqAIJGetCSRAndMemType(A, NULL, NULL, &a, &pmem)); 48106977982Sstefanozampini PetscAssert((PetscMemTypeHost(pmem) && hmem == HYPRE_MEMORY_HOST) || (PetscMemTypeDevice(pmem) && hmem == HYPRE_MEMORY_DEVICE), comm, PETSC_ERR_PLIB, "PETSc and hypre's memory types mismatch"); 48206977982Sstefanozampini PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(diag), hmem)); 48306977982Sstefanozampini hypre_CSRMatrixData(diag) = (HYPRE_Complex *)a; 48406977982Sstefanozampini hypre_CSRMatrixOwnsData(diag) = 0; /* Take ownership of (j,a) away from hypre. As a result, we need to free them on our own */ 48506977982Sstefanozampini 48606977982Sstefanozampini if (B) { 48706977982Sstefanozampini hmem = hypre_CSRMatrixMemoryLocation(offd); 48806977982Sstefanozampini PetscCall(MatSeqAIJGetCSRAndMemType(B, NULL, NULL, &a, &pmem)); 48906977982Sstefanozampini PetscAssert((PetscMemTypeHost(pmem) && hmem == HYPRE_MEMORY_HOST) || (PetscMemTypeDevice(pmem) && hmem == HYPRE_MEMORY_DEVICE), comm, PETSC_ERR_PLIB, "PETSc and hypre's memory types mismatch"); 49006977982Sstefanozampini PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(offd), hmem)); 49106977982Sstefanozampini hypre_CSRMatrixData(offd) = (HYPRE_Complex *)a; 49206977982Sstefanozampini hypre_CSRMatrixOwnsData(offd) = 0; 49306977982Sstefanozampini } 49406977982Sstefanozampini hmat->cooMatAttached = PETSC_TRUE; 49506977982Sstefanozampini PetscFunctionReturn(PETSC_SUCCESS); 49606977982Sstefanozampini } 49706977982Sstefanozampini 4981c265611SJunchao Zhang // Build COO's coordinate list i[], j[] based on CSR's i[], j[] arrays and the number of local rows 'n' 49906977982Sstefanozampini static PetscErrorCode CSRtoCOO_Private(PetscInt n, const PetscInt ii[], const PetscInt jj[], PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j) 50006977982Sstefanozampini { 50106977982Sstefanozampini PetscInt *cooi, *cooj; 50206977982Sstefanozampini 50306977982Sstefanozampini PetscFunctionBegin; 50406977982Sstefanozampini *ncoo = ii[n]; 50506977982Sstefanozampini PetscCall(PetscMalloc2(*ncoo, &cooi, *ncoo, &cooj)); 50606977982Sstefanozampini for (PetscInt i = 0; i < n; i++) { 50706977982Sstefanozampini for (PetscInt j = ii[i]; j < ii[i + 1]; j++) cooi[j] = i; 50806977982Sstefanozampini } 50906977982Sstefanozampini PetscCall(PetscArraycpy(cooj, jj, *ncoo)); 51006977982Sstefanozampini *coo_i = cooi; 51106977982Sstefanozampini *coo_j = cooj; 51206977982Sstefanozampini PetscFunctionReturn(PETSC_SUCCESS); 51306977982Sstefanozampini } 51406977982Sstefanozampini 5151c265611SJunchao Zhang // Similar to CSRtoCOO_Private, but the CSR's i[], j[] are of type HYPRE_Int 51606977982Sstefanozampini static PetscErrorCode CSRtoCOO_HYPRE_Int_Private(PetscInt n, const HYPRE_Int ii[], const HYPRE_Int jj[], PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j) 51706977982Sstefanozampini { 51806977982Sstefanozampini PetscInt *cooi, *cooj; 51906977982Sstefanozampini 52006977982Sstefanozampini PetscFunctionBegin; 52106977982Sstefanozampini *ncoo = ii[n]; 52206977982Sstefanozampini PetscCall(PetscMalloc2(*ncoo, &cooi, *ncoo, &cooj)); 52306977982Sstefanozampini for (PetscInt i = 0; i < n; i++) { 52406977982Sstefanozampini for (HYPRE_Int j = ii[i]; j < ii[i + 1]; j++) cooi[j] = i; 52506977982Sstefanozampini } 52606977982Sstefanozampini for (PetscCount i = 0; i < *ncoo; i++) cooj[i] = jj[i]; 52706977982Sstefanozampini *coo_i = cooi; 52806977982Sstefanozampini *coo_j = cooj; 52906977982Sstefanozampini PetscFunctionReturn(PETSC_SUCCESS); 53006977982Sstefanozampini } 53106977982Sstefanozampini 5321c265611SJunchao 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 53306977982Sstefanozampini static PetscErrorCode MatSeqAIJGetCOO_Private(Mat A, PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j) 53406977982Sstefanozampini { 53506977982Sstefanozampini PetscInt n; 53606977982Sstefanozampini const PetscInt *ii, *jj; 53706977982Sstefanozampini PetscBool done; 53806977982Sstefanozampini 53906977982Sstefanozampini PetscFunctionBegin; 54006977982Sstefanozampini PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &done)); 54106977982Sstefanozampini PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Failure for MatGetRowIJ"); 54206977982Sstefanozampini PetscCall(CSRtoCOO_Private(n, ii, jj, ncoo, coo_i, coo_j)); 54306977982Sstefanozampini PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &done)); 54406977982Sstefanozampini PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Failure for MatRestoreRowIJ"); 54506977982Sstefanozampini PetscFunctionReturn(PETSC_SUCCESS); 54606977982Sstefanozampini } 54706977982Sstefanozampini 5481c265611SJunchao Zhang // Build a COO data structure for the hypreCSRMatrix, as if the nonzeros are laid out in the same order as in the hypreCSRMatrix 54906977982Sstefanozampini static PetscErrorCode hypreCSRMatrixGetCOO_Private(hypre_CSRMatrix *A, PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j) 55006977982Sstefanozampini { 55106977982Sstefanozampini PetscInt n = hypre_CSRMatrixNumRows(A); 55206977982Sstefanozampini HYPRE_Int *ii, *jj; 55306977982Sstefanozampini HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST; 55406977982Sstefanozampini 55506977982Sstefanozampini PetscFunctionBegin; 55606977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 55706977982Sstefanozampini mem = hypre_CSRMatrixMemoryLocation(A); 55806977982Sstefanozampini if (mem != HYPRE_MEMORY_HOST) { 55906977982Sstefanozampini PetscCount nnz = hypre_CSRMatrixNumNonzeros(A); 56006977982Sstefanozampini PetscCall(PetscMalloc2(n + 1, &ii, nnz, &jj)); 56106977982Sstefanozampini hypre_TMemcpy(ii, hypre_CSRMatrixI(A), HYPRE_Int, n + 1, HYPRE_MEMORY_HOST, mem); 56206977982Sstefanozampini hypre_TMemcpy(jj, hypre_CSRMatrixJ(A), HYPRE_Int, nnz, HYPRE_MEMORY_HOST, mem); 56306977982Sstefanozampini } else { 56406977982Sstefanozampini #else 56506977982Sstefanozampini { 56606977982Sstefanozampini #endif 56706977982Sstefanozampini ii = hypre_CSRMatrixI(A); 56806977982Sstefanozampini jj = hypre_CSRMatrixJ(A); 56906977982Sstefanozampini } 57006977982Sstefanozampini PetscCall(CSRtoCOO_HYPRE_Int_Private(n, ii, jj, ncoo, coo_i, coo_j)); 57106977982Sstefanozampini if (mem != HYPRE_MEMORY_HOST) PetscCall(PetscFree2(ii, jj)); 57206977982Sstefanozampini PetscFunctionReturn(PETSC_SUCCESS); 57306977982Sstefanozampini } 57406977982Sstefanozampini 57506977982Sstefanozampini static PetscErrorCode MatSetValuesCOOFromCSRMatrix_Private(Mat A, hypre_CSRMatrix *H) 57606977982Sstefanozampini { 57706977982Sstefanozampini PetscBool iscpu = PETSC_TRUE; 57806977982Sstefanozampini PetscScalar *a; 57906977982Sstefanozampini HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST; 58006977982Sstefanozampini 58106977982Sstefanozampini PetscFunctionBegin; 58206977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 58306977982Sstefanozampini mem = hypre_CSRMatrixMemoryLocation(H); 58406977982Sstefanozampini PetscCall(PetscObjectTypeCompare((PetscObject)A, MATSEQAIJ, &iscpu)); 58506977982Sstefanozampini #endif 58606977982Sstefanozampini if (iscpu && mem != HYPRE_MEMORY_HOST) { 58706977982Sstefanozampini PetscCount nnz = hypre_CSRMatrixNumNonzeros(H); 58806977982Sstefanozampini PetscCall(PetscMalloc1(nnz, &a)); 58906977982Sstefanozampini hypre_TMemcpy(a, hypre_CSRMatrixData(H), PetscScalar, nnz, HYPRE_MEMORY_HOST, mem); 59006977982Sstefanozampini } else { 59106977982Sstefanozampini a = (PetscScalar *)hypre_CSRMatrixData(H); 59206977982Sstefanozampini } 59306977982Sstefanozampini PetscCall(MatSetValuesCOO(A, a, INSERT_VALUES)); 59406977982Sstefanozampini if (iscpu && mem != HYPRE_MEMORY_HOST) PetscCall(PetscFree(a)); 595b73e3080SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 596b73e3080SStefano Zampini } 597b73e3080SStefano Zampini 598b73e3080SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType type, MatReuse reuse, Mat *B) 599b73e3080SStefano Zampini { 600b73e3080SStefano Zampini MPI_Comm comm = PetscObjectComm((PetscObject)A); 60106977982Sstefanozampini Mat M = NULL, dH = NULL, oH = NULL, dA = NULL, oA = NULL; 602d7185485SAlex Lindsay PetscBool ismpiaij, issbaij, isbaij, boundtocpu = PETSC_TRUE; 603b73e3080SStefano Zampini Mat_HYPRE *hA; 604d7185485SAlex Lindsay PetscMemType memtype = PETSC_MEMTYPE_HOST; 605b73e3080SStefano Zampini 606b73e3080SStefano Zampini PetscFunctionBegin; 607d7185485SAlex Lindsay if (PetscDefined(HAVE_HYPRE_DEVICE)) { 608d7185485SAlex Lindsay PetscCall(MatGetCurrentMemType(A, &memtype)); 609d7185485SAlex Lindsay PetscHYPREInitialize(); 610d7185485SAlex Lindsay boundtocpu = PetscMemTypeHost(memtype) ? PETSC_TRUE : PETSC_FALSE; 611d7185485SAlex Lindsay PetscCallExternal(HYPRE_SetMemoryLocation, boundtocpu ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE); 612d7185485SAlex Lindsay } 613d7185485SAlex Lindsay 614b73e3080SStefano Zampini PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &issbaij, MATSEQSBAIJ, MATMPIBAIJ, "")); 615b73e3080SStefano Zampini PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &isbaij, MATSEQBAIJ, MATMPIBAIJ, "")); 616b73e3080SStefano Zampini if (isbaij || issbaij) { /* handle BAIJ and SBAIJ */ 617b73e3080SStefano Zampini PetscBool ismpi; 618b73e3080SStefano Zampini MatType newtype; 619b73e3080SStefano Zampini 620b73e3080SStefano Zampini PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &ismpi, MATMPISBAIJ, MATMPIBAIJ, "")); 621b73e3080SStefano Zampini newtype = ismpi ? MATMPIAIJ : MATSEQAIJ; 62263c07aadSStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 623b73e3080SStefano Zampini PetscCall(MatConvert(*B, newtype, MAT_INPLACE_MATRIX, B)); 624b73e3080SStefano Zampini PetscCall(MatConvert(A, newtype, MAT_REUSE_MATRIX, B)); 625b73e3080SStefano Zampini PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B)); 626b73e3080SStefano Zampini } else if (reuse == MAT_INITIAL_MATRIX) { 627b73e3080SStefano Zampini PetscCall(MatConvert(A, newtype, MAT_INITIAL_MATRIX, B)); 628b73e3080SStefano Zampini PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B)); 62963c07aadSStefano Zampini } else { 630b73e3080SStefano Zampini PetscCall(MatConvert(A, newtype, MAT_INPLACE_MATRIX, &A)); 631b73e3080SStefano Zampini PetscCall(MatConvert(A, MATHYPRE, MAT_INPLACE_MATRIX, &A)); 632b73e3080SStefano Zampini } 633d7185485SAlex Lindsay #if defined(PETSC_HAVE_DEVICE) 634d7185485SAlex Lindsay (*B)->boundtocpu = boundtocpu; 635d7185485SAlex Lindsay #endif 636b73e3080SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 637b73e3080SStefano Zampini } 63806977982Sstefanozampini 63906977982Sstefanozampini dA = A; 640b73e3080SStefano Zampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 641b73e3080SStefano Zampini if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(A, &dA, &oA, NULL)); 64206977982Sstefanozampini 643b73e3080SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 64406977982Sstefanozampini PetscCount coo_n; 64506977982Sstefanozampini PetscInt *coo_i, *coo_j; 64606977982Sstefanozampini 6479566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &M)); 6489566063dSJacob Faibussowitsch PetscCall(MatSetType(M, MATHYPRE)); 6499566063dSJacob Faibussowitsch PetscCall(MatSetSizes(M, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N)); 650b73e3080SStefano Zampini PetscCall(MatSetOption(M, MAT_SORTED_FULL, PETSC_TRUE)); 651b73e3080SStefano Zampini PetscCall(MatSetOption(M, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE)); 652b73e3080SStefano Zampini 653b73e3080SStefano Zampini hA = (Mat_HYPRE *)M->data; 65406977982Sstefanozampini PetscCall(MatHYPRE_CreateFromMat(A, hA)); 65506977982Sstefanozampini PetscCall(MatHYPRE_IJMatrixCopyIJ(A, hA->ij)); 65606977982Sstefanozampini 65706977982Sstefanozampini PetscCall(MatHYPRE_CreateCOOMat(M)); 65806977982Sstefanozampini 65906977982Sstefanozampini dH = hA->cooMat; 66006977982Sstefanozampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)hA->cooMat, MATMPIAIJ, &ismpiaij)); 66106977982Sstefanozampini if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(hA->cooMat, &dH, &oH, NULL)); 66206977982Sstefanozampini 66306977982Sstefanozampini PetscCall(PetscObjectSetName((PetscObject)dH, "_internal_COO_mat_for_hypre")); 66406977982Sstefanozampini PetscCall(MatSeqAIJGetCOO_Private(dA, &coo_n, &coo_i, &coo_j)); 66506977982Sstefanozampini PetscCall(MatSetPreallocationCOO(dH, coo_n, coo_i, coo_j)); 66606977982Sstefanozampini PetscCall(PetscFree2(coo_i, coo_j)); 66706977982Sstefanozampini if (oH) { 66806977982Sstefanozampini PetscCall(PetscLayoutDestroy(&oH->cmap)); 66906977982Sstefanozampini PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)oH), oA->cmap->n, oA->cmap->n, 1, &oH->cmap)); 67006977982Sstefanozampini PetscCall(MatSeqAIJGetCOO_Private(oA, &coo_n, &coo_i, &coo_j)); 67106977982Sstefanozampini PetscCall(MatSetPreallocationCOO(oH, coo_n, coo_i, coo_j)); 67206977982Sstefanozampini PetscCall(PetscFree2(coo_i, coo_j)); 67306977982Sstefanozampini } 67406977982Sstefanozampini hA->cooMat->assembled = PETSC_TRUE; 67506977982Sstefanozampini 676b73e3080SStefano Zampini M->preallocated = PETSC_TRUE; 67706977982Sstefanozampini PetscCall(MatAssemblyBegin(M, MAT_FINAL_ASSEMBLY)); 67806977982Sstefanozampini PetscCall(MatAssemblyEnd(M, MAT_FINAL_ASSEMBLY)); 67906977982Sstefanozampini 68006977982Sstefanozampini PetscCall(MatHYPRE_AttachCOOMat(M)); 68184d4e069SStefano Zampini if (reuse == MAT_INITIAL_MATRIX) *B = M; 682b73e3080SStefano Zampini } else M = *B; 683b73e3080SStefano Zampini 684b73e3080SStefano Zampini hA = (Mat_HYPRE *)M->data; 68506977982Sstefanozampini PetscCheck(hA->cooMat, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet"); 68606977982Sstefanozampini 68706977982Sstefanozampini dH = hA->cooMat; 68806977982Sstefanozampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)hA->cooMat, MATMPIAIJ, &ismpiaij)); 68906977982Sstefanozampini if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(hA->cooMat, &dH, &oH, NULL)); 69006977982Sstefanozampini 69106977982Sstefanozampini PetscScalar *a; 69206977982Sstefanozampini PetscCall(MatSeqAIJGetCSRAndMemType(dA, NULL, NULL, &a, NULL)); 69306977982Sstefanozampini PetscCall(MatSetValuesCOO(dH, a, INSERT_VALUES)); 69406977982Sstefanozampini if (oH) { 69506977982Sstefanozampini PetscCall(MatSeqAIJGetCSRAndMemType(oA, NULL, NULL, &a, NULL)); 69606977982Sstefanozampini PetscCall(MatSetValuesCOO(oH, a, INSERT_VALUES)); 69706977982Sstefanozampini } 698b73e3080SStefano Zampini 69948a46eb9SPierre Jolivet if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &M)); 700d7185485SAlex Lindsay #if defined(PETSC_HAVE_DEVICE) 701d7185485SAlex Lindsay (*B)->boundtocpu = boundtocpu; 702d7185485SAlex Lindsay #endif 7033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 70463c07aadSStefano Zampini } 70563c07aadSStefano Zampini 706d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_HYPRE_AIJ(Mat A, MatType mtype, MatReuse reuse, Mat *B) 707d71ae5a4SJacob Faibussowitsch { 70806977982Sstefanozampini Mat M, dA = NULL, oA = NULL; 70963c07aadSStefano Zampini hypre_ParCSRMatrix *parcsr; 71006977982Sstefanozampini hypre_CSRMatrix *dH, *oH; 71163c07aadSStefano Zampini MPI_Comm comm; 71206977982Sstefanozampini PetscBool ismpiaij, isseqaij; 71363c07aadSStefano Zampini 71463c07aadSStefano Zampini PetscFunctionBegin; 71563c07aadSStefano Zampini comm = PetscObjectComm((PetscObject)A); 71663c07aadSStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 7179566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATMPIAIJ, &ismpiaij)); 7189566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATSEQAIJ, &isseqaij)); 71906977982Sstefanozampini PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Only MATMPIAIJ or MATSEQAIJ base types are supported"); 72063c07aadSStefano Zampini } 72106977982Sstefanozampini PetscCall(MatHYPREGetParCSR(A, &parcsr)); 7226ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 72306977982Sstefanozampini if (HYPRE_MEMORY_DEVICE == hypre_ParCSRMatrixMemoryLocation(parcsr)) { 72406977982Sstefanozampini PetscBool isaij; 72506977982Sstefanozampini 72606977982Sstefanozampini PetscCall(PetscStrcmp(mtype, MATAIJ, &isaij)); 72706977982Sstefanozampini if (isaij) { 72806977982Sstefanozampini PetscMPIInt size; 72906977982Sstefanozampini 7309566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 73106977982Sstefanozampini #if defined(HYPRE_USING_HIP) 73206977982Sstefanozampini mtype = size > 1 ? MATMPIAIJHIPSPARSE : MATSEQAIJHIPSPARSE; 73306977982Sstefanozampini #elif defined(HYPRE_USING_CUDA) 73406977982Sstefanozampini mtype = size > 1 ? MATMPIAIJCUSPARSE : MATSEQAIJCUSPARSE; 73506977982Sstefanozampini #else 73606977982Sstefanozampini mtype = size > 1 ? MATMPIAIJ : MATSEQAIJ; 73706977982Sstefanozampini #endif 73863c07aadSStefano Zampini } 73963c07aadSStefano Zampini } 74006977982Sstefanozampini #endif 74106977982Sstefanozampini dH = hypre_ParCSRMatrixDiag(parcsr); 74206977982Sstefanozampini oH = hypre_ParCSRMatrixOffd(parcsr); 7439371c9d4SSatish Balay if (reuse != MAT_REUSE_MATRIX) { 74406977982Sstefanozampini PetscCount coo_n; 74506977982Sstefanozampini PetscInt *coo_i, *coo_j; 74663c07aadSStefano Zampini 74706977982Sstefanozampini PetscCall(MatCreate(comm, &M)); 74806977982Sstefanozampini PetscCall(MatSetType(M, mtype)); 74906977982Sstefanozampini PetscCall(MatSetSizes(M, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N)); 75006977982Sstefanozampini PetscCall(MatMPIAIJSetPreallocation(M, 0, NULL, 0, NULL)); 75163c07aadSStefano Zampini 75206977982Sstefanozampini dA = M; 75306977982Sstefanozampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)M, MATMPIAIJ, &ismpiaij)); 75406977982Sstefanozampini if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(M, &dA, &oA, NULL)); 755a16187a7SStefano Zampini 75606977982Sstefanozampini PetscCall(hypreCSRMatrixGetCOO_Private(dH, &coo_n, &coo_i, &coo_j)); 75706977982Sstefanozampini PetscCall(MatSetPreallocationCOO(dA, coo_n, coo_i, coo_j)); 75806977982Sstefanozampini PetscCall(PetscFree2(coo_i, coo_j)); 75906977982Sstefanozampini if (ismpiaij) { 76006977982Sstefanozampini HYPRE_Int nc = hypre_CSRMatrixNumCols(oH); 761a16187a7SStefano Zampini 76206977982Sstefanozampini PetscCall(PetscLayoutDestroy(&oA->cmap)); 76306977982Sstefanozampini PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)oA), nc, nc, 1, &oA->cmap)); 76406977982Sstefanozampini PetscCall(hypreCSRMatrixGetCOO_Private(oH, &coo_n, &coo_i, &coo_j)); 76506977982Sstefanozampini PetscCall(MatSetPreallocationCOO(oA, coo_n, coo_i, coo_j)); 76606977982Sstefanozampini PetscCall(PetscFree2(coo_i, coo_j)); 767a16187a7SStefano Zampini 76806977982Sstefanozampini /* garray */ 769f4f49eeaSPierre Jolivet Mat_MPIAIJ *aij = (Mat_MPIAIJ *)M->data; 77006977982Sstefanozampini HYPRE_BigInt *harray = hypre_ParCSRMatrixColMapOffd(parcsr); 77106977982Sstefanozampini PetscInt *garray; 77206977982Sstefanozampini 77306977982Sstefanozampini PetscCall(PetscFree(aij->garray)); 77406977982Sstefanozampini PetscCall(PetscMalloc1(nc, &garray)); 77506977982Sstefanozampini for (HYPRE_Int i = 0; i < nc; i++) garray[i] = (PetscInt)harray[i]; 77606977982Sstefanozampini aij->garray = garray; 77706977982Sstefanozampini PetscCall(MatSetUpMultiply_MPIAIJ(M)); 778a16187a7SStefano Zampini } 77906977982Sstefanozampini if (reuse == MAT_INITIAL_MATRIX) *B = M; 78006977982Sstefanozampini } else M = *B; 781225daaf8SStefano Zampini 78206977982Sstefanozampini dA = M; 78306977982Sstefanozampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)M, MATMPIAIJ, &ismpiaij)); 78406977982Sstefanozampini if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(M, &dA, &oA, NULL)); 78506977982Sstefanozampini PetscCall(MatSetValuesCOOFromCSRMatrix_Private(dA, dH)); 78606977982Sstefanozampini if (oA) PetscCall(MatSetValuesCOOFromCSRMatrix_Private(oA, oH)); 78706977982Sstefanozampini M->assembled = PETSC_TRUE; 78806977982Sstefanozampini if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &M)); 7893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 79063c07aadSStefano Zampini } 79163c07aadSStefano Zampini 792d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJGetParCSR_Private(Mat A, hypre_ParCSRMatrix **hA) 793d71ae5a4SJacob Faibussowitsch { 794613e5ff0Sstefano_zampini hypre_ParCSRMatrix *tA; 795c1a070e6SStefano Zampini hypre_CSRMatrix *hdiag, *hoffd; 796c1a070e6SStefano Zampini Mat_SeqAIJ *diag, *offd; 7972cf14000SStefano Zampini PetscInt *garray, i, noffd, dnnz, onnz, *row_starts, *col_starts; 798c1a070e6SStefano Zampini MPI_Comm comm = PetscObjectComm((PetscObject)A); 799613e5ff0Sstefano_zampini PetscBool ismpiaij, isseqaij; 8002cf14000SStefano Zampini PetscBool sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int)); 8016ea7df73SStefano Zampini HYPRE_Int *hdi = NULL, *hdj = NULL, *hoi = NULL, *hoj = NULL; 8025c97c10fSStefano Zampini PetscInt *pdi = NULL, *pdj = NULL, *poi = NULL, *poj = NULL; 80306977982Sstefanozampini PetscBool iscuda, iship; 80406977982Sstefanozampini #if defined(PETSC_HAVE_DEVICE) && defined(PETSC_HAVE_HYPRE_DEVICE) 80506977982Sstefanozampini PetscBool boundtocpu = A->boundtocpu; 80606977982Sstefanozampini #else 80706977982Sstefanozampini PetscBool boundtocpu = PETSC_TRUE; 8086ea7df73SStefano Zampini #endif 809c1a070e6SStefano Zampini 810c1a070e6SStefano Zampini PetscFunctionBegin; 8119566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 8129566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isseqaij)); 81308401ef6SPierre Jolivet PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Unsupported type %s", ((PetscObject)A)->type_name); 814b655ebf8SZach Atkins PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, "")); 815b655ebf8SZach Atkins PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iship, MATSEQAIJHIPSPARSE, MATMPIAIJHIPSPARSE, "")); 816ea9ee2c1SPierre Jolivet PetscHYPREInitialize(); 817c1a070e6SStefano Zampini if (ismpiaij) { 818f4f49eeaSPierre Jolivet Mat_MPIAIJ *a = (Mat_MPIAIJ *)A->data; 819c1a070e6SStefano Zampini 820c1a070e6SStefano Zampini diag = (Mat_SeqAIJ *)a->A->data; 821c1a070e6SStefano Zampini offd = (Mat_SeqAIJ *)a->B->data; 82206977982Sstefanozampini if (!boundtocpu && (iscuda || iship)) { 82306977982Sstefanozampini #if defined(HYPRE_USING_CUDA) && defined(PETSC_HAVE_CUDA) 82406977982Sstefanozampini if (iscuda) { 8256ea7df73SStefano Zampini sameint = PETSC_TRUE; 8269566063dSJacob Faibussowitsch PetscCall(MatSeqAIJCUSPARSEGetIJ(a->A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj)); 8279566063dSJacob Faibussowitsch PetscCall(MatSeqAIJCUSPARSEGetIJ(a->B, PETSC_FALSE, (const HYPRE_Int **)&hoi, (const HYPRE_Int **)&hoj)); 82806977982Sstefanozampini } 8296ea7df73SStefano Zampini #endif 83006977982Sstefanozampini #if defined(HYPRE_USING_HIP) && defined(PETSC_HAVE_HIP) 83106977982Sstefanozampini if (iship) { 83206977982Sstefanozampini sameint = PETSC_TRUE; 83306977982Sstefanozampini PetscCall(MatSeqAIJHIPSPARSEGetIJ(a->A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj)); 83406977982Sstefanozampini PetscCall(MatSeqAIJHIPSPARSEGetIJ(a->B, PETSC_FALSE, (const HYPRE_Int **)&hoi, (const HYPRE_Int **)&hoj)); 83506977982Sstefanozampini } 83606977982Sstefanozampini #endif 83706977982Sstefanozampini } else { 83806977982Sstefanozampini boundtocpu = PETSC_TRUE; 8396ea7df73SStefano Zampini pdi = diag->i; 8406ea7df73SStefano Zampini pdj = diag->j; 8416ea7df73SStefano Zampini poi = offd->i; 8426ea7df73SStefano Zampini poj = offd->j; 8436ea7df73SStefano Zampini if (sameint) { 8446ea7df73SStefano Zampini hdi = (HYPRE_Int *)pdi; 8456ea7df73SStefano Zampini hdj = (HYPRE_Int *)pdj; 8466ea7df73SStefano Zampini hoi = (HYPRE_Int *)poi; 8476ea7df73SStefano Zampini hoj = (HYPRE_Int *)poj; 8486ea7df73SStefano Zampini } 8496ea7df73SStefano Zampini } 850c1a070e6SStefano Zampini garray = a->garray; 851c1a070e6SStefano Zampini noffd = a->B->cmap->N; 852c1a070e6SStefano Zampini dnnz = diag->nz; 853c1a070e6SStefano Zampini onnz = offd->nz; 854c1a070e6SStefano Zampini } else { 855c1a070e6SStefano Zampini diag = (Mat_SeqAIJ *)A->data; 856c1a070e6SStefano Zampini offd = NULL; 85706977982Sstefanozampini if (!boundtocpu && (iscuda || iship)) { 85806977982Sstefanozampini #if defined(HYPRE_USING_CUDA) && defined(PETSC_HAVE_CUDA) 85906977982Sstefanozampini if (iscuda) { 8606ea7df73SStefano Zampini sameint = PETSC_TRUE; 8619566063dSJacob Faibussowitsch PetscCall(MatSeqAIJCUSPARSEGetIJ(A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj)); 86206977982Sstefanozampini } 8636ea7df73SStefano Zampini #endif 86406977982Sstefanozampini #if defined(HYPRE_USING_HIP) && defined(PETSC_HAVE_HIP) 86506977982Sstefanozampini if (iship) { 86606977982Sstefanozampini sameint = PETSC_TRUE; 86706977982Sstefanozampini PetscCall(MatSeqAIJHIPSPARSEGetIJ(A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj)); 86806977982Sstefanozampini } 86906977982Sstefanozampini #endif 87006977982Sstefanozampini } else { 87106977982Sstefanozampini boundtocpu = PETSC_TRUE; 8726ea7df73SStefano Zampini pdi = diag->i; 8736ea7df73SStefano Zampini pdj = diag->j; 8746ea7df73SStefano Zampini if (sameint) { 8756ea7df73SStefano Zampini hdi = (HYPRE_Int *)pdi; 8766ea7df73SStefano Zampini hdj = (HYPRE_Int *)pdj; 8776ea7df73SStefano Zampini } 8786ea7df73SStefano Zampini } 879c1a070e6SStefano Zampini garray = NULL; 880c1a070e6SStefano Zampini noffd = 0; 881c1a070e6SStefano Zampini dnnz = diag->nz; 882c1a070e6SStefano Zampini onnz = 0; 883c1a070e6SStefano Zampini } 884225daaf8SStefano Zampini 885c1a070e6SStefano Zampini /* create a temporary ParCSR */ 886c1a070e6SStefano Zampini if (HYPRE_AssumedPartitionCheck()) { 887c1a070e6SStefano Zampini PetscMPIInt myid; 888c1a070e6SStefano Zampini 8899566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &myid)); 890c1a070e6SStefano Zampini row_starts = A->rmap->range + myid; 891c1a070e6SStefano Zampini col_starts = A->cmap->range + myid; 892c1a070e6SStefano Zampini } else { 893c1a070e6SStefano Zampini row_starts = A->rmap->range; 894c1a070e6SStefano Zampini col_starts = A->cmap->range; 895c1a070e6SStefano Zampini } 8962cf14000SStefano Zampini tA = hypre_ParCSRMatrixCreate(comm, A->rmap->N, A->cmap->N, (HYPRE_BigInt *)row_starts, (HYPRE_BigInt *)col_starts, noffd, dnnz, onnz); 897a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 898c1a070e6SStefano Zampini hypre_ParCSRMatrixSetRowStartsOwner(tA, 0); 899c1a070e6SStefano Zampini hypre_ParCSRMatrixSetColStartsOwner(tA, 0); 900a1d2239cSSatish Balay #endif 901c1a070e6SStefano Zampini 902225daaf8SStefano Zampini /* set diagonal part */ 903c1a070e6SStefano Zampini hdiag = hypre_ParCSRMatrixDiag(tA); 9046ea7df73SStefano Zampini if (!sameint) { /* malloc CSR pointers */ 9059566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(A->rmap->n + 1, &hdi, dnnz, &hdj)); 906f4f49eeaSPierre Jolivet for (i = 0; i < A->rmap->n + 1; i++) hdi[i] = (HYPRE_Int)pdi[i]; 907f4f49eeaSPierre Jolivet for (i = 0; i < dnnz; i++) hdj[i] = (HYPRE_Int)pdj[i]; 9082cf14000SStefano Zampini } 9096ea7df73SStefano Zampini hypre_CSRMatrixI(hdiag) = hdi; 9106ea7df73SStefano Zampini hypre_CSRMatrixJ(hdiag) = hdj; 91139accc25SStefano Zampini hypre_CSRMatrixData(hdiag) = (HYPRE_Complex *)diag->a; 912c1a070e6SStefano Zampini hypre_CSRMatrixNumNonzeros(hdiag) = diag->nz; 913c1a070e6SStefano Zampini hypre_CSRMatrixSetRownnz(hdiag); 914c1a070e6SStefano Zampini hypre_CSRMatrixSetDataOwner(hdiag, 0); 915c1a070e6SStefano Zampini 9164cf0e950SBarry Smith /* set off-diagonal part */ 917c1a070e6SStefano Zampini hoffd = hypre_ParCSRMatrixOffd(tA); 918c1a070e6SStefano Zampini if (offd) { 9196ea7df73SStefano Zampini if (!sameint) { /* malloc CSR pointers */ 9209566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(A->rmap->n + 1, &hoi, onnz, &hoj)); 921f4f49eeaSPierre Jolivet for (i = 0; i < A->rmap->n + 1; i++) hoi[i] = (HYPRE_Int)poi[i]; 922f4f49eeaSPierre Jolivet for (i = 0; i < onnz; i++) hoj[i] = (HYPRE_Int)poj[i]; 9232cf14000SStefano Zampini } 9246ea7df73SStefano Zampini hypre_CSRMatrixI(hoffd) = hoi; 9256ea7df73SStefano Zampini hypre_CSRMatrixJ(hoffd) = hoj; 92639accc25SStefano Zampini hypre_CSRMatrixData(hoffd) = (HYPRE_Complex *)offd->a; 927c1a070e6SStefano Zampini hypre_CSRMatrixNumNonzeros(hoffd) = offd->nz; 928c1a070e6SStefano Zampini hypre_CSRMatrixSetRownnz(hoffd); 929c1a070e6SStefano Zampini hypre_CSRMatrixSetDataOwner(hoffd, 0); 9306ea7df73SStefano Zampini } 9316ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 93206977982Sstefanozampini PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, !boundtocpu ? HYPRE_MEMORY_DEVICE : HYPRE_MEMORY_HOST); 9336ea7df73SStefano Zampini #else 9346ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0) 935792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixInitialize, tA); 9366ea7df73SStefano Zampini #else 937792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, HYPRE_MEMORY_HOST); 9386ea7df73SStefano Zampini #endif 9396ea7df73SStefano Zampini #endif 9406ea7df73SStefano Zampini hypre_TFree(hypre_ParCSRMatrixColMapOffd(tA), HYPRE_MEMORY_HOST); 941c1a070e6SStefano Zampini hypre_ParCSRMatrixSetNumNonzeros(tA); 9422cf14000SStefano Zampini hypre_ParCSRMatrixColMapOffd(tA) = (HYPRE_BigInt *)garray; 943792fecdfSBarry Smith if (!hypre_ParCSRMatrixCommPkg(tA)) PetscCallExternal(hypre_MatvecCommPkgCreate, tA); 944613e5ff0Sstefano_zampini *hA = tA; 9453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 946613e5ff0Sstefano_zampini } 947c1a070e6SStefano Zampini 948d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJRestoreParCSR_Private(Mat A, hypre_ParCSRMatrix **hA) 949d71ae5a4SJacob Faibussowitsch { 950613e5ff0Sstefano_zampini hypre_CSRMatrix *hdiag, *hoffd; 9516ea7df73SStefano Zampini PetscBool ismpiaij, sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int)); 952b655ebf8SZach Atkins PetscBool iscuda, iship; 953c1a070e6SStefano Zampini 954613e5ff0Sstefano_zampini PetscFunctionBegin; 9559566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 9569566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, "")); 957b655ebf8SZach Atkins PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iship, MATSEQAIJHIPSPARSE, MATMPIAIJHIPSPARSE, "")); 958b655ebf8SZach Atkins #if defined(HYPRE_USING_CUDA) && defined(PETSC_HAVE_CUDA) 9596ea7df73SStefano Zampini if (iscuda) sameint = PETSC_TRUE; 960b655ebf8SZach Atkins #elif defined(HYPRE_USING_HIP) && defined(PETSC_HAVE_HIP) 961b655ebf8SZach Atkins if (iship) sameint = PETSC_TRUE; 9626ea7df73SStefano Zampini #endif 963613e5ff0Sstefano_zampini hdiag = hypre_ParCSRMatrixDiag(*hA); 964613e5ff0Sstefano_zampini hoffd = hypre_ParCSRMatrixOffd(*hA); 9656ea7df73SStefano Zampini /* free temporary memory allocated by PETSc 9666ea7df73SStefano Zampini set pointers to NULL before destroying tA */ 9672cf14000SStefano Zampini if (!sameint) { 9682cf14000SStefano Zampini HYPRE_Int *hi, *hj; 9692cf14000SStefano Zampini 9702cf14000SStefano Zampini hi = hypre_CSRMatrixI(hdiag); 9712cf14000SStefano Zampini hj = hypre_CSRMatrixJ(hdiag); 9729566063dSJacob Faibussowitsch PetscCall(PetscFree2(hi, hj)); 9736ea7df73SStefano Zampini if (ismpiaij) { 9742cf14000SStefano Zampini hi = hypre_CSRMatrixI(hoffd); 9752cf14000SStefano Zampini hj = hypre_CSRMatrixJ(hoffd); 9769566063dSJacob Faibussowitsch PetscCall(PetscFree2(hi, hj)); 9772cf14000SStefano Zampini } 9782cf14000SStefano Zampini } 979c1a070e6SStefano Zampini hypre_CSRMatrixI(hdiag) = NULL; 980c1a070e6SStefano Zampini hypre_CSRMatrixJ(hdiag) = NULL; 981c1a070e6SStefano Zampini hypre_CSRMatrixData(hdiag) = NULL; 9826ea7df73SStefano Zampini if (ismpiaij) { 983c1a070e6SStefano Zampini hypre_CSRMatrixI(hoffd) = NULL; 984c1a070e6SStefano Zampini hypre_CSRMatrixJ(hoffd) = NULL; 985c1a070e6SStefano Zampini hypre_CSRMatrixData(hoffd) = NULL; 9866ea7df73SStefano Zampini } 987613e5ff0Sstefano_zampini hypre_ParCSRMatrixColMapOffd(*hA) = NULL; 988613e5ff0Sstefano_zampini hypre_ParCSRMatrixDestroy(*hA); 989613e5ff0Sstefano_zampini *hA = NULL; 9903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 991613e5ff0Sstefano_zampini } 992613e5ff0Sstefano_zampini 993613e5ff0Sstefano_zampini /* calls RAP from BoomerAMG: 9943dad0653Sstefano_zampini the resulting ParCSR will not own the column and row starts 9956ea7df73SStefano Zampini It looks like we don't need to have the diagonal entries ordered first */ 996d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_RAP(hypre_ParCSRMatrix *hR, hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hP, hypre_ParCSRMatrix **hRAP) 997d71ae5a4SJacob Faibussowitsch { 998a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 999613e5ff0Sstefano_zampini HYPRE_Int P_owns_col_starts, R_owns_row_starts; 1000a1d2239cSSatish Balay #endif 1001613e5ff0Sstefano_zampini 1002613e5ff0Sstefano_zampini PetscFunctionBegin; 1003a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 1004613e5ff0Sstefano_zampini P_owns_col_starts = hypre_ParCSRMatrixOwnsColStarts(hP); 1005613e5ff0Sstefano_zampini R_owns_row_starts = hypre_ParCSRMatrixOwnsRowStarts(hR); 1006a1d2239cSSatish Balay #endif 10076ea7df73SStefano Zampini /* can be replaced by version test later */ 10086ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 1009792fecdfSBarry Smith PetscStackPushExternal("hypre_ParCSRMatrixRAP"); 10106ea7df73SStefano Zampini *hRAP = hypre_ParCSRMatrixRAP(hR, hA, hP); 10116ea7df73SStefano Zampini PetscStackPop; 10126ea7df73SStefano Zampini #else 1013792fecdfSBarry Smith PetscCallExternal(hypre_BoomerAMGBuildCoarseOperator, hR, hA, hP, hRAP); 1014792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixSetNumNonzeros, *hRAP); 10156ea7df73SStefano Zampini #endif 1016613e5ff0Sstefano_zampini /* hypre_BoomerAMGBuildCoarseOperator steals the col_starts from P and the row_starts from R */ 1017a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 1018613e5ff0Sstefano_zampini hypre_ParCSRMatrixSetRowStartsOwner(*hRAP, 0); 1019613e5ff0Sstefano_zampini hypre_ParCSRMatrixSetColStartsOwner(*hRAP, 0); 1020613e5ff0Sstefano_zampini if (P_owns_col_starts) hypre_ParCSRMatrixSetColStartsOwner(hP, 1); 1021613e5ff0Sstefano_zampini if (R_owns_row_starts) hypre_ParCSRMatrixSetRowStartsOwner(hR, 1); 1022a1d2239cSSatish Balay #endif 10233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1024613e5ff0Sstefano_zampini } 1025613e5ff0Sstefano_zampini 1026d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat P, Mat C) 1027d71ae5a4SJacob Faibussowitsch { 10286f231fbdSstefano_zampini Mat B; 10296abb4441SStefano Zampini hypre_ParCSRMatrix *hA, *hP, *hPtAP = NULL; 10304222ddf1SHong Zhang Mat_Product *product = C->product; 1031613e5ff0Sstefano_zampini 1032613e5ff0Sstefano_zampini PetscFunctionBegin; 10339566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(A, &hA)); 10349566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(P, &hP)); 10359566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_RAP(hP, hA, hP, &hPtAP)); 10369566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(hPtAP, MATAIJ, PETSC_OWN_POINTER, &B)); 10374222ddf1SHong Zhang 10389566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(C, &B)); 10394222ddf1SHong Zhang C->product = product; 10404222ddf1SHong Zhang 10419566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(A, &hA)); 10429566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(P, &hP)); 10433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10446f231fbdSstefano_zampini } 10456f231fbdSstefano_zampini 1046d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatPtAPSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat P, PetscReal fill, Mat C) 1047d71ae5a4SJacob Faibussowitsch { 10486f231fbdSstefano_zampini PetscFunctionBegin; 10499566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATAIJ)); 10504222ddf1SHong Zhang C->ops->ptapnumeric = MatPtAPNumeric_AIJ_AIJ_wHYPRE; 10514222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_PtAP; 10523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1053613e5ff0Sstefano_zampini } 1054613e5ff0Sstefano_zampini 1055d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_HYPRE(Mat A, Mat P, Mat C) 1056d71ae5a4SJacob Faibussowitsch { 10574cc28894Sstefano_zampini Mat B; 10584cc28894Sstefano_zampini Mat_HYPRE *hP; 10596abb4441SStefano Zampini hypre_ParCSRMatrix *hA = NULL, *Pparcsr, *ptapparcsr = NULL; 1060613e5ff0Sstefano_zampini HYPRE_Int type; 1061613e5ff0Sstefano_zampini MPI_Comm comm = PetscObjectComm((PetscObject)A); 10624cc28894Sstefano_zampini PetscBool ishypre; 1063613e5ff0Sstefano_zampini 1064613e5ff0Sstefano_zampini PetscFunctionBegin; 10659566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre)); 106628b400f6SJacob Faibussowitsch PetscCheck(ishypre, comm, PETSC_ERR_USER, "P should be of type %s", MATHYPRE); 10674cc28894Sstefano_zampini hP = (Mat_HYPRE *)P->data; 1068792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type); 106908401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 1070792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr); 1071613e5ff0Sstefano_zampini 10729566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(A, &hA)); 10739566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, hA, Pparcsr, &ptapparcsr)); 10749566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(A, &hA)); 1075225daaf8SStefano Zampini 10764cc28894Sstefano_zampini /* create temporary matrix and merge to C */ 10779566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(ptapparcsr, ((PetscObject)C)->type_name, PETSC_OWN_POINTER, &B)); 10789566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(C, &B)); 10793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10804cc28894Sstefano_zampini } 10814cc28894Sstefano_zampini 1082d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_HYPRE_HYPRE(Mat A, Mat P, Mat C) 1083d71ae5a4SJacob Faibussowitsch { 10844cc28894Sstefano_zampini Mat B; 10856abb4441SStefano Zampini hypre_ParCSRMatrix *Aparcsr, *Pparcsr, *ptapparcsr = NULL; 10864cc28894Sstefano_zampini Mat_HYPRE *hA, *hP; 10874cc28894Sstefano_zampini PetscBool ishypre; 10884cc28894Sstefano_zampini HYPRE_Int type; 10894cc28894Sstefano_zampini 10904cc28894Sstefano_zampini PetscFunctionBegin; 10919566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre)); 109228b400f6SJacob Faibussowitsch PetscCheck(ishypre, PetscObjectComm((PetscObject)P), PETSC_ERR_USER, "P should be of type %s", MATHYPRE); 10939566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre)); 109428b400f6SJacob Faibussowitsch PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE); 10954cc28894Sstefano_zampini hA = (Mat_HYPRE *)A->data; 10964cc28894Sstefano_zampini hP = (Mat_HYPRE *)P->data; 1097792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type); 109808401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 1099792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type); 110008401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)P), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 1101792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr); 1102792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr); 11039566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, Aparcsr, Pparcsr, &ptapparcsr)); 11049566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(ptapparcsr, MATHYPRE, PETSC_OWN_POINTER, &B)); 11059566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(C, &B)); 11063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11074cc28894Sstefano_zampini } 11084cc28894Sstefano_zampini 1109d501dc42Sstefano_zampini /* calls hypre_ParMatmul 1110d501dc42Sstefano_zampini hypre_ParMatMul uses hypre_ParMatrixCreate with the communicator of hA 11113dad0653Sstefano_zampini hypre_ParMatrixCreate does not duplicate the communicator 11126ea7df73SStefano Zampini It looks like we don't need to have the diagonal entries ordered first */ 1113d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_MatMatMult(hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hB, hypre_ParCSRMatrix **hAB) 1114d71ae5a4SJacob Faibussowitsch { 1115d501dc42Sstefano_zampini PetscFunctionBegin; 11166ea7df73SStefano Zampini /* can be replaced by version test later */ 11176ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 1118792fecdfSBarry Smith PetscStackPushExternal("hypre_ParCSRMatMat"); 11196ea7df73SStefano Zampini *hAB = hypre_ParCSRMatMat(hA, hB); 11206ea7df73SStefano Zampini #else 1121792fecdfSBarry Smith PetscStackPushExternal("hypre_ParMatmul"); 1122d501dc42Sstefano_zampini *hAB = hypre_ParMatmul(hA, hB); 11236ea7df73SStefano Zampini #endif 1124d501dc42Sstefano_zampini PetscStackPop; 11253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1126d501dc42Sstefano_zampini } 1127d501dc42Sstefano_zampini 1128d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C) 1129d71ae5a4SJacob Faibussowitsch { 11305e5acdf2Sstefano_zampini Mat D; 1131d501dc42Sstefano_zampini hypre_ParCSRMatrix *hA, *hB, *hAB = NULL; 11324222ddf1SHong Zhang Mat_Product *product = C->product; 11335e5acdf2Sstefano_zampini 11345e5acdf2Sstefano_zampini PetscFunctionBegin; 11359566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(A, &hA)); 11369566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(B, &hB)); 11379566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_MatMatMult(hA, hB, &hAB)); 11389566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(hAB, MATAIJ, PETSC_OWN_POINTER, &D)); 11394222ddf1SHong Zhang 11409566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(C, &D)); 11414222ddf1SHong Zhang C->product = product; 11424222ddf1SHong Zhang 11439566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(A, &hA)); 11449566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(B, &hB)); 11453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11465e5acdf2Sstefano_zampini } 11475e5acdf2Sstefano_zampini 1148d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatMatMultSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat B, PetscReal fill, Mat C) 1149d71ae5a4SJacob Faibussowitsch { 11505e5acdf2Sstefano_zampini PetscFunctionBegin; 11519566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATAIJ)); 11524222ddf1SHong Zhang C->ops->matmultnumeric = MatMatMultNumeric_AIJ_AIJ_wHYPRE; 11534222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_AB; 11543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11555e5acdf2Sstefano_zampini } 11565e5acdf2Sstefano_zampini 1157d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_HYPRE_HYPRE(Mat A, Mat B, Mat C) 1158d71ae5a4SJacob Faibussowitsch { 1159d501dc42Sstefano_zampini Mat D; 1160d501dc42Sstefano_zampini hypre_ParCSRMatrix *Aparcsr, *Bparcsr, *ABparcsr = NULL; 1161d501dc42Sstefano_zampini Mat_HYPRE *hA, *hB; 1162d501dc42Sstefano_zampini PetscBool ishypre; 1163d501dc42Sstefano_zampini HYPRE_Int type; 11644222ddf1SHong Zhang Mat_Product *product; 1165d501dc42Sstefano_zampini 1166d501dc42Sstefano_zampini PetscFunctionBegin; 11679566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)B, MATHYPRE, &ishypre)); 116828b400f6SJacob Faibussowitsch PetscCheck(ishypre, PetscObjectComm((PetscObject)B), PETSC_ERR_USER, "B should be of type %s", MATHYPRE); 11699566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre)); 117028b400f6SJacob Faibussowitsch PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE); 1171d501dc42Sstefano_zampini hA = (Mat_HYPRE *)A->data; 1172d501dc42Sstefano_zampini hB = (Mat_HYPRE *)B->data; 1173792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type); 117408401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 1175792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hB->ij, &type); 117608401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 1177792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr); 1178792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hB->ij, (void **)&Bparcsr); 11799566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_MatMatMult(Aparcsr, Bparcsr, &ABparcsr)); 11809566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(ABparcsr, MATHYPRE, PETSC_OWN_POINTER, &D)); 11814222ddf1SHong Zhang 1182d501dc42Sstefano_zampini /* need to use HeaderReplace because HeaderMerge messes up with the communicator */ 11834222ddf1SHong Zhang product = C->product; /* save it from MatHeaderReplace() */ 11844222ddf1SHong Zhang C->product = NULL; 11859566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(C, &D)); 11864222ddf1SHong Zhang C->product = product; 1187d501dc42Sstefano_zampini C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE; 11884222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_AB; 11893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1190d501dc42Sstefano_zampini } 1191d501dc42Sstefano_zampini 1192d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultNumeric_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, Mat D) 1193d71ae5a4SJacob Faibussowitsch { 119420e1dc0dSstefano_zampini Mat E; 11956abb4441SStefano Zampini hypre_ParCSRMatrix *hA, *hB, *hC, *hABC = NULL; 119620e1dc0dSstefano_zampini 119720e1dc0dSstefano_zampini PetscFunctionBegin; 11989566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(A, &hA)); 11999566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(B, &hB)); 12009566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(C, &hC)); 12019566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_RAP(hA, hB, hC, &hABC)); 12029566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(hABC, MATAIJ, PETSC_OWN_POINTER, &E)); 12039566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(D, &E)); 12049566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(A, &hA)); 12059566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(B, &hB)); 12069566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(C, &hC)); 12073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 120820e1dc0dSstefano_zampini } 120920e1dc0dSstefano_zampini 1210d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultSymbolic_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, PetscReal fill, Mat D) 1211d71ae5a4SJacob Faibussowitsch { 121220e1dc0dSstefano_zampini PetscFunctionBegin; 12139566063dSJacob Faibussowitsch PetscCall(MatSetType(D, MATAIJ)); 12143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 121520e1dc0dSstefano_zampini } 121620e1dc0dSstefano_zampini 1217d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_AB_HYPRE(Mat C) 1218d71ae5a4SJacob Faibussowitsch { 12194222ddf1SHong Zhang PetscFunctionBegin; 12204222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_AB; 12213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12224222ddf1SHong Zhang } 12234222ddf1SHong Zhang 1224d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_AB(Mat C) 1225d71ae5a4SJacob Faibussowitsch { 12264222ddf1SHong Zhang Mat_Product *product = C->product; 12274222ddf1SHong Zhang PetscBool Ahypre; 12284222ddf1SHong Zhang 12294222ddf1SHong Zhang PetscFunctionBegin; 12309566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)product->A, MATHYPRE, &Ahypre)); 12314222ddf1SHong Zhang if (Ahypre) { /* A is a Hypre matrix */ 12329566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATHYPRE)); 12334222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_AB_HYPRE; 12344222ddf1SHong Zhang C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE; 12353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12366718818eSStefano Zampini } 12373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12384222ddf1SHong Zhang } 12394222ddf1SHong Zhang 1240d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_PtAP_HYPRE(Mat C) 1241d71ae5a4SJacob Faibussowitsch { 12424222ddf1SHong Zhang PetscFunctionBegin; 12434222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_PtAP; 12443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12454222ddf1SHong Zhang } 12464222ddf1SHong Zhang 1247d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_PtAP(Mat C) 1248d71ae5a4SJacob Faibussowitsch { 12494222ddf1SHong Zhang Mat_Product *product = C->product; 12504222ddf1SHong Zhang PetscBool flg; 12514222ddf1SHong Zhang PetscInt type = 0; 12524222ddf1SHong Zhang const char *outTypes[4] = {"aij", "seqaij", "mpiaij", "hypre"}; 12534222ddf1SHong Zhang PetscInt ntype = 4; 12544222ddf1SHong Zhang Mat A = product->A; 12554222ddf1SHong Zhang PetscBool Ahypre; 12564222ddf1SHong Zhang 12574222ddf1SHong Zhang PetscFunctionBegin; 12589566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &Ahypre)); 12594222ddf1SHong Zhang if (Ahypre) { /* A is a Hypre matrix */ 12609566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATHYPRE)); 12614222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE; 12624222ddf1SHong Zhang C->ops->ptapnumeric = MatPtAPNumeric_HYPRE_HYPRE; 12633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12644222ddf1SHong Zhang } 12654222ddf1SHong Zhang 12664222ddf1SHong Zhang /* A is AIJ, P is Hypre, C = PtAP can be either AIJ or Hypre format */ 12674222ddf1SHong Zhang /* Get runtime option */ 12684222ddf1SHong Zhang if (product->api_user) { 1269d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatPtAP_HYPRE", "Mat"); 12709566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-matptap_hypre_outtype", "MatPtAP outtype", "MatPtAP outtype", outTypes, ntype, outTypes[type], &type, &flg)); 1271d0609cedSBarry Smith PetscOptionsEnd(); 12724222ddf1SHong Zhang } else { 1273d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatProduct_PtAP_HYPRE", "Mat"); 12749566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-mat_product_algorithm_hypre_outtype", "MatProduct_PtAP outtype", "MatProduct_PtAP", outTypes, ntype, outTypes[type], &type, &flg)); 1275d0609cedSBarry Smith PetscOptionsEnd(); 12764222ddf1SHong Zhang } 12774222ddf1SHong Zhang 12784222ddf1SHong Zhang if (type == 0 || type == 1 || type == 2) { 12799566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATAIJ)); 12804222ddf1SHong Zhang } else if (type == 3) { 12819566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATHYPRE)); 12824222ddf1SHong Zhang } else SETERRQ(PetscObjectComm((PetscObject)C), PETSC_ERR_SUP, "MatPtAP outtype is not supported"); 12834222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE; 12844222ddf1SHong Zhang C->ops->ptapnumeric = MatPtAPNumeric_AIJ_HYPRE; 12853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12864222ddf1SHong Zhang } 12874222ddf1SHong Zhang 1288d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE(Mat C) 1289d71ae5a4SJacob Faibussowitsch { 12904222ddf1SHong Zhang Mat_Product *product = C->product; 12914222ddf1SHong Zhang 12924222ddf1SHong Zhang PetscFunctionBegin; 12934222ddf1SHong Zhang switch (product->type) { 1294d71ae5a4SJacob Faibussowitsch case MATPRODUCT_AB: 1295d71ae5a4SJacob Faibussowitsch PetscCall(MatProductSetFromOptions_HYPRE_AB(C)); 1296d71ae5a4SJacob Faibussowitsch break; 1297d71ae5a4SJacob Faibussowitsch case MATPRODUCT_PtAP: 1298d71ae5a4SJacob Faibussowitsch PetscCall(MatProductSetFromOptions_HYPRE_PtAP(C)); 1299d71ae5a4SJacob Faibussowitsch break; 1300d71ae5a4SJacob Faibussowitsch default: 1301d71ae5a4SJacob Faibussowitsch break; 13024222ddf1SHong Zhang } 13033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13044222ddf1SHong Zhang } 13054222ddf1SHong Zhang 1306d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTranspose_HYPRE(Mat A, Vec x, Vec y) 1307d71ae5a4SJacob Faibussowitsch { 130863c07aadSStefano Zampini PetscFunctionBegin; 13099566063dSJacob Faibussowitsch PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_TRUE)); 13103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 131163c07aadSStefano Zampini } 131263c07aadSStefano Zampini 1313d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_HYPRE(Mat A, Vec x, Vec y) 1314d71ae5a4SJacob Faibussowitsch { 131563c07aadSStefano Zampini PetscFunctionBegin; 13169566063dSJacob Faibussowitsch PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_FALSE)); 13173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 131863c07aadSStefano Zampini } 131963c07aadSStefano Zampini 1320d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultAdd_HYPRE(Mat A, Vec x, Vec y, Vec z) 1321d71ae5a4SJacob Faibussowitsch { 1322414bd5c3SStefano Zampini PetscFunctionBegin; 132348a46eb9SPierre Jolivet if (y != z) PetscCall(VecCopy(y, z)); 13249566063dSJacob Faibussowitsch PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_FALSE)); 13253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1326414bd5c3SStefano Zampini } 1327414bd5c3SStefano Zampini 1328d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTransposeAdd_HYPRE(Mat A, Vec x, Vec y, Vec z) 1329d71ae5a4SJacob Faibussowitsch { 1330414bd5c3SStefano Zampini PetscFunctionBegin; 133148a46eb9SPierre Jolivet if (y != z) PetscCall(VecCopy(y, z)); 13329566063dSJacob Faibussowitsch PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_TRUE)); 13333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1334414bd5c3SStefano Zampini } 1335414bd5c3SStefano Zampini 1336414bd5c3SStefano Zampini /* y = a * A * x + b * y or y = a * A^t * x + b * y depending on trans */ 1337d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_MultKernel_Private(Mat A, HYPRE_Complex a, Vec x, HYPRE_Complex b, Vec y, PetscBool trans) 1338d71ae5a4SJacob Faibussowitsch { 133963c07aadSStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 134063c07aadSStefano Zampini hypre_ParCSRMatrix *parcsr; 134163c07aadSStefano Zampini hypre_ParVector *hx, *hy; 134263c07aadSStefano Zampini 134363c07aadSStefano Zampini PetscFunctionBegin; 134463c07aadSStefano Zampini if (trans) { 13459566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorPushVecRead(hA->b, x)); 13469566063dSJacob Faibussowitsch if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->x, y)); 13479566063dSJacob Faibussowitsch else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->x, y)); 1348792fecdfSBarry Smith PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hx); 1349792fecdfSBarry Smith PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hy); 135063c07aadSStefano Zampini } else { 13519566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorPushVecRead(hA->x, x)); 13529566063dSJacob Faibussowitsch if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->b, y)); 13539566063dSJacob Faibussowitsch else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->b, y)); 1354792fecdfSBarry Smith PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hx); 1355792fecdfSBarry Smith PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hy); 135663c07aadSStefano Zampini } 1357792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr); 13586ea7df73SStefano Zampini if (trans) { 1359792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixMatvecT, a, parcsr, hx, b, hy); 13606ea7df73SStefano Zampini } else { 1361792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixMatvec, a, parcsr, hx, b, hy); 13626ea7df73SStefano Zampini } 13639566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorPopVec(hA->x)); 13649566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorPopVec(hA->b)); 13653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 136663c07aadSStefano Zampini } 136763c07aadSStefano Zampini 1368d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_HYPRE(Mat A) 1369d71ae5a4SJacob Faibussowitsch { 137063c07aadSStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 137163c07aadSStefano Zampini 137263c07aadSStefano Zampini PetscFunctionBegin; 13739566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorDestroy(&hA->x)); 13749566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorDestroy(&hA->b)); 137506977982Sstefanozampini PetscCall(MatHYPRE_DestroyCOOMat(A)); /* must be called before destroying the individual CSR */ 1376978814f1SStefano Zampini if (hA->ij) { 1377978814f1SStefano Zampini if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL; 1378792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixDestroy, hA->ij); 1379978814f1SStefano Zampini } 13809566063dSJacob Faibussowitsch if (hA->comm) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)A), &hA->comm)); 1381c69f721fSFande Kong 13829566063dSJacob Faibussowitsch PetscCall(MatStashDestroy_Private(&A->stash)); 13839566063dSJacob Faibussowitsch PetscCall(PetscFree(hA->array)); 1384a32e9c99SJunchao Zhang if (hA->rows_d) PetscStackCallExternalVoid("hypre_Free", hypre_Free(hA->rows_d, HYPRE_MEMORY_DEVICE)); 1385c69f721fSFande Kong 13869566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_aij_C", NULL)); 13879566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_is_C", NULL)); 13889566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_hypre_C", NULL)); 13899566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaij_hypre_C", NULL)); 139006977982Sstefanozampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijhipsparse_hypre_C", NULL)); 139106977982Sstefanozampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaijhipsparse_hypre_C", NULL)); 139206977982Sstefanozampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijcusparse_hypre_C", NULL)); 139306977982Sstefanozampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaijcusparse_hypre_C", NULL)); 13949566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPRESetPreallocation_C", NULL)); 13959566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPREGetParCSR_C", NULL)); 13965fbaff96SJunchao Zhang PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL)); 13975fbaff96SJunchao Zhang PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL)); 13989566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 13993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 140063c07aadSStefano Zampini } 140163c07aadSStefano Zampini 1402d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetUp_HYPRE(Mat A) 1403d71ae5a4SJacob Faibussowitsch { 14044ec6421dSstefano_zampini PetscFunctionBegin; 140506977982Sstefanozampini if (!A->preallocated) PetscCall(MatHYPRESetPreallocation(A, PETSC_DEFAULT, NULL, PETSC_DEFAULT, NULL)); 14063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14074ec6421dSstefano_zampini } 14084ec6421dSstefano_zampini 14096ea7df73SStefano Zampini //TODO FIX hypre_CSRMatrixMatvecOutOfPlace 14106ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 1411d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatBindToCPU_HYPRE(Mat A, PetscBool bind) 1412d71ae5a4SJacob Faibussowitsch { 14136ea7df73SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 14146ea7df73SStefano Zampini HYPRE_MemoryLocation hmem = bind ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE; 14156ea7df73SStefano Zampini 14166ea7df73SStefano Zampini PetscFunctionBegin; 14176ea7df73SStefano Zampini A->boundtocpu = bind; 14185fbaff96SJunchao Zhang if (hA->ij && hypre_IJMatrixAssembleFlag(hA->ij) && hmem != hypre_IJMatrixMemoryLocation(hA->ij)) { 14196ea7df73SStefano Zampini hypre_ParCSRMatrix *parcsr; 1420792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr); 1421792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixMigrate, parcsr, hmem); 14226ea7df73SStefano Zampini } 14239566063dSJacob Faibussowitsch if (hA->x) PetscCall(VecHYPRE_IJBindToCPU(hA->x, bind)); 14249566063dSJacob Faibussowitsch if (hA->b) PetscCall(VecHYPRE_IJBindToCPU(hA->b, bind)); 14253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14266ea7df73SStefano Zampini } 14276ea7df73SStefano Zampini #endif 14286ea7df73SStefano Zampini 1429d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_HYPRE(Mat A, MatAssemblyType mode) 1430d71ae5a4SJacob Faibussowitsch { 143163c07aadSStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1432c69f721fSFande Kong PetscMPIInt n; 1433c69f721fSFande Kong PetscInt i, j, rstart, ncols, flg; 1434c69f721fSFande Kong PetscInt *row, *col; 1435c69f721fSFande Kong PetscScalar *val; 143663c07aadSStefano Zampini 143763c07aadSStefano Zampini PetscFunctionBegin; 143808401ef6SPierre Jolivet PetscCheck(mode != MAT_FLUSH_ASSEMBLY, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_FLUSH_ASSEMBLY currently not supported with MATHYPRE"); 1439c69f721fSFande Kong 1440c69f721fSFande Kong if (!A->nooffprocentries) { 1441c69f721fSFande Kong while (1) { 14429566063dSJacob Faibussowitsch PetscCall(MatStashScatterGetMesg_Private(&A->stash, &n, &row, &col, &val, &flg)); 1443c69f721fSFande Kong if (!flg) break; 1444c69f721fSFande Kong 1445c69f721fSFande Kong for (i = 0; i < n;) { 1446c69f721fSFande Kong /* Now identify the consecutive vals belonging to the same row */ 1447c69f721fSFande Kong for (j = i, rstart = row[j]; j < n; j++) { 1448c69f721fSFande Kong if (row[j] != rstart) break; 1449c69f721fSFande Kong } 1450c69f721fSFande Kong if (j < n) ncols = j - i; 1451c69f721fSFande Kong else ncols = n - i; 1452c69f721fSFande Kong /* Now assemble all these values with a single function call */ 14539566063dSJacob Faibussowitsch PetscCall(MatSetValues_HYPRE(A, 1, row + i, ncols, col + i, val + i, A->insertmode)); 1454c69f721fSFande Kong 1455c69f721fSFande Kong i = j; 1456c69f721fSFande Kong } 1457c69f721fSFande Kong } 14589566063dSJacob Faibussowitsch PetscCall(MatStashScatterEnd_Private(&A->stash)); 1459c69f721fSFande Kong } 1460c69f721fSFande Kong 1461792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixAssemble, hA->ij); 1462336664bdSPierre Jolivet /* The assembly routine destroys the aux_matrix, we recreate it here by calling HYPRE_IJMatrixInitialize */ 1463336664bdSPierre 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 */ 1464651b1cf9SStefano Zampini if (!A->sortedfull) { 1465af1cf968SStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 1466af1cf968SStefano Zampini 1467af1cf968SStefano Zampini /* call destroy just to make sure we do not leak anything */ 1468af1cf968SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij); 1469792fecdfSBarry Smith PetscCallExternal(hypre_AuxParCSRMatrixDestroy, aux_matrix); 1470af1cf968SStefano Zampini hypre_IJMatrixTranslator(hA->ij) = NULL; 1471af1cf968SStefano Zampini 1472af1cf968SStefano Zampini /* Initialize with assembled flag -> it only recreates the aux_par_matrix */ 1473792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij); 1474af1cf968SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij); 14756ea7df73SStefano Zampini if (aux_matrix) { 1476af1cf968SStefano Zampini hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1; /* see comment in MatHYPRESetPreallocation_HYPRE */ 147722235d61SPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 1478792fecdfSBarry Smith PetscCallExternal(hypre_AuxParCSRMatrixInitialize, aux_matrix); 147922235d61SPierre Jolivet #else 1480792fecdfSBarry Smith PetscCallExternal(hypre_AuxParCSRMatrixInitialize_v2, aux_matrix, HYPRE_MEMORY_HOST); 148122235d61SPierre Jolivet #endif 1482af1cf968SStefano Zampini } 14836ea7df73SStefano Zampini } 14846ea7df73SStefano Zampini { 14856ea7df73SStefano Zampini hypre_ParCSRMatrix *parcsr; 14866ea7df73SStefano Zampini 1487792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr); 1488792fecdfSBarry Smith if (!hypre_ParCSRMatrixCommPkg(parcsr)) PetscCallExternal(hypre_MatvecCommPkgCreate, parcsr); 14896ea7df73SStefano Zampini } 14909566063dSJacob Faibussowitsch if (!hA->x) PetscCall(VecHYPRE_IJVectorCreate(A->cmap, &hA->x)); 14919566063dSJacob Faibussowitsch if (!hA->b) PetscCall(VecHYPRE_IJVectorCreate(A->rmap, &hA->b)); 14926ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 14939566063dSJacob Faibussowitsch PetscCall(MatBindToCPU_HYPRE(A, A->boundtocpu)); 14946ea7df73SStefano Zampini #endif 14953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 149663c07aadSStefano Zampini } 149763c07aadSStefano Zampini 1498d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetArray_HYPRE(Mat A, PetscInt size, void **array) 1499d71ae5a4SJacob Faibussowitsch { 1500c69f721fSFande Kong Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1501c69f721fSFande Kong 1502c69f721fSFande Kong PetscFunctionBegin; 1503651b1cf9SStefano Zampini PetscCheck(hA->array_available, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Temporary space is in use"); 1504c69f721fSFande Kong 1505651b1cf9SStefano Zampini if (hA->array_size >= size) { 150639accc25SStefano Zampini *array = hA->array; 150739accc25SStefano Zampini } else { 15089566063dSJacob Faibussowitsch PetscCall(PetscFree(hA->array)); 1509651b1cf9SStefano Zampini hA->array_size = size; 1510651b1cf9SStefano Zampini PetscCall(PetscMalloc(hA->array_size, &hA->array)); 1511c69f721fSFande Kong *array = hA->array; 1512c69f721fSFande Kong } 1513c69f721fSFande Kong 1514651b1cf9SStefano Zampini hA->array_available = PETSC_FALSE; 15153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1516c69f721fSFande Kong } 1517c69f721fSFande Kong 1518d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreArray_HYPRE(Mat A, void **array) 1519d71ae5a4SJacob Faibussowitsch { 1520c69f721fSFande Kong Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1521c69f721fSFande Kong 1522c69f721fSFande Kong PetscFunctionBegin; 1523c69f721fSFande Kong *array = NULL; 1524651b1cf9SStefano Zampini hA->array_available = PETSC_TRUE; 15253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1526c69f721fSFande Kong } 1527c69f721fSFande Kong 1528d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_HYPRE(Mat A, PetscInt nr, const PetscInt rows[], PetscInt nc, const PetscInt cols[], const PetscScalar v[], InsertMode ins) 1529d71ae5a4SJacob Faibussowitsch { 1530d975228cSstefano_zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1531d975228cSstefano_zampini PetscScalar *vals = (PetscScalar *)v; 153239accc25SStefano Zampini HYPRE_Complex *sscr; 1533c69f721fSFande Kong PetscInt *cscr[2]; 1534c69f721fSFande Kong PetscInt i, nzc; 1535651b1cf9SStefano Zampini PetscInt rst = A->rmap->rstart, ren = A->rmap->rend; 153608defe43SFande Kong void *array = NULL; 1537d975228cSstefano_zampini 1538d975228cSstefano_zampini PetscFunctionBegin; 15399566063dSJacob Faibussowitsch PetscCall(MatGetArray_HYPRE(A, sizeof(PetscInt) * (2 * nc) + sizeof(HYPRE_Complex) * nc * nr, &array)); 1540c69f721fSFande Kong cscr[0] = (PetscInt *)array; 1541c69f721fSFande Kong cscr[1] = ((PetscInt *)array) + nc; 154239accc25SStefano Zampini sscr = (HYPRE_Complex *)(((PetscInt *)array) + nc * 2); 1543d975228cSstefano_zampini for (i = 0, nzc = 0; i < nc; i++) { 1544d975228cSstefano_zampini if (cols[i] >= 0) { 1545d975228cSstefano_zampini cscr[0][nzc] = cols[i]; 1546d975228cSstefano_zampini cscr[1][nzc++] = i; 1547d975228cSstefano_zampini } 1548d975228cSstefano_zampini } 1549c69f721fSFande Kong if (!nzc) { 15509566063dSJacob Faibussowitsch PetscCall(MatRestoreArray_HYPRE(A, &array)); 15513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1552c69f721fSFande Kong } 1553d975228cSstefano_zampini 15546ea7df73SStefano Zampini #if 0 //defined(PETSC_HAVE_HYPRE_DEVICE) 15556ea7df73SStefano Zampini if (HYPRE_MEMORY_HOST != hypre_IJMatrixMemoryLocation(hA->ij)) { 15566ea7df73SStefano Zampini hypre_ParCSRMatrix *parcsr; 15576ea7df73SStefano Zampini 1558792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject,hA->ij,(void**)&parcsr); 1559792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixMigrate,parcsr, HYPRE_MEMORY_HOST); 15606ea7df73SStefano Zampini } 15616ea7df73SStefano Zampini #endif 15626ea7df73SStefano Zampini 1563d975228cSstefano_zampini if (ins == ADD_VALUES) { 1564d975228cSstefano_zampini for (i = 0; i < nr; i++) { 15656ea7df73SStefano Zampini if (rows[i] >= 0) { 1566d975228cSstefano_zampini PetscInt j; 15672cf14000SStefano Zampini HYPRE_Int hnc = (HYPRE_Int)nzc; 15682cf14000SStefano Zampini 1569651b1cf9SStefano Zampini if (!nzc) continue; 1570651b1cf9SStefano Zampini /* nonlocal values */ 1571651b1cf9SStefano Zampini if (rows[i] < rst || rows[i] >= ren) { 1572651b1cf9SStefano 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]); 1573651b1cf9SStefano Zampini if (hA->donotstash) continue; 1574651b1cf9SStefano Zampini } 1575aed4548fSBarry 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]); 15769566063dSJacob Faibussowitsch for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j])); 1577792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixAddToValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr); 1578d975228cSstefano_zampini } 1579d975228cSstefano_zampini vals += nc; 1580d975228cSstefano_zampini } 1581d975228cSstefano_zampini } else { /* INSERT_VALUES */ 1582d975228cSstefano_zampini for (i = 0; i < nr; i++) { 15836ea7df73SStefano Zampini if (rows[i] >= 0) { 1584d975228cSstefano_zampini PetscInt j; 15852cf14000SStefano Zampini HYPRE_Int hnc = (HYPRE_Int)nzc; 15862cf14000SStefano Zampini 1587651b1cf9SStefano Zampini if (!nzc) continue; 1588aed4548fSBarry 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]); 15899566063dSJacob Faibussowitsch for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j])); 1590c69f721fSFande Kong /* nonlocal values */ 1591651b1cf9SStefano Zampini if (rows[i] < rst || rows[i] >= ren) { 1592651b1cf9SStefano 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]); 1593651b1cf9SStefano Zampini if (!hA->donotstash) PetscCall(MatStashValuesRow_Private(&A->stash, rows[i], nzc, cscr[0], (PetscScalar *)sscr, PETSC_FALSE)); 1594651b1cf9SStefano Zampini } 1595c69f721fSFande Kong /* local values */ 1596651b1cf9SStefano Zampini else 1597651b1cf9SStefano Zampini PetscCallExternal(HYPRE_IJMatrixSetValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr); 1598d975228cSstefano_zampini } 1599d975228cSstefano_zampini vals += nc; 1600d975228cSstefano_zampini } 1601d975228cSstefano_zampini } 1602c69f721fSFande Kong 16039566063dSJacob Faibussowitsch PetscCall(MatRestoreArray_HYPRE(A, &array)); 16043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1605d975228cSstefano_zampini } 1606d975228cSstefano_zampini 1607d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRESetPreallocation_HYPRE(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[]) 1608d71ae5a4SJacob Faibussowitsch { 1609d975228cSstefano_zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 16107d968826Sstefano_zampini HYPRE_Int *hdnnz, *honnz; 161106a29025Sstefano_zampini PetscInt i, rs, re, cs, ce, bs; 1612d975228cSstefano_zampini PetscMPIInt size; 1613d975228cSstefano_zampini 1614d975228cSstefano_zampini PetscFunctionBegin; 16159566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 16169566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 1617d975228cSstefano_zampini rs = A->rmap->rstart; 1618d975228cSstefano_zampini re = A->rmap->rend; 1619d975228cSstefano_zampini cs = A->cmap->rstart; 1620d975228cSstefano_zampini ce = A->cmap->rend; 1621d975228cSstefano_zampini if (!hA->ij) { 1622792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rs, re - 1, cs, ce - 1, &hA->ij); 1623792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR); 1624d975228cSstefano_zampini } else { 16252cf14000SStefano Zampini HYPRE_BigInt hrs, hre, hcs, hce; 1626792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetLocalRange, hA->ij, &hrs, &hre, &hcs, &hce); 1627aed4548fSBarry 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); 1628aed4548fSBarry 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); 1629d975228cSstefano_zampini } 163006977982Sstefanozampini PetscCall(MatHYPRE_DestroyCOOMat(A)); 16319566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 163206a29025Sstefano_zampini if (dnz == PETSC_DEFAULT || dnz == PETSC_DECIDE) dnz = 10 * bs; 163306a29025Sstefano_zampini if (onz == PETSC_DEFAULT || onz == PETSC_DECIDE) onz = 10 * bs; 163406a29025Sstefano_zampini 1635d975228cSstefano_zampini if (!dnnz) { 16369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n, &hdnnz)); 1637d975228cSstefano_zampini for (i = 0; i < A->rmap->n; i++) hdnnz[i] = dnz; 1638d975228cSstefano_zampini } else { 16397d968826Sstefano_zampini hdnnz = (HYPRE_Int *)dnnz; 1640d975228cSstefano_zampini } 16419566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 1642d975228cSstefano_zampini if (size > 1) { 1643ddbeb582SStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 1644d975228cSstefano_zampini if (!onnz) { 16459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n, &honnz)); 1646d975228cSstefano_zampini for (i = 0; i < A->rmap->n; i++) honnz[i] = onz; 164722235d61SPierre Jolivet } else honnz = (HYPRE_Int *)onnz; 1648ddbeb582SStefano Zampini /* SetDiagOffdSizes sets hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0, since it seems 1649ddbeb582SStefano Zampini they assume the user will input the entire row values, properly sorted 1650336664bdSPierre Jolivet In PETSc, we don't make such an assumption and set this flag to 1, 1651336664bdSPierre Jolivet unless the option MAT_SORTED_FULL is set to true. 1652ddbeb582SStefano Zampini Also, to avoid possible memory leaks, we destroy and recreate the translator 1653ddbeb582SStefano Zampini This has to be done here, as HYPRE_IJMatrixInitialize will properly initialize 1654ddbeb582SStefano Zampini the IJ matrix for us */ 1655ddbeb582SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij); 1656ddbeb582SStefano Zampini hypre_AuxParCSRMatrixDestroy(aux_matrix); 1657ddbeb582SStefano Zampini hypre_IJMatrixTranslator(hA->ij) = NULL; 1658792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, hA->ij, hdnnz, honnz); 1659ddbeb582SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij); 1660651b1cf9SStefano Zampini hypre_AuxParCSRMatrixNeedAux(aux_matrix) = !A->sortedfull; 1661d975228cSstefano_zampini } else { 1662d975228cSstefano_zampini honnz = NULL; 1663792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetRowSizes, hA->ij, hdnnz); 1664d975228cSstefano_zampini } 1665ddbeb582SStefano Zampini 1666af1cf968SStefano Zampini /* reset assembled flag and call the initialize method */ 1667af1cf968SStefano Zampini hypre_IJMatrixAssembleFlag(hA->ij) = 0; 16686ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 1669792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij); 16706ea7df73SStefano Zampini #else 1671792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize_v2, hA->ij, HYPRE_MEMORY_HOST); 16726ea7df73SStefano Zampini #endif 167348a46eb9SPierre Jolivet if (!dnnz) PetscCall(PetscFree(hdnnz)); 167448a46eb9SPierre Jolivet if (!onnz && honnz) PetscCall(PetscFree(honnz)); 1675af1cf968SStefano Zampini /* Match AIJ logic */ 167606a29025Sstefano_zampini A->preallocated = PETSC_TRUE; 1677af1cf968SStefano Zampini A->assembled = PETSC_FALSE; 16783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1679d975228cSstefano_zampini } 1680d975228cSstefano_zampini 1681d975228cSstefano_zampini /*@C 1682d975228cSstefano_zampini MatHYPRESetPreallocation - Preallocates memory for a sparse parallel matrix in HYPRE IJ format 1683d975228cSstefano_zampini 1684c3339decSBarry Smith Collective 1685d975228cSstefano_zampini 1686d975228cSstefano_zampini Input Parameters: 1687d975228cSstefano_zampini + A - the matrix 1688d975228cSstefano_zampini . dnz - number of nonzeros per row in DIAGONAL portion of local submatrix 1689d975228cSstefano_zampini (same value is used for all local rows) 1690d975228cSstefano_zampini . dnnz - array containing the number of nonzeros in the various rows of the 1691d975228cSstefano_zampini DIAGONAL portion of the local submatrix (possibly different for each row) 16922ef1f0ffSBarry Smith or `NULL` (`PETSC_NULL_INTEGER` in Fortran), if `d_nz` is used to specify the nonzero structure. 16932ef1f0ffSBarry Smith The size of this array is equal to the number of local rows, i.e `m`. 1694d975228cSstefano_zampini For matrices that will be factored, you must leave room for (and set) 1695d975228cSstefano_zampini the diagonal entry even if it is zero. 1696d975228cSstefano_zampini . onz - number of nonzeros per row in the OFF-DIAGONAL portion of local 1697d975228cSstefano_zampini submatrix (same value is used for all local rows). 1698d975228cSstefano_zampini - onnz - array containing the number of nonzeros in the various rows of the 1699d975228cSstefano_zampini OFF-DIAGONAL portion of the local submatrix (possibly different for 17002ef1f0ffSBarry Smith each row) or `NULL` (`PETSC_NULL_INTEGER` in Fortran), if `o_nz` is used to specify the nonzero 1701d975228cSstefano_zampini structure. The size of this array is equal to the number 17022ef1f0ffSBarry Smith of local rows, i.e `m`. 1703d975228cSstefano_zampini 17042fe279fdSBarry Smith Level: intermediate 17052fe279fdSBarry Smith 170611a5261eSBarry Smith Note: 17072ef1f0ffSBarry Smith If the *nnz parameter is given then the *nz parameter is ignored; for sequential matrices, `onz` and `onnz` are ignored. 1708d975228cSstefano_zampini 17091cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatMPIAIJSetPreallocation()`, `MATHYPRE`, `MATAIJ` 1710d975228cSstefano_zampini @*/ 1711d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHYPRESetPreallocation(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[]) 1712d71ae5a4SJacob Faibussowitsch { 1713d975228cSstefano_zampini PetscFunctionBegin; 1714d975228cSstefano_zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1715d975228cSstefano_zampini PetscValidType(A, 1); 1716cac4c232SBarry Smith PetscTryMethod(A, "MatHYPRESetPreallocation_C", (Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]), (A, dnz, dnnz, onz, onnz)); 17173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1718d975228cSstefano_zampini } 1719d975228cSstefano_zampini 172020f4b53cSBarry Smith /*@C 17212ef1f0ffSBarry Smith MatCreateFromParCSR - Creates a `Mat` from a `hypre_ParCSRMatrix` 1722225daaf8SStefano Zampini 1723225daaf8SStefano Zampini Collective 1724225daaf8SStefano Zampini 1725225daaf8SStefano Zampini Input Parameters: 17262ef1f0ffSBarry Smith + parcsr - the pointer to the `hypre_ParCSRMatrix` 17272ef1f0ffSBarry Smith . mtype - matrix type to be created. Currently `MATAIJ`, `MATIS` and `MATHYPRE` are supported. 172820f4b53cSBarry Smith - copymode - PETSc copying options, see `PetscCopyMode` 1729225daaf8SStefano Zampini 1730225daaf8SStefano Zampini Output Parameter: 1731225daaf8SStefano Zampini . A - the matrix 1732225daaf8SStefano Zampini 1733225daaf8SStefano Zampini Level: intermediate 1734225daaf8SStefano Zampini 1735bfe80ac4SPierre Jolivet .seealso: [](ch_matrices), `Mat`, `MATHYPRE`, `PetscCopyMode` 173620f4b53cSBarry Smith @*/ 1737d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreateFromParCSR(hypre_ParCSRMatrix *parcsr, MatType mtype, PetscCopyMode copymode, Mat *A) 1738d71ae5a4SJacob Faibussowitsch { 1739225daaf8SStefano Zampini Mat T; 1740978814f1SStefano Zampini Mat_HYPRE *hA; 1741978814f1SStefano Zampini MPI_Comm comm; 1742978814f1SStefano Zampini PetscInt rstart, rend, cstart, cend, M, N; 1743d248a85cSRichard Tran Mills PetscBool isseqaij, isseqaijmkl, ismpiaij, isaij, ishyp, isis; 1744978814f1SStefano Zampini 1745978814f1SStefano Zampini PetscFunctionBegin; 1746978814f1SStefano Zampini comm = hypre_ParCSRMatrixComm(parcsr); 17479566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQAIJ, &isseqaij)); 17489566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQAIJMKL, &isseqaijmkl)); 17499566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPIAIJ, &ismpiaij)); 17509566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATAIJ, &isaij)); 17519566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATHYPRE, &ishyp)); 17529566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATIS, &isis)); 1753d248a85cSRichard Tran Mills isaij = (PetscBool)(isseqaij || isseqaijmkl || ismpiaij || isaij); 17546ea7df73SStefano Zampini /* TODO */ 1755aed4548fSBarry 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); 1756978814f1SStefano Zampini /* access ParCSRMatrix */ 1757978814f1SStefano Zampini rstart = hypre_ParCSRMatrixFirstRowIndex(parcsr); 1758978814f1SStefano Zampini rend = hypre_ParCSRMatrixLastRowIndex(parcsr); 1759978814f1SStefano Zampini cstart = hypre_ParCSRMatrixFirstColDiag(parcsr); 1760978814f1SStefano Zampini cend = hypre_ParCSRMatrixLastColDiag(parcsr); 1761978814f1SStefano Zampini M = hypre_ParCSRMatrixGlobalNumRows(parcsr); 1762978814f1SStefano Zampini N = hypre_ParCSRMatrixGlobalNumCols(parcsr); 1763978814f1SStefano Zampini 1764978814f1SStefano Zampini /* create PETSc matrix with MatHYPRE */ 17659566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &T)); 1766c2886e86SStefano Zampini PetscCall(MatSetSizes(T, PetscMax(rend - rstart + 1, 0), PetscMax(cend - cstart + 1, 0), M, N)); 17679566063dSJacob Faibussowitsch PetscCall(MatSetType(T, MATHYPRE)); 1768f4f49eeaSPierre Jolivet hA = (Mat_HYPRE *)T->data; 1769978814f1SStefano Zampini 1770978814f1SStefano Zampini /* create HYPRE_IJMatrix */ 1771c2886e86SStefano Zampini PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rstart, rend, cstart, cend, &hA->ij); 1772792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR); 177345b8d346SStefano Zampini 177445b8d346SStefano Zampini /* create new ParCSR object if needed */ 177545b8d346SStefano Zampini if (ishyp && copymode == PETSC_COPY_VALUES) { 177645b8d346SStefano Zampini hypre_ParCSRMatrix *new_parcsr; 17776ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0) 177845b8d346SStefano Zampini hypre_CSRMatrix *hdiag, *hoffd, *ndiag, *noffd; 177945b8d346SStefano Zampini 17800e6427aaSSatish Balay new_parcsr = hypre_ParCSRMatrixClone(parcsr, 0); 178145b8d346SStefano Zampini hdiag = hypre_ParCSRMatrixDiag(parcsr); 178245b8d346SStefano Zampini hoffd = hypre_ParCSRMatrixOffd(parcsr); 178345b8d346SStefano Zampini ndiag = hypre_ParCSRMatrixDiag(new_parcsr); 178445b8d346SStefano Zampini noffd = hypre_ParCSRMatrixOffd(new_parcsr); 17859566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hypre_CSRMatrixData(ndiag), hypre_CSRMatrixData(hdiag), hypre_CSRMatrixNumNonzeros(hdiag))); 17869566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hypre_CSRMatrixData(noffd), hypre_CSRMatrixData(hoffd), hypre_CSRMatrixNumNonzeros(hoffd))); 17876ea7df73SStefano Zampini #else 17886ea7df73SStefano Zampini new_parcsr = hypre_ParCSRMatrixClone(parcsr, 1); 17896ea7df73SStefano Zampini #endif 179045b8d346SStefano Zampini parcsr = new_parcsr; 179145b8d346SStefano Zampini copymode = PETSC_OWN_POINTER; 179245b8d346SStefano Zampini } 1793978814f1SStefano Zampini 1794978814f1SStefano Zampini /* set ParCSR object */ 1795978814f1SStefano Zampini hypre_IJMatrixObject(hA->ij) = parcsr; 17964ec6421dSstefano_zampini T->preallocated = PETSC_TRUE; 1797978814f1SStefano Zampini 1798978814f1SStefano Zampini /* set assembled flag */ 1799978814f1SStefano Zampini hypre_IJMatrixAssembleFlag(hA->ij) = 1; 18006ea7df73SStefano Zampini #if 0 1801792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize,hA->ij); 18026ea7df73SStefano Zampini #endif 1803225daaf8SStefano Zampini if (ishyp) { 18046d2a658fSstefano_zampini PetscMPIInt myid = 0; 18056d2a658fSstefano_zampini 18066d2a658fSstefano_zampini /* make sure we always have row_starts and col_starts available */ 180748a46eb9SPierre Jolivet if (HYPRE_AssumedPartitionCheck()) PetscCallMPI(MPI_Comm_rank(comm, &myid)); 1808a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 18096d2a658fSstefano_zampini if (!hypre_ParCSRMatrixOwnsColStarts(parcsr)) { 18106d2a658fSstefano_zampini PetscLayout map; 18116d2a658fSstefano_zampini 18129566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(T, NULL, &map)); 18139566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(map)); 18142cf14000SStefano Zampini hypre_ParCSRMatrixColStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid); 18156d2a658fSstefano_zampini } 18166d2a658fSstefano_zampini if (!hypre_ParCSRMatrixOwnsRowStarts(parcsr)) { 18176d2a658fSstefano_zampini PetscLayout map; 18186d2a658fSstefano_zampini 18199566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(T, &map, NULL)); 18209566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(map)); 18212cf14000SStefano Zampini hypre_ParCSRMatrixRowStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid); 18226d2a658fSstefano_zampini } 1823a1d2239cSSatish Balay #endif 1824978814f1SStefano Zampini /* prevent from freeing the pointer */ 1825978814f1SStefano Zampini if (copymode == PETSC_USE_POINTER) hA->inner_free = PETSC_FALSE; 1826225daaf8SStefano Zampini *A = T; 18279566063dSJacob Faibussowitsch PetscCall(MatSetOption(*A, MAT_SORTED_FULL, PETSC_TRUE)); 18289566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*A, MAT_FINAL_ASSEMBLY)); 18299566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*A, MAT_FINAL_ASSEMBLY)); 1830bb4689ddSStefano Zampini } else if (isaij) { 1831bb4689ddSStefano Zampini if (copymode != PETSC_OWN_POINTER) { 1832225daaf8SStefano Zampini /* prevent from freeing the pointer */ 1833225daaf8SStefano Zampini hA->inner_free = PETSC_FALSE; 18349566063dSJacob Faibussowitsch PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INITIAL_MATRIX, A)); 18359566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 1836225daaf8SStefano Zampini } else { /* AIJ return type with PETSC_OWN_POINTER */ 18379566063dSJacob Faibussowitsch PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INPLACE_MATRIX, &T)); 1838225daaf8SStefano Zampini *A = T; 1839225daaf8SStefano Zampini } 1840bb4689ddSStefano Zampini } else if (isis) { 18419566063dSJacob Faibussowitsch PetscCall(MatConvert_HYPRE_IS(T, MATIS, MAT_INITIAL_MATRIX, A)); 18428cfe8d00SStefano Zampini if (copymode != PETSC_OWN_POINTER) hA->inner_free = PETSC_FALSE; 18439566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 1844bb4689ddSStefano Zampini } 18453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1846978814f1SStefano Zampini } 1847978814f1SStefano Zampini 1848d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPREGetParCSR_HYPRE(Mat A, hypre_ParCSRMatrix **parcsr) 1849d71ae5a4SJacob Faibussowitsch { 1850dd9c0a25Sstefano_zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1851dd9c0a25Sstefano_zampini HYPRE_Int type; 1852dd9c0a25Sstefano_zampini 1853dd9c0a25Sstefano_zampini PetscFunctionBegin; 185428b400f6SJacob Faibussowitsch PetscCheck(hA->ij, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "HYPRE_IJMatrix not present"); 1855792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type); 185608401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "HYPRE_IJMatrix is not of type HYPRE_PARCSR"); 1857792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)parcsr); 18583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1859dd9c0a25Sstefano_zampini } 1860dd9c0a25Sstefano_zampini 186120f4b53cSBarry Smith /*@C 1862dd9c0a25Sstefano_zampini MatHYPREGetParCSR - Gets the pointer to the ParCSR matrix 1863dd9c0a25Sstefano_zampini 1864cc4c1da9SBarry Smith Not Collective, No Fortran Support 1865dd9c0a25Sstefano_zampini 186620f4b53cSBarry Smith Input Parameter: 186720f4b53cSBarry Smith . A - the `MATHYPRE` object 1868dd9c0a25Sstefano_zampini 1869dd9c0a25Sstefano_zampini Output Parameter: 18702ef1f0ffSBarry Smith . parcsr - the pointer to the `hypre_ParCSRMatrix` 1871dd9c0a25Sstefano_zampini 1872dd9c0a25Sstefano_zampini Level: intermediate 1873dd9c0a25Sstefano_zampini 1874bfe80ac4SPierre Jolivet .seealso: [](ch_matrices), `Mat`, `MATHYPRE`, `PetscCopyMode` 187520f4b53cSBarry Smith @*/ 1876d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHYPREGetParCSR(Mat A, hypre_ParCSRMatrix **parcsr) 1877d71ae5a4SJacob Faibussowitsch { 1878dd9c0a25Sstefano_zampini PetscFunctionBegin; 1879dd9c0a25Sstefano_zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1880dd9c0a25Sstefano_zampini PetscValidType(A, 1); 1881cac4c232SBarry Smith PetscUseMethod(A, "MatHYPREGetParCSR_C", (Mat, hypre_ParCSRMatrix **), (A, parcsr)); 18823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1883dd9c0a25Sstefano_zampini } 1884dd9c0a25Sstefano_zampini 1885d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_HYPRE(Mat A, PetscBool *missing, PetscInt *dd) 1886d71ae5a4SJacob Faibussowitsch { 188768ec7858SStefano Zampini hypre_ParCSRMatrix *parcsr; 188868ec7858SStefano Zampini hypre_CSRMatrix *ha; 188968ec7858SStefano Zampini PetscInt rst; 189068ec7858SStefano Zampini 189168ec7858SStefano Zampini PetscFunctionBegin; 189208401ef6SPierre Jolivet PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented with non-square diagonal blocks"); 18939566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rst, NULL)); 18949566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 189568ec7858SStefano Zampini if (missing) *missing = PETSC_FALSE; 189668ec7858SStefano Zampini if (dd) *dd = -1; 189768ec7858SStefano Zampini ha = hypre_ParCSRMatrixDiag(parcsr); 189868ec7858SStefano Zampini if (ha) { 189968299464SStefano Zampini PetscInt size, i; 190068299464SStefano Zampini HYPRE_Int *ii, *jj; 190168ec7858SStefano Zampini 190268ec7858SStefano Zampini size = hypre_CSRMatrixNumRows(ha); 190368ec7858SStefano Zampini ii = hypre_CSRMatrixI(ha); 190468ec7858SStefano Zampini jj = hypre_CSRMatrixJ(ha); 190568ec7858SStefano Zampini for (i = 0; i < size; i++) { 190668ec7858SStefano Zampini PetscInt j; 190768ec7858SStefano Zampini PetscBool found = PETSC_FALSE; 190868ec7858SStefano Zampini 19099371c9d4SSatish Balay for (j = ii[i]; j < ii[i + 1] && !found; j++) found = (jj[j] == i) ? PETSC_TRUE : PETSC_FALSE; 191068ec7858SStefano Zampini 191168ec7858SStefano Zampini if (!found) { 19123ba16761SJacob Faibussowitsch PetscCall(PetscInfo(A, "Matrix is missing local diagonal entry %" PetscInt_FMT "\n", i)); 191368ec7858SStefano Zampini if (missing) *missing = PETSC_TRUE; 191468ec7858SStefano Zampini if (dd) *dd = i + rst; 19153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 191668ec7858SStefano Zampini } 191768ec7858SStefano Zampini } 191868ec7858SStefano Zampini if (!size) { 19193ba16761SJacob Faibussowitsch PetscCall(PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n")); 192068ec7858SStefano Zampini if (missing) *missing = PETSC_TRUE; 192168ec7858SStefano Zampini if (dd) *dd = rst; 192268ec7858SStefano Zampini } 192368ec7858SStefano Zampini } else { 19243ba16761SJacob Faibussowitsch PetscCall(PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n")); 192568ec7858SStefano Zampini if (missing) *missing = PETSC_TRUE; 192668ec7858SStefano Zampini if (dd) *dd = rst; 192768ec7858SStefano Zampini } 19283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 192968ec7858SStefano Zampini } 193068ec7858SStefano Zampini 1931d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatScale_HYPRE(Mat A, PetscScalar s) 1932d71ae5a4SJacob Faibussowitsch { 193368ec7858SStefano Zampini hypre_ParCSRMatrix *parcsr; 19346ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 193568ec7858SStefano Zampini hypre_CSRMatrix *ha; 19366ea7df73SStefano Zampini #endif 193739accc25SStefano Zampini HYPRE_Complex hs; 193868ec7858SStefano Zampini 193968ec7858SStefano Zampini PetscFunctionBegin; 19409566063dSJacob Faibussowitsch PetscCall(PetscHYPREScalarCast(s, &hs)); 19419566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 19426ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 19, 0) 1943792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixScale, parcsr, hs); 19446ea7df73SStefano Zampini #else /* diagonal part */ 194568ec7858SStefano Zampini ha = hypre_ParCSRMatrixDiag(parcsr); 194668ec7858SStefano Zampini if (ha) { 194768299464SStefano Zampini PetscInt size, i; 194868299464SStefano Zampini HYPRE_Int *ii; 194939accc25SStefano Zampini HYPRE_Complex *a; 195068ec7858SStefano Zampini 195168ec7858SStefano Zampini size = hypre_CSRMatrixNumRows(ha); 195268ec7858SStefano Zampini a = hypre_CSRMatrixData(ha); 195368ec7858SStefano Zampini ii = hypre_CSRMatrixI(ha); 195439accc25SStefano Zampini for (i = 0; i < ii[size]; i++) a[i] *= hs; 195568ec7858SStefano Zampini } 19564cf0e950SBarry Smith /* off-diagonal part */ 195768ec7858SStefano Zampini ha = hypre_ParCSRMatrixOffd(parcsr); 195868ec7858SStefano Zampini if (ha) { 195968299464SStefano Zampini PetscInt size, i; 196068299464SStefano Zampini HYPRE_Int *ii; 196139accc25SStefano Zampini HYPRE_Complex *a; 196268ec7858SStefano Zampini 196368ec7858SStefano Zampini size = hypre_CSRMatrixNumRows(ha); 196468ec7858SStefano Zampini a = hypre_CSRMatrixData(ha); 196568ec7858SStefano Zampini ii = hypre_CSRMatrixI(ha); 196639accc25SStefano Zampini for (i = 0; i < ii[size]; i++) a[i] *= hs; 196768ec7858SStefano Zampini } 19686ea7df73SStefano Zampini #endif 19693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 197068ec7858SStefano Zampini } 197168ec7858SStefano Zampini 1972d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_HYPRE(Mat A, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 1973d71ae5a4SJacob Faibussowitsch { 197468ec7858SStefano Zampini hypre_ParCSRMatrix *parcsr; 197568299464SStefano Zampini HYPRE_Int *lrows; 197668299464SStefano Zampini PetscInt rst, ren, i; 197768ec7858SStefano Zampini 197868ec7858SStefano Zampini PetscFunctionBegin; 197908401ef6SPierre Jolivet PetscCheck(!x && !b, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "To be implemented"); 19809566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 19819566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRows, &lrows)); 19829566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rst, &ren)); 198368ec7858SStefano Zampini for (i = 0; i < numRows; i++) { 19847a46b595SBarry Smith PetscCheck(rows[i] >= rst && rows[i] < ren, PETSC_COMM_SELF, PETSC_ERR_SUP, "Non-local rows not yet supported"); 198568ec7858SStefano Zampini lrows[i] = rows[i] - rst; 198668ec7858SStefano Zampini } 1987792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixEliminateRowsCols, parcsr, numRows, lrows); 19889566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 19893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 199068ec7858SStefano Zampini } 199168ec7858SStefano Zampini 1992d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPRE_CSRMatrix(hypre_CSRMatrix *ha) 1993d71ae5a4SJacob Faibussowitsch { 1994c69f721fSFande Kong PetscFunctionBegin; 1995c69f721fSFande Kong if (ha) { 1996c69f721fSFande Kong HYPRE_Int *ii, size; 1997c69f721fSFande Kong HYPRE_Complex *a; 1998c69f721fSFande Kong 1999c69f721fSFande Kong size = hypre_CSRMatrixNumRows(ha); 2000c69f721fSFande Kong a = hypre_CSRMatrixData(ha); 2001c69f721fSFande Kong ii = hypre_CSRMatrixI(ha); 2002c69f721fSFande Kong 20039566063dSJacob Faibussowitsch if (a) PetscCall(PetscArrayzero(a, ii[size])); 2004c69f721fSFande Kong } 20053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2006c69f721fSFande Kong } 2007c69f721fSFande Kong 200866976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPRE(Mat A) 2009d71ae5a4SJacob Faibussowitsch { 20106ea7df73SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 20116ea7df73SStefano Zampini 20126ea7df73SStefano Zampini PetscFunctionBegin; 20136ea7df73SStefano Zampini if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(hA->ij)) { 2014792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetConstantValues, hA->ij, 0.0); 20156ea7df73SStefano Zampini } else { 2016c69f721fSFande Kong hypre_ParCSRMatrix *parcsr; 2017c69f721fSFande Kong 20189566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 20199566063dSJacob Faibussowitsch PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr))); 20209566063dSJacob Faibussowitsch PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr))); 20216ea7df73SStefano Zampini } 20223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2023c69f721fSFande Kong } 2024c69f721fSFande Kong 2025d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_HYPRE_CSRMatrix(hypre_CSRMatrix *hA, PetscInt N, const PetscInt rows[], HYPRE_Complex diag) 2026d71ae5a4SJacob Faibussowitsch { 202739accc25SStefano Zampini PetscInt ii; 202839accc25SStefano Zampini HYPRE_Int *i, *j; 202939accc25SStefano Zampini HYPRE_Complex *a; 2030c69f721fSFande Kong 2031c69f721fSFande Kong PetscFunctionBegin; 20323ba16761SJacob Faibussowitsch if (!hA) PetscFunctionReturn(PETSC_SUCCESS); 2033c69f721fSFande Kong 203439accc25SStefano Zampini i = hypre_CSRMatrixI(hA); 203539accc25SStefano Zampini j = hypre_CSRMatrixJ(hA); 2036c69f721fSFande Kong a = hypre_CSRMatrixData(hA); 2037a32e9c99SJunchao Zhang #if defined(PETSC_HAVE_HYPRE_DEVICE) 2038a32e9c99SJunchao Zhang if (HYPRE_MEMORY_DEVICE == hypre_CSRMatrixMemoryLocation(hA)) { 2039a32e9c99SJunchao Zhang #if defined(HYPRE_USING_CUDA) 2040a32e9c99SJunchao Zhang MatZeroRows_CUDA(N, rows, i, j, a, diag); 2041a32e9c99SJunchao Zhang #elif defined(HYPRE_USING_HIP) 2042a32e9c99SJunchao Zhang MatZeroRows_HIP(N, rows, i, j, a, diag); 2043a32e9c99SJunchao Zhang #elif defined(PETSC_HAVE_KOKKOS) 2044a32e9c99SJunchao Zhang MatZeroRows_Kokkos(N, rows, i, j, a, diag); 2045a32e9c99SJunchao Zhang #else 2046a32e9c99SJunchao Zhang SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for MatZeroRows on a hypre matrix in this memory location"); 2047a32e9c99SJunchao Zhang #endif 2048a32e9c99SJunchao Zhang } else 2049a32e9c99SJunchao Zhang #endif 2050a32e9c99SJunchao Zhang { 2051c69f721fSFande Kong for (ii = 0; ii < N; ii++) { 205239accc25SStefano Zampini HYPRE_Int jj, ibeg, iend, irow; 205339accc25SStefano Zampini 2054c69f721fSFande Kong irow = rows[ii]; 2055c69f721fSFande Kong ibeg = i[irow]; 2056c69f721fSFande Kong iend = i[irow + 1]; 2057c69f721fSFande Kong for (jj = ibeg; jj < iend; jj++) 2058c69f721fSFande Kong if (j[jj] == irow) a[jj] = diag; 2059c69f721fSFande Kong else a[jj] = 0.0; 2060c69f721fSFande Kong } 2061a32e9c99SJunchao Zhang } 20623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2063c69f721fSFande Kong } 2064c69f721fSFande Kong 2065d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_HYPRE(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 2066d71ae5a4SJacob Faibussowitsch { 2067c69f721fSFande Kong hypre_ParCSRMatrix *parcsr; 2068a32e9c99SJunchao Zhang PetscInt *lrows, len, *lrows2; 206939accc25SStefano Zampini HYPRE_Complex hdiag; 2070c69f721fSFande Kong 2071c69f721fSFande Kong PetscFunctionBegin; 207208401ef6SPierre Jolivet PetscCheck(!x && !b, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Does not support to modify the solution and the right hand size"); 20739566063dSJacob Faibussowitsch PetscCall(PetscHYPREScalarCast(diag, &hdiag)); 2074c69f721fSFande Kong /* retrieve the internal matrix */ 20759566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 2076c69f721fSFande Kong /* get locally owned rows */ 20779566063dSJacob Faibussowitsch PetscCall(MatZeroRowsMapLocal_Private(A, N, rows, &len, &lrows)); 2078a32e9c99SJunchao Zhang 2079a32e9c99SJunchao Zhang #if defined(PETSC_HAVE_HYPRE_DEVICE) 2080a32e9c99SJunchao Zhang if (HYPRE_MEMORY_DEVICE == hypre_CSRMatrixMemoryLocation(hypre_ParCSRMatrixDiag(parcsr))) { 2081a32e9c99SJunchao Zhang Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 2082a32e9c99SJunchao Zhang PetscInt m; 2083a32e9c99SJunchao Zhang PetscCall(MatGetLocalSize(A, &m, NULL)); 2084a32e9c99SJunchao Zhang if (!hA->rows_d) { 2085a32e9c99SJunchao Zhang hA->rows_d = hypre_TAlloc(PetscInt, m, HYPRE_MEMORY_DEVICE); 2086a32e9c99SJunchao Zhang if (m) PetscCheck(hA->rows_d, PETSC_COMM_SELF, PETSC_ERR_MEM, "HYPRE_TAlloc failed"); 2087a32e9c99SJunchao Zhang } 2088a32e9c99SJunchao Zhang PetscCheck(len <= m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Too many rows in rows[]"); 2089a32e9c99SJunchao Zhang PetscStackCallExternalVoid("hypre_Memcpy", hypre_Memcpy(hA->rows_d, lrows, sizeof(PetscInt) * len, HYPRE_MEMORY_DEVICE, HYPRE_MEMORY_HOST)); 2090a32e9c99SJunchao Zhang lrows2 = hA->rows_d; 2091a32e9c99SJunchao Zhang } else 2092a32e9c99SJunchao Zhang #endif 2093a32e9c99SJunchao Zhang { 2094a32e9c99SJunchao Zhang lrows2 = lrows; 2095a32e9c99SJunchao Zhang } 2096a32e9c99SJunchao Zhang 2097c69f721fSFande Kong /* zero diagonal part */ 2098a32e9c99SJunchao Zhang PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr), len, lrows2, hdiag)); 2099c69f721fSFande Kong /* zero off-diagonal part */ 2100a32e9c99SJunchao Zhang PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr), len, lrows2, 0.0)); 2101c69f721fSFande Kong 21029566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 21033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2104c69f721fSFande Kong } 2105c69f721fSFande Kong 2106d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_HYPRE(Mat mat, MatAssemblyType mode) 2107d71ae5a4SJacob Faibussowitsch { 2108c69f721fSFande Kong PetscFunctionBegin; 21093ba16761SJacob Faibussowitsch if (mat->nooffprocentries) PetscFunctionReturn(PETSC_SUCCESS); 2110c69f721fSFande Kong 21119566063dSJacob Faibussowitsch PetscCall(MatStashScatterBegin_Private(mat, &mat->stash, mat->rmap->range)); 21123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2113c69f721fSFande Kong } 2114c69f721fSFande Kong 2115d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) 2116d71ae5a4SJacob Faibussowitsch { 2117c69f721fSFande Kong hypre_ParCSRMatrix *parcsr; 21182cf14000SStefano Zampini HYPRE_Int hnz; 2119c69f721fSFande Kong 2120c69f721fSFande Kong PetscFunctionBegin; 2121c69f721fSFande Kong /* retrieve the internal matrix */ 21229566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 2123c69f721fSFande Kong /* call HYPRE API */ 2124792fecdfSBarry Smith PetscCallExternal(HYPRE_ParCSRMatrixGetRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v); 21252cf14000SStefano Zampini if (nz) *nz = (PetscInt)hnz; 21263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2127c69f721fSFande Kong } 2128c69f721fSFande Kong 2129d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) 2130d71ae5a4SJacob Faibussowitsch { 2131c69f721fSFande Kong hypre_ParCSRMatrix *parcsr; 21322cf14000SStefano Zampini HYPRE_Int hnz; 2133c69f721fSFande Kong 2134c69f721fSFande Kong PetscFunctionBegin; 2135c69f721fSFande Kong /* retrieve the internal matrix */ 21369566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 2137c69f721fSFande Kong /* call HYPRE API */ 21382cf14000SStefano Zampini hnz = nz ? (HYPRE_Int)(*nz) : 0; 2139792fecdfSBarry Smith PetscCallExternal(HYPRE_ParCSRMatrixRestoreRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v); 21403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2141c69f721fSFande Kong } 2142c69f721fSFande Kong 2143d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetValues_HYPRE(Mat A, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2144d71ae5a4SJacob Faibussowitsch { 214545b8d346SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 2146c69f721fSFande Kong PetscInt i; 21471d4906efSStefano Zampini 2148c69f721fSFande Kong PetscFunctionBegin; 21493ba16761SJacob Faibussowitsch if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2150c69f721fSFande Kong /* Ignore negative row indices 2151c69f721fSFande Kong * And negative column indices should be automatically ignored in hypre 2152c69f721fSFande Kong * */ 21532cf14000SStefano Zampini for (i = 0; i < m; i++) { 21542cf14000SStefano Zampini if (idxm[i] >= 0) { 21552cf14000SStefano Zampini HYPRE_Int hn = (HYPRE_Int)n; 2156792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetValues, hA->ij, 1, &hn, (HYPRE_BigInt *)&idxm[i], (HYPRE_BigInt *)idxn, (HYPRE_Complex *)(v + i * n)); 21572cf14000SStefano Zampini } 21582cf14000SStefano Zampini } 21593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2160c69f721fSFande Kong } 2161c69f721fSFande Kong 2162d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_HYPRE(Mat A, MatOption op, PetscBool flg) 2163d71ae5a4SJacob Faibussowitsch { 2164ddbeb582SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 2165ddbeb582SStefano Zampini 2166ddbeb582SStefano Zampini PetscFunctionBegin; 2167c6698e78SStefano Zampini switch (op) { 2168ddbeb582SStefano Zampini case MAT_NO_OFF_PROC_ENTRIES: 216948a46eb9SPierre Jolivet if (flg) PetscCallExternal(HYPRE_IJMatrixSetMaxOffProcElmts, hA->ij, 0); 2170ddbeb582SStefano Zampini break; 2171651b1cf9SStefano Zampini case MAT_IGNORE_OFF_PROC_ENTRIES: 2172651b1cf9SStefano Zampini hA->donotstash = flg; 2173d71ae5a4SJacob Faibussowitsch break; 2174d71ae5a4SJacob Faibussowitsch default: 2175d71ae5a4SJacob Faibussowitsch break; 2176ddbeb582SStefano Zampini } 21773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2178ddbeb582SStefano Zampini } 2179c69f721fSFande Kong 2180d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_HYPRE(Mat A, PetscViewer view) 2181d71ae5a4SJacob Faibussowitsch { 218245b8d346SStefano Zampini PetscViewerFormat format; 218345b8d346SStefano Zampini 218445b8d346SStefano Zampini PetscFunctionBegin; 21859566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(view, &format)); 21863ba16761SJacob Faibussowitsch if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(PETSC_SUCCESS); 218745b8d346SStefano Zampini if (format != PETSC_VIEWER_NATIVE) { 21886ea7df73SStefano Zampini Mat B; 21896ea7df73SStefano Zampini hypre_ParCSRMatrix *parcsr; 21906ea7df73SStefano Zampini PetscErrorCode (*mview)(Mat, PetscViewer) = NULL; 21916ea7df73SStefano Zampini 21929566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 21939566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(parcsr, MATAIJ, PETSC_USE_POINTER, &B)); 21949566063dSJacob Faibussowitsch PetscCall(MatGetOperation(B, MATOP_VIEW, (void (**)(void))&mview)); 219528b400f6SJacob Faibussowitsch PetscCheck(mview, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Missing view operation"); 21969566063dSJacob Faibussowitsch PetscCall((*mview)(B, view)); 21979566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 219845b8d346SStefano Zampini } else { 219945b8d346SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 220045b8d346SStefano Zampini PetscMPIInt size; 220145b8d346SStefano Zampini PetscBool isascii; 220245b8d346SStefano Zampini const char *filename; 220345b8d346SStefano Zampini 220445b8d346SStefano Zampini /* HYPRE uses only text files */ 22059566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERASCII, &isascii)); 220628b400f6SJacob Faibussowitsch PetscCheck(isascii, PetscObjectComm((PetscObject)view), PETSC_ERR_SUP, "PetscViewerType %s: native HYPRE format needs PETSCVIEWERASCII", ((PetscObject)view)->type_name); 22079566063dSJacob Faibussowitsch PetscCall(PetscViewerFileGetName(view, &filename)); 2208792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixPrint, hA->ij, filename); 22099566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(hA->comm, &size)); 221045b8d346SStefano Zampini if (size > 1) { 22119566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(view, "Matrix files: %s.%05d ... %s.%05d\n", filename, 0, filename, size - 1)); 221245b8d346SStefano Zampini } else { 22139566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(view, "Matrix file: %s.%05d\n", filename, 0)); 221445b8d346SStefano Zampini } 221545b8d346SStefano Zampini } 22163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 221745b8d346SStefano Zampini } 221845b8d346SStefano Zampini 2219d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCopy_HYPRE(Mat A, Mat B, MatStructure str) 2220d71ae5a4SJacob Faibussowitsch { 2221465edc17SStefano Zampini hypre_ParCSRMatrix *acsr, *bcsr; 2222465edc17SStefano Zampini 2223465edc17SStefano Zampini PetscFunctionBegin; 2224465edc17SStefano Zampini if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) { 22259566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &acsr)); 22269566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(B, &bcsr)); 2227792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixCopy, acsr, bcsr, 1); 22289566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_SORTED_FULL, PETSC_TRUE)); /* "perfect" preallocation, so no need for hypre_AuxParCSRMatrixNeedAux */ 22299566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 22309566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 2231465edc17SStefano Zampini } else { 22329566063dSJacob Faibussowitsch PetscCall(MatCopy_Basic(A, B, str)); 2233465edc17SStefano Zampini } 22343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2235465edc17SStefano Zampini } 2236465edc17SStefano Zampini 2237d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_HYPRE(Mat A, Vec d) 2238d71ae5a4SJacob Faibussowitsch { 22396305df00SStefano Zampini hypre_ParCSRMatrix *parcsr; 22406305df00SStefano Zampini hypre_CSRMatrix *dmat; 224139accc25SStefano Zampini HYPRE_Complex *a; 22426305df00SStefano Zampini PetscBool cong; 22436305df00SStefano Zampini 22446305df00SStefano Zampini PetscFunctionBegin; 22459566063dSJacob Faibussowitsch PetscCall(MatHasCongruentLayouts(A, &cong)); 224628b400f6SJacob Faibussowitsch PetscCheck(cong, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only for square matrices with same local distributions of rows and columns"); 22479566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 22486305df00SStefano Zampini dmat = hypre_ParCSRMatrixDiag(parcsr); 22496305df00SStefano Zampini if (dmat) { 225006977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 225106977982Sstefanozampini HYPRE_MemoryLocation mem = hypre_CSRMatrixMemoryLocation(dmat); 225206977982Sstefanozampini #else 225306977982Sstefanozampini HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST; 225406977982Sstefanozampini #endif 225506977982Sstefanozampini 225606977982Sstefanozampini if (mem != HYPRE_MEMORY_HOST) PetscCall(VecGetArrayWriteAndMemType(d, (PetscScalar **)&a, NULL)); 225706977982Sstefanozampini else PetscCall(VecGetArrayWrite(d, (PetscScalar **)&a)); 225806977982Sstefanozampini hypre_CSRMatrixExtractDiagonal(dmat, a, 0); 225906977982Sstefanozampini if (mem != HYPRE_MEMORY_HOST) PetscCall(VecRestoreArrayWriteAndMemType(d, (PetscScalar **)&a)); 226006977982Sstefanozampini else PetscCall(VecRestoreArrayWrite(d, (PetscScalar **)&a)); 22616305df00SStefano Zampini } 22623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22636305df00SStefano Zampini } 22646305df00SStefano Zampini 2265363d496dSStefano Zampini #include <petscblaslapack.h> 2266363d496dSStefano Zampini 2267d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAXPY_HYPRE(Mat Y, PetscScalar a, Mat X, MatStructure str) 2268d71ae5a4SJacob Faibussowitsch { 2269363d496dSStefano Zampini PetscFunctionBegin; 22706ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 22716ea7df73SStefano Zampini { 22726ea7df73SStefano Zampini Mat B; 22736ea7df73SStefano Zampini hypre_ParCSRMatrix *x, *y, *z; 22746ea7df73SStefano Zampini 22759566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR(Y, &y)); 22769566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR(X, &x)); 2277792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixAdd, 1.0, y, 1.0, x, &z); 22789566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(z, MATHYPRE, PETSC_OWN_POINTER, &B)); 22799566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(Y, &B)); 22806ea7df73SStefano Zampini } 22816ea7df73SStefano Zampini #else 2282363d496dSStefano Zampini if (str == SAME_NONZERO_PATTERN) { 2283363d496dSStefano Zampini hypre_ParCSRMatrix *x, *y; 2284363d496dSStefano Zampini hypre_CSRMatrix *xloc, *yloc; 2285363d496dSStefano Zampini PetscInt xnnz, ynnz; 228639accc25SStefano Zampini HYPRE_Complex *xarr, *yarr; 2287363d496dSStefano Zampini PetscBLASInt one = 1, bnz; 2288363d496dSStefano Zampini 22899566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR(Y, &y)); 22909566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR(X, &x)); 2291363d496dSStefano Zampini 2292363d496dSStefano Zampini /* diagonal block */ 2293363d496dSStefano Zampini xloc = hypre_ParCSRMatrixDiag(x); 2294363d496dSStefano Zampini yloc = hypre_ParCSRMatrixDiag(y); 2295363d496dSStefano Zampini xnnz = 0; 2296363d496dSStefano Zampini ynnz = 0; 2297363d496dSStefano Zampini xarr = NULL; 2298363d496dSStefano Zampini yarr = NULL; 2299363d496dSStefano Zampini if (xloc) { 230039accc25SStefano Zampini xarr = hypre_CSRMatrixData(xloc); 2301363d496dSStefano Zampini xnnz = hypre_CSRMatrixNumNonzeros(xloc); 2302363d496dSStefano Zampini } 2303363d496dSStefano Zampini if (yloc) { 230439accc25SStefano Zampini yarr = hypre_CSRMatrixData(yloc); 2305363d496dSStefano Zampini ynnz = hypre_CSRMatrixNumNonzeros(yloc); 2306363d496dSStefano Zampini } 230708401ef6SPierre Jolivet PetscCheck(xnnz == ynnz, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Different number of nonzeros in diagonal block %" PetscInt_FMT " != %" PetscInt_FMT, xnnz, ynnz); 23089566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(xnnz, &bnz)); 2309792fecdfSBarry Smith PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one)); 2310363d496dSStefano Zampini 2311363d496dSStefano Zampini /* off-diagonal block */ 2312363d496dSStefano Zampini xloc = hypre_ParCSRMatrixOffd(x); 2313363d496dSStefano Zampini yloc = hypre_ParCSRMatrixOffd(y); 2314363d496dSStefano Zampini xnnz = 0; 2315363d496dSStefano Zampini ynnz = 0; 2316363d496dSStefano Zampini xarr = NULL; 2317363d496dSStefano Zampini yarr = NULL; 2318363d496dSStefano Zampini if (xloc) { 231939accc25SStefano Zampini xarr = hypre_CSRMatrixData(xloc); 2320363d496dSStefano Zampini xnnz = hypre_CSRMatrixNumNonzeros(xloc); 2321363d496dSStefano Zampini } 2322363d496dSStefano Zampini if (yloc) { 232339accc25SStefano Zampini yarr = hypre_CSRMatrixData(yloc); 2324363d496dSStefano Zampini ynnz = hypre_CSRMatrixNumNonzeros(yloc); 2325363d496dSStefano Zampini } 232608401ef6SPierre 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); 23279566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(xnnz, &bnz)); 2328792fecdfSBarry Smith PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one)); 2329363d496dSStefano Zampini } else if (str == SUBSET_NONZERO_PATTERN) { 23309566063dSJacob Faibussowitsch PetscCall(MatAXPY_Basic(Y, a, X, str)); 2331363d496dSStefano Zampini } else { 2332363d496dSStefano Zampini Mat B; 2333363d496dSStefano Zampini 23349566063dSJacob Faibussowitsch PetscCall(MatAXPY_Basic_Preallocate(Y, X, &B)); 23359566063dSJacob Faibussowitsch PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str)); 23369566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(Y, &B)); 2337363d496dSStefano Zampini } 23386ea7df73SStefano Zampini #endif 23393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2340363d496dSStefano Zampini } 2341363d496dSStefano Zampini 23422c4ab24aSJunchao Zhang static PetscErrorCode MatDuplicate_HYPRE(Mat A, MatDuplicateOption op, Mat *B) 23432c4ab24aSJunchao Zhang { 23442c4ab24aSJunchao Zhang hypre_ParCSRMatrix *parcsr = NULL; 23452c4ab24aSJunchao Zhang PetscCopyMode cpmode; 23462c4ab24aSJunchao Zhang Mat_HYPRE *hA; 23472c4ab24aSJunchao Zhang 23482c4ab24aSJunchao Zhang PetscFunctionBegin; 23492c4ab24aSJunchao Zhang PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 23502c4ab24aSJunchao Zhang if (op == MAT_DO_NOT_COPY_VALUES || op == MAT_SHARE_NONZERO_PATTERN) { 23512c4ab24aSJunchao Zhang parcsr = hypre_ParCSRMatrixClone(parcsr, 0); 23522c4ab24aSJunchao Zhang cpmode = PETSC_OWN_POINTER; 23532c4ab24aSJunchao Zhang } else { 23542c4ab24aSJunchao Zhang cpmode = PETSC_COPY_VALUES; 23552c4ab24aSJunchao Zhang } 23562c4ab24aSJunchao Zhang PetscCall(MatCreateFromParCSR(parcsr, MATHYPRE, cpmode, B)); 23572c4ab24aSJunchao Zhang hA = (Mat_HYPRE *)A->data; 23582c4ab24aSJunchao Zhang if (hA->cooMat) { 235906977982Sstefanozampini Mat_HYPRE *hB = (Mat_HYPRE *)((*B)->data); 2360b73e3080SStefano Zampini op = (op == MAT_DO_NOT_COPY_VALUES) ? op : MAT_COPY_VALUES; 2361b73e3080SStefano Zampini /* Cannot simply increase the reference count of hA->cooMat, since B needs to share cooMat's data array */ 236206977982Sstefanozampini PetscCall(MatDuplicate(hA->cooMat, op, &hB->cooMat)); 236306977982Sstefanozampini PetscCall(MatHYPRE_AttachCOOMat(*B)); 23642c4ab24aSJunchao Zhang } 23652c4ab24aSJunchao Zhang PetscFunctionReturn(PETSC_SUCCESS); 23662c4ab24aSJunchao Zhang } 23672c4ab24aSJunchao Zhang 2368d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetPreallocationCOO_HYPRE(Mat mat, PetscCount coo_n, PetscInt coo_i[], PetscInt coo_j[]) 2369d71ae5a4SJacob Faibussowitsch { 237006977982Sstefanozampini Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data; 23715fbaff96SJunchao Zhang 23725fbaff96SJunchao Zhang PetscFunctionBegin; 2373651b1cf9SStefano Zampini /* Build an agent matrix cooMat with AIJ format 23745fbaff96SJunchao 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. 23755fbaff96SJunchao Zhang */ 237606977982Sstefanozampini PetscCall(MatHYPRE_CreateCOOMat(mat)); 237706977982Sstefanozampini PetscCall(MatSetOption(hmat->cooMat, MAT_IGNORE_OFF_PROC_ENTRIES, hmat->donotstash)); 237806977982Sstefanozampini PetscCall(MatSetOption(hmat->cooMat, MAT_NO_OFF_PROC_ENTRIES, mat->nooffprocentries)); 2379651b1cf9SStefano Zampini 2380651b1cf9SStefano Zampini /* MatSetPreallocationCOO_SeqAIJ and MatSetPreallocationCOO_MPIAIJ uses this specific 2381651b1cf9SStefano Zampini name to automatically put the diagonal entries first */ 238206977982Sstefanozampini PetscCall(PetscObjectSetName((PetscObject)hmat->cooMat, "_internal_COO_mat_for_hypre")); 238306977982Sstefanozampini PetscCall(MatSetPreallocationCOO(hmat->cooMat, coo_n, coo_i, coo_j)); 238406977982Sstefanozampini hmat->cooMat->assembled = PETSC_TRUE; 23855fbaff96SJunchao Zhang 23865fbaff96SJunchao Zhang /* Copy the sparsity pattern from cooMat to hypre IJMatrix hmat->ij */ 23875fbaff96SJunchao Zhang PetscCall(MatSetOption(mat, MAT_SORTED_FULL, PETSC_TRUE)); 238806977982Sstefanozampini PetscCall(MatHYPRE_CreateFromMat(hmat->cooMat, hmat)); /* Create hmat->ij and preallocate it */ 238906977982Sstefanozampini PetscCall(MatHYPRE_IJMatrixCopyIJ(hmat->cooMat, hmat->ij)); /* Copy A's (i,j) to hmat->ij */ 23905fbaff96SJunchao Zhang 23915fbaff96SJunchao Zhang mat->preallocated = PETSC_TRUE; 23925fbaff96SJunchao Zhang PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 23935fbaff96SJunchao Zhang PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); /* Migrate mat to device if it is bound to. Hypre builds its own SpMV context here */ 23945fbaff96SJunchao Zhang 23952c4ab24aSJunchao Zhang /* Attach cooMat to mat */ 239606977982Sstefanozampini PetscCall(MatHYPRE_AttachCOOMat(mat)); 23973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23985fbaff96SJunchao Zhang } 23995fbaff96SJunchao Zhang 2400d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesCOO_HYPRE(Mat mat, const PetscScalar v[], InsertMode imode) 2401d71ae5a4SJacob Faibussowitsch { 24025fbaff96SJunchao Zhang Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data; 24035fbaff96SJunchao Zhang 24045fbaff96SJunchao Zhang PetscFunctionBegin; 2405b73e3080SStefano Zampini PetscCheck(hmat->cooMat, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet"); 24065fbaff96SJunchao Zhang PetscCall(MatSetValuesCOO(hmat->cooMat, v, imode)); 2407651b1cf9SStefano Zampini PetscCall(MatViewFromOptions(hmat->cooMat, (PetscObject)mat, "-cooMat_view")); 24083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24095fbaff96SJunchao Zhang } 24105fbaff96SJunchao Zhang 241103db1824SAlex Lindsay static PetscErrorCode MatGetCurrentMemType_HYPRE(Mat A, PetscMemType *m) 241203db1824SAlex Lindsay { 241303db1824SAlex Lindsay PetscBool petsconcpu; 241403db1824SAlex Lindsay 241503db1824SAlex Lindsay PetscFunctionBegin; 241603db1824SAlex Lindsay PetscCall(MatBoundToCPU(A, &petsconcpu)); 241703db1824SAlex Lindsay *m = petsconcpu ? PETSC_MEMTYPE_HOST : PETSC_MEMTYPE_DEVICE; 241803db1824SAlex Lindsay PetscFunctionReturn(PETSC_SUCCESS); 241903db1824SAlex Lindsay } 242003db1824SAlex Lindsay 2421a055b5aaSBarry Smith /*MC 24222ef1f0ffSBarry Smith MATHYPRE - "hypre" - A matrix type to be used for sequential and parallel sparse matrices 2423a055b5aaSBarry Smith based on the hypre IJ interface. 2424a055b5aaSBarry Smith 2425a055b5aaSBarry Smith Level: intermediate 2426a055b5aaSBarry Smith 24271cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatHYPRESetPreallocation` 2428a055b5aaSBarry Smith M*/ 2429d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_HYPRE(Mat B) 2430d71ae5a4SJacob Faibussowitsch { 243163c07aadSStefano Zampini Mat_HYPRE *hB; 2432a9e6c71bSAlex Lindsay #if defined(PETSC_HAVE_HYPRE_DEVICE) 2433a9e6c71bSAlex Lindsay HYPRE_MemoryLocation memory_location; 2434a9e6c71bSAlex Lindsay #endif 243563c07aadSStefano Zampini 243663c07aadSStefano Zampini PetscFunctionBegin; 2437a9e6c71bSAlex Lindsay PetscHYPREInitialize(); 24384dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&hB)); 24396ea7df73SStefano Zampini 2440978814f1SStefano Zampini hB->inner_free = PETSC_TRUE; 2441651b1cf9SStefano Zampini hB->array_available = PETSC_TRUE; 2442978814f1SStefano Zampini 244363c07aadSStefano Zampini B->data = (void *)hB; 244463c07aadSStefano Zampini 24459566063dSJacob Faibussowitsch PetscCall(PetscMemzero(B->ops, sizeof(struct _MatOps))); 244663c07aadSStefano Zampini B->ops->mult = MatMult_HYPRE; 244763c07aadSStefano Zampini B->ops->multtranspose = MatMultTranspose_HYPRE; 2448414bd5c3SStefano Zampini B->ops->multadd = MatMultAdd_HYPRE; 2449414bd5c3SStefano Zampini B->ops->multtransposeadd = MatMultTransposeAdd_HYPRE; 245063c07aadSStefano Zampini B->ops->setup = MatSetUp_HYPRE; 245163c07aadSStefano Zampini B->ops->destroy = MatDestroy_HYPRE; 245263c07aadSStefano Zampini B->ops->assemblyend = MatAssemblyEnd_HYPRE; 2453c69f721fSFande Kong B->ops->assemblybegin = MatAssemblyBegin_HYPRE; 2454d975228cSstefano_zampini B->ops->setvalues = MatSetValues_HYPRE; 245568ec7858SStefano Zampini B->ops->missingdiagonal = MatMissingDiagonal_HYPRE; 245668ec7858SStefano Zampini B->ops->scale = MatScale_HYPRE; 245768ec7858SStefano Zampini B->ops->zerorowscolumns = MatZeroRowsColumns_HYPRE; 2458c69f721fSFande Kong B->ops->zeroentries = MatZeroEntries_HYPRE; 2459c69f721fSFande Kong B->ops->zerorows = MatZeroRows_HYPRE; 2460c69f721fSFande Kong B->ops->getrow = MatGetRow_HYPRE; 2461c69f721fSFande Kong B->ops->restorerow = MatRestoreRow_HYPRE; 2462c69f721fSFande Kong B->ops->getvalues = MatGetValues_HYPRE; 2463ddbeb582SStefano Zampini B->ops->setoption = MatSetOption_HYPRE; 246445b8d346SStefano Zampini B->ops->duplicate = MatDuplicate_HYPRE; 2465465edc17SStefano Zampini B->ops->copy = MatCopy_HYPRE; 246645b8d346SStefano Zampini B->ops->view = MatView_HYPRE; 24676305df00SStefano Zampini B->ops->getdiagonal = MatGetDiagonal_HYPRE; 2468363d496dSStefano Zampini B->ops->axpy = MatAXPY_HYPRE; 24694222ddf1SHong Zhang B->ops->productsetfromoptions = MatProductSetFromOptions_HYPRE; 247003db1824SAlex Lindsay B->ops->getcurrentmemtype = MatGetCurrentMemType_HYPRE; 24716ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 24726ea7df73SStefano Zampini B->ops->bindtocpu = MatBindToCPU_HYPRE; 2473a9e6c71bSAlex Lindsay /* Get hypre's default memory location. Users can control this using the corresponding HYPRE_SetMemoryLocation API */ 2474a9e6c71bSAlex Lindsay PetscCallExternal(HYPRE_GetMemoryLocation, &memory_location); 2475a9e6c71bSAlex Lindsay B->boundtocpu = (memory_location == HYPRE_MEMORY_HOST) ? PETSC_TRUE : PETSC_FALSE; 24766ea7df73SStefano Zampini #endif 247745b8d346SStefano Zampini 247845b8d346SStefano Zampini /* build cache for off array entries formed */ 24799566063dSJacob Faibussowitsch PetscCall(MatStashCreate_Private(PetscObjectComm((PetscObject)B), 1, &B->stash)); 248063c07aadSStefano Zampini 24819566063dSJacob Faibussowitsch PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)B), &hB->comm)); 24829566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRE)); 24839566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_aij_C", MatConvert_HYPRE_AIJ)); 24849566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_is_C", MatConvert_HYPRE_IS)); 24859566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_hypre_C", MatProductSetFromOptions_HYPRE)); 24869566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaij_hypre_C", MatProductSetFromOptions_HYPRE)); 24879566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPRESetPreallocation_C", MatHYPRESetPreallocation_HYPRE)); 24889566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPREGetParCSR_C", MatHYPREGetParCSR_HYPRE)); 24895fbaff96SJunchao Zhang PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_HYPRE)); 24905fbaff96SJunchao Zhang PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetValuesCOO_C", MatSetValuesCOO_HYPRE)); 24916ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 24926ea7df73SStefano Zampini #if defined(HYPRE_USING_HIP) 249306977982Sstefanozampini PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijhipsparse_hypre_C", MatProductSetFromOptions_HYPRE)); 249406977982Sstefanozampini PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaijhipsparse_hypre_C", MatProductSetFromOptions_HYPRE)); 24959566063dSJacob Faibussowitsch PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP)); 24969566063dSJacob Faibussowitsch PetscCall(MatSetVecType(B, VECHIP)); 24976ea7df73SStefano Zampini #endif 24986ea7df73SStefano Zampini #if defined(HYPRE_USING_CUDA) 249906977982Sstefanozampini PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijcusparse_hypre_C", MatProductSetFromOptions_HYPRE)); 250006977982Sstefanozampini PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaijcusparse_hypre_C", MatProductSetFromOptions_HYPRE)); 25019566063dSJacob Faibussowitsch PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA)); 25029566063dSJacob Faibussowitsch PetscCall(MatSetVecType(B, VECCUDA)); 25036ea7df73SStefano Zampini #endif 25046ea7df73SStefano Zampini #endif 25053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 250663c07aadSStefano Zampini } 2507