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); 25*b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_MPIAIJ(Mat, HYPRE_IJMatrix); 26*b73e3080SStefano 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(); 93792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rstart, rend - 1, cstart, cend - 1, &hA->ij); 94792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR); 9563c07aadSStefano Zampini { 9663c07aadSStefano Zampini PetscBool same; 9763c07aadSStefano Zampini Mat A_d, A_o; 9863c07aadSStefano Zampini const PetscInt *colmap; 999566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &same)); 10063c07aadSStefano Zampini if (same) { 1019566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(A, &A_d, &A_o, &colmap)); 1029566063dSJacob Faibussowitsch PetscCall(MatHYPRE_IJMatrixPreallocate(A_d, A_o, hA->ij)); 1033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10463c07aadSStefano Zampini } 1059566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIBAIJ, &same)); 10663c07aadSStefano Zampini if (same) { 1079566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJGetSeqBAIJ(A, &A_d, &A_o, &colmap)); 1089566063dSJacob Faibussowitsch PetscCall(MatHYPRE_IJMatrixPreallocate(A_d, A_o, hA->ij)); 1093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11063c07aadSStefano Zampini } 1119566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &same)); 11263c07aadSStefano Zampini if (same) { 1139566063dSJacob Faibussowitsch PetscCall(MatHYPRE_IJMatrixPreallocate(A, NULL, hA->ij)); 1143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11563c07aadSStefano Zampini } 1169566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQBAIJ, &same)); 11763c07aadSStefano Zampini if (same) { 1189566063dSJacob Faibussowitsch PetscCall(MatHYPRE_IJMatrixPreallocate(A, NULL, hA->ij)); 1193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12063c07aadSStefano Zampini } 12163c07aadSStefano Zampini } 1223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12363c07aadSStefano Zampini } 12463c07aadSStefano Zampini 125*b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ(Mat A, HYPRE_IJMatrix ij) 126d71ae5a4SJacob Faibussowitsch { 12763c07aadSStefano Zampini PetscBool flg; 12863c07aadSStefano Zampini 12963c07aadSStefano Zampini PetscFunctionBegin; 1306ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 131792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize, ij); 1326ea7df73SStefano Zampini #else 133792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize_v2, ij, HYPRE_MEMORY_HOST); 1346ea7df73SStefano Zampini #endif 1359566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &flg)); 136*b73e3080SStefano Zampini if (flg) { 137*b73e3080SStefano Zampini PetscCall(MatHYPRE_IJMatrixCopyIJ_MPIAIJ(A, ij)); 1383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13963c07aadSStefano Zampini } 1409566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &flg)); 14163c07aadSStefano Zampini if (flg) { 142*b73e3080SStefano Zampini PetscCall(MatHYPRE_IJMatrixCopyIJ_SeqAIJ(A, ij)); 1433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14463c07aadSStefano Zampini } 145*b73e3080SStefano Zampini PetscCheck(PETSC_FALSE, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "No support for matrix type %s", ((PetscObject)A)->type_name); 14663c07aadSStefano Zampini } 14763c07aadSStefano Zampini 148*b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_SeqAIJ(Mat A, HYPRE_IJMatrix ij) 149d71ae5a4SJacob Faibussowitsch { 15063c07aadSStefano Zampini Mat_SeqAIJ *pdiag = (Mat_SeqAIJ *)A->data; 15158968eb6SStefano Zampini HYPRE_Int type; 15263c07aadSStefano Zampini hypre_ParCSRMatrix *par_matrix; 15363c07aadSStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 15463c07aadSStefano Zampini hypre_CSRMatrix *hdiag; 1552cf14000SStefano Zampini PetscBool sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int)); 15663c07aadSStefano Zampini 15763c07aadSStefano Zampini PetscFunctionBegin; 158792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type); 15908401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 160792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix); 16163c07aadSStefano Zampini hdiag = hypre_ParCSRMatrixDiag(par_matrix); 16263c07aadSStefano Zampini /* 16363c07aadSStefano Zampini this is the Hack part where we monkey directly with the hypre datastructures 16463c07aadSStefano Zampini */ 1652cf14000SStefano Zampini if (sameint) { 1669566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hdiag->i, pdiag->i, A->rmap->n + 1)); 1679566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hdiag->j, pdiag->j, pdiag->nz)); 1682cf14000SStefano Zampini } else { 1692cf14000SStefano Zampini PetscInt i; 1702cf14000SStefano Zampini 1712cf14000SStefano Zampini for (i = 0; i < A->rmap->n + 1; i++) hdiag->i[i] = (HYPRE_Int)pdiag->i[i]; 1722cf14000SStefano Zampini for (i = 0; i < pdiag->nz; i++) hdiag->j[i] = (HYPRE_Int)pdiag->j[i]; 1732cf14000SStefano Zampini } 1746ea7df73SStefano Zampini 175ea9daf28SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij); 17663c07aadSStefano Zampini hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0; 1773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17863c07aadSStefano Zampini } 17963c07aadSStefano Zampini 180*b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_MPIAIJ(Mat A, HYPRE_IJMatrix ij) 181d71ae5a4SJacob Faibussowitsch { 18263c07aadSStefano Zampini Mat_MPIAIJ *pA = (Mat_MPIAIJ *)A->data; 18363c07aadSStefano Zampini Mat_SeqAIJ *pdiag, *poffd; 18463c07aadSStefano Zampini PetscInt i, *garray = pA->garray, *jj, cstart, *pjj; 1852cf14000SStefano Zampini HYPRE_Int *hjj, type; 18663c07aadSStefano Zampini hypre_ParCSRMatrix *par_matrix; 18763c07aadSStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 18863c07aadSStefano Zampini hypre_CSRMatrix *hdiag, *hoffd; 1892cf14000SStefano Zampini PetscBool sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int)); 19063c07aadSStefano Zampini 19163c07aadSStefano Zampini PetscFunctionBegin; 19263c07aadSStefano Zampini pdiag = (Mat_SeqAIJ *)pA->A->data; 19363c07aadSStefano Zampini poffd = (Mat_SeqAIJ *)pA->B->data; 194da81f932SPierre Jolivet /* cstart is only valid for square MPIAIJ laid out in the usual way */ 1959566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &cstart, NULL)); 19663c07aadSStefano Zampini 197792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type); 19808401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 199792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix); 20063c07aadSStefano Zampini hdiag = hypre_ParCSRMatrixDiag(par_matrix); 20163c07aadSStefano Zampini hoffd = hypre_ParCSRMatrixOffd(par_matrix); 20263c07aadSStefano Zampini 2032cf14000SStefano Zampini if (sameint) { 2049566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hdiag->i, pdiag->i, pA->A->rmap->n + 1)); 2052cf14000SStefano Zampini } else { 2062cf14000SStefano Zampini for (i = 0; i < pA->A->rmap->n + 1; i++) hdiag->i[i] = (HYPRE_Int)(pdiag->i[i]); 2072cf14000SStefano Zampini } 208*b73e3080SStefano Zampini 2092cf14000SStefano Zampini hjj = hdiag->j; 2102cf14000SStefano Zampini pjj = pdiag->j; 211c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0) 2122cf14000SStefano Zampini for (i = 0; i < pdiag->nz; i++) hjj[i] = pjj[i]; 213c6698e78SStefano Zampini #else 2142cf14000SStefano Zampini for (i = 0; i < pdiag->nz; i++) hjj[i] = cstart + pjj[i]; 215c6698e78SStefano Zampini #endif 2162cf14000SStefano Zampini if (sameint) { 2179566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hoffd->i, poffd->i, pA->A->rmap->n + 1)); 2182cf14000SStefano Zampini } else { 2192cf14000SStefano Zampini for (i = 0; i < pA->A->rmap->n + 1; i++) hoffd->i[i] = (HYPRE_Int)(poffd->i[i]); 2202cf14000SStefano Zampini } 2212cf14000SStefano Zampini 222c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0) 223792fecdfSBarry Smith PetscCallExternal(hypre_CSRMatrixBigInitialize, hoffd); 224c6698e78SStefano Zampini jj = (PetscInt *)hoffd->big_j; 225c6698e78SStefano Zampini #else 22663c07aadSStefano Zampini jj = (PetscInt *)hoffd->j; 227c6698e78SStefano Zampini #endif 2282cf14000SStefano Zampini pjj = poffd->j; 22963c07aadSStefano Zampini for (i = 0; i < poffd->nz; i++) jj[i] = garray[pjj[i]]; 230c6698e78SStefano Zampini 231ea9daf28SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij); 23263c07aadSStefano Zampini hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0; 2333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23463c07aadSStefano Zampini } 23563c07aadSStefano Zampini 236d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_HYPRE_IS(Mat A, MatType mtype, MatReuse reuse, Mat *B) 237d71ae5a4SJacob Faibussowitsch { 2382df22349SStefano Zampini Mat_HYPRE *mhA = (Mat_HYPRE *)(A->data); 2392df22349SStefano Zampini Mat lA; 2402df22349SStefano Zampini ISLocalToGlobalMapping rl2g, cl2g; 2412df22349SStefano Zampini IS is; 2422df22349SStefano Zampini hypre_ParCSRMatrix *hA; 2432df22349SStefano Zampini hypre_CSRMatrix *hdiag, *hoffd; 2442df22349SStefano Zampini MPI_Comm comm; 24539accc25SStefano Zampini HYPRE_Complex *hdd, *hod, *aa; 24639accc25SStefano Zampini PetscScalar *data; 2472cf14000SStefano Zampini HYPRE_BigInt *col_map_offd; 2482cf14000SStefano Zampini HYPRE_Int *hdi, *hdj, *hoi, *hoj; 2492df22349SStefano Zampini PetscInt *ii, *jj, *iptr, *jptr; 2502df22349SStefano Zampini PetscInt cum, dr, dc, oc, str, stc, nnz, i, jd, jo, M, N; 25158968eb6SStefano Zampini HYPRE_Int type; 2522df22349SStefano Zampini 2532df22349SStefano Zampini PetscFunctionBegin; 254a1787963SStefano Zampini comm = PetscObjectComm((PetscObject)A); 255792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, mhA->ij, &type); 25608401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 257792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, mhA->ij, (void **)&hA); 2582df22349SStefano Zampini M = hypre_ParCSRMatrixGlobalNumRows(hA); 2592df22349SStefano Zampini N = hypre_ParCSRMatrixGlobalNumCols(hA); 2602df22349SStefano Zampini str = hypre_ParCSRMatrixFirstRowIndex(hA); 2612df22349SStefano Zampini stc = hypre_ParCSRMatrixFirstColDiag(hA); 2622df22349SStefano Zampini hdiag = hypre_ParCSRMatrixDiag(hA); 2632df22349SStefano Zampini hoffd = hypre_ParCSRMatrixOffd(hA); 2642df22349SStefano Zampini dr = hypre_CSRMatrixNumRows(hdiag); 2652df22349SStefano Zampini dc = hypre_CSRMatrixNumCols(hdiag); 2662df22349SStefano Zampini nnz = hypre_CSRMatrixNumNonzeros(hdiag); 2672df22349SStefano Zampini hdi = hypre_CSRMatrixI(hdiag); 2682df22349SStefano Zampini hdj = hypre_CSRMatrixJ(hdiag); 2692df22349SStefano Zampini hdd = hypre_CSRMatrixData(hdiag); 2702df22349SStefano Zampini oc = hypre_CSRMatrixNumCols(hoffd); 2712df22349SStefano Zampini nnz += hypre_CSRMatrixNumNonzeros(hoffd); 2722df22349SStefano Zampini hoi = hypre_CSRMatrixI(hoffd); 2732df22349SStefano Zampini hoj = hypre_CSRMatrixJ(hoffd); 2742df22349SStefano Zampini hod = hypre_CSRMatrixData(hoffd); 2752df22349SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 2762df22349SStefano Zampini PetscInt *aux; 2772df22349SStefano Zampini 2782df22349SStefano Zampini /* generate l2g maps for rows and cols */ 2799566063dSJacob Faibussowitsch PetscCall(ISCreateStride(comm, dr, str, 1, &is)); 2809566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g)); 2819566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2822df22349SStefano Zampini col_map_offd = hypre_ParCSRMatrixColMapOffd(hA); 2839566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dc + oc, &aux)); 2842df22349SStefano Zampini for (i = 0; i < dc; i++) aux[i] = i + stc; 2852df22349SStefano Zampini for (i = 0; i < oc; i++) aux[i + dc] = col_map_offd[i]; 2869566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, dc + oc, aux, PETSC_OWN_POINTER, &is)); 2879566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g)); 2889566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2892df22349SStefano Zampini /* create MATIS object */ 2909566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, B)); 2919566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, dr, dc, M, N)); 2929566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, MATIS)); 2939566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*B, rl2g, cl2g)); 2949566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 2959566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 2962df22349SStefano Zampini 2972df22349SStefano Zampini /* allocate CSR for local matrix */ 2989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dr + 1, &iptr)); 2999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &jptr)); 3009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &data)); 3012df22349SStefano Zampini } else { 3022df22349SStefano Zampini PetscInt nr; 3032df22349SStefano Zampini PetscBool done; 3049566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*B, &lA)); 3059566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lA, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&iptr, (const PetscInt **)&jptr, &done)); 30608401ef6SPierre 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); 30708401ef6SPierre 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); 3089566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(lA, &data)); 3092df22349SStefano Zampini } 3102df22349SStefano Zampini /* merge local matrices */ 3112df22349SStefano Zampini ii = iptr; 3122df22349SStefano Zampini jj = jptr; 31339accc25SStefano 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++ */ 3142df22349SStefano Zampini *ii = *(hdi++) + *(hoi++); 3152df22349SStefano Zampini for (jd = 0, jo = 0, cum = 0; *ii < nnz; cum++) { 31639accc25SStefano Zampini PetscScalar *aold = (PetscScalar *)aa; 3172df22349SStefano Zampini PetscInt *jold = jj, nc = jd + jo; 3189371c9d4SSatish Balay for (; jd < *hdi; jd++) { 3199371c9d4SSatish Balay *jj++ = *hdj++; 3209371c9d4SSatish Balay *aa++ = *hdd++; 3219371c9d4SSatish Balay } 3229371c9d4SSatish Balay for (; jo < *hoi; jo++) { 3239371c9d4SSatish Balay *jj++ = *hoj++ + dc; 3249371c9d4SSatish Balay *aa++ = *hod++; 3259371c9d4SSatish Balay } 3262df22349SStefano Zampini *(++ii) = *(hdi++) + *(hoi++); 3279566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithScalarArray(jd + jo - nc, jold, aold)); 3282df22349SStefano Zampini } 3292df22349SStefano Zampini for (; cum < dr; cum++) *(++ii) = nnz; 3302df22349SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 331a033916dSStefano Zampini Mat_SeqAIJ *a; 332a033916dSStefano Zampini 3339566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, dr, dc + oc, iptr, jptr, data, &lA)); 3349566063dSJacob Faibussowitsch PetscCall(MatISSetLocalMat(*B, lA)); 335a033916dSStefano Zampini /* hack SeqAIJ */ 336a033916dSStefano Zampini a = (Mat_SeqAIJ *)(lA->data); 337a033916dSStefano Zampini a->free_a = PETSC_TRUE; 338a033916dSStefano Zampini a->free_ij = PETSC_TRUE; 3399566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lA)); 3402df22349SStefano Zampini } 3419566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY)); 3429566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY)); 34348a46eb9SPierre Jolivet if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, B)); 3443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3452df22349SStefano Zampini } 3462df22349SStefano Zampini 347*b73e3080SStefano Zampini /* Move diagonal elements of the diagonal block to the front of their row, as needed by ParCSRMatrix. So damn hacky */ 348*b73e3080SStefano Zampini static PetscErrorCode EnsureHypreCSR_SeqAIJ(Mat A, hypre_CSRMatrix *hA) 349d71ae5a4SJacob Faibussowitsch { 350*b73e3080SStefano Zampini Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 351*b73e3080SStefano Zampini PetscBool isseqaij; 352*b73e3080SStefano Zampini HYPRE_Int tmpj, *hj; 353*b73e3080SStefano Zampini HYPRE_Complex tmpv, *ha; 35463c07aadSStefano Zampini 35563c07aadSStefano Zampini PetscFunctionBegin; 356*b73e3080SStefano Zampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isseqaij)); 357*b73e3080SStefano Zampini PetscCheck(isseqaij, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Not for type %s\n", ((PetscObject)A)->type_name); 358*b73e3080SStefano Zampini hj = hypre_CSRMatrixJ(hA); 359*b73e3080SStefano Zampini ha = hypre_CSRMatrixData(hA); 360*b73e3080SStefano Zampini #define swap_with_tmp(a, b, t) \ 361*b73e3080SStefano Zampini { \ 362*b73e3080SStefano Zampini t = a; \ 363*b73e3080SStefano Zampini a = b; \ 364*b73e3080SStefano Zampini b = t; \ 365*b73e3080SStefano Zampini } 366*b73e3080SStefano Zampini for (PetscInt i = 0; i < A->rmap->n; i++) { 367*b73e3080SStefano 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[] */ 368*b73e3080SStefano Zampini swap_with_tmp(ha[aij->i[i]], ha[aij->diag[i]], tmpv); 369*b73e3080SStefano Zampini if (hj[aij->i[i]] != i) swap_with_tmp(hj[aij->i[i]], hj[aij->diag[i]], tmpj); 370*b73e3080SStefano Zampini } 371*b73e3080SStefano Zampini } 372*b73e3080SStefano Zampini #undef swap_with_tmp 373*b73e3080SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 374*b73e3080SStefano Zampini } 375*b73e3080SStefano Zampini 376*b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyValues(Mat A, HYPRE_IJMatrix ij) 377*b73e3080SStefano Zampini { 378*b73e3080SStefano Zampini HYPRE_Int type; 379*b73e3080SStefano Zampini hypre_ParCSRMatrix *par_matrix; 380*b73e3080SStefano Zampini hypre_CSRMatrix *hdiag, *hoffd; 381*b73e3080SStefano Zampini PetscBool ismpiaij; 382*b73e3080SStefano Zampini Mat dA = A, oA = NULL; 383*b73e3080SStefano Zampini PetscInt nnz; 384*b73e3080SStefano Zampini const PetscScalar *pa; 385*b73e3080SStefano Zampini 386*b73e3080SStefano Zampini PetscFunctionBegin; 387*b73e3080SStefano Zampini PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type); 388*b73e3080SStefano Zampini PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 389*b73e3080SStefano Zampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 390*b73e3080SStefano Zampini if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(A, &dA, &oA, NULL)); 391*b73e3080SStefano Zampini PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix); 392*b73e3080SStefano Zampini 393*b73e3080SStefano Zampini hdiag = hypre_ParCSRMatrixDiag(par_matrix); 394*b73e3080SStefano Zampini nnz = hypre_CSRMatrixNumNonzeros(hdiag); 395*b73e3080SStefano Zampini PetscCall(MatSeqAIJGetArrayRead(dA, &pa)); 396*b73e3080SStefano Zampini PetscCall(PetscArraycpy(hdiag->data, pa, nnz)); 397*b73e3080SStefano Zampini PetscCall(MatSeqAIJRestoreArrayRead(dA, &pa)); 398*b73e3080SStefano Zampini if (oA) { 399*b73e3080SStefano Zampini hoffd = hypre_ParCSRMatrixOffd(par_matrix); 400*b73e3080SStefano Zampini nnz = hypre_CSRMatrixNumNonzeros(hoffd); 401*b73e3080SStefano Zampini PetscCall(MatSeqAIJGetArrayRead(oA, &pa)); 402*b73e3080SStefano Zampini PetscCall(PetscArraycpy(hoffd->data, pa, nnz)); 403*b73e3080SStefano Zampini PetscCall(MatSeqAIJRestoreArrayRead(dA, &pa)); 404*b73e3080SStefano Zampini } 405*b73e3080SStefano Zampini PetscCall(EnsureHypreCSR_SeqAIJ(dA, hdiag)); 406*b73e3080SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 407*b73e3080SStefano Zampini } 408*b73e3080SStefano Zampini 409*b73e3080SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType type, MatReuse reuse, Mat *B) 410*b73e3080SStefano Zampini { 411*b73e3080SStefano Zampini MPI_Comm comm = PetscObjectComm((PetscObject)A); 412*b73e3080SStefano Zampini Mat M = NULL; 413*b73e3080SStefano Zampini Mat dA = A, oA = NULL; 414*b73e3080SStefano Zampini PetscBool ismpiaij, issbaij, isbaij; 415*b73e3080SStefano Zampini Mat_HYPRE *hA; 416*b73e3080SStefano Zampini 417*b73e3080SStefano Zampini PetscFunctionBegin; 418*b73e3080SStefano Zampini PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &issbaij, MATSEQSBAIJ, MATMPIBAIJ, "")); 419*b73e3080SStefano Zampini PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &isbaij, MATSEQBAIJ, MATMPIBAIJ, "")); 420*b73e3080SStefano Zampini if (isbaij || issbaij) { /* handle BAIJ and SBAIJ */ 421*b73e3080SStefano Zampini PetscBool ismpi; 422*b73e3080SStefano Zampini MatType newtype; 423*b73e3080SStefano Zampini 424*b73e3080SStefano Zampini PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &ismpi, MATMPISBAIJ, MATMPIBAIJ, "")); 425*b73e3080SStefano Zampini newtype = ismpi ? MATMPIAIJ : MATSEQAIJ; 42663c07aadSStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 427*b73e3080SStefano Zampini PetscCall(MatConvert(*B, newtype, MAT_INPLACE_MATRIX, B)); 428*b73e3080SStefano Zampini PetscCall(MatConvert(A, newtype, MAT_REUSE_MATRIX, B)); 429*b73e3080SStefano Zampini PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B)); 430*b73e3080SStefano Zampini } else if (reuse == MAT_INITIAL_MATRIX) { 431*b73e3080SStefano Zampini PetscCall(MatConvert(A, newtype, MAT_INITIAL_MATRIX, B)); 432*b73e3080SStefano Zampini PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B)); 43363c07aadSStefano Zampini } else { 434*b73e3080SStefano Zampini PetscCall(MatConvert(A, newtype, MAT_INPLACE_MATRIX, &A)); 435*b73e3080SStefano Zampini PetscCall(MatConvert(A, MATHYPRE, MAT_INPLACE_MATRIX, &A)); 436*b73e3080SStefano Zampini } 437*b73e3080SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 438*b73e3080SStefano Zampini } 439*b73e3080SStefano Zampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 440*b73e3080SStefano Zampini if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(A, &dA, &oA, NULL)); 441*b73e3080SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 4429566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &M)); 4439566063dSJacob Faibussowitsch PetscCall(MatSetType(M, MATHYPRE)); 4449566063dSJacob Faibussowitsch PetscCall(MatSetSizes(M, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N)); 445*b73e3080SStefano Zampini PetscCall(MatSetOption(M, MAT_SORTED_FULL, PETSC_TRUE)); 446*b73e3080SStefano Zampini PetscCall(MatSetOption(M, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE)); 447*b73e3080SStefano Zampini PetscCall(PetscLayoutSetUp(M->rmap)); 448*b73e3080SStefano Zampini PetscCall(PetscLayoutSetUp(M->cmap)); 449*b73e3080SStefano Zampini 450*b73e3080SStefano Zampini hA = (Mat_HYPRE *)M->data; 451*b73e3080SStefano Zampini PetscCall(MatHYPRE_CreateFromMat(A, hA)); /* Create hmat->ij and preallocate it */ 452*b73e3080SStefano Zampini PetscCall(MatHYPRE_IJMatrixCopyIJ(A, hA->ij)); /* Copy A's (a,i,j) to hmat->ij */ 453*b73e3080SStefano Zampini M->preallocated = PETSC_TRUE; 45484d4e069SStefano Zampini if (reuse == MAT_INITIAL_MATRIX) *B = M; 455*b73e3080SStefano Zampini } else M = *B; 456*b73e3080SStefano Zampini 457*b73e3080SStefano Zampini hA = (Mat_HYPRE *)M->data; 458*b73e3080SStefano Zampini PetscCall(MatHYPRE_IJMatrixCopyValues(A, hA->ij)); 459*b73e3080SStefano Zampini PetscCall(MatAssemblyBegin(M, MAT_FINAL_ASSEMBLY)); 460*b73e3080SStefano Zampini PetscCall(MatAssemblyEnd(M, MAT_FINAL_ASSEMBLY)); /* Migrate mat to device if it is bound to. Hypre builds its own SpMV context here */ 461*b73e3080SStefano Zampini 46248a46eb9SPierre Jolivet if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &M)); 4633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46463c07aadSStefano Zampini } 46563c07aadSStefano Zampini 466d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_HYPRE_AIJ(Mat A, MatType mtype, MatReuse reuse, Mat *B) 467d71ae5a4SJacob Faibussowitsch { 46863c07aadSStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 46963c07aadSStefano Zampini hypre_ParCSRMatrix *parcsr; 47063c07aadSStefano Zampini hypre_CSRMatrix *hdiag, *hoffd; 47163c07aadSStefano Zampini MPI_Comm comm; 47263c07aadSStefano Zampini PetscScalar *da, *oa, *aptr; 47363c07aadSStefano Zampini PetscInt *dii, *djj, *oii, *ojj, *iptr; 47463c07aadSStefano Zampini PetscInt i, dnnz, onnz, m, n; 47558968eb6SStefano Zampini HYPRE_Int type; 47663c07aadSStefano Zampini PetscMPIInt size; 4772cf14000SStefano Zampini PetscBool sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int)); 478*b73e3080SStefano Zampini PetscBool downs = PETSC_TRUE, oowns = PETSC_TRUE; 47963c07aadSStefano Zampini 48063c07aadSStefano Zampini PetscFunctionBegin; 48163c07aadSStefano Zampini comm = PetscObjectComm((PetscObject)A); 482792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type); 48308401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 48463c07aadSStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 48563c07aadSStefano Zampini PetscBool ismpiaij, isseqaij; 4869566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATMPIAIJ, &ismpiaij)); 4879566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATSEQAIJ, &isseqaij)); 48808401ef6SPierre Jolivet PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Only MATMPIAIJ or MATSEQAIJ are supported"); 48963c07aadSStefano Zampini } 4906ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 49108401ef6SPierre Jolivet PetscCheck(HYPRE_MEMORY_DEVICE != hypre_IJMatrixMemoryLocation(hA->ij), comm, PETSC_ERR_SUP, "Not yet implemented"); 4926ea7df73SStefano Zampini #endif 4939566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 49463c07aadSStefano Zampini 495792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr); 49663c07aadSStefano Zampini hdiag = hypre_ParCSRMatrixDiag(parcsr); 49763c07aadSStefano Zampini hoffd = hypre_ParCSRMatrixOffd(parcsr); 49863c07aadSStefano Zampini m = hypre_CSRMatrixNumRows(hdiag); 49963c07aadSStefano Zampini n = hypre_CSRMatrixNumCols(hdiag); 50063c07aadSStefano Zampini dnnz = hypre_CSRMatrixNumNonzeros(hdiag); 50163c07aadSStefano Zampini onnz = hypre_CSRMatrixNumNonzeros(hoffd); 502225daaf8SStefano Zampini if (reuse == MAT_INITIAL_MATRIX) { 5039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &dii)); 5049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dnnz, &djj)); 5059566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dnnz, &da)); 506225daaf8SStefano Zampini } else if (reuse == MAT_REUSE_MATRIX) { 50763c07aadSStefano Zampini PetscInt nr; 50863c07aadSStefano Zampini PetscBool done; 50963c07aadSStefano Zampini if (size > 1) { 51063c07aadSStefano Zampini Mat_MPIAIJ *b = (Mat_MPIAIJ *)((*B)->data); 51163c07aadSStefano Zampini 5129566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(b->A, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&dii, (const PetscInt **)&djj, &done)); 51308401ef6SPierre 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); 51408401ef6SPierre 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); 5159566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(b->A, &da)); 51663c07aadSStefano Zampini } else { 5179566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(*B, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&dii, (const PetscInt **)&djj, &done)); 51808401ef6SPierre Jolivet PetscCheck(nr == m, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of local rows! %" PetscInt_FMT " != %" PetscInt_FMT, nr, m); 51908401ef6SPierre 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); 5209566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(*B, &da)); 52163c07aadSStefano Zampini } 522225daaf8SStefano Zampini } else { /* MAT_INPLACE_MATRIX */ 523*b73e3080SStefano Zampini downs = (PetscBool)(hypre_CSRMatrixOwnsData(hdiag)); 524*b73e3080SStefano Zampini if (!sameint || !downs) { 5259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &dii)); 5269566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dnnz, &djj)); 5272cf14000SStefano Zampini } else { 5287d968826Sstefano_zampini dii = (PetscInt *)hypre_CSRMatrixI(hdiag); 5297d968826Sstefano_zampini djj = (PetscInt *)hypre_CSRMatrixJ(hdiag); 53063c07aadSStefano Zampini } 531*b73e3080SStefano Zampini if (!downs) { 532*b73e3080SStefano Zampini PetscCall(PetscMalloc1(dnnz, &da)); 533*b73e3080SStefano Zampini } else da = (PetscScalar *)hypre_CSRMatrixData(hdiag); 53463c07aadSStefano Zampini } 5352cf14000SStefano Zampini 5362cf14000SStefano Zampini if (!sameint) { 5379371c9d4SSatish Balay if (reuse != MAT_REUSE_MATRIX) { 5389371c9d4SSatish Balay for (i = 0; i < m + 1; i++) dii[i] = (PetscInt)(hypre_CSRMatrixI(hdiag)[i]); 5399371c9d4SSatish Balay } 5402cf14000SStefano Zampini for (i = 0; i < dnnz; i++) djj[i] = (PetscInt)(hypre_CSRMatrixJ(hdiag)[i]); 5412cf14000SStefano Zampini } else { 5429566063dSJacob Faibussowitsch if (reuse != MAT_REUSE_MATRIX) PetscCall(PetscArraycpy(dii, hypre_CSRMatrixI(hdiag), m + 1)); 5439566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(djj, hypre_CSRMatrixJ(hdiag), dnnz)); 5442cf14000SStefano Zampini } 5459566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(da, hypre_CSRMatrixData(hdiag), dnnz)); 54663c07aadSStefano Zampini iptr = djj; 54763c07aadSStefano Zampini aptr = da; 54863c07aadSStefano Zampini for (i = 0; i < m; i++) { 54963c07aadSStefano Zampini PetscInt nc = dii[i + 1] - dii[i]; 5509566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithScalarArray(nc, iptr, aptr)); 55163c07aadSStefano Zampini iptr += nc; 55263c07aadSStefano Zampini aptr += nc; 55363c07aadSStefano Zampini } 55463c07aadSStefano Zampini if (size > 1) { 5552cf14000SStefano Zampini HYPRE_BigInt *coffd; 5562cf14000SStefano Zampini HYPRE_Int *offdj; 55763c07aadSStefano Zampini 558225daaf8SStefano Zampini if (reuse == MAT_INITIAL_MATRIX) { 5599566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &oii)); 5609566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(onnz, &ojj)); 5619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(onnz, &oa)); 562225daaf8SStefano Zampini } else if (reuse == MAT_REUSE_MATRIX) { 56363c07aadSStefano Zampini Mat_MPIAIJ *b = (Mat_MPIAIJ *)((*B)->data); 56463c07aadSStefano Zampini PetscInt nr, hr = hypre_CSRMatrixNumRows(hoffd); 56563c07aadSStefano Zampini PetscBool done; 56663c07aadSStefano Zampini 5679566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(b->B, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&oii, (const PetscInt **)&ojj, &done)); 56808401ef6SPierre 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); 569*b73e3080SStefano 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); 5709566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetArray(b->B, &oa)); 571225daaf8SStefano Zampini } else { /* MAT_INPLACE_MATRIX */ 572*b73e3080SStefano Zampini oowns = (PetscBool)(hypre_CSRMatrixOwnsData(hoffd)); 573*b73e3080SStefano Zampini if (!sameint || !oowns) { 5749566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(m + 1, &oii)); 5759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(onnz, &ojj)); 5762cf14000SStefano Zampini } else { 5777d968826Sstefano_zampini oii = (PetscInt *)hypre_CSRMatrixI(hoffd); 5787d968826Sstefano_zampini ojj = (PetscInt *)hypre_CSRMatrixJ(hoffd); 57963c07aadSStefano Zampini } 580*b73e3080SStefano Zampini if (!oowns) { 581*b73e3080SStefano Zampini PetscCall(PetscMalloc1(onnz, &oa)); 582*b73e3080SStefano Zampini } else oa = (PetscScalar *)hypre_CSRMatrixData(hoffd); 58363c07aadSStefano Zampini } 584a16187a7SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 5852cf14000SStefano Zampini if (!sameint) { 5862cf14000SStefano Zampini for (i = 0; i < m + 1; i++) oii[i] = (PetscInt)(hypre_CSRMatrixI(hoffd)[i]); 5872cf14000SStefano Zampini } else { 5889566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(oii, hypre_CSRMatrixI(hoffd), m + 1)); 5892cf14000SStefano Zampini } 590a16187a7SStefano Zampini } 5919566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(oa, hypre_CSRMatrixData(hoffd), onnz)); 592a16187a7SStefano Zampini 59363c07aadSStefano Zampini offdj = hypre_CSRMatrixJ(hoffd); 59463c07aadSStefano Zampini coffd = hypre_ParCSRMatrixColMapOffd(parcsr); 595a16187a7SStefano Zampini /* we only need the permutation to be computed properly, I don't know if HYPRE 596a16187a7SStefano Zampini messes up with the ordering. Just in case, allocate some memory and free it 597a16187a7SStefano Zampini later */ 598a16187a7SStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 599a16187a7SStefano Zampini Mat_MPIAIJ *b = (Mat_MPIAIJ *)((*B)->data); 600a16187a7SStefano Zampini PetscInt mnz; 601a16187a7SStefano Zampini 6029566063dSJacob Faibussowitsch PetscCall(MatSeqAIJGetMaxRowNonzeros(b->B, &mnz)); 6039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mnz, &ojj)); 6049371c9d4SSatish Balay } else 6059371c9d4SSatish Balay for (i = 0; i < onnz; i++) ojj[i] = coffd[offdj[i]]; 60663c07aadSStefano Zampini iptr = ojj; 60763c07aadSStefano Zampini aptr = oa; 60863c07aadSStefano Zampini for (i = 0; i < m; i++) { 60963c07aadSStefano Zampini PetscInt nc = oii[i + 1] - oii[i]; 610a16187a7SStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 611a16187a7SStefano Zampini PetscInt j; 612a16187a7SStefano Zampini 613a16187a7SStefano Zampini iptr = ojj; 614a16187a7SStefano Zampini for (j = 0; j < nc; j++) iptr[j] = coffd[offdj[oii[i] + j]]; 615a16187a7SStefano Zampini } 6169566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithScalarArray(nc, iptr, aptr)); 61763c07aadSStefano Zampini iptr += nc; 61863c07aadSStefano Zampini aptr += nc; 61963c07aadSStefano Zampini } 6209566063dSJacob Faibussowitsch if (reuse == MAT_REUSE_MATRIX) PetscCall(PetscFree(ojj)); 621225daaf8SStefano Zampini if (reuse == MAT_INITIAL_MATRIX) { 62263c07aadSStefano Zampini Mat_MPIAIJ *b; 62363c07aadSStefano Zampini Mat_SeqAIJ *d, *o; 624225daaf8SStefano Zampini 6259566063dSJacob Faibussowitsch PetscCall(MatCreateMPIAIJWithSplitArrays(comm, m, n, PETSC_DECIDE, PETSC_DECIDE, dii, djj, da, oii, ojj, oa, B)); 62663c07aadSStefano Zampini /* hack MPIAIJ */ 62763c07aadSStefano Zampini b = (Mat_MPIAIJ *)((*B)->data); 62863c07aadSStefano Zampini d = (Mat_SeqAIJ *)b->A->data; 62963c07aadSStefano Zampini o = (Mat_SeqAIJ *)b->B->data; 63063c07aadSStefano Zampini d->free_a = PETSC_TRUE; 63163c07aadSStefano Zampini d->free_ij = PETSC_TRUE; 63263c07aadSStefano Zampini o->free_a = PETSC_TRUE; 63363c07aadSStefano Zampini o->free_ij = PETSC_TRUE; 634225daaf8SStefano Zampini } else if (reuse == MAT_INPLACE_MATRIX) { 635225daaf8SStefano Zampini Mat T; 6362cf14000SStefano Zampini 6379566063dSJacob Faibussowitsch PetscCall(MatCreateMPIAIJWithSplitArrays(comm, m, n, PETSC_DECIDE, PETSC_DECIDE, dii, djj, da, oii, ojj, oa, &T)); 638*b73e3080SStefano Zampini if (sameint && downs) { /* ownership of CSR pointers is transferred to PETSc */ 639225daaf8SStefano Zampini hypre_CSRMatrixI(hdiag) = NULL; 640225daaf8SStefano Zampini hypre_CSRMatrixJ(hdiag) = NULL; 641*b73e3080SStefano Zampini } else { /* Hack MPIAIJ -> free ij but maybe not a */ 6422cf14000SStefano Zampini Mat_MPIAIJ *b = (Mat_MPIAIJ *)(T->data); 6432cf14000SStefano Zampini Mat_SeqAIJ *d = (Mat_SeqAIJ *)(b->A->data); 6442cf14000SStefano Zampini 6452cf14000SStefano Zampini d->free_ij = PETSC_TRUE; 646*b73e3080SStefano Zampini d->free_a = downs ? PETSC_FALSE : PETSC_TRUE; 647*b73e3080SStefano Zampini } 648*b73e3080SStefano Zampini if (sameint && oowns) { /* ownership of CSR pointers is transferred to PETSc */ 649*b73e3080SStefano Zampini hypre_CSRMatrixI(hoffd) = NULL; 650*b73e3080SStefano Zampini hypre_CSRMatrixJ(hoffd) = NULL; 651*b73e3080SStefano Zampini } else { /* Hack MPIAIJ -> free ij but maybe not a */ 652*b73e3080SStefano Zampini Mat_MPIAIJ *b = (Mat_MPIAIJ *)(T->data); 653*b73e3080SStefano Zampini Mat_SeqAIJ *o = (Mat_SeqAIJ *)(b->B->data); 654*b73e3080SStefano Zampini 6552cf14000SStefano Zampini o->free_ij = PETSC_TRUE; 656*b73e3080SStefano Zampini o->free_a = oowns ? PETSC_FALSE : PETSC_TRUE; 6572cf14000SStefano Zampini } 6582cf14000SStefano Zampini hypre_CSRMatrixData(hdiag) = NULL; 659225daaf8SStefano Zampini hypre_CSRMatrixData(hoffd) = NULL; 6609566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &T)); 66163c07aadSStefano Zampini } 662225daaf8SStefano Zampini } else { 663225daaf8SStefano Zampini oii = NULL; 664225daaf8SStefano Zampini ojj = NULL; 665225daaf8SStefano Zampini oa = NULL; 666225daaf8SStefano Zampini if (reuse == MAT_INITIAL_MATRIX) { 66763c07aadSStefano Zampini Mat_SeqAIJ *b; 6682cf14000SStefano Zampini 6699566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(comm, m, n, dii, djj, da, B)); 67063c07aadSStefano Zampini /* hack SeqAIJ */ 67163c07aadSStefano Zampini b = (Mat_SeqAIJ *)((*B)->data); 67263c07aadSStefano Zampini b->free_a = PETSC_TRUE; 67363c07aadSStefano Zampini b->free_ij = PETSC_TRUE; 674225daaf8SStefano Zampini } else if (reuse == MAT_INPLACE_MATRIX) { 675225daaf8SStefano Zampini Mat T; 6762cf14000SStefano Zampini 6779566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(comm, m, n, dii, djj, da, &T)); 678*b73e3080SStefano Zampini if (sameint && downs) { /* ownership of CSR pointers is transferred to PETSc */ 679225daaf8SStefano Zampini hypre_CSRMatrixI(hdiag) = NULL; 680225daaf8SStefano Zampini hypre_CSRMatrixJ(hdiag) = NULL; 681*b73e3080SStefano Zampini } else { /* free ij but maybe not a */ 6822cf14000SStefano Zampini Mat_SeqAIJ *b = (Mat_SeqAIJ *)(T->data); 6832cf14000SStefano Zampini 6842cf14000SStefano Zampini b->free_ij = PETSC_TRUE; 685*b73e3080SStefano Zampini b->free_a = downs ? PETSC_FALSE : PETSC_TRUE; 6862cf14000SStefano Zampini } 687225daaf8SStefano Zampini hypre_CSRMatrixData(hdiag) = NULL; 6889566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(A, &T)); 68963c07aadSStefano Zampini } 690225daaf8SStefano Zampini } 691225daaf8SStefano Zampini 6922cf14000SStefano Zampini /* we have to use hypre_Tfree to free the HYPRE arrays 693da81f932SPierre Jolivet that PETSc now owns */ 69463c07aadSStefano Zampini if (reuse == MAT_INPLACE_MATRIX) { 6959371c9d4SSatish Balay const char *names[6] = {"_hypre_csr_da", "_hypre_csr_oa", "_hypre_csr_dii", "_hypre_csr_djj", "_hypre_csr_oii", "_hypre_csr_ojj"}; 696*b73e3080SStefano Zampini // clang-format off 697*b73e3080SStefano Zampini void *ptrs[6] = {downs ? da : NULL, 698*b73e3080SStefano Zampini oowns ? oa : NULL, 699*b73e3080SStefano Zampini downs && sameint ? dii : NULL, 700*b73e3080SStefano Zampini downs && sameint ? djj : NULL, 701*b73e3080SStefano Zampini oowns && sameint ? oii : NULL, 702*b73e3080SStefano Zampini oowns && sameint ? ojj : NULL}; 703*b73e3080SStefano Zampini // clang-format on 704*b73e3080SStefano Zampini for (i = 0; i < 6; i++) { 705225daaf8SStefano Zampini PetscContainer c; 706225daaf8SStefano Zampini 7079566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(comm, &c)); 7089566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(c, ptrs[i])); 7099566063dSJacob Faibussowitsch PetscCall(PetscContainerSetUserDestroy(c, hypre_array_destroy)); 7109566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)(*B), names[i], (PetscObject)c)); 7119566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&c)); 712225daaf8SStefano Zampini } 71363c07aadSStefano Zampini } 7143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 71563c07aadSStefano Zampini } 71663c07aadSStefano Zampini 717d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJGetParCSR_Private(Mat A, hypre_ParCSRMatrix **hA) 718d71ae5a4SJacob Faibussowitsch { 719613e5ff0Sstefano_zampini hypre_ParCSRMatrix *tA; 720c1a070e6SStefano Zampini hypre_CSRMatrix *hdiag, *hoffd; 721c1a070e6SStefano Zampini Mat_SeqAIJ *diag, *offd; 7222cf14000SStefano Zampini PetscInt *garray, i, noffd, dnnz, onnz, *row_starts, *col_starts; 723c1a070e6SStefano Zampini MPI_Comm comm = PetscObjectComm((PetscObject)A); 724613e5ff0Sstefano_zampini PetscBool ismpiaij, isseqaij; 7252cf14000SStefano Zampini PetscBool sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int)); 7266ea7df73SStefano Zampini HYPRE_Int *hdi = NULL, *hdj = NULL, *hoi = NULL, *hoj = NULL; 7275c97c10fSStefano Zampini PetscInt *pdi = NULL, *pdj = NULL, *poi = NULL, *poj = NULL; 7286ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 7296ea7df73SStefano Zampini PetscBool iscuda = PETSC_FALSE; 7306ea7df73SStefano Zampini #endif 731c1a070e6SStefano Zampini 732c1a070e6SStefano Zampini PetscFunctionBegin; 7339566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 7349566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isseqaij)); 73508401ef6SPierre Jolivet PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Unsupported type %s", ((PetscObject)A)->type_name); 736ea9ee2c1SPierre Jolivet PetscHYPREInitialize(); 737c1a070e6SStefano Zampini if (ismpiaij) { 738c1a070e6SStefano Zampini Mat_MPIAIJ *a = (Mat_MPIAIJ *)(A->data); 739c1a070e6SStefano Zampini 740c1a070e6SStefano Zampini diag = (Mat_SeqAIJ *)a->A->data; 741c1a070e6SStefano Zampini offd = (Mat_SeqAIJ *)a->B->data; 7426ea7df73SStefano Zampini #if defined(PETSC_HAVE_CUDA) && defined(PETSC_HAVE_HYPRE_DEVICE) && defined(HYPRE_USING_CUDA) 7439566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMPIAIJCUSPARSE, &iscuda)); 7446ea7df73SStefano Zampini if (iscuda && !A->boundtocpu) { 7456ea7df73SStefano Zampini sameint = PETSC_TRUE; 7469566063dSJacob Faibussowitsch PetscCall(MatSeqAIJCUSPARSEGetIJ(a->A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj)); 7479566063dSJacob Faibussowitsch PetscCall(MatSeqAIJCUSPARSEGetIJ(a->B, PETSC_FALSE, (const HYPRE_Int **)&hoi, (const HYPRE_Int **)&hoj)); 7486ea7df73SStefano Zampini } else { 7496ea7df73SStefano Zampini #else 7506ea7df73SStefano Zampini { 7516ea7df73SStefano Zampini #endif 7526ea7df73SStefano Zampini pdi = diag->i; 7536ea7df73SStefano Zampini pdj = diag->j; 7546ea7df73SStefano Zampini poi = offd->i; 7556ea7df73SStefano Zampini poj = offd->j; 7566ea7df73SStefano Zampini if (sameint) { 7576ea7df73SStefano Zampini hdi = (HYPRE_Int *)pdi; 7586ea7df73SStefano Zampini hdj = (HYPRE_Int *)pdj; 7596ea7df73SStefano Zampini hoi = (HYPRE_Int *)poi; 7606ea7df73SStefano Zampini hoj = (HYPRE_Int *)poj; 7616ea7df73SStefano Zampini } 7626ea7df73SStefano Zampini } 763c1a070e6SStefano Zampini garray = a->garray; 764c1a070e6SStefano Zampini noffd = a->B->cmap->N; 765c1a070e6SStefano Zampini dnnz = diag->nz; 766c1a070e6SStefano Zampini onnz = offd->nz; 767c1a070e6SStefano Zampini } else { 768c1a070e6SStefano Zampini diag = (Mat_SeqAIJ *)A->data; 769c1a070e6SStefano Zampini offd = NULL; 7706ea7df73SStefano Zampini #if defined(PETSC_HAVE_CUDA) && defined(PETSC_HAVE_HYPRE_DEVICE) 7719566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATSEQAIJCUSPARSE, &iscuda)); 7726ea7df73SStefano Zampini if (iscuda && !A->boundtocpu) { 7736ea7df73SStefano Zampini sameint = PETSC_TRUE; 7749566063dSJacob Faibussowitsch PetscCall(MatSeqAIJCUSPARSEGetIJ(A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj)); 7756ea7df73SStefano Zampini } else { 7766ea7df73SStefano Zampini #else 7776ea7df73SStefano Zampini { 7786ea7df73SStefano Zampini #endif 7796ea7df73SStefano Zampini pdi = diag->i; 7806ea7df73SStefano Zampini pdj = diag->j; 7816ea7df73SStefano Zampini if (sameint) { 7826ea7df73SStefano Zampini hdi = (HYPRE_Int *)pdi; 7836ea7df73SStefano Zampini hdj = (HYPRE_Int *)pdj; 7846ea7df73SStefano Zampini } 7856ea7df73SStefano Zampini } 786c1a070e6SStefano Zampini garray = NULL; 787c1a070e6SStefano Zampini noffd = 0; 788c1a070e6SStefano Zampini dnnz = diag->nz; 789c1a070e6SStefano Zampini onnz = 0; 790c1a070e6SStefano Zampini } 791225daaf8SStefano Zampini 792c1a070e6SStefano Zampini /* create a temporary ParCSR */ 793c1a070e6SStefano Zampini if (HYPRE_AssumedPartitionCheck()) { 794c1a070e6SStefano Zampini PetscMPIInt myid; 795c1a070e6SStefano Zampini 7969566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &myid)); 797c1a070e6SStefano Zampini row_starts = A->rmap->range + myid; 798c1a070e6SStefano Zampini col_starts = A->cmap->range + myid; 799c1a070e6SStefano Zampini } else { 800c1a070e6SStefano Zampini row_starts = A->rmap->range; 801c1a070e6SStefano Zampini col_starts = A->cmap->range; 802c1a070e6SStefano Zampini } 8032cf14000SStefano Zampini tA = hypre_ParCSRMatrixCreate(comm, A->rmap->N, A->cmap->N, (HYPRE_BigInt *)row_starts, (HYPRE_BigInt *)col_starts, noffd, dnnz, onnz); 804a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 805c1a070e6SStefano Zampini hypre_ParCSRMatrixSetRowStartsOwner(tA, 0); 806c1a070e6SStefano Zampini hypre_ParCSRMatrixSetColStartsOwner(tA, 0); 807a1d2239cSSatish Balay #endif 808c1a070e6SStefano Zampini 809225daaf8SStefano Zampini /* set diagonal part */ 810c1a070e6SStefano Zampini hdiag = hypre_ParCSRMatrixDiag(tA); 8116ea7df73SStefano Zampini if (!sameint) { /* malloc CSR pointers */ 8129566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(A->rmap->n + 1, &hdi, dnnz, &hdj)); 8136ea7df73SStefano Zampini for (i = 0; i < A->rmap->n + 1; i++) hdi[i] = (HYPRE_Int)(pdi[i]); 8146ea7df73SStefano Zampini for (i = 0; i < dnnz; i++) hdj[i] = (HYPRE_Int)(pdj[i]); 8152cf14000SStefano Zampini } 8166ea7df73SStefano Zampini hypre_CSRMatrixI(hdiag) = hdi; 8176ea7df73SStefano Zampini hypre_CSRMatrixJ(hdiag) = hdj; 81839accc25SStefano Zampini hypre_CSRMatrixData(hdiag) = (HYPRE_Complex *)diag->a; 819c1a070e6SStefano Zampini hypre_CSRMatrixNumNonzeros(hdiag) = diag->nz; 820c1a070e6SStefano Zampini hypre_CSRMatrixSetRownnz(hdiag); 821c1a070e6SStefano Zampini hypre_CSRMatrixSetDataOwner(hdiag, 0); 822c1a070e6SStefano Zampini 823225daaf8SStefano Zampini /* set offdiagonal part */ 824c1a070e6SStefano Zampini hoffd = hypre_ParCSRMatrixOffd(tA); 825c1a070e6SStefano Zampini if (offd) { 8266ea7df73SStefano Zampini if (!sameint) { /* malloc CSR pointers */ 8279566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(A->rmap->n + 1, &hoi, onnz, &hoj)); 8286ea7df73SStefano Zampini for (i = 0; i < A->rmap->n + 1; i++) hoi[i] = (HYPRE_Int)(poi[i]); 8296ea7df73SStefano Zampini for (i = 0; i < onnz; i++) hoj[i] = (HYPRE_Int)(poj[i]); 8302cf14000SStefano Zampini } 8316ea7df73SStefano Zampini hypre_CSRMatrixI(hoffd) = hoi; 8326ea7df73SStefano Zampini hypre_CSRMatrixJ(hoffd) = hoj; 83339accc25SStefano Zampini hypre_CSRMatrixData(hoffd) = (HYPRE_Complex *)offd->a; 834c1a070e6SStefano Zampini hypre_CSRMatrixNumNonzeros(hoffd) = offd->nz; 835c1a070e6SStefano Zampini hypre_CSRMatrixSetRownnz(hoffd); 836c1a070e6SStefano Zampini hypre_CSRMatrixSetDataOwner(hoffd, 0); 8376ea7df73SStefano Zampini } 8386ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 839792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, iscuda ? HYPRE_MEMORY_DEVICE : HYPRE_MEMORY_HOST); 8406ea7df73SStefano Zampini #else 8416ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0) 842792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixInitialize, tA); 8436ea7df73SStefano Zampini #else 844792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, HYPRE_MEMORY_HOST); 8456ea7df73SStefano Zampini #endif 8466ea7df73SStefano Zampini #endif 8476ea7df73SStefano Zampini hypre_TFree(hypre_ParCSRMatrixColMapOffd(tA), HYPRE_MEMORY_HOST); 848c1a070e6SStefano Zampini hypre_ParCSRMatrixSetNumNonzeros(tA); 8492cf14000SStefano Zampini hypre_ParCSRMatrixColMapOffd(tA) = (HYPRE_BigInt *)garray; 850792fecdfSBarry Smith if (!hypre_ParCSRMatrixCommPkg(tA)) PetscCallExternal(hypre_MatvecCommPkgCreate, tA); 851613e5ff0Sstefano_zampini *hA = tA; 8523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 853613e5ff0Sstefano_zampini } 854c1a070e6SStefano Zampini 855d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJRestoreParCSR_Private(Mat A, hypre_ParCSRMatrix **hA) 856d71ae5a4SJacob Faibussowitsch { 857613e5ff0Sstefano_zampini hypre_CSRMatrix *hdiag, *hoffd; 8586ea7df73SStefano Zampini PetscBool ismpiaij, sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int)); 8596ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 8606ea7df73SStefano Zampini PetscBool iscuda = PETSC_FALSE; 8616ea7df73SStefano Zampini #endif 862c1a070e6SStefano Zampini 863613e5ff0Sstefano_zampini PetscFunctionBegin; 8649566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 8656ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 8669566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, "")); 8676ea7df73SStefano Zampini if (iscuda) sameint = PETSC_TRUE; 8686ea7df73SStefano Zampini #endif 869613e5ff0Sstefano_zampini hdiag = hypre_ParCSRMatrixDiag(*hA); 870613e5ff0Sstefano_zampini hoffd = hypre_ParCSRMatrixOffd(*hA); 8716ea7df73SStefano Zampini /* free temporary memory allocated by PETSc 8726ea7df73SStefano Zampini set pointers to NULL before destroying tA */ 8732cf14000SStefano Zampini if (!sameint) { 8742cf14000SStefano Zampini HYPRE_Int *hi, *hj; 8752cf14000SStefano Zampini 8762cf14000SStefano Zampini hi = hypre_CSRMatrixI(hdiag); 8772cf14000SStefano Zampini hj = hypre_CSRMatrixJ(hdiag); 8789566063dSJacob Faibussowitsch PetscCall(PetscFree2(hi, hj)); 8796ea7df73SStefano Zampini if (ismpiaij) { 8802cf14000SStefano Zampini hi = hypre_CSRMatrixI(hoffd); 8812cf14000SStefano Zampini hj = hypre_CSRMatrixJ(hoffd); 8829566063dSJacob Faibussowitsch PetscCall(PetscFree2(hi, hj)); 8832cf14000SStefano Zampini } 8842cf14000SStefano Zampini } 885c1a070e6SStefano Zampini hypre_CSRMatrixI(hdiag) = NULL; 886c1a070e6SStefano Zampini hypre_CSRMatrixJ(hdiag) = NULL; 887c1a070e6SStefano Zampini hypre_CSRMatrixData(hdiag) = NULL; 8886ea7df73SStefano Zampini if (ismpiaij) { 889c1a070e6SStefano Zampini hypre_CSRMatrixI(hoffd) = NULL; 890c1a070e6SStefano Zampini hypre_CSRMatrixJ(hoffd) = NULL; 891c1a070e6SStefano Zampini hypre_CSRMatrixData(hoffd) = NULL; 8926ea7df73SStefano Zampini } 893613e5ff0Sstefano_zampini hypre_ParCSRMatrixColMapOffd(*hA) = NULL; 894613e5ff0Sstefano_zampini hypre_ParCSRMatrixDestroy(*hA); 895613e5ff0Sstefano_zampini *hA = NULL; 8963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 897613e5ff0Sstefano_zampini } 898613e5ff0Sstefano_zampini 899613e5ff0Sstefano_zampini /* calls RAP from BoomerAMG: 9003dad0653Sstefano_zampini the resulting ParCSR will not own the column and row starts 9016ea7df73SStefano Zampini It looks like we don't need to have the diagonal entries ordered first */ 902d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_RAP(hypre_ParCSRMatrix *hR, hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hP, hypre_ParCSRMatrix **hRAP) 903d71ae5a4SJacob Faibussowitsch { 904a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 905613e5ff0Sstefano_zampini HYPRE_Int P_owns_col_starts, R_owns_row_starts; 906a1d2239cSSatish Balay #endif 907613e5ff0Sstefano_zampini 908613e5ff0Sstefano_zampini PetscFunctionBegin; 909a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 910613e5ff0Sstefano_zampini P_owns_col_starts = hypre_ParCSRMatrixOwnsColStarts(hP); 911613e5ff0Sstefano_zampini R_owns_row_starts = hypre_ParCSRMatrixOwnsRowStarts(hR); 912a1d2239cSSatish Balay #endif 9136ea7df73SStefano Zampini /* can be replaced by version test later */ 9146ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 915792fecdfSBarry Smith PetscStackPushExternal("hypre_ParCSRMatrixRAP"); 9166ea7df73SStefano Zampini *hRAP = hypre_ParCSRMatrixRAP(hR, hA, hP); 9176ea7df73SStefano Zampini PetscStackPop; 9186ea7df73SStefano Zampini #else 919792fecdfSBarry Smith PetscCallExternal(hypre_BoomerAMGBuildCoarseOperator, hR, hA, hP, hRAP); 920792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixSetNumNonzeros, *hRAP); 9216ea7df73SStefano Zampini #endif 922613e5ff0Sstefano_zampini /* hypre_BoomerAMGBuildCoarseOperator steals the col_starts from P and the row_starts from R */ 923a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 924613e5ff0Sstefano_zampini hypre_ParCSRMatrixSetRowStartsOwner(*hRAP, 0); 925613e5ff0Sstefano_zampini hypre_ParCSRMatrixSetColStartsOwner(*hRAP, 0); 926613e5ff0Sstefano_zampini if (P_owns_col_starts) hypre_ParCSRMatrixSetColStartsOwner(hP, 1); 927613e5ff0Sstefano_zampini if (R_owns_row_starts) hypre_ParCSRMatrixSetRowStartsOwner(hR, 1); 928a1d2239cSSatish Balay #endif 9293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 930613e5ff0Sstefano_zampini } 931613e5ff0Sstefano_zampini 932d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat P, Mat C) 933d71ae5a4SJacob Faibussowitsch { 9346f231fbdSstefano_zampini Mat B; 9356abb4441SStefano Zampini hypre_ParCSRMatrix *hA, *hP, *hPtAP = NULL; 9364222ddf1SHong Zhang Mat_Product *product = C->product; 937613e5ff0Sstefano_zampini 938613e5ff0Sstefano_zampini PetscFunctionBegin; 9399566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(A, &hA)); 9409566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(P, &hP)); 9419566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_RAP(hP, hA, hP, &hPtAP)); 9429566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(hPtAP, MATAIJ, PETSC_OWN_POINTER, &B)); 9434222ddf1SHong Zhang 9449566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(C, &B)); 9454222ddf1SHong Zhang C->product = product; 9464222ddf1SHong Zhang 9479566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(A, &hA)); 9489566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(P, &hP)); 9493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9506f231fbdSstefano_zampini } 9516f231fbdSstefano_zampini 952d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatPtAPSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat P, PetscReal fill, Mat C) 953d71ae5a4SJacob Faibussowitsch { 9546f231fbdSstefano_zampini PetscFunctionBegin; 9559566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATAIJ)); 9564222ddf1SHong Zhang C->ops->ptapnumeric = MatPtAPNumeric_AIJ_AIJ_wHYPRE; 9574222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_PtAP; 9583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 959613e5ff0Sstefano_zampini } 960613e5ff0Sstefano_zampini 961d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_HYPRE(Mat A, Mat P, Mat C) 962d71ae5a4SJacob Faibussowitsch { 9634cc28894Sstefano_zampini Mat B; 9644cc28894Sstefano_zampini Mat_HYPRE *hP; 9656abb4441SStefano Zampini hypre_ParCSRMatrix *hA = NULL, *Pparcsr, *ptapparcsr = NULL; 966613e5ff0Sstefano_zampini HYPRE_Int type; 967613e5ff0Sstefano_zampini MPI_Comm comm = PetscObjectComm((PetscObject)A); 9684cc28894Sstefano_zampini PetscBool ishypre; 969613e5ff0Sstefano_zampini 970613e5ff0Sstefano_zampini PetscFunctionBegin; 9719566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre)); 97228b400f6SJacob Faibussowitsch PetscCheck(ishypre, comm, PETSC_ERR_USER, "P should be of type %s", MATHYPRE); 9734cc28894Sstefano_zampini hP = (Mat_HYPRE *)P->data; 974792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type); 97508401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 976792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr); 977613e5ff0Sstefano_zampini 9789566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(A, &hA)); 9799566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, hA, Pparcsr, &ptapparcsr)); 9809566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(A, &hA)); 981225daaf8SStefano Zampini 9824cc28894Sstefano_zampini /* create temporary matrix and merge to C */ 9839566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(ptapparcsr, ((PetscObject)C)->type_name, PETSC_OWN_POINTER, &B)); 9849566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(C, &B)); 9853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9864cc28894Sstefano_zampini } 9874cc28894Sstefano_zampini 988d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_HYPRE_HYPRE(Mat A, Mat P, Mat C) 989d71ae5a4SJacob Faibussowitsch { 9904cc28894Sstefano_zampini Mat B; 9916abb4441SStefano Zampini hypre_ParCSRMatrix *Aparcsr, *Pparcsr, *ptapparcsr = NULL; 9924cc28894Sstefano_zampini Mat_HYPRE *hA, *hP; 9934cc28894Sstefano_zampini PetscBool ishypre; 9944cc28894Sstefano_zampini HYPRE_Int type; 9954cc28894Sstefano_zampini 9964cc28894Sstefano_zampini PetscFunctionBegin; 9979566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre)); 99828b400f6SJacob Faibussowitsch PetscCheck(ishypre, PetscObjectComm((PetscObject)P), PETSC_ERR_USER, "P should be of type %s", MATHYPRE); 9999566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre)); 100028b400f6SJacob Faibussowitsch PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE); 10014cc28894Sstefano_zampini hA = (Mat_HYPRE *)A->data; 10024cc28894Sstefano_zampini hP = (Mat_HYPRE *)P->data; 1003792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type); 100408401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 1005792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type); 100608401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)P), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 1007792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr); 1008792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr); 10099566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, Aparcsr, Pparcsr, &ptapparcsr)); 10109566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(ptapparcsr, MATHYPRE, PETSC_OWN_POINTER, &B)); 10119566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(C, &B)); 10123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10134cc28894Sstefano_zampini } 10144cc28894Sstefano_zampini 1015d501dc42Sstefano_zampini /* calls hypre_ParMatmul 1016d501dc42Sstefano_zampini hypre_ParMatMul uses hypre_ParMatrixCreate with the communicator of hA 10173dad0653Sstefano_zampini hypre_ParMatrixCreate does not duplicate the communicator 10186ea7df73SStefano Zampini It looks like we don't need to have the diagonal entries ordered first */ 1019d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_MatMatMult(hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hB, hypre_ParCSRMatrix **hAB) 1020d71ae5a4SJacob Faibussowitsch { 1021d501dc42Sstefano_zampini PetscFunctionBegin; 10226ea7df73SStefano Zampini /* can be replaced by version test later */ 10236ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 1024792fecdfSBarry Smith PetscStackPushExternal("hypre_ParCSRMatMat"); 10256ea7df73SStefano Zampini *hAB = hypre_ParCSRMatMat(hA, hB); 10266ea7df73SStefano Zampini #else 1027792fecdfSBarry Smith PetscStackPushExternal("hypre_ParMatmul"); 1028d501dc42Sstefano_zampini *hAB = hypre_ParMatmul(hA, hB); 10296ea7df73SStefano Zampini #endif 1030d501dc42Sstefano_zampini PetscStackPop; 10313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1032d501dc42Sstefano_zampini } 1033d501dc42Sstefano_zampini 1034d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C) 1035d71ae5a4SJacob Faibussowitsch { 10365e5acdf2Sstefano_zampini Mat D; 1037d501dc42Sstefano_zampini hypre_ParCSRMatrix *hA, *hB, *hAB = NULL; 10384222ddf1SHong Zhang Mat_Product *product = C->product; 10395e5acdf2Sstefano_zampini 10405e5acdf2Sstefano_zampini PetscFunctionBegin; 10419566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(A, &hA)); 10429566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(B, &hB)); 10439566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_MatMatMult(hA, hB, &hAB)); 10449566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(hAB, MATAIJ, PETSC_OWN_POINTER, &D)); 10454222ddf1SHong Zhang 10469566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(C, &D)); 10474222ddf1SHong Zhang C->product = product; 10484222ddf1SHong Zhang 10499566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(A, &hA)); 10509566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(B, &hB)); 10513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10525e5acdf2Sstefano_zampini } 10535e5acdf2Sstefano_zampini 1054d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatMatMultSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat B, PetscReal fill, Mat C) 1055d71ae5a4SJacob Faibussowitsch { 10565e5acdf2Sstefano_zampini PetscFunctionBegin; 10579566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATAIJ)); 10584222ddf1SHong Zhang C->ops->matmultnumeric = MatMatMultNumeric_AIJ_AIJ_wHYPRE; 10594222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_AB; 10603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10615e5acdf2Sstefano_zampini } 10625e5acdf2Sstefano_zampini 1063d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_HYPRE_HYPRE(Mat A, Mat B, Mat C) 1064d71ae5a4SJacob Faibussowitsch { 1065d501dc42Sstefano_zampini Mat D; 1066d501dc42Sstefano_zampini hypre_ParCSRMatrix *Aparcsr, *Bparcsr, *ABparcsr = NULL; 1067d501dc42Sstefano_zampini Mat_HYPRE *hA, *hB; 1068d501dc42Sstefano_zampini PetscBool ishypre; 1069d501dc42Sstefano_zampini HYPRE_Int type; 10704222ddf1SHong Zhang Mat_Product *product; 1071d501dc42Sstefano_zampini 1072d501dc42Sstefano_zampini PetscFunctionBegin; 10739566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)B, MATHYPRE, &ishypre)); 107428b400f6SJacob Faibussowitsch PetscCheck(ishypre, PetscObjectComm((PetscObject)B), PETSC_ERR_USER, "B should be of type %s", MATHYPRE); 10759566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre)); 107628b400f6SJacob Faibussowitsch PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE); 1077d501dc42Sstefano_zampini hA = (Mat_HYPRE *)A->data; 1078d501dc42Sstefano_zampini hB = (Mat_HYPRE *)B->data; 1079792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type); 108008401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 1081792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hB->ij, &type); 108208401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 1083792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr); 1084792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hB->ij, (void **)&Bparcsr); 10859566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_MatMatMult(Aparcsr, Bparcsr, &ABparcsr)); 10869566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(ABparcsr, MATHYPRE, PETSC_OWN_POINTER, &D)); 10874222ddf1SHong Zhang 1088d501dc42Sstefano_zampini /* need to use HeaderReplace because HeaderMerge messes up with the communicator */ 10894222ddf1SHong Zhang product = C->product; /* save it from MatHeaderReplace() */ 10904222ddf1SHong Zhang C->product = NULL; 10919566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(C, &D)); 10924222ddf1SHong Zhang C->product = product; 1093d501dc42Sstefano_zampini C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE; 10944222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_AB; 10953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1096d501dc42Sstefano_zampini } 1097d501dc42Sstefano_zampini 1098d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultNumeric_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, Mat D) 1099d71ae5a4SJacob Faibussowitsch { 110020e1dc0dSstefano_zampini Mat E; 11016abb4441SStefano Zampini hypre_ParCSRMatrix *hA, *hB, *hC, *hABC = NULL; 110220e1dc0dSstefano_zampini 110320e1dc0dSstefano_zampini PetscFunctionBegin; 11049566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(A, &hA)); 11059566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(B, &hB)); 11069566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(C, &hC)); 11079566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_RAP(hA, hB, hC, &hABC)); 11089566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(hABC, MATAIJ, PETSC_OWN_POINTER, &E)); 11099566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(D, &E)); 11109566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(A, &hA)); 11119566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(B, &hB)); 11129566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(C, &hC)); 11133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 111420e1dc0dSstefano_zampini } 111520e1dc0dSstefano_zampini 1116d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultSymbolic_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, PetscReal fill, Mat D) 1117d71ae5a4SJacob Faibussowitsch { 111820e1dc0dSstefano_zampini PetscFunctionBegin; 11199566063dSJacob Faibussowitsch PetscCall(MatSetType(D, MATAIJ)); 11203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 112120e1dc0dSstefano_zampini } 112220e1dc0dSstefano_zampini 1123d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_AB_HYPRE(Mat C) 1124d71ae5a4SJacob Faibussowitsch { 11254222ddf1SHong Zhang PetscFunctionBegin; 11264222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_AB; 11273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11284222ddf1SHong Zhang } 11294222ddf1SHong Zhang 1130d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_AB(Mat C) 1131d71ae5a4SJacob Faibussowitsch { 11324222ddf1SHong Zhang Mat_Product *product = C->product; 11334222ddf1SHong Zhang PetscBool Ahypre; 11344222ddf1SHong Zhang 11354222ddf1SHong Zhang PetscFunctionBegin; 11369566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)product->A, MATHYPRE, &Ahypre)); 11374222ddf1SHong Zhang if (Ahypre) { /* A is a Hypre matrix */ 11389566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATHYPRE)); 11394222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_AB_HYPRE; 11404222ddf1SHong Zhang C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE; 11413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11426718818eSStefano Zampini } 11433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11444222ddf1SHong Zhang } 11454222ddf1SHong Zhang 1146d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_PtAP_HYPRE(Mat C) 1147d71ae5a4SJacob Faibussowitsch { 11484222ddf1SHong Zhang PetscFunctionBegin; 11494222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_PtAP; 11503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11514222ddf1SHong Zhang } 11524222ddf1SHong Zhang 1153d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_PtAP(Mat C) 1154d71ae5a4SJacob Faibussowitsch { 11554222ddf1SHong Zhang Mat_Product *product = C->product; 11564222ddf1SHong Zhang PetscBool flg; 11574222ddf1SHong Zhang PetscInt type = 0; 11584222ddf1SHong Zhang const char *outTypes[4] = {"aij", "seqaij", "mpiaij", "hypre"}; 11594222ddf1SHong Zhang PetscInt ntype = 4; 11604222ddf1SHong Zhang Mat A = product->A; 11614222ddf1SHong Zhang PetscBool Ahypre; 11624222ddf1SHong Zhang 11634222ddf1SHong Zhang PetscFunctionBegin; 11649566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &Ahypre)); 11654222ddf1SHong Zhang if (Ahypre) { /* A is a Hypre matrix */ 11669566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATHYPRE)); 11674222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE; 11684222ddf1SHong Zhang C->ops->ptapnumeric = MatPtAPNumeric_HYPRE_HYPRE; 11693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11704222ddf1SHong Zhang } 11714222ddf1SHong Zhang 11724222ddf1SHong Zhang /* A is AIJ, P is Hypre, C = PtAP can be either AIJ or Hypre format */ 11734222ddf1SHong Zhang /* Get runtime option */ 11744222ddf1SHong Zhang if (product->api_user) { 1175d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatPtAP_HYPRE", "Mat"); 11769566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-matptap_hypre_outtype", "MatPtAP outtype", "MatPtAP outtype", outTypes, ntype, outTypes[type], &type, &flg)); 1177d0609cedSBarry Smith PetscOptionsEnd(); 11784222ddf1SHong Zhang } else { 1179d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatProduct_PtAP_HYPRE", "Mat"); 11809566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-mat_product_algorithm_hypre_outtype", "MatProduct_PtAP outtype", "MatProduct_PtAP", outTypes, ntype, outTypes[type], &type, &flg)); 1181d0609cedSBarry Smith PetscOptionsEnd(); 11824222ddf1SHong Zhang } 11834222ddf1SHong Zhang 11844222ddf1SHong Zhang if (type == 0 || type == 1 || type == 2) { 11859566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATAIJ)); 11864222ddf1SHong Zhang } else if (type == 3) { 11879566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATHYPRE)); 11884222ddf1SHong Zhang } else SETERRQ(PetscObjectComm((PetscObject)C), PETSC_ERR_SUP, "MatPtAP outtype is not supported"); 11894222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE; 11904222ddf1SHong Zhang C->ops->ptapnumeric = MatPtAPNumeric_AIJ_HYPRE; 11913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11924222ddf1SHong Zhang } 11934222ddf1SHong Zhang 1194d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE(Mat C) 1195d71ae5a4SJacob Faibussowitsch { 11964222ddf1SHong Zhang Mat_Product *product = C->product; 11974222ddf1SHong Zhang 11984222ddf1SHong Zhang PetscFunctionBegin; 11994222ddf1SHong Zhang switch (product->type) { 1200d71ae5a4SJacob Faibussowitsch case MATPRODUCT_AB: 1201d71ae5a4SJacob Faibussowitsch PetscCall(MatProductSetFromOptions_HYPRE_AB(C)); 1202d71ae5a4SJacob Faibussowitsch break; 1203d71ae5a4SJacob Faibussowitsch case MATPRODUCT_PtAP: 1204d71ae5a4SJacob Faibussowitsch PetscCall(MatProductSetFromOptions_HYPRE_PtAP(C)); 1205d71ae5a4SJacob Faibussowitsch break; 1206d71ae5a4SJacob Faibussowitsch default: 1207d71ae5a4SJacob Faibussowitsch break; 12084222ddf1SHong Zhang } 12093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12104222ddf1SHong Zhang } 12114222ddf1SHong Zhang 1212d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTranspose_HYPRE(Mat A, Vec x, Vec y) 1213d71ae5a4SJacob Faibussowitsch { 121463c07aadSStefano Zampini PetscFunctionBegin; 12159566063dSJacob Faibussowitsch PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_TRUE)); 12163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 121763c07aadSStefano Zampini } 121863c07aadSStefano Zampini 1219d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_HYPRE(Mat A, Vec x, Vec y) 1220d71ae5a4SJacob Faibussowitsch { 122163c07aadSStefano Zampini PetscFunctionBegin; 12229566063dSJacob Faibussowitsch PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_FALSE)); 12233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 122463c07aadSStefano Zampini } 122563c07aadSStefano Zampini 1226d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultAdd_HYPRE(Mat A, Vec x, Vec y, Vec z) 1227d71ae5a4SJacob Faibussowitsch { 1228414bd5c3SStefano Zampini PetscFunctionBegin; 122948a46eb9SPierre Jolivet if (y != z) PetscCall(VecCopy(y, z)); 12309566063dSJacob Faibussowitsch PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_FALSE)); 12313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1232414bd5c3SStefano Zampini } 1233414bd5c3SStefano Zampini 1234d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTransposeAdd_HYPRE(Mat A, Vec x, Vec y, Vec z) 1235d71ae5a4SJacob Faibussowitsch { 1236414bd5c3SStefano Zampini PetscFunctionBegin; 123748a46eb9SPierre Jolivet if (y != z) PetscCall(VecCopy(y, z)); 12389566063dSJacob Faibussowitsch PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_TRUE)); 12393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1240414bd5c3SStefano Zampini } 1241414bd5c3SStefano Zampini 1242414bd5c3SStefano Zampini /* y = a * A * x + b * y or y = a * A^t * x + b * y depending on trans */ 1243d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_MultKernel_Private(Mat A, HYPRE_Complex a, Vec x, HYPRE_Complex b, Vec y, PetscBool trans) 1244d71ae5a4SJacob Faibussowitsch { 124563c07aadSStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 124663c07aadSStefano Zampini hypre_ParCSRMatrix *parcsr; 124763c07aadSStefano Zampini hypre_ParVector *hx, *hy; 124863c07aadSStefano Zampini 124963c07aadSStefano Zampini PetscFunctionBegin; 125063c07aadSStefano Zampini if (trans) { 12519566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorPushVecRead(hA->b, x)); 12529566063dSJacob Faibussowitsch if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->x, y)); 12539566063dSJacob Faibussowitsch else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->x, y)); 1254792fecdfSBarry Smith PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hx); 1255792fecdfSBarry Smith PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hy); 125663c07aadSStefano Zampini } else { 12579566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorPushVecRead(hA->x, x)); 12589566063dSJacob Faibussowitsch if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->b, y)); 12599566063dSJacob Faibussowitsch else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->b, y)); 1260792fecdfSBarry Smith PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hx); 1261792fecdfSBarry Smith PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hy); 126263c07aadSStefano Zampini } 1263792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr); 12646ea7df73SStefano Zampini if (trans) { 1265792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixMatvecT, a, parcsr, hx, b, hy); 12666ea7df73SStefano Zampini } else { 1267792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixMatvec, a, parcsr, hx, b, hy); 12686ea7df73SStefano Zampini } 12699566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorPopVec(hA->x)); 12709566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorPopVec(hA->b)); 12713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 127263c07aadSStefano Zampini } 127363c07aadSStefano Zampini 1274d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_HYPRE(Mat A) 1275d71ae5a4SJacob Faibussowitsch { 127663c07aadSStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 127763c07aadSStefano Zampini 127863c07aadSStefano Zampini PetscFunctionBegin; 12799566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorDestroy(&hA->x)); 12809566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorDestroy(&hA->b)); 1281978814f1SStefano Zampini if (hA->ij) { 1282978814f1SStefano Zampini if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL; 1283792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixDestroy, hA->ij); 1284978814f1SStefano Zampini } 12859566063dSJacob Faibussowitsch if (hA->comm) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)A), &hA->comm)); 1286c69f721fSFande Kong 12879566063dSJacob Faibussowitsch PetscCall(MatStashDestroy_Private(&A->stash)); 12889566063dSJacob Faibussowitsch PetscCall(PetscFree(hA->array)); 1289c69f721fSFande Kong 12905fbaff96SJunchao Zhang if (hA->cooMat) { 12915fbaff96SJunchao Zhang PetscCall(MatDestroy(&hA->cooMat)); 1292e77caa6dSBarry Smith PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hA->diagJ, hA->memType)); 1293e77caa6dSBarry Smith PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hA->offdJ, hA->memType)); 1294e77caa6dSBarry Smith PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hA->diag, hA->memType)); 12955fbaff96SJunchao Zhang } 12965fbaff96SJunchao Zhang 12979566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_aij_C", NULL)); 12989566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_is_C", NULL)); 12999566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_hypre_C", NULL)); 13009566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaij_hypre_C", NULL)); 13019566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPRESetPreallocation_C", NULL)); 13029566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPREGetParCSR_C", NULL)); 13035fbaff96SJunchao Zhang PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL)); 13045fbaff96SJunchao Zhang PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL)); 13059566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 13063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 130763c07aadSStefano Zampini } 130863c07aadSStefano Zampini 1309d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetUp_HYPRE(Mat A) 1310d71ae5a4SJacob Faibussowitsch { 13114ec6421dSstefano_zampini PetscFunctionBegin; 13129566063dSJacob Faibussowitsch PetscCall(MatHYPRESetPreallocation(A, PETSC_DEFAULT, NULL, PETSC_DEFAULT, NULL)); 13133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13144ec6421dSstefano_zampini } 13154ec6421dSstefano_zampini 13166ea7df73SStefano Zampini //TODO FIX hypre_CSRMatrixMatvecOutOfPlace 13176ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 1318d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatBindToCPU_HYPRE(Mat A, PetscBool bind) 1319d71ae5a4SJacob Faibussowitsch { 13206ea7df73SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 13216ea7df73SStefano Zampini HYPRE_MemoryLocation hmem = bind ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE; 13226ea7df73SStefano Zampini 13236ea7df73SStefano Zampini PetscFunctionBegin; 13246ea7df73SStefano Zampini A->boundtocpu = bind; 13255fbaff96SJunchao Zhang if (hA->ij && hypre_IJMatrixAssembleFlag(hA->ij) && hmem != hypre_IJMatrixMemoryLocation(hA->ij)) { 13266ea7df73SStefano Zampini hypre_ParCSRMatrix *parcsr; 1327792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr); 1328792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixMigrate, parcsr, hmem); 13296ea7df73SStefano Zampini } 13309566063dSJacob Faibussowitsch if (hA->x) PetscCall(VecHYPRE_IJBindToCPU(hA->x, bind)); 13319566063dSJacob Faibussowitsch if (hA->b) PetscCall(VecHYPRE_IJBindToCPU(hA->b, bind)); 13323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13336ea7df73SStefano Zampini } 13346ea7df73SStefano Zampini #endif 13356ea7df73SStefano Zampini 1336d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_HYPRE(Mat A, MatAssemblyType mode) 1337d71ae5a4SJacob Faibussowitsch { 133863c07aadSStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1339c69f721fSFande Kong PetscMPIInt n; 1340c69f721fSFande Kong PetscInt i, j, rstart, ncols, flg; 1341c69f721fSFande Kong PetscInt *row, *col; 1342c69f721fSFande Kong PetscScalar *val; 134363c07aadSStefano Zampini 134463c07aadSStefano Zampini PetscFunctionBegin; 134508401ef6SPierre Jolivet PetscCheck(mode != MAT_FLUSH_ASSEMBLY, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_FLUSH_ASSEMBLY currently not supported with MATHYPRE"); 1346c69f721fSFande Kong 1347c69f721fSFande Kong if (!A->nooffprocentries) { 1348c69f721fSFande Kong while (1) { 13499566063dSJacob Faibussowitsch PetscCall(MatStashScatterGetMesg_Private(&A->stash, &n, &row, &col, &val, &flg)); 1350c69f721fSFande Kong if (!flg) break; 1351c69f721fSFande Kong 1352c69f721fSFande Kong for (i = 0; i < n;) { 1353c69f721fSFande Kong /* Now identify the consecutive vals belonging to the same row */ 1354c69f721fSFande Kong for (j = i, rstart = row[j]; j < n; j++) { 1355c69f721fSFande Kong if (row[j] != rstart) break; 1356c69f721fSFande Kong } 1357c69f721fSFande Kong if (j < n) ncols = j - i; 1358c69f721fSFande Kong else ncols = n - i; 1359c69f721fSFande Kong /* Now assemble all these values with a single function call */ 13609566063dSJacob Faibussowitsch PetscCall(MatSetValues_HYPRE(A, 1, row + i, ncols, col + i, val + i, A->insertmode)); 1361c69f721fSFande Kong 1362c69f721fSFande Kong i = j; 1363c69f721fSFande Kong } 1364c69f721fSFande Kong } 13659566063dSJacob Faibussowitsch PetscCall(MatStashScatterEnd_Private(&A->stash)); 1366c69f721fSFande Kong } 1367c69f721fSFande Kong 1368792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixAssemble, hA->ij); 1369336664bdSPierre Jolivet /* The assembly routine destroys the aux_matrix, we recreate it here by calling HYPRE_IJMatrixInitialize */ 1370336664bdSPierre 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 */ 1371336664bdSPierre Jolivet if (!hA->sorted_full) { 1372af1cf968SStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 1373af1cf968SStefano Zampini 1374af1cf968SStefano Zampini /* call destroy just to make sure we do not leak anything */ 1375af1cf968SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij); 1376792fecdfSBarry Smith PetscCallExternal(hypre_AuxParCSRMatrixDestroy, aux_matrix); 1377af1cf968SStefano Zampini hypre_IJMatrixTranslator(hA->ij) = NULL; 1378af1cf968SStefano Zampini 1379af1cf968SStefano Zampini /* Initialize with assembled flag -> it only recreates the aux_par_matrix */ 1380792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij); 1381af1cf968SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij); 13826ea7df73SStefano Zampini if (aux_matrix) { 1383af1cf968SStefano Zampini hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1; /* see comment in MatHYPRESetPreallocation_HYPRE */ 138422235d61SPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 1385792fecdfSBarry Smith PetscCallExternal(hypre_AuxParCSRMatrixInitialize, aux_matrix); 138622235d61SPierre Jolivet #else 1387792fecdfSBarry Smith PetscCallExternal(hypre_AuxParCSRMatrixInitialize_v2, aux_matrix, HYPRE_MEMORY_HOST); 138822235d61SPierre Jolivet #endif 1389af1cf968SStefano Zampini } 13906ea7df73SStefano Zampini } 13916ea7df73SStefano Zampini { 13926ea7df73SStefano Zampini hypre_ParCSRMatrix *parcsr; 13936ea7df73SStefano Zampini 1394792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr); 1395792fecdfSBarry Smith if (!hypre_ParCSRMatrixCommPkg(parcsr)) PetscCallExternal(hypre_MatvecCommPkgCreate, parcsr); 13966ea7df73SStefano Zampini } 13979566063dSJacob Faibussowitsch if (!hA->x) PetscCall(VecHYPRE_IJVectorCreate(A->cmap, &hA->x)); 13989566063dSJacob Faibussowitsch if (!hA->b) PetscCall(VecHYPRE_IJVectorCreate(A->rmap, &hA->b)); 13996ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 14009566063dSJacob Faibussowitsch PetscCall(MatBindToCPU_HYPRE(A, A->boundtocpu)); 14016ea7df73SStefano Zampini #endif 14023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 140363c07aadSStefano Zampini } 140463c07aadSStefano Zampini 1405d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetArray_HYPRE(Mat A, PetscInt size, void **array) 1406d71ae5a4SJacob Faibussowitsch { 1407c69f721fSFande Kong Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1408c69f721fSFande Kong 1409c69f721fSFande Kong PetscFunctionBegin; 141028b400f6SJacob Faibussowitsch PetscCheck(hA->available, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Temporary space is in use"); 1411c69f721fSFande Kong 141239accc25SStefano Zampini if (hA->size >= size) { 141339accc25SStefano Zampini *array = hA->array; 141439accc25SStefano Zampini } else { 14159566063dSJacob Faibussowitsch PetscCall(PetscFree(hA->array)); 1416c69f721fSFande Kong hA->size = size; 14179566063dSJacob Faibussowitsch PetscCall(PetscMalloc(hA->size, &hA->array)); 1418c69f721fSFande Kong *array = hA->array; 1419c69f721fSFande Kong } 1420c69f721fSFande Kong 1421c69f721fSFande Kong hA->available = PETSC_FALSE; 14223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1423c69f721fSFande Kong } 1424c69f721fSFande Kong 1425d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreArray_HYPRE(Mat A, void **array) 1426d71ae5a4SJacob Faibussowitsch { 1427c69f721fSFande Kong Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1428c69f721fSFande Kong 1429c69f721fSFande Kong PetscFunctionBegin; 1430c69f721fSFande Kong *array = NULL; 1431c69f721fSFande Kong hA->available = PETSC_TRUE; 14323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1433c69f721fSFande Kong } 1434c69f721fSFande Kong 1435d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_HYPRE(Mat A, PetscInt nr, const PetscInt rows[], PetscInt nc, const PetscInt cols[], const PetscScalar v[], InsertMode ins) 1436d71ae5a4SJacob Faibussowitsch { 1437d975228cSstefano_zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1438d975228cSstefano_zampini PetscScalar *vals = (PetscScalar *)v; 143939accc25SStefano Zampini HYPRE_Complex *sscr; 1440c69f721fSFande Kong PetscInt *cscr[2]; 1441c69f721fSFande Kong PetscInt i, nzc; 144208defe43SFande Kong void *array = NULL; 1443d975228cSstefano_zampini 1444d975228cSstefano_zampini PetscFunctionBegin; 14459566063dSJacob Faibussowitsch PetscCall(MatGetArray_HYPRE(A, sizeof(PetscInt) * (2 * nc) + sizeof(HYPRE_Complex) * nc * nr, &array)); 1446c69f721fSFande Kong cscr[0] = (PetscInt *)array; 1447c69f721fSFande Kong cscr[1] = ((PetscInt *)array) + nc; 144839accc25SStefano Zampini sscr = (HYPRE_Complex *)(((PetscInt *)array) + nc * 2); 1449d975228cSstefano_zampini for (i = 0, nzc = 0; i < nc; i++) { 1450d975228cSstefano_zampini if (cols[i] >= 0) { 1451d975228cSstefano_zampini cscr[0][nzc] = cols[i]; 1452d975228cSstefano_zampini cscr[1][nzc++] = i; 1453d975228cSstefano_zampini } 1454d975228cSstefano_zampini } 1455c69f721fSFande Kong if (!nzc) { 14569566063dSJacob Faibussowitsch PetscCall(MatRestoreArray_HYPRE(A, &array)); 14573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1458c69f721fSFande Kong } 1459d975228cSstefano_zampini 14606ea7df73SStefano Zampini #if 0 //defined(PETSC_HAVE_HYPRE_DEVICE) 14616ea7df73SStefano Zampini if (HYPRE_MEMORY_HOST != hypre_IJMatrixMemoryLocation(hA->ij)) { 14626ea7df73SStefano Zampini hypre_ParCSRMatrix *parcsr; 14636ea7df73SStefano Zampini 1464792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject,hA->ij,(void**)&parcsr); 1465792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixMigrate,parcsr, HYPRE_MEMORY_HOST); 14666ea7df73SStefano Zampini } 14676ea7df73SStefano Zampini #endif 14686ea7df73SStefano Zampini 1469d975228cSstefano_zampini if (ins == ADD_VALUES) { 1470d975228cSstefano_zampini for (i = 0; i < nr; i++) { 14716ea7df73SStefano Zampini if (rows[i] >= 0) { 1472d975228cSstefano_zampini PetscInt j; 14732cf14000SStefano Zampini HYPRE_Int hnc = (HYPRE_Int)nzc; 14742cf14000SStefano Zampini 1475aed4548fSBarry 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]); 14769566063dSJacob Faibussowitsch for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j])); 1477792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixAddToValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr); 1478d975228cSstefano_zampini } 1479d975228cSstefano_zampini vals += nc; 1480d975228cSstefano_zampini } 1481d975228cSstefano_zampini } else { /* INSERT_VALUES */ 1482d975228cSstefano_zampini PetscInt rst, ren; 1483c69f721fSFande Kong 14849566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rst, &ren)); 1485d975228cSstefano_zampini for (i = 0; i < nr; i++) { 14866ea7df73SStefano Zampini if (rows[i] >= 0) { 1487d975228cSstefano_zampini PetscInt j; 14882cf14000SStefano Zampini HYPRE_Int hnc = (HYPRE_Int)nzc; 14892cf14000SStefano Zampini 1490aed4548fSBarry 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]); 14919566063dSJacob Faibussowitsch for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j])); 1492c69f721fSFande Kong /* nonlocal values */ 14939566063dSJacob Faibussowitsch if (rows[i] < rst || rows[i] >= ren) PetscCall(MatStashValuesRow_Private(&A->stash, rows[i], nzc, cscr[0], (PetscScalar *)sscr, PETSC_FALSE)); 1494c69f721fSFande Kong /* local values */ 1495792fecdfSBarry Smith else PetscCallExternal(HYPRE_IJMatrixSetValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr); 1496d975228cSstefano_zampini } 1497d975228cSstefano_zampini vals += nc; 1498d975228cSstefano_zampini } 1499d975228cSstefano_zampini } 1500c69f721fSFande Kong 15019566063dSJacob Faibussowitsch PetscCall(MatRestoreArray_HYPRE(A, &array)); 15023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1503d975228cSstefano_zampini } 1504d975228cSstefano_zampini 1505d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRESetPreallocation_HYPRE(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[]) 1506d71ae5a4SJacob Faibussowitsch { 1507d975228cSstefano_zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 15087d968826Sstefano_zampini HYPRE_Int *hdnnz, *honnz; 150906a29025Sstefano_zampini PetscInt i, rs, re, cs, ce, bs; 1510d975228cSstefano_zampini PetscMPIInt size; 1511d975228cSstefano_zampini 1512d975228cSstefano_zampini PetscFunctionBegin; 15139566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 15149566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 1515d975228cSstefano_zampini rs = A->rmap->rstart; 1516d975228cSstefano_zampini re = A->rmap->rend; 1517d975228cSstefano_zampini cs = A->cmap->rstart; 1518d975228cSstefano_zampini ce = A->cmap->rend; 1519d975228cSstefano_zampini if (!hA->ij) { 1520792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rs, re - 1, cs, ce - 1, &hA->ij); 1521792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR); 1522d975228cSstefano_zampini } else { 15232cf14000SStefano Zampini HYPRE_BigInt hrs, hre, hcs, hce; 1524792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetLocalRange, hA->ij, &hrs, &hre, &hcs, &hce); 1525aed4548fSBarry 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); 1526aed4548fSBarry 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); 1527d975228cSstefano_zampini } 15289566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 152906a29025Sstefano_zampini if (dnz == PETSC_DEFAULT || dnz == PETSC_DECIDE) dnz = 10 * bs; 153006a29025Sstefano_zampini if (onz == PETSC_DEFAULT || onz == PETSC_DECIDE) onz = 10 * bs; 153106a29025Sstefano_zampini 1532d975228cSstefano_zampini if (!dnnz) { 15339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n, &hdnnz)); 1534d975228cSstefano_zampini for (i = 0; i < A->rmap->n; i++) hdnnz[i] = dnz; 1535d975228cSstefano_zampini } else { 15367d968826Sstefano_zampini hdnnz = (HYPRE_Int *)dnnz; 1537d975228cSstefano_zampini } 15389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 1539d975228cSstefano_zampini if (size > 1) { 1540ddbeb582SStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 1541d975228cSstefano_zampini if (!onnz) { 15429566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n, &honnz)); 1543d975228cSstefano_zampini for (i = 0; i < A->rmap->n; i++) honnz[i] = onz; 154422235d61SPierre Jolivet } else honnz = (HYPRE_Int *)onnz; 1545ddbeb582SStefano Zampini /* SetDiagOffdSizes sets hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0, since it seems 1546ddbeb582SStefano Zampini they assume the user will input the entire row values, properly sorted 1547336664bdSPierre Jolivet In PETSc, we don't make such an assumption and set this flag to 1, 1548336664bdSPierre Jolivet unless the option MAT_SORTED_FULL is set to true. 1549ddbeb582SStefano Zampini Also, to avoid possible memory leaks, we destroy and recreate the translator 1550ddbeb582SStefano Zampini This has to be done here, as HYPRE_IJMatrixInitialize will properly initialize 1551ddbeb582SStefano Zampini the IJ matrix for us */ 1552ddbeb582SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij); 1553ddbeb582SStefano Zampini hypre_AuxParCSRMatrixDestroy(aux_matrix); 1554ddbeb582SStefano Zampini hypre_IJMatrixTranslator(hA->ij) = NULL; 1555792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, hA->ij, hdnnz, honnz); 1556ddbeb582SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij); 1557336664bdSPierre Jolivet hypre_AuxParCSRMatrixNeedAux(aux_matrix) = !hA->sorted_full; 1558d975228cSstefano_zampini } else { 1559d975228cSstefano_zampini honnz = NULL; 1560792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetRowSizes, hA->ij, hdnnz); 1561d975228cSstefano_zampini } 1562ddbeb582SStefano Zampini 1563af1cf968SStefano Zampini /* reset assembled flag and call the initialize method */ 1564af1cf968SStefano Zampini hypre_IJMatrixAssembleFlag(hA->ij) = 0; 15656ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 1566792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij); 15676ea7df73SStefano Zampini #else 1568792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize_v2, hA->ij, HYPRE_MEMORY_HOST); 15696ea7df73SStefano Zampini #endif 157048a46eb9SPierre Jolivet if (!dnnz) PetscCall(PetscFree(hdnnz)); 157148a46eb9SPierre Jolivet if (!onnz && honnz) PetscCall(PetscFree(honnz)); 1572af1cf968SStefano Zampini /* Match AIJ logic */ 157306a29025Sstefano_zampini A->preallocated = PETSC_TRUE; 1574af1cf968SStefano Zampini A->assembled = PETSC_FALSE; 15753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1576d975228cSstefano_zampini } 1577d975228cSstefano_zampini 1578d975228cSstefano_zampini /*@C 1579d975228cSstefano_zampini MatHYPRESetPreallocation - Preallocates memory for a sparse parallel matrix in HYPRE IJ format 1580d975228cSstefano_zampini 1581c3339decSBarry Smith Collective 1582d975228cSstefano_zampini 1583d975228cSstefano_zampini Input Parameters: 1584d975228cSstefano_zampini + A - the matrix 1585d975228cSstefano_zampini . dnz - number of nonzeros per row in DIAGONAL portion of local submatrix 1586d975228cSstefano_zampini (same value is used for all local rows) 1587d975228cSstefano_zampini . dnnz - array containing the number of nonzeros in the various rows of the 1588d975228cSstefano_zampini DIAGONAL portion of the local submatrix (possibly different for each row) 15892ef1f0ffSBarry Smith or `NULL` (`PETSC_NULL_INTEGER` in Fortran), if `d_nz` is used to specify the nonzero structure. 15902ef1f0ffSBarry Smith The size of this array is equal to the number of local rows, i.e `m`. 1591d975228cSstefano_zampini For matrices that will be factored, you must leave room for (and set) 1592d975228cSstefano_zampini the diagonal entry even if it is zero. 1593d975228cSstefano_zampini . onz - number of nonzeros per row in the OFF-DIAGONAL portion of local 1594d975228cSstefano_zampini submatrix (same value is used for all local rows). 1595d975228cSstefano_zampini - onnz - array containing the number of nonzeros in the various rows of the 1596d975228cSstefano_zampini OFF-DIAGONAL portion of the local submatrix (possibly different for 15972ef1f0ffSBarry Smith each row) or `NULL` (`PETSC_NULL_INTEGER` in Fortran), if `o_nz` is used to specify the nonzero 1598d975228cSstefano_zampini structure. The size of this array is equal to the number 15992ef1f0ffSBarry Smith of local rows, i.e `m`. 1600d975228cSstefano_zampini 16012fe279fdSBarry Smith Level: intermediate 16022fe279fdSBarry Smith 160311a5261eSBarry Smith Note: 16042ef1f0ffSBarry Smith If the *nnz parameter is given then the *nz parameter is ignored; for sequential matrices, `onz` and `onnz` are ignored. 1605d975228cSstefano_zampini 16061cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatMPIAIJSetPreallocation()`, `MATHYPRE`, `MATAIJ` 1607d975228cSstefano_zampini @*/ 1608d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHYPRESetPreallocation(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[]) 1609d71ae5a4SJacob Faibussowitsch { 1610d975228cSstefano_zampini PetscFunctionBegin; 1611d975228cSstefano_zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1612d975228cSstefano_zampini PetscValidType(A, 1); 1613cac4c232SBarry Smith PetscTryMethod(A, "MatHYPRESetPreallocation_C", (Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]), (A, dnz, dnnz, onz, onnz)); 16143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1615d975228cSstefano_zampini } 1616d975228cSstefano_zampini 161720f4b53cSBarry Smith /*@C 16182ef1f0ffSBarry Smith MatCreateFromParCSR - Creates a `Mat` from a `hypre_ParCSRMatrix` 1619225daaf8SStefano Zampini 1620225daaf8SStefano Zampini Collective 1621225daaf8SStefano Zampini 1622225daaf8SStefano Zampini Input Parameters: 16232ef1f0ffSBarry Smith + parcsr - the pointer to the `hypre_ParCSRMatrix` 16242ef1f0ffSBarry Smith . mtype - matrix type to be created. Currently `MATAIJ`, `MATIS` and `MATHYPRE` are supported. 162520f4b53cSBarry Smith - copymode - PETSc copying options, see `PetscCopyMode` 1626225daaf8SStefano Zampini 1627225daaf8SStefano Zampini Output Parameter: 1628225daaf8SStefano Zampini . A - the matrix 1629225daaf8SStefano Zampini 1630225daaf8SStefano Zampini Level: intermediate 1631225daaf8SStefano Zampini 16321cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatHYPRE`, `PetscCopyMode` 163320f4b53cSBarry Smith @*/ 1634d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreateFromParCSR(hypre_ParCSRMatrix *parcsr, MatType mtype, PetscCopyMode copymode, Mat *A) 1635d71ae5a4SJacob Faibussowitsch { 1636225daaf8SStefano Zampini Mat T; 1637978814f1SStefano Zampini Mat_HYPRE *hA; 1638978814f1SStefano Zampini MPI_Comm comm; 1639978814f1SStefano Zampini PetscInt rstart, rend, cstart, cend, M, N; 1640d248a85cSRichard Tran Mills PetscBool isseqaij, isseqaijmkl, ismpiaij, isaij, ishyp, isis; 1641978814f1SStefano Zampini 1642978814f1SStefano Zampini PetscFunctionBegin; 1643978814f1SStefano Zampini comm = hypre_ParCSRMatrixComm(parcsr); 16449566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQAIJ, &isseqaij)); 16459566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQAIJMKL, &isseqaijmkl)); 16469566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPIAIJ, &ismpiaij)); 16479566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATAIJ, &isaij)); 16489566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATHYPRE, &ishyp)); 16499566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATIS, &isis)); 1650d248a85cSRichard Tran Mills isaij = (PetscBool)(isseqaij || isseqaijmkl || ismpiaij || isaij); 16516ea7df73SStefano Zampini /* TODO */ 1652aed4548fSBarry 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); 1653978814f1SStefano Zampini /* access ParCSRMatrix */ 1654978814f1SStefano Zampini rstart = hypre_ParCSRMatrixFirstRowIndex(parcsr); 1655978814f1SStefano Zampini rend = hypre_ParCSRMatrixLastRowIndex(parcsr); 1656978814f1SStefano Zampini cstart = hypre_ParCSRMatrixFirstColDiag(parcsr); 1657978814f1SStefano Zampini cend = hypre_ParCSRMatrixLastColDiag(parcsr); 1658978814f1SStefano Zampini M = hypre_ParCSRMatrixGlobalNumRows(parcsr); 1659978814f1SStefano Zampini N = hypre_ParCSRMatrixGlobalNumCols(parcsr); 1660978814f1SStefano Zampini 1661fa92c42cSstefano_zampini /* fix for empty local rows/columns */ 1662fa92c42cSstefano_zampini if (rend < rstart) rend = rstart; 1663fa92c42cSstefano_zampini if (cend < cstart) cend = cstart; 1664fa92c42cSstefano_zampini 1665e6471dc9SStefano Zampini /* PETSc convention */ 1666e6471dc9SStefano Zampini rend++; 1667e6471dc9SStefano Zampini cend++; 1668e6471dc9SStefano Zampini rend = PetscMin(rend, M); 1669e6471dc9SStefano Zampini cend = PetscMin(cend, N); 1670e6471dc9SStefano Zampini 1671978814f1SStefano Zampini /* create PETSc matrix with MatHYPRE */ 16729566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &T)); 16739566063dSJacob Faibussowitsch PetscCall(MatSetSizes(T, rend - rstart, cend - cstart, M, N)); 16749566063dSJacob Faibussowitsch PetscCall(MatSetType(T, MATHYPRE)); 1675225daaf8SStefano Zampini hA = (Mat_HYPRE *)(T->data); 1676978814f1SStefano Zampini 1677978814f1SStefano Zampini /* create HYPRE_IJMatrix */ 1678792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rstart, rend - 1, cstart, cend - 1, &hA->ij); 1679792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR); 168045b8d346SStefano Zampini 16816ea7df73SStefano Zampini // TODO DEV 168245b8d346SStefano Zampini /* create new ParCSR object if needed */ 168345b8d346SStefano Zampini if (ishyp && copymode == PETSC_COPY_VALUES) { 168445b8d346SStefano Zampini hypre_ParCSRMatrix *new_parcsr; 16856ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0) 168645b8d346SStefano Zampini hypre_CSRMatrix *hdiag, *hoffd, *ndiag, *noffd; 168745b8d346SStefano Zampini 16880e6427aaSSatish Balay new_parcsr = hypre_ParCSRMatrixClone(parcsr, 0); 168945b8d346SStefano Zampini hdiag = hypre_ParCSRMatrixDiag(parcsr); 169045b8d346SStefano Zampini hoffd = hypre_ParCSRMatrixOffd(parcsr); 169145b8d346SStefano Zampini ndiag = hypre_ParCSRMatrixDiag(new_parcsr); 169245b8d346SStefano Zampini noffd = hypre_ParCSRMatrixOffd(new_parcsr); 16939566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hypre_CSRMatrixData(ndiag), hypre_CSRMatrixData(hdiag), hypre_CSRMatrixNumNonzeros(hdiag))); 16949566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hypre_CSRMatrixData(noffd), hypre_CSRMatrixData(hoffd), hypre_CSRMatrixNumNonzeros(hoffd))); 16956ea7df73SStefano Zampini #else 16966ea7df73SStefano Zampini new_parcsr = hypre_ParCSRMatrixClone(parcsr, 1); 16976ea7df73SStefano Zampini #endif 169845b8d346SStefano Zampini parcsr = new_parcsr; 169945b8d346SStefano Zampini copymode = PETSC_OWN_POINTER; 170045b8d346SStefano Zampini } 1701978814f1SStefano Zampini 1702978814f1SStefano Zampini /* set ParCSR object */ 1703978814f1SStefano Zampini hypre_IJMatrixObject(hA->ij) = parcsr; 17044ec6421dSstefano_zampini T->preallocated = PETSC_TRUE; 1705978814f1SStefano Zampini 1706978814f1SStefano Zampini /* set assembled flag */ 1707978814f1SStefano Zampini hypre_IJMatrixAssembleFlag(hA->ij) = 1; 17086ea7df73SStefano Zampini #if 0 1709792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize,hA->ij); 17106ea7df73SStefano Zampini #endif 1711225daaf8SStefano Zampini if (ishyp) { 17126d2a658fSstefano_zampini PetscMPIInt myid = 0; 17136d2a658fSstefano_zampini 17146d2a658fSstefano_zampini /* make sure we always have row_starts and col_starts available */ 171548a46eb9SPierre Jolivet if (HYPRE_AssumedPartitionCheck()) PetscCallMPI(MPI_Comm_rank(comm, &myid)); 1716a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 17176d2a658fSstefano_zampini if (!hypre_ParCSRMatrixOwnsColStarts(parcsr)) { 17186d2a658fSstefano_zampini PetscLayout map; 17196d2a658fSstefano_zampini 17209566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(T, NULL, &map)); 17219566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(map)); 17222cf14000SStefano Zampini hypre_ParCSRMatrixColStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid); 17236d2a658fSstefano_zampini } 17246d2a658fSstefano_zampini if (!hypre_ParCSRMatrixOwnsRowStarts(parcsr)) { 17256d2a658fSstefano_zampini PetscLayout map; 17266d2a658fSstefano_zampini 17279566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(T, &map, NULL)); 17289566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(map)); 17292cf14000SStefano Zampini hypre_ParCSRMatrixRowStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid); 17306d2a658fSstefano_zampini } 1731a1d2239cSSatish Balay #endif 1732978814f1SStefano Zampini /* prevent from freeing the pointer */ 1733978814f1SStefano Zampini if (copymode == PETSC_USE_POINTER) hA->inner_free = PETSC_FALSE; 1734225daaf8SStefano Zampini *A = T; 17359566063dSJacob Faibussowitsch PetscCall(MatSetOption(*A, MAT_SORTED_FULL, PETSC_TRUE)); 17369566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*A, MAT_FINAL_ASSEMBLY)); 17379566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*A, MAT_FINAL_ASSEMBLY)); 1738bb4689ddSStefano Zampini } else if (isaij) { 1739bb4689ddSStefano Zampini if (copymode != PETSC_OWN_POINTER) { 1740225daaf8SStefano Zampini /* prevent from freeing the pointer */ 1741225daaf8SStefano Zampini hA->inner_free = PETSC_FALSE; 17429566063dSJacob Faibussowitsch PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INITIAL_MATRIX, A)); 17439566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 1744225daaf8SStefano Zampini } else { /* AIJ return type with PETSC_OWN_POINTER */ 17459566063dSJacob Faibussowitsch PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INPLACE_MATRIX, &T)); 1746225daaf8SStefano Zampini *A = T; 1747225daaf8SStefano Zampini } 1748bb4689ddSStefano Zampini } else if (isis) { 17499566063dSJacob Faibussowitsch PetscCall(MatConvert_HYPRE_IS(T, MATIS, MAT_INITIAL_MATRIX, A)); 17508cfe8d00SStefano Zampini if (copymode != PETSC_OWN_POINTER) hA->inner_free = PETSC_FALSE; 17519566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 1752bb4689ddSStefano Zampini } 17533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1754978814f1SStefano Zampini } 1755978814f1SStefano Zampini 1756d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPREGetParCSR_HYPRE(Mat A, hypre_ParCSRMatrix **parcsr) 1757d71ae5a4SJacob Faibussowitsch { 1758dd9c0a25Sstefano_zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1759dd9c0a25Sstefano_zampini HYPRE_Int type; 1760dd9c0a25Sstefano_zampini 1761dd9c0a25Sstefano_zampini PetscFunctionBegin; 176228b400f6SJacob Faibussowitsch PetscCheck(hA->ij, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "HYPRE_IJMatrix not present"); 1763792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type); 176408401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "HYPRE_IJMatrix is not of type HYPRE_PARCSR"); 1765792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)parcsr); 17663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1767dd9c0a25Sstefano_zampini } 1768dd9c0a25Sstefano_zampini 176920f4b53cSBarry Smith /*@C 1770dd9c0a25Sstefano_zampini MatHYPREGetParCSR - Gets the pointer to the ParCSR matrix 1771dd9c0a25Sstefano_zampini 17722ef1f0ffSBarry Smith Not Collective 1773dd9c0a25Sstefano_zampini 177420f4b53cSBarry Smith Input Parameter: 177520f4b53cSBarry Smith . A - the `MATHYPRE` object 1776dd9c0a25Sstefano_zampini 1777dd9c0a25Sstefano_zampini Output Parameter: 17782ef1f0ffSBarry Smith . parcsr - the pointer to the `hypre_ParCSRMatrix` 1779dd9c0a25Sstefano_zampini 1780dd9c0a25Sstefano_zampini Level: intermediate 1781dd9c0a25Sstefano_zampini 17821cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatHYPRE`, `PetscCopyMode` 178320f4b53cSBarry Smith @*/ 1784d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHYPREGetParCSR(Mat A, hypre_ParCSRMatrix **parcsr) 1785d71ae5a4SJacob Faibussowitsch { 1786dd9c0a25Sstefano_zampini PetscFunctionBegin; 1787dd9c0a25Sstefano_zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1788dd9c0a25Sstefano_zampini PetscValidType(A, 1); 1789cac4c232SBarry Smith PetscUseMethod(A, "MatHYPREGetParCSR_C", (Mat, hypre_ParCSRMatrix **), (A, parcsr)); 17903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1791dd9c0a25Sstefano_zampini } 1792dd9c0a25Sstefano_zampini 1793d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_HYPRE(Mat A, PetscBool *missing, PetscInt *dd) 1794d71ae5a4SJacob Faibussowitsch { 179568ec7858SStefano Zampini hypre_ParCSRMatrix *parcsr; 179668ec7858SStefano Zampini hypre_CSRMatrix *ha; 179768ec7858SStefano Zampini PetscInt rst; 179868ec7858SStefano Zampini 179968ec7858SStefano Zampini PetscFunctionBegin; 180008401ef6SPierre Jolivet PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented with non-square diagonal blocks"); 18019566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rst, NULL)); 18029566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 180368ec7858SStefano Zampini if (missing) *missing = PETSC_FALSE; 180468ec7858SStefano Zampini if (dd) *dd = -1; 180568ec7858SStefano Zampini ha = hypre_ParCSRMatrixDiag(parcsr); 180668ec7858SStefano Zampini if (ha) { 180768299464SStefano Zampini PetscInt size, i; 180868299464SStefano Zampini HYPRE_Int *ii, *jj; 180968ec7858SStefano Zampini 181068ec7858SStefano Zampini size = hypre_CSRMatrixNumRows(ha); 181168ec7858SStefano Zampini ii = hypre_CSRMatrixI(ha); 181268ec7858SStefano Zampini jj = hypre_CSRMatrixJ(ha); 181368ec7858SStefano Zampini for (i = 0; i < size; i++) { 181468ec7858SStefano Zampini PetscInt j; 181568ec7858SStefano Zampini PetscBool found = PETSC_FALSE; 181668ec7858SStefano Zampini 18179371c9d4SSatish Balay for (j = ii[i]; j < ii[i + 1] && !found; j++) found = (jj[j] == i) ? PETSC_TRUE : PETSC_FALSE; 181868ec7858SStefano Zampini 181968ec7858SStefano Zampini if (!found) { 18203ba16761SJacob Faibussowitsch PetscCall(PetscInfo(A, "Matrix is missing local diagonal entry %" PetscInt_FMT "\n", i)); 182168ec7858SStefano Zampini if (missing) *missing = PETSC_TRUE; 182268ec7858SStefano Zampini if (dd) *dd = i + rst; 18233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 182468ec7858SStefano Zampini } 182568ec7858SStefano Zampini } 182668ec7858SStefano Zampini if (!size) { 18273ba16761SJacob Faibussowitsch PetscCall(PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n")); 182868ec7858SStefano Zampini if (missing) *missing = PETSC_TRUE; 182968ec7858SStefano Zampini if (dd) *dd = rst; 183068ec7858SStefano Zampini } 183168ec7858SStefano Zampini } else { 18323ba16761SJacob Faibussowitsch PetscCall(PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n")); 183368ec7858SStefano Zampini if (missing) *missing = PETSC_TRUE; 183468ec7858SStefano Zampini if (dd) *dd = rst; 183568ec7858SStefano Zampini } 18363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 183768ec7858SStefano Zampini } 183868ec7858SStefano Zampini 1839d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatScale_HYPRE(Mat A, PetscScalar s) 1840d71ae5a4SJacob Faibussowitsch { 184168ec7858SStefano Zampini hypre_ParCSRMatrix *parcsr; 18426ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 184368ec7858SStefano Zampini hypre_CSRMatrix *ha; 18446ea7df73SStefano Zampini #endif 184539accc25SStefano Zampini HYPRE_Complex hs; 184668ec7858SStefano Zampini 184768ec7858SStefano Zampini PetscFunctionBegin; 18489566063dSJacob Faibussowitsch PetscCall(PetscHYPREScalarCast(s, &hs)); 18499566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 18506ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 19, 0) 1851792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixScale, parcsr, hs); 18526ea7df73SStefano Zampini #else /* diagonal part */ 185368ec7858SStefano Zampini ha = hypre_ParCSRMatrixDiag(parcsr); 185468ec7858SStefano Zampini if (ha) { 185568299464SStefano Zampini PetscInt size, i; 185668299464SStefano Zampini HYPRE_Int *ii; 185739accc25SStefano Zampini HYPRE_Complex *a; 185868ec7858SStefano Zampini 185968ec7858SStefano Zampini size = hypre_CSRMatrixNumRows(ha); 186068ec7858SStefano Zampini a = hypre_CSRMatrixData(ha); 186168ec7858SStefano Zampini ii = hypre_CSRMatrixI(ha); 186239accc25SStefano Zampini for (i = 0; i < ii[size]; i++) a[i] *= hs; 186368ec7858SStefano Zampini } 186468ec7858SStefano Zampini /* offdiagonal part */ 186568ec7858SStefano Zampini ha = hypre_ParCSRMatrixOffd(parcsr); 186668ec7858SStefano Zampini if (ha) { 186768299464SStefano Zampini PetscInt size, i; 186868299464SStefano Zampini HYPRE_Int *ii; 186939accc25SStefano Zampini HYPRE_Complex *a; 187068ec7858SStefano Zampini 187168ec7858SStefano Zampini size = hypre_CSRMatrixNumRows(ha); 187268ec7858SStefano Zampini a = hypre_CSRMatrixData(ha); 187368ec7858SStefano Zampini ii = hypre_CSRMatrixI(ha); 187439accc25SStefano Zampini for (i = 0; i < ii[size]; i++) a[i] *= hs; 187568ec7858SStefano Zampini } 18766ea7df73SStefano Zampini #endif 18773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 187868ec7858SStefano Zampini } 187968ec7858SStefano Zampini 1880d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_HYPRE(Mat A, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 1881d71ae5a4SJacob Faibussowitsch { 188268ec7858SStefano Zampini hypre_ParCSRMatrix *parcsr; 188368299464SStefano Zampini HYPRE_Int *lrows; 188468299464SStefano Zampini PetscInt rst, ren, i; 188568ec7858SStefano Zampini 188668ec7858SStefano Zampini PetscFunctionBegin; 188708401ef6SPierre Jolivet PetscCheck(!x && !b, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "To be implemented"); 18889566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 18899566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRows, &lrows)); 18909566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rst, &ren)); 189168ec7858SStefano Zampini for (i = 0; i < numRows; i++) { 18927a46b595SBarry Smith PetscCheck(rows[i] >= rst && rows[i] < ren, PETSC_COMM_SELF, PETSC_ERR_SUP, "Non-local rows not yet supported"); 189368ec7858SStefano Zampini lrows[i] = rows[i] - rst; 189468ec7858SStefano Zampini } 1895792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixEliminateRowsCols, parcsr, numRows, lrows); 18969566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 18973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 189868ec7858SStefano Zampini } 189968ec7858SStefano Zampini 1900d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPRE_CSRMatrix(hypre_CSRMatrix *ha) 1901d71ae5a4SJacob Faibussowitsch { 1902c69f721fSFande Kong PetscFunctionBegin; 1903c69f721fSFande Kong if (ha) { 1904c69f721fSFande Kong HYPRE_Int *ii, size; 1905c69f721fSFande Kong HYPRE_Complex *a; 1906c69f721fSFande Kong 1907c69f721fSFande Kong size = hypre_CSRMatrixNumRows(ha); 1908c69f721fSFande Kong a = hypre_CSRMatrixData(ha); 1909c69f721fSFande Kong ii = hypre_CSRMatrixI(ha); 1910c69f721fSFande Kong 19119566063dSJacob Faibussowitsch if (a) PetscCall(PetscArrayzero(a, ii[size])); 1912c69f721fSFande Kong } 19133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1914c69f721fSFande Kong } 1915c69f721fSFande Kong 1916d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroEntries_HYPRE(Mat A) 1917d71ae5a4SJacob Faibussowitsch { 19186ea7df73SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 19196ea7df73SStefano Zampini 19206ea7df73SStefano Zampini PetscFunctionBegin; 19216ea7df73SStefano Zampini if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(hA->ij)) { 1922792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetConstantValues, hA->ij, 0.0); 19236ea7df73SStefano Zampini } else { 1924c69f721fSFande Kong hypre_ParCSRMatrix *parcsr; 1925c69f721fSFande Kong 19269566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 19279566063dSJacob Faibussowitsch PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr))); 19289566063dSJacob Faibussowitsch PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr))); 19296ea7df73SStefano Zampini } 19303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1931c69f721fSFande Kong } 1932c69f721fSFande Kong 1933d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_HYPRE_CSRMatrix(hypre_CSRMatrix *hA, PetscInt N, const PetscInt rows[], HYPRE_Complex diag) 1934d71ae5a4SJacob Faibussowitsch { 193539accc25SStefano Zampini PetscInt ii; 193639accc25SStefano Zampini HYPRE_Int *i, *j; 193739accc25SStefano Zampini HYPRE_Complex *a; 1938c69f721fSFande Kong 1939c69f721fSFande Kong PetscFunctionBegin; 19403ba16761SJacob Faibussowitsch if (!hA) PetscFunctionReturn(PETSC_SUCCESS); 1941c69f721fSFande Kong 194239accc25SStefano Zampini i = hypre_CSRMatrixI(hA); 194339accc25SStefano Zampini j = hypre_CSRMatrixJ(hA); 1944c69f721fSFande Kong a = hypre_CSRMatrixData(hA); 1945c69f721fSFande Kong 1946c69f721fSFande Kong for (ii = 0; ii < N; ii++) { 194739accc25SStefano Zampini HYPRE_Int jj, ibeg, iend, irow; 194839accc25SStefano Zampini 1949c69f721fSFande Kong irow = rows[ii]; 1950c69f721fSFande Kong ibeg = i[irow]; 1951c69f721fSFande Kong iend = i[irow + 1]; 1952c69f721fSFande Kong for (jj = ibeg; jj < iend; jj++) 1953c69f721fSFande Kong if (j[jj] == irow) a[jj] = diag; 1954c69f721fSFande Kong else a[jj] = 0.0; 1955c69f721fSFande Kong } 19563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1957c69f721fSFande Kong } 1958c69f721fSFande Kong 1959d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_HYPRE(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 1960d71ae5a4SJacob Faibussowitsch { 1961c69f721fSFande Kong hypre_ParCSRMatrix *parcsr; 1962c69f721fSFande Kong PetscInt *lrows, len; 196339accc25SStefano Zampini HYPRE_Complex hdiag; 1964c69f721fSFande Kong 1965c69f721fSFande Kong PetscFunctionBegin; 196608401ef6SPierre Jolivet PetscCheck(!x && !b, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Does not support to modify the solution and the right hand size"); 19679566063dSJacob Faibussowitsch PetscCall(PetscHYPREScalarCast(diag, &hdiag)); 1968c69f721fSFande Kong /* retrieve the internal matrix */ 19699566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 1970c69f721fSFande Kong /* get locally owned rows */ 19719566063dSJacob Faibussowitsch PetscCall(MatZeroRowsMapLocal_Private(A, N, rows, &len, &lrows)); 1972c69f721fSFande Kong /* zero diagonal part */ 19739566063dSJacob Faibussowitsch PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr), len, lrows, hdiag)); 1974c69f721fSFande Kong /* zero off-diagonal part */ 19759566063dSJacob Faibussowitsch PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr), len, lrows, 0.0)); 1976c69f721fSFande Kong 19779566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 19783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1979c69f721fSFande Kong } 1980c69f721fSFande Kong 1981d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_HYPRE(Mat mat, MatAssemblyType mode) 1982d71ae5a4SJacob Faibussowitsch { 1983c69f721fSFande Kong PetscFunctionBegin; 19843ba16761SJacob Faibussowitsch if (mat->nooffprocentries) PetscFunctionReturn(PETSC_SUCCESS); 1985c69f721fSFande Kong 19869566063dSJacob Faibussowitsch PetscCall(MatStashScatterBegin_Private(mat, &mat->stash, mat->rmap->range)); 19873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1988c69f721fSFande Kong } 1989c69f721fSFande Kong 1990d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) 1991d71ae5a4SJacob Faibussowitsch { 1992c69f721fSFande Kong hypre_ParCSRMatrix *parcsr; 19932cf14000SStefano Zampini HYPRE_Int hnz; 1994c69f721fSFande Kong 1995c69f721fSFande Kong PetscFunctionBegin; 1996c69f721fSFande Kong /* retrieve the internal matrix */ 19979566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 1998c69f721fSFande Kong /* call HYPRE API */ 1999792fecdfSBarry Smith PetscCallExternal(HYPRE_ParCSRMatrixGetRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v); 20002cf14000SStefano Zampini if (nz) *nz = (PetscInt)hnz; 20013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2002c69f721fSFande Kong } 2003c69f721fSFande Kong 2004d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) 2005d71ae5a4SJacob Faibussowitsch { 2006c69f721fSFande Kong hypre_ParCSRMatrix *parcsr; 20072cf14000SStefano Zampini HYPRE_Int hnz; 2008c69f721fSFande Kong 2009c69f721fSFande Kong PetscFunctionBegin; 2010c69f721fSFande Kong /* retrieve the internal matrix */ 20119566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 2012c69f721fSFande Kong /* call HYPRE API */ 20132cf14000SStefano Zampini hnz = nz ? (HYPRE_Int)(*nz) : 0; 2014792fecdfSBarry Smith PetscCallExternal(HYPRE_ParCSRMatrixRestoreRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v); 20153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2016c69f721fSFande Kong } 2017c69f721fSFande Kong 2018d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetValues_HYPRE(Mat A, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2019d71ae5a4SJacob Faibussowitsch { 202045b8d346SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 2021c69f721fSFande Kong PetscInt i; 20221d4906efSStefano Zampini 2023c69f721fSFande Kong PetscFunctionBegin; 20243ba16761SJacob Faibussowitsch if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2025c69f721fSFande Kong /* Ignore negative row indices 2026c69f721fSFande Kong * And negative column indices should be automatically ignored in hypre 2027c69f721fSFande Kong * */ 20282cf14000SStefano Zampini for (i = 0; i < m; i++) { 20292cf14000SStefano Zampini if (idxm[i] >= 0) { 20302cf14000SStefano Zampini HYPRE_Int hn = (HYPRE_Int)n; 2031792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetValues, hA->ij, 1, &hn, (HYPRE_BigInt *)&idxm[i], (HYPRE_BigInt *)idxn, (HYPRE_Complex *)(v + i * n)); 20322cf14000SStefano Zampini } 20332cf14000SStefano Zampini } 20343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2035c69f721fSFande Kong } 2036c69f721fSFande Kong 2037d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_HYPRE(Mat A, MatOption op, PetscBool flg) 2038d71ae5a4SJacob Faibussowitsch { 2039ddbeb582SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 2040ddbeb582SStefano Zampini 2041ddbeb582SStefano Zampini PetscFunctionBegin; 2042c6698e78SStefano Zampini switch (op) { 2043ddbeb582SStefano Zampini case MAT_NO_OFF_PROC_ENTRIES: 204448a46eb9SPierre Jolivet if (flg) PetscCallExternal(HYPRE_IJMatrixSetMaxOffProcElmts, hA->ij, 0); 2045ddbeb582SStefano Zampini break; 2046d71ae5a4SJacob Faibussowitsch case MAT_SORTED_FULL: 2047d71ae5a4SJacob Faibussowitsch hA->sorted_full = flg; 2048d71ae5a4SJacob Faibussowitsch break; 2049d71ae5a4SJacob Faibussowitsch default: 2050d71ae5a4SJacob Faibussowitsch break; 2051ddbeb582SStefano Zampini } 20523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2053ddbeb582SStefano Zampini } 2054c69f721fSFande Kong 2055d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_HYPRE(Mat A, PetscViewer view) 2056d71ae5a4SJacob Faibussowitsch { 205745b8d346SStefano Zampini PetscViewerFormat format; 205845b8d346SStefano Zampini 205945b8d346SStefano Zampini PetscFunctionBegin; 20609566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(view, &format)); 20613ba16761SJacob Faibussowitsch if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(PETSC_SUCCESS); 206245b8d346SStefano Zampini if (format != PETSC_VIEWER_NATIVE) { 20636ea7df73SStefano Zampini Mat B; 20646ea7df73SStefano Zampini hypre_ParCSRMatrix *parcsr; 20656ea7df73SStefano Zampini PetscErrorCode (*mview)(Mat, PetscViewer) = NULL; 20666ea7df73SStefano Zampini 20679566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 20689566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(parcsr, MATAIJ, PETSC_USE_POINTER, &B)); 20699566063dSJacob Faibussowitsch PetscCall(MatGetOperation(B, MATOP_VIEW, (void (**)(void)) & mview)); 207028b400f6SJacob Faibussowitsch PetscCheck(mview, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Missing view operation"); 20719566063dSJacob Faibussowitsch PetscCall((*mview)(B, view)); 20729566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 207345b8d346SStefano Zampini } else { 207445b8d346SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 207545b8d346SStefano Zampini PetscMPIInt size; 207645b8d346SStefano Zampini PetscBool isascii; 207745b8d346SStefano Zampini const char *filename; 207845b8d346SStefano Zampini 207945b8d346SStefano Zampini /* HYPRE uses only text files */ 20809566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERASCII, &isascii)); 208128b400f6SJacob Faibussowitsch PetscCheck(isascii, PetscObjectComm((PetscObject)view), PETSC_ERR_SUP, "PetscViewerType %s: native HYPRE format needs PETSCVIEWERASCII", ((PetscObject)view)->type_name); 20829566063dSJacob Faibussowitsch PetscCall(PetscViewerFileGetName(view, &filename)); 2083792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixPrint, hA->ij, filename); 20849566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(hA->comm, &size)); 208545b8d346SStefano Zampini if (size > 1) { 20869566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(view, "Matrix files: %s.%05d ... %s.%05d\n", filename, 0, filename, size - 1)); 208745b8d346SStefano Zampini } else { 20889566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(view, "Matrix file: %s.%05d\n", filename, 0)); 208945b8d346SStefano Zampini } 209045b8d346SStefano Zampini } 20913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 209245b8d346SStefano Zampini } 209345b8d346SStefano Zampini 2094d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCopy_HYPRE(Mat A, Mat B, MatStructure str) 2095d71ae5a4SJacob Faibussowitsch { 2096465edc17SStefano Zampini hypre_ParCSRMatrix *acsr, *bcsr; 2097465edc17SStefano Zampini 2098465edc17SStefano Zampini PetscFunctionBegin; 2099465edc17SStefano Zampini if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) { 21009566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &acsr)); 21019566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(B, &bcsr)); 2102792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixCopy, acsr, bcsr, 1); 21039566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_SORTED_FULL, PETSC_TRUE)); /* "perfect" preallocation, so no need for hypre_AuxParCSRMatrixNeedAux */ 21049566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 21059566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 2106465edc17SStefano Zampini } else { 21079566063dSJacob Faibussowitsch PetscCall(MatCopy_Basic(A, B, str)); 2108465edc17SStefano Zampini } 21093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2110465edc17SStefano Zampini } 2111465edc17SStefano Zampini 2112d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_HYPRE(Mat A, Vec d) 2113d71ae5a4SJacob Faibussowitsch { 21146305df00SStefano Zampini hypre_ParCSRMatrix *parcsr; 21156305df00SStefano Zampini hypre_CSRMatrix *dmat; 211639accc25SStefano Zampini HYPRE_Complex *a; 211739accc25SStefano Zampini HYPRE_Complex *data = NULL; 21182cf14000SStefano Zampini HYPRE_Int *diag = NULL; 21192cf14000SStefano Zampini PetscInt i; 21206305df00SStefano Zampini PetscBool cong; 21216305df00SStefano Zampini 21226305df00SStefano Zampini PetscFunctionBegin; 21239566063dSJacob Faibussowitsch PetscCall(MatHasCongruentLayouts(A, &cong)); 212428b400f6SJacob Faibussowitsch PetscCheck(cong, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only for square matrices with same local distributions of rows and columns"); 212576bd3646SJed Brown if (PetscDefined(USE_DEBUG)) { 21266305df00SStefano Zampini PetscBool miss; 21279566063dSJacob Faibussowitsch PetscCall(MatMissingDiagonal(A, &miss, NULL)); 212808401ef6SPierre Jolivet PetscCheck(!miss || !A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented when diagonal entries are missing"); 21296305df00SStefano Zampini } 21309566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 21316305df00SStefano Zampini dmat = hypre_ParCSRMatrixDiag(parcsr); 21326305df00SStefano Zampini if (dmat) { 213339accc25SStefano Zampini /* this cast fixes the clang error: implicit conversion from 'HYPRE_Complex' (aka '_Complex double') to 'double' is not permitted in C++ */ 21349566063dSJacob Faibussowitsch PetscCall(VecGetArray(d, (PetscScalar **)&a)); 21352cf14000SStefano Zampini diag = hypre_CSRMatrixI(dmat); 213639accc25SStefano Zampini data = hypre_CSRMatrixData(dmat); 21376305df00SStefano Zampini for (i = 0; i < A->rmap->n; i++) a[i] = data[diag[i]]; 21389566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(d, (PetscScalar **)&a)); 21396305df00SStefano Zampini } 21403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 21416305df00SStefano Zampini } 21426305df00SStefano Zampini 2143363d496dSStefano Zampini #include <petscblaslapack.h> 2144363d496dSStefano Zampini 2145d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAXPY_HYPRE(Mat Y, PetscScalar a, Mat X, MatStructure str) 2146d71ae5a4SJacob Faibussowitsch { 2147363d496dSStefano Zampini PetscFunctionBegin; 21486ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 21496ea7df73SStefano Zampini { 21506ea7df73SStefano Zampini Mat B; 21516ea7df73SStefano Zampini hypre_ParCSRMatrix *x, *y, *z; 21526ea7df73SStefano Zampini 21539566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR(Y, &y)); 21549566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR(X, &x)); 2155792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixAdd, 1.0, y, 1.0, x, &z); 21569566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(z, MATHYPRE, PETSC_OWN_POINTER, &B)); 21579566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(Y, &B)); 21586ea7df73SStefano Zampini } 21596ea7df73SStefano Zampini #else 2160363d496dSStefano Zampini if (str == SAME_NONZERO_PATTERN) { 2161363d496dSStefano Zampini hypre_ParCSRMatrix *x, *y; 2162363d496dSStefano Zampini hypre_CSRMatrix *xloc, *yloc; 2163363d496dSStefano Zampini PetscInt xnnz, ynnz; 216439accc25SStefano Zampini HYPRE_Complex *xarr, *yarr; 2165363d496dSStefano Zampini PetscBLASInt one = 1, bnz; 2166363d496dSStefano Zampini 21679566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR(Y, &y)); 21689566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR(X, &x)); 2169363d496dSStefano Zampini 2170363d496dSStefano Zampini /* diagonal block */ 2171363d496dSStefano Zampini xloc = hypre_ParCSRMatrixDiag(x); 2172363d496dSStefano Zampini yloc = hypre_ParCSRMatrixDiag(y); 2173363d496dSStefano Zampini xnnz = 0; 2174363d496dSStefano Zampini ynnz = 0; 2175363d496dSStefano Zampini xarr = NULL; 2176363d496dSStefano Zampini yarr = NULL; 2177363d496dSStefano Zampini if (xloc) { 217839accc25SStefano Zampini xarr = hypre_CSRMatrixData(xloc); 2179363d496dSStefano Zampini xnnz = hypre_CSRMatrixNumNonzeros(xloc); 2180363d496dSStefano Zampini } 2181363d496dSStefano Zampini if (yloc) { 218239accc25SStefano Zampini yarr = hypre_CSRMatrixData(yloc); 2183363d496dSStefano Zampini ynnz = hypre_CSRMatrixNumNonzeros(yloc); 2184363d496dSStefano Zampini } 218508401ef6SPierre Jolivet PetscCheck(xnnz == ynnz, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Different number of nonzeros in diagonal block %" PetscInt_FMT " != %" PetscInt_FMT, xnnz, ynnz); 21869566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(xnnz, &bnz)); 2187792fecdfSBarry Smith PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one)); 2188363d496dSStefano Zampini 2189363d496dSStefano Zampini /* off-diagonal block */ 2190363d496dSStefano Zampini xloc = hypre_ParCSRMatrixOffd(x); 2191363d496dSStefano Zampini yloc = hypre_ParCSRMatrixOffd(y); 2192363d496dSStefano Zampini xnnz = 0; 2193363d496dSStefano Zampini ynnz = 0; 2194363d496dSStefano Zampini xarr = NULL; 2195363d496dSStefano Zampini yarr = NULL; 2196363d496dSStefano Zampini if (xloc) { 219739accc25SStefano Zampini xarr = hypre_CSRMatrixData(xloc); 2198363d496dSStefano Zampini xnnz = hypre_CSRMatrixNumNonzeros(xloc); 2199363d496dSStefano Zampini } 2200363d496dSStefano Zampini if (yloc) { 220139accc25SStefano Zampini yarr = hypre_CSRMatrixData(yloc); 2202363d496dSStefano Zampini ynnz = hypre_CSRMatrixNumNonzeros(yloc); 2203363d496dSStefano Zampini } 220408401ef6SPierre 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); 22059566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(xnnz, &bnz)); 2206792fecdfSBarry Smith PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one)); 2207363d496dSStefano Zampini } else if (str == SUBSET_NONZERO_PATTERN) { 22089566063dSJacob Faibussowitsch PetscCall(MatAXPY_Basic(Y, a, X, str)); 2209363d496dSStefano Zampini } else { 2210363d496dSStefano Zampini Mat B; 2211363d496dSStefano Zampini 22129566063dSJacob Faibussowitsch PetscCall(MatAXPY_Basic_Preallocate(Y, X, &B)); 22139566063dSJacob Faibussowitsch PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str)); 22149566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(Y, &B)); 2215363d496dSStefano Zampini } 22166ea7df73SStefano Zampini #endif 22173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2218363d496dSStefano Zampini } 2219363d496dSStefano Zampini 22202c4ab24aSJunchao Zhang /* Attach cooMat to hypre matrix mat. The two matrices will share the same data array */ 22212c4ab24aSJunchao Zhang static PetscErrorCode MatAttachCOOMat_HYPRE(Mat mat, Mat cooMat) 22222c4ab24aSJunchao Zhang { 22232c4ab24aSJunchao Zhang Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data; 22242c4ab24aSJunchao Zhang hypre_CSRMatrix *diag, *offd; 22252c4ab24aSJunchao Zhang hypre_ParCSRMatrix *parCSR; 22262c4ab24aSJunchao Zhang HYPRE_MemoryLocation hypreMemtype = HYPRE_MEMORY_HOST; 22272c4ab24aSJunchao Zhang PetscMemType petscMemtype; 22282c4ab24aSJunchao Zhang Mat A, B; 22292c4ab24aSJunchao Zhang PetscScalar *Aa, *Ba; 22302c4ab24aSJunchao Zhang PetscMPIInt size; 22312c4ab24aSJunchao Zhang MPI_Comm comm; 22322c4ab24aSJunchao Zhang PetscLayout rmap; 22332c4ab24aSJunchao Zhang 22342c4ab24aSJunchao Zhang PetscFunctionBegin; 22352c4ab24aSJunchao Zhang PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 22362c4ab24aSJunchao Zhang PetscCallMPI(MPI_Comm_size(comm, &size)); 22372c4ab24aSJunchao Zhang PetscCall(MatGetLayouts(mat, &rmap, NULL)); 22382c4ab24aSJunchao Zhang 22392c4ab24aSJunchao Zhang /* Alias cooMat's data array to IJMatrix's */ 22402c4ab24aSJunchao Zhang PetscCallExternal(HYPRE_IJMatrixGetObject, hmat->ij, (void **)&parCSR); 22412c4ab24aSJunchao Zhang diag = hypre_ParCSRMatrixDiag(parCSR); 22422c4ab24aSJunchao Zhang offd = hypre_ParCSRMatrixOffd(parCSR); 22432c4ab24aSJunchao Zhang 22442c4ab24aSJunchao Zhang hypreMemtype = hypre_CSRMatrixMemoryLocation(diag); 22452c4ab24aSJunchao Zhang A = (size == 1) ? cooMat : ((Mat_MPIAIJ *)cooMat->data)->A; 22462c4ab24aSJunchao Zhang PetscCall(MatSeqAIJGetCSRAndMemType(A, NULL, NULL, &Aa, &petscMemtype)); 22472c4ab24aSJunchao 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"); 22482c4ab24aSJunchao Zhang 22492c4ab24aSJunchao Zhang hmat->diagJ = hypre_CSRMatrixJ(diag); 22502c4ab24aSJunchao Zhang PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(diag), hypreMemtype)); 22512c4ab24aSJunchao Zhang hypre_CSRMatrixData(diag) = (HYPRE_Complex *)Aa; 22522c4ab24aSJunchao Zhang hypre_CSRMatrixOwnsData(diag) = 0; /* Take ownership of (j,a) away from hypre. As a result, we need to free them on our own */ 22532c4ab24aSJunchao Zhang 22542c4ab24aSJunchao Zhang /* Copy diagonal pointers of A to device to facilitate MatSeqAIJMoveDiagonalValuesFront_SeqAIJKokkos */ 22552c4ab24aSJunchao Zhang if (hypreMemtype == HYPRE_MEMORY_DEVICE) { 22562c4ab24aSJunchao Zhang PetscStackCallExternalVoid("hypre_TAlloc", hmat->diag = hypre_TAlloc(PetscInt, rmap->n, hypreMemtype)); 22572c4ab24aSJunchao Zhang PetscCall(MatMarkDiagonal_SeqAIJ(A)); /* We need updated diagonal positions */ 22582c4ab24aSJunchao Zhang PetscStackCallExternalVoid("hypre_TMemcpy", hypre_TMemcpy(hmat->diag, ((Mat_SeqAIJ *)A->data)->diag, PetscInt, rmap->n, hypreMemtype, HYPRE_MEMORY_HOST)); 22592c4ab24aSJunchao Zhang } 22602c4ab24aSJunchao Zhang 22612c4ab24aSJunchao Zhang if (size > 1) { 22622c4ab24aSJunchao Zhang B = ((Mat_MPIAIJ *)cooMat->data)->B; 22632c4ab24aSJunchao Zhang PetscCall(MatSeqAIJGetCSRAndMemType(B, NULL, NULL, &Ba, &petscMemtype)); 22642c4ab24aSJunchao Zhang hmat->offdJ = hypre_CSRMatrixJ(offd); 22652c4ab24aSJunchao Zhang PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(offd), hypreMemtype)); 22662c4ab24aSJunchao Zhang hypre_CSRMatrixData(offd) = (HYPRE_Complex *)Ba; 22672c4ab24aSJunchao Zhang hypre_CSRMatrixOwnsData(offd) = 0; 22682c4ab24aSJunchao Zhang } 22692c4ab24aSJunchao Zhang 22702c4ab24aSJunchao Zhang /* Record cooMat for use in MatSetValuesCOO_HYPRE */ 22712c4ab24aSJunchao Zhang hmat->cooMat = cooMat; 22722c4ab24aSJunchao Zhang hmat->memType = hypreMemtype; 22732c4ab24aSJunchao Zhang PetscFunctionReturn(PETSC_SUCCESS); 22742c4ab24aSJunchao Zhang } 22752c4ab24aSJunchao Zhang 22762c4ab24aSJunchao Zhang static PetscErrorCode MatDuplicate_HYPRE(Mat A, MatDuplicateOption op, Mat *B) 22772c4ab24aSJunchao Zhang { 22782c4ab24aSJunchao Zhang hypre_ParCSRMatrix *parcsr = NULL; 22792c4ab24aSJunchao Zhang PetscCopyMode cpmode; 22802c4ab24aSJunchao Zhang Mat_HYPRE *hA; 22812c4ab24aSJunchao Zhang Mat cooMat; 22822c4ab24aSJunchao Zhang 22832c4ab24aSJunchao Zhang PetscFunctionBegin; 22842c4ab24aSJunchao Zhang PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 22852c4ab24aSJunchao Zhang if (op == MAT_DO_NOT_COPY_VALUES || op == MAT_SHARE_NONZERO_PATTERN) { 22862c4ab24aSJunchao Zhang parcsr = hypre_ParCSRMatrixClone(parcsr, 0); 22872c4ab24aSJunchao Zhang cpmode = PETSC_OWN_POINTER; 22882c4ab24aSJunchao Zhang } else { 22892c4ab24aSJunchao Zhang cpmode = PETSC_COPY_VALUES; 22902c4ab24aSJunchao Zhang } 22912c4ab24aSJunchao Zhang PetscCall(MatCreateFromParCSR(parcsr, MATHYPRE, cpmode, B)); 22922c4ab24aSJunchao Zhang hA = (Mat_HYPRE *)A->data; 22932c4ab24aSJunchao Zhang if (hA->cooMat) { 2294*b73e3080SStefano Zampini op = (op == MAT_DO_NOT_COPY_VALUES) ? op : MAT_COPY_VALUES; 2295*b73e3080SStefano Zampini /* Cannot simply increase the reference count of hA->cooMat, since B needs to share cooMat's data array */ 2296*b73e3080SStefano Zampini PetscCall(MatDuplicate(hA->cooMat, op, &cooMat)); 22972c4ab24aSJunchao Zhang PetscCall(MatAttachCOOMat_HYPRE(*B, cooMat)); 22982c4ab24aSJunchao Zhang } 22992c4ab24aSJunchao Zhang PetscFunctionReturn(PETSC_SUCCESS); 23002c4ab24aSJunchao Zhang } 23012c4ab24aSJunchao Zhang 2302d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetPreallocationCOO_HYPRE(Mat mat, PetscCount coo_n, PetscInt coo_i[], PetscInt coo_j[]) 2303d71ae5a4SJacob Faibussowitsch { 23045fbaff96SJunchao Zhang MPI_Comm comm; 23055fbaff96SJunchao Zhang PetscMPIInt size; 23065fbaff96SJunchao Zhang PetscLayout rmap, cmap; 23075fbaff96SJunchao Zhang Mat_HYPRE *hmat; 23082c4ab24aSJunchao Zhang Mat cooMat; 23095fbaff96SJunchao Zhang MatType matType = MATAIJ; /* default type of cooMat */ 23105fbaff96SJunchao Zhang 23115fbaff96SJunchao Zhang PetscFunctionBegin; 23125fbaff96SJunchao Zhang /* Build an agent matrix cooMat whose type is either MATAIJ or MATAIJKOKKOS. 23135fbaff96SJunchao 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. 23145fbaff96SJunchao Zhang */ 23155fbaff96SJunchao Zhang PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 23165fbaff96SJunchao Zhang PetscCallMPI(MPI_Comm_size(comm, &size)); 23175fbaff96SJunchao Zhang PetscCall(PetscLayoutSetUp(mat->rmap)); 23185fbaff96SJunchao Zhang PetscCall(PetscLayoutSetUp(mat->cmap)); 23195fbaff96SJunchao Zhang PetscCall(MatGetLayouts(mat, &rmap, &cmap)); 23205fbaff96SJunchao Zhang 23215fbaff96SJunchao Zhang #if defined(PETSC_HAVE_DEVICE) 23225fbaff96SJunchao Zhang if (!mat->boundtocpu) { /* mat will be on device, so will cooMat */ 23235fbaff96SJunchao Zhang #if defined(PETSC_HAVE_KOKKOS) 23245fbaff96SJunchao Zhang matType = MATAIJKOKKOS; 23255fbaff96SJunchao Zhang #else 23265fbaff96SJunchao Zhang SETERRQ(comm, PETSC_ERR_SUP, "To support MATHYPRE COO assembly on device, we need Kokkos, e.g., --download-kokkos --download-kokkos-kernels"); 23275fbaff96SJunchao Zhang #endif 23285fbaff96SJunchao Zhang } 23295fbaff96SJunchao Zhang #endif 23305fbaff96SJunchao Zhang 23315fbaff96SJunchao Zhang /* Do COO preallocation through cooMat */ 23325fbaff96SJunchao Zhang hmat = (Mat_HYPRE *)mat->data; 23335fbaff96SJunchao Zhang PetscCall(MatDestroy(&hmat->cooMat)); 23345fbaff96SJunchao Zhang PetscCall(MatCreate(comm, &cooMat)); 23355fbaff96SJunchao Zhang PetscCall(MatSetType(cooMat, matType)); 23365fbaff96SJunchao Zhang PetscCall(MatSetLayouts(cooMat, rmap, cmap)); 23375fbaff96SJunchao Zhang PetscCall(MatSetPreallocationCOO(cooMat, coo_n, coo_i, coo_j)); 2338*b73e3080SStefano Zampini cooMat->assembled = PETSC_TRUE; 23395fbaff96SJunchao Zhang 23405fbaff96SJunchao Zhang /* Copy the sparsity pattern from cooMat to hypre IJMatrix hmat->ij */ 23415fbaff96SJunchao Zhang PetscCall(MatSetOption(mat, MAT_SORTED_FULL, PETSC_TRUE)); 23425fbaff96SJunchao Zhang PetscCall(MatSetOption(mat, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE)); 23435fbaff96SJunchao Zhang PetscCall(MatHYPRE_CreateFromMat(cooMat, hmat)); /* Create hmat->ij and preallocate it */ 2344*b73e3080SStefano Zampini PetscCall(MatHYPRE_IJMatrixCopyIJ(cooMat, hmat->ij)); /* Copy A's (i,j) to hmat->ij */ 23455fbaff96SJunchao Zhang 23465fbaff96SJunchao Zhang mat->preallocated = PETSC_TRUE; 23475fbaff96SJunchao Zhang PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY)); 23485fbaff96SJunchao Zhang PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); /* Migrate mat to device if it is bound to. Hypre builds its own SpMV context here */ 23495fbaff96SJunchao Zhang 23502c4ab24aSJunchao Zhang /* Attach cooMat to mat */ 23512c4ab24aSJunchao Zhang PetscCall(MatAttachCOOMat_HYPRE(mat, cooMat)); 23523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23535fbaff96SJunchao Zhang } 23545fbaff96SJunchao Zhang 2355d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesCOO_HYPRE(Mat mat, const PetscScalar v[], InsertMode imode) 2356d71ae5a4SJacob Faibussowitsch { 23575fbaff96SJunchao Zhang Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data; 2358*b73e3080SStefano Zampini PetscBool ismpiaij; 23595fbaff96SJunchao Zhang Mat A; 23605fbaff96SJunchao Zhang 23615fbaff96SJunchao Zhang PetscFunctionBegin; 2362*b73e3080SStefano Zampini PetscCheck(hmat->cooMat, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet"); 23635fbaff96SJunchao Zhang PetscCall(MatSetValuesCOO(hmat->cooMat, v, imode)); 23645fbaff96SJunchao Zhang 2365*b73e3080SStefano Zampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)hmat->cooMat, MATMPIAIJ, &ismpiaij)); 2366*b73e3080SStefano Zampini 23675fbaff96SJunchao Zhang /* Move diagonal elements of the diagonal block to the front of their row, as needed by ParCSRMatrix. So damn hacky */ 2368*b73e3080SStefano Zampini A = ismpiaij ? ((Mat_MPIAIJ *)hmat->cooMat->data)->A : hmat->cooMat; 23695fbaff96SJunchao Zhang if (hmat->memType == HYPRE_MEMORY_HOST) { 23705fbaff96SJunchao Zhang Mat_SeqAIJ *aij = (Mat_SeqAIJ *)A->data; 23715fbaff96SJunchao Zhang PetscInt i, m, *Ai = aij->i, *Adiag = aij->diag; 23725fbaff96SJunchao Zhang PetscScalar *Aa = aij->a, tmp; 23735fbaff96SJunchao Zhang 23745fbaff96SJunchao Zhang PetscCall(MatGetSize(A, &m, NULL)); 23755fbaff96SJunchao Zhang for (i = 0; i < m; i++) { 2376*b73e3080SStefano Zampini if (Adiag[i] >= Ai[i] && Adiag[i] < Ai[i + 1]) { /* Diagonal element of this row exists in a[] and j[] */ 23775fbaff96SJunchao Zhang tmp = Aa[Ai[i]]; 23785fbaff96SJunchao Zhang Aa[Ai[i]] = Aa[Adiag[i]]; 23795fbaff96SJunchao Zhang Aa[Adiag[i]] = tmp; 23805fbaff96SJunchao Zhang } 23815fbaff96SJunchao Zhang } 23825fbaff96SJunchao Zhang } else { 23835fbaff96SJunchao Zhang #if defined(PETSC_HAVE_KOKKOS_KERNELS) 23845fbaff96SJunchao Zhang PetscCall(MatSeqAIJMoveDiagonalValuesFront_SeqAIJKokkos(A, hmat->diag)); 23855fbaff96SJunchao Zhang #endif 23865fbaff96SJunchao Zhang } 23873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23885fbaff96SJunchao Zhang } 23895fbaff96SJunchao Zhang 2390a055b5aaSBarry Smith /*MC 23912ef1f0ffSBarry Smith MATHYPRE - "hypre" - A matrix type to be used for sequential and parallel sparse matrices 2392a055b5aaSBarry Smith based on the hypre IJ interface. 2393a055b5aaSBarry Smith 2394a055b5aaSBarry Smith Level: intermediate 2395a055b5aaSBarry Smith 23961cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatHYPRESetPreallocation` 2397a055b5aaSBarry Smith M*/ 2398a055b5aaSBarry Smith 2399d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_HYPRE(Mat B) 2400d71ae5a4SJacob Faibussowitsch { 240163c07aadSStefano Zampini Mat_HYPRE *hB; 240263c07aadSStefano Zampini 240363c07aadSStefano Zampini PetscFunctionBegin; 24044dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&hB)); 24056ea7df73SStefano Zampini 2406978814f1SStefano Zampini hB->inner_free = PETSC_TRUE; 2407c69f721fSFande Kong hB->available = PETSC_TRUE; 2408336664bdSPierre Jolivet hB->sorted_full = PETSC_FALSE; /* no assumption whether column indices are sorted or not */ 2409c69f721fSFande Kong hB->size = 0; 2410c69f721fSFande Kong hB->array = NULL; 2411978814f1SStefano Zampini 241263c07aadSStefano Zampini B->data = (void *)hB; 241363c07aadSStefano Zampini B->assembled = PETSC_FALSE; 241463c07aadSStefano Zampini 24159566063dSJacob Faibussowitsch PetscCall(PetscMemzero(B->ops, sizeof(struct _MatOps))); 241663c07aadSStefano Zampini B->ops->mult = MatMult_HYPRE; 241763c07aadSStefano Zampini B->ops->multtranspose = MatMultTranspose_HYPRE; 2418414bd5c3SStefano Zampini B->ops->multadd = MatMultAdd_HYPRE; 2419414bd5c3SStefano Zampini B->ops->multtransposeadd = MatMultTransposeAdd_HYPRE; 242063c07aadSStefano Zampini B->ops->setup = MatSetUp_HYPRE; 242163c07aadSStefano Zampini B->ops->destroy = MatDestroy_HYPRE; 242263c07aadSStefano Zampini B->ops->assemblyend = MatAssemblyEnd_HYPRE; 2423c69f721fSFande Kong B->ops->assemblybegin = MatAssemblyBegin_HYPRE; 2424d975228cSstefano_zampini B->ops->setvalues = MatSetValues_HYPRE; 242568ec7858SStefano Zampini B->ops->missingdiagonal = MatMissingDiagonal_HYPRE; 242668ec7858SStefano Zampini B->ops->scale = MatScale_HYPRE; 242768ec7858SStefano Zampini B->ops->zerorowscolumns = MatZeroRowsColumns_HYPRE; 2428c69f721fSFande Kong B->ops->zeroentries = MatZeroEntries_HYPRE; 2429c69f721fSFande Kong B->ops->zerorows = MatZeroRows_HYPRE; 2430c69f721fSFande Kong B->ops->getrow = MatGetRow_HYPRE; 2431c69f721fSFande Kong B->ops->restorerow = MatRestoreRow_HYPRE; 2432c69f721fSFande Kong B->ops->getvalues = MatGetValues_HYPRE; 2433ddbeb582SStefano Zampini B->ops->setoption = MatSetOption_HYPRE; 243445b8d346SStefano Zampini B->ops->duplicate = MatDuplicate_HYPRE; 2435465edc17SStefano Zampini B->ops->copy = MatCopy_HYPRE; 243645b8d346SStefano Zampini B->ops->view = MatView_HYPRE; 24376305df00SStefano Zampini B->ops->getdiagonal = MatGetDiagonal_HYPRE; 2438363d496dSStefano Zampini B->ops->axpy = MatAXPY_HYPRE; 24394222ddf1SHong Zhang B->ops->productsetfromoptions = MatProductSetFromOptions_HYPRE; 24406ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 24416ea7df73SStefano Zampini B->ops->bindtocpu = MatBindToCPU_HYPRE; 24426ea7df73SStefano Zampini B->boundtocpu = PETSC_FALSE; 24436ea7df73SStefano Zampini #endif 244445b8d346SStefano Zampini 244545b8d346SStefano Zampini /* build cache for off array entries formed */ 24469566063dSJacob Faibussowitsch PetscCall(MatStashCreate_Private(PetscObjectComm((PetscObject)B), 1, &B->stash)); 244763c07aadSStefano Zampini 24489566063dSJacob Faibussowitsch PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)B), &hB->comm)); 24499566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRE)); 24509566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_aij_C", MatConvert_HYPRE_AIJ)); 24519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_is_C", MatConvert_HYPRE_IS)); 24529566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_hypre_C", MatProductSetFromOptions_HYPRE)); 24539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaij_hypre_C", MatProductSetFromOptions_HYPRE)); 24549566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPRESetPreallocation_C", MatHYPRESetPreallocation_HYPRE)); 24559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPREGetParCSR_C", MatHYPREGetParCSR_HYPRE)); 24565fbaff96SJunchao Zhang PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_HYPRE)); 24575fbaff96SJunchao Zhang PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetValuesCOO_C", MatSetValuesCOO_HYPRE)); 24586ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 24596ea7df73SStefano Zampini #if defined(HYPRE_USING_HIP) 24609566063dSJacob Faibussowitsch PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP)); 24619566063dSJacob Faibussowitsch PetscCall(MatSetVecType(B, VECHIP)); 24626ea7df73SStefano Zampini #endif 24636ea7df73SStefano Zampini #if defined(HYPRE_USING_CUDA) 24649566063dSJacob Faibussowitsch PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA)); 24659566063dSJacob Faibussowitsch PetscCall(MatSetVecType(B, VECCUDA)); 24666ea7df73SStefano Zampini #endif 24676ea7df73SStefano Zampini #endif 2468ea9ee2c1SPierre Jolivet PetscHYPREInitialize(); 24693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 247063c07aadSStefano Zampini } 247163c07aadSStefano Zampini 2472d71ae5a4SJacob Faibussowitsch static PetscErrorCode hypre_array_destroy(void *ptr) 2473d71ae5a4SJacob Faibussowitsch { 2474225daaf8SStefano Zampini PetscFunctionBegin; 2475*b73e3080SStefano Zampini if (ptr) hypre_TFree(ptr, HYPRE_MEMORY_HOST); 24763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2477225daaf8SStefano Zampini } 2478