163c07aadSStefano Zampini 263c07aadSStefano Zampini /* 363c07aadSStefano Zampini Creates hypre ijmatrix from PETSc matrix 463c07aadSStefano Zampini */ 5225daaf8SStefano Zampini 6c6698e78SStefano Zampini #include <petscpkg_version.h> 739accc25SStefano Zampini #include <petsc/private/petschypre.h> 8dd9c0a25Sstefano_zampini #include <petscmathypre.h> 963c07aadSStefano Zampini #include <petsc/private/matimpl.h> 10a4af0ceeSJacob Faibussowitsch #include <petsc/private/deviceimpl.h> 1163c07aadSStefano Zampini #include <../src/mat/impls/hypre/mhypre.h> 1263c07aadSStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h> 1358968eb6SStefano Zampini #include <../src/vec/vec/impls/hypre/vhyp.h> 1458968eb6SStefano Zampini #include <HYPRE.h> 15c1a070e6SStefano Zampini #include <HYPRE_utilities.h> 16cd8bc7baSStefano Zampini #include <_hypre_parcsr_ls.h> 1768ec7858SStefano Zampini #include <_hypre_sstruct_ls.h> 1863c07aadSStefano Zampini 190e6427aaSSatish Balay #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0) 200e6427aaSSatish Balay #define hypre_ParCSRMatrixClone(A, B) hypre_ParCSRMatrixCompleteClone(A) 210e6427aaSSatish Balay #endif 220e6427aaSSatish Balay 2363c07aadSStefano Zampini static PetscErrorCode MatHYPRE_CreateFromMat(Mat, Mat_HYPRE *); 2463c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat, Mat, HYPRE_IJMatrix); 25b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_MPIAIJ(Mat, HYPRE_IJMatrix); 26b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_SeqAIJ(Mat, HYPRE_IJMatrix); 2739accc25SStefano Zampini static PetscErrorCode MatHYPRE_MultKernel_Private(Mat, HYPRE_Complex, Vec, HYPRE_Complex, Vec, PetscBool); 28225daaf8SStefano Zampini static PetscErrorCode hypre_array_destroy(void *); 296ea7df73SStefano Zampini static PetscErrorCode MatSetValues_HYPRE(Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[], const PetscScalar[], InsertMode ins); 3063c07aadSStefano Zampini 31d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat A_d, Mat A_o, HYPRE_IJMatrix ij) 32d71ae5a4SJacob Faibussowitsch { 3363c07aadSStefano Zampini PetscInt i, n_d, n_o; 3463c07aadSStefano Zampini const PetscInt *ia_d, *ia_o; 3563c07aadSStefano Zampini PetscBool done_d = PETSC_FALSE, done_o = PETSC_FALSE; 362cf14000SStefano Zampini HYPRE_Int *nnz_d = NULL, *nnz_o = NULL; 3763c07aadSStefano Zampini 3863c07aadSStefano Zampini PetscFunctionBegin; 3963c07aadSStefano Zampini if (A_d) { /* determine number of nonzero entries in local diagonal part */ 409566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A_d, 0, PETSC_FALSE, PETSC_FALSE, &n_d, &ia_d, NULL, &done_d)); 4163c07aadSStefano Zampini if (done_d) { 429566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_d, &nnz_d)); 43ad540459SPierre Jolivet for (i = 0; i < n_d; i++) nnz_d[i] = ia_d[i + 1] - ia_d[i]; 4463c07aadSStefano Zampini } 459566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A_d, 0, PETSC_FALSE, PETSC_FALSE, NULL, &ia_d, NULL, &done_d)); 4663c07aadSStefano Zampini } 4763c07aadSStefano Zampini if (A_o) { /* determine number of nonzero entries in local off-diagonal part */ 489566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A_o, 0, PETSC_FALSE, PETSC_FALSE, &n_o, &ia_o, NULL, &done_o)); 4963c07aadSStefano Zampini if (done_o) { 509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_o, &nnz_o)); 51ad540459SPierre Jolivet for (i = 0; i < n_o; i++) nnz_o[i] = ia_o[i + 1] - ia_o[i]; 5263c07aadSStefano Zampini } 539566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A_o, 0, PETSC_FALSE, PETSC_FALSE, &n_o, &ia_o, NULL, &done_o)); 5463c07aadSStefano Zampini } 5563c07aadSStefano Zampini if (done_d) { /* set number of nonzeros in HYPRE IJ matrix */ 5663c07aadSStefano Zampini if (!done_o) { /* only diagonal part */ 579566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n_d, &nnz_o)); 5863c07aadSStefano Zampini } 59c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0) 60c6698e78SStefano Zampini { /* If we don't do this, the columns of the matrix will be all zeros! */ 61c6698e78SStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 62c6698e78SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij); 63c6698e78SStefano Zampini hypre_AuxParCSRMatrixDestroy(aux_matrix); 64c6698e78SStefano Zampini hypre_IJMatrixTranslator(ij) = NULL; 65792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, ij, nnz_d, nnz_o); 6622235d61SPierre Jolivet /* it seems they partially fixed it in 2.19.0 */ 6722235d61SPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 68c6698e78SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij); 69c6698e78SStefano Zampini hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1; 7022235d61SPierre Jolivet #endif 71c6698e78SStefano Zampini } 72c6698e78SStefano Zampini #else 73792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, ij, nnz_d, nnz_o); 74c6698e78SStefano Zampini #endif 759566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz_d)); 769566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz_o)); 7763c07aadSStefano Zampini } 783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7963c07aadSStefano Zampini } 8063c07aadSStefano Zampini 81d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_CreateFromMat(Mat A, Mat_HYPRE *hA) 82d71ae5a4SJacob Faibussowitsch { 8363c07aadSStefano Zampini PetscInt rstart, rend, cstart, cend; 8463c07aadSStefano Zampini 8563c07aadSStefano Zampini PetscFunctionBegin; 869566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 879566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 8863c07aadSStefano Zampini rstart = A->rmap->rstart; 8963c07aadSStefano Zampini rend = A->rmap->rend; 9063c07aadSStefano Zampini cstart = A->cmap->rstart; 9163c07aadSStefano Zampini cend = A->cmap->rend; 92ea9ee2c1SPierre Jolivet PetscHYPREInitialize(); 93*651b1cf9SStefano Zampini if (hA->ij) { 94*651b1cf9SStefano Zampini if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL; 95*651b1cf9SStefano Zampini PetscCallExternal(HYPRE_IJMatrixDestroy, hA->ij); 96*651b1cf9SStefano Zampini } 97792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rstart, rend - 1, cstart, cend - 1, &hA->ij); 98792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR); 9963c07aadSStefano Zampini { 10063c07aadSStefano Zampini PetscBool same; 10163c07aadSStefano Zampini Mat A_d, A_o; 10263c07aadSStefano Zampini const PetscInt *colmap; 1039566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &same)); 10463c07aadSStefano Zampini if (same) { 1059566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(A, &A_d, &A_o, &colmap)); 1069566063dSJacob Faibussowitsch PetscCall(MatHYPRE_IJMatrixPreallocate(A_d, A_o, hA->ij)); 1073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10863c07aadSStefano Zampini } 1099566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIBAIJ, &same)); 11063c07aadSStefano Zampini if (same) { 1119566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJGetSeqBAIJ(A, &A_d, &A_o, &colmap)); 1129566063dSJacob Faibussowitsch PetscCall(MatHYPRE_IJMatrixPreallocate(A_d, A_o, hA->ij)); 1133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11463c07aadSStefano Zampini } 1159566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &same)); 11663c07aadSStefano Zampini if (same) { 1179566063dSJacob Faibussowitsch PetscCall(MatHYPRE_IJMatrixPreallocate(A, NULL, hA->ij)); 1183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11963c07aadSStefano Zampini } 1209566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQBAIJ, &same)); 12163c07aadSStefano Zampini if (same) { 1229566063dSJacob Faibussowitsch PetscCall(MatHYPRE_IJMatrixPreallocate(A, NULL, hA->ij)); 1233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12463c07aadSStefano Zampini } 12563c07aadSStefano Zampini } 1263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12763c07aadSStefano Zampini } 12863c07aadSStefano Zampini 129b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ(Mat A, HYPRE_IJMatrix ij) 130d71ae5a4SJacob Faibussowitsch { 13163c07aadSStefano Zampini PetscBool flg; 13263c07aadSStefano Zampini 13363c07aadSStefano Zampini PetscFunctionBegin; 1346ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 135792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize, ij); 1366ea7df73SStefano Zampini #else 137792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize_v2, ij, HYPRE_MEMORY_HOST); 1386ea7df73SStefano Zampini #endif 1399566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &flg)); 140b73e3080SStefano Zampini if (flg) { 141b73e3080SStefano Zampini PetscCall(MatHYPRE_IJMatrixCopyIJ_MPIAIJ(A, ij)); 1423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14363c07aadSStefano Zampini } 1449566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &flg)); 14563c07aadSStefano Zampini if (flg) { 146b73e3080SStefano Zampini PetscCall(MatHYPRE_IJMatrixCopyIJ_SeqAIJ(A, ij)); 1473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14863c07aadSStefano Zampini } 149b73e3080SStefano Zampini PetscCheck(PETSC_FALSE, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "No support for matrix type %s", ((PetscObject)A)->type_name); 15063c07aadSStefano Zampini } 15163c07aadSStefano Zampini 152b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_SeqAIJ(Mat A, HYPRE_IJMatrix ij) 153d71ae5a4SJacob Faibussowitsch { 15463c07aadSStefano Zampini Mat_SeqAIJ *pdiag = (Mat_SeqAIJ *)A->data; 15558968eb6SStefano Zampini HYPRE_Int type; 15663c07aadSStefano Zampini hypre_ParCSRMatrix *par_matrix; 15763c07aadSStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 15863c07aadSStefano Zampini hypre_CSRMatrix *hdiag; 1592cf14000SStefano Zampini PetscBool sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int)); 16063c07aadSStefano Zampini 16163c07aadSStefano Zampini PetscFunctionBegin; 162792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type); 16308401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 164792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix); 16563c07aadSStefano Zampini hdiag = hypre_ParCSRMatrixDiag(par_matrix); 16663c07aadSStefano Zampini /* 16763c07aadSStefano Zampini this is the Hack part where we monkey directly with the hypre datastructures 16863c07aadSStefano Zampini */ 1692cf14000SStefano Zampini if (sameint) { 1709566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hdiag->i, pdiag->i, A->rmap->n + 1)); 1719566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hdiag->j, pdiag->j, pdiag->nz)); 1722cf14000SStefano Zampini } else { 1732cf14000SStefano Zampini PetscInt i; 1742cf14000SStefano Zampini 1752cf14000SStefano Zampini for (i = 0; i < A->rmap->n + 1; i++) hdiag->i[i] = (HYPRE_Int)pdiag->i[i]; 1762cf14000SStefano Zampini for (i = 0; i < pdiag->nz; i++) hdiag->j[i] = (HYPRE_Int)pdiag->j[i]; 1772cf14000SStefano Zampini } 1786ea7df73SStefano Zampini 179ea9daf28SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij); 18063c07aadSStefano Zampini hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0; 1813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18263c07aadSStefano Zampini } 18363c07aadSStefano Zampini 184b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_MPIAIJ(Mat A, HYPRE_IJMatrix ij) 185d71ae5a4SJacob Faibussowitsch { 18663c07aadSStefano Zampini Mat_MPIAIJ *pA = (Mat_MPIAIJ *)A->data; 18763c07aadSStefano Zampini Mat_SeqAIJ *pdiag, *poffd; 18863c07aadSStefano Zampini PetscInt i, *garray = pA->garray, *jj, cstart, *pjj; 1892cf14000SStefano Zampini HYPRE_Int *hjj, type; 19063c07aadSStefano Zampini hypre_ParCSRMatrix *par_matrix; 19163c07aadSStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 19263c07aadSStefano Zampini hypre_CSRMatrix *hdiag, *hoffd; 1932cf14000SStefano Zampini PetscBool sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int)); 19463c07aadSStefano Zampini 19563c07aadSStefano Zampini PetscFunctionBegin; 19663c07aadSStefano Zampini pdiag = (Mat_SeqAIJ *)pA->A->data; 19763c07aadSStefano Zampini poffd = (Mat_SeqAIJ *)pA->B->data; 198da81f932SPierre Jolivet /* cstart is only valid for square MPIAIJ laid out in the usual way */ 1999566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &cstart, NULL)); 20063c07aadSStefano Zampini 201792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type); 20208401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 203792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix); 20463c07aadSStefano Zampini hdiag = hypre_ParCSRMatrixDiag(par_matrix); 20563c07aadSStefano Zampini hoffd = hypre_ParCSRMatrixOffd(par_matrix); 20663c07aadSStefano Zampini 2072cf14000SStefano Zampini if (sameint) { 2089566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hdiag->i, pdiag->i, pA->A->rmap->n + 1)); 2092cf14000SStefano Zampini } else { 2102cf14000SStefano Zampini for (i = 0; i < pA->A->rmap->n + 1; i++) hdiag->i[i] = (HYPRE_Int)(pdiag->i[i]); 2112cf14000SStefano Zampini } 212b73e3080SStefano Zampini 2132cf14000SStefano Zampini hjj = hdiag->j; 2142cf14000SStefano Zampini pjj = pdiag->j; 215c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0) 2162cf14000SStefano Zampini for (i = 0; i < pdiag->nz; i++) hjj[i] = pjj[i]; 217c6698e78SStefano Zampini #else 2182cf14000SStefano Zampini for (i = 0; i < pdiag->nz; i++) hjj[i] = cstart + pjj[i]; 219c6698e78SStefano Zampini #endif 2202cf14000SStefano Zampini if (sameint) { 2219566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hoffd->i, poffd->i, pA->A->rmap->n + 1)); 2222cf14000SStefano Zampini } else { 2232cf14000SStefano Zampini for (i = 0; i < pA->A->rmap->n + 1; i++) hoffd->i[i] = (HYPRE_Int)(poffd->i[i]); 2242cf14000SStefano Zampini } 2252cf14000SStefano Zampini 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 #else 23063c07aadSStefano Zampini jj = (PetscInt *)hoffd->j; 231c6698e78SStefano Zampini #endif 2322cf14000SStefano Zampini pjj = poffd->j; 23363c07aadSStefano Zampini for (i = 0; i < poffd->nz; i++) jj[i] = garray[pjj[i]]; 234c6698e78SStefano Zampini 235ea9daf28SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij); 23663c07aadSStefano Zampini hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0; 2373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23863c07aadSStefano Zampini } 23963c07aadSStefano Zampini 240d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_HYPRE_IS(Mat A, MatType mtype, MatReuse reuse, Mat *B) 241d71ae5a4SJacob Faibussowitsch { 2422df22349SStefano Zampini Mat_HYPRE *mhA = (Mat_HYPRE *)(A->data); 2432df22349SStefano Zampini Mat lA; 2442df22349SStefano Zampini ISLocalToGlobalMapping rl2g, cl2g; 2452df22349SStefano Zampini IS is; 2462df22349SStefano Zampini hypre_ParCSRMatrix *hA; 2472df22349SStefano Zampini hypre_CSRMatrix *hdiag, *hoffd; 2482df22349SStefano Zampini MPI_Comm comm; 24939accc25SStefano Zampini HYPRE_Complex *hdd, *hod, *aa; 25039accc25SStefano Zampini PetscScalar *data; 2512cf14000SStefano Zampini HYPRE_BigInt *col_map_offd; 2522cf14000SStefano Zampini HYPRE_Int *hdi, *hdj, *hoi, *hoj; 2532df22349SStefano Zampini PetscInt *ii, *jj, *iptr, *jptr; 2542df22349SStefano Zampini PetscInt cum, dr, dc, oc, str, stc, nnz, i, jd, jo, M, N; 25558968eb6SStefano Zampini HYPRE_Int type; 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); 2622df22349SStefano Zampini M = hypre_ParCSRMatrixGlobalNumRows(hA); 2632df22349SStefano Zampini N = hypre_ParCSRMatrixGlobalNumCols(hA); 2642df22349SStefano Zampini str = hypre_ParCSRMatrixFirstRowIndex(hA); 2652df22349SStefano Zampini stc = hypre_ParCSRMatrixFirstColDiag(hA); 2662df22349SStefano Zampini hdiag = hypre_ParCSRMatrixDiag(hA); 2672df22349SStefano Zampini hoffd = hypre_ParCSRMatrixOffd(hA); 2682df22349SStefano Zampini dr = hypre_CSRMatrixNumRows(hdiag); 2692df22349SStefano Zampini dc = hypre_CSRMatrixNumCols(hdiag); 2702df22349SStefano Zampini nnz = hypre_CSRMatrixNumNonzeros(hdiag); 2712df22349SStefano Zampini hdi = hypre_CSRMatrixI(hdiag); 2722df22349SStefano Zampini hdj = hypre_CSRMatrixJ(hdiag); 2732df22349SStefano Zampini hdd = hypre_CSRMatrixData(hdiag); 2742df22349SStefano Zampini oc = hypre_CSRMatrixNumCols(hoffd); 2752df22349SStefano Zampini nnz += hypre_CSRMatrixNumNonzeros(hoffd); 2762df22349SStefano Zampini hoi = hypre_CSRMatrixI(hoffd); 2772df22349SStefano Zampini hoj = hypre_CSRMatrixJ(hoffd); 2782df22349SStefano Zampini hod = hypre_CSRMatrixData(hoffd); 2792df22349SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 2802df22349SStefano Zampini PetscInt *aux; 2812df22349SStefano Zampini 2822df22349SStefano Zampini /* generate l2g maps for rows and cols */ 2839566063dSJacob Faibussowitsch PetscCall(ISCreateStride(comm, dr, str, 1, &is)); 2849566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g)); 2859566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2862df22349SStefano Zampini col_map_offd = hypre_ParCSRMatrixColMapOffd(hA); 2879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dc + oc, &aux)); 2882df22349SStefano Zampini for (i = 0; i < dc; i++) aux[i] = i + stc; 2892df22349SStefano Zampini for (i = 0; i < oc; i++) aux[i + dc] = col_map_offd[i]; 2909566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, dc + oc, aux, PETSC_OWN_POINTER, &is)); 2919566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g)); 2929566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2932df22349SStefano Zampini /* create MATIS object */ 2949566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, B)); 2959566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, dr, dc, M, N)); 2969566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, MATIS)); 2979566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*B, rl2g, cl2g)); 2989566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 2999566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 3002df22349SStefano Zampini 3012df22349SStefano Zampini /* allocate CSR for local matrix */ 3029566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dr + 1, &iptr)); 3039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &jptr)); 3049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &data)); 3052df22349SStefano Zampini } else { 3062df22349SStefano Zampini PetscInt nr; 3072df22349SStefano Zampini PetscBool done; 3089566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*B, &lA)); 3099566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lA, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&iptr, (const PetscInt **)&jptr, &done)); 31008401ef6SPierre 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); 31108401ef6SPierre 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); 3129566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(lA, &data)); 3132df22349SStefano Zampini } 3142df22349SStefano Zampini /* merge local matrices */ 3152df22349SStefano Zampini ii = iptr; 3162df22349SStefano Zampini jj = jptr; 31739accc25SStefano 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++ */ 3182df22349SStefano Zampini *ii = *(hdi++) + *(hoi++); 3192df22349SStefano Zampini for (jd = 0, jo = 0, cum = 0; *ii < nnz; cum++) { 32039accc25SStefano Zampini PetscScalar *aold = (PetscScalar *)aa; 3212df22349SStefano Zampini PetscInt *jold = jj, nc = jd + jo; 3229371c9d4SSatish Balay for (; jd < *hdi; jd++) { 3239371c9d4SSatish Balay *jj++ = *hdj++; 3249371c9d4SSatish Balay *aa++ = *hdd++; 3259371c9d4SSatish Balay } 3269371c9d4SSatish Balay for (; jo < *hoi; jo++) { 3279371c9d4SSatish Balay *jj++ = *hoj++ + dc; 3289371c9d4SSatish Balay *aa++ = *hod++; 3299371c9d4SSatish Balay } 3302df22349SStefano Zampini *(++ii) = *(hdi++) + *(hoi++); 3319566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithScalarArray(jd + jo - nc, jold, aold)); 3322df22349SStefano Zampini } 3332df22349SStefano Zampini for (; cum < dr; cum++) *(++ii) = nnz; 3342df22349SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 335a033916dSStefano Zampini Mat_SeqAIJ *a; 336a033916dSStefano Zampini 3379566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, dr, dc + oc, iptr, jptr, data, &lA)); 3389566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*B, lA)); 339a033916dSStefano Zampini /* hack SeqAIJ */ 340a033916dSStefano Zampini a = (Mat_SeqAIJ *)(lA->data); 341a033916dSStefano Zampini a->free_a = PETSC_TRUE; 342a033916dSStefano Zampini a->free_ij = PETSC_TRUE; 3439566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lA)); 3442df22349SStefano Zampini } 3459566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY)); 3469566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY)); 34748a46eb9SPierre Jolivet if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, B)); 3483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3492df22349SStefano Zampini } 3502df22349SStefano Zampini 351b73e3080SStefano Zampini /* Move diagonal elements of the diagonal block to the front of their row, as needed by ParCSRMatrix. So damn hacky */ 352b73e3080SStefano Zampini static PetscErrorCode EnsureHypreCSR_SeqAIJ(Mat A, hypre_CSRMatrix *hA) 353d71ae5a4SJacob Faibussowitsch { 354b73e3080SStefano Zampini Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 355b73e3080SStefano Zampini PetscBool isseqaij; 356b73e3080SStefano Zampini HYPRE_Int tmpj, *hj; 357b73e3080SStefano Zampini HYPRE_Complex tmpv, *ha; 35863c07aadSStefano Zampini 35963c07aadSStefano Zampini PetscFunctionBegin; 360b73e3080SStefano Zampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isseqaij)); 361b73e3080SStefano Zampini PetscCheck(isseqaij, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Not for type %s\n", ((PetscObject)A)->type_name); 362b73e3080SStefano Zampini hj = hypre_CSRMatrixJ(hA); 363b73e3080SStefano Zampini ha = hypre_CSRMatrixData(hA); 364b73e3080SStefano Zampini #define swap_with_tmp(a, b, t) \ 365b73e3080SStefano Zampini { \ 366b73e3080SStefano Zampini t = a; \ 367b73e3080SStefano Zampini a = b; \ 368b73e3080SStefano Zampini b = t; \ 369b73e3080SStefano Zampini } 370b73e3080SStefano Zampini for (PetscInt i = 0; i < A->rmap->n; i++) { 371b73e3080SStefano Zampini if (aij->diag[i] >= aij->i[i] && aij->diag[i] < aij->i[i + 1]) { /* Diagonal element of this row exists in a[] and j[] */ 372b73e3080SStefano Zampini swap_with_tmp(ha[aij->i[i]], ha[aij->diag[i]], tmpv); 373b73e3080SStefano Zampini if (hj[aij->i[i]] != i) swap_with_tmp(hj[aij->i[i]], hj[aij->diag[i]], tmpj); 374b73e3080SStefano Zampini } 375b73e3080SStefano Zampini } 376b73e3080SStefano Zampini #undef swap_with_tmp 377b73e3080SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 378b73e3080SStefano Zampini } 379b73e3080SStefano Zampini 380b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyValues(Mat A, HYPRE_IJMatrix ij) 381b73e3080SStefano Zampini { 382b73e3080SStefano Zampini HYPRE_Int type; 383b73e3080SStefano Zampini hypre_ParCSRMatrix *par_matrix; 384b73e3080SStefano Zampini hypre_CSRMatrix *hdiag, *hoffd; 385b73e3080SStefano Zampini PetscBool ismpiaij; 386b73e3080SStefano Zampini Mat dA = A, oA = NULL; 387b73e3080SStefano Zampini PetscInt nnz; 388b73e3080SStefano Zampini const PetscScalar *pa; 389b73e3080SStefano Zampini 390b73e3080SStefano Zampini PetscFunctionBegin; 391b73e3080SStefano Zampini PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type); 392b73e3080SStefano Zampini PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 393b73e3080SStefano Zampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 394b73e3080SStefano Zampini if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(A, &dA, &oA, NULL)); 395b73e3080SStefano Zampini PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix); 396b73e3080SStefano Zampini 397b73e3080SStefano Zampini hdiag = hypre_ParCSRMatrixDiag(par_matrix); 398b73e3080SStefano Zampini nnz = hypre_CSRMatrixNumNonzeros(hdiag); 399b73e3080SStefano Zampini PetscCall(MatSeqAIJGetArrayRead(dA, &pa)); 400b73e3080SStefano Zampini PetscCall(PetscArraycpy(hdiag->data, pa, nnz)); 401b73e3080SStefano Zampini PetscCall(MatSeqAIJRestoreArrayRead(dA, &pa)); 402b73e3080SStefano Zampini if (oA) { 403b73e3080SStefano Zampini hoffd = hypre_ParCSRMatrixOffd(par_matrix); 404b73e3080SStefano Zampini nnz = hypre_CSRMatrixNumNonzeros(hoffd); 405b73e3080SStefano Zampini PetscCall(MatSeqAIJGetArrayRead(oA, &pa)); 406b73e3080SStefano Zampini PetscCall(PetscArraycpy(hoffd->data, pa, nnz)); 407b73e3080SStefano Zampini PetscCall(MatSeqAIJRestoreArrayRead(dA, &pa)); 408b73e3080SStefano Zampini } 409b73e3080SStefano Zampini PetscCall(EnsureHypreCSR_SeqAIJ(dA, hdiag)); 410b73e3080SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 411b73e3080SStefano Zampini } 412b73e3080SStefano Zampini 413b73e3080SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType type, MatReuse reuse, Mat *B) 414b73e3080SStefano Zampini { 415b73e3080SStefano Zampini MPI_Comm comm = PetscObjectComm((PetscObject)A); 416b73e3080SStefano Zampini Mat M = NULL; 417b73e3080SStefano Zampini Mat dA = A, oA = NULL; 418b73e3080SStefano Zampini PetscBool ismpiaij, issbaij, isbaij; 419b73e3080SStefano Zampini Mat_HYPRE *hA; 420b73e3080SStefano Zampini 421b73e3080SStefano Zampini PetscFunctionBegin; 422b73e3080SStefano Zampini PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &issbaij, MATSEQSBAIJ, MATMPIBAIJ, "")); 423b73e3080SStefano Zampini PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &isbaij, MATSEQBAIJ, MATMPIBAIJ, "")); 424b73e3080SStefano Zampini if (isbaij || issbaij) { /* handle BAIJ and SBAIJ */ 425b73e3080SStefano Zampini PetscBool ismpi; 426b73e3080SStefano Zampini MatType newtype; 427b73e3080SStefano Zampini 428b73e3080SStefano Zampini PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &ismpi, MATMPISBAIJ, MATMPIBAIJ, "")); 429b73e3080SStefano Zampini newtype = ismpi ? MATMPIAIJ : MATSEQAIJ; 43063c07aadSStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 431b73e3080SStefano Zampini PetscCall(MatConvert(*B, newtype, MAT_INPLACE_MATRIX, B)); 432b73e3080SStefano Zampini PetscCall(MatConvert(A, newtype, MAT_REUSE_MATRIX, B)); 433b73e3080SStefano Zampini PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B)); 434b73e3080SStefano Zampini } else if (reuse == MAT_INITIAL_MATRIX) { 435b73e3080SStefano Zampini PetscCall(MatConvert(A, newtype, MAT_INITIAL_MATRIX, B)); 436b73e3080SStefano Zampini PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B)); 43763c07aadSStefano Zampini } else { 438b73e3080SStefano Zampini PetscCall(MatConvert(A, newtype, MAT_INPLACE_MATRIX, &A)); 439b73e3080SStefano Zampini PetscCall(MatConvert(A, MATHYPRE, MAT_INPLACE_MATRIX, &A)); 440b73e3080SStefano Zampini } 441b73e3080SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 442b73e3080SStefano Zampini } 443b73e3080SStefano Zampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 444b73e3080SStefano Zampini if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(A, &dA, &oA, NULL)); 445b73e3080SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 4469566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &M)); 4479566063dSJacob Faibussowitsch PetscCall(MatSetType(M, MATHYPRE)); 4489566063dSJacob Faibussowitsch PetscCall(MatSetSizes(M, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N)); 449b73e3080SStefano Zampini PetscCall(MatSetOption(M, MAT_SORTED_FULL, PETSC_TRUE)); 450b73e3080SStefano Zampini PetscCall(MatSetOption(M, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE)); 451b73e3080SStefano Zampini PetscCall(PetscLayoutSetUp(M->rmap)); 452b73e3080SStefano Zampini PetscCall(PetscLayoutSetUp(M->cmap)); 453b73e3080SStefano Zampini 454b73e3080SStefano Zampini hA = (Mat_HYPRE *)M->data; 455b73e3080SStefano Zampini PetscCall(MatHYPRE_CreateFromMat(A, hA)); /* Create hmat->ij and preallocate it */ 456b73e3080SStefano Zampini PetscCall(MatHYPRE_IJMatrixCopyIJ(A, hA->ij)); /* Copy A's (a,i,j) to hmat->ij */ 457b73e3080SStefano Zampini M->preallocated = PETSC_TRUE; 45884d4e069SStefano Zampini if (reuse == MAT_INITIAL_MATRIX) *B = M; 459b73e3080SStefano Zampini } else M = *B; 460b73e3080SStefano Zampini 461b73e3080SStefano Zampini hA = (Mat_HYPRE *)M->data; 462b73e3080SStefano Zampini PetscCall(MatHYPRE_IJMatrixCopyValues(A, hA->ij)); 463b73e3080SStefano Zampini PetscCall(MatAssemblyBegin(M, MAT_FINAL_ASSEMBLY)); 464b73e3080SStefano Zampini PetscCall(MatAssemblyEnd(M, MAT_FINAL_ASSEMBLY)); /* Migrate mat to device if it is bound to. Hypre builds its own SpMV context here */ 465b73e3080SStefano Zampini 46648a46eb9SPierre Jolivet if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &M)); 4673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46863c07aadSStefano Zampini } 46963c07aadSStefano Zampini 470d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_HYPRE_AIJ(Mat A, MatType mtype, MatReuse reuse, Mat *B) 471d71ae5a4SJacob Faibussowitsch { 47263c07aadSStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 47363c07aadSStefano Zampini hypre_ParCSRMatrix *parcsr; 47463c07aadSStefano Zampini hypre_CSRMatrix *hdiag, *hoffd; 47563c07aadSStefano Zampini MPI_Comm comm; 47663c07aadSStefano Zampini PetscScalar *da, *oa, *aptr; 47763c07aadSStefano Zampini PetscInt *dii, *djj, *oii, *ojj, *iptr; 47863c07aadSStefano Zampini PetscInt i, dnnz, onnz, m, n; 47958968eb6SStefano Zampini HYPRE_Int type; 48063c07aadSStefano Zampini PetscMPIInt size; 4812cf14000SStefano Zampini PetscBool sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int)); 482b73e3080SStefano Zampini PetscBool downs = PETSC_TRUE, oowns = PETSC_TRUE; 48363c07aadSStefano Zampini 48463c07aadSStefano Zampini PetscFunctionBegin; 48563c07aadSStefano Zampini comm = PetscObjectComm((PetscObject)A); 486792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type); 48708401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 48863c07aadSStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 48963c07aadSStefano Zampini PetscBool ismpiaij, isseqaij; 4909566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATMPIAIJ, &ismpiaij)); 4919566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATSEQAIJ, &isseqaij)); 49208401ef6SPierre Jolivet PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Only MATMPIAIJ or MATSEQAIJ are supported"); 49363c07aadSStefano Zampini } 4946ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 49508401ef6SPierre Jolivet PetscCheck(HYPRE_MEMORY_DEVICE != hypre_IJMatrixMemoryLocation(hA->ij), comm, PETSC_ERR_SUP, "Not yet implemented"); 4966ea7df73SStefano Zampini #endif 4979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 49863c07aadSStefano Zampini 499792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr); 50063c07aadSStefano Zampini hdiag = hypre_ParCSRMatrixDiag(parcsr); 50163c07aadSStefano Zampini hoffd = hypre_ParCSRMatrixOffd(parcsr); 50263c07aadSStefano Zampini m = hypre_CSRMatrixNumRows(hdiag); 50363c07aadSStefano Zampini n = hypre_CSRMatrixNumCols(hdiag); 50463c07aadSStefano Zampini dnnz = hypre_CSRMatrixNumNonzeros(hdiag); 50563c07aadSStefano Zampini onnz = hypre_CSRMatrixNumNonzeros(hoffd); 506225daaf8SStefano Zampini if (reuse == MAT_INITIAL_MATRIX) { 5079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &dii)); 5089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dnnz, &djj)); 5099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dnnz, &da)); 510225daaf8SStefano Zampini } else if (reuse == MAT_REUSE_MATRIX) { 51163c07aadSStefano Zampini PetscInt nr; 51263c07aadSStefano Zampini PetscBool done; 51363c07aadSStefano Zampini if (size > 1) { 51463c07aadSStefano Zampini Mat_MPIAIJ *b = (Mat_MPIAIJ *)((*B)->data); 51563c07aadSStefano Zampini 5169566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(b->A, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&dii, (const PetscInt **)&djj, &done)); 51708401ef6SPierre Jolivet PetscCheck(nr == m, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of local rows in diag part! %" PetscInt_FMT " != %" PetscInt_FMT, nr, m); 51808401ef6SPierre Jolivet PetscCheck(dii[nr] >= dnnz, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of nonzeros in diag part! reuse %" PetscInt_FMT " hypre %" PetscInt_FMT, dii[nr], dnnz); 5199566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(b->A, &da)); 52063c07aadSStefano Zampini } else { 5219566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(*B, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&dii, (const PetscInt **)&djj, &done)); 52208401ef6SPierre Jolivet PetscCheck(nr == m, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of local rows! %" PetscInt_FMT " != %" PetscInt_FMT, nr, m); 52308401ef6SPierre Jolivet PetscCheck(dii[nr] >= dnnz, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of nonzeros! reuse %" PetscInt_FMT " hypre %" PetscInt_FMT, dii[nr], dnnz); 5249566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(*B, &da)); 52563c07aadSStefano Zampini } 526225daaf8SStefano Zampini } else { /* MAT_INPLACE_MATRIX */ 527b73e3080SStefano Zampini downs = (PetscBool)(hypre_CSRMatrixOwnsData(hdiag)); 528b73e3080SStefano Zampini if (!sameint || !downs) { 5299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &dii)); 5309566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dnnz, &djj)); 5312cf14000SStefano Zampini } else { 5327d968826Sstefano_zampini dii = (PetscInt *)hypre_CSRMatrixI(hdiag); 5337d968826Sstefano_zampini djj = (PetscInt *)hypre_CSRMatrixJ(hdiag); 53463c07aadSStefano Zampini } 535b73e3080SStefano Zampini if (!downs) { 536b73e3080SStefano Zampini PetscCall(PetscMalloc1(dnnz, &da)); 537b73e3080SStefano Zampini } else da = (PetscScalar *)hypre_CSRMatrixData(hdiag); 53863c07aadSStefano Zampini } 5392cf14000SStefano Zampini 5402cf14000SStefano Zampini if (!sameint) { 5419371c9d4SSatish Balay if (reuse != MAT_REUSE_MATRIX) { 5429371c9d4SSatish Balay for (i = 0; i < m + 1; i++) dii[i] = (PetscInt)(hypre_CSRMatrixI(hdiag)[i]); 5439371c9d4SSatish Balay } 5442cf14000SStefano Zampini for (i = 0; i < dnnz; i++) djj[i] = (PetscInt)(hypre_CSRMatrixJ(hdiag)[i]); 5452cf14000SStefano Zampini } else { 5469566063dSJacob Faibussowitsch if (reuse != MAT_REUSE_MATRIX) PetscCall(PetscArraycpy(dii, hypre_CSRMatrixI(hdiag), m + 1)); 5479566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(djj, hypre_CSRMatrixJ(hdiag), dnnz)); 5482cf14000SStefano Zampini } 5499566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(da, hypre_CSRMatrixData(hdiag), dnnz)); 55063c07aadSStefano Zampini iptr = djj; 55163c07aadSStefano Zampini aptr = da; 55263c07aadSStefano Zampini for (i = 0; i < m; i++) { 55363c07aadSStefano Zampini PetscInt nc = dii[i + 1] - dii[i]; 5549566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithScalarArray(nc, iptr, aptr)); 55563c07aadSStefano Zampini iptr += nc; 55663c07aadSStefano Zampini aptr += nc; 55763c07aadSStefano Zampini } 55863c07aadSStefano Zampini if (size > 1) { 5592cf14000SStefano Zampini HYPRE_BigInt *coffd; 5602cf14000SStefano Zampini HYPRE_Int *offdj; 56163c07aadSStefano Zampini 562225daaf8SStefano Zampini if (reuse == MAT_INITIAL_MATRIX) { 5639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &oii)); 5649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(onnz, &ojj)); 5659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(onnz, &oa)); 566225daaf8SStefano Zampini } else if (reuse == MAT_REUSE_MATRIX) { 56763c07aadSStefano Zampini Mat_MPIAIJ *b = (Mat_MPIAIJ *)((*B)->data); 56863c07aadSStefano Zampini PetscInt nr, hr = hypre_CSRMatrixNumRows(hoffd); 56963c07aadSStefano Zampini PetscBool done; 57063c07aadSStefano Zampini 5719566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(b->B, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&oii, (const PetscInt **)&ojj, &done)); 57208401ef6SPierre Jolivet PetscCheck(nr == hr, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of local rows in offdiag part! %" PetscInt_FMT " != %" PetscInt_FMT, nr, hr); 573b73e3080SStefano Zampini PetscCheck(oii[nr] >= onnz, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse matrix: different number of nonzeros in off-diagonal part of matrix! reuse %" PetscInt_FMT " hypre %" PetscInt_FMT, oii[nr], onnz); 5749566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(b->B, &oa)); 575225daaf8SStefano Zampini } else { /* MAT_INPLACE_MATRIX */ 576b73e3080SStefano Zampini oowns = (PetscBool)(hypre_CSRMatrixOwnsData(hoffd)); 577b73e3080SStefano Zampini if (!sameint || !oowns) { 5789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &oii)); 5799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(onnz, &ojj)); 5802cf14000SStefano Zampini } else { 5817d968826Sstefano_zampini oii = (PetscInt *)hypre_CSRMatrixI(hoffd); 5827d968826Sstefano_zampini ojj = (PetscInt *)hypre_CSRMatrixJ(hoffd); 58363c07aadSStefano Zampini } 584b73e3080SStefano Zampini if (!oowns) { 585b73e3080SStefano Zampini PetscCall(PetscMalloc1(onnz, &oa)); 586b73e3080SStefano Zampini } else oa = (PetscScalar *)hypre_CSRMatrixData(hoffd); 58763c07aadSStefano Zampini } 588a16187a7SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 5892cf14000SStefano Zampini if (!sameint) { 5902cf14000SStefano Zampini for (i = 0; i < m + 1; i++) oii[i] = (PetscInt)(hypre_CSRMatrixI(hoffd)[i]); 5912cf14000SStefano Zampini } else { 5929566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(oii, hypre_CSRMatrixI(hoffd), m + 1)); 5932cf14000SStefano Zampini } 594a16187a7SStefano Zampini } 5959566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(oa, hypre_CSRMatrixData(hoffd), onnz)); 596a16187a7SStefano Zampini 59763c07aadSStefano Zampini offdj = hypre_CSRMatrixJ(hoffd); 59863c07aadSStefano Zampini coffd = hypre_ParCSRMatrixColMapOffd(parcsr); 599a16187a7SStefano Zampini /* we only need the permutation to be computed properly, I don't know if HYPRE 600a16187a7SStefano Zampini messes up with the ordering. Just in case, allocate some memory and free it 601a16187a7SStefano Zampini later */ 602a16187a7SStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 603a16187a7SStefano Zampini Mat_MPIAIJ *b = (Mat_MPIAIJ *)((*B)->data); 604a16187a7SStefano Zampini PetscInt mnz; 605a16187a7SStefano Zampini 6069566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetMaxRowNonzeros(b->B, &mnz)); 6079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mnz, &ojj)); 6089371c9d4SSatish Balay } else 6099371c9d4SSatish Balay for (i = 0; i < onnz; i++) ojj[i] = coffd[offdj[i]]; 61063c07aadSStefano Zampini iptr = ojj; 61163c07aadSStefano Zampini aptr = oa; 61263c07aadSStefano Zampini for (i = 0; i < m; i++) { 61363c07aadSStefano Zampini PetscInt nc = oii[i + 1] - oii[i]; 614a16187a7SStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 615a16187a7SStefano Zampini PetscInt j; 616a16187a7SStefano Zampini 617a16187a7SStefano Zampini iptr = ojj; 618a16187a7SStefano Zampini for (j = 0; j < nc; j++) iptr[j] = coffd[offdj[oii[i] + j]]; 619a16187a7SStefano Zampini } 6209566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithScalarArray(nc, iptr, aptr)); 62163c07aadSStefano Zampini iptr += nc; 62263c07aadSStefano Zampini aptr += nc; 62363c07aadSStefano Zampini } 6249566063dSJacob Faibussowitsch if (reuse == MAT_REUSE_MATRIX) PetscCall(PetscFree(ojj)); 625225daaf8SStefano Zampini if (reuse == MAT_INITIAL_MATRIX) { 62663c07aadSStefano Zampini Mat_MPIAIJ *b; 62763c07aadSStefano Zampini Mat_SeqAIJ *d, *o; 628225daaf8SStefano Zampini 6299566063dSJacob Faibussowitsch PetscCall(MatCreateMPIAIJWithSplitArrays(comm, m, n, PETSC_DECIDE, PETSC_DECIDE, dii, djj, da, oii, ojj, oa, B)); 63063c07aadSStefano Zampini /* hack MPIAIJ */ 63163c07aadSStefano Zampini b = (Mat_MPIAIJ *)((*B)->data); 63263c07aadSStefano Zampini d = (Mat_SeqAIJ *)b->A->data; 63363c07aadSStefano Zampini o = (Mat_SeqAIJ *)b->B->data; 63463c07aadSStefano Zampini d->free_a = PETSC_TRUE; 63563c07aadSStefano Zampini d->free_ij = PETSC_TRUE; 63663c07aadSStefano Zampini o->free_a = PETSC_TRUE; 63763c07aadSStefano Zampini o->free_ij = PETSC_TRUE; 638225daaf8SStefano Zampini } else if (reuse == MAT_INPLACE_MATRIX) { 639225daaf8SStefano Zampini Mat T; 6402cf14000SStefano Zampini 6419566063dSJacob Faibussowitsch PetscCall(MatCreateMPIAIJWithSplitArrays(comm, m, n, PETSC_DECIDE, PETSC_DECIDE, dii, djj, da, oii, ojj, oa, &T)); 642b73e3080SStefano Zampini if (sameint && downs) { /* ownership of CSR pointers is transferred to PETSc */ 643225daaf8SStefano Zampini hypre_CSRMatrixI(hdiag) = NULL; 644225daaf8SStefano Zampini hypre_CSRMatrixJ(hdiag) = NULL; 645b73e3080SStefano Zampini } else { /* Hack MPIAIJ -> free ij but maybe not a */ 6462cf14000SStefano Zampini Mat_MPIAIJ *b = (Mat_MPIAIJ *)(T->data); 6472cf14000SStefano Zampini Mat_SeqAIJ *d = (Mat_SeqAIJ *)(b->A->data); 6482cf14000SStefano Zampini 6492cf14000SStefano Zampini d->free_ij = PETSC_TRUE; 650b73e3080SStefano Zampini d->free_a = downs ? PETSC_FALSE : PETSC_TRUE; 651b73e3080SStefano Zampini } 652b73e3080SStefano Zampini if (sameint && oowns) { /* ownership of CSR pointers is transferred to PETSc */ 653b73e3080SStefano Zampini hypre_CSRMatrixI(hoffd) = NULL; 654b73e3080SStefano Zampini hypre_CSRMatrixJ(hoffd) = NULL; 655b73e3080SStefano Zampini } else { /* Hack MPIAIJ -> free ij but maybe not a */ 656b73e3080SStefano Zampini Mat_MPIAIJ *b = (Mat_MPIAIJ *)(T->data); 657b73e3080SStefano Zampini Mat_SeqAIJ *o = (Mat_SeqAIJ *)(b->B->data); 658b73e3080SStefano Zampini 6592cf14000SStefano Zampini o->free_ij = PETSC_TRUE; 660b73e3080SStefano Zampini o->free_a = oowns ? PETSC_FALSE : PETSC_TRUE; 6612cf14000SStefano Zampini } 6622cf14000SStefano Zampini hypre_CSRMatrixData(hdiag) = NULL; 663225daaf8SStefano Zampini hypre_CSRMatrixData(hoffd) = NULL; 6649566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &T)); 66563c07aadSStefano Zampini } 666225daaf8SStefano Zampini } else { 667225daaf8SStefano Zampini oii = NULL; 668225daaf8SStefano Zampini ojj = NULL; 669225daaf8SStefano Zampini oa = NULL; 670225daaf8SStefano Zampini if (reuse == MAT_INITIAL_MATRIX) { 67163c07aadSStefano Zampini Mat_SeqAIJ *b; 6722cf14000SStefano Zampini 6739566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(comm, m, n, dii, djj, da, B)); 67463c07aadSStefano Zampini /* hack SeqAIJ */ 67563c07aadSStefano Zampini b = (Mat_SeqAIJ *)((*B)->data); 67663c07aadSStefano Zampini b->free_a = PETSC_TRUE; 67763c07aadSStefano Zampini b->free_ij = PETSC_TRUE; 678225daaf8SStefano Zampini } else if (reuse == MAT_INPLACE_MATRIX) { 679225daaf8SStefano Zampini Mat T; 6802cf14000SStefano Zampini 6819566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(comm, m, n, dii, djj, da, &T)); 682b73e3080SStefano Zampini if (sameint && downs) { /* ownership of CSR pointers is transferred to PETSc */ 683225daaf8SStefano Zampini hypre_CSRMatrixI(hdiag) = NULL; 684225daaf8SStefano Zampini hypre_CSRMatrixJ(hdiag) = NULL; 685b73e3080SStefano Zampini } else { /* free ij but maybe not a */ 6862cf14000SStefano Zampini Mat_SeqAIJ *b = (Mat_SeqAIJ *)(T->data); 6872cf14000SStefano Zampini 6882cf14000SStefano Zampini b->free_ij = PETSC_TRUE; 689b73e3080SStefano Zampini b->free_a = downs ? PETSC_FALSE : PETSC_TRUE; 6902cf14000SStefano Zampini } 691225daaf8SStefano Zampini hypre_CSRMatrixData(hdiag) = NULL; 6929566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &T)); 69363c07aadSStefano Zampini } 694225daaf8SStefano Zampini } 695225daaf8SStefano Zampini 6962cf14000SStefano Zampini /* we have to use hypre_Tfree to free the HYPRE arrays 697da81f932SPierre Jolivet that PETSc now owns */ 69863c07aadSStefano Zampini if (reuse == MAT_INPLACE_MATRIX) { 6999371c9d4SSatish Balay const char *names[6] = {"_hypre_csr_da", "_hypre_csr_oa", "_hypre_csr_dii", "_hypre_csr_djj", "_hypre_csr_oii", "_hypre_csr_ojj"}; 700b73e3080SStefano Zampini // clang-format off 701b73e3080SStefano Zampini void *ptrs[6] = {downs ? da : NULL, 702b73e3080SStefano Zampini oowns ? oa : NULL, 703b73e3080SStefano Zampini downs && sameint ? dii : NULL, 704b73e3080SStefano Zampini downs && sameint ? djj : NULL, 705b73e3080SStefano Zampini oowns && sameint ? oii : NULL, 706b73e3080SStefano Zampini oowns && sameint ? ojj : NULL}; 707b73e3080SStefano Zampini // clang-format on 708b73e3080SStefano Zampini for (i = 0; i < 6; i++) { 709225daaf8SStefano Zampini PetscContainer c; 710225daaf8SStefano Zampini 7119566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(comm, &c)); 7129566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(c, ptrs[i])); 7139566063dSJacob Faibussowitsch PetscCall(PetscContainerSetUserDestroy(c, hypre_array_destroy)); 7149566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)(*B), names[i], (PetscObject)c)); 7159566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&c)); 716225daaf8SStefano Zampini } 71763c07aadSStefano Zampini } 7183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 71963c07aadSStefano Zampini } 72063c07aadSStefano Zampini 721d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJGetParCSR_Private(Mat A, hypre_ParCSRMatrix **hA) 722d71ae5a4SJacob Faibussowitsch { 723613e5ff0Sstefano_zampini hypre_ParCSRMatrix *tA; 724c1a070e6SStefano Zampini hypre_CSRMatrix *hdiag, *hoffd; 725c1a070e6SStefano Zampini Mat_SeqAIJ *diag, *offd; 7262cf14000SStefano Zampini PetscInt *garray, i, noffd, dnnz, onnz, *row_starts, *col_starts; 727c1a070e6SStefano Zampini MPI_Comm comm = PetscObjectComm((PetscObject)A); 728613e5ff0Sstefano_zampini PetscBool ismpiaij, isseqaij; 7292cf14000SStefano Zampini PetscBool sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int)); 7306ea7df73SStefano Zampini HYPRE_Int *hdi = NULL, *hdj = NULL, *hoi = NULL, *hoj = NULL; 7315c97c10fSStefano Zampini PetscInt *pdi = NULL, *pdj = NULL, *poi = NULL, *poj = NULL; 7326ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 7336ea7df73SStefano Zampini PetscBool iscuda = PETSC_FALSE; 7346ea7df73SStefano Zampini #endif 735c1a070e6SStefano Zampini 736c1a070e6SStefano Zampini PetscFunctionBegin; 7379566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 7389566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isseqaij)); 73908401ef6SPierre Jolivet PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Unsupported type %s", ((PetscObject)A)->type_name); 740ea9ee2c1SPierre Jolivet PetscHYPREInitialize(); 741c1a070e6SStefano Zampini if (ismpiaij) { 742c1a070e6SStefano Zampini Mat_MPIAIJ *a = (Mat_MPIAIJ *)(A->data); 743c1a070e6SStefano Zampini 744c1a070e6SStefano Zampini diag = (Mat_SeqAIJ *)a->A->data; 745c1a070e6SStefano Zampini offd = (Mat_SeqAIJ *)a->B->data; 7466ea7df73SStefano Zampini #if defined(PETSC_HAVE_CUDA) && defined(PETSC_HAVE_HYPRE_DEVICE) && defined(HYPRE_USING_CUDA) 7479566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMPIAIJCUSPARSE, &iscuda)); 7486ea7df73SStefano Zampini if (iscuda && !A->boundtocpu) { 7496ea7df73SStefano Zampini sameint = PETSC_TRUE; 7509566063dSJacob Faibussowitsch PetscCall(MatSeqAIJCUSPARSEGetIJ(a->A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj)); 7519566063dSJacob Faibussowitsch PetscCall(MatSeqAIJCUSPARSEGetIJ(a->B, PETSC_FALSE, (const HYPRE_Int **)&hoi, (const HYPRE_Int **)&hoj)); 7526ea7df73SStefano Zampini } else { 7536ea7df73SStefano Zampini #else 7546ea7df73SStefano Zampini { 7556ea7df73SStefano Zampini #endif 7566ea7df73SStefano Zampini pdi = diag->i; 7576ea7df73SStefano Zampini pdj = diag->j; 7586ea7df73SStefano Zampini poi = offd->i; 7596ea7df73SStefano Zampini poj = offd->j; 7606ea7df73SStefano Zampini if (sameint) { 7616ea7df73SStefano Zampini hdi = (HYPRE_Int *)pdi; 7626ea7df73SStefano Zampini hdj = (HYPRE_Int *)pdj; 7636ea7df73SStefano Zampini hoi = (HYPRE_Int *)poi; 7646ea7df73SStefano Zampini hoj = (HYPRE_Int *)poj; 7656ea7df73SStefano Zampini } 7666ea7df73SStefano Zampini } 767c1a070e6SStefano Zampini garray = a->garray; 768c1a070e6SStefano Zampini noffd = a->B->cmap->N; 769c1a070e6SStefano Zampini dnnz = diag->nz; 770c1a070e6SStefano Zampini onnz = offd->nz; 771c1a070e6SStefano Zampini } else { 772c1a070e6SStefano Zampini diag = (Mat_SeqAIJ *)A->data; 773c1a070e6SStefano Zampini offd = NULL; 7746ea7df73SStefano Zampini #if defined(PETSC_HAVE_CUDA) && defined(PETSC_HAVE_HYPRE_DEVICE) 7759566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATSEQAIJCUSPARSE, &iscuda)); 7766ea7df73SStefano Zampini if (iscuda && !A->boundtocpu) { 7776ea7df73SStefano Zampini sameint = PETSC_TRUE; 7789566063dSJacob Faibussowitsch PetscCall(MatSeqAIJCUSPARSEGetIJ(A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj)); 7796ea7df73SStefano Zampini } else { 7806ea7df73SStefano Zampini #else 7816ea7df73SStefano Zampini { 7826ea7df73SStefano Zampini #endif 7836ea7df73SStefano Zampini pdi = diag->i; 7846ea7df73SStefano Zampini pdj = diag->j; 7856ea7df73SStefano Zampini if (sameint) { 7866ea7df73SStefano Zampini hdi = (HYPRE_Int *)pdi; 7876ea7df73SStefano Zampini hdj = (HYPRE_Int *)pdj; 7886ea7df73SStefano Zampini } 7896ea7df73SStefano Zampini } 790c1a070e6SStefano Zampini garray = NULL; 791c1a070e6SStefano Zampini noffd = 0; 792c1a070e6SStefano Zampini dnnz = diag->nz; 793c1a070e6SStefano Zampini onnz = 0; 794c1a070e6SStefano Zampini } 795225daaf8SStefano Zampini 796c1a070e6SStefano Zampini /* create a temporary ParCSR */ 797c1a070e6SStefano Zampini if (HYPRE_AssumedPartitionCheck()) { 798c1a070e6SStefano Zampini PetscMPIInt myid; 799c1a070e6SStefano Zampini 8009566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &myid)); 801c1a070e6SStefano Zampini row_starts = A->rmap->range + myid; 802c1a070e6SStefano Zampini col_starts = A->cmap->range + myid; 803c1a070e6SStefano Zampini } else { 804c1a070e6SStefano Zampini row_starts = A->rmap->range; 805c1a070e6SStefano Zampini col_starts = A->cmap->range; 806c1a070e6SStefano Zampini } 8072cf14000SStefano Zampini tA = hypre_ParCSRMatrixCreate(comm, A->rmap->N, A->cmap->N, (HYPRE_BigInt *)row_starts, (HYPRE_BigInt *)col_starts, noffd, dnnz, onnz); 808a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 809c1a070e6SStefano Zampini hypre_ParCSRMatrixSetRowStartsOwner(tA, 0); 810c1a070e6SStefano Zampini hypre_ParCSRMatrixSetColStartsOwner(tA, 0); 811a1d2239cSSatish Balay #endif 812c1a070e6SStefano Zampini 813225daaf8SStefano Zampini /* set diagonal part */ 814c1a070e6SStefano Zampini hdiag = hypre_ParCSRMatrixDiag(tA); 8156ea7df73SStefano Zampini if (!sameint) { /* malloc CSR pointers */ 8169566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(A->rmap->n + 1, &hdi, dnnz, &hdj)); 8176ea7df73SStefano Zampini for (i = 0; i < A->rmap->n + 1; i++) hdi[i] = (HYPRE_Int)(pdi[i]); 8186ea7df73SStefano Zampini for (i = 0; i < dnnz; i++) hdj[i] = (HYPRE_Int)(pdj[i]); 8192cf14000SStefano Zampini } 8206ea7df73SStefano Zampini hypre_CSRMatrixI(hdiag) = hdi; 8216ea7df73SStefano Zampini hypre_CSRMatrixJ(hdiag) = hdj; 82239accc25SStefano Zampini hypre_CSRMatrixData(hdiag) = (HYPRE_Complex *)diag->a; 823c1a070e6SStefano Zampini hypre_CSRMatrixNumNonzeros(hdiag) = diag->nz; 824c1a070e6SStefano Zampini hypre_CSRMatrixSetRownnz(hdiag); 825c1a070e6SStefano Zampini hypre_CSRMatrixSetDataOwner(hdiag, 0); 826c1a070e6SStefano Zampini 827225daaf8SStefano Zampini /* set offdiagonal part */ 828c1a070e6SStefano Zampini hoffd = hypre_ParCSRMatrixOffd(tA); 829c1a070e6SStefano Zampini if (offd) { 8306ea7df73SStefano Zampini if (!sameint) { /* malloc CSR pointers */ 8319566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(A->rmap->n + 1, &hoi, onnz, &hoj)); 8326ea7df73SStefano Zampini for (i = 0; i < A->rmap->n + 1; i++) hoi[i] = (HYPRE_Int)(poi[i]); 8336ea7df73SStefano Zampini for (i = 0; i < onnz; i++) hoj[i] = (HYPRE_Int)(poj[i]); 8342cf14000SStefano Zampini } 8356ea7df73SStefano Zampini hypre_CSRMatrixI(hoffd) = hoi; 8366ea7df73SStefano Zampini hypre_CSRMatrixJ(hoffd) = hoj; 83739accc25SStefano Zampini hypre_CSRMatrixData(hoffd) = (HYPRE_Complex *)offd->a; 838c1a070e6SStefano Zampini hypre_CSRMatrixNumNonzeros(hoffd) = offd->nz; 839c1a070e6SStefano Zampini hypre_CSRMatrixSetRownnz(hoffd); 840c1a070e6SStefano Zampini hypre_CSRMatrixSetDataOwner(hoffd, 0); 8416ea7df73SStefano Zampini } 8426ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 843792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, iscuda ? HYPRE_MEMORY_DEVICE : HYPRE_MEMORY_HOST); 8446ea7df73SStefano Zampini #else 8456ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0) 846792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixInitialize, tA); 8476ea7df73SStefano Zampini #else 848792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, HYPRE_MEMORY_HOST); 8496ea7df73SStefano Zampini #endif 8506ea7df73SStefano Zampini #endif 8516ea7df73SStefano Zampini hypre_TFree(hypre_ParCSRMatrixColMapOffd(tA), HYPRE_MEMORY_HOST); 852c1a070e6SStefano Zampini hypre_ParCSRMatrixSetNumNonzeros(tA); 8532cf14000SStefano Zampini hypre_ParCSRMatrixColMapOffd(tA) = (HYPRE_BigInt *)garray; 854792fecdfSBarry Smith if (!hypre_ParCSRMatrixCommPkg(tA)) PetscCallExternal(hypre_MatvecCommPkgCreate, tA); 855613e5ff0Sstefano_zampini *hA = tA; 8563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 857613e5ff0Sstefano_zampini } 858c1a070e6SStefano Zampini 859d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJRestoreParCSR_Private(Mat A, hypre_ParCSRMatrix **hA) 860d71ae5a4SJacob Faibussowitsch { 861613e5ff0Sstefano_zampini hypre_CSRMatrix *hdiag, *hoffd; 8626ea7df73SStefano Zampini PetscBool ismpiaij, sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int)); 8636ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 8646ea7df73SStefano Zampini PetscBool iscuda = PETSC_FALSE; 8656ea7df73SStefano Zampini #endif 866c1a070e6SStefano Zampini 867613e5ff0Sstefano_zampini PetscFunctionBegin; 8689566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 8696ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 8709566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, "")); 8716ea7df73SStefano Zampini if (iscuda) sameint = PETSC_TRUE; 8726ea7df73SStefano Zampini #endif 873613e5ff0Sstefano_zampini hdiag = hypre_ParCSRMatrixDiag(*hA); 874613e5ff0Sstefano_zampini hoffd = hypre_ParCSRMatrixOffd(*hA); 8756ea7df73SStefano Zampini /* free temporary memory allocated by PETSc 8766ea7df73SStefano Zampini set pointers to NULL before destroying tA */ 8772cf14000SStefano Zampini if (!sameint) { 8782cf14000SStefano Zampini HYPRE_Int *hi, *hj; 8792cf14000SStefano Zampini 8802cf14000SStefano Zampini hi = hypre_CSRMatrixI(hdiag); 8812cf14000SStefano Zampini hj = hypre_CSRMatrixJ(hdiag); 8829566063dSJacob Faibussowitsch PetscCall(PetscFree2(hi, hj)); 8836ea7df73SStefano Zampini if (ismpiaij) { 8842cf14000SStefano Zampini hi = hypre_CSRMatrixI(hoffd); 8852cf14000SStefano Zampini hj = hypre_CSRMatrixJ(hoffd); 8869566063dSJacob Faibussowitsch PetscCall(PetscFree2(hi, hj)); 8872cf14000SStefano Zampini } 8882cf14000SStefano Zampini } 889c1a070e6SStefano Zampini hypre_CSRMatrixI(hdiag) = NULL; 890c1a070e6SStefano Zampini hypre_CSRMatrixJ(hdiag) = NULL; 891c1a070e6SStefano Zampini hypre_CSRMatrixData(hdiag) = NULL; 8926ea7df73SStefano Zampini if (ismpiaij) { 893c1a070e6SStefano Zampini hypre_CSRMatrixI(hoffd) = NULL; 894c1a070e6SStefano Zampini hypre_CSRMatrixJ(hoffd) = NULL; 895c1a070e6SStefano Zampini hypre_CSRMatrixData(hoffd) = NULL; 8966ea7df73SStefano Zampini } 897613e5ff0Sstefano_zampini hypre_ParCSRMatrixColMapOffd(*hA) = NULL; 898613e5ff0Sstefano_zampini hypre_ParCSRMatrixDestroy(*hA); 899613e5ff0Sstefano_zampini *hA = NULL; 9003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 901613e5ff0Sstefano_zampini } 902613e5ff0Sstefano_zampini 903613e5ff0Sstefano_zampini /* calls RAP from BoomerAMG: 9043dad0653Sstefano_zampini the resulting ParCSR will not own the column and row starts 9056ea7df73SStefano Zampini It looks like we don't need to have the diagonal entries ordered first */ 906d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_RAP(hypre_ParCSRMatrix *hR, hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hP, hypre_ParCSRMatrix **hRAP) 907d71ae5a4SJacob Faibussowitsch { 908a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 909613e5ff0Sstefano_zampini HYPRE_Int P_owns_col_starts, R_owns_row_starts; 910a1d2239cSSatish Balay #endif 911613e5ff0Sstefano_zampini 912613e5ff0Sstefano_zampini PetscFunctionBegin; 913a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 914613e5ff0Sstefano_zampini P_owns_col_starts = hypre_ParCSRMatrixOwnsColStarts(hP); 915613e5ff0Sstefano_zampini R_owns_row_starts = hypre_ParCSRMatrixOwnsRowStarts(hR); 916a1d2239cSSatish Balay #endif 9176ea7df73SStefano Zampini /* can be replaced by version test later */ 9186ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 919792fecdfSBarry Smith PetscStackPushExternal("hypre_ParCSRMatrixRAP"); 9206ea7df73SStefano Zampini *hRAP = hypre_ParCSRMatrixRAP(hR, hA, hP); 9216ea7df73SStefano Zampini PetscStackPop; 9226ea7df73SStefano Zampini #else 923792fecdfSBarry Smith PetscCallExternal(hypre_BoomerAMGBuildCoarseOperator, hR, hA, hP, hRAP); 924792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixSetNumNonzeros, *hRAP); 9256ea7df73SStefano Zampini #endif 926613e5ff0Sstefano_zampini /* hypre_BoomerAMGBuildCoarseOperator steals the col_starts from P and the row_starts from R */ 927a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 928613e5ff0Sstefano_zampini hypre_ParCSRMatrixSetRowStartsOwner(*hRAP, 0); 929613e5ff0Sstefano_zampini hypre_ParCSRMatrixSetColStartsOwner(*hRAP, 0); 930613e5ff0Sstefano_zampini if (P_owns_col_starts) hypre_ParCSRMatrixSetColStartsOwner(hP, 1); 931613e5ff0Sstefano_zampini if (R_owns_row_starts) hypre_ParCSRMatrixSetRowStartsOwner(hR, 1); 932a1d2239cSSatish Balay #endif 9333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 934613e5ff0Sstefano_zampini } 935613e5ff0Sstefano_zampini 936d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat P, Mat C) 937d71ae5a4SJacob Faibussowitsch { 9386f231fbdSstefano_zampini Mat B; 9396abb4441SStefano Zampini hypre_ParCSRMatrix *hA, *hP, *hPtAP = NULL; 9404222ddf1SHong Zhang Mat_Product *product = C->product; 941613e5ff0Sstefano_zampini 942613e5ff0Sstefano_zampini PetscFunctionBegin; 9439566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(A, &hA)); 9449566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(P, &hP)); 9459566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_RAP(hP, hA, hP, &hPtAP)); 9469566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(hPtAP, MATAIJ, PETSC_OWN_POINTER, &B)); 9474222ddf1SHong Zhang 9489566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(C, &B)); 9494222ddf1SHong Zhang C->product = product; 9504222ddf1SHong Zhang 9519566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(A, &hA)); 9529566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(P, &hP)); 9533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9546f231fbdSstefano_zampini } 9556f231fbdSstefano_zampini 956d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatPtAPSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat P, PetscReal fill, Mat C) 957d71ae5a4SJacob Faibussowitsch { 9586f231fbdSstefano_zampini PetscFunctionBegin; 9599566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATAIJ)); 9604222ddf1SHong Zhang C->ops->ptapnumeric = MatPtAPNumeric_AIJ_AIJ_wHYPRE; 9614222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_PtAP; 9623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 963613e5ff0Sstefano_zampini } 964613e5ff0Sstefano_zampini 965d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_HYPRE(Mat A, Mat P, Mat C) 966d71ae5a4SJacob Faibussowitsch { 9674cc28894Sstefano_zampini Mat B; 9684cc28894Sstefano_zampini Mat_HYPRE *hP; 9696abb4441SStefano Zampini hypre_ParCSRMatrix *hA = NULL, *Pparcsr, *ptapparcsr = NULL; 970613e5ff0Sstefano_zampini HYPRE_Int type; 971613e5ff0Sstefano_zampini MPI_Comm comm = PetscObjectComm((PetscObject)A); 9724cc28894Sstefano_zampini PetscBool ishypre; 973613e5ff0Sstefano_zampini 974613e5ff0Sstefano_zampini PetscFunctionBegin; 9759566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre)); 97628b400f6SJacob Faibussowitsch PetscCheck(ishypre, comm, PETSC_ERR_USER, "P should be of type %s", MATHYPRE); 9774cc28894Sstefano_zampini hP = (Mat_HYPRE *)P->data; 978792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type); 97908401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 980792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr); 981613e5ff0Sstefano_zampini 9829566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(A, &hA)); 9839566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, hA, Pparcsr, &ptapparcsr)); 9849566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(A, &hA)); 985225daaf8SStefano Zampini 9864cc28894Sstefano_zampini /* create temporary matrix and merge to C */ 9879566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(ptapparcsr, ((PetscObject)C)->type_name, PETSC_OWN_POINTER, &B)); 9889566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(C, &B)); 9893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9904cc28894Sstefano_zampini } 9914cc28894Sstefano_zampini 992d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_HYPRE_HYPRE(Mat A, Mat P, Mat C) 993d71ae5a4SJacob Faibussowitsch { 9944cc28894Sstefano_zampini Mat B; 9956abb4441SStefano Zampini hypre_ParCSRMatrix *Aparcsr, *Pparcsr, *ptapparcsr = NULL; 9964cc28894Sstefano_zampini Mat_HYPRE *hA, *hP; 9974cc28894Sstefano_zampini PetscBool ishypre; 9984cc28894Sstefano_zampini HYPRE_Int type; 9994cc28894Sstefano_zampini 10004cc28894Sstefano_zampini PetscFunctionBegin; 10019566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre)); 100228b400f6SJacob Faibussowitsch PetscCheck(ishypre, PetscObjectComm((PetscObject)P), PETSC_ERR_USER, "P should be of type %s", MATHYPRE); 10039566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre)); 100428b400f6SJacob Faibussowitsch PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE); 10054cc28894Sstefano_zampini hA = (Mat_HYPRE *)A->data; 10064cc28894Sstefano_zampini hP = (Mat_HYPRE *)P->data; 1007792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type); 100808401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 1009792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type); 101008401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)P), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 1011792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr); 1012792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr); 10139566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, Aparcsr, Pparcsr, &ptapparcsr)); 10149566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(ptapparcsr, MATHYPRE, PETSC_OWN_POINTER, &B)); 10159566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(C, &B)); 10163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10174cc28894Sstefano_zampini } 10184cc28894Sstefano_zampini 1019d501dc42Sstefano_zampini /* calls hypre_ParMatmul 1020d501dc42Sstefano_zampini hypre_ParMatMul uses hypre_ParMatrixCreate with the communicator of hA 10213dad0653Sstefano_zampini hypre_ParMatrixCreate does not duplicate the communicator 10226ea7df73SStefano Zampini It looks like we don't need to have the diagonal entries ordered first */ 1023d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_MatMatMult(hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hB, hypre_ParCSRMatrix **hAB) 1024d71ae5a4SJacob Faibussowitsch { 1025d501dc42Sstefano_zampini PetscFunctionBegin; 10266ea7df73SStefano Zampini /* can be replaced by version test later */ 10276ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 1028792fecdfSBarry Smith PetscStackPushExternal("hypre_ParCSRMatMat"); 10296ea7df73SStefano Zampini *hAB = hypre_ParCSRMatMat(hA, hB); 10306ea7df73SStefano Zampini #else 1031792fecdfSBarry Smith PetscStackPushExternal("hypre_ParMatmul"); 1032d501dc42Sstefano_zampini *hAB = hypre_ParMatmul(hA, hB); 10336ea7df73SStefano Zampini #endif 1034d501dc42Sstefano_zampini PetscStackPop; 10353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1036d501dc42Sstefano_zampini } 1037d501dc42Sstefano_zampini 1038d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C) 1039d71ae5a4SJacob Faibussowitsch { 10405e5acdf2Sstefano_zampini Mat D; 1041d501dc42Sstefano_zampini hypre_ParCSRMatrix *hA, *hB, *hAB = NULL; 10424222ddf1SHong Zhang Mat_Product *product = C->product; 10435e5acdf2Sstefano_zampini 10445e5acdf2Sstefano_zampini PetscFunctionBegin; 10459566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(A, &hA)); 10469566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(B, &hB)); 10479566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_MatMatMult(hA, hB, &hAB)); 10489566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(hAB, MATAIJ, PETSC_OWN_POINTER, &D)); 10494222ddf1SHong Zhang 10509566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(C, &D)); 10514222ddf1SHong Zhang C->product = product; 10524222ddf1SHong Zhang 10539566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(A, &hA)); 10549566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(B, &hB)); 10553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10565e5acdf2Sstefano_zampini } 10575e5acdf2Sstefano_zampini 1058d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatMatMultSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat B, PetscReal fill, Mat C) 1059d71ae5a4SJacob Faibussowitsch { 10605e5acdf2Sstefano_zampini PetscFunctionBegin; 10619566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATAIJ)); 10624222ddf1SHong Zhang C->ops->matmultnumeric = MatMatMultNumeric_AIJ_AIJ_wHYPRE; 10634222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_AB; 10643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10655e5acdf2Sstefano_zampini } 10665e5acdf2Sstefano_zampini 1067d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_HYPRE_HYPRE(Mat A, Mat B, Mat C) 1068d71ae5a4SJacob Faibussowitsch { 1069d501dc42Sstefano_zampini Mat D; 1070d501dc42Sstefano_zampini hypre_ParCSRMatrix *Aparcsr, *Bparcsr, *ABparcsr = NULL; 1071d501dc42Sstefano_zampini Mat_HYPRE *hA, *hB; 1072d501dc42Sstefano_zampini PetscBool ishypre; 1073d501dc42Sstefano_zampini HYPRE_Int type; 10744222ddf1SHong Zhang Mat_Product *product; 1075d501dc42Sstefano_zampini 1076d501dc42Sstefano_zampini PetscFunctionBegin; 10779566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)B, MATHYPRE, &ishypre)); 107828b400f6SJacob Faibussowitsch PetscCheck(ishypre, PetscObjectComm((PetscObject)B), PETSC_ERR_USER, "B should be of type %s", MATHYPRE); 10799566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre)); 108028b400f6SJacob Faibussowitsch PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE); 1081d501dc42Sstefano_zampini hA = (Mat_HYPRE *)A->data; 1082d501dc42Sstefano_zampini hB = (Mat_HYPRE *)B->data; 1083792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type); 108408401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 1085792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hB->ij, &type); 108608401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 1087792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr); 1088792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hB->ij, (void **)&Bparcsr); 10899566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_MatMatMult(Aparcsr, Bparcsr, &ABparcsr)); 10909566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(ABparcsr, MATHYPRE, PETSC_OWN_POINTER, &D)); 10914222ddf1SHong Zhang 1092d501dc42Sstefano_zampini /* need to use HeaderReplace because HeaderMerge messes up with the communicator */ 10934222ddf1SHong Zhang product = C->product; /* save it from MatHeaderReplace() */ 10944222ddf1SHong Zhang C->product = NULL; 10959566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(C, &D)); 10964222ddf1SHong Zhang C->product = product; 1097d501dc42Sstefano_zampini C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE; 10984222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_AB; 10993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1100d501dc42Sstefano_zampini } 1101d501dc42Sstefano_zampini 1102d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultNumeric_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, Mat D) 1103d71ae5a4SJacob Faibussowitsch { 110420e1dc0dSstefano_zampini Mat E; 11056abb4441SStefano Zampini hypre_ParCSRMatrix *hA, *hB, *hC, *hABC = NULL; 110620e1dc0dSstefano_zampini 110720e1dc0dSstefano_zampini PetscFunctionBegin; 11089566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(A, &hA)); 11099566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(B, &hB)); 11109566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(C, &hC)); 11119566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_RAP(hA, hB, hC, &hABC)); 11129566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(hABC, MATAIJ, PETSC_OWN_POINTER, &E)); 11139566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(D, &E)); 11149566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(A, &hA)); 11159566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(B, &hB)); 11169566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(C, &hC)); 11173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 111820e1dc0dSstefano_zampini } 111920e1dc0dSstefano_zampini 1120d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultSymbolic_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, PetscReal fill, Mat D) 1121d71ae5a4SJacob Faibussowitsch { 112220e1dc0dSstefano_zampini PetscFunctionBegin; 11239566063dSJacob Faibussowitsch PetscCall(MatSetType(D, MATAIJ)); 11243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 112520e1dc0dSstefano_zampini } 112620e1dc0dSstefano_zampini 1127d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_AB_HYPRE(Mat C) 1128d71ae5a4SJacob Faibussowitsch { 11294222ddf1SHong Zhang PetscFunctionBegin; 11304222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_AB; 11313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11324222ddf1SHong Zhang } 11334222ddf1SHong Zhang 1134d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_AB(Mat C) 1135d71ae5a4SJacob Faibussowitsch { 11364222ddf1SHong Zhang Mat_Product *product = C->product; 11374222ddf1SHong Zhang PetscBool Ahypre; 11384222ddf1SHong Zhang 11394222ddf1SHong Zhang PetscFunctionBegin; 11409566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)product->A, MATHYPRE, &Ahypre)); 11414222ddf1SHong Zhang if (Ahypre) { /* A is a Hypre matrix */ 11429566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATHYPRE)); 11434222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_AB_HYPRE; 11444222ddf1SHong Zhang C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE; 11453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11466718818eSStefano Zampini } 11473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11484222ddf1SHong Zhang } 11494222ddf1SHong Zhang 1150d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_PtAP_HYPRE(Mat C) 1151d71ae5a4SJacob Faibussowitsch { 11524222ddf1SHong Zhang PetscFunctionBegin; 11534222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_PtAP; 11543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11554222ddf1SHong Zhang } 11564222ddf1SHong Zhang 1157d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_PtAP(Mat C) 1158d71ae5a4SJacob Faibussowitsch { 11594222ddf1SHong Zhang Mat_Product *product = C->product; 11604222ddf1SHong Zhang PetscBool flg; 11614222ddf1SHong Zhang PetscInt type = 0; 11624222ddf1SHong Zhang const char *outTypes[4] = {"aij", "seqaij", "mpiaij", "hypre"}; 11634222ddf1SHong Zhang PetscInt ntype = 4; 11644222ddf1SHong Zhang Mat A = product->A; 11654222ddf1SHong Zhang PetscBool Ahypre; 11664222ddf1SHong Zhang 11674222ddf1SHong Zhang PetscFunctionBegin; 11689566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &Ahypre)); 11694222ddf1SHong Zhang if (Ahypre) { /* A is a Hypre matrix */ 11709566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATHYPRE)); 11714222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE; 11724222ddf1SHong Zhang C->ops->ptapnumeric = MatPtAPNumeric_HYPRE_HYPRE; 11733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11744222ddf1SHong Zhang } 11754222ddf1SHong Zhang 11764222ddf1SHong Zhang /* A is AIJ, P is Hypre, C = PtAP can be either AIJ or Hypre format */ 11774222ddf1SHong Zhang /* Get runtime option */ 11784222ddf1SHong Zhang if (product->api_user) { 1179d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatPtAP_HYPRE", "Mat"); 11809566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-matptap_hypre_outtype", "MatPtAP outtype", "MatPtAP outtype", outTypes, ntype, outTypes[type], &type, &flg)); 1181d0609cedSBarry Smith PetscOptionsEnd(); 11824222ddf1SHong Zhang } else { 1183d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatProduct_PtAP_HYPRE", "Mat"); 11849566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-mat_product_algorithm_hypre_outtype", "MatProduct_PtAP outtype", "MatProduct_PtAP", outTypes, ntype, outTypes[type], &type, &flg)); 1185d0609cedSBarry Smith PetscOptionsEnd(); 11864222ddf1SHong Zhang } 11874222ddf1SHong Zhang 11884222ddf1SHong Zhang if (type == 0 || type == 1 || type == 2) { 11899566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATAIJ)); 11904222ddf1SHong Zhang } else if (type == 3) { 11919566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATHYPRE)); 11924222ddf1SHong Zhang } else SETERRQ(PetscObjectComm((PetscObject)C), PETSC_ERR_SUP, "MatPtAP outtype is not supported"); 11934222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE; 11944222ddf1SHong Zhang C->ops->ptapnumeric = MatPtAPNumeric_AIJ_HYPRE; 11953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11964222ddf1SHong Zhang } 11974222ddf1SHong Zhang 1198d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE(Mat C) 1199d71ae5a4SJacob Faibussowitsch { 12004222ddf1SHong Zhang Mat_Product *product = C->product; 12014222ddf1SHong Zhang 12024222ddf1SHong Zhang PetscFunctionBegin; 12034222ddf1SHong Zhang switch (product->type) { 1204d71ae5a4SJacob Faibussowitsch case MATPRODUCT_AB: 1205d71ae5a4SJacob Faibussowitsch PetscCall(MatProductSetFromOptions_HYPRE_AB(C)); 1206d71ae5a4SJacob Faibussowitsch break; 1207d71ae5a4SJacob Faibussowitsch case MATPRODUCT_PtAP: 1208d71ae5a4SJacob Faibussowitsch PetscCall(MatProductSetFromOptions_HYPRE_PtAP(C)); 1209d71ae5a4SJacob Faibussowitsch break; 1210d71ae5a4SJacob Faibussowitsch default: 1211d71ae5a4SJacob Faibussowitsch break; 12124222ddf1SHong Zhang } 12133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12144222ddf1SHong Zhang } 12154222ddf1SHong Zhang 1216d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTranspose_HYPRE(Mat A, Vec x, Vec y) 1217d71ae5a4SJacob Faibussowitsch { 121863c07aadSStefano Zampini PetscFunctionBegin; 12199566063dSJacob Faibussowitsch PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_TRUE)); 12203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 122163c07aadSStefano Zampini } 122263c07aadSStefano Zampini 1223d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_HYPRE(Mat A, Vec x, Vec y) 1224d71ae5a4SJacob Faibussowitsch { 122563c07aadSStefano Zampini PetscFunctionBegin; 12269566063dSJacob Faibussowitsch PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_FALSE)); 12273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 122863c07aadSStefano Zampini } 122963c07aadSStefano Zampini 1230d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultAdd_HYPRE(Mat A, Vec x, Vec y, Vec z) 1231d71ae5a4SJacob Faibussowitsch { 1232414bd5c3SStefano Zampini PetscFunctionBegin; 123348a46eb9SPierre Jolivet if (y != z) PetscCall(VecCopy(y, z)); 12349566063dSJacob Faibussowitsch PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_FALSE)); 12353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1236414bd5c3SStefano Zampini } 1237414bd5c3SStefano Zampini 1238d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTransposeAdd_HYPRE(Mat A, Vec x, Vec y, Vec z) 1239d71ae5a4SJacob Faibussowitsch { 1240414bd5c3SStefano Zampini PetscFunctionBegin; 124148a46eb9SPierre Jolivet if (y != z) PetscCall(VecCopy(y, z)); 12429566063dSJacob Faibussowitsch PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_TRUE)); 12433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1244414bd5c3SStefano Zampini } 1245414bd5c3SStefano Zampini 1246414bd5c3SStefano Zampini /* y = a * A * x + b * y or y = a * A^t * x + b * y depending on trans */ 1247d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_MultKernel_Private(Mat A, HYPRE_Complex a, Vec x, HYPRE_Complex b, Vec y, PetscBool trans) 1248d71ae5a4SJacob Faibussowitsch { 124963c07aadSStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 125063c07aadSStefano Zampini hypre_ParCSRMatrix *parcsr; 125163c07aadSStefano Zampini hypre_ParVector *hx, *hy; 125263c07aadSStefano Zampini 125363c07aadSStefano Zampini PetscFunctionBegin; 125463c07aadSStefano Zampini if (trans) { 12559566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorPushVecRead(hA->b, x)); 12569566063dSJacob Faibussowitsch if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->x, y)); 12579566063dSJacob Faibussowitsch else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->x, y)); 1258792fecdfSBarry Smith PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hx); 1259792fecdfSBarry Smith PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hy); 126063c07aadSStefano Zampini } else { 12619566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorPushVecRead(hA->x, x)); 12629566063dSJacob Faibussowitsch if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->b, y)); 12639566063dSJacob Faibussowitsch else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->b, y)); 1264792fecdfSBarry Smith PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hx); 1265792fecdfSBarry Smith PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hy); 126663c07aadSStefano Zampini } 1267792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr); 12686ea7df73SStefano Zampini if (trans) { 1269792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixMatvecT, a, parcsr, hx, b, hy); 12706ea7df73SStefano Zampini } else { 1271792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixMatvec, a, parcsr, hx, b, hy); 12726ea7df73SStefano Zampini } 12739566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorPopVec(hA->x)); 12749566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorPopVec(hA->b)); 12753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 127663c07aadSStefano Zampini } 127763c07aadSStefano Zampini 1278d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_HYPRE(Mat A) 1279d71ae5a4SJacob Faibussowitsch { 128063c07aadSStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 128163c07aadSStefano Zampini 128263c07aadSStefano Zampini PetscFunctionBegin; 12839566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorDestroy(&hA->x)); 12849566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorDestroy(&hA->b)); 1285978814f1SStefano Zampini if (hA->ij) { 1286978814f1SStefano Zampini if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL; 1287792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixDestroy, hA->ij); 1288978814f1SStefano Zampini } 12899566063dSJacob Faibussowitsch if (hA->comm) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)A), &hA->comm)); 1290c69f721fSFande Kong 12919566063dSJacob Faibussowitsch PetscCall(MatStashDestroy_Private(&A->stash)); 12929566063dSJacob Faibussowitsch PetscCall(PetscFree(hA->array)); 1293c69f721fSFande Kong 12945fbaff96SJunchao Zhang if (hA->cooMat) { 12955fbaff96SJunchao Zhang PetscCall(MatDestroy(&hA->cooMat)); 1296e77caa6dSBarry Smith PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hA->diagJ, hA->memType)); 1297e77caa6dSBarry Smith PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hA->offdJ, hA->memType)); 1298e77caa6dSBarry Smith PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hA->diag, hA->memType)); 12995fbaff96SJunchao Zhang } 13005fbaff96SJunchao Zhang 13019566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_aij_C", NULL)); 13029566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_is_C", NULL)); 13039566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_hypre_C", NULL)); 13049566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaij_hypre_C", NULL)); 13059566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPRESetPreallocation_C", NULL)); 13069566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPREGetParCSR_C", NULL)); 13075fbaff96SJunchao Zhang PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL)); 13085fbaff96SJunchao Zhang PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL)); 13099566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 13103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 131163c07aadSStefano Zampini } 131263c07aadSStefano Zampini 1313d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetUp_HYPRE(Mat A) 1314d71ae5a4SJacob Faibussowitsch { 13154ec6421dSstefano_zampini PetscFunctionBegin; 13169566063dSJacob Faibussowitsch PetscCall(MatHYPRESetPreallocation(A, PETSC_DEFAULT, NULL, PETSC_DEFAULT, NULL)); 13173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13184ec6421dSstefano_zampini } 13194ec6421dSstefano_zampini 13206ea7df73SStefano Zampini //TODO FIX hypre_CSRMatrixMatvecOutOfPlace 13216ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 1322d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatBindToCPU_HYPRE(Mat A, PetscBool bind) 1323d71ae5a4SJacob Faibussowitsch { 13246ea7df73SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 13256ea7df73SStefano Zampini HYPRE_MemoryLocation hmem = bind ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE; 13266ea7df73SStefano Zampini 13276ea7df73SStefano Zampini PetscFunctionBegin; 13286ea7df73SStefano Zampini A->boundtocpu = bind; 13295fbaff96SJunchao Zhang if (hA->ij && hypre_IJMatrixAssembleFlag(hA->ij) && hmem != hypre_IJMatrixMemoryLocation(hA->ij)) { 13306ea7df73SStefano Zampini hypre_ParCSRMatrix *parcsr; 1331792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr); 1332792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixMigrate, parcsr, hmem); 13336ea7df73SStefano Zampini } 13349566063dSJacob Faibussowitsch if (hA->x) PetscCall(VecHYPRE_IJBindToCPU(hA->x, bind)); 13359566063dSJacob Faibussowitsch if (hA->b) PetscCall(VecHYPRE_IJBindToCPU(hA->b, bind)); 13363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13376ea7df73SStefano Zampini } 13386ea7df73SStefano Zampini #endif 13396ea7df73SStefano Zampini 1340d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_HYPRE(Mat A, MatAssemblyType mode) 1341d71ae5a4SJacob Faibussowitsch { 134263c07aadSStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1343c69f721fSFande Kong PetscMPIInt n; 1344c69f721fSFande Kong PetscInt i, j, rstart, ncols, flg; 1345c69f721fSFande Kong PetscInt *row, *col; 1346c69f721fSFande Kong PetscScalar *val; 134763c07aadSStefano Zampini 134863c07aadSStefano Zampini PetscFunctionBegin; 134908401ef6SPierre Jolivet PetscCheck(mode != MAT_FLUSH_ASSEMBLY, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_FLUSH_ASSEMBLY currently not supported with MATHYPRE"); 1350c69f721fSFande Kong 1351c69f721fSFande Kong if (!A->nooffprocentries) { 1352c69f721fSFande Kong while (1) { 13539566063dSJacob Faibussowitsch PetscCall(MatStashScatterGetMesg_Private(&A->stash, &n, &row, &col, &val, &flg)); 1354c69f721fSFande Kong if (!flg) break; 1355c69f721fSFande Kong 1356c69f721fSFande Kong for (i = 0; i < n;) { 1357c69f721fSFande Kong /* Now identify the consecutive vals belonging to the same row */ 1358c69f721fSFande Kong for (j = i, rstart = row[j]; j < n; j++) { 1359c69f721fSFande Kong if (row[j] != rstart) break; 1360c69f721fSFande Kong } 1361c69f721fSFande Kong if (j < n) ncols = j - i; 1362c69f721fSFande Kong else ncols = n - i; 1363c69f721fSFande Kong /* Now assemble all these values with a single function call */ 13649566063dSJacob Faibussowitsch PetscCall(MatSetValues_HYPRE(A, 1, row + i, ncols, col + i, val + i, A->insertmode)); 1365c69f721fSFande Kong 1366c69f721fSFande Kong i = j; 1367c69f721fSFande Kong } 1368c69f721fSFande Kong } 13699566063dSJacob Faibussowitsch PetscCall(MatStashScatterEnd_Private(&A->stash)); 1370c69f721fSFande Kong } 1371c69f721fSFande Kong 1372792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixAssemble, hA->ij); 1373336664bdSPierre Jolivet /* The assembly routine destroys the aux_matrix, we recreate it here by calling HYPRE_IJMatrixInitialize */ 1374336664bdSPierre 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 */ 1375*651b1cf9SStefano Zampini if (!A->sortedfull) { 1376af1cf968SStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 1377af1cf968SStefano Zampini 1378af1cf968SStefano Zampini /* call destroy just to make sure we do not leak anything */ 1379af1cf968SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij); 1380792fecdfSBarry Smith PetscCallExternal(hypre_AuxParCSRMatrixDestroy, aux_matrix); 1381af1cf968SStefano Zampini hypre_IJMatrixTranslator(hA->ij) = NULL; 1382af1cf968SStefano Zampini 1383af1cf968SStefano Zampini /* Initialize with assembled flag -> it only recreates the aux_par_matrix */ 1384792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij); 1385af1cf968SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij); 13866ea7df73SStefano Zampini if (aux_matrix) { 1387af1cf968SStefano Zampini hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1; /* see comment in MatHYPRESetPreallocation_HYPRE */ 138822235d61SPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 1389792fecdfSBarry Smith PetscCallExternal(hypre_AuxParCSRMatrixInitialize, aux_matrix); 139022235d61SPierre Jolivet #else 1391792fecdfSBarry Smith PetscCallExternal(hypre_AuxParCSRMatrixInitialize_v2, aux_matrix, HYPRE_MEMORY_HOST); 139222235d61SPierre Jolivet #endif 1393af1cf968SStefano Zampini } 13946ea7df73SStefano Zampini } 13956ea7df73SStefano Zampini { 13966ea7df73SStefano Zampini hypre_ParCSRMatrix *parcsr; 13976ea7df73SStefano Zampini 1398792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr); 1399792fecdfSBarry Smith if (!hypre_ParCSRMatrixCommPkg(parcsr)) PetscCallExternal(hypre_MatvecCommPkgCreate, parcsr); 14006ea7df73SStefano Zampini } 14019566063dSJacob Faibussowitsch if (!hA->x) PetscCall(VecHYPRE_IJVectorCreate(A->cmap, &hA->x)); 14029566063dSJacob Faibussowitsch if (!hA->b) PetscCall(VecHYPRE_IJVectorCreate(A->rmap, &hA->b)); 14036ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 14049566063dSJacob Faibussowitsch PetscCall(MatBindToCPU_HYPRE(A, A->boundtocpu)); 14056ea7df73SStefano Zampini #endif 14063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 140763c07aadSStefano Zampini } 140863c07aadSStefano Zampini 1409d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetArray_HYPRE(Mat A, PetscInt size, void **array) 1410d71ae5a4SJacob Faibussowitsch { 1411c69f721fSFande Kong Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1412c69f721fSFande Kong 1413c69f721fSFande Kong PetscFunctionBegin; 1414*651b1cf9SStefano Zampini PetscCheck(hA->array_available, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Temporary space is in use"); 1415c69f721fSFande Kong 1416*651b1cf9SStefano Zampini if (hA->array_size >= size) { 141739accc25SStefano Zampini *array = hA->array; 141839accc25SStefano Zampini } else { 14199566063dSJacob Faibussowitsch PetscCall(PetscFree(hA->array)); 1420*651b1cf9SStefano Zampini hA->array_size = size; 1421*651b1cf9SStefano Zampini PetscCall(PetscMalloc(hA->array_size, &hA->array)); 1422c69f721fSFande Kong *array = hA->array; 1423c69f721fSFande Kong } 1424c69f721fSFande Kong 1425*651b1cf9SStefano Zampini hA->array_available = PETSC_FALSE; 14263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1427c69f721fSFande Kong } 1428c69f721fSFande Kong 1429d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreArray_HYPRE(Mat A, void **array) 1430d71ae5a4SJacob Faibussowitsch { 1431c69f721fSFande Kong Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1432c69f721fSFande Kong 1433c69f721fSFande Kong PetscFunctionBegin; 1434c69f721fSFande Kong *array = NULL; 1435*651b1cf9SStefano Zampini hA->array_available = PETSC_TRUE; 14363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1437c69f721fSFande Kong } 1438c69f721fSFande Kong 1439d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_HYPRE(Mat A, PetscInt nr, const PetscInt rows[], PetscInt nc, const PetscInt cols[], const PetscScalar v[], InsertMode ins) 1440d71ae5a4SJacob Faibussowitsch { 1441d975228cSstefano_zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1442d975228cSstefano_zampini PetscScalar *vals = (PetscScalar *)v; 144339accc25SStefano Zampini HYPRE_Complex *sscr; 1444c69f721fSFande Kong PetscInt *cscr[2]; 1445c69f721fSFande Kong PetscInt i, nzc; 1446*651b1cf9SStefano Zampini PetscInt rst = A->rmap->rstart, ren = A->rmap->rend; 144708defe43SFande Kong void *array = NULL; 1448d975228cSstefano_zampini 1449d975228cSstefano_zampini PetscFunctionBegin; 14509566063dSJacob Faibussowitsch PetscCall(MatGetArray_HYPRE(A, sizeof(PetscInt) * (2 * nc) + sizeof(HYPRE_Complex) * nc * nr, &array)); 1451c69f721fSFande Kong cscr[0] = (PetscInt *)array; 1452c69f721fSFande Kong cscr[1] = ((PetscInt *)array) + nc; 145339accc25SStefano Zampini sscr = (HYPRE_Complex *)(((PetscInt *)array) + nc * 2); 1454d975228cSstefano_zampini for (i = 0, nzc = 0; i < nc; i++) { 1455d975228cSstefano_zampini if (cols[i] >= 0) { 1456d975228cSstefano_zampini cscr[0][nzc] = cols[i]; 1457d975228cSstefano_zampini cscr[1][nzc++] = i; 1458d975228cSstefano_zampini } 1459d975228cSstefano_zampini } 1460c69f721fSFande Kong if (!nzc) { 14619566063dSJacob Faibussowitsch PetscCall(MatRestoreArray_HYPRE(A, &array)); 14623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1463c69f721fSFande Kong } 1464d975228cSstefano_zampini 14656ea7df73SStefano Zampini #if 0 //defined(PETSC_HAVE_HYPRE_DEVICE) 14666ea7df73SStefano Zampini if (HYPRE_MEMORY_HOST != hypre_IJMatrixMemoryLocation(hA->ij)) { 14676ea7df73SStefano Zampini hypre_ParCSRMatrix *parcsr; 14686ea7df73SStefano Zampini 1469792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject,hA->ij,(void**)&parcsr); 1470792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixMigrate,parcsr, HYPRE_MEMORY_HOST); 14716ea7df73SStefano Zampini } 14726ea7df73SStefano Zampini #endif 14736ea7df73SStefano Zampini 1474d975228cSstefano_zampini if (ins == ADD_VALUES) { 1475d975228cSstefano_zampini for (i = 0; i < nr; i++) { 14766ea7df73SStefano Zampini if (rows[i] >= 0) { 1477d975228cSstefano_zampini PetscInt j; 14782cf14000SStefano Zampini HYPRE_Int hnc = (HYPRE_Int)nzc; 14792cf14000SStefano Zampini 1480*651b1cf9SStefano Zampini if (!nzc) continue; 1481*651b1cf9SStefano Zampini /* nonlocal values */ 1482*651b1cf9SStefano Zampini if (rows[i] < rst || rows[i] >= ren) { 1483*651b1cf9SStefano 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]); 1484*651b1cf9SStefano Zampini if (hA->donotstash) continue; 1485*651b1cf9SStefano Zampini } 1486aed4548fSBarry 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]); 14879566063dSJacob Faibussowitsch for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j])); 1488792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixAddToValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr); 1489d975228cSstefano_zampini } 1490d975228cSstefano_zampini vals += nc; 1491d975228cSstefano_zampini } 1492d975228cSstefano_zampini } else { /* INSERT_VALUES */ 1493d975228cSstefano_zampini for (i = 0; i < nr; i++) { 14946ea7df73SStefano Zampini if (rows[i] >= 0) { 1495d975228cSstefano_zampini PetscInt j; 14962cf14000SStefano Zampini HYPRE_Int hnc = (HYPRE_Int)nzc; 14972cf14000SStefano Zampini 1498*651b1cf9SStefano Zampini if (!nzc) continue; 1499aed4548fSBarry 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]); 15009566063dSJacob Faibussowitsch for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j])); 1501c69f721fSFande Kong /* nonlocal values */ 1502*651b1cf9SStefano Zampini if (rows[i] < rst || rows[i] >= ren) { 1503*651b1cf9SStefano 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]); 1504*651b1cf9SStefano Zampini if (!hA->donotstash) PetscCall(MatStashValuesRow_Private(&A->stash, rows[i], nzc, cscr[0], (PetscScalar *)sscr, PETSC_FALSE)); 1505*651b1cf9SStefano Zampini } 1506c69f721fSFande Kong /* local values */ 1507*651b1cf9SStefano Zampini else 1508*651b1cf9SStefano Zampini PetscCallExternal(HYPRE_IJMatrixSetValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr); 1509d975228cSstefano_zampini } 1510d975228cSstefano_zampini vals += nc; 1511d975228cSstefano_zampini } 1512d975228cSstefano_zampini } 1513c69f721fSFande Kong 15149566063dSJacob Faibussowitsch PetscCall(MatRestoreArray_HYPRE(A, &array)); 15153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1516d975228cSstefano_zampini } 1517d975228cSstefano_zampini 1518d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRESetPreallocation_HYPRE(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[]) 1519d71ae5a4SJacob Faibussowitsch { 1520d975228cSstefano_zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 15217d968826Sstefano_zampini HYPRE_Int *hdnnz, *honnz; 152206a29025Sstefano_zampini PetscInt i, rs, re, cs, ce, bs; 1523d975228cSstefano_zampini PetscMPIInt size; 1524d975228cSstefano_zampini 1525d975228cSstefano_zampini PetscFunctionBegin; 15269566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 15279566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 1528d975228cSstefano_zampini rs = A->rmap->rstart; 1529d975228cSstefano_zampini re = A->rmap->rend; 1530d975228cSstefano_zampini cs = A->cmap->rstart; 1531d975228cSstefano_zampini ce = A->cmap->rend; 1532d975228cSstefano_zampini if (!hA->ij) { 1533792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rs, re - 1, cs, ce - 1, &hA->ij); 1534792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR); 1535d975228cSstefano_zampini } else { 15362cf14000SStefano Zampini HYPRE_BigInt hrs, hre, hcs, hce; 1537792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetLocalRange, hA->ij, &hrs, &hre, &hcs, &hce); 1538aed4548fSBarry 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); 1539aed4548fSBarry 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); 1540d975228cSstefano_zampini } 15419566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 154206a29025Sstefano_zampini if (dnz == PETSC_DEFAULT || dnz == PETSC_DECIDE) dnz = 10 * bs; 154306a29025Sstefano_zampini if (onz == PETSC_DEFAULT || onz == PETSC_DECIDE) onz = 10 * bs; 154406a29025Sstefano_zampini 1545d975228cSstefano_zampini if (!dnnz) { 15469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n, &hdnnz)); 1547d975228cSstefano_zampini for (i = 0; i < A->rmap->n; i++) hdnnz[i] = dnz; 1548d975228cSstefano_zampini } else { 15497d968826Sstefano_zampini hdnnz = (HYPRE_Int *)dnnz; 1550d975228cSstefano_zampini } 15519566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 1552d975228cSstefano_zampini if (size > 1) { 1553ddbeb582SStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 1554d975228cSstefano_zampini if (!onnz) { 15559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n, &honnz)); 1556d975228cSstefano_zampini for (i = 0; i < A->rmap->n; i++) honnz[i] = onz; 155722235d61SPierre Jolivet } else honnz = (HYPRE_Int *)onnz; 1558ddbeb582SStefano Zampini /* SetDiagOffdSizes sets hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0, since it seems 1559ddbeb582SStefano Zampini they assume the user will input the entire row values, properly sorted 1560336664bdSPierre Jolivet In PETSc, we don't make such an assumption and set this flag to 1, 1561336664bdSPierre Jolivet unless the option MAT_SORTED_FULL is set to true. 1562ddbeb582SStefano Zampini Also, to avoid possible memory leaks, we destroy and recreate the translator 1563ddbeb582SStefano Zampini This has to be done here, as HYPRE_IJMatrixInitialize will properly initialize 1564ddbeb582SStefano Zampini the IJ matrix for us */ 1565ddbeb582SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij); 1566ddbeb582SStefano Zampini hypre_AuxParCSRMatrixDestroy(aux_matrix); 1567ddbeb582SStefano Zampini hypre_IJMatrixTranslator(hA->ij) = NULL; 1568792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, hA->ij, hdnnz, honnz); 1569ddbeb582SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij); 1570*651b1cf9SStefano Zampini hypre_AuxParCSRMatrixNeedAux(aux_matrix) = !A->sortedfull; 1571d975228cSstefano_zampini } else { 1572d975228cSstefano_zampini honnz = NULL; 1573792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetRowSizes, hA->ij, hdnnz); 1574d975228cSstefano_zampini } 1575ddbeb582SStefano Zampini 1576af1cf968SStefano Zampini /* reset assembled flag and call the initialize method */ 1577af1cf968SStefano Zampini hypre_IJMatrixAssembleFlag(hA->ij) = 0; 15786ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 1579792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij); 15806ea7df73SStefano Zampini #else 1581792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize_v2, hA->ij, HYPRE_MEMORY_HOST); 15826ea7df73SStefano Zampini #endif 158348a46eb9SPierre Jolivet if (!dnnz) PetscCall(PetscFree(hdnnz)); 158448a46eb9SPierre Jolivet if (!onnz && honnz) PetscCall(PetscFree(honnz)); 1585af1cf968SStefano Zampini /* Match AIJ logic */ 158606a29025Sstefano_zampini A->preallocated = PETSC_TRUE; 1587af1cf968SStefano Zampini A->assembled = PETSC_FALSE; 15883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1589d975228cSstefano_zampini } 1590d975228cSstefano_zampini 1591d975228cSstefano_zampini /*@C 1592d975228cSstefano_zampini MatHYPRESetPreallocation - Preallocates memory for a sparse parallel matrix in HYPRE IJ format 1593d975228cSstefano_zampini 1594c3339decSBarry Smith Collective 1595d975228cSstefano_zampini 1596d975228cSstefano_zampini Input Parameters: 1597d975228cSstefano_zampini + A - the matrix 1598d975228cSstefano_zampini . dnz - number of nonzeros per row in DIAGONAL portion of local submatrix 1599d975228cSstefano_zampini (same value is used for all local rows) 1600d975228cSstefano_zampini . dnnz - array containing the number of nonzeros in the various rows of the 1601d975228cSstefano_zampini DIAGONAL portion of the local submatrix (possibly different for each row) 16022ef1f0ffSBarry Smith or `NULL` (`PETSC_NULL_INTEGER` in Fortran), if `d_nz` is used to specify the nonzero structure. 16032ef1f0ffSBarry Smith The size of this array is equal to the number of local rows, i.e `m`. 1604d975228cSstefano_zampini For matrices that will be factored, you must leave room for (and set) 1605d975228cSstefano_zampini the diagonal entry even if it is zero. 1606d975228cSstefano_zampini . onz - number of nonzeros per row in the OFF-DIAGONAL portion of local 1607d975228cSstefano_zampini submatrix (same value is used for all local rows). 1608d975228cSstefano_zampini - onnz - array containing the number of nonzeros in the various rows of the 1609d975228cSstefano_zampini OFF-DIAGONAL portion of the local submatrix (possibly different for 16102ef1f0ffSBarry Smith each row) or `NULL` (`PETSC_NULL_INTEGER` in Fortran), if `o_nz` is used to specify the nonzero 1611d975228cSstefano_zampini structure. The size of this array is equal to the number 16122ef1f0ffSBarry Smith of local rows, i.e `m`. 1613d975228cSstefano_zampini 16142fe279fdSBarry Smith Level: intermediate 16152fe279fdSBarry Smith 161611a5261eSBarry Smith Note: 16172ef1f0ffSBarry Smith If the *nnz parameter is given then the *nz parameter is ignored; for sequential matrices, `onz` and `onnz` are ignored. 1618d975228cSstefano_zampini 16191cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatMPIAIJSetPreallocation()`, `MATHYPRE`, `MATAIJ` 1620d975228cSstefano_zampini @*/ 1621d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHYPRESetPreallocation(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[]) 1622d71ae5a4SJacob Faibussowitsch { 1623d975228cSstefano_zampini PetscFunctionBegin; 1624d975228cSstefano_zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1625d975228cSstefano_zampini PetscValidType(A, 1); 1626cac4c232SBarry Smith PetscTryMethod(A, "MatHYPRESetPreallocation_C", (Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]), (A, dnz, dnnz, onz, onnz)); 16273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1628d975228cSstefano_zampini } 1629d975228cSstefano_zampini 163020f4b53cSBarry Smith /*@C 16312ef1f0ffSBarry Smith MatCreateFromParCSR - Creates a `Mat` from a `hypre_ParCSRMatrix` 1632225daaf8SStefano Zampini 1633225daaf8SStefano Zampini Collective 1634225daaf8SStefano Zampini 1635225daaf8SStefano Zampini Input Parameters: 16362ef1f0ffSBarry Smith + parcsr - the pointer to the `hypre_ParCSRMatrix` 16372ef1f0ffSBarry Smith . mtype - matrix type to be created. Currently `MATAIJ`, `MATIS` and `MATHYPRE` are supported. 163820f4b53cSBarry Smith - copymode - PETSc copying options, see `PetscCopyMode` 1639225daaf8SStefano Zampini 1640225daaf8SStefano Zampini Output Parameter: 1641225daaf8SStefano Zampini . A - the matrix 1642225daaf8SStefano Zampini 1643225daaf8SStefano Zampini Level: intermediate 1644225daaf8SStefano Zampini 16451cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatHYPRE`, `PetscCopyMode` 164620f4b53cSBarry Smith @*/ 1647d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreateFromParCSR(hypre_ParCSRMatrix *parcsr, MatType mtype, PetscCopyMode copymode, Mat *A) 1648d71ae5a4SJacob Faibussowitsch { 1649225daaf8SStefano Zampini Mat T; 1650978814f1SStefano Zampini Mat_HYPRE *hA; 1651978814f1SStefano Zampini MPI_Comm comm; 1652978814f1SStefano Zampini PetscInt rstart, rend, cstart, cend, M, N; 1653d248a85cSRichard Tran Mills PetscBool isseqaij, isseqaijmkl, ismpiaij, isaij, ishyp, isis; 1654978814f1SStefano Zampini 1655978814f1SStefano Zampini PetscFunctionBegin; 1656978814f1SStefano Zampini comm = hypre_ParCSRMatrixComm(parcsr); 16579566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQAIJ, &isseqaij)); 16589566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQAIJMKL, &isseqaijmkl)); 16599566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPIAIJ, &ismpiaij)); 16609566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATAIJ, &isaij)); 16619566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATHYPRE, &ishyp)); 16629566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATIS, &isis)); 1663d248a85cSRichard Tran Mills isaij = (PetscBool)(isseqaij || isseqaijmkl || ismpiaij || isaij); 16646ea7df73SStefano Zampini /* TODO */ 1665aed4548fSBarry 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); 1666978814f1SStefano Zampini /* access ParCSRMatrix */ 1667978814f1SStefano Zampini rstart = hypre_ParCSRMatrixFirstRowIndex(parcsr); 1668978814f1SStefano Zampini rend = hypre_ParCSRMatrixLastRowIndex(parcsr); 1669978814f1SStefano Zampini cstart = hypre_ParCSRMatrixFirstColDiag(parcsr); 1670978814f1SStefano Zampini cend = hypre_ParCSRMatrixLastColDiag(parcsr); 1671978814f1SStefano Zampini M = hypre_ParCSRMatrixGlobalNumRows(parcsr); 1672978814f1SStefano Zampini N = hypre_ParCSRMatrixGlobalNumCols(parcsr); 1673978814f1SStefano Zampini 1674fa92c42cSstefano_zampini /* fix for empty local rows/columns */ 1675fa92c42cSstefano_zampini if (rend < rstart) rend = rstart; 1676fa92c42cSstefano_zampini if (cend < cstart) cend = cstart; 1677fa92c42cSstefano_zampini 1678e6471dc9SStefano Zampini /* PETSc convention */ 1679e6471dc9SStefano Zampini rend++; 1680e6471dc9SStefano Zampini cend++; 1681e6471dc9SStefano Zampini rend = PetscMin(rend, M); 1682e6471dc9SStefano Zampini cend = PetscMin(cend, N); 1683e6471dc9SStefano Zampini 1684978814f1SStefano Zampini /* create PETSc matrix with MatHYPRE */ 16859566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &T)); 16869566063dSJacob Faibussowitsch PetscCall(MatSetSizes(T, rend - rstart, cend - cstart, M, N)); 16879566063dSJacob Faibussowitsch PetscCall(MatSetType(T, MATHYPRE)); 1688225daaf8SStefano Zampini hA = (Mat_HYPRE *)(T->data); 1689978814f1SStefano Zampini 1690978814f1SStefano Zampini /* create HYPRE_IJMatrix */ 1691792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rstart, rend - 1, cstart, cend - 1, &hA->ij); 1692792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR); 169345b8d346SStefano Zampini 16946ea7df73SStefano Zampini // TODO DEV 169545b8d346SStefano Zampini /* create new ParCSR object if needed */ 169645b8d346SStefano Zampini if (ishyp && copymode == PETSC_COPY_VALUES) { 169745b8d346SStefano Zampini hypre_ParCSRMatrix *new_parcsr; 16986ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0) 169945b8d346SStefano Zampini hypre_CSRMatrix *hdiag, *hoffd, *ndiag, *noffd; 170045b8d346SStefano Zampini 17010e6427aaSSatish Balay new_parcsr = hypre_ParCSRMatrixClone(parcsr, 0); 170245b8d346SStefano Zampini hdiag = hypre_ParCSRMatrixDiag(parcsr); 170345b8d346SStefano Zampini hoffd = hypre_ParCSRMatrixOffd(parcsr); 170445b8d346SStefano Zampini ndiag = hypre_ParCSRMatrixDiag(new_parcsr); 170545b8d346SStefano Zampini noffd = hypre_ParCSRMatrixOffd(new_parcsr); 17069566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hypre_CSRMatrixData(ndiag), hypre_CSRMatrixData(hdiag), hypre_CSRMatrixNumNonzeros(hdiag))); 17079566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hypre_CSRMatrixData(noffd), hypre_CSRMatrixData(hoffd), hypre_CSRMatrixNumNonzeros(hoffd))); 17086ea7df73SStefano Zampini #else 17096ea7df73SStefano Zampini new_parcsr = hypre_ParCSRMatrixClone(parcsr, 1); 17106ea7df73SStefano Zampini #endif 171145b8d346SStefano Zampini parcsr = new_parcsr; 171245b8d346SStefano Zampini copymode = PETSC_OWN_POINTER; 171345b8d346SStefano Zampini } 1714978814f1SStefano Zampini 1715978814f1SStefano Zampini /* set ParCSR object */ 1716978814f1SStefano Zampini hypre_IJMatrixObject(hA->ij) = parcsr; 17174ec6421dSstefano_zampini T->preallocated = PETSC_TRUE; 1718978814f1SStefano Zampini 1719978814f1SStefano Zampini /* set assembled flag */ 1720978814f1SStefano Zampini hypre_IJMatrixAssembleFlag(hA->ij) = 1; 17216ea7df73SStefano Zampini #if 0 1722792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize,hA->ij); 17236ea7df73SStefano Zampini #endif 1724225daaf8SStefano Zampini if (ishyp) { 17256d2a658fSstefano_zampini PetscMPIInt myid = 0; 17266d2a658fSstefano_zampini 17276d2a658fSstefano_zampini /* make sure we always have row_starts and col_starts available */ 172848a46eb9SPierre Jolivet if (HYPRE_AssumedPartitionCheck()) PetscCallMPI(MPI_Comm_rank(comm, &myid)); 1729a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 17306d2a658fSstefano_zampini if (!hypre_ParCSRMatrixOwnsColStarts(parcsr)) { 17316d2a658fSstefano_zampini PetscLayout map; 17326d2a658fSstefano_zampini 17339566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(T, NULL, &map)); 17349566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(map)); 17352cf14000SStefano Zampini hypre_ParCSRMatrixColStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid); 17366d2a658fSstefano_zampini } 17376d2a658fSstefano_zampini if (!hypre_ParCSRMatrixOwnsRowStarts(parcsr)) { 17386d2a658fSstefano_zampini PetscLayout map; 17396d2a658fSstefano_zampini 17409566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(T, &map, NULL)); 17419566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(map)); 17422cf14000SStefano Zampini hypre_ParCSRMatrixRowStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid); 17436d2a658fSstefano_zampini } 1744a1d2239cSSatish Balay #endif 1745978814f1SStefano Zampini /* prevent from freeing the pointer */ 1746978814f1SStefano Zampini if (copymode == PETSC_USE_POINTER) hA->inner_free = PETSC_FALSE; 1747225daaf8SStefano Zampini *A = T; 17489566063dSJacob Faibussowitsch PetscCall(MatSetOption(*A, MAT_SORTED_FULL, PETSC_TRUE)); 17499566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*A, MAT_FINAL_ASSEMBLY)); 17509566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*A, MAT_FINAL_ASSEMBLY)); 1751bb4689ddSStefano Zampini } else if (isaij) { 1752bb4689ddSStefano Zampini if (copymode != PETSC_OWN_POINTER) { 1753225daaf8SStefano Zampini /* prevent from freeing the pointer */ 1754225daaf8SStefano Zampini hA->inner_free = PETSC_FALSE; 17559566063dSJacob Faibussowitsch PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INITIAL_MATRIX, A)); 17569566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 1757225daaf8SStefano Zampini } else { /* AIJ return type with PETSC_OWN_POINTER */ 17589566063dSJacob Faibussowitsch PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INPLACE_MATRIX, &T)); 1759225daaf8SStefano Zampini *A = T; 1760225daaf8SStefano Zampini } 1761bb4689ddSStefano Zampini } else if (isis) { 17629566063dSJacob Faibussowitsch PetscCall(MatConvert_HYPRE_IS(T, MATIS, MAT_INITIAL_MATRIX, A)); 17638cfe8d00SStefano Zampini if (copymode != PETSC_OWN_POINTER) hA->inner_free = PETSC_FALSE; 17649566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 1765bb4689ddSStefano Zampini } 17663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1767978814f1SStefano Zampini } 1768978814f1SStefano Zampini 1769d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPREGetParCSR_HYPRE(Mat A, hypre_ParCSRMatrix **parcsr) 1770d71ae5a4SJacob Faibussowitsch { 1771dd9c0a25Sstefano_zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1772dd9c0a25Sstefano_zampini HYPRE_Int type; 1773dd9c0a25Sstefano_zampini 1774dd9c0a25Sstefano_zampini PetscFunctionBegin; 177528b400f6SJacob Faibussowitsch PetscCheck(hA->ij, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "HYPRE_IJMatrix not present"); 1776792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type); 177708401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "HYPRE_IJMatrix is not of type HYPRE_PARCSR"); 1778792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)parcsr); 17793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1780dd9c0a25Sstefano_zampini } 1781dd9c0a25Sstefano_zampini 178220f4b53cSBarry Smith /*@C 1783dd9c0a25Sstefano_zampini MatHYPREGetParCSR - Gets the pointer to the ParCSR matrix 1784dd9c0a25Sstefano_zampini 17852ef1f0ffSBarry Smith Not Collective 1786dd9c0a25Sstefano_zampini 178720f4b53cSBarry Smith Input Parameter: 178820f4b53cSBarry Smith . A - the `MATHYPRE` object 1789dd9c0a25Sstefano_zampini 1790dd9c0a25Sstefano_zampini Output Parameter: 17912ef1f0ffSBarry Smith . parcsr - the pointer to the `hypre_ParCSRMatrix` 1792dd9c0a25Sstefano_zampini 1793dd9c0a25Sstefano_zampini Level: intermediate 1794dd9c0a25Sstefano_zampini 17951cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatHYPRE`, `PetscCopyMode` 179620f4b53cSBarry Smith @*/ 1797d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHYPREGetParCSR(Mat A, hypre_ParCSRMatrix **parcsr) 1798d71ae5a4SJacob Faibussowitsch { 1799dd9c0a25Sstefano_zampini PetscFunctionBegin; 1800dd9c0a25Sstefano_zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1801dd9c0a25Sstefano_zampini PetscValidType(A, 1); 1802cac4c232SBarry Smith PetscUseMethod(A, "MatHYPREGetParCSR_C", (Mat, hypre_ParCSRMatrix **), (A, parcsr)); 18033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1804dd9c0a25Sstefano_zampini } 1805dd9c0a25Sstefano_zampini 1806d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_HYPRE(Mat A, PetscBool *missing, PetscInt *dd) 1807d71ae5a4SJacob Faibussowitsch { 180868ec7858SStefano Zampini hypre_ParCSRMatrix *parcsr; 180968ec7858SStefano Zampini hypre_CSRMatrix *ha; 181068ec7858SStefano Zampini PetscInt rst; 181168ec7858SStefano Zampini 181268ec7858SStefano Zampini PetscFunctionBegin; 181308401ef6SPierre Jolivet PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented with non-square diagonal blocks"); 18149566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rst, NULL)); 18159566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 181668ec7858SStefano Zampini if (missing) *missing = PETSC_FALSE; 181768ec7858SStefano Zampini if (dd) *dd = -1; 181868ec7858SStefano Zampini ha = hypre_ParCSRMatrixDiag(parcsr); 181968ec7858SStefano Zampini if (ha) { 182068299464SStefano Zampini PetscInt size, i; 182168299464SStefano Zampini HYPRE_Int *ii, *jj; 182268ec7858SStefano Zampini 182368ec7858SStefano Zampini size = hypre_CSRMatrixNumRows(ha); 182468ec7858SStefano Zampini ii = hypre_CSRMatrixI(ha); 182568ec7858SStefano Zampini jj = hypre_CSRMatrixJ(ha); 182668ec7858SStefano Zampini for (i = 0; i < size; i++) { 182768ec7858SStefano Zampini PetscInt j; 182868ec7858SStefano Zampini PetscBool found = PETSC_FALSE; 182968ec7858SStefano Zampini 18309371c9d4SSatish Balay for (j = ii[i]; j < ii[i + 1] && !found; j++) found = (jj[j] == i) ? PETSC_TRUE : PETSC_FALSE; 183168ec7858SStefano Zampini 183268ec7858SStefano Zampini if (!found) { 18333ba16761SJacob Faibussowitsch PetscCall(PetscInfo(A, "Matrix is missing local diagonal entry %" PetscInt_FMT "\n", i)); 183468ec7858SStefano Zampini if (missing) *missing = PETSC_TRUE; 183568ec7858SStefano Zampini if (dd) *dd = i + rst; 18363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 183768ec7858SStefano Zampini } 183868ec7858SStefano Zampini } 183968ec7858SStefano Zampini if (!size) { 18403ba16761SJacob Faibussowitsch PetscCall(PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n")); 184168ec7858SStefano Zampini if (missing) *missing = PETSC_TRUE; 184268ec7858SStefano Zampini if (dd) *dd = rst; 184368ec7858SStefano Zampini } 184468ec7858SStefano Zampini } else { 18453ba16761SJacob Faibussowitsch PetscCall(PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n")); 184668ec7858SStefano Zampini if (missing) *missing = PETSC_TRUE; 184768ec7858SStefano Zampini if (dd) *dd = rst; 184868ec7858SStefano Zampini } 18493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 185068ec7858SStefano Zampini } 185168ec7858SStefano Zampini 1852d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatScale_HYPRE(Mat A, PetscScalar s) 1853d71ae5a4SJacob Faibussowitsch { 185468ec7858SStefano Zampini hypre_ParCSRMatrix *parcsr; 18556ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 185668ec7858SStefano Zampini hypre_CSRMatrix *ha; 18576ea7df73SStefano Zampini #endif 185839accc25SStefano Zampini HYPRE_Complex hs; 185968ec7858SStefano Zampini 186068ec7858SStefano Zampini PetscFunctionBegin; 18619566063dSJacob Faibussowitsch PetscCall(PetscHYPREScalarCast(s, &hs)); 18629566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 18636ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 19, 0) 1864792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixScale, parcsr, hs); 18656ea7df73SStefano Zampini #else /* diagonal part */ 186668ec7858SStefano Zampini ha = hypre_ParCSRMatrixDiag(parcsr); 186768ec7858SStefano Zampini if (ha) { 186868299464SStefano Zampini PetscInt size, i; 186968299464SStefano Zampini HYPRE_Int *ii; 187039accc25SStefano Zampini HYPRE_Complex *a; 187168ec7858SStefano Zampini 187268ec7858SStefano Zampini size = hypre_CSRMatrixNumRows(ha); 187368ec7858SStefano Zampini a = hypre_CSRMatrixData(ha); 187468ec7858SStefano Zampini ii = hypre_CSRMatrixI(ha); 187539accc25SStefano Zampini for (i = 0; i < ii[size]; i++) a[i] *= hs; 187668ec7858SStefano Zampini } 187768ec7858SStefano Zampini /* offdiagonal part */ 187868ec7858SStefano Zampini ha = hypre_ParCSRMatrixOffd(parcsr); 187968ec7858SStefano Zampini if (ha) { 188068299464SStefano Zampini PetscInt size, i; 188168299464SStefano Zampini HYPRE_Int *ii; 188239accc25SStefano Zampini HYPRE_Complex *a; 188368ec7858SStefano Zampini 188468ec7858SStefano Zampini size = hypre_CSRMatrixNumRows(ha); 188568ec7858SStefano Zampini a = hypre_CSRMatrixData(ha); 188668ec7858SStefano Zampini ii = hypre_CSRMatrixI(ha); 188739accc25SStefano Zampini for (i = 0; i < ii[size]; i++) a[i] *= hs; 188868ec7858SStefano Zampini } 18896ea7df73SStefano Zampini #endif 18903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 189168ec7858SStefano Zampini } 189268ec7858SStefano Zampini 1893d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_HYPRE(Mat A, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 1894d71ae5a4SJacob Faibussowitsch { 189568ec7858SStefano Zampini hypre_ParCSRMatrix *parcsr; 189668299464SStefano Zampini HYPRE_Int *lrows; 189768299464SStefano Zampini PetscInt rst, ren, i; 189868ec7858SStefano Zampini 189968ec7858SStefano Zampini PetscFunctionBegin; 190008401ef6SPierre Jolivet PetscCheck(!x && !b, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "To be implemented"); 19019566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 19029566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRows, &lrows)); 19039566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rst, &ren)); 190468ec7858SStefano Zampini for (i = 0; i < numRows; i++) { 19057a46b595SBarry Smith PetscCheck(rows[i] >= rst && rows[i] < ren, PETSC_COMM_SELF, PETSC_ERR_SUP, "Non-local rows not yet supported"); 190668ec7858SStefano Zampini lrows[i] = rows[i] - rst; 190768ec7858SStefano Zampini } 1908792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixEliminateRowsCols, parcsr, numRows, lrows); 19099566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 19103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 191168ec7858SStefano Zampini } 191268ec7858SStefano Zampini 1913d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPRE_CSRMatrix(hypre_CSRMatrix *ha) 1914d71ae5a4SJacob Faibussowitsch { 1915c69f721fSFande Kong PetscFunctionBegin; 1916c69f721fSFande Kong if (ha) { 1917c69f721fSFande Kong HYPRE_Int *ii, size; 1918c69f721fSFande Kong HYPRE_Complex *a; 1919c69f721fSFande Kong 1920c69f721fSFande Kong size = hypre_CSRMatrixNumRows(ha); 1921c69f721fSFande Kong a = hypre_CSRMatrixData(ha); 1922c69f721fSFande Kong ii = hypre_CSRMatrixI(ha); 1923c69f721fSFande Kong 19249566063dSJacob Faibussowitsch if (a) PetscCall(PetscArrayzero(a, ii[size])); 1925c69f721fSFande Kong } 19263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1927c69f721fSFande Kong } 1928c69f721fSFande Kong 1929d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroEntries_HYPRE(Mat A) 1930d71ae5a4SJacob Faibussowitsch { 19316ea7df73SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 19326ea7df73SStefano Zampini 19336ea7df73SStefano Zampini PetscFunctionBegin; 19346ea7df73SStefano Zampini if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(hA->ij)) { 1935792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetConstantValues, hA->ij, 0.0); 19366ea7df73SStefano Zampini } else { 1937c69f721fSFande Kong hypre_ParCSRMatrix *parcsr; 1938c69f721fSFande Kong 19399566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 19409566063dSJacob Faibussowitsch PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr))); 19419566063dSJacob Faibussowitsch PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr))); 19426ea7df73SStefano Zampini } 19433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1944c69f721fSFande Kong } 1945c69f721fSFande Kong 1946d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_HYPRE_CSRMatrix(hypre_CSRMatrix *hA, PetscInt N, const PetscInt rows[], HYPRE_Complex diag) 1947d71ae5a4SJacob Faibussowitsch { 194839accc25SStefano Zampini PetscInt ii; 194939accc25SStefano Zampini HYPRE_Int *i, *j; 195039accc25SStefano Zampini HYPRE_Complex *a; 1951c69f721fSFande Kong 1952c69f721fSFande Kong PetscFunctionBegin; 19533ba16761SJacob Faibussowitsch if (!hA) PetscFunctionReturn(PETSC_SUCCESS); 1954c69f721fSFande Kong 195539accc25SStefano Zampini i = hypre_CSRMatrixI(hA); 195639accc25SStefano Zampini j = hypre_CSRMatrixJ(hA); 1957c69f721fSFande Kong a = hypre_CSRMatrixData(hA); 1958c69f721fSFande Kong 1959c69f721fSFande Kong for (ii = 0; ii < N; ii++) { 196039accc25SStefano Zampini HYPRE_Int jj, ibeg, iend, irow; 196139accc25SStefano Zampini 1962c69f721fSFande Kong irow = rows[ii]; 1963c69f721fSFande Kong ibeg = i[irow]; 1964c69f721fSFande Kong iend = i[irow + 1]; 1965c69f721fSFande Kong for (jj = ibeg; jj < iend; jj++) 1966c69f721fSFande Kong if (j[jj] == irow) a[jj] = diag; 1967c69f721fSFande Kong else a[jj] = 0.0; 1968c69f721fSFande Kong } 19693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1970c69f721fSFande Kong } 1971c69f721fSFande Kong 1972d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_HYPRE(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 1973d71ae5a4SJacob Faibussowitsch { 1974c69f721fSFande Kong hypre_ParCSRMatrix *parcsr; 1975c69f721fSFande Kong PetscInt *lrows, len; 197639accc25SStefano Zampini HYPRE_Complex hdiag; 1977c69f721fSFande Kong 1978c69f721fSFande Kong PetscFunctionBegin; 197908401ef6SPierre Jolivet PetscCheck(!x && !b, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Does not support to modify the solution and the right hand size"); 19809566063dSJacob Faibussowitsch PetscCall(PetscHYPREScalarCast(diag, &hdiag)); 1981c69f721fSFande Kong /* retrieve the internal matrix */ 19829566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 1983c69f721fSFande Kong /* get locally owned rows */ 19849566063dSJacob Faibussowitsch PetscCall(MatZeroRowsMapLocal_Private(A, N, rows, &len, &lrows)); 1985c69f721fSFande Kong /* zero diagonal part */ 19869566063dSJacob Faibussowitsch PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr), len, lrows, hdiag)); 1987c69f721fSFande Kong /* zero off-diagonal part */ 19889566063dSJacob Faibussowitsch PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr), len, lrows, 0.0)); 1989c69f721fSFande Kong 19909566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 19913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1992c69f721fSFande Kong } 1993c69f721fSFande Kong 1994d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_HYPRE(Mat mat, MatAssemblyType mode) 1995d71ae5a4SJacob Faibussowitsch { 1996c69f721fSFande Kong PetscFunctionBegin; 19973ba16761SJacob Faibussowitsch if (mat->nooffprocentries) PetscFunctionReturn(PETSC_SUCCESS); 1998c69f721fSFande Kong 19999566063dSJacob Faibussowitsch PetscCall(MatStashScatterBegin_Private(mat, &mat->stash, mat->rmap->range)); 20003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2001c69f721fSFande Kong } 2002c69f721fSFande Kong 2003d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) 2004d71ae5a4SJacob Faibussowitsch { 2005c69f721fSFande Kong hypre_ParCSRMatrix *parcsr; 20062cf14000SStefano Zampini HYPRE_Int hnz; 2007c69f721fSFande Kong 2008c69f721fSFande Kong PetscFunctionBegin; 2009c69f721fSFande Kong /* retrieve the internal matrix */ 20109566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 2011c69f721fSFande Kong /* call HYPRE API */ 2012792fecdfSBarry Smith PetscCallExternal(HYPRE_ParCSRMatrixGetRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v); 20132cf14000SStefano Zampini if (nz) *nz = (PetscInt)hnz; 20143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2015c69f721fSFande Kong } 2016c69f721fSFande Kong 2017d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) 2018d71ae5a4SJacob Faibussowitsch { 2019c69f721fSFande Kong hypre_ParCSRMatrix *parcsr; 20202cf14000SStefano Zampini HYPRE_Int hnz; 2021c69f721fSFande Kong 2022c69f721fSFande Kong PetscFunctionBegin; 2023c69f721fSFande Kong /* retrieve the internal matrix */ 20249566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 2025c69f721fSFande Kong /* call HYPRE API */ 20262cf14000SStefano Zampini hnz = nz ? (HYPRE_Int)(*nz) : 0; 2027792fecdfSBarry Smith PetscCallExternal(HYPRE_ParCSRMatrixRestoreRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v); 20283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2029c69f721fSFande Kong } 2030c69f721fSFande Kong 2031d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetValues_HYPRE(Mat A, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2032d71ae5a4SJacob Faibussowitsch { 203345b8d346SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 2034c69f721fSFande Kong PetscInt i; 20351d4906efSStefano Zampini 2036c69f721fSFande Kong PetscFunctionBegin; 20373ba16761SJacob Faibussowitsch if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2038c69f721fSFande Kong /* Ignore negative row indices 2039c69f721fSFande Kong * And negative column indices should be automatically ignored in hypre 2040c69f721fSFande Kong * */ 20412cf14000SStefano Zampini for (i = 0; i < m; i++) { 20422cf14000SStefano Zampini if (idxm[i] >= 0) { 20432cf14000SStefano Zampini HYPRE_Int hn = (HYPRE_Int)n; 2044792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetValues, hA->ij, 1, &hn, (HYPRE_BigInt *)&idxm[i], (HYPRE_BigInt *)idxn, (HYPRE_Complex *)(v + i * n)); 20452cf14000SStefano Zampini } 20462cf14000SStefano Zampini } 20473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2048c69f721fSFande Kong } 2049c69f721fSFande Kong 2050d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_HYPRE(Mat A, MatOption op, PetscBool flg) 2051d71ae5a4SJacob Faibussowitsch { 2052ddbeb582SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 2053ddbeb582SStefano Zampini 2054ddbeb582SStefano Zampini PetscFunctionBegin; 2055c6698e78SStefano Zampini switch (op) { 2056ddbeb582SStefano Zampini case MAT_NO_OFF_PROC_ENTRIES: 205748a46eb9SPierre Jolivet if (flg) PetscCallExternal(HYPRE_IJMatrixSetMaxOffProcElmts, hA->ij, 0); 2058ddbeb582SStefano Zampini break; 2059*651b1cf9SStefano Zampini case MAT_IGNORE_OFF_PROC_ENTRIES: 2060*651b1cf9SStefano Zampini hA->donotstash = flg; 2061d71ae5a4SJacob Faibussowitsch break; 2062d71ae5a4SJacob Faibussowitsch default: 2063d71ae5a4SJacob Faibussowitsch break; 2064ddbeb582SStefano Zampini } 20653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2066ddbeb582SStefano Zampini } 2067c69f721fSFande Kong 2068d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_HYPRE(Mat A, PetscViewer view) 2069d71ae5a4SJacob Faibussowitsch { 207045b8d346SStefano Zampini PetscViewerFormat format; 207145b8d346SStefano Zampini 207245b8d346SStefano Zampini PetscFunctionBegin; 20739566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(view, &format)); 20743ba16761SJacob Faibussowitsch if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(PETSC_SUCCESS); 207545b8d346SStefano Zampini if (format != PETSC_VIEWER_NATIVE) { 20766ea7df73SStefano Zampini Mat B; 20776ea7df73SStefano Zampini hypre_ParCSRMatrix *parcsr; 20786ea7df73SStefano Zampini PetscErrorCode (*mview)(Mat, PetscViewer) = NULL; 20796ea7df73SStefano Zampini 20809566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 20819566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(parcsr, MATAIJ, PETSC_USE_POINTER, &B)); 20829566063dSJacob Faibussowitsch PetscCall(MatGetOperation(B, MATOP_VIEW, (void (**)(void)) & mview)); 208328b400f6SJacob Faibussowitsch PetscCheck(mview, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Missing view operation"); 20849566063dSJacob Faibussowitsch PetscCall((*mview)(B, view)); 20859566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 208645b8d346SStefano Zampini } else { 208745b8d346SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 208845b8d346SStefano Zampini PetscMPIInt size; 208945b8d346SStefano Zampini PetscBool isascii; 209045b8d346SStefano Zampini const char *filename; 209145b8d346SStefano Zampini 209245b8d346SStefano Zampini /* HYPRE uses only text files */ 20939566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERASCII, &isascii)); 209428b400f6SJacob Faibussowitsch PetscCheck(isascii, PetscObjectComm((PetscObject)view), PETSC_ERR_SUP, "PetscViewerType %s: native HYPRE format needs PETSCVIEWERASCII", ((PetscObject)view)->type_name); 20959566063dSJacob Faibussowitsch PetscCall(PetscViewerFileGetName(view, &filename)); 2096792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixPrint, hA->ij, filename); 20979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(hA->comm, &size)); 209845b8d346SStefano Zampini if (size > 1) { 20999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(view, "Matrix files: %s.%05d ... %s.%05d\n", filename, 0, filename, size - 1)); 210045b8d346SStefano Zampini } else { 21019566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(view, "Matrix file: %s.%05d\n", filename, 0)); 210245b8d346SStefano Zampini } 210345b8d346SStefano Zampini } 21043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 210545b8d346SStefano Zampini } 210645b8d346SStefano Zampini 2107d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCopy_HYPRE(Mat A, Mat B, MatStructure str) 2108d71ae5a4SJacob Faibussowitsch { 2109465edc17SStefano Zampini hypre_ParCSRMatrix *acsr, *bcsr; 2110465edc17SStefano Zampini 2111465edc17SStefano Zampini PetscFunctionBegin; 2112465edc17SStefano Zampini if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) { 21139566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &acsr)); 21149566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(B, &bcsr)); 2115792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixCopy, acsr, bcsr, 1); 21169566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_SORTED_FULL, PETSC_TRUE)); /* "perfect" preallocation, so no need for hypre_AuxParCSRMatrixNeedAux */ 21179566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 21189566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 2119465edc17SStefano Zampini } else { 21209566063dSJacob Faibussowitsch PetscCall(MatCopy_Basic(A, B, str)); 2121465edc17SStefano Zampini } 21223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2123465edc17SStefano Zampini } 2124465edc17SStefano Zampini 2125d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_HYPRE(Mat A, Vec d) 2126d71ae5a4SJacob Faibussowitsch { 21276305df00SStefano Zampini hypre_ParCSRMatrix *parcsr; 21286305df00SStefano Zampini hypre_CSRMatrix *dmat; 212939accc25SStefano Zampini HYPRE_Complex *a; 213039accc25SStefano Zampini HYPRE_Complex *data = NULL; 21312cf14000SStefano Zampini HYPRE_Int *diag = NULL; 21322cf14000SStefano Zampini PetscInt i; 21336305df00SStefano Zampini PetscBool cong; 21346305df00SStefano Zampini 21356305df00SStefano Zampini PetscFunctionBegin; 21369566063dSJacob Faibussowitsch PetscCall(MatHasCongruentLayouts(A, &cong)); 213728b400f6SJacob Faibussowitsch PetscCheck(cong, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only for square matrices with same local distributions of rows and columns"); 213876bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 21396305df00SStefano Zampini PetscBool miss; 21409566063dSJacob Faibussowitsch PetscCall(MatMissingDiagonal(A, &miss, NULL)); 214108401ef6SPierre Jolivet PetscCheck(!miss || !A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented when diagonal entries are missing"); 21426305df00SStefano Zampini } 21439566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 21446305df00SStefano Zampini dmat = hypre_ParCSRMatrixDiag(parcsr); 21456305df00SStefano Zampini if (dmat) { 214639accc25SStefano Zampini /* this cast fixes the clang error: implicit conversion from 'HYPRE_Complex' (aka '_Complex double') to 'double' is not permitted in C++ */ 21479566063dSJacob Faibussowitsch PetscCall(VecGetArray(d, (PetscScalar **)&a)); 21482cf14000SStefano Zampini diag = hypre_CSRMatrixI(dmat); 214939accc25SStefano Zampini data = hypre_CSRMatrixData(dmat); 21506305df00SStefano Zampini for (i = 0; i < A->rmap->n; i++) a[i] = data[diag[i]]; 21519566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(d, (PetscScalar **)&a)); 21526305df00SStefano Zampini } 21533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21546305df00SStefano Zampini } 21556305df00SStefano Zampini 2156363d496dSStefano Zampini #include <petscblaslapack.h> 2157363d496dSStefano Zampini 2158d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAXPY_HYPRE(Mat Y, PetscScalar a, Mat X, MatStructure str) 2159d71ae5a4SJacob Faibussowitsch { 2160363d496dSStefano Zampini PetscFunctionBegin; 21616ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 21626ea7df73SStefano Zampini { 21636ea7df73SStefano Zampini Mat B; 21646ea7df73SStefano Zampini hypre_ParCSRMatrix *x, *y, *z; 21656ea7df73SStefano Zampini 21669566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR(Y, &y)); 21679566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR(X, &x)); 2168792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixAdd, 1.0, y, 1.0, x, &z); 21699566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(z, MATHYPRE, PETSC_OWN_POINTER, &B)); 21709566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(Y, &B)); 21716ea7df73SStefano Zampini } 21726ea7df73SStefano Zampini #else 2173363d496dSStefano Zampini if (str == SAME_NONZERO_PATTERN) { 2174363d496dSStefano Zampini hypre_ParCSRMatrix *x, *y; 2175363d496dSStefano Zampini hypre_CSRMatrix *xloc, *yloc; 2176363d496dSStefano Zampini PetscInt xnnz, ynnz; 217739accc25SStefano Zampini HYPRE_Complex *xarr, *yarr; 2178363d496dSStefano Zampini PetscBLASInt one = 1, bnz; 2179363d496dSStefano Zampini 21809566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR(Y, &y)); 21819566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR(X, &x)); 2182363d496dSStefano Zampini 2183363d496dSStefano Zampini /* diagonal block */ 2184363d496dSStefano Zampini xloc = hypre_ParCSRMatrixDiag(x); 2185363d496dSStefano Zampini yloc = hypre_ParCSRMatrixDiag(y); 2186363d496dSStefano Zampini xnnz = 0; 2187363d496dSStefano Zampini ynnz = 0; 2188363d496dSStefano Zampini xarr = NULL; 2189363d496dSStefano Zampini yarr = NULL; 2190363d496dSStefano Zampini if (xloc) { 219139accc25SStefano Zampini xarr = hypre_CSRMatrixData(xloc); 2192363d496dSStefano Zampini xnnz = hypre_CSRMatrixNumNonzeros(xloc); 2193363d496dSStefano Zampini } 2194363d496dSStefano Zampini if (yloc) { 219539accc25SStefano Zampini yarr = hypre_CSRMatrixData(yloc); 2196363d496dSStefano Zampini ynnz = hypre_CSRMatrixNumNonzeros(yloc); 2197363d496dSStefano Zampini } 219808401ef6SPierre Jolivet PetscCheck(xnnz == ynnz, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Different number of nonzeros in diagonal block %" PetscInt_FMT " != %" PetscInt_FMT, xnnz, ynnz); 21999566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(xnnz, &bnz)); 2200792fecdfSBarry Smith PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one)); 2201363d496dSStefano Zampini 2202363d496dSStefano Zampini /* off-diagonal block */ 2203363d496dSStefano Zampini xloc = hypre_ParCSRMatrixOffd(x); 2204363d496dSStefano Zampini yloc = hypre_ParCSRMatrixOffd(y); 2205363d496dSStefano Zampini xnnz = 0; 2206363d496dSStefano Zampini ynnz = 0; 2207363d496dSStefano Zampini xarr = NULL; 2208363d496dSStefano Zampini yarr = NULL; 2209363d496dSStefano Zampini if (xloc) { 221039accc25SStefano Zampini xarr = hypre_CSRMatrixData(xloc); 2211363d496dSStefano Zampini xnnz = hypre_CSRMatrixNumNonzeros(xloc); 2212363d496dSStefano Zampini } 2213363d496dSStefano Zampini if (yloc) { 221439accc25SStefano Zampini yarr = hypre_CSRMatrixData(yloc); 2215363d496dSStefano Zampini ynnz = hypre_CSRMatrixNumNonzeros(yloc); 2216363d496dSStefano Zampini } 221708401ef6SPierre 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); 22189566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(xnnz, &bnz)); 2219792fecdfSBarry Smith PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one)); 2220363d496dSStefano Zampini } else if (str == SUBSET_NONZERO_PATTERN) { 22219566063dSJacob Faibussowitsch PetscCall(MatAXPY_Basic(Y, a, X, str)); 2222363d496dSStefano Zampini } else { 2223363d496dSStefano Zampini Mat B; 2224363d496dSStefano Zampini 22259566063dSJacob Faibussowitsch PetscCall(MatAXPY_Basic_Preallocate(Y, X, &B)); 22269566063dSJacob Faibussowitsch PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str)); 22279566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(Y, &B)); 2228363d496dSStefano Zampini } 22296ea7df73SStefano Zampini #endif 22303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2231363d496dSStefano Zampini } 2232363d496dSStefano Zampini 22332c4ab24aSJunchao Zhang /* Attach cooMat to hypre matrix mat. The two matrices will share the same data array */ 22342c4ab24aSJunchao Zhang static PetscErrorCode MatAttachCOOMat_HYPRE(Mat mat, Mat cooMat) 22352c4ab24aSJunchao Zhang { 22362c4ab24aSJunchao Zhang Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data; 22372c4ab24aSJunchao Zhang hypre_CSRMatrix *diag, *offd; 22382c4ab24aSJunchao Zhang hypre_ParCSRMatrix *parCSR; 22392c4ab24aSJunchao Zhang HYPRE_MemoryLocation hypreMemtype = HYPRE_MEMORY_HOST; 22402c4ab24aSJunchao Zhang PetscMemType petscMemtype; 22412c4ab24aSJunchao Zhang Mat A, B; 22422c4ab24aSJunchao Zhang PetscScalar *Aa, *Ba; 22432c4ab24aSJunchao Zhang PetscMPIInt size; 22442c4ab24aSJunchao Zhang MPI_Comm comm; 22452c4ab24aSJunchao Zhang PetscLayout rmap; 22462c4ab24aSJunchao Zhang 22472c4ab24aSJunchao Zhang PetscFunctionBegin; 22482c4ab24aSJunchao Zhang PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 22492c4ab24aSJunchao Zhang PetscCallMPI(MPI_Comm_size(comm, &size)); 22502c4ab24aSJunchao Zhang PetscCall(MatGetLayouts(mat, &rmap, NULL)); 22512c4ab24aSJunchao Zhang 22522c4ab24aSJunchao Zhang /* Alias cooMat's data array to IJMatrix's */ 22532c4ab24aSJunchao Zhang PetscCallExternal(HYPRE_IJMatrixGetObject, hmat->ij, (void **)&parCSR); 22542c4ab24aSJunchao Zhang diag = hypre_ParCSRMatrixDiag(parCSR); 22552c4ab24aSJunchao Zhang offd = hypre_ParCSRMatrixOffd(parCSR); 22562c4ab24aSJunchao Zhang 22572c4ab24aSJunchao Zhang hypreMemtype = hypre_CSRMatrixMemoryLocation(diag); 22582c4ab24aSJunchao Zhang A = (size == 1) ? cooMat : ((Mat_MPIAIJ *)cooMat->data)->A; 22592c4ab24aSJunchao Zhang PetscCall(MatSeqAIJGetCSRAndMemType(A, NULL, NULL, &Aa, &petscMemtype)); 22602c4ab24aSJunchao Zhang PetscAssert((PetscMemTypeHost(petscMemtype) && hypreMemtype == HYPRE_MEMORY_HOST) || (PetscMemTypeDevice(petscMemtype) && hypreMemtype == HYPRE_MEMORY_DEVICE), comm, PETSC_ERR_PLIB, "PETSc and hypre's memory types mismatch"); 22612c4ab24aSJunchao Zhang 22622c4ab24aSJunchao Zhang hmat->diagJ = hypre_CSRMatrixJ(diag); 22632c4ab24aSJunchao Zhang PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(diag), hypreMemtype)); 22642c4ab24aSJunchao Zhang hypre_CSRMatrixData(diag) = (HYPRE_Complex *)Aa; 22652c4ab24aSJunchao Zhang hypre_CSRMatrixOwnsData(diag) = 0; /* Take ownership of (j,a) away from hypre. As a result, we need to free them on our own */ 22662c4ab24aSJunchao Zhang 22672c4ab24aSJunchao Zhang if (size > 1) { 22682c4ab24aSJunchao Zhang B = ((Mat_MPIAIJ *)cooMat->data)->B; 22692c4ab24aSJunchao Zhang PetscCall(MatSeqAIJGetCSRAndMemType(B, NULL, NULL, &Ba, &petscMemtype)); 22702c4ab24aSJunchao Zhang hmat->offdJ = hypre_CSRMatrixJ(offd); 22712c4ab24aSJunchao Zhang PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(offd), hypreMemtype)); 22722c4ab24aSJunchao Zhang hypre_CSRMatrixData(offd) = (HYPRE_Complex *)Ba; 22732c4ab24aSJunchao Zhang hypre_CSRMatrixOwnsData(offd) = 0; 22742c4ab24aSJunchao Zhang } 22752c4ab24aSJunchao Zhang 22762c4ab24aSJunchao Zhang /* Record cooMat for use in MatSetValuesCOO_HYPRE */ 22772c4ab24aSJunchao Zhang hmat->cooMat = cooMat; 22782c4ab24aSJunchao Zhang hmat->memType = hypreMemtype; 22792c4ab24aSJunchao Zhang PetscFunctionReturn(PETSC_SUCCESS); 22802c4ab24aSJunchao Zhang } 22812c4ab24aSJunchao Zhang 22822c4ab24aSJunchao Zhang static PetscErrorCode MatDuplicate_HYPRE(Mat A, MatDuplicateOption op, Mat *B) 22832c4ab24aSJunchao Zhang { 22842c4ab24aSJunchao Zhang hypre_ParCSRMatrix *parcsr = NULL; 22852c4ab24aSJunchao Zhang PetscCopyMode cpmode; 22862c4ab24aSJunchao Zhang Mat_HYPRE *hA; 22872c4ab24aSJunchao Zhang Mat cooMat; 22882c4ab24aSJunchao Zhang 22892c4ab24aSJunchao Zhang PetscFunctionBegin; 22902c4ab24aSJunchao Zhang PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 22912c4ab24aSJunchao Zhang if (op == MAT_DO_NOT_COPY_VALUES || op == MAT_SHARE_NONZERO_PATTERN) { 22922c4ab24aSJunchao Zhang parcsr = hypre_ParCSRMatrixClone(parcsr, 0); 22932c4ab24aSJunchao Zhang cpmode = PETSC_OWN_POINTER; 22942c4ab24aSJunchao Zhang } else { 22952c4ab24aSJunchao Zhang cpmode = PETSC_COPY_VALUES; 22962c4ab24aSJunchao Zhang } 22972c4ab24aSJunchao Zhang PetscCall(MatCreateFromParCSR(parcsr, MATHYPRE, cpmode, B)); 22982c4ab24aSJunchao Zhang hA = (Mat_HYPRE *)A->data; 22992c4ab24aSJunchao Zhang if (hA->cooMat) { 2300b73e3080SStefano Zampini op = (op == MAT_DO_NOT_COPY_VALUES) ? op : MAT_COPY_VALUES; 2301b73e3080SStefano Zampini /* Cannot simply increase the reference count of hA->cooMat, since B needs to share cooMat's data array */ 2302b73e3080SStefano Zampini PetscCall(MatDuplicate(hA->cooMat, op, &cooMat)); 2303*651b1cf9SStefano Zampini PetscCall(PetscObjectSetName((PetscObject)cooMat, "_internal_COO_mat_for_hypre")); 23042c4ab24aSJunchao Zhang PetscCall(MatAttachCOOMat_HYPRE(*B, cooMat)); 23052c4ab24aSJunchao Zhang } 23062c4ab24aSJunchao Zhang PetscFunctionReturn(PETSC_SUCCESS); 23072c4ab24aSJunchao Zhang } 23082c4ab24aSJunchao Zhang 2309d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetPreallocationCOO_HYPRE(Mat mat, PetscCount coo_n, PetscInt coo_i[], PetscInt coo_j[]) 2310d71ae5a4SJacob Faibussowitsch { 23115fbaff96SJunchao Zhang MPI_Comm comm; 23125fbaff96SJunchao Zhang PetscMPIInt size; 23135fbaff96SJunchao Zhang PetscLayout rmap, cmap; 23145fbaff96SJunchao Zhang Mat_HYPRE *hmat; 23152c4ab24aSJunchao Zhang Mat cooMat; 23165fbaff96SJunchao Zhang MatType matType = MATAIJ; /* default type of cooMat */ 23175fbaff96SJunchao Zhang 23185fbaff96SJunchao Zhang PetscFunctionBegin; 2319*651b1cf9SStefano Zampini /* Build an agent matrix cooMat with AIJ format 23205fbaff96SJunchao 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. 23215fbaff96SJunchao Zhang */ 23225fbaff96SJunchao Zhang PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 23235fbaff96SJunchao Zhang PetscCallMPI(MPI_Comm_size(comm, &size)); 23245fbaff96SJunchao Zhang PetscCall(PetscLayoutSetUp(mat->rmap)); 23255fbaff96SJunchao Zhang PetscCall(PetscLayoutSetUp(mat->cmap)); 23265fbaff96SJunchao Zhang PetscCall(MatGetLayouts(mat, &rmap, &cmap)); 23275fbaff96SJunchao Zhang 2328*651b1cf9SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 23295fbaff96SJunchao Zhang if (!mat->boundtocpu) { /* mat will be on device, so will cooMat */ 2330*651b1cf9SStefano Zampini #if defined(HYPRE_USING_HIP) 2331*651b1cf9SStefano Zampini matType = MATAIJHIPSPARSE; 2332*651b1cf9SStefano Zampini #elif defined(HYPRE_USING_CUDA) 2333*651b1cf9SStefano Zampini matType = MATAIJCUSPARSE; 23345fbaff96SJunchao Zhang #else 2335*651b1cf9SStefano Zampini SETERRQ(comm, PETSC_ERR_SUP, "Do not know the HYPRE device"); 23365fbaff96SJunchao Zhang #endif 23375fbaff96SJunchao Zhang } 23385fbaff96SJunchao Zhang #endif 23395fbaff96SJunchao Zhang 23405fbaff96SJunchao Zhang /* Do COO preallocation through cooMat */ 23415fbaff96SJunchao Zhang hmat = (Mat_HYPRE *)mat->data; 2342*651b1cf9SStefano Zampini if (hmat->cooMat) { 23435fbaff96SJunchao Zhang PetscCall(MatDestroy(&hmat->cooMat)); 2344*651b1cf9SStefano Zampini PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hmat->diagJ, hmat->memType)); 2345*651b1cf9SStefano Zampini PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hmat->offdJ, hmat->memType)); 2346*651b1cf9SStefano Zampini PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hmat->diag, hmat->memType)); 2347*651b1cf9SStefano Zampini } 23485fbaff96SJunchao Zhang PetscCall(MatCreate(comm, &cooMat)); 23495fbaff96SJunchao Zhang PetscCall(MatSetType(cooMat, matType)); 23505fbaff96SJunchao Zhang PetscCall(MatSetLayouts(cooMat, rmap, cmap)); 2351*651b1cf9SStefano Zampini PetscCall(MatSetOption(cooMat, MAT_IGNORE_OFF_PROC_ENTRIES, hmat->donotstash)); 2352*651b1cf9SStefano Zampini PetscCall(MatSetOption(cooMat, MAT_NO_OFF_PROC_ENTRIES, mat->nooffprocentries)); 2353*651b1cf9SStefano Zampini 2354*651b1cf9SStefano Zampini /* MatSetPreallocationCOO_SeqAIJ and MatSetPreallocationCOO_MPIAIJ uses this specific 2355*651b1cf9SStefano Zampini name to automatically put the diagonal entries first */ 2356*651b1cf9SStefano Zampini PetscCall(PetscObjectSetName((PetscObject)cooMat, "_internal_COO_mat_for_hypre")); 23575fbaff96SJunchao Zhang PetscCall(MatSetPreallocationCOO(cooMat, coo_n, coo_i, coo_j)); 2358b73e3080SStefano Zampini cooMat->assembled = PETSC_TRUE; 23595fbaff96SJunchao Zhang 23605fbaff96SJunchao Zhang /* Copy the sparsity pattern from cooMat to hypre IJMatrix hmat->ij */ 23615fbaff96SJunchao Zhang PetscCall(MatSetOption(mat, MAT_SORTED_FULL, PETSC_TRUE)); 23625fbaff96SJunchao Zhang PetscCall(MatHYPRE_CreateFromMat(cooMat, hmat)); /* Create hmat->ij and preallocate it */ 2363b73e3080SStefano Zampini PetscCall(MatHYPRE_IJMatrixCopyIJ(cooMat, hmat->ij)); /* Copy A's (i,j) to hmat->ij */ 23645fbaff96SJunchao Zhang 23655fbaff96SJunchao Zhang mat->preallocated = PETSC_TRUE; 23665fbaff96SJunchao Zhang PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 23675fbaff96SJunchao Zhang PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); /* Migrate mat to device if it is bound to. Hypre builds its own SpMV context here */ 23685fbaff96SJunchao Zhang 23692c4ab24aSJunchao Zhang /* Attach cooMat to mat */ 23702c4ab24aSJunchao Zhang PetscCall(MatAttachCOOMat_HYPRE(mat, cooMat)); 23713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23725fbaff96SJunchao Zhang } 23735fbaff96SJunchao Zhang 2374d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesCOO_HYPRE(Mat mat, const PetscScalar v[], InsertMode imode) 2375d71ae5a4SJacob Faibussowitsch { 23765fbaff96SJunchao Zhang Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data; 23775fbaff96SJunchao Zhang 23785fbaff96SJunchao Zhang PetscFunctionBegin; 2379b73e3080SStefano Zampini PetscCheck(hmat->cooMat, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet"); 23805fbaff96SJunchao Zhang PetscCall(MatSetValuesCOO(hmat->cooMat, v, imode)); 2381*651b1cf9SStefano Zampini PetscCall(MatViewFromOptions(hmat->cooMat, (PetscObject)mat, "-cooMat_view")); 23823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23835fbaff96SJunchao Zhang } 23845fbaff96SJunchao Zhang 2385a055b5aaSBarry Smith /*MC 23862ef1f0ffSBarry Smith MATHYPRE - "hypre" - A matrix type to be used for sequential and parallel sparse matrices 2387a055b5aaSBarry Smith based on the hypre IJ interface. 2388a055b5aaSBarry Smith 2389a055b5aaSBarry Smith Level: intermediate 2390a055b5aaSBarry Smith 23911cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatHYPRESetPreallocation` 2392a055b5aaSBarry Smith M*/ 2393a055b5aaSBarry Smith 2394d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_HYPRE(Mat B) 2395d71ae5a4SJacob Faibussowitsch { 239663c07aadSStefano Zampini Mat_HYPRE *hB; 239763c07aadSStefano Zampini 239863c07aadSStefano Zampini PetscFunctionBegin; 23994dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&hB)); 24006ea7df73SStefano Zampini 2401978814f1SStefano Zampini hB->inner_free = PETSC_TRUE; 2402*651b1cf9SStefano Zampini hB->array_available = PETSC_TRUE; 2403978814f1SStefano Zampini 240463c07aadSStefano Zampini B->data = (void *)hB; 240563c07aadSStefano Zampini 24069566063dSJacob Faibussowitsch PetscCall(PetscMemzero(B->ops, sizeof(struct _MatOps))); 240763c07aadSStefano Zampini B->ops->mult = MatMult_HYPRE; 240863c07aadSStefano Zampini B->ops->multtranspose = MatMultTranspose_HYPRE; 2409414bd5c3SStefano Zampini B->ops->multadd = MatMultAdd_HYPRE; 2410414bd5c3SStefano Zampini B->ops->multtransposeadd = MatMultTransposeAdd_HYPRE; 241163c07aadSStefano Zampini B->ops->setup = MatSetUp_HYPRE; 241263c07aadSStefano Zampini B->ops->destroy = MatDestroy_HYPRE; 241363c07aadSStefano Zampini B->ops->assemblyend = MatAssemblyEnd_HYPRE; 2414c69f721fSFande Kong B->ops->assemblybegin = MatAssemblyBegin_HYPRE; 2415d975228cSstefano_zampini B->ops->setvalues = MatSetValues_HYPRE; 241668ec7858SStefano Zampini B->ops->missingdiagonal = MatMissingDiagonal_HYPRE; 241768ec7858SStefano Zampini B->ops->scale = MatScale_HYPRE; 241868ec7858SStefano Zampini B->ops->zerorowscolumns = MatZeroRowsColumns_HYPRE; 2419c69f721fSFande Kong B->ops->zeroentries = MatZeroEntries_HYPRE; 2420c69f721fSFande Kong B->ops->zerorows = MatZeroRows_HYPRE; 2421c69f721fSFande Kong B->ops->getrow = MatGetRow_HYPRE; 2422c69f721fSFande Kong B->ops->restorerow = MatRestoreRow_HYPRE; 2423c69f721fSFande Kong B->ops->getvalues = MatGetValues_HYPRE; 2424ddbeb582SStefano Zampini B->ops->setoption = MatSetOption_HYPRE; 242545b8d346SStefano Zampini B->ops->duplicate = MatDuplicate_HYPRE; 2426465edc17SStefano Zampini B->ops->copy = MatCopy_HYPRE; 242745b8d346SStefano Zampini B->ops->view = MatView_HYPRE; 24286305df00SStefano Zampini B->ops->getdiagonal = MatGetDiagonal_HYPRE; 2429363d496dSStefano Zampini B->ops->axpy = MatAXPY_HYPRE; 24304222ddf1SHong Zhang B->ops->productsetfromoptions = MatProductSetFromOptions_HYPRE; 24316ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 24326ea7df73SStefano Zampini B->ops->bindtocpu = MatBindToCPU_HYPRE; 24336ea7df73SStefano Zampini B->boundtocpu = PETSC_FALSE; 24346ea7df73SStefano Zampini #endif 243545b8d346SStefano Zampini 243645b8d346SStefano Zampini /* build cache for off array entries formed */ 24379566063dSJacob Faibussowitsch PetscCall(MatStashCreate_Private(PetscObjectComm((PetscObject)B), 1, &B->stash)); 243863c07aadSStefano Zampini 24399566063dSJacob Faibussowitsch PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)B), &hB->comm)); 24409566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRE)); 24419566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_aij_C", MatConvert_HYPRE_AIJ)); 24429566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_is_C", MatConvert_HYPRE_IS)); 24439566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_hypre_C", MatProductSetFromOptions_HYPRE)); 24449566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaij_hypre_C", MatProductSetFromOptions_HYPRE)); 24459566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPRESetPreallocation_C", MatHYPRESetPreallocation_HYPRE)); 24469566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPREGetParCSR_C", MatHYPREGetParCSR_HYPRE)); 24475fbaff96SJunchao Zhang PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_HYPRE)); 24485fbaff96SJunchao Zhang PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetValuesCOO_C", MatSetValuesCOO_HYPRE)); 24496ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 24506ea7df73SStefano Zampini #if defined(HYPRE_USING_HIP) 24519566063dSJacob Faibussowitsch PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP)); 24529566063dSJacob Faibussowitsch PetscCall(MatSetVecType(B, VECHIP)); 24536ea7df73SStefano Zampini #endif 24546ea7df73SStefano Zampini #if defined(HYPRE_USING_CUDA) 24559566063dSJacob Faibussowitsch PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA)); 24569566063dSJacob Faibussowitsch PetscCall(MatSetVecType(B, VECCUDA)); 24576ea7df73SStefano Zampini #endif 24586ea7df73SStefano Zampini #endif 2459ea9ee2c1SPierre Jolivet PetscHYPREInitialize(); 24603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 246163c07aadSStefano Zampini } 246263c07aadSStefano Zampini 2463d71ae5a4SJacob Faibussowitsch static PetscErrorCode hypre_array_destroy(void *ptr) 2464d71ae5a4SJacob Faibussowitsch { 2465225daaf8SStefano Zampini PetscFunctionBegin; 2466b73e3080SStefano Zampini if (ptr) hypre_TFree(ptr, HYPRE_MEMORY_HOST); 24673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2468225daaf8SStefano Zampini } 2469