xref: /petsc/src/mat/impls/hypre/mhypre.c (revision f4f49eeac7efa77fffa46b7ff95a3ed169f659ed)
163c07aadSStefano Zampini /*
263c07aadSStefano Zampini     Creates hypre ijmatrix from PETSc matrix
363c07aadSStefano Zampini */
4225daaf8SStefano Zampini 
5c6698e78SStefano Zampini #include <petscpkg_version.h>
639accc25SStefano Zampini #include <petsc/private/petschypre.h>
7dd9c0a25Sstefano_zampini #include <petscmathypre.h>
863c07aadSStefano Zampini #include <petsc/private/matimpl.h>
9a4af0ceeSJacob Faibussowitsch #include <petsc/private/deviceimpl.h>
1063c07aadSStefano Zampini #include <../src/mat/impls/hypre/mhypre.h>
1163c07aadSStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
1258968eb6SStefano Zampini #include <../src/vec/vec/impls/hypre/vhyp.h>
1358968eb6SStefano Zampini #include <HYPRE.h>
14c1a070e6SStefano Zampini #include <HYPRE_utilities.h>
15cd8bc7baSStefano Zampini #include <_hypre_parcsr_ls.h>
1668ec7858SStefano Zampini #include <_hypre_sstruct_ls.h>
1763c07aadSStefano Zampini 
180e6427aaSSatish Balay #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0)
190e6427aaSSatish Balay   #define hypre_ParCSRMatrixClone(A, B) hypre_ParCSRMatrixCompleteClone(A)
200e6427aaSSatish Balay #endif
210e6427aaSSatish Balay 
2263c07aadSStefano Zampini static PetscErrorCode MatHYPRE_CreateFromMat(Mat, Mat_HYPRE *);
2363c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat, Mat, HYPRE_IJMatrix);
24b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_MPIAIJ(Mat, HYPRE_IJMatrix);
25b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_SeqAIJ(Mat, HYPRE_IJMatrix);
2639accc25SStefano Zampini static PetscErrorCode MatHYPRE_MultKernel_Private(Mat, HYPRE_Complex, Vec, HYPRE_Complex, Vec, PetscBool);
276ea7df73SStefano Zampini static PetscErrorCode MatSetValues_HYPRE(Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[], const PetscScalar[], InsertMode ins);
2863c07aadSStefano Zampini 
29d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat A_d, Mat A_o, HYPRE_IJMatrix ij)
30d71ae5a4SJacob Faibussowitsch {
3163c07aadSStefano Zampini   PetscInt        i, n_d, n_o;
3263c07aadSStefano Zampini   const PetscInt *ia_d, *ia_o;
3363c07aadSStefano Zampini   PetscBool       done_d = PETSC_FALSE, done_o = PETSC_FALSE;
342cf14000SStefano Zampini   HYPRE_Int      *nnz_d = NULL, *nnz_o = NULL;
3563c07aadSStefano Zampini 
3663c07aadSStefano Zampini   PetscFunctionBegin;
3763c07aadSStefano Zampini   if (A_d) { /* determine number of nonzero entries in local diagonal part */
389566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(A_d, 0, PETSC_FALSE, PETSC_FALSE, &n_d, &ia_d, NULL, &done_d));
3963c07aadSStefano Zampini     if (done_d) {
409566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(n_d, &nnz_d));
41ad540459SPierre Jolivet       for (i = 0; i < n_d; i++) nnz_d[i] = ia_d[i + 1] - ia_d[i];
4263c07aadSStefano Zampini     }
439566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowIJ(A_d, 0, PETSC_FALSE, PETSC_FALSE, NULL, &ia_d, NULL, &done_d));
4463c07aadSStefano Zampini   }
4563c07aadSStefano Zampini   if (A_o) { /* determine number of nonzero entries in local off-diagonal part */
469566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(A_o, 0, PETSC_FALSE, PETSC_FALSE, &n_o, &ia_o, NULL, &done_o));
4763c07aadSStefano Zampini     if (done_o) {
489566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(n_o, &nnz_o));
49ad540459SPierre Jolivet       for (i = 0; i < n_o; i++) nnz_o[i] = ia_o[i + 1] - ia_o[i];
5063c07aadSStefano Zampini     }
519566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowIJ(A_o, 0, PETSC_FALSE, PETSC_FALSE, &n_o, &ia_o, NULL, &done_o));
5263c07aadSStefano Zampini   }
5363c07aadSStefano Zampini   if (done_d) {    /* set number of nonzeros in HYPRE IJ matrix */
5463c07aadSStefano Zampini     if (!done_o) { /* only diagonal part */
559566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(n_d, &nnz_o));
5663c07aadSStefano Zampini     }
57c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0)
58c6698e78SStefano Zampini     { /* If we don't do this, the columns of the matrix will be all zeros! */
59c6698e78SStefano Zampini       hypre_AuxParCSRMatrix *aux_matrix;
60c6698e78SStefano Zampini       aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij);
61c6698e78SStefano Zampini       hypre_AuxParCSRMatrixDestroy(aux_matrix);
62c6698e78SStefano Zampini       hypre_IJMatrixTranslator(ij) = NULL;
63792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, ij, nnz_d, nnz_o);
6422235d61SPierre Jolivet       /* it seems they partially fixed it in 2.19.0 */
6522235d61SPierre Jolivet   #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
66c6698e78SStefano Zampini       aux_matrix                               = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij);
67c6698e78SStefano Zampini       hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1;
6822235d61SPierre Jolivet   #endif
69c6698e78SStefano Zampini     }
70c6698e78SStefano Zampini #else
71792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, ij, nnz_d, nnz_o);
72c6698e78SStefano Zampini #endif
739566063dSJacob Faibussowitsch     PetscCall(PetscFree(nnz_d));
749566063dSJacob Faibussowitsch     PetscCall(PetscFree(nnz_o));
7563c07aadSStefano Zampini   }
763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7763c07aadSStefano Zampini }
7863c07aadSStefano Zampini 
79d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_CreateFromMat(Mat A, Mat_HYPRE *hA)
80d71ae5a4SJacob Faibussowitsch {
8163c07aadSStefano Zampini   PetscInt rstart, rend, cstart, cend;
8263c07aadSStefano Zampini 
8363c07aadSStefano Zampini   PetscFunctionBegin;
849566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
859566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
8663c07aadSStefano Zampini   rstart = A->rmap->rstart;
8763c07aadSStefano Zampini   rend   = A->rmap->rend;
8863c07aadSStefano Zampini   cstart = A->cmap->rstart;
8963c07aadSStefano Zampini   cend   = A->cmap->rend;
90ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
91651b1cf9SStefano Zampini   if (hA->ij) {
92651b1cf9SStefano Zampini     if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL;
93651b1cf9SStefano Zampini     PetscCallExternal(HYPRE_IJMatrixDestroy, hA->ij);
94651b1cf9SStefano Zampini   }
95792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rstart, rend - 1, cstart, cend - 1, &hA->ij);
96792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR);
9763c07aadSStefano Zampini   {
9863c07aadSStefano Zampini     PetscBool       same;
9963c07aadSStefano Zampini     Mat             A_d, A_o;
10063c07aadSStefano Zampini     const PetscInt *colmap;
1019566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &same));
10263c07aadSStefano Zampini     if (same) {
1039566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJGetSeqAIJ(A, &A_d, &A_o, &colmap));
1049566063dSJacob Faibussowitsch       PetscCall(MatHYPRE_IJMatrixPreallocate(A_d, A_o, hA->ij));
1053ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
10663c07aadSStefano Zampini     }
1079566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIBAIJ, &same));
10863c07aadSStefano Zampini     if (same) {
1099566063dSJacob Faibussowitsch       PetscCall(MatMPIBAIJGetSeqBAIJ(A, &A_d, &A_o, &colmap));
1109566063dSJacob Faibussowitsch       PetscCall(MatHYPRE_IJMatrixPreallocate(A_d, A_o, hA->ij));
1113ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
11263c07aadSStefano Zampini     }
1139566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &same));
11463c07aadSStefano Zampini     if (same) {
1159566063dSJacob Faibussowitsch       PetscCall(MatHYPRE_IJMatrixPreallocate(A, NULL, hA->ij));
1163ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
11763c07aadSStefano Zampini     }
1189566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQBAIJ, &same));
11963c07aadSStefano Zampini     if (same) {
1209566063dSJacob Faibussowitsch       PetscCall(MatHYPRE_IJMatrixPreallocate(A, NULL, hA->ij));
1213ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
12263c07aadSStefano Zampini     }
12363c07aadSStefano Zampini   }
1243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12563c07aadSStefano Zampini }
12663c07aadSStefano Zampini 
127b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ(Mat A, HYPRE_IJMatrix ij)
128d71ae5a4SJacob Faibussowitsch {
12963c07aadSStefano Zampini   PetscBool flg;
13063c07aadSStefano Zampini 
13163c07aadSStefano Zampini   PetscFunctionBegin;
1326ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
133792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize, ij);
1346ea7df73SStefano Zampini #else
135792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize_v2, ij, HYPRE_MEMORY_HOST);
1366ea7df73SStefano Zampini #endif
1379566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &flg));
138b73e3080SStefano Zampini   if (flg) {
139b73e3080SStefano Zampini     PetscCall(MatHYPRE_IJMatrixCopyIJ_MPIAIJ(A, ij));
1403ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
14163c07aadSStefano Zampini   }
1429566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &flg));
14363c07aadSStefano Zampini   if (flg) {
144b73e3080SStefano Zampini     PetscCall(MatHYPRE_IJMatrixCopyIJ_SeqAIJ(A, ij));
1453ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
14663c07aadSStefano Zampini   }
147b73e3080SStefano Zampini   PetscCheck(PETSC_FALSE, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "No support for matrix type %s", ((PetscObject)A)->type_name);
14863c07aadSStefano Zampini }
14963c07aadSStefano Zampini 
150b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_SeqAIJ(Mat A, HYPRE_IJMatrix ij)
151d71ae5a4SJacob Faibussowitsch {
15263c07aadSStefano Zampini   Mat_SeqAIJ            *pdiag = (Mat_SeqAIJ *)A->data;
15358968eb6SStefano Zampini   HYPRE_Int              type;
15463c07aadSStefano Zampini   hypre_ParCSRMatrix    *par_matrix;
15563c07aadSStefano Zampini   hypre_AuxParCSRMatrix *aux_matrix;
15663c07aadSStefano Zampini   hypre_CSRMatrix       *hdiag;
1572cf14000SStefano Zampini   PetscBool              sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
15863c07aadSStefano Zampini 
15963c07aadSStefano Zampini   PetscFunctionBegin;
160792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type);
16108401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
162792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix);
16363c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(par_matrix);
16463c07aadSStefano Zampini   /*
16563c07aadSStefano Zampini        this is the Hack part where we monkey directly with the hypre datastructures
16663c07aadSStefano Zampini   */
1672cf14000SStefano Zampini   if (sameint) {
1689566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hdiag->i, pdiag->i, A->rmap->n + 1));
1699566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hdiag->j, pdiag->j, pdiag->nz));
1702cf14000SStefano Zampini   } else {
1712cf14000SStefano Zampini     PetscInt i;
1722cf14000SStefano Zampini 
1732cf14000SStefano Zampini     for (i = 0; i < A->rmap->n + 1; i++) hdiag->i[i] = (HYPRE_Int)pdiag->i[i];
1742cf14000SStefano Zampini     for (i = 0; i < pdiag->nz; i++) hdiag->j[i] = (HYPRE_Int)pdiag->j[i];
1752cf14000SStefano Zampini   }
1766ea7df73SStefano Zampini 
177ea9daf28SStefano Zampini   aux_matrix                               = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij);
17863c07aadSStefano Zampini   hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
1793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18063c07aadSStefano Zampini }
18163c07aadSStefano Zampini 
182b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_MPIAIJ(Mat A, HYPRE_IJMatrix ij)
183d71ae5a4SJacob Faibussowitsch {
18463c07aadSStefano Zampini   Mat_MPIAIJ            *pA = (Mat_MPIAIJ *)A->data;
18563c07aadSStefano Zampini   Mat_SeqAIJ            *pdiag, *poffd;
18663c07aadSStefano Zampini   PetscInt               i, *garray = pA->garray, *jj, cstart, *pjj;
1872cf14000SStefano Zampini   HYPRE_Int             *hjj, type;
18863c07aadSStefano Zampini   hypre_ParCSRMatrix    *par_matrix;
18963c07aadSStefano Zampini   hypre_AuxParCSRMatrix *aux_matrix;
19063c07aadSStefano Zampini   hypre_CSRMatrix       *hdiag, *hoffd;
1912cf14000SStefano Zampini   PetscBool              sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
19263c07aadSStefano Zampini 
19363c07aadSStefano Zampini   PetscFunctionBegin;
19463c07aadSStefano Zampini   pdiag = (Mat_SeqAIJ *)pA->A->data;
19563c07aadSStefano Zampini   poffd = (Mat_SeqAIJ *)pA->B->data;
196da81f932SPierre Jolivet   /* cstart is only valid for square MPIAIJ laid out in the usual way */
1979566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &cstart, NULL));
19863c07aadSStefano Zampini 
199792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type);
20008401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
201792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix);
20263c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(par_matrix);
20363c07aadSStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(par_matrix);
20463c07aadSStefano Zampini 
2052cf14000SStefano Zampini   if (sameint) {
2069566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hdiag->i, pdiag->i, pA->A->rmap->n + 1));
2072cf14000SStefano Zampini   } else {
208*f4f49eeaSPierre Jolivet     for (i = 0; i < pA->A->rmap->n + 1; i++) hdiag->i[i] = (HYPRE_Int)pdiag->i[i];
2092cf14000SStefano Zampini   }
210b73e3080SStefano Zampini 
2112cf14000SStefano Zampini   hjj = hdiag->j;
2122cf14000SStefano Zampini   pjj = pdiag->j;
213c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0)
2142cf14000SStefano Zampini   for (i = 0; i < pdiag->nz; i++) hjj[i] = pjj[i];
215c6698e78SStefano Zampini #else
2162cf14000SStefano Zampini   for (i = 0; i < pdiag->nz; i++) hjj[i] = cstart + pjj[i];
217c6698e78SStefano Zampini #endif
2182cf14000SStefano Zampini   if (sameint) {
2199566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hoffd->i, poffd->i, pA->A->rmap->n + 1));
2202cf14000SStefano Zampini   } else {
221*f4f49eeaSPierre Jolivet     for (i = 0; i < pA->A->rmap->n + 1; i++) hoffd->i[i] = (HYPRE_Int)poffd->i[i];
2222cf14000SStefano Zampini   }
2232cf14000SStefano Zampini 
22406977982Sstefanozampini   jj = (PetscInt *)hoffd->j;
225c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0)
226792fecdfSBarry Smith   PetscCallExternal(hypre_CSRMatrixBigInitialize, hoffd);
227c6698e78SStefano Zampini   jj = (PetscInt *)hoffd->big_j;
228c6698e78SStefano Zampini #endif
2292cf14000SStefano Zampini   pjj = poffd->j;
23063c07aadSStefano Zampini   for (i = 0; i < poffd->nz; i++) jj[i] = garray[pjj[i]];
231c6698e78SStefano Zampini 
232ea9daf28SStefano Zampini   aux_matrix                               = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij);
23363c07aadSStefano Zampini   hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
2343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23563c07aadSStefano Zampini }
23663c07aadSStefano Zampini 
237d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_HYPRE_IS(Mat A, MatType mtype, MatReuse reuse, Mat *B)
238d71ae5a4SJacob Faibussowitsch {
239*f4f49eeaSPierre Jolivet   Mat_HYPRE             *mhA = (Mat_HYPRE *)A->data;
2402df22349SStefano Zampini   Mat                    lA;
2412df22349SStefano Zampini   ISLocalToGlobalMapping rl2g, cl2g;
2422df22349SStefano Zampini   IS                     is;
2432df22349SStefano Zampini   hypre_ParCSRMatrix    *hA;
2442df22349SStefano Zampini   hypre_CSRMatrix       *hdiag, *hoffd;
2452df22349SStefano Zampini   MPI_Comm               comm;
24639accc25SStefano Zampini   HYPRE_Complex         *hdd, *hod, *aa;
24739accc25SStefano Zampini   PetscScalar           *data;
2482cf14000SStefano Zampini   HYPRE_BigInt          *col_map_offd;
2492cf14000SStefano Zampini   HYPRE_Int             *hdi, *hdj, *hoi, *hoj;
2502df22349SStefano Zampini   PetscInt              *ii, *jj, *iptr, *jptr;
2512df22349SStefano Zampini   PetscInt               cum, dr, dc, oc, str, stc, nnz, i, jd, jo, M, N;
25258968eb6SStefano Zampini   HYPRE_Int              type;
25306977982Sstefanozampini   MatType                lmattype   = NULL;
25406977982Sstefanozampini   PetscBool              freeparcsr = PETSC_FALSE;
2552df22349SStefano Zampini 
2562df22349SStefano Zampini   PetscFunctionBegin;
257a1787963SStefano Zampini   comm = PetscObjectComm((PetscObject)A);
258792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, mhA->ij, &type);
25908401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
260792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, mhA->ij, (void **)&hA);
26106977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
26206977982Sstefanozampini   if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(mhA->ij)) {
26306977982Sstefanozampini     /* Support by copying back on the host and copy to GPU
26406977982Sstefanozampini        Kind of inefficient, but this is the best we can do now */
26506977982Sstefanozampini   #if defined(HYPRE_USING_HIP)
26606977982Sstefanozampini     lmattype = MATSEQAIJHIPSPARSE;
26706977982Sstefanozampini   #elif defined(HYPRE_USING_CUDA)
26806977982Sstefanozampini     lmattype = MATSEQAIJCUSPARSE;
26906977982Sstefanozampini   #endif
27006977982Sstefanozampini     hA         = hypre_ParCSRMatrixClone_v2(hA, 1, HYPRE_MEMORY_HOST);
27106977982Sstefanozampini     freeparcsr = PETSC_TRUE;
27206977982Sstefanozampini   }
27306977982Sstefanozampini #endif
2742df22349SStefano Zampini   M     = hypre_ParCSRMatrixGlobalNumRows(hA);
2752df22349SStefano Zampini   N     = hypre_ParCSRMatrixGlobalNumCols(hA);
2762df22349SStefano Zampini   str   = hypre_ParCSRMatrixFirstRowIndex(hA);
2772df22349SStefano Zampini   stc   = hypre_ParCSRMatrixFirstColDiag(hA);
2782df22349SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(hA);
2792df22349SStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(hA);
2802df22349SStefano Zampini   dr    = hypre_CSRMatrixNumRows(hdiag);
2812df22349SStefano Zampini   dc    = hypre_CSRMatrixNumCols(hdiag);
2822df22349SStefano Zampini   nnz   = hypre_CSRMatrixNumNonzeros(hdiag);
2832df22349SStefano Zampini   hdi   = hypre_CSRMatrixI(hdiag);
2842df22349SStefano Zampini   hdj   = hypre_CSRMatrixJ(hdiag);
2852df22349SStefano Zampini   hdd   = hypre_CSRMatrixData(hdiag);
2862df22349SStefano Zampini   oc    = hypre_CSRMatrixNumCols(hoffd);
2872df22349SStefano Zampini   nnz += hypre_CSRMatrixNumNonzeros(hoffd);
2882df22349SStefano Zampini   hoi = hypre_CSRMatrixI(hoffd);
2892df22349SStefano Zampini   hoj = hypre_CSRMatrixJ(hoffd);
2902df22349SStefano Zampini   hod = hypre_CSRMatrixData(hoffd);
2912df22349SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
2922df22349SStefano Zampini     PetscInt *aux;
2932df22349SStefano Zampini 
2942df22349SStefano Zampini     /* generate l2g maps for rows and cols */
2959566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(comm, dr, str, 1, &is));
2969566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g));
2979566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
2982df22349SStefano Zampini     col_map_offd = hypre_ParCSRMatrixColMapOffd(hA);
2999566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dc + oc, &aux));
3002df22349SStefano Zampini     for (i = 0; i < dc; i++) aux[i] = i + stc;
3012df22349SStefano Zampini     for (i = 0; i < oc; i++) aux[i + dc] = col_map_offd[i];
3029566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, dc + oc, aux, PETSC_OWN_POINTER, &is));
3039566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g));
3049566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
3052df22349SStefano Zampini     /* create MATIS object */
3069566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm, B));
3079566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(*B, dr, dc, M, N));
3089566063dSJacob Faibussowitsch     PetscCall(MatSetType(*B, MATIS));
3099566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(*B, rl2g, cl2g));
3109566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
3119566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
3122df22349SStefano Zampini 
3132df22349SStefano Zampini     /* allocate CSR for local matrix */
3149566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dr + 1, &iptr));
3159566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &jptr));
3169566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &data));
3172df22349SStefano Zampini   } else {
3182df22349SStefano Zampini     PetscInt  nr;
3192df22349SStefano Zampini     PetscBool done;
3209566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(*B, &lA));
3219566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(lA, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&iptr, (const PetscInt **)&jptr, &done));
32208401ef6SPierre 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);
32308401ef6SPierre 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);
32406977982Sstefanozampini     PetscCall(MatSeqAIJGetArrayWrite(lA, &data));
3252df22349SStefano Zampini   }
3262df22349SStefano Zampini   /* merge local matrices */
3272df22349SStefano Zampini   ii  = iptr;
3282df22349SStefano Zampini   jj  = jptr;
32939accc25SStefano 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++ */
3302df22349SStefano Zampini   *ii = *(hdi++) + *(hoi++);
3312df22349SStefano Zampini   for (jd = 0, jo = 0, cum = 0; *ii < nnz; cum++) {
33239accc25SStefano Zampini     PetscScalar *aold = (PetscScalar *)aa;
3332df22349SStefano Zampini     PetscInt    *jold = jj, nc = jd + jo;
3349371c9d4SSatish Balay     for (; jd < *hdi; jd++) {
3359371c9d4SSatish Balay       *jj++ = *hdj++;
3369371c9d4SSatish Balay       *aa++ = *hdd++;
3379371c9d4SSatish Balay     }
3389371c9d4SSatish Balay     for (; jo < *hoi; jo++) {
3399371c9d4SSatish Balay       *jj++ = *hoj++ + dc;
3409371c9d4SSatish Balay       *aa++ = *hod++;
3419371c9d4SSatish Balay     }
3422df22349SStefano Zampini     *(++ii) = *(hdi++) + *(hoi++);
3439566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithScalarArray(jd + jo - nc, jold, aold));
3442df22349SStefano Zampini   }
3452df22349SStefano Zampini   for (; cum < dr; cum++) *(++ii) = nnz;
3462df22349SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
347a033916dSStefano Zampini     Mat_SeqAIJ *a;
348a033916dSStefano Zampini 
3499566063dSJacob Faibussowitsch     PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, dr, dc + oc, iptr, jptr, data, &lA));
350a033916dSStefano Zampini     /* hack SeqAIJ */
351*f4f49eeaSPierre Jolivet     a          = (Mat_SeqAIJ *)lA->data;
352a033916dSStefano Zampini     a->free_a  = PETSC_TRUE;
353a033916dSStefano Zampini     a->free_ij = PETSC_TRUE;
35406977982Sstefanozampini     if (lmattype) PetscCall(MatConvert(lA, lmattype, MAT_INPLACE_MATRIX, &lA));
35506977982Sstefanozampini     PetscCall(MatISSetLocalMat(*B, lA));
3569566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&lA));
35706977982Sstefanozampini   } else {
35806977982Sstefanozampini     PetscCall(MatSeqAIJRestoreArrayWrite(lA, &data));
3592df22349SStefano Zampini   }
3609566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY));
3619566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY));
36248a46eb9SPierre Jolivet   if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, B));
36306977982Sstefanozampini   if (freeparcsr) PetscCallExternal(hypre_ParCSRMatrixDestroy, hA);
3643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3652df22349SStefano Zampini }
3662df22349SStefano Zampini 
36706977982Sstefanozampini static PetscErrorCode MatHYPRE_DestroyCOOMat(Mat mat)
368d71ae5a4SJacob Faibussowitsch {
36906977982Sstefanozampini   Mat_HYPRE *hA = (Mat_HYPRE *)mat->data;
37063c07aadSStefano Zampini 
37163c07aadSStefano Zampini   PetscFunctionBegin;
37206977982Sstefanozampini   if (hA->cooMat) { /* If cooMat is present we need to destroy the column indices */
37306977982Sstefanozampini     PetscCall(MatDestroy(&hA->cooMat));
37406977982Sstefanozampini     if (hA->cooMatAttached) {
37506977982Sstefanozampini       hypre_CSRMatrix     *csr;
37606977982Sstefanozampini       hypre_ParCSRMatrix  *parcsr;
37706977982Sstefanozampini       HYPRE_MemoryLocation mem;
37806977982Sstefanozampini 
37906977982Sstefanozampini       PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
38006977982Sstefanozampini       csr = hypre_ParCSRMatrixDiag(parcsr);
38106977982Sstefanozampini       if (csr) {
38206977982Sstefanozampini         mem = hypre_CSRMatrixMemoryLocation(csr);
38306977982Sstefanozampini         PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixJ(csr), mem));
38406977982Sstefanozampini         PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixBigJ(csr), mem));
385b73e3080SStefano Zampini       }
38606977982Sstefanozampini       csr = hypre_ParCSRMatrixOffd(parcsr);
38706977982Sstefanozampini       if (csr) {
38806977982Sstefanozampini         mem = hypre_CSRMatrixMemoryLocation(csr);
38906977982Sstefanozampini         PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixJ(csr), mem));
39006977982Sstefanozampini         PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixBigJ(csr), mem));
391b73e3080SStefano Zampini       }
392b73e3080SStefano Zampini     }
39306977982Sstefanozampini   }
39406977982Sstefanozampini   hA->cooMatAttached = PETSC_FALSE;
395b73e3080SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
396b73e3080SStefano Zampini }
397b73e3080SStefano Zampini 
39806977982Sstefanozampini static PetscErrorCode MatHYPRE_CreateCOOMat(Mat mat)
399b73e3080SStefano Zampini {
40006977982Sstefanozampini   MPI_Comm    comm;
40106977982Sstefanozampini   PetscMPIInt size;
40206977982Sstefanozampini   PetscLayout rmap, cmap;
40306977982Sstefanozampini   Mat_HYPRE  *hmat    = (Mat_HYPRE *)mat->data;
40406977982Sstefanozampini   MatType     matType = MATAIJ; /* default type of cooMat */
405b73e3080SStefano Zampini 
406b73e3080SStefano Zampini   PetscFunctionBegin;
40706977982Sstefanozampini   /* Build an agent matrix cooMat with AIJ format
40806977982Sstefanozampini      It has the same sparsity pattern as mat, and also shares the data array with mat. We use cooMat to do the COO work.
40906977982Sstefanozampini    */
41006977982Sstefanozampini   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
41106977982Sstefanozampini   PetscCallMPI(MPI_Comm_size(comm, &size));
41206977982Sstefanozampini   PetscCall(PetscLayoutSetUp(mat->rmap));
41306977982Sstefanozampini   PetscCall(PetscLayoutSetUp(mat->cmap));
41406977982Sstefanozampini   PetscCall(MatGetLayouts(mat, &rmap, &cmap));
415b73e3080SStefano Zampini 
41606977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
41706977982Sstefanozampini   if (!mat->boundtocpu) { /* mat will be on device, so will cooMat */
41806977982Sstefanozampini   #if defined(HYPRE_USING_HIP)
41906977982Sstefanozampini     matType = MATAIJHIPSPARSE;
42006977982Sstefanozampini   #elif defined(HYPRE_USING_CUDA)
42106977982Sstefanozampini     matType  = MATAIJCUSPARSE;
42206977982Sstefanozampini   #else
42306977982Sstefanozampini     SETERRQ(comm, PETSC_ERR_SUP, "Do not know the HYPRE device");
42406977982Sstefanozampini   #endif
425b73e3080SStefano Zampini   }
42606977982Sstefanozampini #endif
42706977982Sstefanozampini 
42806977982Sstefanozampini   /* Do COO preallocation through cooMat */
42906977982Sstefanozampini   PetscCall(MatHYPRE_DestroyCOOMat(mat));
43006977982Sstefanozampini   PetscCall(MatCreate(comm, &hmat->cooMat));
43106977982Sstefanozampini   PetscCall(MatSetType(hmat->cooMat, matType));
43206977982Sstefanozampini   PetscCall(MatSetLayouts(hmat->cooMat, rmap, cmap));
43306977982Sstefanozampini 
43406977982Sstefanozampini   /* allocate local matrices if needed */
43506977982Sstefanozampini   PetscCall(MatMPIAIJSetPreallocation(hmat->cooMat, 0, NULL, 0, NULL));
43606977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
43706977982Sstefanozampini }
43806977982Sstefanozampini 
43906977982Sstefanozampini /* Attach cooMat data array to hypre matrix.
44006977982Sstefanozampini    When AIJCUPMSPARSE will support raw device pointers and not THRUSTARRAY
44106977982Sstefanozampini    we should swap the arrays: i.e., attach hypre matrix array to cooMat
44206977982Sstefanozampini    This is because hypre should be in charge of handling the memory,
44306977982Sstefanozampini    cooMat is only a way to reuse PETSc COO code.
44406977982Sstefanozampini    attaching the memory will then be done at MatSetValuesCOO time and it will dynamically
44506977982Sstefanozampini    support hypre matrix migrating to host.
44606977982Sstefanozampini */
44706977982Sstefanozampini static PetscErrorCode MatHYPRE_AttachCOOMat(Mat mat)
44806977982Sstefanozampini {
44906977982Sstefanozampini   Mat_HYPRE           *hmat = (Mat_HYPRE *)mat->data;
45006977982Sstefanozampini   hypre_CSRMatrix     *diag, *offd;
45106977982Sstefanozampini   hypre_ParCSRMatrix  *parCSR;
45206977982Sstefanozampini   HYPRE_MemoryLocation hmem = HYPRE_MEMORY_HOST;
45306977982Sstefanozampini   PetscMemType         pmem;
45406977982Sstefanozampini   Mat                  A, B;
45506977982Sstefanozampini   PetscScalar         *a;
45606977982Sstefanozampini   PetscMPIInt          size;
45706977982Sstefanozampini   MPI_Comm             comm;
45806977982Sstefanozampini 
45906977982Sstefanozampini   PetscFunctionBegin;
46006977982Sstefanozampini   PetscCheck(hmat->cooMat, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet");
46106977982Sstefanozampini   if (hmat->cooMatAttached) PetscFunctionReturn(PETSC_SUCCESS);
46206977982Sstefanozampini   PetscCheck(hmat->cooMat->preallocated, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix is not preallocated");
46306977982Sstefanozampini   PetscCall(PetscObjectSetName((PetscObject)hmat->cooMat, "_internal_COO_mat_for_hypre"));
46406977982Sstefanozampini   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
46506977982Sstefanozampini   PetscCallMPI(MPI_Comm_size(comm, &size));
46606977982Sstefanozampini 
46706977982Sstefanozampini   /* Alias cooMat's data array to IJMatrix's */
46806977982Sstefanozampini   PetscCallExternal(HYPRE_IJMatrixGetObject, hmat->ij, (void **)&parCSR);
46906977982Sstefanozampini   diag = hypre_ParCSRMatrixDiag(parCSR);
47006977982Sstefanozampini   offd = hypre_ParCSRMatrixOffd(parCSR);
47106977982Sstefanozampini 
47206977982Sstefanozampini   A = (size == 1) ? hmat->cooMat : ((Mat_MPIAIJ *)hmat->cooMat->data)->A;
47306977982Sstefanozampini   B = (size == 1) ? NULL : ((Mat_MPIAIJ *)hmat->cooMat->data)->B;
47406977982Sstefanozampini 
47506977982Sstefanozampini   PetscCall(PetscObjectSetName((PetscObject)A, "_internal_COO_mat_for_hypre"));
47606977982Sstefanozampini   hmem = hypre_CSRMatrixMemoryLocation(diag);
47706977982Sstefanozampini   PetscCall(MatSeqAIJGetCSRAndMemType(A, NULL, NULL, &a, &pmem));
47806977982Sstefanozampini   PetscAssert((PetscMemTypeHost(pmem) && hmem == HYPRE_MEMORY_HOST) || (PetscMemTypeDevice(pmem) && hmem == HYPRE_MEMORY_DEVICE), comm, PETSC_ERR_PLIB, "PETSc and hypre's memory types mismatch");
47906977982Sstefanozampini   PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(diag), hmem));
48006977982Sstefanozampini   hypre_CSRMatrixData(diag)     = (HYPRE_Complex *)a;
48106977982Sstefanozampini   hypre_CSRMatrixOwnsData(diag) = 0; /* Take ownership of (j,a) away from hypre. As a result, we need to free them on our own */
48206977982Sstefanozampini 
48306977982Sstefanozampini   if (B) {
48406977982Sstefanozampini     hmem = hypre_CSRMatrixMemoryLocation(offd);
48506977982Sstefanozampini     PetscCall(MatSeqAIJGetCSRAndMemType(B, NULL, NULL, &a, &pmem));
48606977982Sstefanozampini     PetscAssert((PetscMemTypeHost(pmem) && hmem == HYPRE_MEMORY_HOST) || (PetscMemTypeDevice(pmem) && hmem == HYPRE_MEMORY_DEVICE), comm, PETSC_ERR_PLIB, "PETSc and hypre's memory types mismatch");
48706977982Sstefanozampini     PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(offd), hmem));
48806977982Sstefanozampini     hypre_CSRMatrixData(offd)     = (HYPRE_Complex *)a;
48906977982Sstefanozampini     hypre_CSRMatrixOwnsData(offd) = 0;
49006977982Sstefanozampini   }
49106977982Sstefanozampini   hmat->cooMatAttached = PETSC_TRUE;
49206977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
49306977982Sstefanozampini }
49406977982Sstefanozampini 
49506977982Sstefanozampini static PetscErrorCode CSRtoCOO_Private(PetscInt n, const PetscInt ii[], const PetscInt jj[], PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j)
49606977982Sstefanozampini {
49706977982Sstefanozampini   PetscInt *cooi, *cooj;
49806977982Sstefanozampini 
49906977982Sstefanozampini   PetscFunctionBegin;
50006977982Sstefanozampini   *ncoo = ii[n];
50106977982Sstefanozampini   PetscCall(PetscMalloc2(*ncoo, &cooi, *ncoo, &cooj));
50206977982Sstefanozampini   for (PetscInt i = 0; i < n; i++) {
50306977982Sstefanozampini     for (PetscInt j = ii[i]; j < ii[i + 1]; j++) cooi[j] = i;
50406977982Sstefanozampini   }
50506977982Sstefanozampini   PetscCall(PetscArraycpy(cooj, jj, *ncoo));
50606977982Sstefanozampini   *coo_i = cooi;
50706977982Sstefanozampini   *coo_j = cooj;
50806977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
50906977982Sstefanozampini }
51006977982Sstefanozampini 
51106977982Sstefanozampini static PetscErrorCode CSRtoCOO_HYPRE_Int_Private(PetscInt n, const HYPRE_Int ii[], const HYPRE_Int jj[], PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j)
51206977982Sstefanozampini {
51306977982Sstefanozampini   PetscInt *cooi, *cooj;
51406977982Sstefanozampini 
51506977982Sstefanozampini   PetscFunctionBegin;
51606977982Sstefanozampini   *ncoo = ii[n];
51706977982Sstefanozampini   PetscCall(PetscMalloc2(*ncoo, &cooi, *ncoo, &cooj));
51806977982Sstefanozampini   for (PetscInt i = 0; i < n; i++) {
51906977982Sstefanozampini     for (HYPRE_Int j = ii[i]; j < ii[i + 1]; j++) cooi[j] = i;
52006977982Sstefanozampini   }
52106977982Sstefanozampini   for (PetscCount i = 0; i < *ncoo; i++) cooj[i] = jj[i];
52206977982Sstefanozampini   *coo_i = cooi;
52306977982Sstefanozampini   *coo_j = cooj;
52406977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
52506977982Sstefanozampini }
52606977982Sstefanozampini 
52706977982Sstefanozampini static PetscErrorCode MatSeqAIJGetCOO_Private(Mat A, PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j)
52806977982Sstefanozampini {
52906977982Sstefanozampini   PetscInt        n;
53006977982Sstefanozampini   const PetscInt *ii, *jj;
53106977982Sstefanozampini   PetscBool       done;
53206977982Sstefanozampini 
53306977982Sstefanozampini   PetscFunctionBegin;
53406977982Sstefanozampini   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &done));
53506977982Sstefanozampini   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Failure for MatGetRowIJ");
53606977982Sstefanozampini   PetscCall(CSRtoCOO_Private(n, ii, jj, ncoo, coo_i, coo_j));
53706977982Sstefanozampini   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &done));
53806977982Sstefanozampini   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Failure for MatRestoreRowIJ");
53906977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
54006977982Sstefanozampini }
54106977982Sstefanozampini 
54206977982Sstefanozampini static PetscErrorCode hypreCSRMatrixGetCOO_Private(hypre_CSRMatrix *A, PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j)
54306977982Sstefanozampini {
54406977982Sstefanozampini   PetscInt             n = hypre_CSRMatrixNumRows(A);
54506977982Sstefanozampini   HYPRE_Int           *ii, *jj;
54606977982Sstefanozampini   HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST;
54706977982Sstefanozampini 
54806977982Sstefanozampini   PetscFunctionBegin;
54906977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
55006977982Sstefanozampini   mem = hypre_CSRMatrixMemoryLocation(A);
55106977982Sstefanozampini   if (mem != HYPRE_MEMORY_HOST) {
55206977982Sstefanozampini     PetscCount nnz = hypre_CSRMatrixNumNonzeros(A);
55306977982Sstefanozampini     PetscCall(PetscMalloc2(n + 1, &ii, nnz, &jj));
55406977982Sstefanozampini     hypre_TMemcpy(ii, hypre_CSRMatrixI(A), HYPRE_Int, n + 1, HYPRE_MEMORY_HOST, mem);
55506977982Sstefanozampini     hypre_TMemcpy(jj, hypre_CSRMatrixJ(A), HYPRE_Int, nnz, HYPRE_MEMORY_HOST, mem);
55606977982Sstefanozampini   } else {
55706977982Sstefanozampini #else
55806977982Sstefanozampini   {
55906977982Sstefanozampini #endif
56006977982Sstefanozampini     ii = hypre_CSRMatrixI(A);
56106977982Sstefanozampini     jj = hypre_CSRMatrixJ(A);
56206977982Sstefanozampini   }
56306977982Sstefanozampini   PetscCall(CSRtoCOO_HYPRE_Int_Private(n, ii, jj, ncoo, coo_i, coo_j));
56406977982Sstefanozampini   if (mem != HYPRE_MEMORY_HOST) PetscCall(PetscFree2(ii, jj));
56506977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
56606977982Sstefanozampini }
56706977982Sstefanozampini 
56806977982Sstefanozampini static PetscErrorCode MatSetValuesCOOFromCSRMatrix_Private(Mat A, hypre_CSRMatrix *H)
56906977982Sstefanozampini {
57006977982Sstefanozampini   PetscBool            iscpu = PETSC_TRUE;
57106977982Sstefanozampini   PetscScalar         *a;
57206977982Sstefanozampini   HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST;
57306977982Sstefanozampini 
57406977982Sstefanozampini   PetscFunctionBegin;
57506977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
57606977982Sstefanozampini   mem = hypre_CSRMatrixMemoryLocation(H);
57706977982Sstefanozampini   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATSEQAIJ, &iscpu));
57806977982Sstefanozampini #endif
57906977982Sstefanozampini   if (iscpu && mem != HYPRE_MEMORY_HOST) {
58006977982Sstefanozampini     PetscCount nnz = hypre_CSRMatrixNumNonzeros(H);
58106977982Sstefanozampini     PetscCall(PetscMalloc1(nnz, &a));
58206977982Sstefanozampini     hypre_TMemcpy(a, hypre_CSRMatrixData(H), PetscScalar, nnz, HYPRE_MEMORY_HOST, mem);
58306977982Sstefanozampini   } else {
58406977982Sstefanozampini     a = (PetscScalar *)hypre_CSRMatrixData(H);
58506977982Sstefanozampini   }
58606977982Sstefanozampini   PetscCall(MatSetValuesCOO(A, a, INSERT_VALUES));
58706977982Sstefanozampini   if (iscpu && mem != HYPRE_MEMORY_HOST) PetscCall(PetscFree(a));
588b73e3080SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
589b73e3080SStefano Zampini }
590b73e3080SStefano Zampini 
591b73e3080SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType type, MatReuse reuse, Mat *B)
592b73e3080SStefano Zampini {
593b73e3080SStefano Zampini   MPI_Comm   comm = PetscObjectComm((PetscObject)A);
59406977982Sstefanozampini   Mat        M = NULL, dH = NULL, oH = NULL, dA = NULL, oA = NULL;
595b73e3080SStefano Zampini   PetscBool  ismpiaij, issbaij, isbaij;
596b73e3080SStefano Zampini   Mat_HYPRE *hA;
597b73e3080SStefano Zampini 
598b73e3080SStefano Zampini   PetscFunctionBegin;
599b73e3080SStefano Zampini   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &issbaij, MATSEQSBAIJ, MATMPIBAIJ, ""));
600b73e3080SStefano Zampini   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &isbaij, MATSEQBAIJ, MATMPIBAIJ, ""));
601b73e3080SStefano Zampini   if (isbaij || issbaij) { /* handle BAIJ and SBAIJ */
602b73e3080SStefano Zampini     PetscBool ismpi;
603b73e3080SStefano Zampini     MatType   newtype;
604b73e3080SStefano Zampini 
605b73e3080SStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &ismpi, MATMPISBAIJ, MATMPIBAIJ, ""));
606b73e3080SStefano Zampini     newtype = ismpi ? MATMPIAIJ : MATSEQAIJ;
60763c07aadSStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
608b73e3080SStefano Zampini       PetscCall(MatConvert(*B, newtype, MAT_INPLACE_MATRIX, B));
609b73e3080SStefano Zampini       PetscCall(MatConvert(A, newtype, MAT_REUSE_MATRIX, B));
610b73e3080SStefano Zampini       PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B));
611b73e3080SStefano Zampini     } else if (reuse == MAT_INITIAL_MATRIX) {
612b73e3080SStefano Zampini       PetscCall(MatConvert(A, newtype, MAT_INITIAL_MATRIX, B));
613b73e3080SStefano Zampini       PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B));
61463c07aadSStefano Zampini     } else {
615b73e3080SStefano Zampini       PetscCall(MatConvert(A, newtype, MAT_INPLACE_MATRIX, &A));
616b73e3080SStefano Zampini       PetscCall(MatConvert(A, MATHYPRE, MAT_INPLACE_MATRIX, &A));
617b73e3080SStefano Zampini     }
618b73e3080SStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
619b73e3080SStefano Zampini   }
62006977982Sstefanozampini 
62106977982Sstefanozampini   dA = A;
622b73e3080SStefano Zampini   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
623b73e3080SStefano Zampini   if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(A, &dA, &oA, NULL));
62406977982Sstefanozampini 
625b73e3080SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
62606977982Sstefanozampini     PetscCount coo_n;
62706977982Sstefanozampini     PetscInt  *coo_i, *coo_j;
62806977982Sstefanozampini 
6299566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm, &M));
6309566063dSJacob Faibussowitsch     PetscCall(MatSetType(M, MATHYPRE));
6319566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(M, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
632b73e3080SStefano Zampini     PetscCall(MatSetOption(M, MAT_SORTED_FULL, PETSC_TRUE));
633b73e3080SStefano Zampini     PetscCall(MatSetOption(M, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE));
634b73e3080SStefano Zampini 
635b73e3080SStefano Zampini     hA = (Mat_HYPRE *)M->data;
63606977982Sstefanozampini     PetscCall(MatHYPRE_CreateFromMat(A, hA));
63706977982Sstefanozampini     PetscCall(MatHYPRE_IJMatrixCopyIJ(A, hA->ij));
63806977982Sstefanozampini 
63906977982Sstefanozampini     PetscCall(MatHYPRE_CreateCOOMat(M));
64006977982Sstefanozampini 
64106977982Sstefanozampini     dH = hA->cooMat;
64206977982Sstefanozampini     PetscCall(PetscObjectBaseTypeCompare((PetscObject)hA->cooMat, MATMPIAIJ, &ismpiaij));
64306977982Sstefanozampini     if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(hA->cooMat, &dH, &oH, NULL));
64406977982Sstefanozampini 
64506977982Sstefanozampini     PetscCall(PetscObjectSetName((PetscObject)dH, "_internal_COO_mat_for_hypre"));
64606977982Sstefanozampini     PetscCall(MatSeqAIJGetCOO_Private(dA, &coo_n, &coo_i, &coo_j));
64706977982Sstefanozampini     PetscCall(MatSetPreallocationCOO(dH, coo_n, coo_i, coo_j));
64806977982Sstefanozampini     PetscCall(PetscFree2(coo_i, coo_j));
64906977982Sstefanozampini     if (oH) {
65006977982Sstefanozampini       PetscCall(PetscLayoutDestroy(&oH->cmap));
65106977982Sstefanozampini       PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)oH), oA->cmap->n, oA->cmap->n, 1, &oH->cmap));
65206977982Sstefanozampini       PetscCall(MatSeqAIJGetCOO_Private(oA, &coo_n, &coo_i, &coo_j));
65306977982Sstefanozampini       PetscCall(MatSetPreallocationCOO(oH, coo_n, coo_i, coo_j));
65406977982Sstefanozampini       PetscCall(PetscFree2(coo_i, coo_j));
65506977982Sstefanozampini     }
65606977982Sstefanozampini     hA->cooMat->assembled = PETSC_TRUE;
65706977982Sstefanozampini 
658b73e3080SStefano Zampini     M->preallocated = PETSC_TRUE;
65906977982Sstefanozampini     PetscCall(MatAssemblyBegin(M, MAT_FINAL_ASSEMBLY));
66006977982Sstefanozampini     PetscCall(MatAssemblyEnd(M, MAT_FINAL_ASSEMBLY));
66106977982Sstefanozampini 
66206977982Sstefanozampini     PetscCall(MatHYPRE_AttachCOOMat(M));
66384d4e069SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) *B = M;
664b73e3080SStefano Zampini   } else M = *B;
665b73e3080SStefano Zampini 
666b73e3080SStefano Zampini   hA = (Mat_HYPRE *)M->data;
66706977982Sstefanozampini   PetscCheck(hA->cooMat, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet");
66806977982Sstefanozampini 
66906977982Sstefanozampini   dH = hA->cooMat;
67006977982Sstefanozampini   PetscCall(PetscObjectBaseTypeCompare((PetscObject)hA->cooMat, MATMPIAIJ, &ismpiaij));
67106977982Sstefanozampini   if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(hA->cooMat, &dH, &oH, NULL));
67206977982Sstefanozampini 
67306977982Sstefanozampini   PetscScalar *a;
67406977982Sstefanozampini   PetscCall(MatSeqAIJGetCSRAndMemType(dA, NULL, NULL, &a, NULL));
67506977982Sstefanozampini   PetscCall(MatSetValuesCOO(dH, a, INSERT_VALUES));
67606977982Sstefanozampini   if (oH) {
67706977982Sstefanozampini     PetscCall(MatSeqAIJGetCSRAndMemType(oA, NULL, NULL, &a, NULL));
67806977982Sstefanozampini     PetscCall(MatSetValuesCOO(oH, a, INSERT_VALUES));
67906977982Sstefanozampini   }
680b73e3080SStefano Zampini 
68148a46eb9SPierre Jolivet   if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &M));
6823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
68363c07aadSStefano Zampini }
68463c07aadSStefano Zampini 
685d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_HYPRE_AIJ(Mat A, MatType mtype, MatReuse reuse, Mat *B)
686d71ae5a4SJacob Faibussowitsch {
68706977982Sstefanozampini   Mat                 M, dA = NULL, oA = NULL;
68863c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
68906977982Sstefanozampini   hypre_CSRMatrix    *dH, *oH;
69063c07aadSStefano Zampini   MPI_Comm            comm;
69106977982Sstefanozampini   PetscBool           ismpiaij, isseqaij;
69263c07aadSStefano Zampini 
69363c07aadSStefano Zampini   PetscFunctionBegin;
69463c07aadSStefano Zampini   comm = PetscObjectComm((PetscObject)A);
69563c07aadSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
6969566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATMPIAIJ, &ismpiaij));
6979566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATSEQAIJ, &isseqaij));
69806977982Sstefanozampini     PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Only MATMPIAIJ or MATSEQAIJ base types are supported");
69963c07aadSStefano Zampini   }
70006977982Sstefanozampini   PetscCall(MatHYPREGetParCSR(A, &parcsr));
7016ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
70206977982Sstefanozampini   if (HYPRE_MEMORY_DEVICE == hypre_ParCSRMatrixMemoryLocation(parcsr)) {
70306977982Sstefanozampini     PetscBool isaij;
70406977982Sstefanozampini 
70506977982Sstefanozampini     PetscCall(PetscStrcmp(mtype, MATAIJ, &isaij));
70606977982Sstefanozampini     if (isaij) {
70706977982Sstefanozampini       PetscMPIInt size;
70806977982Sstefanozampini 
7099566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_size(comm, &size));
71006977982Sstefanozampini   #if defined(HYPRE_USING_HIP)
71106977982Sstefanozampini       mtype = size > 1 ? MATMPIAIJHIPSPARSE : MATSEQAIJHIPSPARSE;
71206977982Sstefanozampini   #elif defined(HYPRE_USING_CUDA)
71306977982Sstefanozampini       mtype = size > 1 ? MATMPIAIJCUSPARSE : MATSEQAIJCUSPARSE;
71406977982Sstefanozampini   #else
71506977982Sstefanozampini       mtype = size > 1 ? MATMPIAIJ : MATSEQAIJ;
71606977982Sstefanozampini   #endif
71763c07aadSStefano Zampini     }
71863c07aadSStefano Zampini   }
71906977982Sstefanozampini #endif
72006977982Sstefanozampini   dH = hypre_ParCSRMatrixDiag(parcsr);
72106977982Sstefanozampini   oH = hypre_ParCSRMatrixOffd(parcsr);
7229371c9d4SSatish Balay   if (reuse != MAT_REUSE_MATRIX) {
72306977982Sstefanozampini     PetscCount coo_n;
72406977982Sstefanozampini     PetscInt  *coo_i, *coo_j;
72563c07aadSStefano Zampini 
72606977982Sstefanozampini     PetscCall(MatCreate(comm, &M));
72706977982Sstefanozampini     PetscCall(MatSetType(M, mtype));
72806977982Sstefanozampini     PetscCall(MatSetSizes(M, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
72906977982Sstefanozampini     PetscCall(MatMPIAIJSetPreallocation(M, 0, NULL, 0, NULL));
73063c07aadSStefano Zampini 
73106977982Sstefanozampini     dA = M;
73206977982Sstefanozampini     PetscCall(PetscObjectBaseTypeCompare((PetscObject)M, MATMPIAIJ, &ismpiaij));
73306977982Sstefanozampini     if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(M, &dA, &oA, NULL));
734a16187a7SStefano Zampini 
73506977982Sstefanozampini     PetscCall(hypreCSRMatrixGetCOO_Private(dH, &coo_n, &coo_i, &coo_j));
73606977982Sstefanozampini     PetscCall(MatSetPreallocationCOO(dA, coo_n, coo_i, coo_j));
73706977982Sstefanozampini     PetscCall(PetscFree2(coo_i, coo_j));
73806977982Sstefanozampini     if (ismpiaij) {
73906977982Sstefanozampini       HYPRE_Int nc = hypre_CSRMatrixNumCols(oH);
740a16187a7SStefano Zampini 
74106977982Sstefanozampini       PetscCall(PetscLayoutDestroy(&oA->cmap));
74206977982Sstefanozampini       PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)oA), nc, nc, 1, &oA->cmap));
74306977982Sstefanozampini       PetscCall(hypreCSRMatrixGetCOO_Private(oH, &coo_n, &coo_i, &coo_j));
74406977982Sstefanozampini       PetscCall(MatSetPreallocationCOO(oA, coo_n, coo_i, coo_j));
74506977982Sstefanozampini       PetscCall(PetscFree2(coo_i, coo_j));
746a16187a7SStefano Zampini 
74706977982Sstefanozampini       /* garray */
748*f4f49eeaSPierre Jolivet       Mat_MPIAIJ   *aij    = (Mat_MPIAIJ *)M->data;
74906977982Sstefanozampini       HYPRE_BigInt *harray = hypre_ParCSRMatrixColMapOffd(parcsr);
75006977982Sstefanozampini       PetscInt     *garray;
75106977982Sstefanozampini 
75206977982Sstefanozampini       PetscCall(PetscFree(aij->garray));
75306977982Sstefanozampini       PetscCall(PetscMalloc1(nc, &garray));
75406977982Sstefanozampini       for (HYPRE_Int i = 0; i < nc; i++) garray[i] = (PetscInt)harray[i];
75506977982Sstefanozampini       aij->garray = garray;
75606977982Sstefanozampini       PetscCall(MatSetUpMultiply_MPIAIJ(M));
757a16187a7SStefano Zampini     }
75806977982Sstefanozampini     if (reuse == MAT_INITIAL_MATRIX) *B = M;
75906977982Sstefanozampini   } else M = *B;
760225daaf8SStefano Zampini 
76106977982Sstefanozampini   dA = M;
76206977982Sstefanozampini   PetscCall(PetscObjectBaseTypeCompare((PetscObject)M, MATMPIAIJ, &ismpiaij));
76306977982Sstefanozampini   if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(M, &dA, &oA, NULL));
76406977982Sstefanozampini   PetscCall(MatSetValuesCOOFromCSRMatrix_Private(dA, dH));
76506977982Sstefanozampini   if (oA) PetscCall(MatSetValuesCOOFromCSRMatrix_Private(oA, oH));
76606977982Sstefanozampini   M->assembled = PETSC_TRUE;
76706977982Sstefanozampini   if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &M));
7683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
76963c07aadSStefano Zampini }
77063c07aadSStefano Zampini 
771d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJGetParCSR_Private(Mat A, hypre_ParCSRMatrix **hA)
772d71ae5a4SJacob Faibussowitsch {
773613e5ff0Sstefano_zampini   hypre_ParCSRMatrix *tA;
774c1a070e6SStefano Zampini   hypre_CSRMatrix    *hdiag, *hoffd;
775c1a070e6SStefano Zampini   Mat_SeqAIJ         *diag, *offd;
7762cf14000SStefano Zampini   PetscInt           *garray, i, noffd, dnnz, onnz, *row_starts, *col_starts;
777c1a070e6SStefano Zampini   MPI_Comm            comm = PetscObjectComm((PetscObject)A);
778613e5ff0Sstefano_zampini   PetscBool           ismpiaij, isseqaij;
7792cf14000SStefano Zampini   PetscBool           sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
7806ea7df73SStefano Zampini   HYPRE_Int          *hdi = NULL, *hdj = NULL, *hoi = NULL, *hoj = NULL;
7815c97c10fSStefano Zampini   PetscInt           *pdi = NULL, *pdj = NULL, *poi = NULL, *poj = NULL;
78206977982Sstefanozampini   PetscBool           iscuda, iship;
78306977982Sstefanozampini #if defined(PETSC_HAVE_DEVICE) && defined(PETSC_HAVE_HYPRE_DEVICE)
78406977982Sstefanozampini   PetscBool boundtocpu = A->boundtocpu;
78506977982Sstefanozampini #else
78606977982Sstefanozampini   PetscBool boundtocpu = PETSC_TRUE;
7876ea7df73SStefano Zampini #endif
788c1a070e6SStefano Zampini 
789c1a070e6SStefano Zampini   PetscFunctionBegin;
7909566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
7919566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isseqaij));
79208401ef6SPierre Jolivet   PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Unsupported type %s", ((PetscObject)A)->type_name);
79306977982Sstefanozampini   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iscuda, MATSEQAIJHIPSPARSE, MATMPIAIJCUSPARSE, ""));
79406977982Sstefanozampini   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iship, MATSEQAIJCUSPARSE, MATMPIAIJHIPSPARSE, ""));
795ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
796c1a070e6SStefano Zampini   if (ismpiaij) {
797*f4f49eeaSPierre Jolivet     Mat_MPIAIJ *a = (Mat_MPIAIJ *)A->data;
798c1a070e6SStefano Zampini 
799c1a070e6SStefano Zampini     diag = (Mat_SeqAIJ *)a->A->data;
800c1a070e6SStefano Zampini     offd = (Mat_SeqAIJ *)a->B->data;
80106977982Sstefanozampini     if (!boundtocpu && (iscuda || iship)) {
80206977982Sstefanozampini #if defined(HYPRE_USING_CUDA) && defined(PETSC_HAVE_CUDA)
80306977982Sstefanozampini       if (iscuda) {
8046ea7df73SStefano Zampini         sameint = PETSC_TRUE;
8059566063dSJacob Faibussowitsch         PetscCall(MatSeqAIJCUSPARSEGetIJ(a->A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
8069566063dSJacob Faibussowitsch         PetscCall(MatSeqAIJCUSPARSEGetIJ(a->B, PETSC_FALSE, (const HYPRE_Int **)&hoi, (const HYPRE_Int **)&hoj));
80706977982Sstefanozampini       }
8086ea7df73SStefano Zampini #endif
80906977982Sstefanozampini #if defined(HYPRE_USING_HIP) && defined(PETSC_HAVE_HIP)
81006977982Sstefanozampini       if (iship) {
81106977982Sstefanozampini         sameint = PETSC_TRUE;
81206977982Sstefanozampini         PetscCall(MatSeqAIJHIPSPARSEGetIJ(a->A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
81306977982Sstefanozampini         PetscCall(MatSeqAIJHIPSPARSEGetIJ(a->B, PETSC_FALSE, (const HYPRE_Int **)&hoi, (const HYPRE_Int **)&hoj));
81406977982Sstefanozampini       }
81506977982Sstefanozampini #endif
81606977982Sstefanozampini     } else {
81706977982Sstefanozampini       boundtocpu = PETSC_TRUE;
8186ea7df73SStefano Zampini       pdi        = diag->i;
8196ea7df73SStefano Zampini       pdj        = diag->j;
8206ea7df73SStefano Zampini       poi        = offd->i;
8216ea7df73SStefano Zampini       poj        = offd->j;
8226ea7df73SStefano Zampini       if (sameint) {
8236ea7df73SStefano Zampini         hdi = (HYPRE_Int *)pdi;
8246ea7df73SStefano Zampini         hdj = (HYPRE_Int *)pdj;
8256ea7df73SStefano Zampini         hoi = (HYPRE_Int *)poi;
8266ea7df73SStefano Zampini         hoj = (HYPRE_Int *)poj;
8276ea7df73SStefano Zampini       }
8286ea7df73SStefano Zampini     }
829c1a070e6SStefano Zampini     garray = a->garray;
830c1a070e6SStefano Zampini     noffd  = a->B->cmap->N;
831c1a070e6SStefano Zampini     dnnz   = diag->nz;
832c1a070e6SStefano Zampini     onnz   = offd->nz;
833c1a070e6SStefano Zampini   } else {
834c1a070e6SStefano Zampini     diag = (Mat_SeqAIJ *)A->data;
835c1a070e6SStefano Zampini     offd = NULL;
83606977982Sstefanozampini     if (!boundtocpu && (iscuda || iship)) {
83706977982Sstefanozampini #if defined(HYPRE_USING_CUDA) && defined(PETSC_HAVE_CUDA)
83806977982Sstefanozampini       if (iscuda) {
8396ea7df73SStefano Zampini         sameint = PETSC_TRUE;
8409566063dSJacob Faibussowitsch         PetscCall(MatSeqAIJCUSPARSEGetIJ(A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
84106977982Sstefanozampini       }
8426ea7df73SStefano Zampini #endif
84306977982Sstefanozampini #if defined(HYPRE_USING_HIP) && defined(PETSC_HAVE_HIP)
84406977982Sstefanozampini       if (iship) {
84506977982Sstefanozampini         sameint = PETSC_TRUE;
84606977982Sstefanozampini         PetscCall(MatSeqAIJHIPSPARSEGetIJ(A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
84706977982Sstefanozampini       }
84806977982Sstefanozampini #endif
84906977982Sstefanozampini     } else {
85006977982Sstefanozampini       boundtocpu = PETSC_TRUE;
8516ea7df73SStefano Zampini       pdi        = diag->i;
8526ea7df73SStefano Zampini       pdj        = diag->j;
8536ea7df73SStefano Zampini       if (sameint) {
8546ea7df73SStefano Zampini         hdi = (HYPRE_Int *)pdi;
8556ea7df73SStefano Zampini         hdj = (HYPRE_Int *)pdj;
8566ea7df73SStefano Zampini       }
8576ea7df73SStefano Zampini     }
858c1a070e6SStefano Zampini     garray = NULL;
859c1a070e6SStefano Zampini     noffd  = 0;
860c1a070e6SStefano Zampini     dnnz   = diag->nz;
861c1a070e6SStefano Zampini     onnz   = 0;
862c1a070e6SStefano Zampini   }
863225daaf8SStefano Zampini 
864c1a070e6SStefano Zampini   /* create a temporary ParCSR */
865c1a070e6SStefano Zampini   if (HYPRE_AssumedPartitionCheck()) {
866c1a070e6SStefano Zampini     PetscMPIInt myid;
867c1a070e6SStefano Zampini 
8689566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &myid));
869c1a070e6SStefano Zampini     row_starts = A->rmap->range + myid;
870c1a070e6SStefano Zampini     col_starts = A->cmap->range + myid;
871c1a070e6SStefano Zampini   } else {
872c1a070e6SStefano Zampini     row_starts = A->rmap->range;
873c1a070e6SStefano Zampini     col_starts = A->cmap->range;
874c1a070e6SStefano Zampini   }
8752cf14000SStefano Zampini   tA = hypre_ParCSRMatrixCreate(comm, A->rmap->N, A->cmap->N, (HYPRE_BigInt *)row_starts, (HYPRE_BigInt *)col_starts, noffd, dnnz, onnz);
876a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
877c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetRowStartsOwner(tA, 0);
878c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetColStartsOwner(tA, 0);
879a1d2239cSSatish Balay #endif
880c1a070e6SStefano Zampini 
881225daaf8SStefano Zampini   /* set diagonal part */
882c1a070e6SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(tA);
8836ea7df73SStefano Zampini   if (!sameint) { /* malloc CSR pointers */
8849566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(A->rmap->n + 1, &hdi, dnnz, &hdj));
885*f4f49eeaSPierre Jolivet     for (i = 0; i < A->rmap->n + 1; i++) hdi[i] = (HYPRE_Int)pdi[i];
886*f4f49eeaSPierre Jolivet     for (i = 0; i < dnnz; i++) hdj[i] = (HYPRE_Int)pdj[i];
8872cf14000SStefano Zampini   }
8886ea7df73SStefano Zampini   hypre_CSRMatrixI(hdiag)           = hdi;
8896ea7df73SStefano Zampini   hypre_CSRMatrixJ(hdiag)           = hdj;
89039accc25SStefano Zampini   hypre_CSRMatrixData(hdiag)        = (HYPRE_Complex *)diag->a;
891c1a070e6SStefano Zampini   hypre_CSRMatrixNumNonzeros(hdiag) = diag->nz;
892c1a070e6SStefano Zampini   hypre_CSRMatrixSetRownnz(hdiag);
893c1a070e6SStefano Zampini   hypre_CSRMatrixSetDataOwner(hdiag, 0);
894c1a070e6SStefano Zampini 
8954cf0e950SBarry Smith   /* set off-diagonal part */
896c1a070e6SStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(tA);
897c1a070e6SStefano Zampini   if (offd) {
8986ea7df73SStefano Zampini     if (!sameint) { /* malloc CSR pointers */
8999566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(A->rmap->n + 1, &hoi, onnz, &hoj));
900*f4f49eeaSPierre Jolivet       for (i = 0; i < A->rmap->n + 1; i++) hoi[i] = (HYPRE_Int)poi[i];
901*f4f49eeaSPierre Jolivet       for (i = 0; i < onnz; i++) hoj[i] = (HYPRE_Int)poj[i];
9022cf14000SStefano Zampini     }
9036ea7df73SStefano Zampini     hypre_CSRMatrixI(hoffd)           = hoi;
9046ea7df73SStefano Zampini     hypre_CSRMatrixJ(hoffd)           = hoj;
90539accc25SStefano Zampini     hypre_CSRMatrixData(hoffd)        = (HYPRE_Complex *)offd->a;
906c1a070e6SStefano Zampini     hypre_CSRMatrixNumNonzeros(hoffd) = offd->nz;
907c1a070e6SStefano Zampini     hypre_CSRMatrixSetRownnz(hoffd);
908c1a070e6SStefano Zampini     hypre_CSRMatrixSetDataOwner(hoffd, 0);
9096ea7df73SStefano Zampini   }
9106ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
91106977982Sstefanozampini   PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, !boundtocpu ? HYPRE_MEMORY_DEVICE : HYPRE_MEMORY_HOST);
9126ea7df73SStefano Zampini #else
9136ea7df73SStefano Zampini   #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0)
914792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixInitialize, tA);
9156ea7df73SStefano Zampini   #else
916792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, HYPRE_MEMORY_HOST);
9176ea7df73SStefano Zampini   #endif
9186ea7df73SStefano Zampini #endif
9196ea7df73SStefano Zampini   hypre_TFree(hypre_ParCSRMatrixColMapOffd(tA), HYPRE_MEMORY_HOST);
920c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetNumNonzeros(tA);
9212cf14000SStefano Zampini   hypre_ParCSRMatrixColMapOffd(tA) = (HYPRE_BigInt *)garray;
922792fecdfSBarry Smith   if (!hypre_ParCSRMatrixCommPkg(tA)) PetscCallExternal(hypre_MatvecCommPkgCreate, tA);
923613e5ff0Sstefano_zampini   *hA = tA;
9243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
925613e5ff0Sstefano_zampini }
926c1a070e6SStefano Zampini 
927d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJRestoreParCSR_Private(Mat A, hypre_ParCSRMatrix **hA)
928d71ae5a4SJacob Faibussowitsch {
929613e5ff0Sstefano_zampini   hypre_CSRMatrix *hdiag, *hoffd;
9306ea7df73SStefano Zampini   PetscBool        ismpiaij, sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
9316ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
9326ea7df73SStefano Zampini   PetscBool iscuda = PETSC_FALSE;
9336ea7df73SStefano Zampini #endif
934c1a070e6SStefano Zampini 
935613e5ff0Sstefano_zampini   PetscFunctionBegin;
9369566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
9376ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
9389566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, ""));
9396ea7df73SStefano Zampini   if (iscuda) sameint = PETSC_TRUE;
9406ea7df73SStefano Zampini #endif
941613e5ff0Sstefano_zampini   hdiag = hypre_ParCSRMatrixDiag(*hA);
942613e5ff0Sstefano_zampini   hoffd = hypre_ParCSRMatrixOffd(*hA);
9436ea7df73SStefano Zampini   /* free temporary memory allocated by PETSc
9446ea7df73SStefano Zampini      set pointers to NULL before destroying tA */
9452cf14000SStefano Zampini   if (!sameint) {
9462cf14000SStefano Zampini     HYPRE_Int *hi, *hj;
9472cf14000SStefano Zampini 
9482cf14000SStefano Zampini     hi = hypre_CSRMatrixI(hdiag);
9492cf14000SStefano Zampini     hj = hypre_CSRMatrixJ(hdiag);
9509566063dSJacob Faibussowitsch     PetscCall(PetscFree2(hi, hj));
9516ea7df73SStefano Zampini     if (ismpiaij) {
9522cf14000SStefano Zampini       hi = hypre_CSRMatrixI(hoffd);
9532cf14000SStefano Zampini       hj = hypre_CSRMatrixJ(hoffd);
9549566063dSJacob Faibussowitsch       PetscCall(PetscFree2(hi, hj));
9552cf14000SStefano Zampini     }
9562cf14000SStefano Zampini   }
957c1a070e6SStefano Zampini   hypre_CSRMatrixI(hdiag)    = NULL;
958c1a070e6SStefano Zampini   hypre_CSRMatrixJ(hdiag)    = NULL;
959c1a070e6SStefano Zampini   hypre_CSRMatrixData(hdiag) = NULL;
9606ea7df73SStefano Zampini   if (ismpiaij) {
961c1a070e6SStefano Zampini     hypre_CSRMatrixI(hoffd)    = NULL;
962c1a070e6SStefano Zampini     hypre_CSRMatrixJ(hoffd)    = NULL;
963c1a070e6SStefano Zampini     hypre_CSRMatrixData(hoffd) = NULL;
9646ea7df73SStefano Zampini   }
965613e5ff0Sstefano_zampini   hypre_ParCSRMatrixColMapOffd(*hA) = NULL;
966613e5ff0Sstefano_zampini   hypre_ParCSRMatrixDestroy(*hA);
967613e5ff0Sstefano_zampini   *hA = NULL;
9683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
969613e5ff0Sstefano_zampini }
970613e5ff0Sstefano_zampini 
971613e5ff0Sstefano_zampini /* calls RAP from BoomerAMG:
9723dad0653Sstefano_zampini    the resulting ParCSR will not own the column and row starts
9736ea7df73SStefano Zampini    It looks like we don't need to have the diagonal entries ordered first */
974d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_RAP(hypre_ParCSRMatrix *hR, hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hP, hypre_ParCSRMatrix **hRAP)
975d71ae5a4SJacob Faibussowitsch {
976a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
977613e5ff0Sstefano_zampini   HYPRE_Int P_owns_col_starts, R_owns_row_starts;
978a1d2239cSSatish Balay #endif
979613e5ff0Sstefano_zampini 
980613e5ff0Sstefano_zampini   PetscFunctionBegin;
981a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
982613e5ff0Sstefano_zampini   P_owns_col_starts = hypre_ParCSRMatrixOwnsColStarts(hP);
983613e5ff0Sstefano_zampini   R_owns_row_starts = hypre_ParCSRMatrixOwnsRowStarts(hR);
984a1d2239cSSatish Balay #endif
9856ea7df73SStefano Zampini   /* can be replaced by version test later */
9866ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
987792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParCSRMatrixRAP");
9886ea7df73SStefano Zampini   *hRAP = hypre_ParCSRMatrixRAP(hR, hA, hP);
9896ea7df73SStefano Zampini   PetscStackPop;
9906ea7df73SStefano Zampini #else
991792fecdfSBarry Smith   PetscCallExternal(hypre_BoomerAMGBuildCoarseOperator, hR, hA, hP, hRAP);
992792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixSetNumNonzeros, *hRAP);
9936ea7df73SStefano Zampini #endif
994613e5ff0Sstefano_zampini   /* hypre_BoomerAMGBuildCoarseOperator steals the col_starts from P and the row_starts from R */
995a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
996613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetRowStartsOwner(*hRAP, 0);
997613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetColStartsOwner(*hRAP, 0);
998613e5ff0Sstefano_zampini   if (P_owns_col_starts) hypre_ParCSRMatrixSetColStartsOwner(hP, 1);
999613e5ff0Sstefano_zampini   if (R_owns_row_starts) hypre_ParCSRMatrixSetRowStartsOwner(hR, 1);
1000a1d2239cSSatish Balay #endif
10013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1002613e5ff0Sstefano_zampini }
1003613e5ff0Sstefano_zampini 
1004d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat P, Mat C)
1005d71ae5a4SJacob Faibussowitsch {
10066f231fbdSstefano_zampini   Mat                 B;
10076abb4441SStefano Zampini   hypre_ParCSRMatrix *hA, *hP, *hPtAP = NULL;
10084222ddf1SHong Zhang   Mat_Product        *product = C->product;
1009613e5ff0Sstefano_zampini 
1010613e5ff0Sstefano_zampini   PetscFunctionBegin;
10119566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
10129566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(P, &hP));
10139566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(hP, hA, hP, &hPtAP));
10149566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hPtAP, MATAIJ, PETSC_OWN_POINTER, &B));
10154222ddf1SHong Zhang 
10169566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
10174222ddf1SHong Zhang   C->product = product;
10184222ddf1SHong Zhang 
10199566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
10209566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(P, &hP));
10213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10226f231fbdSstefano_zampini }
10236f231fbdSstefano_zampini 
1024d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatPtAPSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat P, PetscReal fill, Mat C)
1025d71ae5a4SJacob Faibussowitsch {
10266f231fbdSstefano_zampini   PetscFunctionBegin;
10279566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATAIJ));
10284222ddf1SHong Zhang   C->ops->ptapnumeric    = MatPtAPNumeric_AIJ_AIJ_wHYPRE;
10294222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
10303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1031613e5ff0Sstefano_zampini }
1032613e5ff0Sstefano_zampini 
1033d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_HYPRE(Mat A, Mat P, Mat C)
1034d71ae5a4SJacob Faibussowitsch {
10354cc28894Sstefano_zampini   Mat                 B;
10364cc28894Sstefano_zampini   Mat_HYPRE          *hP;
10376abb4441SStefano Zampini   hypre_ParCSRMatrix *hA = NULL, *Pparcsr, *ptapparcsr = NULL;
1038613e5ff0Sstefano_zampini   HYPRE_Int           type;
1039613e5ff0Sstefano_zampini   MPI_Comm            comm = PetscObjectComm((PetscObject)A);
10404cc28894Sstefano_zampini   PetscBool           ishypre;
1041613e5ff0Sstefano_zampini 
1042613e5ff0Sstefano_zampini   PetscFunctionBegin;
10439566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre));
104428b400f6SJacob Faibussowitsch   PetscCheck(ishypre, comm, PETSC_ERR_USER, "P should be of type %s", MATHYPRE);
10454cc28894Sstefano_zampini   hP = (Mat_HYPRE *)P->data;
1046792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type);
104708401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1048792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr);
1049613e5ff0Sstefano_zampini 
10509566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
10519566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, hA, Pparcsr, &ptapparcsr));
10529566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
1053225daaf8SStefano Zampini 
10544cc28894Sstefano_zampini   /* create temporary matrix and merge to C */
10559566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ptapparcsr, ((PetscObject)C)->type_name, PETSC_OWN_POINTER, &B));
10569566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
10573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10584cc28894Sstefano_zampini }
10594cc28894Sstefano_zampini 
1060d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_HYPRE_HYPRE(Mat A, Mat P, Mat C)
1061d71ae5a4SJacob Faibussowitsch {
10624cc28894Sstefano_zampini   Mat                 B;
10636abb4441SStefano Zampini   hypre_ParCSRMatrix *Aparcsr, *Pparcsr, *ptapparcsr = NULL;
10644cc28894Sstefano_zampini   Mat_HYPRE          *hA, *hP;
10654cc28894Sstefano_zampini   PetscBool           ishypre;
10664cc28894Sstefano_zampini   HYPRE_Int           type;
10674cc28894Sstefano_zampini 
10684cc28894Sstefano_zampini   PetscFunctionBegin;
10699566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre));
107028b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)P), PETSC_ERR_USER, "P should be of type %s", MATHYPRE);
10719566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
107228b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE);
10734cc28894Sstefano_zampini   hA = (Mat_HYPRE *)A->data;
10744cc28894Sstefano_zampini   hP = (Mat_HYPRE *)P->data;
1075792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
107608401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1077792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type);
107808401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)P), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1079792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr);
1080792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr);
10819566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, Aparcsr, Pparcsr, &ptapparcsr));
10829566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ptapparcsr, MATHYPRE, PETSC_OWN_POINTER, &B));
10839566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
10843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10854cc28894Sstefano_zampini }
10864cc28894Sstefano_zampini 
1087d501dc42Sstefano_zampini /* calls hypre_ParMatmul
1088d501dc42Sstefano_zampini    hypre_ParMatMul uses hypre_ParMatrixCreate with the communicator of hA
10893dad0653Sstefano_zampini    hypre_ParMatrixCreate does not duplicate the communicator
10906ea7df73SStefano Zampini    It looks like we don't need to have the diagonal entries ordered first */
1091d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_MatMatMult(hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hB, hypre_ParCSRMatrix **hAB)
1092d71ae5a4SJacob Faibussowitsch {
1093d501dc42Sstefano_zampini   PetscFunctionBegin;
10946ea7df73SStefano Zampini   /* can be replaced by version test later */
10956ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
1096792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParCSRMatMat");
10976ea7df73SStefano Zampini   *hAB = hypre_ParCSRMatMat(hA, hB);
10986ea7df73SStefano Zampini #else
1099792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParMatmul");
1100d501dc42Sstefano_zampini   *hAB = hypre_ParMatmul(hA, hB);
11016ea7df73SStefano Zampini #endif
1102d501dc42Sstefano_zampini   PetscStackPop;
11033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1104d501dc42Sstefano_zampini }
1105d501dc42Sstefano_zampini 
1106d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C)
1107d71ae5a4SJacob Faibussowitsch {
11085e5acdf2Sstefano_zampini   Mat                 D;
1109d501dc42Sstefano_zampini   hypre_ParCSRMatrix *hA, *hB, *hAB = NULL;
11104222ddf1SHong Zhang   Mat_Product        *product = C->product;
11115e5acdf2Sstefano_zampini 
11125e5acdf2Sstefano_zampini   PetscFunctionBegin;
11139566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
11149566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(B, &hB));
11159566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_MatMatMult(hA, hB, &hAB));
11169566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hAB, MATAIJ, PETSC_OWN_POINTER, &D));
11174222ddf1SHong Zhang 
11189566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &D));
11194222ddf1SHong Zhang   C->product = product;
11204222ddf1SHong Zhang 
11219566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
11229566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(B, &hB));
11233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11245e5acdf2Sstefano_zampini }
11255e5acdf2Sstefano_zampini 
1126d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatMatMultSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat B, PetscReal fill, Mat C)
1127d71ae5a4SJacob Faibussowitsch {
11285e5acdf2Sstefano_zampini   PetscFunctionBegin;
11299566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATAIJ));
11304222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_AIJ_AIJ_wHYPRE;
11314222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
11323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11335e5acdf2Sstefano_zampini }
11345e5acdf2Sstefano_zampini 
1135d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_HYPRE_HYPRE(Mat A, Mat B, Mat C)
1136d71ae5a4SJacob Faibussowitsch {
1137d501dc42Sstefano_zampini   Mat                 D;
1138d501dc42Sstefano_zampini   hypre_ParCSRMatrix *Aparcsr, *Bparcsr, *ABparcsr = NULL;
1139d501dc42Sstefano_zampini   Mat_HYPRE          *hA, *hB;
1140d501dc42Sstefano_zampini   PetscBool           ishypre;
1141d501dc42Sstefano_zampini   HYPRE_Int           type;
11424222ddf1SHong Zhang   Mat_Product        *product;
1143d501dc42Sstefano_zampini 
1144d501dc42Sstefano_zampini   PetscFunctionBegin;
11459566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)B, MATHYPRE, &ishypre));
114628b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)B), PETSC_ERR_USER, "B should be of type %s", MATHYPRE);
11479566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
114828b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE);
1149d501dc42Sstefano_zampini   hA = (Mat_HYPRE *)A->data;
1150d501dc42Sstefano_zampini   hB = (Mat_HYPRE *)B->data;
1151792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
115208401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1153792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hB->ij, &type);
115408401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1155792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr);
1156792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hB->ij, (void **)&Bparcsr);
11579566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_MatMatMult(Aparcsr, Bparcsr, &ABparcsr));
11589566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ABparcsr, MATHYPRE, PETSC_OWN_POINTER, &D));
11594222ddf1SHong Zhang 
1160d501dc42Sstefano_zampini   /* need to use HeaderReplace because HeaderMerge messes up with the communicator */
11614222ddf1SHong Zhang   product    = C->product; /* save it from MatHeaderReplace() */
11624222ddf1SHong Zhang   C->product = NULL;
11639566063dSJacob Faibussowitsch   PetscCall(MatHeaderReplace(C, &D));
11644222ddf1SHong Zhang   C->product             = product;
1165d501dc42Sstefano_zampini   C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE;
11664222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
11673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1168d501dc42Sstefano_zampini }
1169d501dc42Sstefano_zampini 
1170d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultNumeric_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, Mat D)
1171d71ae5a4SJacob Faibussowitsch {
117220e1dc0dSstefano_zampini   Mat                 E;
11736abb4441SStefano Zampini   hypre_ParCSRMatrix *hA, *hB, *hC, *hABC = NULL;
117420e1dc0dSstefano_zampini 
117520e1dc0dSstefano_zampini   PetscFunctionBegin;
11769566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
11779566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(B, &hB));
11789566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(C, &hC));
11799566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(hA, hB, hC, &hABC));
11809566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hABC, MATAIJ, PETSC_OWN_POINTER, &E));
11819566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(D, &E));
11829566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
11839566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(B, &hB));
11849566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(C, &hC));
11853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
118620e1dc0dSstefano_zampini }
118720e1dc0dSstefano_zampini 
1188d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultSymbolic_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, PetscReal fill, Mat D)
1189d71ae5a4SJacob Faibussowitsch {
119020e1dc0dSstefano_zampini   PetscFunctionBegin;
11919566063dSJacob Faibussowitsch   PetscCall(MatSetType(D, MATAIJ));
11923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
119320e1dc0dSstefano_zampini }
119420e1dc0dSstefano_zampini 
1195d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_AB_HYPRE(Mat C)
1196d71ae5a4SJacob Faibussowitsch {
11974222ddf1SHong Zhang   PetscFunctionBegin;
11984222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
11993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12004222ddf1SHong Zhang }
12014222ddf1SHong Zhang 
1202d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_AB(Mat C)
1203d71ae5a4SJacob Faibussowitsch {
12044222ddf1SHong Zhang   Mat_Product *product = C->product;
12054222ddf1SHong Zhang   PetscBool    Ahypre;
12064222ddf1SHong Zhang 
12074222ddf1SHong Zhang   PetscFunctionBegin;
12089566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)product->A, MATHYPRE, &Ahypre));
12094222ddf1SHong Zhang   if (Ahypre) { /* A is a Hypre matrix */
12109566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
12114222ddf1SHong Zhang     C->ops->productsymbolic = MatProductSymbolic_AB_HYPRE;
12124222ddf1SHong Zhang     C->ops->matmultnumeric  = MatMatMultNumeric_HYPRE_HYPRE;
12133ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
12146718818eSStefano Zampini   }
12153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12164222ddf1SHong Zhang }
12174222ddf1SHong Zhang 
1218d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_PtAP_HYPRE(Mat C)
1219d71ae5a4SJacob Faibussowitsch {
12204222ddf1SHong Zhang   PetscFunctionBegin;
12214222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
12223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12234222ddf1SHong Zhang }
12244222ddf1SHong Zhang 
1225d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_PtAP(Mat C)
1226d71ae5a4SJacob Faibussowitsch {
12274222ddf1SHong Zhang   Mat_Product *product = C->product;
12284222ddf1SHong Zhang   PetscBool    flg;
12294222ddf1SHong Zhang   PetscInt     type        = 0;
12304222ddf1SHong Zhang   const char  *outTypes[4] = {"aij", "seqaij", "mpiaij", "hypre"};
12314222ddf1SHong Zhang   PetscInt     ntype       = 4;
12324222ddf1SHong Zhang   Mat          A           = product->A;
12334222ddf1SHong Zhang   PetscBool    Ahypre;
12344222ddf1SHong Zhang 
12354222ddf1SHong Zhang   PetscFunctionBegin;
12369566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &Ahypre));
12374222ddf1SHong Zhang   if (Ahypre) { /* A is a Hypre matrix */
12389566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
12394222ddf1SHong Zhang     C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE;
12404222ddf1SHong Zhang     C->ops->ptapnumeric     = MatPtAPNumeric_HYPRE_HYPRE;
12413ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
12424222ddf1SHong Zhang   }
12434222ddf1SHong Zhang 
12444222ddf1SHong Zhang   /* A is AIJ, P is Hypre, C = PtAP can be either AIJ or Hypre format */
12454222ddf1SHong Zhang   /* Get runtime option */
12464222ddf1SHong Zhang   if (product->api_user) {
1247d0609cedSBarry Smith     PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatPtAP_HYPRE", "Mat");
12489566063dSJacob Faibussowitsch     PetscCall(PetscOptionsEList("-matptap_hypre_outtype", "MatPtAP outtype", "MatPtAP outtype", outTypes, ntype, outTypes[type], &type, &flg));
1249d0609cedSBarry Smith     PetscOptionsEnd();
12504222ddf1SHong Zhang   } else {
1251d0609cedSBarry Smith     PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatProduct_PtAP_HYPRE", "Mat");
12529566063dSJacob Faibussowitsch     PetscCall(PetscOptionsEList("-mat_product_algorithm_hypre_outtype", "MatProduct_PtAP outtype", "MatProduct_PtAP", outTypes, ntype, outTypes[type], &type, &flg));
1253d0609cedSBarry Smith     PetscOptionsEnd();
12544222ddf1SHong Zhang   }
12554222ddf1SHong Zhang 
12564222ddf1SHong Zhang   if (type == 0 || type == 1 || type == 2) {
12579566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATAIJ));
12584222ddf1SHong Zhang   } else if (type == 3) {
12599566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
12604222ddf1SHong Zhang   } else SETERRQ(PetscObjectComm((PetscObject)C), PETSC_ERR_SUP, "MatPtAP outtype is not supported");
12614222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE;
12624222ddf1SHong Zhang   C->ops->ptapnumeric     = MatPtAPNumeric_AIJ_HYPRE;
12633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12644222ddf1SHong Zhang }
12654222ddf1SHong Zhang 
1266d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE(Mat C)
1267d71ae5a4SJacob Faibussowitsch {
12684222ddf1SHong Zhang   Mat_Product *product = C->product;
12694222ddf1SHong Zhang 
12704222ddf1SHong Zhang   PetscFunctionBegin;
12714222ddf1SHong Zhang   switch (product->type) {
1272d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AB:
1273d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_HYPRE_AB(C));
1274d71ae5a4SJacob Faibussowitsch     break;
1275d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_PtAP:
1276d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_HYPRE_PtAP(C));
1277d71ae5a4SJacob Faibussowitsch     break;
1278d71ae5a4SJacob Faibussowitsch   default:
1279d71ae5a4SJacob Faibussowitsch     break;
12804222ddf1SHong Zhang   }
12813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12824222ddf1SHong Zhang }
12834222ddf1SHong Zhang 
1284d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTranspose_HYPRE(Mat A, Vec x, Vec y)
1285d71ae5a4SJacob Faibussowitsch {
128663c07aadSStefano Zampini   PetscFunctionBegin;
12879566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_TRUE));
12883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
128963c07aadSStefano Zampini }
129063c07aadSStefano Zampini 
1291d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_HYPRE(Mat A, Vec x, Vec y)
1292d71ae5a4SJacob Faibussowitsch {
129363c07aadSStefano Zampini   PetscFunctionBegin;
12949566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_FALSE));
12953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
129663c07aadSStefano Zampini }
129763c07aadSStefano Zampini 
1298d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultAdd_HYPRE(Mat A, Vec x, Vec y, Vec z)
1299d71ae5a4SJacob Faibussowitsch {
1300414bd5c3SStefano Zampini   PetscFunctionBegin;
130148a46eb9SPierre Jolivet   if (y != z) PetscCall(VecCopy(y, z));
13029566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_FALSE));
13033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1304414bd5c3SStefano Zampini }
1305414bd5c3SStefano Zampini 
1306d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTransposeAdd_HYPRE(Mat A, Vec x, Vec y, Vec z)
1307d71ae5a4SJacob Faibussowitsch {
1308414bd5c3SStefano Zampini   PetscFunctionBegin;
130948a46eb9SPierre Jolivet   if (y != z) PetscCall(VecCopy(y, z));
13109566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_TRUE));
13113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1312414bd5c3SStefano Zampini }
1313414bd5c3SStefano Zampini 
1314414bd5c3SStefano Zampini /* y = a * A * x + b * y or y = a * A^t * x + b * y depending on trans */
1315d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_MultKernel_Private(Mat A, HYPRE_Complex a, Vec x, HYPRE_Complex b, Vec y, PetscBool trans)
1316d71ae5a4SJacob Faibussowitsch {
131763c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE *)A->data;
131863c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
131963c07aadSStefano Zampini   hypre_ParVector    *hx, *hy;
132063c07aadSStefano Zampini 
132163c07aadSStefano Zampini   PetscFunctionBegin;
132263c07aadSStefano Zampini   if (trans) {
13239566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorPushVecRead(hA->b, x));
13249566063dSJacob Faibussowitsch     if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->x, y));
13259566063dSJacob Faibussowitsch     else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->x, y));
1326792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hx);
1327792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hy);
132863c07aadSStefano Zampini   } else {
13299566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorPushVecRead(hA->x, x));
13309566063dSJacob Faibussowitsch     if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->b, y));
13319566063dSJacob Faibussowitsch     else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->b, y));
1332792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hx);
1333792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hy);
133463c07aadSStefano Zampini   }
1335792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
13366ea7df73SStefano Zampini   if (trans) {
1337792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMatvecT, a, parcsr, hx, b, hy);
13386ea7df73SStefano Zampini   } else {
1339792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMatvec, a, parcsr, hx, b, hy);
13406ea7df73SStefano Zampini   }
13419566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hA->x));
13429566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hA->b));
13433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
134463c07aadSStefano Zampini }
134563c07aadSStefano Zampini 
1346d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_HYPRE(Mat A)
1347d71ae5a4SJacob Faibussowitsch {
134863c07aadSStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
134963c07aadSStefano Zampini 
135063c07aadSStefano Zampini   PetscFunctionBegin;
13519566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&hA->x));
13529566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&hA->b));
135306977982Sstefanozampini   PetscCall(MatHYPRE_DestroyCOOMat(A)); /* must be called before destroying the individual CSR */
1354978814f1SStefano Zampini   if (hA->ij) {
1355978814f1SStefano Zampini     if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL;
1356792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixDestroy, hA->ij);
1357978814f1SStefano Zampini   }
13589566063dSJacob Faibussowitsch   if (hA->comm) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)A), &hA->comm));
1359c69f721fSFande Kong 
13609566063dSJacob Faibussowitsch   PetscCall(MatStashDestroy_Private(&A->stash));
13619566063dSJacob Faibussowitsch   PetscCall(PetscFree(hA->array));
1362a32e9c99SJunchao Zhang   if (hA->rows_d) PetscStackCallExternalVoid("hypre_Free", hypre_Free(hA->rows_d, HYPRE_MEMORY_DEVICE));
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));
136806977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijhipsparse_hypre_C", NULL));
136906977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaijhipsparse_hypre_C", NULL));
137006977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijcusparse_hypre_C", NULL));
137106977982Sstefanozampini   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;
138306977982Sstefanozampini   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   }
160806977982Sstefanozampini   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));
1756*f4f49eeaSPierre Jolivet   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   }
19444cf0e950SBarry Smith   /* off-diagonal 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 
199666976f2fSJacob Faibussowitsch static 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);
2025a32e9c99SJunchao Zhang #if defined(PETSC_HAVE_HYPRE_DEVICE)
2026a32e9c99SJunchao Zhang   if (HYPRE_MEMORY_DEVICE == hypre_CSRMatrixMemoryLocation(hA)) {
2027a32e9c99SJunchao Zhang   #if defined(HYPRE_USING_CUDA)
2028a32e9c99SJunchao Zhang     MatZeroRows_CUDA(N, rows, i, j, a, diag);
2029a32e9c99SJunchao Zhang   #elif defined(HYPRE_USING_HIP)
2030a32e9c99SJunchao Zhang     MatZeroRows_HIP(N, rows, i, j, a, diag);
2031a32e9c99SJunchao Zhang   #elif defined(PETSC_HAVE_KOKKOS)
2032a32e9c99SJunchao Zhang     MatZeroRows_Kokkos(N, rows, i, j, a, diag);
2033a32e9c99SJunchao Zhang   #else
2034a32e9c99SJunchao Zhang     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for MatZeroRows on a hypre matrix in this memory location");
2035a32e9c99SJunchao Zhang   #endif
2036a32e9c99SJunchao Zhang   } else
2037a32e9c99SJunchao Zhang #endif
2038a32e9c99SJunchao Zhang   {
2039c69f721fSFande Kong     for (ii = 0; ii < N; ii++) {
204039accc25SStefano Zampini       HYPRE_Int jj, ibeg, iend, irow;
204139accc25SStefano Zampini 
2042c69f721fSFande Kong       irow = rows[ii];
2043c69f721fSFande Kong       ibeg = i[irow];
2044c69f721fSFande Kong       iend = i[irow + 1];
2045c69f721fSFande Kong       for (jj = ibeg; jj < iend; jj++)
2046c69f721fSFande Kong         if (j[jj] == irow) a[jj] = diag;
2047c69f721fSFande Kong         else a[jj] = 0.0;
2048c69f721fSFande Kong     }
2049a32e9c99SJunchao Zhang   }
20503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2051c69f721fSFande Kong }
2052c69f721fSFande Kong 
2053d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_HYPRE(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
2054d71ae5a4SJacob Faibussowitsch {
2055c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
2056a32e9c99SJunchao Zhang   PetscInt           *lrows, len, *lrows2;
205739accc25SStefano Zampini   HYPRE_Complex       hdiag;
2058c69f721fSFande Kong 
2059c69f721fSFande Kong   PetscFunctionBegin;
206008401ef6SPierre Jolivet   PetscCheck(!x && !b, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Does not support to modify the solution and the right hand size");
20619566063dSJacob Faibussowitsch   PetscCall(PetscHYPREScalarCast(diag, &hdiag));
2062c69f721fSFande Kong   /* retrieve the internal matrix */
20639566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
2064c69f721fSFande Kong   /* get locally owned rows */
20659566063dSJacob Faibussowitsch   PetscCall(MatZeroRowsMapLocal_Private(A, N, rows, &len, &lrows));
2066a32e9c99SJunchao Zhang 
2067a32e9c99SJunchao Zhang #if defined(PETSC_HAVE_HYPRE_DEVICE)
2068a32e9c99SJunchao Zhang   if (HYPRE_MEMORY_DEVICE == hypre_CSRMatrixMemoryLocation(hypre_ParCSRMatrixDiag(parcsr))) {
2069a32e9c99SJunchao Zhang     Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
2070a32e9c99SJunchao Zhang     PetscInt   m;
2071a32e9c99SJunchao Zhang     PetscCall(MatGetLocalSize(A, &m, NULL));
2072a32e9c99SJunchao Zhang     if (!hA->rows_d) {
2073a32e9c99SJunchao Zhang       hA->rows_d = hypre_TAlloc(PetscInt, m, HYPRE_MEMORY_DEVICE);
2074a32e9c99SJunchao Zhang       if (m) PetscCheck(hA->rows_d, PETSC_COMM_SELF, PETSC_ERR_MEM, "HYPRE_TAlloc failed");
2075a32e9c99SJunchao Zhang     }
2076a32e9c99SJunchao Zhang     PetscCheck(len <= m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Too many rows in rows[]");
2077a32e9c99SJunchao Zhang     PetscStackCallExternalVoid("hypre_Memcpy", hypre_Memcpy(hA->rows_d, lrows, sizeof(PetscInt) * len, HYPRE_MEMORY_DEVICE, HYPRE_MEMORY_HOST));
2078a32e9c99SJunchao Zhang     lrows2 = hA->rows_d;
2079a32e9c99SJunchao Zhang   } else
2080a32e9c99SJunchao Zhang #endif
2081a32e9c99SJunchao Zhang   {
2082a32e9c99SJunchao Zhang     lrows2 = lrows;
2083a32e9c99SJunchao Zhang   }
2084a32e9c99SJunchao Zhang 
2085c69f721fSFande Kong   /* zero diagonal part */
2086a32e9c99SJunchao Zhang   PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr), len, lrows2, hdiag));
2087c69f721fSFande Kong   /* zero off-diagonal part */
2088a32e9c99SJunchao Zhang   PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr), len, lrows2, 0.0));
2089c69f721fSFande Kong 
20909566063dSJacob Faibussowitsch   PetscCall(PetscFree(lrows));
20913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2092c69f721fSFande Kong }
2093c69f721fSFande Kong 
2094d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_HYPRE(Mat mat, MatAssemblyType mode)
2095d71ae5a4SJacob Faibussowitsch {
2096c69f721fSFande Kong   PetscFunctionBegin;
20973ba16761SJacob Faibussowitsch   if (mat->nooffprocentries) PetscFunctionReturn(PETSC_SUCCESS);
2098c69f721fSFande Kong 
20999566063dSJacob Faibussowitsch   PetscCall(MatStashScatterBegin_Private(mat, &mat->stash, mat->rmap->range));
21003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2101c69f721fSFande Kong }
2102c69f721fSFande Kong 
2103d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
2104d71ae5a4SJacob Faibussowitsch {
2105c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
21062cf14000SStefano Zampini   HYPRE_Int           hnz;
2107c69f721fSFande Kong 
2108c69f721fSFande Kong   PetscFunctionBegin;
2109c69f721fSFande Kong   /* retrieve the internal matrix */
21109566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
2111c69f721fSFande Kong   /* call HYPRE API */
2112792fecdfSBarry Smith   PetscCallExternal(HYPRE_ParCSRMatrixGetRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v);
21132cf14000SStefano Zampini   if (nz) *nz = (PetscInt)hnz;
21143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2115c69f721fSFande Kong }
2116c69f721fSFande Kong 
2117d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
2118d71ae5a4SJacob Faibussowitsch {
2119c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
21202cf14000SStefano Zampini   HYPRE_Int           hnz;
2121c69f721fSFande Kong 
2122c69f721fSFande Kong   PetscFunctionBegin;
2123c69f721fSFande Kong   /* retrieve the internal matrix */
21249566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
2125c69f721fSFande Kong   /* call HYPRE API */
21262cf14000SStefano Zampini   hnz = nz ? (HYPRE_Int)(*nz) : 0;
2127792fecdfSBarry Smith   PetscCallExternal(HYPRE_ParCSRMatrixRestoreRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v);
21283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2129c69f721fSFande Kong }
2130c69f721fSFande Kong 
2131d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetValues_HYPRE(Mat A, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2132d71ae5a4SJacob Faibussowitsch {
213345b8d346SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
2134c69f721fSFande Kong   PetscInt   i;
21351d4906efSStefano Zampini 
2136c69f721fSFande Kong   PetscFunctionBegin;
21373ba16761SJacob Faibussowitsch   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2138c69f721fSFande Kong   /* Ignore negative row indices
2139c69f721fSFande Kong    * And negative column indices should be automatically ignored in hypre
2140c69f721fSFande Kong    * */
21412cf14000SStefano Zampini   for (i = 0; i < m; i++) {
21422cf14000SStefano Zampini     if (idxm[i] >= 0) {
21432cf14000SStefano Zampini       HYPRE_Int hn = (HYPRE_Int)n;
2144792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetValues, hA->ij, 1, &hn, (HYPRE_BigInt *)&idxm[i], (HYPRE_BigInt *)idxn, (HYPRE_Complex *)(v + i * n));
21452cf14000SStefano Zampini     }
21462cf14000SStefano Zampini   }
21473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2148c69f721fSFande Kong }
2149c69f721fSFande Kong 
2150d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_HYPRE(Mat A, MatOption op, PetscBool flg)
2151d71ae5a4SJacob Faibussowitsch {
2152ddbeb582SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
2153ddbeb582SStefano Zampini 
2154ddbeb582SStefano Zampini   PetscFunctionBegin;
2155c6698e78SStefano Zampini   switch (op) {
2156ddbeb582SStefano Zampini   case MAT_NO_OFF_PROC_ENTRIES:
215748a46eb9SPierre Jolivet     if (flg) PetscCallExternal(HYPRE_IJMatrixSetMaxOffProcElmts, hA->ij, 0);
2158ddbeb582SStefano Zampini     break;
2159651b1cf9SStefano Zampini   case MAT_IGNORE_OFF_PROC_ENTRIES:
2160651b1cf9SStefano Zampini     hA->donotstash = flg;
2161d71ae5a4SJacob Faibussowitsch     break;
2162d71ae5a4SJacob Faibussowitsch   default:
2163d71ae5a4SJacob Faibussowitsch     break;
2164ddbeb582SStefano Zampini   }
21653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2166ddbeb582SStefano Zampini }
2167c69f721fSFande Kong 
2168d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_HYPRE(Mat A, PetscViewer view)
2169d71ae5a4SJacob Faibussowitsch {
217045b8d346SStefano Zampini   PetscViewerFormat format;
217145b8d346SStefano Zampini 
217245b8d346SStefano Zampini   PetscFunctionBegin;
21739566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(view, &format));
21743ba16761SJacob Faibussowitsch   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(PETSC_SUCCESS);
217545b8d346SStefano Zampini   if (format != PETSC_VIEWER_NATIVE) {
21766ea7df73SStefano Zampini     Mat                 B;
21776ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
21786ea7df73SStefano Zampini     PetscErrorCode (*mview)(Mat, PetscViewer) = NULL;
21796ea7df73SStefano Zampini 
21809566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
21819566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(parcsr, MATAIJ, PETSC_USE_POINTER, &B));
21829566063dSJacob Faibussowitsch     PetscCall(MatGetOperation(B, MATOP_VIEW, (void (**)(void)) & mview));
218328b400f6SJacob Faibussowitsch     PetscCheck(mview, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Missing view operation");
21849566063dSJacob Faibussowitsch     PetscCall((*mview)(B, view));
21859566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
218645b8d346SStefano Zampini   } else {
218745b8d346SStefano Zampini     Mat_HYPRE  *hA = (Mat_HYPRE *)A->data;
218845b8d346SStefano Zampini     PetscMPIInt size;
218945b8d346SStefano Zampini     PetscBool   isascii;
219045b8d346SStefano Zampini     const char *filename;
219145b8d346SStefano Zampini 
219245b8d346SStefano Zampini     /* HYPRE uses only text files */
21939566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERASCII, &isascii));
219428b400f6SJacob Faibussowitsch     PetscCheck(isascii, PetscObjectComm((PetscObject)view), PETSC_ERR_SUP, "PetscViewerType %s: native HYPRE format needs PETSCVIEWERASCII", ((PetscObject)view)->type_name);
21959566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileGetName(view, &filename));
2196792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixPrint, hA->ij, filename);
21979566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(hA->comm, &size));
219845b8d346SStefano Zampini     if (size > 1) {
21999566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(view, "Matrix files: %s.%05d ... %s.%05d\n", filename, 0, filename, size - 1));
220045b8d346SStefano Zampini     } else {
22019566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(view, "Matrix file: %s.%05d\n", filename, 0));
220245b8d346SStefano Zampini     }
220345b8d346SStefano Zampini   }
22043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
220545b8d346SStefano Zampini }
220645b8d346SStefano Zampini 
2207d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCopy_HYPRE(Mat A, Mat B, MatStructure str)
2208d71ae5a4SJacob Faibussowitsch {
2209465edc17SStefano Zampini   hypre_ParCSRMatrix *acsr, *bcsr;
2210465edc17SStefano Zampini 
2211465edc17SStefano Zampini   PetscFunctionBegin;
2212465edc17SStefano Zampini   if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) {
22139566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &acsr));
22149566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(B, &bcsr));
2215792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixCopy, acsr, bcsr, 1);
22169566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_SORTED_FULL, PETSC_TRUE)); /* "perfect" preallocation, so no need for hypre_AuxParCSRMatrixNeedAux */
22179566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
22189566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
2219465edc17SStefano Zampini   } else {
22209566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
2221465edc17SStefano Zampini   }
22223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2223465edc17SStefano Zampini }
2224465edc17SStefano Zampini 
2225d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_HYPRE(Mat A, Vec d)
2226d71ae5a4SJacob Faibussowitsch {
22276305df00SStefano Zampini   hypre_ParCSRMatrix *parcsr;
22286305df00SStefano Zampini   hypre_CSRMatrix    *dmat;
222939accc25SStefano Zampini   HYPRE_Complex      *a;
22306305df00SStefano Zampini   PetscBool           cong;
22316305df00SStefano Zampini 
22326305df00SStefano Zampini   PetscFunctionBegin;
22339566063dSJacob Faibussowitsch   PetscCall(MatHasCongruentLayouts(A, &cong));
223428b400f6SJacob Faibussowitsch   PetscCheck(cong, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only for square matrices with same local distributions of rows and columns");
22359566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
22366305df00SStefano Zampini   dmat = hypre_ParCSRMatrixDiag(parcsr);
22376305df00SStefano Zampini   if (dmat) {
223806977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
223906977982Sstefanozampini     HYPRE_MemoryLocation mem = hypre_CSRMatrixMemoryLocation(dmat);
224006977982Sstefanozampini #else
224106977982Sstefanozampini     HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST;
224206977982Sstefanozampini #endif
224306977982Sstefanozampini 
224406977982Sstefanozampini     if (mem != HYPRE_MEMORY_HOST) PetscCall(VecGetArrayWriteAndMemType(d, (PetscScalar **)&a, NULL));
224506977982Sstefanozampini     else PetscCall(VecGetArrayWrite(d, (PetscScalar **)&a));
224606977982Sstefanozampini     hypre_CSRMatrixExtractDiagonal(dmat, a, 0);
224706977982Sstefanozampini     if (mem != HYPRE_MEMORY_HOST) PetscCall(VecRestoreArrayWriteAndMemType(d, (PetscScalar **)&a));
224806977982Sstefanozampini     else PetscCall(VecRestoreArrayWrite(d, (PetscScalar **)&a));
22496305df00SStefano Zampini   }
22503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22516305df00SStefano Zampini }
22526305df00SStefano Zampini 
2253363d496dSStefano Zampini #include <petscblaslapack.h>
2254363d496dSStefano Zampini 
2255d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAXPY_HYPRE(Mat Y, PetscScalar a, Mat X, MatStructure str)
2256d71ae5a4SJacob Faibussowitsch {
2257363d496dSStefano Zampini   PetscFunctionBegin;
22586ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
22596ea7df73SStefano Zampini   {
22606ea7df73SStefano Zampini     Mat                 B;
22616ea7df73SStefano Zampini     hypre_ParCSRMatrix *x, *y, *z;
22626ea7df73SStefano Zampini 
22639566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(Y, &y));
22649566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(X, &x));
2265792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixAdd, 1.0, y, 1.0, x, &z);
22669566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(z, MATHYPRE, PETSC_OWN_POINTER, &B));
22679566063dSJacob Faibussowitsch     PetscCall(MatHeaderMerge(Y, &B));
22686ea7df73SStefano Zampini   }
22696ea7df73SStefano Zampini #else
2270363d496dSStefano Zampini   if (str == SAME_NONZERO_PATTERN) {
2271363d496dSStefano Zampini     hypre_ParCSRMatrix *x, *y;
2272363d496dSStefano Zampini     hypre_CSRMatrix    *xloc, *yloc;
2273363d496dSStefano Zampini     PetscInt            xnnz, ynnz;
227439accc25SStefano Zampini     HYPRE_Complex      *xarr, *yarr;
2275363d496dSStefano Zampini     PetscBLASInt        one = 1, bnz;
2276363d496dSStefano Zampini 
22779566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(Y, &y));
22789566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(X, &x));
2279363d496dSStefano Zampini 
2280363d496dSStefano Zampini     /* diagonal block */
2281363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixDiag(x);
2282363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixDiag(y);
2283363d496dSStefano Zampini     xnnz = 0;
2284363d496dSStefano Zampini     ynnz = 0;
2285363d496dSStefano Zampini     xarr = NULL;
2286363d496dSStefano Zampini     yarr = NULL;
2287363d496dSStefano Zampini     if (xloc) {
228839accc25SStefano Zampini       xarr = hypre_CSRMatrixData(xloc);
2289363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
2290363d496dSStefano Zampini     }
2291363d496dSStefano Zampini     if (yloc) {
229239accc25SStefano Zampini       yarr = hypre_CSRMatrixData(yloc);
2293363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
2294363d496dSStefano Zampini     }
229508401ef6SPierre Jolivet     PetscCheck(xnnz == ynnz, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Different number of nonzeros in diagonal block %" PetscInt_FMT " != %" PetscInt_FMT, xnnz, ynnz);
22969566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(xnnz, &bnz));
2297792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one));
2298363d496dSStefano Zampini 
2299363d496dSStefano Zampini     /* off-diagonal block */
2300363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixOffd(x);
2301363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixOffd(y);
2302363d496dSStefano Zampini     xnnz = 0;
2303363d496dSStefano Zampini     ynnz = 0;
2304363d496dSStefano Zampini     xarr = NULL;
2305363d496dSStefano Zampini     yarr = NULL;
2306363d496dSStefano Zampini     if (xloc) {
230739accc25SStefano Zampini       xarr = hypre_CSRMatrixData(xloc);
2308363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
2309363d496dSStefano Zampini     }
2310363d496dSStefano Zampini     if (yloc) {
231139accc25SStefano Zampini       yarr = hypre_CSRMatrixData(yloc);
2312363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
2313363d496dSStefano Zampini     }
231408401ef6SPierre 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);
23159566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(xnnz, &bnz));
2316792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one));
2317363d496dSStefano Zampini   } else if (str == SUBSET_NONZERO_PATTERN) {
23189566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic(Y, a, X, str));
2319363d496dSStefano Zampini   } else {
2320363d496dSStefano Zampini     Mat B;
2321363d496dSStefano Zampini 
23229566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic_Preallocate(Y, X, &B));
23239566063dSJacob Faibussowitsch     PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str));
23249566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(Y, &B));
2325363d496dSStefano Zampini   }
23266ea7df73SStefano Zampini #endif
23273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2328363d496dSStefano Zampini }
2329363d496dSStefano Zampini 
23302c4ab24aSJunchao Zhang static PetscErrorCode MatDuplicate_HYPRE(Mat A, MatDuplicateOption op, Mat *B)
23312c4ab24aSJunchao Zhang {
23322c4ab24aSJunchao Zhang   hypre_ParCSRMatrix *parcsr = NULL;
23332c4ab24aSJunchao Zhang   PetscCopyMode       cpmode;
23342c4ab24aSJunchao Zhang   Mat_HYPRE          *hA;
23352c4ab24aSJunchao Zhang 
23362c4ab24aSJunchao Zhang   PetscFunctionBegin;
23372c4ab24aSJunchao Zhang   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
23382c4ab24aSJunchao Zhang   if (op == MAT_DO_NOT_COPY_VALUES || op == MAT_SHARE_NONZERO_PATTERN) {
23392c4ab24aSJunchao Zhang     parcsr = hypre_ParCSRMatrixClone(parcsr, 0);
23402c4ab24aSJunchao Zhang     cpmode = PETSC_OWN_POINTER;
23412c4ab24aSJunchao Zhang   } else {
23422c4ab24aSJunchao Zhang     cpmode = PETSC_COPY_VALUES;
23432c4ab24aSJunchao Zhang   }
23442c4ab24aSJunchao Zhang   PetscCall(MatCreateFromParCSR(parcsr, MATHYPRE, cpmode, B));
23452c4ab24aSJunchao Zhang   hA = (Mat_HYPRE *)A->data;
23462c4ab24aSJunchao Zhang   if (hA->cooMat) {
234706977982Sstefanozampini     Mat_HYPRE *hB = (Mat_HYPRE *)((*B)->data);
2348b73e3080SStefano Zampini     op            = (op == MAT_DO_NOT_COPY_VALUES) ? op : MAT_COPY_VALUES;
2349b73e3080SStefano Zampini     /* Cannot simply increase the reference count of hA->cooMat, since B needs to share cooMat's data array */
235006977982Sstefanozampini     PetscCall(MatDuplicate(hA->cooMat, op, &hB->cooMat));
235106977982Sstefanozampini     PetscCall(MatHYPRE_AttachCOOMat(*B));
23522c4ab24aSJunchao Zhang   }
23532c4ab24aSJunchao Zhang   PetscFunctionReturn(PETSC_SUCCESS);
23542c4ab24aSJunchao Zhang }
23552c4ab24aSJunchao Zhang 
2356d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetPreallocationCOO_HYPRE(Mat mat, PetscCount coo_n, PetscInt coo_i[], PetscInt coo_j[])
2357d71ae5a4SJacob Faibussowitsch {
235806977982Sstefanozampini   Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data;
23595fbaff96SJunchao Zhang 
23605fbaff96SJunchao Zhang   PetscFunctionBegin;
2361651b1cf9SStefano Zampini   /* Build an agent matrix cooMat with AIJ format
23625fbaff96SJunchao 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.
23635fbaff96SJunchao Zhang    */
236406977982Sstefanozampini   PetscCall(MatHYPRE_CreateCOOMat(mat));
236506977982Sstefanozampini   PetscCall(MatSetOption(hmat->cooMat, MAT_IGNORE_OFF_PROC_ENTRIES, hmat->donotstash));
236606977982Sstefanozampini   PetscCall(MatSetOption(hmat->cooMat, MAT_NO_OFF_PROC_ENTRIES, mat->nooffprocentries));
2367651b1cf9SStefano Zampini 
2368651b1cf9SStefano Zampini   /* MatSetPreallocationCOO_SeqAIJ and MatSetPreallocationCOO_MPIAIJ uses this specific
2369651b1cf9SStefano Zampini      name to automatically put the diagonal entries first */
237006977982Sstefanozampini   PetscCall(PetscObjectSetName((PetscObject)hmat->cooMat, "_internal_COO_mat_for_hypre"));
237106977982Sstefanozampini   PetscCall(MatSetPreallocationCOO(hmat->cooMat, coo_n, coo_i, coo_j));
237206977982Sstefanozampini   hmat->cooMat->assembled = PETSC_TRUE;
23735fbaff96SJunchao Zhang 
23745fbaff96SJunchao Zhang   /* Copy the sparsity pattern from cooMat to hypre IJMatrix hmat->ij */
23755fbaff96SJunchao Zhang   PetscCall(MatSetOption(mat, MAT_SORTED_FULL, PETSC_TRUE));
237606977982Sstefanozampini   PetscCall(MatHYPRE_CreateFromMat(hmat->cooMat, hmat));      /* Create hmat->ij and preallocate it */
237706977982Sstefanozampini   PetscCall(MatHYPRE_IJMatrixCopyIJ(hmat->cooMat, hmat->ij)); /* Copy A's (i,j) to hmat->ij */
23785fbaff96SJunchao Zhang 
23795fbaff96SJunchao Zhang   mat->preallocated = PETSC_TRUE;
23805fbaff96SJunchao Zhang   PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
23815fbaff96SJunchao Zhang   PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); /* Migrate mat to device if it is bound to. Hypre builds its own SpMV context here */
23825fbaff96SJunchao Zhang 
23832c4ab24aSJunchao Zhang   /* Attach cooMat to mat */
238406977982Sstefanozampini   PetscCall(MatHYPRE_AttachCOOMat(mat));
23853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23865fbaff96SJunchao Zhang }
23875fbaff96SJunchao Zhang 
2388d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesCOO_HYPRE(Mat mat, const PetscScalar v[], InsertMode imode)
2389d71ae5a4SJacob Faibussowitsch {
23905fbaff96SJunchao Zhang   Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data;
23915fbaff96SJunchao Zhang 
23925fbaff96SJunchao Zhang   PetscFunctionBegin;
2393b73e3080SStefano Zampini   PetscCheck(hmat->cooMat, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet");
23945fbaff96SJunchao Zhang   PetscCall(MatSetValuesCOO(hmat->cooMat, v, imode));
2395651b1cf9SStefano Zampini   PetscCall(MatViewFromOptions(hmat->cooMat, (PetscObject)mat, "-cooMat_view"));
23963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23975fbaff96SJunchao Zhang }
23985fbaff96SJunchao Zhang 
2399a055b5aaSBarry Smith /*MC
24002ef1f0ffSBarry Smith    MATHYPRE - "hypre" - A matrix type to be used for sequential and parallel sparse matrices
2401a055b5aaSBarry Smith           based on the hypre IJ interface.
2402a055b5aaSBarry Smith 
2403a055b5aaSBarry Smith    Level: intermediate
2404a055b5aaSBarry Smith 
24051cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatHYPRESetPreallocation`
2406a055b5aaSBarry Smith M*/
2407a055b5aaSBarry Smith 
2408d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_HYPRE(Mat B)
2409d71ae5a4SJacob Faibussowitsch {
241063c07aadSStefano Zampini   Mat_HYPRE *hB;
241163c07aadSStefano Zampini 
241263c07aadSStefano Zampini   PetscFunctionBegin;
24134dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&hB));
24146ea7df73SStefano Zampini 
2415978814f1SStefano Zampini   hB->inner_free      = PETSC_TRUE;
2416651b1cf9SStefano Zampini   hB->array_available = PETSC_TRUE;
2417978814f1SStefano Zampini 
241863c07aadSStefano Zampini   B->data = (void *)hB;
241963c07aadSStefano Zampini 
24209566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(B->ops, sizeof(struct _MatOps)));
242163c07aadSStefano Zampini   B->ops->mult                  = MatMult_HYPRE;
242263c07aadSStefano Zampini   B->ops->multtranspose         = MatMultTranspose_HYPRE;
2423414bd5c3SStefano Zampini   B->ops->multadd               = MatMultAdd_HYPRE;
2424414bd5c3SStefano Zampini   B->ops->multtransposeadd      = MatMultTransposeAdd_HYPRE;
242563c07aadSStefano Zampini   B->ops->setup                 = MatSetUp_HYPRE;
242663c07aadSStefano Zampini   B->ops->destroy               = MatDestroy_HYPRE;
242763c07aadSStefano Zampini   B->ops->assemblyend           = MatAssemblyEnd_HYPRE;
2428c69f721fSFande Kong   B->ops->assemblybegin         = MatAssemblyBegin_HYPRE;
2429d975228cSstefano_zampini   B->ops->setvalues             = MatSetValues_HYPRE;
243068ec7858SStefano Zampini   B->ops->missingdiagonal       = MatMissingDiagonal_HYPRE;
243168ec7858SStefano Zampini   B->ops->scale                 = MatScale_HYPRE;
243268ec7858SStefano Zampini   B->ops->zerorowscolumns       = MatZeroRowsColumns_HYPRE;
2433c69f721fSFande Kong   B->ops->zeroentries           = MatZeroEntries_HYPRE;
2434c69f721fSFande Kong   B->ops->zerorows              = MatZeroRows_HYPRE;
2435c69f721fSFande Kong   B->ops->getrow                = MatGetRow_HYPRE;
2436c69f721fSFande Kong   B->ops->restorerow            = MatRestoreRow_HYPRE;
2437c69f721fSFande Kong   B->ops->getvalues             = MatGetValues_HYPRE;
2438ddbeb582SStefano Zampini   B->ops->setoption             = MatSetOption_HYPRE;
243945b8d346SStefano Zampini   B->ops->duplicate             = MatDuplicate_HYPRE;
2440465edc17SStefano Zampini   B->ops->copy                  = MatCopy_HYPRE;
244145b8d346SStefano Zampini   B->ops->view                  = MatView_HYPRE;
24426305df00SStefano Zampini   B->ops->getdiagonal           = MatGetDiagonal_HYPRE;
2443363d496dSStefano Zampini   B->ops->axpy                  = MatAXPY_HYPRE;
24444222ddf1SHong Zhang   B->ops->productsetfromoptions = MatProductSetFromOptions_HYPRE;
24456ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
24466ea7df73SStefano Zampini   B->ops->bindtocpu = MatBindToCPU_HYPRE;
24476ea7df73SStefano Zampini   B->boundtocpu     = PETSC_FALSE;
24486ea7df73SStefano Zampini #endif
244945b8d346SStefano Zampini 
245045b8d346SStefano Zampini   /* build cache for off array entries formed */
24519566063dSJacob Faibussowitsch   PetscCall(MatStashCreate_Private(PetscObjectComm((PetscObject)B), 1, &B->stash));
245263c07aadSStefano Zampini 
24539566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)B), &hB->comm));
24549566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRE));
24559566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_aij_C", MatConvert_HYPRE_AIJ));
24569566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_is_C", MatConvert_HYPRE_IS));
24579566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_hypre_C", MatProductSetFromOptions_HYPRE));
24589566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaij_hypre_C", MatProductSetFromOptions_HYPRE));
24599566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPRESetPreallocation_C", MatHYPRESetPreallocation_HYPRE));
24609566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPREGetParCSR_C", MatHYPREGetParCSR_HYPRE));
24615fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_HYPRE));
24625fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetValuesCOO_C", MatSetValuesCOO_HYPRE));
24636ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
24646ea7df73SStefano Zampini   #if defined(HYPRE_USING_HIP)
246506977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijhipsparse_hypre_C", MatProductSetFromOptions_HYPRE));
246606977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaijhipsparse_hypre_C", MatProductSetFromOptions_HYPRE));
24679566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP));
24689566063dSJacob Faibussowitsch   PetscCall(MatSetVecType(B, VECHIP));
24696ea7df73SStefano Zampini   #endif
24706ea7df73SStefano Zampini   #if defined(HYPRE_USING_CUDA)
247106977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijcusparse_hypre_C", MatProductSetFromOptions_HYPRE));
247206977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaijcusparse_hypre_C", MatProductSetFromOptions_HYPRE));
24739566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
24749566063dSJacob Faibussowitsch   PetscCall(MatSetVecType(B, VECCUDA));
24756ea7df73SStefano Zampini   #endif
24766ea7df73SStefano Zampini #endif
2477ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
24783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
247963c07aadSStefano Zampini }
2480