163c07aadSStefano Zampini 263c07aadSStefano Zampini /* 363c07aadSStefano Zampini Creates hypre ijmatrix from PETSc matrix 463c07aadSStefano Zampini */ 5225daaf8SStefano Zampini 6c6698e78SStefano Zampini #include <petscpkg_version.h> 739accc25SStefano Zampini #include <petsc/private/petschypre.h> 8dd9c0a25Sstefano_zampini #include <petscmathypre.h> 963c07aadSStefano Zampini #include <petsc/private/matimpl.h> 10a4af0ceeSJacob Faibussowitsch #include <petsc/private/deviceimpl.h> 1163c07aadSStefano Zampini #include <../src/mat/impls/hypre/mhypre.h> 1263c07aadSStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h> 1358968eb6SStefano Zampini #include <../src/vec/vec/impls/hypre/vhyp.h> 1458968eb6SStefano Zampini #include <HYPRE.h> 15c1a070e6SStefano Zampini #include <HYPRE_utilities.h> 16cd8bc7baSStefano Zampini #include <_hypre_parcsr_ls.h> 1768ec7858SStefano Zampini #include <_hypre_sstruct_ls.h> 1863c07aadSStefano Zampini 190e6427aaSSatish Balay #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0) 200e6427aaSSatish Balay #define hypre_ParCSRMatrixClone(A, B) hypre_ParCSRMatrixCompleteClone(A) 210e6427aaSSatish Balay #endif 220e6427aaSSatish Balay 2363c07aadSStefano Zampini static PetscErrorCode MatHYPRE_CreateFromMat(Mat, Mat_HYPRE *); 2463c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat, Mat, HYPRE_IJMatrix); 25b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_MPIAIJ(Mat, HYPRE_IJMatrix); 26b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_SeqAIJ(Mat, HYPRE_IJMatrix); 2739accc25SStefano Zampini static PetscErrorCode MatHYPRE_MultKernel_Private(Mat, HYPRE_Complex, Vec, HYPRE_Complex, Vec, PetscBool); 286ea7df73SStefano Zampini static PetscErrorCode MatSetValues_HYPRE(Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[], const PetscScalar[], InsertMode ins); 2963c07aadSStefano Zampini 30d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat A_d, Mat A_o, HYPRE_IJMatrix ij) 31d71ae5a4SJacob Faibussowitsch { 3263c07aadSStefano Zampini PetscInt i, n_d, n_o; 3363c07aadSStefano Zampini const PetscInt *ia_d, *ia_o; 3463c07aadSStefano Zampini PetscBool done_d = PETSC_FALSE, done_o = PETSC_FALSE; 352cf14000SStefano Zampini HYPRE_Int *nnz_d = NULL, *nnz_o = NULL; 3663c07aadSStefano Zampini 3763c07aadSStefano Zampini PetscFunctionBegin; 3863c07aadSStefano Zampini if (A_d) { /* determine number of nonzero entries in local diagonal part */ 399566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A_d, 0, PETSC_FALSE, PETSC_FALSE, &n_d, &ia_d, NULL, &done_d)); 4063c07aadSStefano Zampini if (done_d) { 419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_d, &nnz_d)); 42ad540459SPierre Jolivet for (i = 0; i < n_d; i++) nnz_d[i] = ia_d[i + 1] - ia_d[i]; 4363c07aadSStefano Zampini } 449566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A_d, 0, PETSC_FALSE, PETSC_FALSE, NULL, &ia_d, NULL, &done_d)); 4563c07aadSStefano Zampini } 4663c07aadSStefano Zampini if (A_o) { /* determine number of nonzero entries in local off-diagonal part */ 479566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(A_o, 0, PETSC_FALSE, PETSC_FALSE, &n_o, &ia_o, NULL, &done_o)); 4863c07aadSStefano Zampini if (done_o) { 499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_o, &nnz_o)); 50ad540459SPierre Jolivet for (i = 0; i < n_o; i++) nnz_o[i] = ia_o[i + 1] - ia_o[i]; 5163c07aadSStefano Zampini } 529566063dSJacob Faibussowitsch PetscCall(MatRestoreRowIJ(A_o, 0, PETSC_FALSE, PETSC_FALSE, &n_o, &ia_o, NULL, &done_o)); 5363c07aadSStefano Zampini } 5463c07aadSStefano Zampini if (done_d) { /* set number of nonzeros in HYPRE IJ matrix */ 5563c07aadSStefano Zampini if (!done_o) { /* only diagonal part */ 569566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(n_d, &nnz_o)); 5763c07aadSStefano Zampini } 58c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0) 59c6698e78SStefano Zampini { /* If we don't do this, the columns of the matrix will be all zeros! */ 60c6698e78SStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 61c6698e78SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij); 62c6698e78SStefano Zampini hypre_AuxParCSRMatrixDestroy(aux_matrix); 63c6698e78SStefano Zampini hypre_IJMatrixTranslator(ij) = NULL; 64792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, ij, nnz_d, nnz_o); 6522235d61SPierre Jolivet /* it seems they partially fixed it in 2.19.0 */ 6622235d61SPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 67c6698e78SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij); 68c6698e78SStefano Zampini hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1; 6922235d61SPierre Jolivet #endif 70c6698e78SStefano Zampini } 71c6698e78SStefano Zampini #else 72792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, ij, nnz_d, nnz_o); 73c6698e78SStefano Zampini #endif 749566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz_d)); 759566063dSJacob Faibussowitsch PetscCall(PetscFree(nnz_o)); 7663c07aadSStefano Zampini } 773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7863c07aadSStefano Zampini } 7963c07aadSStefano Zampini 80d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_CreateFromMat(Mat A, Mat_HYPRE *hA) 81d71ae5a4SJacob Faibussowitsch { 8263c07aadSStefano Zampini PetscInt rstart, rend, cstart, cend; 8363c07aadSStefano Zampini 8463c07aadSStefano Zampini PetscFunctionBegin; 859566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 869566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 8763c07aadSStefano Zampini rstart = A->rmap->rstart; 8863c07aadSStefano Zampini rend = A->rmap->rend; 8963c07aadSStefano Zampini cstart = A->cmap->rstart; 9063c07aadSStefano Zampini cend = A->cmap->rend; 91ea9ee2c1SPierre Jolivet PetscHYPREInitialize(); 92651b1cf9SStefano Zampini if (hA->ij) { 93651b1cf9SStefano Zampini if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL; 94651b1cf9SStefano Zampini PetscCallExternal(HYPRE_IJMatrixDestroy, hA->ij); 95651b1cf9SStefano Zampini } 96792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rstart, rend - 1, cstart, cend - 1, &hA->ij); 97792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR); 9863c07aadSStefano Zampini { 9963c07aadSStefano Zampini PetscBool same; 10063c07aadSStefano Zampini Mat A_d, A_o; 10163c07aadSStefano Zampini const PetscInt *colmap; 1029566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &same)); 10363c07aadSStefano Zampini if (same) { 1049566063dSJacob Faibussowitsch PetscCall(MatMPIAIJGetSeqAIJ(A, &A_d, &A_o, &colmap)); 1059566063dSJacob Faibussowitsch PetscCall(MatHYPRE_IJMatrixPreallocate(A_d, A_o, hA->ij)); 1063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10763c07aadSStefano Zampini } 1089566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIBAIJ, &same)); 10963c07aadSStefano Zampini if (same) { 1109566063dSJacob Faibussowitsch PetscCall(MatMPIBAIJGetSeqBAIJ(A, &A_d, &A_o, &colmap)); 1119566063dSJacob Faibussowitsch PetscCall(MatHYPRE_IJMatrixPreallocate(A_d, A_o, hA->ij)); 1123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11363c07aadSStefano Zampini } 1149566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &same)); 11563c07aadSStefano Zampini if (same) { 1169566063dSJacob Faibussowitsch PetscCall(MatHYPRE_IJMatrixPreallocate(A, NULL, hA->ij)); 1173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11863c07aadSStefano Zampini } 1199566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQBAIJ, &same)); 12063c07aadSStefano Zampini if (same) { 1219566063dSJacob Faibussowitsch PetscCall(MatHYPRE_IJMatrixPreallocate(A, NULL, hA->ij)); 1223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12363c07aadSStefano Zampini } 12463c07aadSStefano Zampini } 1253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12663c07aadSStefano Zampini } 12763c07aadSStefano Zampini 128b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ(Mat A, HYPRE_IJMatrix ij) 129d71ae5a4SJacob Faibussowitsch { 13063c07aadSStefano Zampini PetscBool flg; 13163c07aadSStefano Zampini 13263c07aadSStefano Zampini PetscFunctionBegin; 1336ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 134792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize, ij); 1356ea7df73SStefano Zampini #else 136792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize_v2, ij, HYPRE_MEMORY_HOST); 1376ea7df73SStefano Zampini #endif 1389566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &flg)); 139b73e3080SStefano Zampini if (flg) { 140b73e3080SStefano Zampini PetscCall(MatHYPRE_IJMatrixCopyIJ_MPIAIJ(A, ij)); 1413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14263c07aadSStefano Zampini } 1439566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &flg)); 14463c07aadSStefano Zampini if (flg) { 145b73e3080SStefano Zampini PetscCall(MatHYPRE_IJMatrixCopyIJ_SeqAIJ(A, ij)); 1463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14763c07aadSStefano Zampini } 148b73e3080SStefano Zampini PetscCheck(PETSC_FALSE, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "No support for matrix type %s", ((PetscObject)A)->type_name); 14963c07aadSStefano Zampini } 15063c07aadSStefano Zampini 151b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_SeqAIJ(Mat A, HYPRE_IJMatrix ij) 152d71ae5a4SJacob Faibussowitsch { 15363c07aadSStefano Zampini Mat_SeqAIJ *pdiag = (Mat_SeqAIJ *)A->data; 15458968eb6SStefano Zampini HYPRE_Int type; 15563c07aadSStefano Zampini hypre_ParCSRMatrix *par_matrix; 15663c07aadSStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 15763c07aadSStefano Zampini hypre_CSRMatrix *hdiag; 1582cf14000SStefano Zampini PetscBool sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int)); 15963c07aadSStefano Zampini 16063c07aadSStefano Zampini PetscFunctionBegin; 161792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type); 16208401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 163792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix); 16463c07aadSStefano Zampini hdiag = hypre_ParCSRMatrixDiag(par_matrix); 16563c07aadSStefano Zampini /* 16663c07aadSStefano Zampini this is the Hack part where we monkey directly with the hypre datastructures 16763c07aadSStefano Zampini */ 1682cf14000SStefano Zampini if (sameint) { 1699566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hdiag->i, pdiag->i, A->rmap->n + 1)); 1709566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hdiag->j, pdiag->j, pdiag->nz)); 1712cf14000SStefano Zampini } else { 1722cf14000SStefano Zampini PetscInt i; 1732cf14000SStefano Zampini 1742cf14000SStefano Zampini for (i = 0; i < A->rmap->n + 1; i++) hdiag->i[i] = (HYPRE_Int)pdiag->i[i]; 1752cf14000SStefano Zampini for (i = 0; i < pdiag->nz; i++) hdiag->j[i] = (HYPRE_Int)pdiag->j[i]; 1762cf14000SStefano Zampini } 1776ea7df73SStefano Zampini 178ea9daf28SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij); 17963c07aadSStefano Zampini hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0; 1803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18163c07aadSStefano Zampini } 18263c07aadSStefano Zampini 183b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_MPIAIJ(Mat A, HYPRE_IJMatrix ij) 184d71ae5a4SJacob Faibussowitsch { 18563c07aadSStefano Zampini Mat_MPIAIJ *pA = (Mat_MPIAIJ *)A->data; 18663c07aadSStefano Zampini Mat_SeqAIJ *pdiag, *poffd; 18763c07aadSStefano Zampini PetscInt i, *garray = pA->garray, *jj, cstart, *pjj; 1882cf14000SStefano Zampini HYPRE_Int *hjj, type; 18963c07aadSStefano Zampini hypre_ParCSRMatrix *par_matrix; 19063c07aadSStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 19163c07aadSStefano Zampini hypre_CSRMatrix *hdiag, *hoffd; 1922cf14000SStefano Zampini PetscBool sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int)); 19363c07aadSStefano Zampini 19463c07aadSStefano Zampini PetscFunctionBegin; 19563c07aadSStefano Zampini pdiag = (Mat_SeqAIJ *)pA->A->data; 19663c07aadSStefano Zampini poffd = (Mat_SeqAIJ *)pA->B->data; 197da81f932SPierre Jolivet /* cstart is only valid for square MPIAIJ laid out in the usual way */ 1989566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &cstart, NULL)); 19963c07aadSStefano Zampini 200792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type); 20108401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 202792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix); 20363c07aadSStefano Zampini hdiag = hypre_ParCSRMatrixDiag(par_matrix); 20463c07aadSStefano Zampini hoffd = hypre_ParCSRMatrixOffd(par_matrix); 20563c07aadSStefano Zampini 2062cf14000SStefano Zampini if (sameint) { 2079566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hdiag->i, pdiag->i, pA->A->rmap->n + 1)); 2082cf14000SStefano Zampini } else { 2092cf14000SStefano Zampini for (i = 0; i < pA->A->rmap->n + 1; i++) hdiag->i[i] = (HYPRE_Int)(pdiag->i[i]); 2102cf14000SStefano Zampini } 211b73e3080SStefano Zampini 2122cf14000SStefano Zampini hjj = hdiag->j; 2132cf14000SStefano Zampini pjj = pdiag->j; 214c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0) 2152cf14000SStefano Zampini for (i = 0; i < pdiag->nz; i++) hjj[i] = pjj[i]; 216c6698e78SStefano Zampini #else 2172cf14000SStefano Zampini for (i = 0; i < pdiag->nz; i++) hjj[i] = cstart + pjj[i]; 218c6698e78SStefano Zampini #endif 2192cf14000SStefano Zampini if (sameint) { 2209566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hoffd->i, poffd->i, pA->A->rmap->n + 1)); 2212cf14000SStefano Zampini } else { 2222cf14000SStefano Zampini for (i = 0; i < pA->A->rmap->n + 1; i++) hoffd->i[i] = (HYPRE_Int)(poffd->i[i]); 2232cf14000SStefano Zampini } 2242cf14000SStefano Zampini 225*06977982Sstefanozampini jj = (PetscInt *)hoffd->j; 226c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0) 227792fecdfSBarry Smith PetscCallExternal(hypre_CSRMatrixBigInitialize, hoffd); 228c6698e78SStefano Zampini jj = (PetscInt *)hoffd->big_j; 229c6698e78SStefano Zampini #endif 2302cf14000SStefano Zampini pjj = poffd->j; 23163c07aadSStefano Zampini for (i = 0; i < poffd->nz; i++) jj[i] = garray[pjj[i]]; 232c6698e78SStefano Zampini 233ea9daf28SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij); 23463c07aadSStefano Zampini hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0; 2353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23663c07aadSStefano Zampini } 23763c07aadSStefano Zampini 238d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_HYPRE_IS(Mat A, MatType mtype, MatReuse reuse, Mat *B) 239d71ae5a4SJacob Faibussowitsch { 2402df22349SStefano Zampini Mat_HYPRE *mhA = (Mat_HYPRE *)(A->data); 2412df22349SStefano Zampini Mat lA; 2422df22349SStefano Zampini ISLocalToGlobalMapping rl2g, cl2g; 2432df22349SStefano Zampini IS is; 2442df22349SStefano Zampini hypre_ParCSRMatrix *hA; 2452df22349SStefano Zampini hypre_CSRMatrix *hdiag, *hoffd; 2462df22349SStefano Zampini MPI_Comm comm; 24739accc25SStefano Zampini HYPRE_Complex *hdd, *hod, *aa; 24839accc25SStefano Zampini PetscScalar *data; 2492cf14000SStefano Zampini HYPRE_BigInt *col_map_offd; 2502cf14000SStefano Zampini HYPRE_Int *hdi, *hdj, *hoi, *hoj; 2512df22349SStefano Zampini PetscInt *ii, *jj, *iptr, *jptr; 2522df22349SStefano Zampini PetscInt cum, dr, dc, oc, str, stc, nnz, i, jd, jo, M, N; 25358968eb6SStefano Zampini HYPRE_Int type; 254*06977982Sstefanozampini MatType lmattype = NULL; 255*06977982Sstefanozampini PetscBool freeparcsr = PETSC_FALSE; 2562df22349SStefano Zampini 2572df22349SStefano Zampini PetscFunctionBegin; 258a1787963SStefano Zampini comm = PetscObjectComm((PetscObject)A); 259792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, mhA->ij, &type); 26008401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 261792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, mhA->ij, (void **)&hA); 262*06977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 263*06977982Sstefanozampini if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(mhA->ij)) { 264*06977982Sstefanozampini /* Support by copying back on the host and copy to GPU 265*06977982Sstefanozampini Kind of inefficient, but this is the best we can do now */ 266*06977982Sstefanozampini #if defined(HYPRE_USING_HIP) 267*06977982Sstefanozampini lmattype = MATSEQAIJHIPSPARSE; 268*06977982Sstefanozampini #elif defined(HYPRE_USING_CUDA) 269*06977982Sstefanozampini lmattype = MATSEQAIJCUSPARSE; 270*06977982Sstefanozampini #endif 271*06977982Sstefanozampini hA = hypre_ParCSRMatrixClone_v2(hA, 1, HYPRE_MEMORY_HOST); 272*06977982Sstefanozampini freeparcsr = PETSC_TRUE; 273*06977982Sstefanozampini } 274*06977982Sstefanozampini #endif 2752df22349SStefano Zampini M = hypre_ParCSRMatrixGlobalNumRows(hA); 2762df22349SStefano Zampini N = hypre_ParCSRMatrixGlobalNumCols(hA); 2772df22349SStefano Zampini str = hypre_ParCSRMatrixFirstRowIndex(hA); 2782df22349SStefano Zampini stc = hypre_ParCSRMatrixFirstColDiag(hA); 2792df22349SStefano Zampini hdiag = hypre_ParCSRMatrixDiag(hA); 2802df22349SStefano Zampini hoffd = hypre_ParCSRMatrixOffd(hA); 2812df22349SStefano Zampini dr = hypre_CSRMatrixNumRows(hdiag); 2822df22349SStefano Zampini dc = hypre_CSRMatrixNumCols(hdiag); 2832df22349SStefano Zampini nnz = hypre_CSRMatrixNumNonzeros(hdiag); 2842df22349SStefano Zampini hdi = hypre_CSRMatrixI(hdiag); 2852df22349SStefano Zampini hdj = hypre_CSRMatrixJ(hdiag); 2862df22349SStefano Zampini hdd = hypre_CSRMatrixData(hdiag); 2872df22349SStefano Zampini oc = hypre_CSRMatrixNumCols(hoffd); 2882df22349SStefano Zampini nnz += hypre_CSRMatrixNumNonzeros(hoffd); 2892df22349SStefano Zampini hoi = hypre_CSRMatrixI(hoffd); 2902df22349SStefano Zampini hoj = hypre_CSRMatrixJ(hoffd); 2912df22349SStefano Zampini hod = hypre_CSRMatrixData(hoffd); 2922df22349SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 2932df22349SStefano Zampini PetscInt *aux; 2942df22349SStefano Zampini 2952df22349SStefano Zampini /* generate l2g maps for rows and cols */ 2969566063dSJacob Faibussowitsch PetscCall(ISCreateStride(comm, dr, str, 1, &is)); 2979566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g)); 2989566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 2992df22349SStefano Zampini col_map_offd = hypre_ParCSRMatrixColMapOffd(hA); 3009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dc + oc, &aux)); 3012df22349SStefano Zampini for (i = 0; i < dc; i++) aux[i] = i + stc; 3022df22349SStefano Zampini for (i = 0; i < oc; i++) aux[i + dc] = col_map_offd[i]; 3039566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(comm, dc + oc, aux, PETSC_OWN_POINTER, &is)); 3049566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g)); 3059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 3062df22349SStefano Zampini /* create MATIS object */ 3079566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, B)); 3089566063dSJacob Faibussowitsch PetscCall(MatSetSizes(*B, dr, dc, M, N)); 3099566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, MATIS)); 3109566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*B, rl2g, cl2g)); 3119566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&rl2g)); 3129566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingDestroy(&cl2g)); 3132df22349SStefano Zampini 3142df22349SStefano Zampini /* allocate CSR for local matrix */ 3159566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(dr + 1, &iptr)); 3169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &jptr)); 3179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nnz, &data)); 3182df22349SStefano Zampini } else { 3192df22349SStefano Zampini PetscInt nr; 3202df22349SStefano Zampini PetscBool done; 3219566063dSJacob Faibussowitsch PetscCall(MatISGetLocalMat(*B, &lA)); 3229566063dSJacob Faibussowitsch PetscCall(MatGetRowIJ(lA, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&iptr, (const PetscInt **)&jptr, &done)); 32308401ef6SPierre Jolivet PetscCheck(nr == dr, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of rows in local mat! %" PetscInt_FMT " != %" PetscInt_FMT, nr, dr); 32408401ef6SPierre Jolivet PetscCheck(iptr[nr] >= nnz, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of nonzeros in local mat! reuse %" PetscInt_FMT " requested %" PetscInt_FMT, iptr[nr], nnz); 325*06977982Sstefanozampini PetscCall(MatSeqAIJGetArrayWrite(lA, &data)); 3262df22349SStefano Zampini } 3272df22349SStefano Zampini /* merge local matrices */ 3282df22349SStefano Zampini ii = iptr; 3292df22349SStefano Zampini jj = jptr; 33039accc25SStefano Zampini aa = (HYPRE_Complex *)data; /* this cast fixes the clang error when doing the assignments below: implicit conversion from 'HYPRE_Complex' (aka '_Complex double') to 'double' is not permitted in C++ */ 3312df22349SStefano Zampini *ii = *(hdi++) + *(hoi++); 3322df22349SStefano Zampini for (jd = 0, jo = 0, cum = 0; *ii < nnz; cum++) { 33339accc25SStefano Zampini PetscScalar *aold = (PetscScalar *)aa; 3342df22349SStefano Zampini PetscInt *jold = jj, nc = jd + jo; 3359371c9d4SSatish Balay for (; jd < *hdi; jd++) { 3369371c9d4SSatish Balay *jj++ = *hdj++; 3379371c9d4SSatish Balay *aa++ = *hdd++; 3389371c9d4SSatish Balay } 3399371c9d4SSatish Balay for (; jo < *hoi; jo++) { 3409371c9d4SSatish Balay *jj++ = *hoj++ + dc; 3419371c9d4SSatish Balay *aa++ = *hod++; 3429371c9d4SSatish Balay } 3432df22349SStefano Zampini *(++ii) = *(hdi++) + *(hoi++); 3449566063dSJacob Faibussowitsch PetscCall(PetscSortIntWithScalarArray(jd + jo - nc, jold, aold)); 3452df22349SStefano Zampini } 3462df22349SStefano Zampini for (; cum < dr; cum++) *(++ii) = nnz; 3472df22349SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 348a033916dSStefano Zampini Mat_SeqAIJ *a; 349a033916dSStefano Zampini 3509566063dSJacob Faibussowitsch PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, dr, dc + oc, iptr, jptr, data, &lA)); 351a033916dSStefano Zampini /* hack SeqAIJ */ 352a033916dSStefano Zampini a = (Mat_SeqAIJ *)(lA->data); 353a033916dSStefano Zampini a->free_a = PETSC_TRUE; 354a033916dSStefano Zampini a->free_ij = PETSC_TRUE; 355*06977982Sstefanozampini if (lmattype) PetscCall(MatConvert(lA, lmattype, MAT_INPLACE_MATRIX, &lA)); 356*06977982Sstefanozampini PetscCall(MatISSetLocalMat(*B, lA)); 3579566063dSJacob Faibussowitsch PetscCall(MatDestroy(&lA)); 358*06977982Sstefanozampini } else { 359*06977982Sstefanozampini PetscCall(MatSeqAIJRestoreArrayWrite(lA, &data)); 3602df22349SStefano Zampini } 3619566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY)); 3629566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY)); 36348a46eb9SPierre Jolivet if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, B)); 364*06977982Sstefanozampini if (freeparcsr) PetscCallExternal(hypre_ParCSRMatrixDestroy, hA); 3653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3662df22349SStefano Zampini } 3672df22349SStefano Zampini 368*06977982Sstefanozampini static PetscErrorCode MatHYPRE_DestroyCOOMat(Mat mat) 369d71ae5a4SJacob Faibussowitsch { 370*06977982Sstefanozampini Mat_HYPRE *hA = (Mat_HYPRE *)mat->data; 37163c07aadSStefano Zampini 37263c07aadSStefano Zampini PetscFunctionBegin; 373*06977982Sstefanozampini if (hA->cooMat) { /* If cooMat is present we need to destroy the column indices */ 374*06977982Sstefanozampini PetscCall(MatDestroy(&hA->cooMat)); 375*06977982Sstefanozampini if (hA->cooMatAttached) { 376*06977982Sstefanozampini hypre_CSRMatrix *csr; 377*06977982Sstefanozampini hypre_ParCSRMatrix *parcsr; 378*06977982Sstefanozampini HYPRE_MemoryLocation mem; 379*06977982Sstefanozampini 380*06977982Sstefanozampini PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr); 381*06977982Sstefanozampini csr = hypre_ParCSRMatrixDiag(parcsr); 382*06977982Sstefanozampini if (csr) { 383*06977982Sstefanozampini mem = hypre_CSRMatrixMemoryLocation(csr); 384*06977982Sstefanozampini PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixJ(csr), mem)); 385*06977982Sstefanozampini PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixBigJ(csr), mem)); 386b73e3080SStefano Zampini } 387*06977982Sstefanozampini csr = hypre_ParCSRMatrixOffd(parcsr); 388*06977982Sstefanozampini if (csr) { 389*06977982Sstefanozampini mem = hypre_CSRMatrixMemoryLocation(csr); 390*06977982Sstefanozampini PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixJ(csr), mem)); 391*06977982Sstefanozampini PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixBigJ(csr), mem)); 392b73e3080SStefano Zampini } 393b73e3080SStefano Zampini } 394*06977982Sstefanozampini } 395*06977982Sstefanozampini hA->cooMatAttached = PETSC_FALSE; 396b73e3080SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 397b73e3080SStefano Zampini } 398b73e3080SStefano Zampini 399*06977982Sstefanozampini static PetscErrorCode MatHYPRE_CreateCOOMat(Mat mat) 400b73e3080SStefano Zampini { 401*06977982Sstefanozampini MPI_Comm comm; 402*06977982Sstefanozampini PetscMPIInt size; 403*06977982Sstefanozampini PetscLayout rmap, cmap; 404*06977982Sstefanozampini Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data; 405*06977982Sstefanozampini MatType matType = MATAIJ; /* default type of cooMat */ 406b73e3080SStefano Zampini 407b73e3080SStefano Zampini PetscFunctionBegin; 408*06977982Sstefanozampini /* Build an agent matrix cooMat with AIJ format 409*06977982Sstefanozampini It has the same sparsity pattern as mat, and also shares the data array with mat. We use cooMat to do the COO work. 410*06977982Sstefanozampini */ 411*06977982Sstefanozampini PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 412*06977982Sstefanozampini PetscCallMPI(MPI_Comm_size(comm, &size)); 413*06977982Sstefanozampini PetscCall(PetscLayoutSetUp(mat->rmap)); 414*06977982Sstefanozampini PetscCall(PetscLayoutSetUp(mat->cmap)); 415*06977982Sstefanozampini PetscCall(MatGetLayouts(mat, &rmap, &cmap)); 416b73e3080SStefano Zampini 417*06977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 418*06977982Sstefanozampini if (!mat->boundtocpu) { /* mat will be on device, so will cooMat */ 419*06977982Sstefanozampini #if defined(HYPRE_USING_HIP) 420*06977982Sstefanozampini matType = MATAIJHIPSPARSE; 421*06977982Sstefanozampini #elif defined(HYPRE_USING_CUDA) 422*06977982Sstefanozampini matType = MATAIJCUSPARSE; 423*06977982Sstefanozampini #else 424*06977982Sstefanozampini SETERRQ(comm, PETSC_ERR_SUP, "Do not know the HYPRE device"); 425*06977982Sstefanozampini #endif 426b73e3080SStefano Zampini } 427*06977982Sstefanozampini #endif 428*06977982Sstefanozampini 429*06977982Sstefanozampini /* Do COO preallocation through cooMat */ 430*06977982Sstefanozampini PetscCall(MatHYPRE_DestroyCOOMat(mat)); 431*06977982Sstefanozampini PetscCall(MatCreate(comm, &hmat->cooMat)); 432*06977982Sstefanozampini PetscCall(MatSetType(hmat->cooMat, matType)); 433*06977982Sstefanozampini PetscCall(MatSetLayouts(hmat->cooMat, rmap, cmap)); 434*06977982Sstefanozampini 435*06977982Sstefanozampini /* allocate local matrices if needed */ 436*06977982Sstefanozampini PetscCall(MatMPIAIJSetPreallocation(hmat->cooMat, 0, NULL, 0, NULL)); 437*06977982Sstefanozampini PetscFunctionReturn(PETSC_SUCCESS); 438*06977982Sstefanozampini } 439*06977982Sstefanozampini 440*06977982Sstefanozampini /* Attach cooMat data array to hypre matrix. 441*06977982Sstefanozampini When AIJCUPMSPARSE will support raw device pointers and not THRUSTARRAY 442*06977982Sstefanozampini we should swap the arrays: i.e., attach hypre matrix array to cooMat 443*06977982Sstefanozampini This is because hypre should be in charge of handling the memory, 444*06977982Sstefanozampini cooMat is only a way to reuse PETSc COO code. 445*06977982Sstefanozampini attaching the memory will then be done at MatSetValuesCOO time and it will dynamically 446*06977982Sstefanozampini support hypre matrix migrating to host. 447*06977982Sstefanozampini */ 448*06977982Sstefanozampini static PetscErrorCode MatHYPRE_AttachCOOMat(Mat mat) 449*06977982Sstefanozampini { 450*06977982Sstefanozampini Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data; 451*06977982Sstefanozampini hypre_CSRMatrix *diag, *offd; 452*06977982Sstefanozampini hypre_ParCSRMatrix *parCSR; 453*06977982Sstefanozampini HYPRE_MemoryLocation hmem = HYPRE_MEMORY_HOST; 454*06977982Sstefanozampini PetscMemType pmem; 455*06977982Sstefanozampini Mat A, B; 456*06977982Sstefanozampini PetscScalar *a; 457*06977982Sstefanozampini PetscMPIInt size; 458*06977982Sstefanozampini MPI_Comm comm; 459*06977982Sstefanozampini 460*06977982Sstefanozampini PetscFunctionBegin; 461*06977982Sstefanozampini PetscCheck(hmat->cooMat, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet"); 462*06977982Sstefanozampini if (hmat->cooMatAttached) PetscFunctionReturn(PETSC_SUCCESS); 463*06977982Sstefanozampini PetscCheck(hmat->cooMat->preallocated, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix is not preallocated"); 464*06977982Sstefanozampini PetscCall(PetscObjectSetName((PetscObject)hmat->cooMat, "_internal_COO_mat_for_hypre")); 465*06977982Sstefanozampini PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 466*06977982Sstefanozampini PetscCallMPI(MPI_Comm_size(comm, &size)); 467*06977982Sstefanozampini 468*06977982Sstefanozampini /* Alias cooMat's data array to IJMatrix's */ 469*06977982Sstefanozampini PetscCallExternal(HYPRE_IJMatrixGetObject, hmat->ij, (void **)&parCSR); 470*06977982Sstefanozampini diag = hypre_ParCSRMatrixDiag(parCSR); 471*06977982Sstefanozampini offd = hypre_ParCSRMatrixOffd(parCSR); 472*06977982Sstefanozampini 473*06977982Sstefanozampini A = (size == 1) ? hmat->cooMat : ((Mat_MPIAIJ *)hmat->cooMat->data)->A; 474*06977982Sstefanozampini B = (size == 1) ? NULL : ((Mat_MPIAIJ *)hmat->cooMat->data)->B; 475*06977982Sstefanozampini 476*06977982Sstefanozampini PetscCall(PetscObjectSetName((PetscObject)A, "_internal_COO_mat_for_hypre")); 477*06977982Sstefanozampini hmem = hypre_CSRMatrixMemoryLocation(diag); 478*06977982Sstefanozampini PetscCall(MatSeqAIJGetCSRAndMemType(A, NULL, NULL, &a, &pmem)); 479*06977982Sstefanozampini PetscAssert((PetscMemTypeHost(pmem) && hmem == HYPRE_MEMORY_HOST) || (PetscMemTypeDevice(pmem) && hmem == HYPRE_MEMORY_DEVICE), comm, PETSC_ERR_PLIB, "PETSc and hypre's memory types mismatch"); 480*06977982Sstefanozampini PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(diag), hmem)); 481*06977982Sstefanozampini hypre_CSRMatrixData(diag) = (HYPRE_Complex *)a; 482*06977982Sstefanozampini hypre_CSRMatrixOwnsData(diag) = 0; /* Take ownership of (j,a) away from hypre. As a result, we need to free them on our own */ 483*06977982Sstefanozampini 484*06977982Sstefanozampini if (B) { 485*06977982Sstefanozampini hmem = hypre_CSRMatrixMemoryLocation(offd); 486*06977982Sstefanozampini PetscCall(MatSeqAIJGetCSRAndMemType(B, NULL, NULL, &a, &pmem)); 487*06977982Sstefanozampini PetscAssert((PetscMemTypeHost(pmem) && hmem == HYPRE_MEMORY_HOST) || (PetscMemTypeDevice(pmem) && hmem == HYPRE_MEMORY_DEVICE), comm, PETSC_ERR_PLIB, "PETSc and hypre's memory types mismatch"); 488*06977982Sstefanozampini PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(offd), hmem)); 489*06977982Sstefanozampini hypre_CSRMatrixData(offd) = (HYPRE_Complex *)a; 490*06977982Sstefanozampini hypre_CSRMatrixOwnsData(offd) = 0; 491*06977982Sstefanozampini } 492*06977982Sstefanozampini hmat->cooMatAttached = PETSC_TRUE; 493*06977982Sstefanozampini PetscFunctionReturn(PETSC_SUCCESS); 494*06977982Sstefanozampini } 495*06977982Sstefanozampini 496*06977982Sstefanozampini static PetscErrorCode CSRtoCOO_Private(PetscInt n, const PetscInt ii[], const PetscInt jj[], PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j) 497*06977982Sstefanozampini { 498*06977982Sstefanozampini PetscInt *cooi, *cooj; 499*06977982Sstefanozampini 500*06977982Sstefanozampini PetscFunctionBegin; 501*06977982Sstefanozampini *ncoo = ii[n]; 502*06977982Sstefanozampini PetscCall(PetscMalloc2(*ncoo, &cooi, *ncoo, &cooj)); 503*06977982Sstefanozampini for (PetscInt i = 0; i < n; i++) { 504*06977982Sstefanozampini for (PetscInt j = ii[i]; j < ii[i + 1]; j++) cooi[j] = i; 505*06977982Sstefanozampini } 506*06977982Sstefanozampini PetscCall(PetscArraycpy(cooj, jj, *ncoo)); 507*06977982Sstefanozampini *coo_i = cooi; 508*06977982Sstefanozampini *coo_j = cooj; 509*06977982Sstefanozampini PetscFunctionReturn(PETSC_SUCCESS); 510*06977982Sstefanozampini } 511*06977982Sstefanozampini 512*06977982Sstefanozampini static PetscErrorCode CSRtoCOO_HYPRE_Int_Private(PetscInt n, const HYPRE_Int ii[], const HYPRE_Int jj[], PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j) 513*06977982Sstefanozampini { 514*06977982Sstefanozampini PetscInt *cooi, *cooj; 515*06977982Sstefanozampini 516*06977982Sstefanozampini PetscFunctionBegin; 517*06977982Sstefanozampini *ncoo = ii[n]; 518*06977982Sstefanozampini PetscCall(PetscMalloc2(*ncoo, &cooi, *ncoo, &cooj)); 519*06977982Sstefanozampini for (PetscInt i = 0; i < n; i++) { 520*06977982Sstefanozampini for (HYPRE_Int j = ii[i]; j < ii[i + 1]; j++) cooi[j] = i; 521*06977982Sstefanozampini } 522*06977982Sstefanozampini for (PetscCount i = 0; i < *ncoo; i++) cooj[i] = jj[i]; 523*06977982Sstefanozampini *coo_i = cooi; 524*06977982Sstefanozampini *coo_j = cooj; 525*06977982Sstefanozampini PetscFunctionReturn(PETSC_SUCCESS); 526*06977982Sstefanozampini } 527*06977982Sstefanozampini 528*06977982Sstefanozampini static PetscErrorCode MatSeqAIJGetCOO_Private(Mat A, PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j) 529*06977982Sstefanozampini { 530*06977982Sstefanozampini PetscInt n; 531*06977982Sstefanozampini const PetscInt *ii, *jj; 532*06977982Sstefanozampini PetscBool done; 533*06977982Sstefanozampini 534*06977982Sstefanozampini PetscFunctionBegin; 535*06977982Sstefanozampini PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &done)); 536*06977982Sstefanozampini PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Failure for MatGetRowIJ"); 537*06977982Sstefanozampini PetscCall(CSRtoCOO_Private(n, ii, jj, ncoo, coo_i, coo_j)); 538*06977982Sstefanozampini PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &done)); 539*06977982Sstefanozampini PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Failure for MatRestoreRowIJ"); 540*06977982Sstefanozampini PetscFunctionReturn(PETSC_SUCCESS); 541*06977982Sstefanozampini } 542*06977982Sstefanozampini 543*06977982Sstefanozampini static PetscErrorCode hypreCSRMatrixGetCOO_Private(hypre_CSRMatrix *A, PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j) 544*06977982Sstefanozampini { 545*06977982Sstefanozampini PetscInt n = hypre_CSRMatrixNumRows(A); 546*06977982Sstefanozampini HYPRE_Int *ii, *jj; 547*06977982Sstefanozampini HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST; 548*06977982Sstefanozampini 549*06977982Sstefanozampini PetscFunctionBegin; 550*06977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 551*06977982Sstefanozampini mem = hypre_CSRMatrixMemoryLocation(A); 552*06977982Sstefanozampini if (mem != HYPRE_MEMORY_HOST) { 553*06977982Sstefanozampini PetscCount nnz = hypre_CSRMatrixNumNonzeros(A); 554*06977982Sstefanozampini PetscCall(PetscMalloc2(n + 1, &ii, nnz, &jj)); 555*06977982Sstefanozampini hypre_TMemcpy(ii, hypre_CSRMatrixI(A), HYPRE_Int, n + 1, HYPRE_MEMORY_HOST, mem); 556*06977982Sstefanozampini hypre_TMemcpy(jj, hypre_CSRMatrixJ(A), HYPRE_Int, nnz, HYPRE_MEMORY_HOST, mem); 557*06977982Sstefanozampini } else { 558*06977982Sstefanozampini #else 559*06977982Sstefanozampini { 560*06977982Sstefanozampini #endif 561*06977982Sstefanozampini ii = hypre_CSRMatrixI(A); 562*06977982Sstefanozampini jj = hypre_CSRMatrixJ(A); 563*06977982Sstefanozampini } 564*06977982Sstefanozampini PetscCall(CSRtoCOO_HYPRE_Int_Private(n, ii, jj, ncoo, coo_i, coo_j)); 565*06977982Sstefanozampini if (mem != HYPRE_MEMORY_HOST) PetscCall(PetscFree2(ii, jj)); 566*06977982Sstefanozampini PetscFunctionReturn(PETSC_SUCCESS); 567*06977982Sstefanozampini } 568*06977982Sstefanozampini 569*06977982Sstefanozampini static PetscErrorCode MatSetValuesCOOFromCSRMatrix_Private(Mat A, hypre_CSRMatrix *H) 570*06977982Sstefanozampini { 571*06977982Sstefanozampini PetscBool iscpu = PETSC_TRUE; 572*06977982Sstefanozampini PetscScalar *a; 573*06977982Sstefanozampini HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST; 574*06977982Sstefanozampini 575*06977982Sstefanozampini PetscFunctionBegin; 576*06977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 577*06977982Sstefanozampini mem = hypre_CSRMatrixMemoryLocation(H); 578*06977982Sstefanozampini PetscCall(PetscObjectTypeCompare((PetscObject)A, MATSEQAIJ, &iscpu)); 579*06977982Sstefanozampini #endif 580*06977982Sstefanozampini if (iscpu && mem != HYPRE_MEMORY_HOST) { 581*06977982Sstefanozampini PetscCount nnz = hypre_CSRMatrixNumNonzeros(H); 582*06977982Sstefanozampini PetscCall(PetscMalloc1(nnz, &a)); 583*06977982Sstefanozampini hypre_TMemcpy(a, hypre_CSRMatrixData(H), PetscScalar, nnz, HYPRE_MEMORY_HOST, mem); 584*06977982Sstefanozampini } else { 585*06977982Sstefanozampini a = (PetscScalar *)hypre_CSRMatrixData(H); 586*06977982Sstefanozampini } 587*06977982Sstefanozampini PetscCall(MatSetValuesCOO(A, a, INSERT_VALUES)); 588*06977982Sstefanozampini if (iscpu && mem != HYPRE_MEMORY_HOST) PetscCall(PetscFree(a)); 589b73e3080SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 590b73e3080SStefano Zampini } 591b73e3080SStefano Zampini 592b73e3080SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType type, MatReuse reuse, Mat *B) 593b73e3080SStefano Zampini { 594b73e3080SStefano Zampini MPI_Comm comm = PetscObjectComm((PetscObject)A); 595*06977982Sstefanozampini Mat M = NULL, dH = NULL, oH = NULL, dA = NULL, oA = NULL; 596b73e3080SStefano Zampini PetscBool ismpiaij, issbaij, isbaij; 597b73e3080SStefano Zampini Mat_HYPRE *hA; 598b73e3080SStefano Zampini 599b73e3080SStefano Zampini PetscFunctionBegin; 600b73e3080SStefano Zampini PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &issbaij, MATSEQSBAIJ, MATMPIBAIJ, "")); 601b73e3080SStefano Zampini PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &isbaij, MATSEQBAIJ, MATMPIBAIJ, "")); 602b73e3080SStefano Zampini if (isbaij || issbaij) { /* handle BAIJ and SBAIJ */ 603b73e3080SStefano Zampini PetscBool ismpi; 604b73e3080SStefano Zampini MatType newtype; 605b73e3080SStefano Zampini 606b73e3080SStefano Zampini PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &ismpi, MATMPISBAIJ, MATMPIBAIJ, "")); 607b73e3080SStefano Zampini newtype = ismpi ? MATMPIAIJ : MATSEQAIJ; 60863c07aadSStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 609b73e3080SStefano Zampini PetscCall(MatConvert(*B, newtype, MAT_INPLACE_MATRIX, B)); 610b73e3080SStefano Zampini PetscCall(MatConvert(A, newtype, MAT_REUSE_MATRIX, B)); 611b73e3080SStefano Zampini PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B)); 612b73e3080SStefano Zampini } else if (reuse == MAT_INITIAL_MATRIX) { 613b73e3080SStefano Zampini PetscCall(MatConvert(A, newtype, MAT_INITIAL_MATRIX, B)); 614b73e3080SStefano Zampini PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B)); 61563c07aadSStefano Zampini } else { 616b73e3080SStefano Zampini PetscCall(MatConvert(A, newtype, MAT_INPLACE_MATRIX, &A)); 617b73e3080SStefano Zampini PetscCall(MatConvert(A, MATHYPRE, MAT_INPLACE_MATRIX, &A)); 618b73e3080SStefano Zampini } 619b73e3080SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 620b73e3080SStefano Zampini } 621*06977982Sstefanozampini 622*06977982Sstefanozampini dA = A; 623b73e3080SStefano Zampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 624b73e3080SStefano Zampini if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(A, &dA, &oA, NULL)); 625*06977982Sstefanozampini 626b73e3080SStefano Zampini if (reuse != MAT_REUSE_MATRIX) { 627*06977982Sstefanozampini PetscCount coo_n; 628*06977982Sstefanozampini PetscInt *coo_i, *coo_j; 629*06977982Sstefanozampini 6309566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &M)); 6319566063dSJacob Faibussowitsch PetscCall(MatSetType(M, MATHYPRE)); 6329566063dSJacob Faibussowitsch PetscCall(MatSetSizes(M, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N)); 633b73e3080SStefano Zampini PetscCall(MatSetOption(M, MAT_SORTED_FULL, PETSC_TRUE)); 634b73e3080SStefano Zampini PetscCall(MatSetOption(M, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE)); 635b73e3080SStefano Zampini 636b73e3080SStefano Zampini hA = (Mat_HYPRE *)M->data; 637*06977982Sstefanozampini PetscCall(MatHYPRE_CreateFromMat(A, hA)); 638*06977982Sstefanozampini PetscCall(MatHYPRE_IJMatrixCopyIJ(A, hA->ij)); 639*06977982Sstefanozampini 640*06977982Sstefanozampini PetscCall(MatHYPRE_CreateCOOMat(M)); 641*06977982Sstefanozampini 642*06977982Sstefanozampini dH = hA->cooMat; 643*06977982Sstefanozampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)hA->cooMat, MATMPIAIJ, &ismpiaij)); 644*06977982Sstefanozampini if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(hA->cooMat, &dH, &oH, NULL)); 645*06977982Sstefanozampini 646*06977982Sstefanozampini PetscCall(PetscObjectSetName((PetscObject)dH, "_internal_COO_mat_for_hypre")); 647*06977982Sstefanozampini PetscCall(MatSeqAIJGetCOO_Private(dA, &coo_n, &coo_i, &coo_j)); 648*06977982Sstefanozampini PetscCall(MatSetPreallocationCOO(dH, coo_n, coo_i, coo_j)); 649*06977982Sstefanozampini PetscCall(PetscFree2(coo_i, coo_j)); 650*06977982Sstefanozampini if (oH) { 651*06977982Sstefanozampini PetscCall(PetscLayoutDestroy(&oH->cmap)); 652*06977982Sstefanozampini PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)oH), oA->cmap->n, oA->cmap->n, 1, &oH->cmap)); 653*06977982Sstefanozampini PetscCall(MatSeqAIJGetCOO_Private(oA, &coo_n, &coo_i, &coo_j)); 654*06977982Sstefanozampini PetscCall(MatSetPreallocationCOO(oH, coo_n, coo_i, coo_j)); 655*06977982Sstefanozampini PetscCall(PetscFree2(coo_i, coo_j)); 656*06977982Sstefanozampini } 657*06977982Sstefanozampini hA->cooMat->assembled = PETSC_TRUE; 658*06977982Sstefanozampini 659b73e3080SStefano Zampini M->preallocated = PETSC_TRUE; 660*06977982Sstefanozampini PetscCall(MatAssemblyBegin(M, MAT_FINAL_ASSEMBLY)); 661*06977982Sstefanozampini PetscCall(MatAssemblyEnd(M, MAT_FINAL_ASSEMBLY)); 662*06977982Sstefanozampini 663*06977982Sstefanozampini PetscCall(MatHYPRE_AttachCOOMat(M)); 66484d4e069SStefano Zampini if (reuse == MAT_INITIAL_MATRIX) *B = M; 665b73e3080SStefano Zampini } else M = *B; 666b73e3080SStefano Zampini 667b73e3080SStefano Zampini hA = (Mat_HYPRE *)M->data; 668*06977982Sstefanozampini PetscCheck(hA->cooMat, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet"); 669*06977982Sstefanozampini 670*06977982Sstefanozampini dH = hA->cooMat; 671*06977982Sstefanozampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)hA->cooMat, MATMPIAIJ, &ismpiaij)); 672*06977982Sstefanozampini if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(hA->cooMat, &dH, &oH, NULL)); 673*06977982Sstefanozampini 674*06977982Sstefanozampini PetscScalar *a; 675*06977982Sstefanozampini PetscCall(MatSeqAIJGetCSRAndMemType(dA, NULL, NULL, &a, NULL)); 676*06977982Sstefanozampini PetscCall(MatSetValuesCOO(dH, a, INSERT_VALUES)); 677*06977982Sstefanozampini if (oH) { 678*06977982Sstefanozampini PetscCall(MatSeqAIJGetCSRAndMemType(oA, NULL, NULL, &a, NULL)); 679*06977982Sstefanozampini PetscCall(MatSetValuesCOO(oH, a, INSERT_VALUES)); 680*06977982Sstefanozampini } 681b73e3080SStefano Zampini 68248a46eb9SPierre Jolivet if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &M)); 6833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 68463c07aadSStefano Zampini } 68563c07aadSStefano Zampini 686d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_HYPRE_AIJ(Mat A, MatType mtype, MatReuse reuse, Mat *B) 687d71ae5a4SJacob Faibussowitsch { 688*06977982Sstefanozampini Mat M, dA = NULL, oA = NULL; 68963c07aadSStefano Zampini hypre_ParCSRMatrix *parcsr; 690*06977982Sstefanozampini hypre_CSRMatrix *dH, *oH; 69163c07aadSStefano Zampini MPI_Comm comm; 692*06977982Sstefanozampini PetscBool ismpiaij, isseqaij; 69363c07aadSStefano Zampini 69463c07aadSStefano Zampini PetscFunctionBegin; 69563c07aadSStefano Zampini comm = PetscObjectComm((PetscObject)A); 69663c07aadSStefano Zampini if (reuse == MAT_REUSE_MATRIX) { 6979566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATMPIAIJ, &ismpiaij)); 6989566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATSEQAIJ, &isseqaij)); 699*06977982Sstefanozampini PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Only MATMPIAIJ or MATSEQAIJ base types are supported"); 70063c07aadSStefano Zampini } 701*06977982Sstefanozampini PetscCall(MatHYPREGetParCSR(A, &parcsr)); 7026ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 703*06977982Sstefanozampini if (HYPRE_MEMORY_DEVICE == hypre_ParCSRMatrixMemoryLocation(parcsr)) { 704*06977982Sstefanozampini PetscBool isaij; 705*06977982Sstefanozampini 706*06977982Sstefanozampini PetscCall(PetscStrcmp(mtype, MATAIJ, &isaij)); 707*06977982Sstefanozampini if (isaij) { 708*06977982Sstefanozampini PetscMPIInt size; 709*06977982Sstefanozampini 7109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 711*06977982Sstefanozampini #if defined(HYPRE_USING_HIP) 712*06977982Sstefanozampini mtype = size > 1 ? MATMPIAIJHIPSPARSE : MATSEQAIJHIPSPARSE; 713*06977982Sstefanozampini #elif defined(HYPRE_USING_CUDA) 714*06977982Sstefanozampini mtype = size > 1 ? MATMPIAIJCUSPARSE : MATSEQAIJCUSPARSE; 715*06977982Sstefanozampini #else 716*06977982Sstefanozampini mtype = size > 1 ? MATMPIAIJ : MATSEQAIJ; 717*06977982Sstefanozampini #endif 71863c07aadSStefano Zampini } 71963c07aadSStefano Zampini } 720*06977982Sstefanozampini #endif 721*06977982Sstefanozampini dH = hypre_ParCSRMatrixDiag(parcsr); 722*06977982Sstefanozampini oH = hypre_ParCSRMatrixOffd(parcsr); 7239371c9d4SSatish Balay if (reuse != MAT_REUSE_MATRIX) { 724*06977982Sstefanozampini PetscCount coo_n; 725*06977982Sstefanozampini PetscInt *coo_i, *coo_j; 72663c07aadSStefano Zampini 727*06977982Sstefanozampini PetscCall(MatCreate(comm, &M)); 728*06977982Sstefanozampini PetscCall(MatSetType(M, mtype)); 729*06977982Sstefanozampini PetscCall(MatSetSizes(M, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N)); 730*06977982Sstefanozampini PetscCall(MatMPIAIJSetPreallocation(M, 0, NULL, 0, NULL)); 73163c07aadSStefano Zampini 732*06977982Sstefanozampini dA = M; 733*06977982Sstefanozampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)M, MATMPIAIJ, &ismpiaij)); 734*06977982Sstefanozampini if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(M, &dA, &oA, NULL)); 735a16187a7SStefano Zampini 736*06977982Sstefanozampini PetscCall(hypreCSRMatrixGetCOO_Private(dH, &coo_n, &coo_i, &coo_j)); 737*06977982Sstefanozampini PetscCall(MatSetPreallocationCOO(dA, coo_n, coo_i, coo_j)); 738*06977982Sstefanozampini PetscCall(PetscFree2(coo_i, coo_j)); 739*06977982Sstefanozampini if (ismpiaij) { 740*06977982Sstefanozampini HYPRE_Int nc = hypre_CSRMatrixNumCols(oH); 741a16187a7SStefano Zampini 742*06977982Sstefanozampini PetscCall(PetscLayoutDestroy(&oA->cmap)); 743*06977982Sstefanozampini PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)oA), nc, nc, 1, &oA->cmap)); 744*06977982Sstefanozampini PetscCall(hypreCSRMatrixGetCOO_Private(oH, &coo_n, &coo_i, &coo_j)); 745*06977982Sstefanozampini PetscCall(MatSetPreallocationCOO(oA, coo_n, coo_i, coo_j)); 746*06977982Sstefanozampini PetscCall(PetscFree2(coo_i, coo_j)); 747a16187a7SStefano Zampini 748*06977982Sstefanozampini /* garray */ 749*06977982Sstefanozampini Mat_MPIAIJ *aij = (Mat_MPIAIJ *)(M->data); 750*06977982Sstefanozampini HYPRE_BigInt *harray = hypre_ParCSRMatrixColMapOffd(parcsr); 751*06977982Sstefanozampini PetscInt *garray; 752*06977982Sstefanozampini 753*06977982Sstefanozampini PetscCall(PetscFree(aij->garray)); 754*06977982Sstefanozampini PetscCall(PetscMalloc1(nc, &garray)); 755*06977982Sstefanozampini for (HYPRE_Int i = 0; i < nc; i++) garray[i] = (PetscInt)harray[i]; 756*06977982Sstefanozampini aij->garray = garray; 757*06977982Sstefanozampini PetscCall(MatSetUpMultiply_MPIAIJ(M)); 758a16187a7SStefano Zampini } 759*06977982Sstefanozampini if (reuse == MAT_INITIAL_MATRIX) *B = M; 760*06977982Sstefanozampini } else M = *B; 761225daaf8SStefano Zampini 762*06977982Sstefanozampini dA = M; 763*06977982Sstefanozampini PetscCall(PetscObjectBaseTypeCompare((PetscObject)M, MATMPIAIJ, &ismpiaij)); 764*06977982Sstefanozampini if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(M, &dA, &oA, NULL)); 765*06977982Sstefanozampini PetscCall(MatSetValuesCOOFromCSRMatrix_Private(dA, dH)); 766*06977982Sstefanozampini if (oA) PetscCall(MatSetValuesCOOFromCSRMatrix_Private(oA, oH)); 767*06977982Sstefanozampini M->assembled = PETSC_TRUE; 768*06977982Sstefanozampini if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &M)); 7693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 77063c07aadSStefano Zampini } 77163c07aadSStefano Zampini 772d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJGetParCSR_Private(Mat A, hypre_ParCSRMatrix **hA) 773d71ae5a4SJacob Faibussowitsch { 774613e5ff0Sstefano_zampini hypre_ParCSRMatrix *tA; 775c1a070e6SStefano Zampini hypre_CSRMatrix *hdiag, *hoffd; 776c1a070e6SStefano Zampini Mat_SeqAIJ *diag, *offd; 7772cf14000SStefano Zampini PetscInt *garray, i, noffd, dnnz, onnz, *row_starts, *col_starts; 778c1a070e6SStefano Zampini MPI_Comm comm = PetscObjectComm((PetscObject)A); 779613e5ff0Sstefano_zampini PetscBool ismpiaij, isseqaij; 7802cf14000SStefano Zampini PetscBool sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int)); 7816ea7df73SStefano Zampini HYPRE_Int *hdi = NULL, *hdj = NULL, *hoi = NULL, *hoj = NULL; 7825c97c10fSStefano Zampini PetscInt *pdi = NULL, *pdj = NULL, *poi = NULL, *poj = NULL; 783*06977982Sstefanozampini PetscBool iscuda, iship; 784*06977982Sstefanozampini #if defined(PETSC_HAVE_DEVICE) && defined(PETSC_HAVE_HYPRE_DEVICE) 785*06977982Sstefanozampini PetscBool boundtocpu = A->boundtocpu; 786*06977982Sstefanozampini #else 787*06977982Sstefanozampini PetscBool boundtocpu = PETSC_TRUE; 7886ea7df73SStefano Zampini #endif 789c1a070e6SStefano Zampini 790c1a070e6SStefano Zampini PetscFunctionBegin; 7919566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 7929566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isseqaij)); 79308401ef6SPierre Jolivet PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Unsupported type %s", ((PetscObject)A)->type_name); 794*06977982Sstefanozampini PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iscuda, MATSEQAIJHIPSPARSE, MATMPIAIJCUSPARSE, "")); 795*06977982Sstefanozampini PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iship, MATSEQAIJCUSPARSE, MATMPIAIJHIPSPARSE, "")); 796ea9ee2c1SPierre Jolivet PetscHYPREInitialize(); 797c1a070e6SStefano Zampini if (ismpiaij) { 798c1a070e6SStefano Zampini Mat_MPIAIJ *a = (Mat_MPIAIJ *)(A->data); 799c1a070e6SStefano Zampini 800c1a070e6SStefano Zampini diag = (Mat_SeqAIJ *)a->A->data; 801c1a070e6SStefano Zampini offd = (Mat_SeqAIJ *)a->B->data; 802*06977982Sstefanozampini if (!boundtocpu && (iscuda || iship)) { 803*06977982Sstefanozampini #if defined(HYPRE_USING_CUDA) && defined(PETSC_HAVE_CUDA) 804*06977982Sstefanozampini if (iscuda) { 8056ea7df73SStefano Zampini sameint = PETSC_TRUE; 8069566063dSJacob Faibussowitsch PetscCall(MatSeqAIJCUSPARSEGetIJ(a->A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj)); 8079566063dSJacob Faibussowitsch PetscCall(MatSeqAIJCUSPARSEGetIJ(a->B, PETSC_FALSE, (const HYPRE_Int **)&hoi, (const HYPRE_Int **)&hoj)); 808*06977982Sstefanozampini } 8096ea7df73SStefano Zampini #endif 810*06977982Sstefanozampini #if defined(HYPRE_USING_HIP) && defined(PETSC_HAVE_HIP) 811*06977982Sstefanozampini if (iship) { 812*06977982Sstefanozampini sameint = PETSC_TRUE; 813*06977982Sstefanozampini PetscCall(MatSeqAIJHIPSPARSEGetIJ(a->A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj)); 814*06977982Sstefanozampini PetscCall(MatSeqAIJHIPSPARSEGetIJ(a->B, PETSC_FALSE, (const HYPRE_Int **)&hoi, (const HYPRE_Int **)&hoj)); 815*06977982Sstefanozampini } 816*06977982Sstefanozampini #endif 817*06977982Sstefanozampini } else { 818*06977982Sstefanozampini boundtocpu = PETSC_TRUE; 8196ea7df73SStefano Zampini pdi = diag->i; 8206ea7df73SStefano Zampini pdj = diag->j; 8216ea7df73SStefano Zampini poi = offd->i; 8226ea7df73SStefano Zampini poj = offd->j; 8236ea7df73SStefano Zampini if (sameint) { 8246ea7df73SStefano Zampini hdi = (HYPRE_Int *)pdi; 8256ea7df73SStefano Zampini hdj = (HYPRE_Int *)pdj; 8266ea7df73SStefano Zampini hoi = (HYPRE_Int *)poi; 8276ea7df73SStefano Zampini hoj = (HYPRE_Int *)poj; 8286ea7df73SStefano Zampini } 8296ea7df73SStefano Zampini } 830c1a070e6SStefano Zampini garray = a->garray; 831c1a070e6SStefano Zampini noffd = a->B->cmap->N; 832c1a070e6SStefano Zampini dnnz = diag->nz; 833c1a070e6SStefano Zampini onnz = offd->nz; 834c1a070e6SStefano Zampini } else { 835c1a070e6SStefano Zampini diag = (Mat_SeqAIJ *)A->data; 836c1a070e6SStefano Zampini offd = NULL; 837*06977982Sstefanozampini if (!boundtocpu && (iscuda || iship)) { 838*06977982Sstefanozampini #if defined(HYPRE_USING_CUDA) && defined(PETSC_HAVE_CUDA) 839*06977982Sstefanozampini if (iscuda) { 8406ea7df73SStefano Zampini sameint = PETSC_TRUE; 8419566063dSJacob Faibussowitsch PetscCall(MatSeqAIJCUSPARSEGetIJ(A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj)); 842*06977982Sstefanozampini } 8436ea7df73SStefano Zampini #endif 844*06977982Sstefanozampini #if defined(HYPRE_USING_HIP) && defined(PETSC_HAVE_HIP) 845*06977982Sstefanozampini if (iship) { 846*06977982Sstefanozampini sameint = PETSC_TRUE; 847*06977982Sstefanozampini PetscCall(MatSeqAIJHIPSPARSEGetIJ(A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj)); 848*06977982Sstefanozampini } 849*06977982Sstefanozampini #endif 850*06977982Sstefanozampini } else { 851*06977982Sstefanozampini boundtocpu = PETSC_TRUE; 8526ea7df73SStefano Zampini pdi = diag->i; 8536ea7df73SStefano Zampini pdj = diag->j; 8546ea7df73SStefano Zampini if (sameint) { 8556ea7df73SStefano Zampini hdi = (HYPRE_Int *)pdi; 8566ea7df73SStefano Zampini hdj = (HYPRE_Int *)pdj; 8576ea7df73SStefano Zampini } 8586ea7df73SStefano Zampini } 859c1a070e6SStefano Zampini garray = NULL; 860c1a070e6SStefano Zampini noffd = 0; 861c1a070e6SStefano Zampini dnnz = diag->nz; 862c1a070e6SStefano Zampini onnz = 0; 863c1a070e6SStefano Zampini } 864225daaf8SStefano Zampini 865c1a070e6SStefano Zampini /* create a temporary ParCSR */ 866c1a070e6SStefano Zampini if (HYPRE_AssumedPartitionCheck()) { 867c1a070e6SStefano Zampini PetscMPIInt myid; 868c1a070e6SStefano Zampini 8699566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &myid)); 870c1a070e6SStefano Zampini row_starts = A->rmap->range + myid; 871c1a070e6SStefano Zampini col_starts = A->cmap->range + myid; 872c1a070e6SStefano Zampini } else { 873c1a070e6SStefano Zampini row_starts = A->rmap->range; 874c1a070e6SStefano Zampini col_starts = A->cmap->range; 875c1a070e6SStefano Zampini } 8762cf14000SStefano Zampini tA = hypre_ParCSRMatrixCreate(comm, A->rmap->N, A->cmap->N, (HYPRE_BigInt *)row_starts, (HYPRE_BigInt *)col_starts, noffd, dnnz, onnz); 877a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 878c1a070e6SStefano Zampini hypre_ParCSRMatrixSetRowStartsOwner(tA, 0); 879c1a070e6SStefano Zampini hypre_ParCSRMatrixSetColStartsOwner(tA, 0); 880a1d2239cSSatish Balay #endif 881c1a070e6SStefano Zampini 882225daaf8SStefano Zampini /* set diagonal part */ 883c1a070e6SStefano Zampini hdiag = hypre_ParCSRMatrixDiag(tA); 8846ea7df73SStefano Zampini if (!sameint) { /* malloc CSR pointers */ 8859566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(A->rmap->n + 1, &hdi, dnnz, &hdj)); 8866ea7df73SStefano Zampini for (i = 0; i < A->rmap->n + 1; i++) hdi[i] = (HYPRE_Int)(pdi[i]); 8876ea7df73SStefano Zampini for (i = 0; i < dnnz; i++) hdj[i] = (HYPRE_Int)(pdj[i]); 8882cf14000SStefano Zampini } 8896ea7df73SStefano Zampini hypre_CSRMatrixI(hdiag) = hdi; 8906ea7df73SStefano Zampini hypre_CSRMatrixJ(hdiag) = hdj; 89139accc25SStefano Zampini hypre_CSRMatrixData(hdiag) = (HYPRE_Complex *)diag->a; 892c1a070e6SStefano Zampini hypre_CSRMatrixNumNonzeros(hdiag) = diag->nz; 893c1a070e6SStefano Zampini hypre_CSRMatrixSetRownnz(hdiag); 894c1a070e6SStefano Zampini hypre_CSRMatrixSetDataOwner(hdiag, 0); 895c1a070e6SStefano Zampini 896225daaf8SStefano Zampini /* set offdiagonal part */ 897c1a070e6SStefano Zampini hoffd = hypre_ParCSRMatrixOffd(tA); 898c1a070e6SStefano Zampini if (offd) { 8996ea7df73SStefano Zampini if (!sameint) { /* malloc CSR pointers */ 9009566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(A->rmap->n + 1, &hoi, onnz, &hoj)); 9016ea7df73SStefano Zampini for (i = 0; i < A->rmap->n + 1; i++) hoi[i] = (HYPRE_Int)(poi[i]); 9026ea7df73SStefano Zampini for (i = 0; i < onnz; i++) hoj[i] = (HYPRE_Int)(poj[i]); 9032cf14000SStefano Zampini } 9046ea7df73SStefano Zampini hypre_CSRMatrixI(hoffd) = hoi; 9056ea7df73SStefano Zampini hypre_CSRMatrixJ(hoffd) = hoj; 90639accc25SStefano Zampini hypre_CSRMatrixData(hoffd) = (HYPRE_Complex *)offd->a; 907c1a070e6SStefano Zampini hypre_CSRMatrixNumNonzeros(hoffd) = offd->nz; 908c1a070e6SStefano Zampini hypre_CSRMatrixSetRownnz(hoffd); 909c1a070e6SStefano Zampini hypre_CSRMatrixSetDataOwner(hoffd, 0); 9106ea7df73SStefano Zampini } 9116ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 912*06977982Sstefanozampini PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, !boundtocpu ? HYPRE_MEMORY_DEVICE : HYPRE_MEMORY_HOST); 9136ea7df73SStefano Zampini #else 9146ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0) 915792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixInitialize, tA); 9166ea7df73SStefano Zampini #else 917792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, HYPRE_MEMORY_HOST); 9186ea7df73SStefano Zampini #endif 9196ea7df73SStefano Zampini #endif 9206ea7df73SStefano Zampini hypre_TFree(hypre_ParCSRMatrixColMapOffd(tA), HYPRE_MEMORY_HOST); 921c1a070e6SStefano Zampini hypre_ParCSRMatrixSetNumNonzeros(tA); 9222cf14000SStefano Zampini hypre_ParCSRMatrixColMapOffd(tA) = (HYPRE_BigInt *)garray; 923792fecdfSBarry Smith if (!hypre_ParCSRMatrixCommPkg(tA)) PetscCallExternal(hypre_MatvecCommPkgCreate, tA); 924613e5ff0Sstefano_zampini *hA = tA; 9253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 926613e5ff0Sstefano_zampini } 927c1a070e6SStefano Zampini 928d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJRestoreParCSR_Private(Mat A, hypre_ParCSRMatrix **hA) 929d71ae5a4SJacob Faibussowitsch { 930613e5ff0Sstefano_zampini hypre_CSRMatrix *hdiag, *hoffd; 9316ea7df73SStefano Zampini PetscBool ismpiaij, sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int)); 9326ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 9336ea7df73SStefano Zampini PetscBool iscuda = PETSC_FALSE; 9346ea7df73SStefano Zampini #endif 935c1a070e6SStefano Zampini 936613e5ff0Sstefano_zampini PetscFunctionBegin; 9379566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij)); 9386ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 9399566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, "")); 9406ea7df73SStefano Zampini if (iscuda) sameint = PETSC_TRUE; 9416ea7df73SStefano Zampini #endif 942613e5ff0Sstefano_zampini hdiag = hypre_ParCSRMatrixDiag(*hA); 943613e5ff0Sstefano_zampini hoffd = hypre_ParCSRMatrixOffd(*hA); 9446ea7df73SStefano Zampini /* free temporary memory allocated by PETSc 9456ea7df73SStefano Zampini set pointers to NULL before destroying tA */ 9462cf14000SStefano Zampini if (!sameint) { 9472cf14000SStefano Zampini HYPRE_Int *hi, *hj; 9482cf14000SStefano Zampini 9492cf14000SStefano Zampini hi = hypre_CSRMatrixI(hdiag); 9502cf14000SStefano Zampini hj = hypre_CSRMatrixJ(hdiag); 9519566063dSJacob Faibussowitsch PetscCall(PetscFree2(hi, hj)); 9526ea7df73SStefano Zampini if (ismpiaij) { 9532cf14000SStefano Zampini hi = hypre_CSRMatrixI(hoffd); 9542cf14000SStefano Zampini hj = hypre_CSRMatrixJ(hoffd); 9559566063dSJacob Faibussowitsch PetscCall(PetscFree2(hi, hj)); 9562cf14000SStefano Zampini } 9572cf14000SStefano Zampini } 958c1a070e6SStefano Zampini hypre_CSRMatrixI(hdiag) = NULL; 959c1a070e6SStefano Zampini hypre_CSRMatrixJ(hdiag) = NULL; 960c1a070e6SStefano Zampini hypre_CSRMatrixData(hdiag) = NULL; 9616ea7df73SStefano Zampini if (ismpiaij) { 962c1a070e6SStefano Zampini hypre_CSRMatrixI(hoffd) = NULL; 963c1a070e6SStefano Zampini hypre_CSRMatrixJ(hoffd) = NULL; 964c1a070e6SStefano Zampini hypre_CSRMatrixData(hoffd) = NULL; 9656ea7df73SStefano Zampini } 966613e5ff0Sstefano_zampini hypre_ParCSRMatrixColMapOffd(*hA) = NULL; 967613e5ff0Sstefano_zampini hypre_ParCSRMatrixDestroy(*hA); 968613e5ff0Sstefano_zampini *hA = NULL; 9693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 970613e5ff0Sstefano_zampini } 971613e5ff0Sstefano_zampini 972613e5ff0Sstefano_zampini /* calls RAP from BoomerAMG: 9733dad0653Sstefano_zampini the resulting ParCSR will not own the column and row starts 9746ea7df73SStefano Zampini It looks like we don't need to have the diagonal entries ordered first */ 975d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_RAP(hypre_ParCSRMatrix *hR, hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hP, hypre_ParCSRMatrix **hRAP) 976d71ae5a4SJacob Faibussowitsch { 977a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 978613e5ff0Sstefano_zampini HYPRE_Int P_owns_col_starts, R_owns_row_starts; 979a1d2239cSSatish Balay #endif 980613e5ff0Sstefano_zampini 981613e5ff0Sstefano_zampini PetscFunctionBegin; 982a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 983613e5ff0Sstefano_zampini P_owns_col_starts = hypre_ParCSRMatrixOwnsColStarts(hP); 984613e5ff0Sstefano_zampini R_owns_row_starts = hypre_ParCSRMatrixOwnsRowStarts(hR); 985a1d2239cSSatish Balay #endif 9866ea7df73SStefano Zampini /* can be replaced by version test later */ 9876ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 988792fecdfSBarry Smith PetscStackPushExternal("hypre_ParCSRMatrixRAP"); 9896ea7df73SStefano Zampini *hRAP = hypre_ParCSRMatrixRAP(hR, hA, hP); 9906ea7df73SStefano Zampini PetscStackPop; 9916ea7df73SStefano Zampini #else 992792fecdfSBarry Smith PetscCallExternal(hypre_BoomerAMGBuildCoarseOperator, hR, hA, hP, hRAP); 993792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixSetNumNonzeros, *hRAP); 9946ea7df73SStefano Zampini #endif 995613e5ff0Sstefano_zampini /* hypre_BoomerAMGBuildCoarseOperator steals the col_starts from P and the row_starts from R */ 996a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 997613e5ff0Sstefano_zampini hypre_ParCSRMatrixSetRowStartsOwner(*hRAP, 0); 998613e5ff0Sstefano_zampini hypre_ParCSRMatrixSetColStartsOwner(*hRAP, 0); 999613e5ff0Sstefano_zampini if (P_owns_col_starts) hypre_ParCSRMatrixSetColStartsOwner(hP, 1); 1000613e5ff0Sstefano_zampini if (R_owns_row_starts) hypre_ParCSRMatrixSetRowStartsOwner(hR, 1); 1001a1d2239cSSatish Balay #endif 10023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1003613e5ff0Sstefano_zampini } 1004613e5ff0Sstefano_zampini 1005d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat P, Mat C) 1006d71ae5a4SJacob Faibussowitsch { 10076f231fbdSstefano_zampini Mat B; 10086abb4441SStefano Zampini hypre_ParCSRMatrix *hA, *hP, *hPtAP = NULL; 10094222ddf1SHong Zhang Mat_Product *product = C->product; 1010613e5ff0Sstefano_zampini 1011613e5ff0Sstefano_zampini PetscFunctionBegin; 10129566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(A, &hA)); 10139566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(P, &hP)); 10149566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_RAP(hP, hA, hP, &hPtAP)); 10159566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(hPtAP, MATAIJ, PETSC_OWN_POINTER, &B)); 10164222ddf1SHong Zhang 10179566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(C, &B)); 10184222ddf1SHong Zhang C->product = product; 10194222ddf1SHong Zhang 10209566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(A, &hA)); 10219566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(P, &hP)); 10223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10236f231fbdSstefano_zampini } 10246f231fbdSstefano_zampini 1025d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatPtAPSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat P, PetscReal fill, Mat C) 1026d71ae5a4SJacob Faibussowitsch { 10276f231fbdSstefano_zampini PetscFunctionBegin; 10289566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATAIJ)); 10294222ddf1SHong Zhang C->ops->ptapnumeric = MatPtAPNumeric_AIJ_AIJ_wHYPRE; 10304222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_PtAP; 10313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1032613e5ff0Sstefano_zampini } 1033613e5ff0Sstefano_zampini 1034d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_HYPRE(Mat A, Mat P, Mat C) 1035d71ae5a4SJacob Faibussowitsch { 10364cc28894Sstefano_zampini Mat B; 10374cc28894Sstefano_zampini Mat_HYPRE *hP; 10386abb4441SStefano Zampini hypre_ParCSRMatrix *hA = NULL, *Pparcsr, *ptapparcsr = NULL; 1039613e5ff0Sstefano_zampini HYPRE_Int type; 1040613e5ff0Sstefano_zampini MPI_Comm comm = PetscObjectComm((PetscObject)A); 10414cc28894Sstefano_zampini PetscBool ishypre; 1042613e5ff0Sstefano_zampini 1043613e5ff0Sstefano_zampini PetscFunctionBegin; 10449566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre)); 104528b400f6SJacob Faibussowitsch PetscCheck(ishypre, comm, PETSC_ERR_USER, "P should be of type %s", MATHYPRE); 10464cc28894Sstefano_zampini hP = (Mat_HYPRE *)P->data; 1047792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type); 104808401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 1049792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr); 1050613e5ff0Sstefano_zampini 10519566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(A, &hA)); 10529566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, hA, Pparcsr, &ptapparcsr)); 10539566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(A, &hA)); 1054225daaf8SStefano Zampini 10554cc28894Sstefano_zampini /* create temporary matrix and merge to C */ 10569566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(ptapparcsr, ((PetscObject)C)->type_name, PETSC_OWN_POINTER, &B)); 10579566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(C, &B)); 10583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10594cc28894Sstefano_zampini } 10604cc28894Sstefano_zampini 1061d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_HYPRE_HYPRE(Mat A, Mat P, Mat C) 1062d71ae5a4SJacob Faibussowitsch { 10634cc28894Sstefano_zampini Mat B; 10646abb4441SStefano Zampini hypre_ParCSRMatrix *Aparcsr, *Pparcsr, *ptapparcsr = NULL; 10654cc28894Sstefano_zampini Mat_HYPRE *hA, *hP; 10664cc28894Sstefano_zampini PetscBool ishypre; 10674cc28894Sstefano_zampini HYPRE_Int type; 10684cc28894Sstefano_zampini 10694cc28894Sstefano_zampini PetscFunctionBegin; 10709566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre)); 107128b400f6SJacob Faibussowitsch PetscCheck(ishypre, PetscObjectComm((PetscObject)P), PETSC_ERR_USER, "P should be of type %s", MATHYPRE); 10729566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre)); 107328b400f6SJacob Faibussowitsch PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE); 10744cc28894Sstefano_zampini hA = (Mat_HYPRE *)A->data; 10754cc28894Sstefano_zampini hP = (Mat_HYPRE *)P->data; 1076792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type); 107708401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 1078792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type); 107908401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)P), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 1080792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr); 1081792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr); 10829566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, Aparcsr, Pparcsr, &ptapparcsr)); 10839566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(ptapparcsr, MATHYPRE, PETSC_OWN_POINTER, &B)); 10849566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(C, &B)); 10853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 10864cc28894Sstefano_zampini } 10874cc28894Sstefano_zampini 1088d501dc42Sstefano_zampini /* calls hypre_ParMatmul 1089d501dc42Sstefano_zampini hypre_ParMatMul uses hypre_ParMatrixCreate with the communicator of hA 10903dad0653Sstefano_zampini hypre_ParMatrixCreate does not duplicate the communicator 10916ea7df73SStefano Zampini It looks like we don't need to have the diagonal entries ordered first */ 1092d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_MatMatMult(hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hB, hypre_ParCSRMatrix **hAB) 1093d71ae5a4SJacob Faibussowitsch { 1094d501dc42Sstefano_zampini PetscFunctionBegin; 10956ea7df73SStefano Zampini /* can be replaced by version test later */ 10966ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 1097792fecdfSBarry Smith PetscStackPushExternal("hypre_ParCSRMatMat"); 10986ea7df73SStefano Zampini *hAB = hypre_ParCSRMatMat(hA, hB); 10996ea7df73SStefano Zampini #else 1100792fecdfSBarry Smith PetscStackPushExternal("hypre_ParMatmul"); 1101d501dc42Sstefano_zampini *hAB = hypre_ParMatmul(hA, hB); 11026ea7df73SStefano Zampini #endif 1103d501dc42Sstefano_zampini PetscStackPop; 11043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1105d501dc42Sstefano_zampini } 1106d501dc42Sstefano_zampini 1107d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C) 1108d71ae5a4SJacob Faibussowitsch { 11095e5acdf2Sstefano_zampini Mat D; 1110d501dc42Sstefano_zampini hypre_ParCSRMatrix *hA, *hB, *hAB = NULL; 11114222ddf1SHong Zhang Mat_Product *product = C->product; 11125e5acdf2Sstefano_zampini 11135e5acdf2Sstefano_zampini PetscFunctionBegin; 11149566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(A, &hA)); 11159566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(B, &hB)); 11169566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_MatMatMult(hA, hB, &hAB)); 11179566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(hAB, MATAIJ, PETSC_OWN_POINTER, &D)); 11184222ddf1SHong Zhang 11199566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(C, &D)); 11204222ddf1SHong Zhang C->product = product; 11214222ddf1SHong Zhang 11229566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(A, &hA)); 11239566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(B, &hB)); 11243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11255e5acdf2Sstefano_zampini } 11265e5acdf2Sstefano_zampini 1127d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatMatMultSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat B, PetscReal fill, Mat C) 1128d71ae5a4SJacob Faibussowitsch { 11295e5acdf2Sstefano_zampini PetscFunctionBegin; 11309566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATAIJ)); 11314222ddf1SHong Zhang C->ops->matmultnumeric = MatMatMultNumeric_AIJ_AIJ_wHYPRE; 11324222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_AB; 11333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11345e5acdf2Sstefano_zampini } 11355e5acdf2Sstefano_zampini 1136d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_HYPRE_HYPRE(Mat A, Mat B, Mat C) 1137d71ae5a4SJacob Faibussowitsch { 1138d501dc42Sstefano_zampini Mat D; 1139d501dc42Sstefano_zampini hypre_ParCSRMatrix *Aparcsr, *Bparcsr, *ABparcsr = NULL; 1140d501dc42Sstefano_zampini Mat_HYPRE *hA, *hB; 1141d501dc42Sstefano_zampini PetscBool ishypre; 1142d501dc42Sstefano_zampini HYPRE_Int type; 11434222ddf1SHong Zhang Mat_Product *product; 1144d501dc42Sstefano_zampini 1145d501dc42Sstefano_zampini PetscFunctionBegin; 11469566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)B, MATHYPRE, &ishypre)); 114728b400f6SJacob Faibussowitsch PetscCheck(ishypre, PetscObjectComm((PetscObject)B), PETSC_ERR_USER, "B should be of type %s", MATHYPRE); 11489566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre)); 114928b400f6SJacob Faibussowitsch PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE); 1150d501dc42Sstefano_zampini hA = (Mat_HYPRE *)A->data; 1151d501dc42Sstefano_zampini hB = (Mat_HYPRE *)B->data; 1152792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type); 115308401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 1154792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hB->ij, &type); 115508401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported"); 1156792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr); 1157792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hB->ij, (void **)&Bparcsr); 11589566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_MatMatMult(Aparcsr, Bparcsr, &ABparcsr)); 11599566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(ABparcsr, MATHYPRE, PETSC_OWN_POINTER, &D)); 11604222ddf1SHong Zhang 1161d501dc42Sstefano_zampini /* need to use HeaderReplace because HeaderMerge messes up with the communicator */ 11624222ddf1SHong Zhang product = C->product; /* save it from MatHeaderReplace() */ 11634222ddf1SHong Zhang C->product = NULL; 11649566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(C, &D)); 11654222ddf1SHong Zhang C->product = product; 1166d501dc42Sstefano_zampini C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE; 11674222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_AB; 11683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1169d501dc42Sstefano_zampini } 1170d501dc42Sstefano_zampini 1171d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultNumeric_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, Mat D) 1172d71ae5a4SJacob Faibussowitsch { 117320e1dc0dSstefano_zampini Mat E; 11746abb4441SStefano Zampini hypre_ParCSRMatrix *hA, *hB, *hC, *hABC = NULL; 117520e1dc0dSstefano_zampini 117620e1dc0dSstefano_zampini PetscFunctionBegin; 11779566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(A, &hA)); 11789566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(B, &hB)); 11799566063dSJacob Faibussowitsch PetscCall(MatAIJGetParCSR_Private(C, &hC)); 11809566063dSJacob Faibussowitsch PetscCall(MatHYPRE_ParCSR_RAP(hA, hB, hC, &hABC)); 11819566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(hABC, MATAIJ, PETSC_OWN_POINTER, &E)); 11829566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(D, &E)); 11839566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(A, &hA)); 11849566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(B, &hB)); 11859566063dSJacob Faibussowitsch PetscCall(MatAIJRestoreParCSR_Private(C, &hC)); 11863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 118720e1dc0dSstefano_zampini } 118820e1dc0dSstefano_zampini 1189d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultSymbolic_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, PetscReal fill, Mat D) 1190d71ae5a4SJacob Faibussowitsch { 119120e1dc0dSstefano_zampini PetscFunctionBegin; 11929566063dSJacob Faibussowitsch PetscCall(MatSetType(D, MATAIJ)); 11933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 119420e1dc0dSstefano_zampini } 119520e1dc0dSstefano_zampini 1196d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_AB_HYPRE(Mat C) 1197d71ae5a4SJacob Faibussowitsch { 11984222ddf1SHong Zhang PetscFunctionBegin; 11994222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_AB; 12003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12014222ddf1SHong Zhang } 12024222ddf1SHong Zhang 1203d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_AB(Mat C) 1204d71ae5a4SJacob Faibussowitsch { 12054222ddf1SHong Zhang Mat_Product *product = C->product; 12064222ddf1SHong Zhang PetscBool Ahypre; 12074222ddf1SHong Zhang 12084222ddf1SHong Zhang PetscFunctionBegin; 12099566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)product->A, MATHYPRE, &Ahypre)); 12104222ddf1SHong Zhang if (Ahypre) { /* A is a Hypre matrix */ 12119566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATHYPRE)); 12124222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_AB_HYPRE; 12134222ddf1SHong Zhang C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE; 12143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12156718818eSStefano Zampini } 12163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12174222ddf1SHong Zhang } 12184222ddf1SHong Zhang 1219d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_PtAP_HYPRE(Mat C) 1220d71ae5a4SJacob Faibussowitsch { 12214222ddf1SHong Zhang PetscFunctionBegin; 12224222ddf1SHong Zhang C->ops->productnumeric = MatProductNumeric_PtAP; 12233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12244222ddf1SHong Zhang } 12254222ddf1SHong Zhang 1226d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_PtAP(Mat C) 1227d71ae5a4SJacob Faibussowitsch { 12284222ddf1SHong Zhang Mat_Product *product = C->product; 12294222ddf1SHong Zhang PetscBool flg; 12304222ddf1SHong Zhang PetscInt type = 0; 12314222ddf1SHong Zhang const char *outTypes[4] = {"aij", "seqaij", "mpiaij", "hypre"}; 12324222ddf1SHong Zhang PetscInt ntype = 4; 12334222ddf1SHong Zhang Mat A = product->A; 12344222ddf1SHong Zhang PetscBool Ahypre; 12354222ddf1SHong Zhang 12364222ddf1SHong Zhang PetscFunctionBegin; 12379566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &Ahypre)); 12384222ddf1SHong Zhang if (Ahypre) { /* A is a Hypre matrix */ 12399566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATHYPRE)); 12404222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE; 12414222ddf1SHong Zhang C->ops->ptapnumeric = MatPtAPNumeric_HYPRE_HYPRE; 12423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12434222ddf1SHong Zhang } 12444222ddf1SHong Zhang 12454222ddf1SHong Zhang /* A is AIJ, P is Hypre, C = PtAP can be either AIJ or Hypre format */ 12464222ddf1SHong Zhang /* Get runtime option */ 12474222ddf1SHong Zhang if (product->api_user) { 1248d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatPtAP_HYPRE", "Mat"); 12499566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-matptap_hypre_outtype", "MatPtAP outtype", "MatPtAP outtype", outTypes, ntype, outTypes[type], &type, &flg)); 1250d0609cedSBarry Smith PetscOptionsEnd(); 12514222ddf1SHong Zhang } else { 1252d0609cedSBarry Smith PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatProduct_PtAP_HYPRE", "Mat"); 12539566063dSJacob Faibussowitsch PetscCall(PetscOptionsEList("-mat_product_algorithm_hypre_outtype", "MatProduct_PtAP outtype", "MatProduct_PtAP", outTypes, ntype, outTypes[type], &type, &flg)); 1254d0609cedSBarry Smith PetscOptionsEnd(); 12554222ddf1SHong Zhang } 12564222ddf1SHong Zhang 12574222ddf1SHong Zhang if (type == 0 || type == 1 || type == 2) { 12589566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATAIJ)); 12594222ddf1SHong Zhang } else if (type == 3) { 12609566063dSJacob Faibussowitsch PetscCall(MatSetType(C, MATHYPRE)); 12614222ddf1SHong Zhang } else SETERRQ(PetscObjectComm((PetscObject)C), PETSC_ERR_SUP, "MatPtAP outtype is not supported"); 12624222ddf1SHong Zhang C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE; 12634222ddf1SHong Zhang C->ops->ptapnumeric = MatPtAPNumeric_AIJ_HYPRE; 12643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12654222ddf1SHong Zhang } 12664222ddf1SHong Zhang 1267d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE(Mat C) 1268d71ae5a4SJacob Faibussowitsch { 12694222ddf1SHong Zhang Mat_Product *product = C->product; 12704222ddf1SHong Zhang 12714222ddf1SHong Zhang PetscFunctionBegin; 12724222ddf1SHong Zhang switch (product->type) { 1273d71ae5a4SJacob Faibussowitsch case MATPRODUCT_AB: 1274d71ae5a4SJacob Faibussowitsch PetscCall(MatProductSetFromOptions_HYPRE_AB(C)); 1275d71ae5a4SJacob Faibussowitsch break; 1276d71ae5a4SJacob Faibussowitsch case MATPRODUCT_PtAP: 1277d71ae5a4SJacob Faibussowitsch PetscCall(MatProductSetFromOptions_HYPRE_PtAP(C)); 1278d71ae5a4SJacob Faibussowitsch break; 1279d71ae5a4SJacob Faibussowitsch default: 1280d71ae5a4SJacob Faibussowitsch break; 12814222ddf1SHong Zhang } 12823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12834222ddf1SHong Zhang } 12844222ddf1SHong Zhang 1285d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTranspose_HYPRE(Mat A, Vec x, Vec y) 1286d71ae5a4SJacob Faibussowitsch { 128763c07aadSStefano Zampini PetscFunctionBegin; 12889566063dSJacob Faibussowitsch PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_TRUE)); 12893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 129063c07aadSStefano Zampini } 129163c07aadSStefano Zampini 1292d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_HYPRE(Mat A, Vec x, Vec y) 1293d71ae5a4SJacob Faibussowitsch { 129463c07aadSStefano Zampini PetscFunctionBegin; 12959566063dSJacob Faibussowitsch PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_FALSE)); 12963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 129763c07aadSStefano Zampini } 129863c07aadSStefano Zampini 1299d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultAdd_HYPRE(Mat A, Vec x, Vec y, Vec z) 1300d71ae5a4SJacob Faibussowitsch { 1301414bd5c3SStefano Zampini PetscFunctionBegin; 130248a46eb9SPierre Jolivet if (y != z) PetscCall(VecCopy(y, z)); 13039566063dSJacob Faibussowitsch PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_FALSE)); 13043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1305414bd5c3SStefano Zampini } 1306414bd5c3SStefano Zampini 1307d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTransposeAdd_HYPRE(Mat A, Vec x, Vec y, Vec z) 1308d71ae5a4SJacob Faibussowitsch { 1309414bd5c3SStefano Zampini PetscFunctionBegin; 131048a46eb9SPierre Jolivet if (y != z) PetscCall(VecCopy(y, z)); 13119566063dSJacob Faibussowitsch PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_TRUE)); 13123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1313414bd5c3SStefano Zampini } 1314414bd5c3SStefano Zampini 1315414bd5c3SStefano Zampini /* y = a * A * x + b * y or y = a * A^t * x + b * y depending on trans */ 1316d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_MultKernel_Private(Mat A, HYPRE_Complex a, Vec x, HYPRE_Complex b, Vec y, PetscBool trans) 1317d71ae5a4SJacob Faibussowitsch { 131863c07aadSStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 131963c07aadSStefano Zampini hypre_ParCSRMatrix *parcsr; 132063c07aadSStefano Zampini hypre_ParVector *hx, *hy; 132163c07aadSStefano Zampini 132263c07aadSStefano Zampini PetscFunctionBegin; 132363c07aadSStefano Zampini if (trans) { 13249566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorPushVecRead(hA->b, x)); 13259566063dSJacob Faibussowitsch if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->x, y)); 13269566063dSJacob Faibussowitsch else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->x, y)); 1327792fecdfSBarry Smith PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hx); 1328792fecdfSBarry Smith PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hy); 132963c07aadSStefano Zampini } else { 13309566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorPushVecRead(hA->x, x)); 13319566063dSJacob Faibussowitsch if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->b, y)); 13329566063dSJacob Faibussowitsch else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->b, y)); 1333792fecdfSBarry Smith PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hx); 1334792fecdfSBarry Smith PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hy); 133563c07aadSStefano Zampini } 1336792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr); 13376ea7df73SStefano Zampini if (trans) { 1338792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixMatvecT, a, parcsr, hx, b, hy); 13396ea7df73SStefano Zampini } else { 1340792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixMatvec, a, parcsr, hx, b, hy); 13416ea7df73SStefano Zampini } 13429566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorPopVec(hA->x)); 13439566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorPopVec(hA->b)); 13443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 134563c07aadSStefano Zampini } 134663c07aadSStefano Zampini 1347d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_HYPRE(Mat A) 1348d71ae5a4SJacob Faibussowitsch { 134963c07aadSStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 135063c07aadSStefano Zampini 135163c07aadSStefano Zampini PetscFunctionBegin; 13529566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorDestroy(&hA->x)); 13539566063dSJacob Faibussowitsch PetscCall(VecHYPRE_IJVectorDestroy(&hA->b)); 1354*06977982Sstefanozampini PetscCall(MatHYPRE_DestroyCOOMat(A)); /* must be called before destroying the individual CSR */ 1355978814f1SStefano Zampini if (hA->ij) { 1356978814f1SStefano Zampini if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL; 1357792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixDestroy, hA->ij); 1358978814f1SStefano Zampini } 13599566063dSJacob Faibussowitsch if (hA->comm) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)A), &hA->comm)); 1360c69f721fSFande Kong 13619566063dSJacob Faibussowitsch PetscCall(MatStashDestroy_Private(&A->stash)); 13629566063dSJacob Faibussowitsch PetscCall(PetscFree(hA->array)); 1363c69f721fSFande Kong 13649566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_aij_C", NULL)); 13659566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_is_C", NULL)); 13669566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_hypre_C", NULL)); 13679566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaij_hypre_C", NULL)); 1368*06977982Sstefanozampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijhipsparse_hypre_C", NULL)); 1369*06977982Sstefanozampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaijhipsparse_hypre_C", NULL)); 1370*06977982Sstefanozampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijcusparse_hypre_C", NULL)); 1371*06977982Sstefanozampini PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaijcusparse_hypre_C", NULL)); 13729566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPRESetPreallocation_C", NULL)); 13739566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPREGetParCSR_C", NULL)); 13745fbaff96SJunchao Zhang PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL)); 13755fbaff96SJunchao Zhang PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL)); 13769566063dSJacob Faibussowitsch PetscCall(PetscFree(A->data)); 13773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 137863c07aadSStefano Zampini } 137963c07aadSStefano Zampini 1380d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetUp_HYPRE(Mat A) 1381d71ae5a4SJacob Faibussowitsch { 13824ec6421dSstefano_zampini PetscFunctionBegin; 1383*06977982Sstefanozampini if (!A->preallocated) PetscCall(MatHYPRESetPreallocation(A, PETSC_DEFAULT, NULL, PETSC_DEFAULT, NULL)); 13843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13854ec6421dSstefano_zampini } 13864ec6421dSstefano_zampini 13876ea7df73SStefano Zampini //TODO FIX hypre_CSRMatrixMatvecOutOfPlace 13886ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 1389d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatBindToCPU_HYPRE(Mat A, PetscBool bind) 1390d71ae5a4SJacob Faibussowitsch { 13916ea7df73SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 13926ea7df73SStefano Zampini HYPRE_MemoryLocation hmem = bind ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE; 13936ea7df73SStefano Zampini 13946ea7df73SStefano Zampini PetscFunctionBegin; 13956ea7df73SStefano Zampini A->boundtocpu = bind; 13965fbaff96SJunchao Zhang if (hA->ij && hypre_IJMatrixAssembleFlag(hA->ij) && hmem != hypre_IJMatrixMemoryLocation(hA->ij)) { 13976ea7df73SStefano Zampini hypre_ParCSRMatrix *parcsr; 1398792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr); 1399792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixMigrate, parcsr, hmem); 14006ea7df73SStefano Zampini } 14019566063dSJacob Faibussowitsch if (hA->x) PetscCall(VecHYPRE_IJBindToCPU(hA->x, bind)); 14029566063dSJacob Faibussowitsch if (hA->b) PetscCall(VecHYPRE_IJBindToCPU(hA->b, bind)); 14033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14046ea7df73SStefano Zampini } 14056ea7df73SStefano Zampini #endif 14066ea7df73SStefano Zampini 1407d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_HYPRE(Mat A, MatAssemblyType mode) 1408d71ae5a4SJacob Faibussowitsch { 140963c07aadSStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1410c69f721fSFande Kong PetscMPIInt n; 1411c69f721fSFande Kong PetscInt i, j, rstart, ncols, flg; 1412c69f721fSFande Kong PetscInt *row, *col; 1413c69f721fSFande Kong PetscScalar *val; 141463c07aadSStefano Zampini 141563c07aadSStefano Zampini PetscFunctionBegin; 141608401ef6SPierre Jolivet PetscCheck(mode != MAT_FLUSH_ASSEMBLY, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_FLUSH_ASSEMBLY currently not supported with MATHYPRE"); 1417c69f721fSFande Kong 1418c69f721fSFande Kong if (!A->nooffprocentries) { 1419c69f721fSFande Kong while (1) { 14209566063dSJacob Faibussowitsch PetscCall(MatStashScatterGetMesg_Private(&A->stash, &n, &row, &col, &val, &flg)); 1421c69f721fSFande Kong if (!flg) break; 1422c69f721fSFande Kong 1423c69f721fSFande Kong for (i = 0; i < n;) { 1424c69f721fSFande Kong /* Now identify the consecutive vals belonging to the same row */ 1425c69f721fSFande Kong for (j = i, rstart = row[j]; j < n; j++) { 1426c69f721fSFande Kong if (row[j] != rstart) break; 1427c69f721fSFande Kong } 1428c69f721fSFande Kong if (j < n) ncols = j - i; 1429c69f721fSFande Kong else ncols = n - i; 1430c69f721fSFande Kong /* Now assemble all these values with a single function call */ 14319566063dSJacob Faibussowitsch PetscCall(MatSetValues_HYPRE(A, 1, row + i, ncols, col + i, val + i, A->insertmode)); 1432c69f721fSFande Kong 1433c69f721fSFande Kong i = j; 1434c69f721fSFande Kong } 1435c69f721fSFande Kong } 14369566063dSJacob Faibussowitsch PetscCall(MatStashScatterEnd_Private(&A->stash)); 1437c69f721fSFande Kong } 1438c69f721fSFande Kong 1439792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixAssemble, hA->ij); 1440336664bdSPierre Jolivet /* The assembly routine destroys the aux_matrix, we recreate it here by calling HYPRE_IJMatrixInitialize */ 1441336664bdSPierre 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 */ 1442651b1cf9SStefano Zampini if (!A->sortedfull) { 1443af1cf968SStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 1444af1cf968SStefano Zampini 1445af1cf968SStefano Zampini /* call destroy just to make sure we do not leak anything */ 1446af1cf968SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij); 1447792fecdfSBarry Smith PetscCallExternal(hypre_AuxParCSRMatrixDestroy, aux_matrix); 1448af1cf968SStefano Zampini hypre_IJMatrixTranslator(hA->ij) = NULL; 1449af1cf968SStefano Zampini 1450af1cf968SStefano Zampini /* Initialize with assembled flag -> it only recreates the aux_par_matrix */ 1451792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij); 1452af1cf968SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij); 14536ea7df73SStefano Zampini if (aux_matrix) { 1454af1cf968SStefano Zampini hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1; /* see comment in MatHYPRESetPreallocation_HYPRE */ 145522235d61SPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 1456792fecdfSBarry Smith PetscCallExternal(hypre_AuxParCSRMatrixInitialize, aux_matrix); 145722235d61SPierre Jolivet #else 1458792fecdfSBarry Smith PetscCallExternal(hypre_AuxParCSRMatrixInitialize_v2, aux_matrix, HYPRE_MEMORY_HOST); 145922235d61SPierre Jolivet #endif 1460af1cf968SStefano Zampini } 14616ea7df73SStefano Zampini } 14626ea7df73SStefano Zampini { 14636ea7df73SStefano Zampini hypre_ParCSRMatrix *parcsr; 14646ea7df73SStefano Zampini 1465792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr); 1466792fecdfSBarry Smith if (!hypre_ParCSRMatrixCommPkg(parcsr)) PetscCallExternal(hypre_MatvecCommPkgCreate, parcsr); 14676ea7df73SStefano Zampini } 14689566063dSJacob Faibussowitsch if (!hA->x) PetscCall(VecHYPRE_IJVectorCreate(A->cmap, &hA->x)); 14699566063dSJacob Faibussowitsch if (!hA->b) PetscCall(VecHYPRE_IJVectorCreate(A->rmap, &hA->b)); 14706ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 14719566063dSJacob Faibussowitsch PetscCall(MatBindToCPU_HYPRE(A, A->boundtocpu)); 14726ea7df73SStefano Zampini #endif 14733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 147463c07aadSStefano Zampini } 147563c07aadSStefano Zampini 1476d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetArray_HYPRE(Mat A, PetscInt size, void **array) 1477d71ae5a4SJacob Faibussowitsch { 1478c69f721fSFande Kong Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1479c69f721fSFande Kong 1480c69f721fSFande Kong PetscFunctionBegin; 1481651b1cf9SStefano Zampini PetscCheck(hA->array_available, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Temporary space is in use"); 1482c69f721fSFande Kong 1483651b1cf9SStefano Zampini if (hA->array_size >= size) { 148439accc25SStefano Zampini *array = hA->array; 148539accc25SStefano Zampini } else { 14869566063dSJacob Faibussowitsch PetscCall(PetscFree(hA->array)); 1487651b1cf9SStefano Zampini hA->array_size = size; 1488651b1cf9SStefano Zampini PetscCall(PetscMalloc(hA->array_size, &hA->array)); 1489c69f721fSFande Kong *array = hA->array; 1490c69f721fSFande Kong } 1491c69f721fSFande Kong 1492651b1cf9SStefano Zampini hA->array_available = PETSC_FALSE; 14933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1494c69f721fSFande Kong } 1495c69f721fSFande Kong 1496d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreArray_HYPRE(Mat A, void **array) 1497d71ae5a4SJacob Faibussowitsch { 1498c69f721fSFande Kong Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1499c69f721fSFande Kong 1500c69f721fSFande Kong PetscFunctionBegin; 1501c69f721fSFande Kong *array = NULL; 1502651b1cf9SStefano Zampini hA->array_available = PETSC_TRUE; 15033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1504c69f721fSFande Kong } 1505c69f721fSFande Kong 1506d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_HYPRE(Mat A, PetscInt nr, const PetscInt rows[], PetscInt nc, const PetscInt cols[], const PetscScalar v[], InsertMode ins) 1507d71ae5a4SJacob Faibussowitsch { 1508d975228cSstefano_zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1509d975228cSstefano_zampini PetscScalar *vals = (PetscScalar *)v; 151039accc25SStefano Zampini HYPRE_Complex *sscr; 1511c69f721fSFande Kong PetscInt *cscr[2]; 1512c69f721fSFande Kong PetscInt i, nzc; 1513651b1cf9SStefano Zampini PetscInt rst = A->rmap->rstart, ren = A->rmap->rend; 151408defe43SFande Kong void *array = NULL; 1515d975228cSstefano_zampini 1516d975228cSstefano_zampini PetscFunctionBegin; 15179566063dSJacob Faibussowitsch PetscCall(MatGetArray_HYPRE(A, sizeof(PetscInt) * (2 * nc) + sizeof(HYPRE_Complex) * nc * nr, &array)); 1518c69f721fSFande Kong cscr[0] = (PetscInt *)array; 1519c69f721fSFande Kong cscr[1] = ((PetscInt *)array) + nc; 152039accc25SStefano Zampini sscr = (HYPRE_Complex *)(((PetscInt *)array) + nc * 2); 1521d975228cSstefano_zampini for (i = 0, nzc = 0; i < nc; i++) { 1522d975228cSstefano_zampini if (cols[i] >= 0) { 1523d975228cSstefano_zampini cscr[0][nzc] = cols[i]; 1524d975228cSstefano_zampini cscr[1][nzc++] = i; 1525d975228cSstefano_zampini } 1526d975228cSstefano_zampini } 1527c69f721fSFande Kong if (!nzc) { 15289566063dSJacob Faibussowitsch PetscCall(MatRestoreArray_HYPRE(A, &array)); 15293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1530c69f721fSFande Kong } 1531d975228cSstefano_zampini 15326ea7df73SStefano Zampini #if 0 //defined(PETSC_HAVE_HYPRE_DEVICE) 15336ea7df73SStefano Zampini if (HYPRE_MEMORY_HOST != hypre_IJMatrixMemoryLocation(hA->ij)) { 15346ea7df73SStefano Zampini hypre_ParCSRMatrix *parcsr; 15356ea7df73SStefano Zampini 1536792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject,hA->ij,(void**)&parcsr); 1537792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixMigrate,parcsr, HYPRE_MEMORY_HOST); 15386ea7df73SStefano Zampini } 15396ea7df73SStefano Zampini #endif 15406ea7df73SStefano Zampini 1541d975228cSstefano_zampini if (ins == ADD_VALUES) { 1542d975228cSstefano_zampini for (i = 0; i < nr; i++) { 15436ea7df73SStefano Zampini if (rows[i] >= 0) { 1544d975228cSstefano_zampini PetscInt j; 15452cf14000SStefano Zampini HYPRE_Int hnc = (HYPRE_Int)nzc; 15462cf14000SStefano Zampini 1547651b1cf9SStefano Zampini if (!nzc) continue; 1548651b1cf9SStefano Zampini /* nonlocal values */ 1549651b1cf9SStefano Zampini if (rows[i] < rst || rows[i] >= ren) { 1550651b1cf9SStefano Zampini PetscCheck(!A->nooffprocentries, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Setting off process row %" PetscInt_FMT " even though MatSetOption(,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE) was set", rows[i]); 1551651b1cf9SStefano Zampini if (hA->donotstash) continue; 1552651b1cf9SStefano Zampini } 1553aed4548fSBarry 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]); 15549566063dSJacob Faibussowitsch for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j])); 1555792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixAddToValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr); 1556d975228cSstefano_zampini } 1557d975228cSstefano_zampini vals += nc; 1558d975228cSstefano_zampini } 1559d975228cSstefano_zampini } else { /* INSERT_VALUES */ 1560d975228cSstefano_zampini for (i = 0; i < nr; i++) { 15616ea7df73SStefano Zampini if (rows[i] >= 0) { 1562d975228cSstefano_zampini PetscInt j; 15632cf14000SStefano Zampini HYPRE_Int hnc = (HYPRE_Int)nzc; 15642cf14000SStefano Zampini 1565651b1cf9SStefano Zampini if (!nzc) continue; 1566aed4548fSBarry 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]); 15679566063dSJacob Faibussowitsch for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j])); 1568c69f721fSFande Kong /* nonlocal values */ 1569651b1cf9SStefano Zampini if (rows[i] < rst || rows[i] >= ren) { 1570651b1cf9SStefano Zampini PetscCheck(!A->nooffprocentries, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Setting off process row %" PetscInt_FMT " even though MatSetOption(,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE) was set", rows[i]); 1571651b1cf9SStefano Zampini if (!hA->donotstash) PetscCall(MatStashValuesRow_Private(&A->stash, rows[i], nzc, cscr[0], (PetscScalar *)sscr, PETSC_FALSE)); 1572651b1cf9SStefano Zampini } 1573c69f721fSFande Kong /* local values */ 1574651b1cf9SStefano Zampini else 1575651b1cf9SStefano Zampini PetscCallExternal(HYPRE_IJMatrixSetValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr); 1576d975228cSstefano_zampini } 1577d975228cSstefano_zampini vals += nc; 1578d975228cSstefano_zampini } 1579d975228cSstefano_zampini } 1580c69f721fSFande Kong 15819566063dSJacob Faibussowitsch PetscCall(MatRestoreArray_HYPRE(A, &array)); 15823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1583d975228cSstefano_zampini } 1584d975228cSstefano_zampini 1585d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRESetPreallocation_HYPRE(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[]) 1586d71ae5a4SJacob Faibussowitsch { 1587d975228cSstefano_zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 15887d968826Sstefano_zampini HYPRE_Int *hdnnz, *honnz; 158906a29025Sstefano_zampini PetscInt i, rs, re, cs, ce, bs; 1590d975228cSstefano_zampini PetscMPIInt size; 1591d975228cSstefano_zampini 1592d975228cSstefano_zampini PetscFunctionBegin; 15939566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->rmap)); 15949566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(A->cmap)); 1595d975228cSstefano_zampini rs = A->rmap->rstart; 1596d975228cSstefano_zampini re = A->rmap->rend; 1597d975228cSstefano_zampini cs = A->cmap->rstart; 1598d975228cSstefano_zampini ce = A->cmap->rend; 1599d975228cSstefano_zampini if (!hA->ij) { 1600792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rs, re - 1, cs, ce - 1, &hA->ij); 1601792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR); 1602d975228cSstefano_zampini } else { 16032cf14000SStefano Zampini HYPRE_BigInt hrs, hre, hcs, hce; 1604792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetLocalRange, hA->ij, &hrs, &hre, &hcs, &hce); 1605aed4548fSBarry 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); 1606aed4548fSBarry 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); 1607d975228cSstefano_zampini } 1608*06977982Sstefanozampini PetscCall(MatHYPRE_DestroyCOOMat(A)); 16099566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(A, &bs)); 161006a29025Sstefano_zampini if (dnz == PETSC_DEFAULT || dnz == PETSC_DECIDE) dnz = 10 * bs; 161106a29025Sstefano_zampini if (onz == PETSC_DEFAULT || onz == PETSC_DECIDE) onz = 10 * bs; 161206a29025Sstefano_zampini 1613d975228cSstefano_zampini if (!dnnz) { 16149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n, &hdnnz)); 1615d975228cSstefano_zampini for (i = 0; i < A->rmap->n; i++) hdnnz[i] = dnz; 1616d975228cSstefano_zampini } else { 16177d968826Sstefano_zampini hdnnz = (HYPRE_Int *)dnnz; 1618d975228cSstefano_zampini } 16199566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 1620d975228cSstefano_zampini if (size > 1) { 1621ddbeb582SStefano Zampini hypre_AuxParCSRMatrix *aux_matrix; 1622d975228cSstefano_zampini if (!onnz) { 16239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(A->rmap->n, &honnz)); 1624d975228cSstefano_zampini for (i = 0; i < A->rmap->n; i++) honnz[i] = onz; 162522235d61SPierre Jolivet } else honnz = (HYPRE_Int *)onnz; 1626ddbeb582SStefano Zampini /* SetDiagOffdSizes sets hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0, since it seems 1627ddbeb582SStefano Zampini they assume the user will input the entire row values, properly sorted 1628336664bdSPierre Jolivet In PETSc, we don't make such an assumption and set this flag to 1, 1629336664bdSPierre Jolivet unless the option MAT_SORTED_FULL is set to true. 1630ddbeb582SStefano Zampini Also, to avoid possible memory leaks, we destroy and recreate the translator 1631ddbeb582SStefano Zampini This has to be done here, as HYPRE_IJMatrixInitialize will properly initialize 1632ddbeb582SStefano Zampini the IJ matrix for us */ 1633ddbeb582SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij); 1634ddbeb582SStefano Zampini hypre_AuxParCSRMatrixDestroy(aux_matrix); 1635ddbeb582SStefano Zampini hypre_IJMatrixTranslator(hA->ij) = NULL; 1636792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, hA->ij, hdnnz, honnz); 1637ddbeb582SStefano Zampini aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij); 1638651b1cf9SStefano Zampini hypre_AuxParCSRMatrixNeedAux(aux_matrix) = !A->sortedfull; 1639d975228cSstefano_zampini } else { 1640d975228cSstefano_zampini honnz = NULL; 1641792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetRowSizes, hA->ij, hdnnz); 1642d975228cSstefano_zampini } 1643ddbeb582SStefano Zampini 1644af1cf968SStefano Zampini /* reset assembled flag and call the initialize method */ 1645af1cf968SStefano Zampini hypre_IJMatrixAssembleFlag(hA->ij) = 0; 16466ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 1647792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij); 16486ea7df73SStefano Zampini #else 1649792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize_v2, hA->ij, HYPRE_MEMORY_HOST); 16506ea7df73SStefano Zampini #endif 165148a46eb9SPierre Jolivet if (!dnnz) PetscCall(PetscFree(hdnnz)); 165248a46eb9SPierre Jolivet if (!onnz && honnz) PetscCall(PetscFree(honnz)); 1653af1cf968SStefano Zampini /* Match AIJ logic */ 165406a29025Sstefano_zampini A->preallocated = PETSC_TRUE; 1655af1cf968SStefano Zampini A->assembled = PETSC_FALSE; 16563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1657d975228cSstefano_zampini } 1658d975228cSstefano_zampini 1659d975228cSstefano_zampini /*@C 1660d975228cSstefano_zampini MatHYPRESetPreallocation - Preallocates memory for a sparse parallel matrix in HYPRE IJ format 1661d975228cSstefano_zampini 1662c3339decSBarry Smith Collective 1663d975228cSstefano_zampini 1664d975228cSstefano_zampini Input Parameters: 1665d975228cSstefano_zampini + A - the matrix 1666d975228cSstefano_zampini . dnz - number of nonzeros per row in DIAGONAL portion of local submatrix 1667d975228cSstefano_zampini (same value is used for all local rows) 1668d975228cSstefano_zampini . dnnz - array containing the number of nonzeros in the various rows of the 1669d975228cSstefano_zampini DIAGONAL portion of the local submatrix (possibly different for each row) 16702ef1f0ffSBarry Smith or `NULL` (`PETSC_NULL_INTEGER` in Fortran), if `d_nz` is used to specify the nonzero structure. 16712ef1f0ffSBarry Smith The size of this array is equal to the number of local rows, i.e `m`. 1672d975228cSstefano_zampini For matrices that will be factored, you must leave room for (and set) 1673d975228cSstefano_zampini the diagonal entry even if it is zero. 1674d975228cSstefano_zampini . onz - number of nonzeros per row in the OFF-DIAGONAL portion of local 1675d975228cSstefano_zampini submatrix (same value is used for all local rows). 1676d975228cSstefano_zampini - onnz - array containing the number of nonzeros in the various rows of the 1677d975228cSstefano_zampini OFF-DIAGONAL portion of the local submatrix (possibly different for 16782ef1f0ffSBarry Smith each row) or `NULL` (`PETSC_NULL_INTEGER` in Fortran), if `o_nz` is used to specify the nonzero 1679d975228cSstefano_zampini structure. The size of this array is equal to the number 16802ef1f0ffSBarry Smith of local rows, i.e `m`. 1681d975228cSstefano_zampini 16822fe279fdSBarry Smith Level: intermediate 16832fe279fdSBarry Smith 168411a5261eSBarry Smith Note: 16852ef1f0ffSBarry Smith If the *nnz parameter is given then the *nz parameter is ignored; for sequential matrices, `onz` and `onnz` are ignored. 1686d975228cSstefano_zampini 16871cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatMPIAIJSetPreallocation()`, `MATHYPRE`, `MATAIJ` 1688d975228cSstefano_zampini @*/ 1689d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHYPRESetPreallocation(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[]) 1690d71ae5a4SJacob Faibussowitsch { 1691d975228cSstefano_zampini PetscFunctionBegin; 1692d975228cSstefano_zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1693d975228cSstefano_zampini PetscValidType(A, 1); 1694cac4c232SBarry Smith PetscTryMethod(A, "MatHYPRESetPreallocation_C", (Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]), (A, dnz, dnnz, onz, onnz)); 16953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1696d975228cSstefano_zampini } 1697d975228cSstefano_zampini 169820f4b53cSBarry Smith /*@C 16992ef1f0ffSBarry Smith MatCreateFromParCSR - Creates a `Mat` from a `hypre_ParCSRMatrix` 1700225daaf8SStefano Zampini 1701225daaf8SStefano Zampini Collective 1702225daaf8SStefano Zampini 1703225daaf8SStefano Zampini Input Parameters: 17042ef1f0ffSBarry Smith + parcsr - the pointer to the `hypre_ParCSRMatrix` 17052ef1f0ffSBarry Smith . mtype - matrix type to be created. Currently `MATAIJ`, `MATIS` and `MATHYPRE` are supported. 170620f4b53cSBarry Smith - copymode - PETSc copying options, see `PetscCopyMode` 1707225daaf8SStefano Zampini 1708225daaf8SStefano Zampini Output Parameter: 1709225daaf8SStefano Zampini . A - the matrix 1710225daaf8SStefano Zampini 1711225daaf8SStefano Zampini Level: intermediate 1712225daaf8SStefano Zampini 17131cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatHYPRE`, `PetscCopyMode` 171420f4b53cSBarry Smith @*/ 1715d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreateFromParCSR(hypre_ParCSRMatrix *parcsr, MatType mtype, PetscCopyMode copymode, Mat *A) 1716d71ae5a4SJacob Faibussowitsch { 1717225daaf8SStefano Zampini Mat T; 1718978814f1SStefano Zampini Mat_HYPRE *hA; 1719978814f1SStefano Zampini MPI_Comm comm; 1720978814f1SStefano Zampini PetscInt rstart, rend, cstart, cend, M, N; 1721d248a85cSRichard Tran Mills PetscBool isseqaij, isseqaijmkl, ismpiaij, isaij, ishyp, isis; 1722978814f1SStefano Zampini 1723978814f1SStefano Zampini PetscFunctionBegin; 1724978814f1SStefano Zampini comm = hypre_ParCSRMatrixComm(parcsr); 17259566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQAIJ, &isseqaij)); 17269566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATSEQAIJMKL, &isseqaijmkl)); 17279566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATMPIAIJ, &ismpiaij)); 17289566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATAIJ, &isaij)); 17299566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATHYPRE, &ishyp)); 17309566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mtype, MATIS, &isis)); 1731d248a85cSRichard Tran Mills isaij = (PetscBool)(isseqaij || isseqaijmkl || ismpiaij || isaij); 17326ea7df73SStefano Zampini /* TODO */ 1733aed4548fSBarry 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); 1734978814f1SStefano Zampini /* access ParCSRMatrix */ 1735978814f1SStefano Zampini rstart = hypre_ParCSRMatrixFirstRowIndex(parcsr); 1736978814f1SStefano Zampini rend = hypre_ParCSRMatrixLastRowIndex(parcsr); 1737978814f1SStefano Zampini cstart = hypre_ParCSRMatrixFirstColDiag(parcsr); 1738978814f1SStefano Zampini cend = hypre_ParCSRMatrixLastColDiag(parcsr); 1739978814f1SStefano Zampini M = hypre_ParCSRMatrixGlobalNumRows(parcsr); 1740978814f1SStefano Zampini N = hypre_ParCSRMatrixGlobalNumCols(parcsr); 1741978814f1SStefano Zampini 1742fa92c42cSstefano_zampini /* fix for empty local rows/columns */ 1743fa92c42cSstefano_zampini if (rend < rstart) rend = rstart; 1744fa92c42cSstefano_zampini if (cend < cstart) cend = cstart; 1745fa92c42cSstefano_zampini 1746e6471dc9SStefano Zampini /* PETSc convention */ 1747e6471dc9SStefano Zampini rend++; 1748e6471dc9SStefano Zampini cend++; 1749e6471dc9SStefano Zampini rend = PetscMin(rend, M); 1750e6471dc9SStefano Zampini cend = PetscMin(cend, N); 1751e6471dc9SStefano Zampini 1752978814f1SStefano Zampini /* create PETSc matrix with MatHYPRE */ 17539566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &T)); 17549566063dSJacob Faibussowitsch PetscCall(MatSetSizes(T, rend - rstart, cend - cstart, M, N)); 17559566063dSJacob Faibussowitsch PetscCall(MatSetType(T, MATHYPRE)); 1756225daaf8SStefano Zampini hA = (Mat_HYPRE *)(T->data); 1757978814f1SStefano Zampini 1758978814f1SStefano Zampini /* create HYPRE_IJMatrix */ 1759792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rstart, rend - 1, cstart, cend - 1, &hA->ij); 1760792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR); 176145b8d346SStefano Zampini 176245b8d346SStefano Zampini /* create new ParCSR object if needed */ 176345b8d346SStefano Zampini if (ishyp && copymode == PETSC_COPY_VALUES) { 176445b8d346SStefano Zampini hypre_ParCSRMatrix *new_parcsr; 17656ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0) 176645b8d346SStefano Zampini hypre_CSRMatrix *hdiag, *hoffd, *ndiag, *noffd; 176745b8d346SStefano Zampini 17680e6427aaSSatish Balay new_parcsr = hypre_ParCSRMatrixClone(parcsr, 0); 176945b8d346SStefano Zampini hdiag = hypre_ParCSRMatrixDiag(parcsr); 177045b8d346SStefano Zampini hoffd = hypre_ParCSRMatrixOffd(parcsr); 177145b8d346SStefano Zampini ndiag = hypre_ParCSRMatrixDiag(new_parcsr); 177245b8d346SStefano Zampini noffd = hypre_ParCSRMatrixOffd(new_parcsr); 17739566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hypre_CSRMatrixData(ndiag), hypre_CSRMatrixData(hdiag), hypre_CSRMatrixNumNonzeros(hdiag))); 17749566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(hypre_CSRMatrixData(noffd), hypre_CSRMatrixData(hoffd), hypre_CSRMatrixNumNonzeros(hoffd))); 17756ea7df73SStefano Zampini #else 17766ea7df73SStefano Zampini new_parcsr = hypre_ParCSRMatrixClone(parcsr, 1); 17776ea7df73SStefano Zampini #endif 177845b8d346SStefano Zampini parcsr = new_parcsr; 177945b8d346SStefano Zampini copymode = PETSC_OWN_POINTER; 178045b8d346SStefano Zampini } 1781978814f1SStefano Zampini 1782978814f1SStefano Zampini /* set ParCSR object */ 1783978814f1SStefano Zampini hypre_IJMatrixObject(hA->ij) = parcsr; 17844ec6421dSstefano_zampini T->preallocated = PETSC_TRUE; 1785978814f1SStefano Zampini 1786978814f1SStefano Zampini /* set assembled flag */ 1787978814f1SStefano Zampini hypre_IJMatrixAssembleFlag(hA->ij) = 1; 17886ea7df73SStefano Zampini #if 0 1789792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixInitialize,hA->ij); 17906ea7df73SStefano Zampini #endif 1791225daaf8SStefano Zampini if (ishyp) { 17926d2a658fSstefano_zampini PetscMPIInt myid = 0; 17936d2a658fSstefano_zampini 17946d2a658fSstefano_zampini /* make sure we always have row_starts and col_starts available */ 179548a46eb9SPierre Jolivet if (HYPRE_AssumedPartitionCheck()) PetscCallMPI(MPI_Comm_rank(comm, &myid)); 1796a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts) 17976d2a658fSstefano_zampini if (!hypre_ParCSRMatrixOwnsColStarts(parcsr)) { 17986d2a658fSstefano_zampini PetscLayout map; 17996d2a658fSstefano_zampini 18009566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(T, NULL, &map)); 18019566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(map)); 18022cf14000SStefano Zampini hypre_ParCSRMatrixColStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid); 18036d2a658fSstefano_zampini } 18046d2a658fSstefano_zampini if (!hypre_ParCSRMatrixOwnsRowStarts(parcsr)) { 18056d2a658fSstefano_zampini PetscLayout map; 18066d2a658fSstefano_zampini 18079566063dSJacob Faibussowitsch PetscCall(MatGetLayouts(T, &map, NULL)); 18089566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(map)); 18092cf14000SStefano Zampini hypre_ParCSRMatrixRowStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid); 18106d2a658fSstefano_zampini } 1811a1d2239cSSatish Balay #endif 1812978814f1SStefano Zampini /* prevent from freeing the pointer */ 1813978814f1SStefano Zampini if (copymode == PETSC_USE_POINTER) hA->inner_free = PETSC_FALSE; 1814225daaf8SStefano Zampini *A = T; 18159566063dSJacob Faibussowitsch PetscCall(MatSetOption(*A, MAT_SORTED_FULL, PETSC_TRUE)); 18169566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(*A, MAT_FINAL_ASSEMBLY)); 18179566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(*A, MAT_FINAL_ASSEMBLY)); 1818bb4689ddSStefano Zampini } else if (isaij) { 1819bb4689ddSStefano Zampini if (copymode != PETSC_OWN_POINTER) { 1820225daaf8SStefano Zampini /* prevent from freeing the pointer */ 1821225daaf8SStefano Zampini hA->inner_free = PETSC_FALSE; 18229566063dSJacob Faibussowitsch PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INITIAL_MATRIX, A)); 18239566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 1824225daaf8SStefano Zampini } else { /* AIJ return type with PETSC_OWN_POINTER */ 18259566063dSJacob Faibussowitsch PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INPLACE_MATRIX, &T)); 1826225daaf8SStefano Zampini *A = T; 1827225daaf8SStefano Zampini } 1828bb4689ddSStefano Zampini } else if (isis) { 18299566063dSJacob Faibussowitsch PetscCall(MatConvert_HYPRE_IS(T, MATIS, MAT_INITIAL_MATRIX, A)); 18308cfe8d00SStefano Zampini if (copymode != PETSC_OWN_POINTER) hA->inner_free = PETSC_FALSE; 18319566063dSJacob Faibussowitsch PetscCall(MatDestroy(&T)); 1832bb4689ddSStefano Zampini } 18333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1834978814f1SStefano Zampini } 1835978814f1SStefano Zampini 1836d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPREGetParCSR_HYPRE(Mat A, hypre_ParCSRMatrix **parcsr) 1837d71ae5a4SJacob Faibussowitsch { 1838dd9c0a25Sstefano_zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 1839dd9c0a25Sstefano_zampini HYPRE_Int type; 1840dd9c0a25Sstefano_zampini 1841dd9c0a25Sstefano_zampini PetscFunctionBegin; 184228b400f6SJacob Faibussowitsch PetscCheck(hA->ij, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "HYPRE_IJMatrix not present"); 1843792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type); 184408401ef6SPierre Jolivet PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "HYPRE_IJMatrix is not of type HYPRE_PARCSR"); 1845792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)parcsr); 18463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1847dd9c0a25Sstefano_zampini } 1848dd9c0a25Sstefano_zampini 184920f4b53cSBarry Smith /*@C 1850dd9c0a25Sstefano_zampini MatHYPREGetParCSR - Gets the pointer to the ParCSR matrix 1851dd9c0a25Sstefano_zampini 18522ef1f0ffSBarry Smith Not Collective 1853dd9c0a25Sstefano_zampini 185420f4b53cSBarry Smith Input Parameter: 185520f4b53cSBarry Smith . A - the `MATHYPRE` object 1856dd9c0a25Sstefano_zampini 1857dd9c0a25Sstefano_zampini Output Parameter: 18582ef1f0ffSBarry Smith . parcsr - the pointer to the `hypre_ParCSRMatrix` 1859dd9c0a25Sstefano_zampini 1860dd9c0a25Sstefano_zampini Level: intermediate 1861dd9c0a25Sstefano_zampini 18621cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatHYPRE`, `PetscCopyMode` 186320f4b53cSBarry Smith @*/ 1864d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHYPREGetParCSR(Mat A, hypre_ParCSRMatrix **parcsr) 1865d71ae5a4SJacob Faibussowitsch { 1866dd9c0a25Sstefano_zampini PetscFunctionBegin; 1867dd9c0a25Sstefano_zampini PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1868dd9c0a25Sstefano_zampini PetscValidType(A, 1); 1869cac4c232SBarry Smith PetscUseMethod(A, "MatHYPREGetParCSR_C", (Mat, hypre_ParCSRMatrix **), (A, parcsr)); 18703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1871dd9c0a25Sstefano_zampini } 1872dd9c0a25Sstefano_zampini 1873d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_HYPRE(Mat A, PetscBool *missing, PetscInt *dd) 1874d71ae5a4SJacob Faibussowitsch { 187568ec7858SStefano Zampini hypre_ParCSRMatrix *parcsr; 187668ec7858SStefano Zampini hypre_CSRMatrix *ha; 187768ec7858SStefano Zampini PetscInt rst; 187868ec7858SStefano Zampini 187968ec7858SStefano Zampini PetscFunctionBegin; 188008401ef6SPierre Jolivet PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented with non-square diagonal blocks"); 18819566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rst, NULL)); 18829566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 188368ec7858SStefano Zampini if (missing) *missing = PETSC_FALSE; 188468ec7858SStefano Zampini if (dd) *dd = -1; 188568ec7858SStefano Zampini ha = hypre_ParCSRMatrixDiag(parcsr); 188668ec7858SStefano Zampini if (ha) { 188768299464SStefano Zampini PetscInt size, i; 188868299464SStefano Zampini HYPRE_Int *ii, *jj; 188968ec7858SStefano Zampini 189068ec7858SStefano Zampini size = hypre_CSRMatrixNumRows(ha); 189168ec7858SStefano Zampini ii = hypre_CSRMatrixI(ha); 189268ec7858SStefano Zampini jj = hypre_CSRMatrixJ(ha); 189368ec7858SStefano Zampini for (i = 0; i < size; i++) { 189468ec7858SStefano Zampini PetscInt j; 189568ec7858SStefano Zampini PetscBool found = PETSC_FALSE; 189668ec7858SStefano Zampini 18979371c9d4SSatish Balay for (j = ii[i]; j < ii[i + 1] && !found; j++) found = (jj[j] == i) ? PETSC_TRUE : PETSC_FALSE; 189868ec7858SStefano Zampini 189968ec7858SStefano Zampini if (!found) { 19003ba16761SJacob Faibussowitsch PetscCall(PetscInfo(A, "Matrix is missing local diagonal entry %" PetscInt_FMT "\n", i)); 190168ec7858SStefano Zampini if (missing) *missing = PETSC_TRUE; 190268ec7858SStefano Zampini if (dd) *dd = i + rst; 19033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 190468ec7858SStefano Zampini } 190568ec7858SStefano Zampini } 190668ec7858SStefano Zampini if (!size) { 19073ba16761SJacob Faibussowitsch PetscCall(PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n")); 190868ec7858SStefano Zampini if (missing) *missing = PETSC_TRUE; 190968ec7858SStefano Zampini if (dd) *dd = rst; 191068ec7858SStefano Zampini } 191168ec7858SStefano Zampini } else { 19123ba16761SJacob Faibussowitsch PetscCall(PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n")); 191368ec7858SStefano Zampini if (missing) *missing = PETSC_TRUE; 191468ec7858SStefano Zampini if (dd) *dd = rst; 191568ec7858SStefano Zampini } 19163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 191768ec7858SStefano Zampini } 191868ec7858SStefano Zampini 1919d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatScale_HYPRE(Mat A, PetscScalar s) 1920d71ae5a4SJacob Faibussowitsch { 192168ec7858SStefano Zampini hypre_ParCSRMatrix *parcsr; 19226ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0) 192368ec7858SStefano Zampini hypre_CSRMatrix *ha; 19246ea7df73SStefano Zampini #endif 192539accc25SStefano Zampini HYPRE_Complex hs; 192668ec7858SStefano Zampini 192768ec7858SStefano Zampini PetscFunctionBegin; 19289566063dSJacob Faibussowitsch PetscCall(PetscHYPREScalarCast(s, &hs)); 19299566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 19306ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 19, 0) 1931792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixScale, parcsr, hs); 19326ea7df73SStefano Zampini #else /* diagonal part */ 193368ec7858SStefano Zampini ha = hypre_ParCSRMatrixDiag(parcsr); 193468ec7858SStefano Zampini if (ha) { 193568299464SStefano Zampini PetscInt size, i; 193668299464SStefano Zampini HYPRE_Int *ii; 193739accc25SStefano Zampini HYPRE_Complex *a; 193868ec7858SStefano Zampini 193968ec7858SStefano Zampini size = hypre_CSRMatrixNumRows(ha); 194068ec7858SStefano Zampini a = hypre_CSRMatrixData(ha); 194168ec7858SStefano Zampini ii = hypre_CSRMatrixI(ha); 194239accc25SStefano Zampini for (i = 0; i < ii[size]; i++) a[i] *= hs; 194368ec7858SStefano Zampini } 194468ec7858SStefano Zampini /* offdiagonal part */ 194568ec7858SStefano Zampini ha = hypre_ParCSRMatrixOffd(parcsr); 194668ec7858SStefano Zampini if (ha) { 194768299464SStefano Zampini PetscInt size, i; 194868299464SStefano Zampini HYPRE_Int *ii; 194939accc25SStefano Zampini HYPRE_Complex *a; 195068ec7858SStefano Zampini 195168ec7858SStefano Zampini size = hypre_CSRMatrixNumRows(ha); 195268ec7858SStefano Zampini a = hypre_CSRMatrixData(ha); 195368ec7858SStefano Zampini ii = hypre_CSRMatrixI(ha); 195439accc25SStefano Zampini for (i = 0; i < ii[size]; i++) a[i] *= hs; 195568ec7858SStefano Zampini } 19566ea7df73SStefano Zampini #endif 19573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 195868ec7858SStefano Zampini } 195968ec7858SStefano Zampini 1960d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_HYPRE(Mat A, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 1961d71ae5a4SJacob Faibussowitsch { 196268ec7858SStefano Zampini hypre_ParCSRMatrix *parcsr; 196368299464SStefano Zampini HYPRE_Int *lrows; 196468299464SStefano Zampini PetscInt rst, ren, i; 196568ec7858SStefano Zampini 196668ec7858SStefano Zampini PetscFunctionBegin; 196708401ef6SPierre Jolivet PetscCheck(!x && !b, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "To be implemented"); 19689566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 19699566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numRows, &lrows)); 19709566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rst, &ren)); 197168ec7858SStefano Zampini for (i = 0; i < numRows; i++) { 19727a46b595SBarry Smith PetscCheck(rows[i] >= rst && rows[i] < ren, PETSC_COMM_SELF, PETSC_ERR_SUP, "Non-local rows not yet supported"); 197368ec7858SStefano Zampini lrows[i] = rows[i] - rst; 197468ec7858SStefano Zampini } 1975792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixEliminateRowsCols, parcsr, numRows, lrows); 19769566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 19773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 197868ec7858SStefano Zampini } 197968ec7858SStefano Zampini 1980d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPRE_CSRMatrix(hypre_CSRMatrix *ha) 1981d71ae5a4SJacob Faibussowitsch { 1982c69f721fSFande Kong PetscFunctionBegin; 1983c69f721fSFande Kong if (ha) { 1984c69f721fSFande Kong HYPRE_Int *ii, size; 1985c69f721fSFande Kong HYPRE_Complex *a; 1986c69f721fSFande Kong 1987c69f721fSFande Kong size = hypre_CSRMatrixNumRows(ha); 1988c69f721fSFande Kong a = hypre_CSRMatrixData(ha); 1989c69f721fSFande Kong ii = hypre_CSRMatrixI(ha); 1990c69f721fSFande Kong 19919566063dSJacob Faibussowitsch if (a) PetscCall(PetscArrayzero(a, ii[size])); 1992c69f721fSFande Kong } 19933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1994c69f721fSFande Kong } 1995c69f721fSFande Kong 1996d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroEntries_HYPRE(Mat A) 1997d71ae5a4SJacob Faibussowitsch { 19986ea7df73SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 19996ea7df73SStefano Zampini 20006ea7df73SStefano Zampini PetscFunctionBegin; 20016ea7df73SStefano Zampini if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(hA->ij)) { 2002792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixSetConstantValues, hA->ij, 0.0); 20036ea7df73SStefano Zampini } else { 2004c69f721fSFande Kong hypre_ParCSRMatrix *parcsr; 2005c69f721fSFande Kong 20069566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 20079566063dSJacob Faibussowitsch PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr))); 20089566063dSJacob Faibussowitsch PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr))); 20096ea7df73SStefano Zampini } 20103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2011c69f721fSFande Kong } 2012c69f721fSFande Kong 2013d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_HYPRE_CSRMatrix(hypre_CSRMatrix *hA, PetscInt N, const PetscInt rows[], HYPRE_Complex diag) 2014d71ae5a4SJacob Faibussowitsch { 201539accc25SStefano Zampini PetscInt ii; 201639accc25SStefano Zampini HYPRE_Int *i, *j; 201739accc25SStefano Zampini HYPRE_Complex *a; 2018c69f721fSFande Kong 2019c69f721fSFande Kong PetscFunctionBegin; 20203ba16761SJacob Faibussowitsch if (!hA) PetscFunctionReturn(PETSC_SUCCESS); 2021c69f721fSFande Kong 202239accc25SStefano Zampini i = hypre_CSRMatrixI(hA); 202339accc25SStefano Zampini j = hypre_CSRMatrixJ(hA); 2024c69f721fSFande Kong a = hypre_CSRMatrixData(hA); 2025c69f721fSFande Kong 2026c69f721fSFande Kong for (ii = 0; ii < N; ii++) { 202739accc25SStefano Zampini HYPRE_Int jj, ibeg, iend, irow; 202839accc25SStefano Zampini 2029c69f721fSFande Kong irow = rows[ii]; 2030c69f721fSFande Kong ibeg = i[irow]; 2031c69f721fSFande Kong iend = i[irow + 1]; 2032c69f721fSFande Kong for (jj = ibeg; jj < iend; jj++) 2033c69f721fSFande Kong if (j[jj] == irow) a[jj] = diag; 2034c69f721fSFande Kong else a[jj] = 0.0; 2035c69f721fSFande Kong } 20363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2037c69f721fSFande Kong } 2038c69f721fSFande Kong 2039d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_HYPRE(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 2040d71ae5a4SJacob Faibussowitsch { 2041c69f721fSFande Kong hypre_ParCSRMatrix *parcsr; 2042c69f721fSFande Kong PetscInt *lrows, len; 204339accc25SStefano Zampini HYPRE_Complex hdiag; 2044c69f721fSFande Kong 2045c69f721fSFande Kong PetscFunctionBegin; 204608401ef6SPierre Jolivet PetscCheck(!x && !b, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Does not support to modify the solution and the right hand size"); 20479566063dSJacob Faibussowitsch PetscCall(PetscHYPREScalarCast(diag, &hdiag)); 2048c69f721fSFande Kong /* retrieve the internal matrix */ 20499566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 2050c69f721fSFande Kong /* get locally owned rows */ 20519566063dSJacob Faibussowitsch PetscCall(MatZeroRowsMapLocal_Private(A, N, rows, &len, &lrows)); 2052c69f721fSFande Kong /* zero diagonal part */ 20539566063dSJacob Faibussowitsch PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr), len, lrows, hdiag)); 2054c69f721fSFande Kong /* zero off-diagonal part */ 20559566063dSJacob Faibussowitsch PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr), len, lrows, 0.0)); 2056c69f721fSFande Kong 20579566063dSJacob Faibussowitsch PetscCall(PetscFree(lrows)); 20583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2059c69f721fSFande Kong } 2060c69f721fSFande Kong 2061d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_HYPRE(Mat mat, MatAssemblyType mode) 2062d71ae5a4SJacob Faibussowitsch { 2063c69f721fSFande Kong PetscFunctionBegin; 20643ba16761SJacob Faibussowitsch if (mat->nooffprocentries) PetscFunctionReturn(PETSC_SUCCESS); 2065c69f721fSFande Kong 20669566063dSJacob Faibussowitsch PetscCall(MatStashScatterBegin_Private(mat, &mat->stash, mat->rmap->range)); 20673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2068c69f721fSFande Kong } 2069c69f721fSFande Kong 2070d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) 2071d71ae5a4SJacob Faibussowitsch { 2072c69f721fSFande Kong hypre_ParCSRMatrix *parcsr; 20732cf14000SStefano Zampini HYPRE_Int hnz; 2074c69f721fSFande Kong 2075c69f721fSFande Kong PetscFunctionBegin; 2076c69f721fSFande Kong /* retrieve the internal matrix */ 20779566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 2078c69f721fSFande Kong /* call HYPRE API */ 2079792fecdfSBarry Smith PetscCallExternal(HYPRE_ParCSRMatrixGetRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v); 20802cf14000SStefano Zampini if (nz) *nz = (PetscInt)hnz; 20813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2082c69f721fSFande Kong } 2083c69f721fSFande Kong 2084d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) 2085d71ae5a4SJacob Faibussowitsch { 2086c69f721fSFande Kong hypre_ParCSRMatrix *parcsr; 20872cf14000SStefano Zampini HYPRE_Int hnz; 2088c69f721fSFande Kong 2089c69f721fSFande Kong PetscFunctionBegin; 2090c69f721fSFande Kong /* retrieve the internal matrix */ 20919566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 2092c69f721fSFande Kong /* call HYPRE API */ 20932cf14000SStefano Zampini hnz = nz ? (HYPRE_Int)(*nz) : 0; 2094792fecdfSBarry Smith PetscCallExternal(HYPRE_ParCSRMatrixRestoreRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v); 20953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2096c69f721fSFande Kong } 2097c69f721fSFande Kong 2098d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetValues_HYPRE(Mat A, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2099d71ae5a4SJacob Faibussowitsch { 210045b8d346SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 2101c69f721fSFande Kong PetscInt i; 21021d4906efSStefano Zampini 2103c69f721fSFande Kong PetscFunctionBegin; 21043ba16761SJacob Faibussowitsch if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2105c69f721fSFande Kong /* Ignore negative row indices 2106c69f721fSFande Kong * And negative column indices should be automatically ignored in hypre 2107c69f721fSFande Kong * */ 21082cf14000SStefano Zampini for (i = 0; i < m; i++) { 21092cf14000SStefano Zampini if (idxm[i] >= 0) { 21102cf14000SStefano Zampini HYPRE_Int hn = (HYPRE_Int)n; 2111792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixGetValues, hA->ij, 1, &hn, (HYPRE_BigInt *)&idxm[i], (HYPRE_BigInt *)idxn, (HYPRE_Complex *)(v + i * n)); 21122cf14000SStefano Zampini } 21132cf14000SStefano Zampini } 21143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2115c69f721fSFande Kong } 2116c69f721fSFande Kong 2117d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_HYPRE(Mat A, MatOption op, PetscBool flg) 2118d71ae5a4SJacob Faibussowitsch { 2119ddbeb582SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 2120ddbeb582SStefano Zampini 2121ddbeb582SStefano Zampini PetscFunctionBegin; 2122c6698e78SStefano Zampini switch (op) { 2123ddbeb582SStefano Zampini case MAT_NO_OFF_PROC_ENTRIES: 212448a46eb9SPierre Jolivet if (flg) PetscCallExternal(HYPRE_IJMatrixSetMaxOffProcElmts, hA->ij, 0); 2125ddbeb582SStefano Zampini break; 2126651b1cf9SStefano Zampini case MAT_IGNORE_OFF_PROC_ENTRIES: 2127651b1cf9SStefano Zampini hA->donotstash = flg; 2128d71ae5a4SJacob Faibussowitsch break; 2129d71ae5a4SJacob Faibussowitsch default: 2130d71ae5a4SJacob Faibussowitsch break; 2131ddbeb582SStefano Zampini } 21323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2133ddbeb582SStefano Zampini } 2134c69f721fSFande Kong 2135d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_HYPRE(Mat A, PetscViewer view) 2136d71ae5a4SJacob Faibussowitsch { 213745b8d346SStefano Zampini PetscViewerFormat format; 213845b8d346SStefano Zampini 213945b8d346SStefano Zampini PetscFunctionBegin; 21409566063dSJacob Faibussowitsch PetscCall(PetscViewerGetFormat(view, &format)); 21413ba16761SJacob Faibussowitsch if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(PETSC_SUCCESS); 214245b8d346SStefano Zampini if (format != PETSC_VIEWER_NATIVE) { 21436ea7df73SStefano Zampini Mat B; 21446ea7df73SStefano Zampini hypre_ParCSRMatrix *parcsr; 21456ea7df73SStefano Zampini PetscErrorCode (*mview)(Mat, PetscViewer) = NULL; 21466ea7df73SStefano Zampini 21479566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 21489566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(parcsr, MATAIJ, PETSC_USE_POINTER, &B)); 21499566063dSJacob Faibussowitsch PetscCall(MatGetOperation(B, MATOP_VIEW, (void (**)(void)) & mview)); 215028b400f6SJacob Faibussowitsch PetscCheck(mview, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Missing view operation"); 21519566063dSJacob Faibussowitsch PetscCall((*mview)(B, view)); 21529566063dSJacob Faibussowitsch PetscCall(MatDestroy(&B)); 215345b8d346SStefano Zampini } else { 215445b8d346SStefano Zampini Mat_HYPRE *hA = (Mat_HYPRE *)A->data; 215545b8d346SStefano Zampini PetscMPIInt size; 215645b8d346SStefano Zampini PetscBool isascii; 215745b8d346SStefano Zampini const char *filename; 215845b8d346SStefano Zampini 215945b8d346SStefano Zampini /* HYPRE uses only text files */ 21609566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERASCII, &isascii)); 216128b400f6SJacob Faibussowitsch PetscCheck(isascii, PetscObjectComm((PetscObject)view), PETSC_ERR_SUP, "PetscViewerType %s: native HYPRE format needs PETSCVIEWERASCII", ((PetscObject)view)->type_name); 21629566063dSJacob Faibussowitsch PetscCall(PetscViewerFileGetName(view, &filename)); 2163792fecdfSBarry Smith PetscCallExternal(HYPRE_IJMatrixPrint, hA->ij, filename); 21649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(hA->comm, &size)); 216545b8d346SStefano Zampini if (size > 1) { 21669566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(view, "Matrix files: %s.%05d ... %s.%05d\n", filename, 0, filename, size - 1)); 216745b8d346SStefano Zampini } else { 21689566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(view, "Matrix file: %s.%05d\n", filename, 0)); 216945b8d346SStefano Zampini } 217045b8d346SStefano Zampini } 21713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 217245b8d346SStefano Zampini } 217345b8d346SStefano Zampini 2174d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCopy_HYPRE(Mat A, Mat B, MatStructure str) 2175d71ae5a4SJacob Faibussowitsch { 2176465edc17SStefano Zampini hypre_ParCSRMatrix *acsr, *bcsr; 2177465edc17SStefano Zampini 2178465edc17SStefano Zampini PetscFunctionBegin; 2179465edc17SStefano Zampini if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) { 21809566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &acsr)); 21819566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(B, &bcsr)); 2182792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixCopy, acsr, bcsr, 1); 21839566063dSJacob Faibussowitsch PetscCall(MatSetOption(B, MAT_SORTED_FULL, PETSC_TRUE)); /* "perfect" preallocation, so no need for hypre_AuxParCSRMatrixNeedAux */ 21849566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 21859566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 2186465edc17SStefano Zampini } else { 21879566063dSJacob Faibussowitsch PetscCall(MatCopy_Basic(A, B, str)); 2188465edc17SStefano Zampini } 21893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2190465edc17SStefano Zampini } 2191465edc17SStefano Zampini 2192d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_HYPRE(Mat A, Vec d) 2193d71ae5a4SJacob Faibussowitsch { 21946305df00SStefano Zampini hypre_ParCSRMatrix *parcsr; 21956305df00SStefano Zampini hypre_CSRMatrix *dmat; 219639accc25SStefano Zampini HYPRE_Complex *a; 21976305df00SStefano Zampini PetscBool cong; 21986305df00SStefano Zampini 21996305df00SStefano Zampini PetscFunctionBegin; 22009566063dSJacob Faibussowitsch PetscCall(MatHasCongruentLayouts(A, &cong)); 220128b400f6SJacob Faibussowitsch PetscCheck(cong, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only for square matrices with same local distributions of rows and columns"); 22029566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 22036305df00SStefano Zampini dmat = hypre_ParCSRMatrixDiag(parcsr); 22046305df00SStefano Zampini if (dmat) { 2205*06977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 2206*06977982Sstefanozampini HYPRE_MemoryLocation mem = hypre_CSRMatrixMemoryLocation(dmat); 2207*06977982Sstefanozampini #else 2208*06977982Sstefanozampini HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST; 2209*06977982Sstefanozampini #endif 2210*06977982Sstefanozampini 2211*06977982Sstefanozampini if (mem != HYPRE_MEMORY_HOST) PetscCall(VecGetArrayWriteAndMemType(d, (PetscScalar **)&a, NULL)); 2212*06977982Sstefanozampini else PetscCall(VecGetArrayWrite(d, (PetscScalar **)&a)); 2213*06977982Sstefanozampini hypre_CSRMatrixExtractDiagonal(dmat, a, 0); 2214*06977982Sstefanozampini if (mem != HYPRE_MEMORY_HOST) PetscCall(VecRestoreArrayWriteAndMemType(d, (PetscScalar **)&a)); 2215*06977982Sstefanozampini else PetscCall(VecRestoreArrayWrite(d, (PetscScalar **)&a)); 22166305df00SStefano Zampini } 22173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 22186305df00SStefano Zampini } 22196305df00SStefano Zampini 2220363d496dSStefano Zampini #include <petscblaslapack.h> 2221363d496dSStefano Zampini 2222d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAXPY_HYPRE(Mat Y, PetscScalar a, Mat X, MatStructure str) 2223d71ae5a4SJacob Faibussowitsch { 2224363d496dSStefano Zampini PetscFunctionBegin; 22256ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 22266ea7df73SStefano Zampini { 22276ea7df73SStefano Zampini Mat B; 22286ea7df73SStefano Zampini hypre_ParCSRMatrix *x, *y, *z; 22296ea7df73SStefano Zampini 22309566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR(Y, &y)); 22319566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR(X, &x)); 2232792fecdfSBarry Smith PetscCallExternal(hypre_ParCSRMatrixAdd, 1.0, y, 1.0, x, &z); 22339566063dSJacob Faibussowitsch PetscCall(MatCreateFromParCSR(z, MATHYPRE, PETSC_OWN_POINTER, &B)); 22349566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(Y, &B)); 22356ea7df73SStefano Zampini } 22366ea7df73SStefano Zampini #else 2237363d496dSStefano Zampini if (str == SAME_NONZERO_PATTERN) { 2238363d496dSStefano Zampini hypre_ParCSRMatrix *x, *y; 2239363d496dSStefano Zampini hypre_CSRMatrix *xloc, *yloc; 2240363d496dSStefano Zampini PetscInt xnnz, ynnz; 224139accc25SStefano Zampini HYPRE_Complex *xarr, *yarr; 2242363d496dSStefano Zampini PetscBLASInt one = 1, bnz; 2243363d496dSStefano Zampini 22449566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR(Y, &y)); 22459566063dSJacob Faibussowitsch PetscCall(MatHYPREGetParCSR(X, &x)); 2246363d496dSStefano Zampini 2247363d496dSStefano Zampini /* diagonal block */ 2248363d496dSStefano Zampini xloc = hypre_ParCSRMatrixDiag(x); 2249363d496dSStefano Zampini yloc = hypre_ParCSRMatrixDiag(y); 2250363d496dSStefano Zampini xnnz = 0; 2251363d496dSStefano Zampini ynnz = 0; 2252363d496dSStefano Zampini xarr = NULL; 2253363d496dSStefano Zampini yarr = NULL; 2254363d496dSStefano Zampini if (xloc) { 225539accc25SStefano Zampini xarr = hypre_CSRMatrixData(xloc); 2256363d496dSStefano Zampini xnnz = hypre_CSRMatrixNumNonzeros(xloc); 2257363d496dSStefano Zampini } 2258363d496dSStefano Zampini if (yloc) { 225939accc25SStefano Zampini yarr = hypre_CSRMatrixData(yloc); 2260363d496dSStefano Zampini ynnz = hypre_CSRMatrixNumNonzeros(yloc); 2261363d496dSStefano Zampini } 226208401ef6SPierre Jolivet PetscCheck(xnnz == ynnz, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Different number of nonzeros in diagonal block %" PetscInt_FMT " != %" PetscInt_FMT, xnnz, ynnz); 22639566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(xnnz, &bnz)); 2264792fecdfSBarry Smith PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one)); 2265363d496dSStefano Zampini 2266363d496dSStefano Zampini /* off-diagonal block */ 2267363d496dSStefano Zampini xloc = hypre_ParCSRMatrixOffd(x); 2268363d496dSStefano Zampini yloc = hypre_ParCSRMatrixOffd(y); 2269363d496dSStefano Zampini xnnz = 0; 2270363d496dSStefano Zampini ynnz = 0; 2271363d496dSStefano Zampini xarr = NULL; 2272363d496dSStefano Zampini yarr = NULL; 2273363d496dSStefano Zampini if (xloc) { 227439accc25SStefano Zampini xarr = hypre_CSRMatrixData(xloc); 2275363d496dSStefano Zampini xnnz = hypre_CSRMatrixNumNonzeros(xloc); 2276363d496dSStefano Zampini } 2277363d496dSStefano Zampini if (yloc) { 227839accc25SStefano Zampini yarr = hypre_CSRMatrixData(yloc); 2279363d496dSStefano Zampini ynnz = hypre_CSRMatrixNumNonzeros(yloc); 2280363d496dSStefano Zampini } 228108401ef6SPierre 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); 22829566063dSJacob Faibussowitsch PetscCall(PetscBLASIntCast(xnnz, &bnz)); 2283792fecdfSBarry Smith PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one)); 2284363d496dSStefano Zampini } else if (str == SUBSET_NONZERO_PATTERN) { 22859566063dSJacob Faibussowitsch PetscCall(MatAXPY_Basic(Y, a, X, str)); 2286363d496dSStefano Zampini } else { 2287363d496dSStefano Zampini Mat B; 2288363d496dSStefano Zampini 22899566063dSJacob Faibussowitsch PetscCall(MatAXPY_Basic_Preallocate(Y, X, &B)); 22909566063dSJacob Faibussowitsch PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str)); 22919566063dSJacob Faibussowitsch PetscCall(MatHeaderReplace(Y, &B)); 2292363d496dSStefano Zampini } 22936ea7df73SStefano Zampini #endif 22943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2295363d496dSStefano Zampini } 2296363d496dSStefano Zampini 22972c4ab24aSJunchao Zhang static PetscErrorCode MatDuplicate_HYPRE(Mat A, MatDuplicateOption op, Mat *B) 22982c4ab24aSJunchao Zhang { 22992c4ab24aSJunchao Zhang hypre_ParCSRMatrix *parcsr = NULL; 23002c4ab24aSJunchao Zhang PetscCopyMode cpmode; 23012c4ab24aSJunchao Zhang Mat_HYPRE *hA; 23022c4ab24aSJunchao Zhang 23032c4ab24aSJunchao Zhang PetscFunctionBegin; 23042c4ab24aSJunchao Zhang PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr)); 23052c4ab24aSJunchao Zhang if (op == MAT_DO_NOT_COPY_VALUES || op == MAT_SHARE_NONZERO_PATTERN) { 23062c4ab24aSJunchao Zhang parcsr = hypre_ParCSRMatrixClone(parcsr, 0); 23072c4ab24aSJunchao Zhang cpmode = PETSC_OWN_POINTER; 23082c4ab24aSJunchao Zhang } else { 23092c4ab24aSJunchao Zhang cpmode = PETSC_COPY_VALUES; 23102c4ab24aSJunchao Zhang } 23112c4ab24aSJunchao Zhang PetscCall(MatCreateFromParCSR(parcsr, MATHYPRE, cpmode, B)); 23122c4ab24aSJunchao Zhang hA = (Mat_HYPRE *)A->data; 23132c4ab24aSJunchao Zhang if (hA->cooMat) { 2314*06977982Sstefanozampini Mat_HYPRE *hB = (Mat_HYPRE *)((*B)->data); 2315b73e3080SStefano Zampini op = (op == MAT_DO_NOT_COPY_VALUES) ? op : MAT_COPY_VALUES; 2316b73e3080SStefano Zampini /* Cannot simply increase the reference count of hA->cooMat, since B needs to share cooMat's data array */ 2317*06977982Sstefanozampini PetscCall(MatDuplicate(hA->cooMat, op, &hB->cooMat)); 2318*06977982Sstefanozampini PetscCall(MatHYPRE_AttachCOOMat(*B)); 23192c4ab24aSJunchao Zhang } 23202c4ab24aSJunchao Zhang PetscFunctionReturn(PETSC_SUCCESS); 23212c4ab24aSJunchao Zhang } 23222c4ab24aSJunchao Zhang 2323d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetPreallocationCOO_HYPRE(Mat mat, PetscCount coo_n, PetscInt coo_i[], PetscInt coo_j[]) 2324d71ae5a4SJacob Faibussowitsch { 2325*06977982Sstefanozampini Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data; 23265fbaff96SJunchao Zhang 23275fbaff96SJunchao Zhang PetscFunctionBegin; 2328651b1cf9SStefano Zampini /* Build an agent matrix cooMat with AIJ format 23295fbaff96SJunchao 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. 23305fbaff96SJunchao Zhang */ 2331*06977982Sstefanozampini PetscCall(MatHYPRE_CreateCOOMat(mat)); 2332*06977982Sstefanozampini PetscCall(MatSetOption(hmat->cooMat, MAT_IGNORE_OFF_PROC_ENTRIES, hmat->donotstash)); 2333*06977982Sstefanozampini PetscCall(MatSetOption(hmat->cooMat, MAT_NO_OFF_PROC_ENTRIES, mat->nooffprocentries)); 2334651b1cf9SStefano Zampini 2335651b1cf9SStefano Zampini /* MatSetPreallocationCOO_SeqAIJ and MatSetPreallocationCOO_MPIAIJ uses this specific 2336651b1cf9SStefano Zampini name to automatically put the diagonal entries first */ 2337*06977982Sstefanozampini PetscCall(PetscObjectSetName((PetscObject)hmat->cooMat, "_internal_COO_mat_for_hypre")); 2338*06977982Sstefanozampini PetscCall(MatSetPreallocationCOO(hmat->cooMat, coo_n, coo_i, coo_j)); 2339*06977982Sstefanozampini hmat->cooMat->assembled = PETSC_TRUE; 23405fbaff96SJunchao Zhang 23415fbaff96SJunchao Zhang /* Copy the sparsity pattern from cooMat to hypre IJMatrix hmat->ij */ 23425fbaff96SJunchao Zhang PetscCall(MatSetOption(mat, MAT_SORTED_FULL, PETSC_TRUE)); 2343*06977982Sstefanozampini PetscCall(MatHYPRE_CreateFromMat(hmat->cooMat, hmat)); /* Create hmat->ij and preallocate it */ 2344*06977982Sstefanozampini PetscCall(MatHYPRE_IJMatrixCopyIJ(hmat->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 */ 2351*06977982Sstefanozampini PetscCall(MatHYPRE_AttachCOOMat(mat)); 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; 23585fbaff96SJunchao Zhang 23595fbaff96SJunchao Zhang PetscFunctionBegin; 2360b73e3080SStefano Zampini PetscCheck(hmat->cooMat, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet"); 23615fbaff96SJunchao Zhang PetscCall(MatSetValuesCOO(hmat->cooMat, v, imode)); 2362651b1cf9SStefano Zampini PetscCall(MatViewFromOptions(hmat->cooMat, (PetscObject)mat, "-cooMat_view")); 23633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 23645fbaff96SJunchao Zhang } 23655fbaff96SJunchao Zhang 2366a055b5aaSBarry Smith /*MC 23672ef1f0ffSBarry Smith MATHYPRE - "hypre" - A matrix type to be used for sequential and parallel sparse matrices 2368a055b5aaSBarry Smith based on the hypre IJ interface. 2369a055b5aaSBarry Smith 2370a055b5aaSBarry Smith Level: intermediate 2371a055b5aaSBarry Smith 23721cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatHYPRESetPreallocation` 2373a055b5aaSBarry Smith M*/ 2374a055b5aaSBarry Smith 2375d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_HYPRE(Mat B) 2376d71ae5a4SJacob Faibussowitsch { 237763c07aadSStefano Zampini Mat_HYPRE *hB; 237863c07aadSStefano Zampini 237963c07aadSStefano Zampini PetscFunctionBegin; 23804dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&hB)); 23816ea7df73SStefano Zampini 2382978814f1SStefano Zampini hB->inner_free = PETSC_TRUE; 2383651b1cf9SStefano Zampini hB->array_available = PETSC_TRUE; 2384978814f1SStefano Zampini 238563c07aadSStefano Zampini B->data = (void *)hB; 238663c07aadSStefano Zampini 23879566063dSJacob Faibussowitsch PetscCall(PetscMemzero(B->ops, sizeof(struct _MatOps))); 238863c07aadSStefano Zampini B->ops->mult = MatMult_HYPRE; 238963c07aadSStefano Zampini B->ops->multtranspose = MatMultTranspose_HYPRE; 2390414bd5c3SStefano Zampini B->ops->multadd = MatMultAdd_HYPRE; 2391414bd5c3SStefano Zampini B->ops->multtransposeadd = MatMultTransposeAdd_HYPRE; 239263c07aadSStefano Zampini B->ops->setup = MatSetUp_HYPRE; 239363c07aadSStefano Zampini B->ops->destroy = MatDestroy_HYPRE; 239463c07aadSStefano Zampini B->ops->assemblyend = MatAssemblyEnd_HYPRE; 2395c69f721fSFande Kong B->ops->assemblybegin = MatAssemblyBegin_HYPRE; 2396d975228cSstefano_zampini B->ops->setvalues = MatSetValues_HYPRE; 239768ec7858SStefano Zampini B->ops->missingdiagonal = MatMissingDiagonal_HYPRE; 239868ec7858SStefano Zampini B->ops->scale = MatScale_HYPRE; 239968ec7858SStefano Zampini B->ops->zerorowscolumns = MatZeroRowsColumns_HYPRE; 2400c69f721fSFande Kong B->ops->zeroentries = MatZeroEntries_HYPRE; 2401c69f721fSFande Kong B->ops->zerorows = MatZeroRows_HYPRE; 2402c69f721fSFande Kong B->ops->getrow = MatGetRow_HYPRE; 2403c69f721fSFande Kong B->ops->restorerow = MatRestoreRow_HYPRE; 2404c69f721fSFande Kong B->ops->getvalues = MatGetValues_HYPRE; 2405ddbeb582SStefano Zampini B->ops->setoption = MatSetOption_HYPRE; 240645b8d346SStefano Zampini B->ops->duplicate = MatDuplicate_HYPRE; 2407465edc17SStefano Zampini B->ops->copy = MatCopy_HYPRE; 240845b8d346SStefano Zampini B->ops->view = MatView_HYPRE; 24096305df00SStefano Zampini B->ops->getdiagonal = MatGetDiagonal_HYPRE; 2410363d496dSStefano Zampini B->ops->axpy = MatAXPY_HYPRE; 24114222ddf1SHong Zhang B->ops->productsetfromoptions = MatProductSetFromOptions_HYPRE; 24126ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 24136ea7df73SStefano Zampini B->ops->bindtocpu = MatBindToCPU_HYPRE; 24146ea7df73SStefano Zampini B->boundtocpu = PETSC_FALSE; 24156ea7df73SStefano Zampini #endif 241645b8d346SStefano Zampini 241745b8d346SStefano Zampini /* build cache for off array entries formed */ 24189566063dSJacob Faibussowitsch PetscCall(MatStashCreate_Private(PetscObjectComm((PetscObject)B), 1, &B->stash)); 241963c07aadSStefano Zampini 24209566063dSJacob Faibussowitsch PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)B), &hB->comm)); 24219566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRE)); 24229566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_aij_C", MatConvert_HYPRE_AIJ)); 24239566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_is_C", MatConvert_HYPRE_IS)); 24249566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_hypre_C", MatProductSetFromOptions_HYPRE)); 24259566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaij_hypre_C", MatProductSetFromOptions_HYPRE)); 24269566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPRESetPreallocation_C", MatHYPRESetPreallocation_HYPRE)); 24279566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPREGetParCSR_C", MatHYPREGetParCSR_HYPRE)); 24285fbaff96SJunchao Zhang PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_HYPRE)); 24295fbaff96SJunchao Zhang PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetValuesCOO_C", MatSetValuesCOO_HYPRE)); 24306ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE) 24316ea7df73SStefano Zampini #if defined(HYPRE_USING_HIP) 2432*06977982Sstefanozampini PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijhipsparse_hypre_C", MatProductSetFromOptions_HYPRE)); 2433*06977982Sstefanozampini PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaijhipsparse_hypre_C", MatProductSetFromOptions_HYPRE)); 24349566063dSJacob Faibussowitsch PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP)); 24359566063dSJacob Faibussowitsch PetscCall(MatSetVecType(B, VECHIP)); 24366ea7df73SStefano Zampini #endif 24376ea7df73SStefano Zampini #if defined(HYPRE_USING_CUDA) 2438*06977982Sstefanozampini PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijcusparse_hypre_C", MatProductSetFromOptions_HYPRE)); 2439*06977982Sstefanozampini PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaijcusparse_hypre_C", MatProductSetFromOptions_HYPRE)); 24409566063dSJacob Faibussowitsch PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA)); 24419566063dSJacob Faibussowitsch PetscCall(MatSetVecType(B, VECCUDA)); 24426ea7df73SStefano Zampini #endif 24436ea7df73SStefano Zampini #endif 2444ea9ee2c1SPierre Jolivet PetscHYPREInitialize(); 24453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 244663c07aadSStefano Zampini } 2447