xref: /petsc/src/mat/impls/hypre/mhypre.c (revision 87ef5fa6811571b1c9af112cbc5dd26bafbd084e)
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);
148*87ef5fa6SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
14963c07aadSStefano Zampini }
15063c07aadSStefano Zampini 
151b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_SeqAIJ(Mat A, HYPRE_IJMatrix ij)
152d71ae5a4SJacob Faibussowitsch {
15363c07aadSStefano Zampini   Mat_SeqAIJ            *pdiag = (Mat_SeqAIJ *)A->data;
15458968eb6SStefano Zampini   HYPRE_Int              type;
15563c07aadSStefano Zampini   hypre_ParCSRMatrix    *par_matrix;
15663c07aadSStefano Zampini   hypre_AuxParCSRMatrix *aux_matrix;
15763c07aadSStefano Zampini   hypre_CSRMatrix       *hdiag;
1582cf14000SStefano Zampini   PetscBool              sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
15963c07aadSStefano Zampini 
16063c07aadSStefano Zampini   PetscFunctionBegin;
161792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type);
16208401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
163792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix);
16463c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(par_matrix);
16563c07aadSStefano Zampini   /*
16663c07aadSStefano Zampini        this is the Hack part where we monkey directly with the hypre datastructures
16763c07aadSStefano Zampini   */
1682cf14000SStefano Zampini   if (sameint) {
1699566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hdiag->i, pdiag->i, A->rmap->n + 1));
1709566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hdiag->j, pdiag->j, pdiag->nz));
1712cf14000SStefano Zampini   } else {
1722cf14000SStefano Zampini     PetscInt i;
1732cf14000SStefano Zampini 
1742cf14000SStefano Zampini     for (i = 0; i < A->rmap->n + 1; i++) hdiag->i[i] = (HYPRE_Int)pdiag->i[i];
1752cf14000SStefano Zampini     for (i = 0; i < pdiag->nz; i++) hdiag->j[i] = (HYPRE_Int)pdiag->j[i];
1762cf14000SStefano Zampini   }
1776ea7df73SStefano Zampini 
178ea9daf28SStefano Zampini   aux_matrix                               = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij);
17963c07aadSStefano Zampini   hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
1803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18163c07aadSStefano Zampini }
18263c07aadSStefano Zampini 
183b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_MPIAIJ(Mat A, HYPRE_IJMatrix ij)
184d71ae5a4SJacob Faibussowitsch {
18563c07aadSStefano Zampini   Mat_MPIAIJ            *pA = (Mat_MPIAIJ *)A->data;
18663c07aadSStefano Zampini   Mat_SeqAIJ            *pdiag, *poffd;
18763c07aadSStefano Zampini   PetscInt               i, *garray = pA->garray, *jj, cstart, *pjj;
1882cf14000SStefano Zampini   HYPRE_Int             *hjj, type;
18963c07aadSStefano Zampini   hypre_ParCSRMatrix    *par_matrix;
19063c07aadSStefano Zampini   hypre_AuxParCSRMatrix *aux_matrix;
19163c07aadSStefano Zampini   hypre_CSRMatrix       *hdiag, *hoffd;
1922cf14000SStefano Zampini   PetscBool              sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
19363c07aadSStefano Zampini 
19463c07aadSStefano Zampini   PetscFunctionBegin;
19563c07aadSStefano Zampini   pdiag = (Mat_SeqAIJ *)pA->A->data;
19663c07aadSStefano Zampini   poffd = (Mat_SeqAIJ *)pA->B->data;
197da81f932SPierre Jolivet   /* cstart is only valid for square MPIAIJ laid out in the usual way */
1989566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &cstart, NULL));
19963c07aadSStefano Zampini 
200792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type);
20108401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
202792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix);
20363c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(par_matrix);
20463c07aadSStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(par_matrix);
20563c07aadSStefano Zampini 
2062cf14000SStefano Zampini   if (sameint) {
2079566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hdiag->i, pdiag->i, pA->A->rmap->n + 1));
2082cf14000SStefano Zampini   } else {
209f4f49eeaSPierre Jolivet     for (i = 0; i < pA->A->rmap->n + 1; i++) hdiag->i[i] = (HYPRE_Int)pdiag->i[i];
2102cf14000SStefano Zampini   }
211b73e3080SStefano Zampini 
2122cf14000SStefano Zampini   hjj = hdiag->j;
2132cf14000SStefano Zampini   pjj = pdiag->j;
214c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0)
2152cf14000SStefano Zampini   for (i = 0; i < pdiag->nz; i++) hjj[i] = pjj[i];
216c6698e78SStefano Zampini #else
2172cf14000SStefano Zampini   for (i = 0; i < pdiag->nz; i++) hjj[i] = cstart + pjj[i];
218c6698e78SStefano Zampini #endif
2192cf14000SStefano Zampini   if (sameint) {
2209566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hoffd->i, poffd->i, pA->A->rmap->n + 1));
2212cf14000SStefano Zampini   } else {
222f4f49eeaSPierre Jolivet     for (i = 0; i < pA->A->rmap->n + 1; i++) hoffd->i[i] = (HYPRE_Int)poffd->i[i];
2232cf14000SStefano Zampini   }
2242cf14000SStefano Zampini 
22506977982Sstefanozampini   jj = (PetscInt *)hoffd->j;
226c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0)
227792fecdfSBarry Smith   PetscCallExternal(hypre_CSRMatrixBigInitialize, hoffd);
228c6698e78SStefano Zampini   jj = (PetscInt *)hoffd->big_j;
229c6698e78SStefano Zampini #endif
2302cf14000SStefano Zampini   pjj = poffd->j;
23163c07aadSStefano Zampini   for (i = 0; i < poffd->nz; i++) jj[i] = garray[pjj[i]];
232c6698e78SStefano Zampini 
233ea9daf28SStefano Zampini   aux_matrix                               = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij);
23463c07aadSStefano Zampini   hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
2353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23663c07aadSStefano Zampini }
23763c07aadSStefano Zampini 
238d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_HYPRE_IS(Mat A, MatType mtype, MatReuse reuse, Mat *B)
239d71ae5a4SJacob Faibussowitsch {
240f4f49eeaSPierre Jolivet   Mat_HYPRE             *mhA = (Mat_HYPRE *)A->data;
2412df22349SStefano Zampini   Mat                    lA;
2422df22349SStefano Zampini   ISLocalToGlobalMapping rl2g, cl2g;
2432df22349SStefano Zampini   IS                     is;
2442df22349SStefano Zampini   hypre_ParCSRMatrix    *hA;
2452df22349SStefano Zampini   hypre_CSRMatrix       *hdiag, *hoffd;
2462df22349SStefano Zampini   MPI_Comm               comm;
24739accc25SStefano Zampini   HYPRE_Complex         *hdd, *hod, *aa;
24839accc25SStefano Zampini   PetscScalar           *data;
2492cf14000SStefano Zampini   HYPRE_BigInt          *col_map_offd;
2502cf14000SStefano Zampini   HYPRE_Int             *hdi, *hdj, *hoi, *hoj;
2512df22349SStefano Zampini   PetscInt              *ii, *jj, *iptr, *jptr;
2522df22349SStefano Zampini   PetscInt               cum, dr, dc, oc, str, stc, nnz, i, jd, jo, M, N;
25358968eb6SStefano Zampini   HYPRE_Int              type;
25406977982Sstefanozampini   MatType                lmattype   = NULL;
25506977982Sstefanozampini   PetscBool              freeparcsr = PETSC_FALSE;
2562df22349SStefano Zampini 
2572df22349SStefano Zampini   PetscFunctionBegin;
258a1787963SStefano Zampini   comm = PetscObjectComm((PetscObject)A);
259792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, mhA->ij, &type);
26008401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
261792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, mhA->ij, (void **)&hA);
26206977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
26306977982Sstefanozampini   if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(mhA->ij)) {
26406977982Sstefanozampini     /* Support by copying back on the host and copy to GPU
26506977982Sstefanozampini        Kind of inefficient, but this is the best we can do now */
26606977982Sstefanozampini   #if defined(HYPRE_USING_HIP)
26706977982Sstefanozampini     lmattype = MATSEQAIJHIPSPARSE;
26806977982Sstefanozampini   #elif defined(HYPRE_USING_CUDA)
26906977982Sstefanozampini     lmattype = MATSEQAIJCUSPARSE;
27006977982Sstefanozampini   #endif
27106977982Sstefanozampini     hA         = hypre_ParCSRMatrixClone_v2(hA, 1, HYPRE_MEMORY_HOST);
27206977982Sstefanozampini     freeparcsr = PETSC_TRUE;
27306977982Sstefanozampini   }
27406977982Sstefanozampini #endif
2752df22349SStefano Zampini   M     = hypre_ParCSRMatrixGlobalNumRows(hA);
2762df22349SStefano Zampini   N     = hypre_ParCSRMatrixGlobalNumCols(hA);
2772df22349SStefano Zampini   str   = hypre_ParCSRMatrixFirstRowIndex(hA);
2782df22349SStefano Zampini   stc   = hypre_ParCSRMatrixFirstColDiag(hA);
2792df22349SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(hA);
2802df22349SStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(hA);
2812df22349SStefano Zampini   dr    = hypre_CSRMatrixNumRows(hdiag);
2822df22349SStefano Zampini   dc    = hypre_CSRMatrixNumCols(hdiag);
2832df22349SStefano Zampini   nnz   = hypre_CSRMatrixNumNonzeros(hdiag);
2842df22349SStefano Zampini   hdi   = hypre_CSRMatrixI(hdiag);
2852df22349SStefano Zampini   hdj   = hypre_CSRMatrixJ(hdiag);
2862df22349SStefano Zampini   hdd   = hypre_CSRMatrixData(hdiag);
2872df22349SStefano Zampini   oc    = hypre_CSRMatrixNumCols(hoffd);
2882df22349SStefano Zampini   nnz += hypre_CSRMatrixNumNonzeros(hoffd);
2892df22349SStefano Zampini   hoi = hypre_CSRMatrixI(hoffd);
2902df22349SStefano Zampini   hoj = hypre_CSRMatrixJ(hoffd);
2912df22349SStefano Zampini   hod = hypre_CSRMatrixData(hoffd);
2922df22349SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
2932df22349SStefano Zampini     PetscInt *aux;
2942df22349SStefano Zampini 
2952df22349SStefano Zampini     /* generate l2g maps for rows and cols */
2969566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(comm, dr, str, 1, &is));
2979566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g));
2989566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
2992df22349SStefano Zampini     col_map_offd = hypre_ParCSRMatrixColMapOffd(hA);
3009566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dc + oc, &aux));
3012df22349SStefano Zampini     for (i = 0; i < dc; i++) aux[i] = i + stc;
3022df22349SStefano Zampini     for (i = 0; i < oc; i++) aux[i + dc] = col_map_offd[i];
3039566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, dc + oc, aux, PETSC_OWN_POINTER, &is));
3049566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g));
3059566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
3062df22349SStefano Zampini     /* create MATIS object */
3079566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm, B));
3089566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(*B, dr, dc, M, N));
3099566063dSJacob Faibussowitsch     PetscCall(MatSetType(*B, MATIS));
3109566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(*B, rl2g, cl2g));
3119566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
3129566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
3132df22349SStefano Zampini 
3142df22349SStefano Zampini     /* allocate CSR for local matrix */
3159566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dr + 1, &iptr));
3169566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &jptr));
3179566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &data));
3182df22349SStefano Zampini   } else {
3192df22349SStefano Zampini     PetscInt  nr;
3202df22349SStefano Zampini     PetscBool done;
3219566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(*B, &lA));
3229566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(lA, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&iptr, (const PetscInt **)&jptr, &done));
32308401ef6SPierre Jolivet     PetscCheck(nr == dr, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of rows in local mat! %" PetscInt_FMT " != %" PetscInt_FMT, nr, dr);
32408401ef6SPierre Jolivet     PetscCheck(iptr[nr] >= nnz, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of nonzeros in local mat! reuse %" PetscInt_FMT " requested %" PetscInt_FMT, iptr[nr], nnz);
32506977982Sstefanozampini     PetscCall(MatSeqAIJGetArrayWrite(lA, &data));
3262df22349SStefano Zampini   }
3272df22349SStefano Zampini   /* merge local matrices */
3282df22349SStefano Zampini   ii  = iptr;
3292df22349SStefano Zampini   jj  = jptr;
33039accc25SStefano Zampini   aa  = (HYPRE_Complex *)data; /* this cast fixes the clang error when doing the assignments below: implicit conversion from 'HYPRE_Complex' (aka '_Complex double') to 'double' is not permitted in C++ */
3312df22349SStefano Zampini   *ii = *(hdi++) + *(hoi++);
3322df22349SStefano Zampini   for (jd = 0, jo = 0, cum = 0; *ii < nnz; cum++) {
33339accc25SStefano Zampini     PetscScalar *aold = (PetscScalar *)aa;
3342df22349SStefano Zampini     PetscInt    *jold = jj, nc = jd + jo;
3359371c9d4SSatish Balay     for (; jd < *hdi; jd++) {
3369371c9d4SSatish Balay       *jj++ = *hdj++;
3379371c9d4SSatish Balay       *aa++ = *hdd++;
3389371c9d4SSatish Balay     }
3399371c9d4SSatish Balay     for (; jo < *hoi; jo++) {
3409371c9d4SSatish Balay       *jj++ = *hoj++ + dc;
3419371c9d4SSatish Balay       *aa++ = *hod++;
3429371c9d4SSatish Balay     }
3432df22349SStefano Zampini     *(++ii) = *(hdi++) + *(hoi++);
3449566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithScalarArray(jd + jo - nc, jold, aold));
3452df22349SStefano Zampini   }
3462df22349SStefano Zampini   for (; cum < dr; cum++) *(++ii) = nnz;
3472df22349SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
348a033916dSStefano Zampini     Mat_SeqAIJ *a;
349a033916dSStefano Zampini 
3509566063dSJacob Faibussowitsch     PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, dr, dc + oc, iptr, jptr, data, &lA));
351a033916dSStefano Zampini     /* hack SeqAIJ */
352f4f49eeaSPierre Jolivet     a          = (Mat_SeqAIJ *)lA->data;
353a033916dSStefano Zampini     a->free_a  = PETSC_TRUE;
354a033916dSStefano Zampini     a->free_ij = PETSC_TRUE;
35506977982Sstefanozampini     if (lmattype) PetscCall(MatConvert(lA, lmattype, MAT_INPLACE_MATRIX, &lA));
35606977982Sstefanozampini     PetscCall(MatISSetLocalMat(*B, lA));
3579566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&lA));
35806977982Sstefanozampini   } else {
35906977982Sstefanozampini     PetscCall(MatSeqAIJRestoreArrayWrite(lA, &data));
3602df22349SStefano Zampini   }
3619566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY));
3629566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY));
36348a46eb9SPierre Jolivet   if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, B));
36406977982Sstefanozampini   if (freeparcsr) PetscCallExternal(hypre_ParCSRMatrixDestroy, hA);
3653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3662df22349SStefano Zampini }
3672df22349SStefano Zampini 
36806977982Sstefanozampini static PetscErrorCode MatHYPRE_DestroyCOOMat(Mat mat)
369d71ae5a4SJacob Faibussowitsch {
37006977982Sstefanozampini   Mat_HYPRE *hA = (Mat_HYPRE *)mat->data;
37163c07aadSStefano Zampini 
37263c07aadSStefano Zampini   PetscFunctionBegin;
37306977982Sstefanozampini   if (hA->cooMat) { /* If cooMat is present we need to destroy the column indices */
37406977982Sstefanozampini     PetscCall(MatDestroy(&hA->cooMat));
37506977982Sstefanozampini     if (hA->cooMatAttached) {
37606977982Sstefanozampini       hypre_CSRMatrix     *csr;
37706977982Sstefanozampini       hypre_ParCSRMatrix  *parcsr;
37806977982Sstefanozampini       HYPRE_MemoryLocation mem;
37906977982Sstefanozampini 
38006977982Sstefanozampini       PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
38106977982Sstefanozampini       csr = hypre_ParCSRMatrixDiag(parcsr);
38206977982Sstefanozampini       if (csr) {
38306977982Sstefanozampini         mem = hypre_CSRMatrixMemoryLocation(csr);
38406977982Sstefanozampini         PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixJ(csr), mem));
38506977982Sstefanozampini         PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixBigJ(csr), mem));
386b73e3080SStefano Zampini       }
38706977982Sstefanozampini       csr = hypre_ParCSRMatrixOffd(parcsr);
38806977982Sstefanozampini       if (csr) {
38906977982Sstefanozampini         mem = hypre_CSRMatrixMemoryLocation(csr);
39006977982Sstefanozampini         PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixJ(csr), mem));
39106977982Sstefanozampini         PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixBigJ(csr), mem));
392b73e3080SStefano Zampini       }
393b73e3080SStefano Zampini     }
39406977982Sstefanozampini   }
39506977982Sstefanozampini   hA->cooMatAttached = PETSC_FALSE;
396b73e3080SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
397b73e3080SStefano Zampini }
398b73e3080SStefano Zampini 
39906977982Sstefanozampini static PetscErrorCode MatHYPRE_CreateCOOMat(Mat mat)
400b73e3080SStefano Zampini {
40106977982Sstefanozampini   MPI_Comm    comm;
40206977982Sstefanozampini   PetscMPIInt size;
40306977982Sstefanozampini   PetscLayout rmap, cmap;
40406977982Sstefanozampini   Mat_HYPRE  *hmat    = (Mat_HYPRE *)mat->data;
40506977982Sstefanozampini   MatType     matType = MATAIJ; /* default type of cooMat */
406b73e3080SStefano Zampini 
407b73e3080SStefano Zampini   PetscFunctionBegin;
40806977982Sstefanozampini   /* Build an agent matrix cooMat with AIJ format
40906977982Sstefanozampini      It has the same sparsity pattern as mat, and also shares the data array with mat. We use cooMat to do the COO work.
41006977982Sstefanozampini    */
41106977982Sstefanozampini   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
41206977982Sstefanozampini   PetscCallMPI(MPI_Comm_size(comm, &size));
41306977982Sstefanozampini   PetscCall(PetscLayoutSetUp(mat->rmap));
41406977982Sstefanozampini   PetscCall(PetscLayoutSetUp(mat->cmap));
41506977982Sstefanozampini   PetscCall(MatGetLayouts(mat, &rmap, &cmap));
416b73e3080SStefano Zampini 
41706977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
41806977982Sstefanozampini   if (!mat->boundtocpu) { /* mat will be on device, so will cooMat */
41906977982Sstefanozampini   #if defined(HYPRE_USING_HIP)
42006977982Sstefanozampini     matType = MATAIJHIPSPARSE;
42106977982Sstefanozampini   #elif defined(HYPRE_USING_CUDA)
42206977982Sstefanozampini     matType = MATAIJCUSPARSE;
42306977982Sstefanozampini   #else
42406977982Sstefanozampini     SETERRQ(comm, PETSC_ERR_SUP, "Do not know the HYPRE device");
42506977982Sstefanozampini   #endif
426b73e3080SStefano Zampini   }
42706977982Sstefanozampini #endif
42806977982Sstefanozampini 
42906977982Sstefanozampini   /* Do COO preallocation through cooMat */
43006977982Sstefanozampini   PetscCall(MatHYPRE_DestroyCOOMat(mat));
43106977982Sstefanozampini   PetscCall(MatCreate(comm, &hmat->cooMat));
43206977982Sstefanozampini   PetscCall(MatSetType(hmat->cooMat, matType));
43306977982Sstefanozampini   PetscCall(MatSetLayouts(hmat->cooMat, rmap, cmap));
43406977982Sstefanozampini 
43506977982Sstefanozampini   /* allocate local matrices if needed */
43606977982Sstefanozampini   PetscCall(MatMPIAIJSetPreallocation(hmat->cooMat, 0, NULL, 0, NULL));
43706977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
43806977982Sstefanozampini }
43906977982Sstefanozampini 
44006977982Sstefanozampini /* Attach cooMat data array to hypre matrix.
44106977982Sstefanozampini    When AIJCUPMSPARSE will support raw device pointers and not THRUSTARRAY
44206977982Sstefanozampini    we should swap the arrays: i.e., attach hypre matrix array to cooMat
44306977982Sstefanozampini    This is because hypre should be in charge of handling the memory,
44406977982Sstefanozampini    cooMat is only a way to reuse PETSc COO code.
44506977982Sstefanozampini    attaching the memory will then be done at MatSetValuesCOO time and it will dynamically
44606977982Sstefanozampini    support hypre matrix migrating to host.
44706977982Sstefanozampini */
44806977982Sstefanozampini static PetscErrorCode MatHYPRE_AttachCOOMat(Mat mat)
44906977982Sstefanozampini {
45006977982Sstefanozampini   Mat_HYPRE           *hmat = (Mat_HYPRE *)mat->data;
45106977982Sstefanozampini   hypre_CSRMatrix     *diag, *offd;
45206977982Sstefanozampini   hypre_ParCSRMatrix  *parCSR;
45306977982Sstefanozampini   HYPRE_MemoryLocation hmem = HYPRE_MEMORY_HOST;
45406977982Sstefanozampini   PetscMemType         pmem;
45506977982Sstefanozampini   Mat                  A, B;
45606977982Sstefanozampini   PetscScalar         *a;
45706977982Sstefanozampini   PetscMPIInt          size;
45806977982Sstefanozampini   MPI_Comm             comm;
45906977982Sstefanozampini 
46006977982Sstefanozampini   PetscFunctionBegin;
46106977982Sstefanozampini   PetscCheck(hmat->cooMat, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet");
46206977982Sstefanozampini   if (hmat->cooMatAttached) PetscFunctionReturn(PETSC_SUCCESS);
46306977982Sstefanozampini   PetscCheck(hmat->cooMat->preallocated, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix is not preallocated");
46406977982Sstefanozampini   PetscCall(PetscObjectSetName((PetscObject)hmat->cooMat, "_internal_COO_mat_for_hypre"));
46506977982Sstefanozampini   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
46606977982Sstefanozampini   PetscCallMPI(MPI_Comm_size(comm, &size));
46706977982Sstefanozampini 
46806977982Sstefanozampini   /* Alias cooMat's data array to IJMatrix's */
46906977982Sstefanozampini   PetscCallExternal(HYPRE_IJMatrixGetObject, hmat->ij, (void **)&parCSR);
47006977982Sstefanozampini   diag = hypre_ParCSRMatrixDiag(parCSR);
47106977982Sstefanozampini   offd = hypre_ParCSRMatrixOffd(parCSR);
47206977982Sstefanozampini 
47306977982Sstefanozampini   A = (size == 1) ? hmat->cooMat : ((Mat_MPIAIJ *)hmat->cooMat->data)->A;
47406977982Sstefanozampini   B = (size == 1) ? NULL : ((Mat_MPIAIJ *)hmat->cooMat->data)->B;
47506977982Sstefanozampini 
47606977982Sstefanozampini   PetscCall(PetscObjectSetName((PetscObject)A, "_internal_COO_mat_for_hypre"));
47706977982Sstefanozampini   hmem = hypre_CSRMatrixMemoryLocation(diag);
47806977982Sstefanozampini   PetscCall(MatSeqAIJGetCSRAndMemType(A, NULL, NULL, &a, &pmem));
47906977982Sstefanozampini   PetscAssert((PetscMemTypeHost(pmem) && hmem == HYPRE_MEMORY_HOST) || (PetscMemTypeDevice(pmem) && hmem == HYPRE_MEMORY_DEVICE), comm, PETSC_ERR_PLIB, "PETSc and hypre's memory types mismatch");
48006977982Sstefanozampini   PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(diag), hmem));
48106977982Sstefanozampini   hypre_CSRMatrixData(diag)     = (HYPRE_Complex *)a;
48206977982Sstefanozampini   hypre_CSRMatrixOwnsData(diag) = 0; /* Take ownership of (j,a) away from hypre. As a result, we need to free them on our own */
48306977982Sstefanozampini 
48406977982Sstefanozampini   if (B) {
48506977982Sstefanozampini     hmem = hypre_CSRMatrixMemoryLocation(offd);
48606977982Sstefanozampini     PetscCall(MatSeqAIJGetCSRAndMemType(B, NULL, NULL, &a, &pmem));
48706977982Sstefanozampini     PetscAssert((PetscMemTypeHost(pmem) && hmem == HYPRE_MEMORY_HOST) || (PetscMemTypeDevice(pmem) && hmem == HYPRE_MEMORY_DEVICE), comm, PETSC_ERR_PLIB, "PETSc and hypre's memory types mismatch");
48806977982Sstefanozampini     PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(offd), hmem));
48906977982Sstefanozampini     hypre_CSRMatrixData(offd)     = (HYPRE_Complex *)a;
49006977982Sstefanozampini     hypre_CSRMatrixOwnsData(offd) = 0;
49106977982Sstefanozampini   }
49206977982Sstefanozampini   hmat->cooMatAttached = PETSC_TRUE;
49306977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
49406977982Sstefanozampini }
49506977982Sstefanozampini 
49606977982Sstefanozampini static PetscErrorCode CSRtoCOO_Private(PetscInt n, const PetscInt ii[], const PetscInt jj[], PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j)
49706977982Sstefanozampini {
49806977982Sstefanozampini   PetscInt *cooi, *cooj;
49906977982Sstefanozampini 
50006977982Sstefanozampini   PetscFunctionBegin;
50106977982Sstefanozampini   *ncoo = ii[n];
50206977982Sstefanozampini   PetscCall(PetscMalloc2(*ncoo, &cooi, *ncoo, &cooj));
50306977982Sstefanozampini   for (PetscInt i = 0; i < n; i++) {
50406977982Sstefanozampini     for (PetscInt j = ii[i]; j < ii[i + 1]; j++) cooi[j] = i;
50506977982Sstefanozampini   }
50606977982Sstefanozampini   PetscCall(PetscArraycpy(cooj, jj, *ncoo));
50706977982Sstefanozampini   *coo_i = cooi;
50806977982Sstefanozampini   *coo_j = cooj;
50906977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
51006977982Sstefanozampini }
51106977982Sstefanozampini 
51206977982Sstefanozampini static PetscErrorCode CSRtoCOO_HYPRE_Int_Private(PetscInt n, const HYPRE_Int ii[], const HYPRE_Int jj[], PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j)
51306977982Sstefanozampini {
51406977982Sstefanozampini   PetscInt *cooi, *cooj;
51506977982Sstefanozampini 
51606977982Sstefanozampini   PetscFunctionBegin;
51706977982Sstefanozampini   *ncoo = ii[n];
51806977982Sstefanozampini   PetscCall(PetscMalloc2(*ncoo, &cooi, *ncoo, &cooj));
51906977982Sstefanozampini   for (PetscInt i = 0; i < n; i++) {
52006977982Sstefanozampini     for (HYPRE_Int j = ii[i]; j < ii[i + 1]; j++) cooi[j] = i;
52106977982Sstefanozampini   }
52206977982Sstefanozampini   for (PetscCount i = 0; i < *ncoo; i++) cooj[i] = jj[i];
52306977982Sstefanozampini   *coo_i = cooi;
52406977982Sstefanozampini   *coo_j = cooj;
52506977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
52606977982Sstefanozampini }
52706977982Sstefanozampini 
52806977982Sstefanozampini static PetscErrorCode MatSeqAIJGetCOO_Private(Mat A, PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j)
52906977982Sstefanozampini {
53006977982Sstefanozampini   PetscInt        n;
53106977982Sstefanozampini   const PetscInt *ii, *jj;
53206977982Sstefanozampini   PetscBool       done;
53306977982Sstefanozampini 
53406977982Sstefanozampini   PetscFunctionBegin;
53506977982Sstefanozampini   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &done));
53606977982Sstefanozampini   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Failure for MatGetRowIJ");
53706977982Sstefanozampini   PetscCall(CSRtoCOO_Private(n, ii, jj, ncoo, coo_i, coo_j));
53806977982Sstefanozampini   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &done));
53906977982Sstefanozampini   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Failure for MatRestoreRowIJ");
54006977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
54106977982Sstefanozampini }
54206977982Sstefanozampini 
54306977982Sstefanozampini static PetscErrorCode hypreCSRMatrixGetCOO_Private(hypre_CSRMatrix *A, PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j)
54406977982Sstefanozampini {
54506977982Sstefanozampini   PetscInt             n = hypre_CSRMatrixNumRows(A);
54606977982Sstefanozampini   HYPRE_Int           *ii, *jj;
54706977982Sstefanozampini   HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST;
54806977982Sstefanozampini 
54906977982Sstefanozampini   PetscFunctionBegin;
55006977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
55106977982Sstefanozampini   mem = hypre_CSRMatrixMemoryLocation(A);
55206977982Sstefanozampini   if (mem != HYPRE_MEMORY_HOST) {
55306977982Sstefanozampini     PetscCount nnz = hypre_CSRMatrixNumNonzeros(A);
55406977982Sstefanozampini     PetscCall(PetscMalloc2(n + 1, &ii, nnz, &jj));
55506977982Sstefanozampini     hypre_TMemcpy(ii, hypre_CSRMatrixI(A), HYPRE_Int, n + 1, HYPRE_MEMORY_HOST, mem);
55606977982Sstefanozampini     hypre_TMemcpy(jj, hypre_CSRMatrixJ(A), HYPRE_Int, nnz, HYPRE_MEMORY_HOST, mem);
55706977982Sstefanozampini   } else {
55806977982Sstefanozampini #else
55906977982Sstefanozampini   {
56006977982Sstefanozampini #endif
56106977982Sstefanozampini     ii = hypre_CSRMatrixI(A);
56206977982Sstefanozampini     jj = hypre_CSRMatrixJ(A);
56306977982Sstefanozampini   }
56406977982Sstefanozampini   PetscCall(CSRtoCOO_HYPRE_Int_Private(n, ii, jj, ncoo, coo_i, coo_j));
56506977982Sstefanozampini   if (mem != HYPRE_MEMORY_HOST) PetscCall(PetscFree2(ii, jj));
56606977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
56706977982Sstefanozampini }
56806977982Sstefanozampini 
56906977982Sstefanozampini static PetscErrorCode MatSetValuesCOOFromCSRMatrix_Private(Mat A, hypre_CSRMatrix *H)
57006977982Sstefanozampini {
57106977982Sstefanozampini   PetscBool            iscpu = PETSC_TRUE;
57206977982Sstefanozampini   PetscScalar         *a;
57306977982Sstefanozampini   HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST;
57406977982Sstefanozampini 
57506977982Sstefanozampini   PetscFunctionBegin;
57606977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
57706977982Sstefanozampini   mem = hypre_CSRMatrixMemoryLocation(H);
57806977982Sstefanozampini   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATSEQAIJ, &iscpu));
57906977982Sstefanozampini #endif
58006977982Sstefanozampini   if (iscpu && mem != HYPRE_MEMORY_HOST) {
58106977982Sstefanozampini     PetscCount nnz = hypre_CSRMatrixNumNonzeros(H);
58206977982Sstefanozampini     PetscCall(PetscMalloc1(nnz, &a));
58306977982Sstefanozampini     hypre_TMemcpy(a, hypre_CSRMatrixData(H), PetscScalar, nnz, HYPRE_MEMORY_HOST, mem);
58406977982Sstefanozampini   } else {
58506977982Sstefanozampini     a = (PetscScalar *)hypre_CSRMatrixData(H);
58606977982Sstefanozampini   }
58706977982Sstefanozampini   PetscCall(MatSetValuesCOO(A, a, INSERT_VALUES));
58806977982Sstefanozampini   if (iscpu && mem != HYPRE_MEMORY_HOST) PetscCall(PetscFree(a));
589b73e3080SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
590b73e3080SStefano Zampini }
591b73e3080SStefano Zampini 
592b73e3080SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType type, MatReuse reuse, Mat *B)
593b73e3080SStefano Zampini {
594b73e3080SStefano Zampini   MPI_Comm   comm = PetscObjectComm((PetscObject)A);
59506977982Sstefanozampini   Mat        M = NULL, dH = NULL, oH = NULL, dA = NULL, oA = NULL;
596b73e3080SStefano Zampini   PetscBool  ismpiaij, issbaij, isbaij;
597b73e3080SStefano Zampini   Mat_HYPRE *hA;
598b73e3080SStefano Zampini 
599b73e3080SStefano Zampini   PetscFunctionBegin;
600b73e3080SStefano Zampini   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &issbaij, MATSEQSBAIJ, MATMPIBAIJ, ""));
601b73e3080SStefano Zampini   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &isbaij, MATSEQBAIJ, MATMPIBAIJ, ""));
602b73e3080SStefano Zampini   if (isbaij || issbaij) { /* handle BAIJ and SBAIJ */
603b73e3080SStefano Zampini     PetscBool ismpi;
604b73e3080SStefano Zampini     MatType   newtype;
605b73e3080SStefano Zampini 
606b73e3080SStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &ismpi, MATMPISBAIJ, MATMPIBAIJ, ""));
607b73e3080SStefano Zampini     newtype = ismpi ? MATMPIAIJ : MATSEQAIJ;
60863c07aadSStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
609b73e3080SStefano Zampini       PetscCall(MatConvert(*B, newtype, MAT_INPLACE_MATRIX, B));
610b73e3080SStefano Zampini       PetscCall(MatConvert(A, newtype, MAT_REUSE_MATRIX, B));
611b73e3080SStefano Zampini       PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B));
612b73e3080SStefano Zampini     } else if (reuse == MAT_INITIAL_MATRIX) {
613b73e3080SStefano Zampini       PetscCall(MatConvert(A, newtype, MAT_INITIAL_MATRIX, B));
614b73e3080SStefano Zampini       PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B));
61563c07aadSStefano Zampini     } else {
616b73e3080SStefano Zampini       PetscCall(MatConvert(A, newtype, MAT_INPLACE_MATRIX, &A));
617b73e3080SStefano Zampini       PetscCall(MatConvert(A, MATHYPRE, MAT_INPLACE_MATRIX, &A));
618b73e3080SStefano Zampini     }
619b73e3080SStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
620b73e3080SStefano Zampini   }
62106977982Sstefanozampini 
62206977982Sstefanozampini   dA = A;
623b73e3080SStefano Zampini   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
624b73e3080SStefano Zampini   if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(A, &dA, &oA, NULL));
62506977982Sstefanozampini 
626b73e3080SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
62706977982Sstefanozampini     PetscCount coo_n;
62806977982Sstefanozampini     PetscInt  *coo_i, *coo_j;
62906977982Sstefanozampini 
6309566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm, &M));
6319566063dSJacob Faibussowitsch     PetscCall(MatSetType(M, MATHYPRE));
6329566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(M, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
633b73e3080SStefano Zampini     PetscCall(MatSetOption(M, MAT_SORTED_FULL, PETSC_TRUE));
634b73e3080SStefano Zampini     PetscCall(MatSetOption(M, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE));
635b73e3080SStefano Zampini 
636b73e3080SStefano Zampini     hA = (Mat_HYPRE *)M->data;
63706977982Sstefanozampini     PetscCall(MatHYPRE_CreateFromMat(A, hA));
63806977982Sstefanozampini     PetscCall(MatHYPRE_IJMatrixCopyIJ(A, hA->ij));
63906977982Sstefanozampini 
64006977982Sstefanozampini     PetscCall(MatHYPRE_CreateCOOMat(M));
64106977982Sstefanozampini 
64206977982Sstefanozampini     dH = hA->cooMat;
64306977982Sstefanozampini     PetscCall(PetscObjectBaseTypeCompare((PetscObject)hA->cooMat, MATMPIAIJ, &ismpiaij));
64406977982Sstefanozampini     if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(hA->cooMat, &dH, &oH, NULL));
64506977982Sstefanozampini 
64606977982Sstefanozampini     PetscCall(PetscObjectSetName((PetscObject)dH, "_internal_COO_mat_for_hypre"));
64706977982Sstefanozampini     PetscCall(MatSeqAIJGetCOO_Private(dA, &coo_n, &coo_i, &coo_j));
64806977982Sstefanozampini     PetscCall(MatSetPreallocationCOO(dH, coo_n, coo_i, coo_j));
64906977982Sstefanozampini     PetscCall(PetscFree2(coo_i, coo_j));
65006977982Sstefanozampini     if (oH) {
65106977982Sstefanozampini       PetscCall(PetscLayoutDestroy(&oH->cmap));
65206977982Sstefanozampini       PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)oH), oA->cmap->n, oA->cmap->n, 1, &oH->cmap));
65306977982Sstefanozampini       PetscCall(MatSeqAIJGetCOO_Private(oA, &coo_n, &coo_i, &coo_j));
65406977982Sstefanozampini       PetscCall(MatSetPreallocationCOO(oH, coo_n, coo_i, coo_j));
65506977982Sstefanozampini       PetscCall(PetscFree2(coo_i, coo_j));
65606977982Sstefanozampini     }
65706977982Sstefanozampini     hA->cooMat->assembled = PETSC_TRUE;
65806977982Sstefanozampini 
659b73e3080SStefano Zampini     M->preallocated = PETSC_TRUE;
66006977982Sstefanozampini     PetscCall(MatAssemblyBegin(M, MAT_FINAL_ASSEMBLY));
66106977982Sstefanozampini     PetscCall(MatAssemblyEnd(M, MAT_FINAL_ASSEMBLY));
66206977982Sstefanozampini 
66306977982Sstefanozampini     PetscCall(MatHYPRE_AttachCOOMat(M));
66484d4e069SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) *B = M;
665b73e3080SStefano Zampini   } else M = *B;
666b73e3080SStefano Zampini 
667b73e3080SStefano Zampini   hA = (Mat_HYPRE *)M->data;
66806977982Sstefanozampini   PetscCheck(hA->cooMat, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet");
66906977982Sstefanozampini 
67006977982Sstefanozampini   dH = hA->cooMat;
67106977982Sstefanozampini   PetscCall(PetscObjectBaseTypeCompare((PetscObject)hA->cooMat, MATMPIAIJ, &ismpiaij));
67206977982Sstefanozampini   if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(hA->cooMat, &dH, &oH, NULL));
67306977982Sstefanozampini 
67406977982Sstefanozampini   PetscScalar *a;
67506977982Sstefanozampini   PetscCall(MatSeqAIJGetCSRAndMemType(dA, NULL, NULL, &a, NULL));
67606977982Sstefanozampini   PetscCall(MatSetValuesCOO(dH, a, INSERT_VALUES));
67706977982Sstefanozampini   if (oH) {
67806977982Sstefanozampini     PetscCall(MatSeqAIJGetCSRAndMemType(oA, NULL, NULL, &a, NULL));
67906977982Sstefanozampini     PetscCall(MatSetValuesCOO(oH, a, INSERT_VALUES));
68006977982Sstefanozampini   }
681b73e3080SStefano Zampini 
68248a46eb9SPierre Jolivet   if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &M));
6833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
68463c07aadSStefano Zampini }
68563c07aadSStefano Zampini 
686d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_HYPRE_AIJ(Mat A, MatType mtype, MatReuse reuse, Mat *B)
687d71ae5a4SJacob Faibussowitsch {
68806977982Sstefanozampini   Mat                 M, dA = NULL, oA = NULL;
68963c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
69006977982Sstefanozampini   hypre_CSRMatrix    *dH, *oH;
69163c07aadSStefano Zampini   MPI_Comm            comm;
69206977982Sstefanozampini   PetscBool           ismpiaij, isseqaij;
69363c07aadSStefano Zampini 
69463c07aadSStefano Zampini   PetscFunctionBegin;
69563c07aadSStefano Zampini   comm = PetscObjectComm((PetscObject)A);
69663c07aadSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
6979566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATMPIAIJ, &ismpiaij));
6989566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATSEQAIJ, &isseqaij));
69906977982Sstefanozampini     PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Only MATMPIAIJ or MATSEQAIJ base types are supported");
70063c07aadSStefano Zampini   }
70106977982Sstefanozampini   PetscCall(MatHYPREGetParCSR(A, &parcsr));
7026ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
70306977982Sstefanozampini   if (HYPRE_MEMORY_DEVICE == hypre_ParCSRMatrixMemoryLocation(parcsr)) {
70406977982Sstefanozampini     PetscBool isaij;
70506977982Sstefanozampini 
70606977982Sstefanozampini     PetscCall(PetscStrcmp(mtype, MATAIJ, &isaij));
70706977982Sstefanozampini     if (isaij) {
70806977982Sstefanozampini       PetscMPIInt size;
70906977982Sstefanozampini 
7109566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_size(comm, &size));
71106977982Sstefanozampini   #if defined(HYPRE_USING_HIP)
71206977982Sstefanozampini       mtype = size > 1 ? MATMPIAIJHIPSPARSE : MATSEQAIJHIPSPARSE;
71306977982Sstefanozampini   #elif defined(HYPRE_USING_CUDA)
71406977982Sstefanozampini       mtype = size > 1 ? MATMPIAIJCUSPARSE : MATSEQAIJCUSPARSE;
71506977982Sstefanozampini   #else
71606977982Sstefanozampini       mtype = size > 1 ? MATMPIAIJ : MATSEQAIJ;
71706977982Sstefanozampini   #endif
71863c07aadSStefano Zampini     }
71963c07aadSStefano Zampini   }
72006977982Sstefanozampini #endif
72106977982Sstefanozampini   dH = hypre_ParCSRMatrixDiag(parcsr);
72206977982Sstefanozampini   oH = hypre_ParCSRMatrixOffd(parcsr);
7239371c9d4SSatish Balay   if (reuse != MAT_REUSE_MATRIX) {
72406977982Sstefanozampini     PetscCount coo_n;
72506977982Sstefanozampini     PetscInt  *coo_i, *coo_j;
72663c07aadSStefano Zampini 
72706977982Sstefanozampini     PetscCall(MatCreate(comm, &M));
72806977982Sstefanozampini     PetscCall(MatSetType(M, mtype));
72906977982Sstefanozampini     PetscCall(MatSetSizes(M, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
73006977982Sstefanozampini     PetscCall(MatMPIAIJSetPreallocation(M, 0, NULL, 0, NULL));
73163c07aadSStefano Zampini 
73206977982Sstefanozampini     dA = M;
73306977982Sstefanozampini     PetscCall(PetscObjectBaseTypeCompare((PetscObject)M, MATMPIAIJ, &ismpiaij));
73406977982Sstefanozampini     if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(M, &dA, &oA, NULL));
735a16187a7SStefano Zampini 
73606977982Sstefanozampini     PetscCall(hypreCSRMatrixGetCOO_Private(dH, &coo_n, &coo_i, &coo_j));
73706977982Sstefanozampini     PetscCall(MatSetPreallocationCOO(dA, coo_n, coo_i, coo_j));
73806977982Sstefanozampini     PetscCall(PetscFree2(coo_i, coo_j));
73906977982Sstefanozampini     if (ismpiaij) {
74006977982Sstefanozampini       HYPRE_Int nc = hypre_CSRMatrixNumCols(oH);
741a16187a7SStefano Zampini 
74206977982Sstefanozampini       PetscCall(PetscLayoutDestroy(&oA->cmap));
74306977982Sstefanozampini       PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)oA), nc, nc, 1, &oA->cmap));
74406977982Sstefanozampini       PetscCall(hypreCSRMatrixGetCOO_Private(oH, &coo_n, &coo_i, &coo_j));
74506977982Sstefanozampini       PetscCall(MatSetPreallocationCOO(oA, coo_n, coo_i, coo_j));
74606977982Sstefanozampini       PetscCall(PetscFree2(coo_i, coo_j));
747a16187a7SStefano Zampini 
74806977982Sstefanozampini       /* garray */
749f4f49eeaSPierre Jolivet       Mat_MPIAIJ   *aij    = (Mat_MPIAIJ *)M->data;
75006977982Sstefanozampini       HYPRE_BigInt *harray = hypre_ParCSRMatrixColMapOffd(parcsr);
75106977982Sstefanozampini       PetscInt     *garray;
75206977982Sstefanozampini 
75306977982Sstefanozampini       PetscCall(PetscFree(aij->garray));
75406977982Sstefanozampini       PetscCall(PetscMalloc1(nc, &garray));
75506977982Sstefanozampini       for (HYPRE_Int i = 0; i < nc; i++) garray[i] = (PetscInt)harray[i];
75606977982Sstefanozampini       aij->garray = garray;
75706977982Sstefanozampini       PetscCall(MatSetUpMultiply_MPIAIJ(M));
758a16187a7SStefano Zampini     }
75906977982Sstefanozampini     if (reuse == MAT_INITIAL_MATRIX) *B = M;
76006977982Sstefanozampini   } else M = *B;
761225daaf8SStefano Zampini 
76206977982Sstefanozampini   dA = M;
76306977982Sstefanozampini   PetscCall(PetscObjectBaseTypeCompare((PetscObject)M, MATMPIAIJ, &ismpiaij));
76406977982Sstefanozampini   if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(M, &dA, &oA, NULL));
76506977982Sstefanozampini   PetscCall(MatSetValuesCOOFromCSRMatrix_Private(dA, dH));
76606977982Sstefanozampini   if (oA) PetscCall(MatSetValuesCOOFromCSRMatrix_Private(oA, oH));
76706977982Sstefanozampini   M->assembled = PETSC_TRUE;
76806977982Sstefanozampini   if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &M));
7693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
77063c07aadSStefano Zampini }
77163c07aadSStefano Zampini 
772d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJGetParCSR_Private(Mat A, hypre_ParCSRMatrix **hA)
773d71ae5a4SJacob Faibussowitsch {
774613e5ff0Sstefano_zampini   hypre_ParCSRMatrix *tA;
775c1a070e6SStefano Zampini   hypre_CSRMatrix    *hdiag, *hoffd;
776c1a070e6SStefano Zampini   Mat_SeqAIJ         *diag, *offd;
7772cf14000SStefano Zampini   PetscInt           *garray, i, noffd, dnnz, onnz, *row_starts, *col_starts;
778c1a070e6SStefano Zampini   MPI_Comm            comm = PetscObjectComm((PetscObject)A);
779613e5ff0Sstefano_zampini   PetscBool           ismpiaij, isseqaij;
7802cf14000SStefano Zampini   PetscBool           sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
7816ea7df73SStefano Zampini   HYPRE_Int          *hdi = NULL, *hdj = NULL, *hoi = NULL, *hoj = NULL;
7825c97c10fSStefano Zampini   PetscInt           *pdi = NULL, *pdj = NULL, *poi = NULL, *poj = NULL;
78306977982Sstefanozampini   PetscBool           iscuda, iship;
78406977982Sstefanozampini #if defined(PETSC_HAVE_DEVICE) && defined(PETSC_HAVE_HYPRE_DEVICE)
78506977982Sstefanozampini   PetscBool boundtocpu = A->boundtocpu;
78606977982Sstefanozampini #else
78706977982Sstefanozampini   PetscBool boundtocpu = PETSC_TRUE;
7886ea7df73SStefano Zampini #endif
789c1a070e6SStefano Zampini 
790c1a070e6SStefano Zampini   PetscFunctionBegin;
7919566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
7929566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isseqaij));
79308401ef6SPierre Jolivet   PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Unsupported type %s", ((PetscObject)A)->type_name);
79406977982Sstefanozampini   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iscuda, MATSEQAIJHIPSPARSE, MATMPIAIJCUSPARSE, ""));
79506977982Sstefanozampini   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iship, MATSEQAIJCUSPARSE, MATMPIAIJHIPSPARSE, ""));
796ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
797c1a070e6SStefano Zampini   if (ismpiaij) {
798f4f49eeaSPierre Jolivet     Mat_MPIAIJ *a = (Mat_MPIAIJ *)A->data;
799c1a070e6SStefano Zampini 
800c1a070e6SStefano Zampini     diag = (Mat_SeqAIJ *)a->A->data;
801c1a070e6SStefano Zampini     offd = (Mat_SeqAIJ *)a->B->data;
80206977982Sstefanozampini     if (!boundtocpu && (iscuda || iship)) {
80306977982Sstefanozampini #if defined(HYPRE_USING_CUDA) && defined(PETSC_HAVE_CUDA)
80406977982Sstefanozampini       if (iscuda) {
8056ea7df73SStefano Zampini         sameint = PETSC_TRUE;
8069566063dSJacob Faibussowitsch         PetscCall(MatSeqAIJCUSPARSEGetIJ(a->A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
8079566063dSJacob Faibussowitsch         PetscCall(MatSeqAIJCUSPARSEGetIJ(a->B, PETSC_FALSE, (const HYPRE_Int **)&hoi, (const HYPRE_Int **)&hoj));
80806977982Sstefanozampini       }
8096ea7df73SStefano Zampini #endif
81006977982Sstefanozampini #if defined(HYPRE_USING_HIP) && defined(PETSC_HAVE_HIP)
81106977982Sstefanozampini       if (iship) {
81206977982Sstefanozampini         sameint = PETSC_TRUE;
81306977982Sstefanozampini         PetscCall(MatSeqAIJHIPSPARSEGetIJ(a->A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
81406977982Sstefanozampini         PetscCall(MatSeqAIJHIPSPARSEGetIJ(a->B, PETSC_FALSE, (const HYPRE_Int **)&hoi, (const HYPRE_Int **)&hoj));
81506977982Sstefanozampini       }
81606977982Sstefanozampini #endif
81706977982Sstefanozampini     } else {
81806977982Sstefanozampini       boundtocpu = PETSC_TRUE;
8196ea7df73SStefano Zampini       pdi        = diag->i;
8206ea7df73SStefano Zampini       pdj        = diag->j;
8216ea7df73SStefano Zampini       poi        = offd->i;
8226ea7df73SStefano Zampini       poj        = offd->j;
8236ea7df73SStefano Zampini       if (sameint) {
8246ea7df73SStefano Zampini         hdi = (HYPRE_Int *)pdi;
8256ea7df73SStefano Zampini         hdj = (HYPRE_Int *)pdj;
8266ea7df73SStefano Zampini         hoi = (HYPRE_Int *)poi;
8276ea7df73SStefano Zampini         hoj = (HYPRE_Int *)poj;
8286ea7df73SStefano Zampini       }
8296ea7df73SStefano Zampini     }
830c1a070e6SStefano Zampini     garray = a->garray;
831c1a070e6SStefano Zampini     noffd  = a->B->cmap->N;
832c1a070e6SStefano Zampini     dnnz   = diag->nz;
833c1a070e6SStefano Zampini     onnz   = offd->nz;
834c1a070e6SStefano Zampini   } else {
835c1a070e6SStefano Zampini     diag = (Mat_SeqAIJ *)A->data;
836c1a070e6SStefano Zampini     offd = NULL;
83706977982Sstefanozampini     if (!boundtocpu && (iscuda || iship)) {
83806977982Sstefanozampini #if defined(HYPRE_USING_CUDA) && defined(PETSC_HAVE_CUDA)
83906977982Sstefanozampini       if (iscuda) {
8406ea7df73SStefano Zampini         sameint = PETSC_TRUE;
8419566063dSJacob Faibussowitsch         PetscCall(MatSeqAIJCUSPARSEGetIJ(A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
84206977982Sstefanozampini       }
8436ea7df73SStefano Zampini #endif
84406977982Sstefanozampini #if defined(HYPRE_USING_HIP) && defined(PETSC_HAVE_HIP)
84506977982Sstefanozampini       if (iship) {
84606977982Sstefanozampini         sameint = PETSC_TRUE;
84706977982Sstefanozampini         PetscCall(MatSeqAIJHIPSPARSEGetIJ(A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
84806977982Sstefanozampini       }
84906977982Sstefanozampini #endif
85006977982Sstefanozampini     } else {
85106977982Sstefanozampini       boundtocpu = PETSC_TRUE;
8526ea7df73SStefano Zampini       pdi        = diag->i;
8536ea7df73SStefano Zampini       pdj        = diag->j;
8546ea7df73SStefano Zampini       if (sameint) {
8556ea7df73SStefano Zampini         hdi = (HYPRE_Int *)pdi;
8566ea7df73SStefano Zampini         hdj = (HYPRE_Int *)pdj;
8576ea7df73SStefano Zampini       }
8586ea7df73SStefano Zampini     }
859c1a070e6SStefano Zampini     garray = NULL;
860c1a070e6SStefano Zampini     noffd  = 0;
861c1a070e6SStefano Zampini     dnnz   = diag->nz;
862c1a070e6SStefano Zampini     onnz   = 0;
863c1a070e6SStefano Zampini   }
864225daaf8SStefano Zampini 
865c1a070e6SStefano Zampini   /* create a temporary ParCSR */
866c1a070e6SStefano Zampini   if (HYPRE_AssumedPartitionCheck()) {
867c1a070e6SStefano Zampini     PetscMPIInt myid;
868c1a070e6SStefano Zampini 
8699566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &myid));
870c1a070e6SStefano Zampini     row_starts = A->rmap->range + myid;
871c1a070e6SStefano Zampini     col_starts = A->cmap->range + myid;
872c1a070e6SStefano Zampini   } else {
873c1a070e6SStefano Zampini     row_starts = A->rmap->range;
874c1a070e6SStefano Zampini     col_starts = A->cmap->range;
875c1a070e6SStefano Zampini   }
8762cf14000SStefano Zampini   tA = hypre_ParCSRMatrixCreate(comm, A->rmap->N, A->cmap->N, (HYPRE_BigInt *)row_starts, (HYPRE_BigInt *)col_starts, noffd, dnnz, onnz);
877a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
878c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetRowStartsOwner(tA, 0);
879c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetColStartsOwner(tA, 0);
880a1d2239cSSatish Balay #endif
881c1a070e6SStefano Zampini 
882225daaf8SStefano Zampini   /* set diagonal part */
883c1a070e6SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(tA);
8846ea7df73SStefano Zampini   if (!sameint) { /* malloc CSR pointers */
8859566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(A->rmap->n + 1, &hdi, dnnz, &hdj));
886f4f49eeaSPierre Jolivet     for (i = 0; i < A->rmap->n + 1; i++) hdi[i] = (HYPRE_Int)pdi[i];
887f4f49eeaSPierre Jolivet     for (i = 0; i < dnnz; i++) hdj[i] = (HYPRE_Int)pdj[i];
8882cf14000SStefano Zampini   }
8896ea7df73SStefano Zampini   hypre_CSRMatrixI(hdiag)           = hdi;
8906ea7df73SStefano Zampini   hypre_CSRMatrixJ(hdiag)           = hdj;
89139accc25SStefano Zampini   hypre_CSRMatrixData(hdiag)        = (HYPRE_Complex *)diag->a;
892c1a070e6SStefano Zampini   hypre_CSRMatrixNumNonzeros(hdiag) = diag->nz;
893c1a070e6SStefano Zampini   hypre_CSRMatrixSetRownnz(hdiag);
894c1a070e6SStefano Zampini   hypre_CSRMatrixSetDataOwner(hdiag, 0);
895c1a070e6SStefano Zampini 
8964cf0e950SBarry Smith   /* set off-diagonal part */
897c1a070e6SStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(tA);
898c1a070e6SStefano Zampini   if (offd) {
8996ea7df73SStefano Zampini     if (!sameint) { /* malloc CSR pointers */
9009566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(A->rmap->n + 1, &hoi, onnz, &hoj));
901f4f49eeaSPierre Jolivet       for (i = 0; i < A->rmap->n + 1; i++) hoi[i] = (HYPRE_Int)poi[i];
902f4f49eeaSPierre Jolivet       for (i = 0; i < onnz; i++) hoj[i] = (HYPRE_Int)poj[i];
9032cf14000SStefano Zampini     }
9046ea7df73SStefano Zampini     hypre_CSRMatrixI(hoffd)           = hoi;
9056ea7df73SStefano Zampini     hypre_CSRMatrixJ(hoffd)           = hoj;
90639accc25SStefano Zampini     hypre_CSRMatrixData(hoffd)        = (HYPRE_Complex *)offd->a;
907c1a070e6SStefano Zampini     hypre_CSRMatrixNumNonzeros(hoffd) = offd->nz;
908c1a070e6SStefano Zampini     hypre_CSRMatrixSetRownnz(hoffd);
909c1a070e6SStefano Zampini     hypre_CSRMatrixSetDataOwner(hoffd, 0);
9106ea7df73SStefano Zampini   }
9116ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
91206977982Sstefanozampini   PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, !boundtocpu ? HYPRE_MEMORY_DEVICE : HYPRE_MEMORY_HOST);
9136ea7df73SStefano Zampini #else
9146ea7df73SStefano Zampini   #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0)
915792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixInitialize, tA);
9166ea7df73SStefano Zampini   #else
917792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, HYPRE_MEMORY_HOST);
9186ea7df73SStefano Zampini   #endif
9196ea7df73SStefano Zampini #endif
9206ea7df73SStefano Zampini   hypre_TFree(hypre_ParCSRMatrixColMapOffd(tA), HYPRE_MEMORY_HOST);
921c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetNumNonzeros(tA);
9222cf14000SStefano Zampini   hypre_ParCSRMatrixColMapOffd(tA) = (HYPRE_BigInt *)garray;
923792fecdfSBarry Smith   if (!hypre_ParCSRMatrixCommPkg(tA)) PetscCallExternal(hypre_MatvecCommPkgCreate, tA);
924613e5ff0Sstefano_zampini   *hA = tA;
9253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
926613e5ff0Sstefano_zampini }
927c1a070e6SStefano Zampini 
928d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJRestoreParCSR_Private(Mat A, hypre_ParCSRMatrix **hA)
929d71ae5a4SJacob Faibussowitsch {
930613e5ff0Sstefano_zampini   hypre_CSRMatrix *hdiag, *hoffd;
9316ea7df73SStefano Zampini   PetscBool        ismpiaij, sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
9326ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
9336ea7df73SStefano Zampini   PetscBool iscuda = PETSC_FALSE;
9346ea7df73SStefano Zampini #endif
935c1a070e6SStefano Zampini 
936613e5ff0Sstefano_zampini   PetscFunctionBegin;
9379566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
9386ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
9399566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, ""));
9406ea7df73SStefano Zampini   if (iscuda) sameint = PETSC_TRUE;
9416ea7df73SStefano Zampini #endif
942613e5ff0Sstefano_zampini   hdiag = hypre_ParCSRMatrixDiag(*hA);
943613e5ff0Sstefano_zampini   hoffd = hypre_ParCSRMatrixOffd(*hA);
9446ea7df73SStefano Zampini   /* free temporary memory allocated by PETSc
9456ea7df73SStefano Zampini      set pointers to NULL before destroying tA */
9462cf14000SStefano Zampini   if (!sameint) {
9472cf14000SStefano Zampini     HYPRE_Int *hi, *hj;
9482cf14000SStefano Zampini 
9492cf14000SStefano Zampini     hi = hypre_CSRMatrixI(hdiag);
9502cf14000SStefano Zampini     hj = hypre_CSRMatrixJ(hdiag);
9519566063dSJacob Faibussowitsch     PetscCall(PetscFree2(hi, hj));
9526ea7df73SStefano Zampini     if (ismpiaij) {
9532cf14000SStefano Zampini       hi = hypre_CSRMatrixI(hoffd);
9542cf14000SStefano Zampini       hj = hypre_CSRMatrixJ(hoffd);
9559566063dSJacob Faibussowitsch       PetscCall(PetscFree2(hi, hj));
9562cf14000SStefano Zampini     }
9572cf14000SStefano Zampini   }
958c1a070e6SStefano Zampini   hypre_CSRMatrixI(hdiag)    = NULL;
959c1a070e6SStefano Zampini   hypre_CSRMatrixJ(hdiag)    = NULL;
960c1a070e6SStefano Zampini   hypre_CSRMatrixData(hdiag) = NULL;
9616ea7df73SStefano Zampini   if (ismpiaij) {
962c1a070e6SStefano Zampini     hypre_CSRMatrixI(hoffd)    = NULL;
963c1a070e6SStefano Zampini     hypre_CSRMatrixJ(hoffd)    = NULL;
964c1a070e6SStefano Zampini     hypre_CSRMatrixData(hoffd) = NULL;
9656ea7df73SStefano Zampini   }
966613e5ff0Sstefano_zampini   hypre_ParCSRMatrixColMapOffd(*hA) = NULL;
967613e5ff0Sstefano_zampini   hypre_ParCSRMatrixDestroy(*hA);
968613e5ff0Sstefano_zampini   *hA = NULL;
9693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
970613e5ff0Sstefano_zampini }
971613e5ff0Sstefano_zampini 
972613e5ff0Sstefano_zampini /* calls RAP from BoomerAMG:
9733dad0653Sstefano_zampini    the resulting ParCSR will not own the column and row starts
9746ea7df73SStefano Zampini    It looks like we don't need to have the diagonal entries ordered first */
975d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_RAP(hypre_ParCSRMatrix *hR, hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hP, hypre_ParCSRMatrix **hRAP)
976d71ae5a4SJacob Faibussowitsch {
977a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
978613e5ff0Sstefano_zampini   HYPRE_Int P_owns_col_starts, R_owns_row_starts;
979a1d2239cSSatish Balay #endif
980613e5ff0Sstefano_zampini 
981613e5ff0Sstefano_zampini   PetscFunctionBegin;
982a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
983613e5ff0Sstefano_zampini   P_owns_col_starts = hypre_ParCSRMatrixOwnsColStarts(hP);
984613e5ff0Sstefano_zampini   R_owns_row_starts = hypre_ParCSRMatrixOwnsRowStarts(hR);
985a1d2239cSSatish Balay #endif
9866ea7df73SStefano Zampini   /* can be replaced by version test later */
9876ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
988792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParCSRMatrixRAP");
9896ea7df73SStefano Zampini   *hRAP = hypre_ParCSRMatrixRAP(hR, hA, hP);
9906ea7df73SStefano Zampini   PetscStackPop;
9916ea7df73SStefano Zampini #else
992792fecdfSBarry Smith   PetscCallExternal(hypre_BoomerAMGBuildCoarseOperator, hR, hA, hP, hRAP);
993792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixSetNumNonzeros, *hRAP);
9946ea7df73SStefano Zampini #endif
995613e5ff0Sstefano_zampini   /* hypre_BoomerAMGBuildCoarseOperator steals the col_starts from P and the row_starts from R */
996a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
997613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetRowStartsOwner(*hRAP, 0);
998613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetColStartsOwner(*hRAP, 0);
999613e5ff0Sstefano_zampini   if (P_owns_col_starts) hypre_ParCSRMatrixSetColStartsOwner(hP, 1);
1000613e5ff0Sstefano_zampini   if (R_owns_row_starts) hypre_ParCSRMatrixSetRowStartsOwner(hR, 1);
1001a1d2239cSSatish Balay #endif
10023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1003613e5ff0Sstefano_zampini }
1004613e5ff0Sstefano_zampini 
1005d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat P, Mat C)
1006d71ae5a4SJacob Faibussowitsch {
10076f231fbdSstefano_zampini   Mat                 B;
10086abb4441SStefano Zampini   hypre_ParCSRMatrix *hA, *hP, *hPtAP = NULL;
10094222ddf1SHong Zhang   Mat_Product        *product = C->product;
1010613e5ff0Sstefano_zampini 
1011613e5ff0Sstefano_zampini   PetscFunctionBegin;
10129566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
10139566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(P, &hP));
10149566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(hP, hA, hP, &hPtAP));
10159566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hPtAP, MATAIJ, PETSC_OWN_POINTER, &B));
10164222ddf1SHong Zhang 
10179566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
10184222ddf1SHong Zhang   C->product = product;
10194222ddf1SHong Zhang 
10209566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
10219566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(P, &hP));
10223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10236f231fbdSstefano_zampini }
10246f231fbdSstefano_zampini 
1025d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatPtAPSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat P, PetscReal fill, Mat C)
1026d71ae5a4SJacob Faibussowitsch {
10276f231fbdSstefano_zampini   PetscFunctionBegin;
10289566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATAIJ));
10294222ddf1SHong Zhang   C->ops->ptapnumeric    = MatPtAPNumeric_AIJ_AIJ_wHYPRE;
10304222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
10313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1032613e5ff0Sstefano_zampini }
1033613e5ff0Sstefano_zampini 
1034d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_HYPRE(Mat A, Mat P, Mat C)
1035d71ae5a4SJacob Faibussowitsch {
10364cc28894Sstefano_zampini   Mat                 B;
10374cc28894Sstefano_zampini   Mat_HYPRE          *hP;
10386abb4441SStefano Zampini   hypre_ParCSRMatrix *hA = NULL, *Pparcsr, *ptapparcsr = NULL;
1039613e5ff0Sstefano_zampini   HYPRE_Int           type;
1040613e5ff0Sstefano_zampini   MPI_Comm            comm = PetscObjectComm((PetscObject)A);
10414cc28894Sstefano_zampini   PetscBool           ishypre;
1042613e5ff0Sstefano_zampini 
1043613e5ff0Sstefano_zampini   PetscFunctionBegin;
10449566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre));
104528b400f6SJacob Faibussowitsch   PetscCheck(ishypre, comm, PETSC_ERR_USER, "P should be of type %s", MATHYPRE);
10464cc28894Sstefano_zampini   hP = (Mat_HYPRE *)P->data;
1047792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type);
104808401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1049792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr);
1050613e5ff0Sstefano_zampini 
10519566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
10529566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, hA, Pparcsr, &ptapparcsr));
10539566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
1054225daaf8SStefano Zampini 
10554cc28894Sstefano_zampini   /* create temporary matrix and merge to C */
10569566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ptapparcsr, ((PetscObject)C)->type_name, PETSC_OWN_POINTER, &B));
10579566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
10583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10594cc28894Sstefano_zampini }
10604cc28894Sstefano_zampini 
1061d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_HYPRE_HYPRE(Mat A, Mat P, Mat C)
1062d71ae5a4SJacob Faibussowitsch {
10634cc28894Sstefano_zampini   Mat                 B;
10646abb4441SStefano Zampini   hypre_ParCSRMatrix *Aparcsr, *Pparcsr, *ptapparcsr = NULL;
10654cc28894Sstefano_zampini   Mat_HYPRE          *hA, *hP;
10664cc28894Sstefano_zampini   PetscBool           ishypre;
10674cc28894Sstefano_zampini   HYPRE_Int           type;
10684cc28894Sstefano_zampini 
10694cc28894Sstefano_zampini   PetscFunctionBegin;
10709566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre));
107128b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)P), PETSC_ERR_USER, "P should be of type %s", MATHYPRE);
10729566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
107328b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE);
10744cc28894Sstefano_zampini   hA = (Mat_HYPRE *)A->data;
10754cc28894Sstefano_zampini   hP = (Mat_HYPRE *)P->data;
1076792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
107708401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1078792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type);
107908401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)P), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1080792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr);
1081792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr);
10829566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, Aparcsr, Pparcsr, &ptapparcsr));
10839566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ptapparcsr, MATHYPRE, PETSC_OWN_POINTER, &B));
10849566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
10853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10864cc28894Sstefano_zampini }
10874cc28894Sstefano_zampini 
1088d501dc42Sstefano_zampini /* calls hypre_ParMatmul
1089d501dc42Sstefano_zampini    hypre_ParMatMul uses hypre_ParMatrixCreate with the communicator of hA
10903dad0653Sstefano_zampini    hypre_ParMatrixCreate does not duplicate the communicator
10916ea7df73SStefano Zampini    It looks like we don't need to have the diagonal entries ordered first */
1092d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_MatMatMult(hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hB, hypre_ParCSRMatrix **hAB)
1093d71ae5a4SJacob Faibussowitsch {
1094d501dc42Sstefano_zampini   PetscFunctionBegin;
10956ea7df73SStefano Zampini   /* can be replaced by version test later */
10966ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
1097792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParCSRMatMat");
10986ea7df73SStefano Zampini   *hAB = hypre_ParCSRMatMat(hA, hB);
10996ea7df73SStefano Zampini #else
1100792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParMatmul");
1101d501dc42Sstefano_zampini   *hAB = hypre_ParMatmul(hA, hB);
11026ea7df73SStefano Zampini #endif
1103d501dc42Sstefano_zampini   PetscStackPop;
11043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1105d501dc42Sstefano_zampini }
1106d501dc42Sstefano_zampini 
1107d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C)
1108d71ae5a4SJacob Faibussowitsch {
11095e5acdf2Sstefano_zampini   Mat                 D;
1110d501dc42Sstefano_zampini   hypre_ParCSRMatrix *hA, *hB, *hAB = NULL;
11114222ddf1SHong Zhang   Mat_Product        *product = C->product;
11125e5acdf2Sstefano_zampini 
11135e5acdf2Sstefano_zampini   PetscFunctionBegin;
11149566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
11159566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(B, &hB));
11169566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_MatMatMult(hA, hB, &hAB));
11179566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hAB, MATAIJ, PETSC_OWN_POINTER, &D));
11184222ddf1SHong Zhang 
11199566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &D));
11204222ddf1SHong Zhang   C->product = product;
11214222ddf1SHong Zhang 
11229566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
11239566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(B, &hB));
11243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11255e5acdf2Sstefano_zampini }
11265e5acdf2Sstefano_zampini 
1127d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatMatMultSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat B, PetscReal fill, Mat C)
1128d71ae5a4SJacob Faibussowitsch {
11295e5acdf2Sstefano_zampini   PetscFunctionBegin;
11309566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATAIJ));
11314222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_AIJ_AIJ_wHYPRE;
11324222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
11333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11345e5acdf2Sstefano_zampini }
11355e5acdf2Sstefano_zampini 
1136d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_HYPRE_HYPRE(Mat A, Mat B, Mat C)
1137d71ae5a4SJacob Faibussowitsch {
1138d501dc42Sstefano_zampini   Mat                 D;
1139d501dc42Sstefano_zampini   hypre_ParCSRMatrix *Aparcsr, *Bparcsr, *ABparcsr = NULL;
1140d501dc42Sstefano_zampini   Mat_HYPRE          *hA, *hB;
1141d501dc42Sstefano_zampini   PetscBool           ishypre;
1142d501dc42Sstefano_zampini   HYPRE_Int           type;
11434222ddf1SHong Zhang   Mat_Product        *product;
1144d501dc42Sstefano_zampini 
1145d501dc42Sstefano_zampini   PetscFunctionBegin;
11469566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)B, MATHYPRE, &ishypre));
114728b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)B), PETSC_ERR_USER, "B should be of type %s", MATHYPRE);
11489566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
114928b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE);
1150d501dc42Sstefano_zampini   hA = (Mat_HYPRE *)A->data;
1151d501dc42Sstefano_zampini   hB = (Mat_HYPRE *)B->data;
1152792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
115308401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1154792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hB->ij, &type);
115508401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1156792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr);
1157792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hB->ij, (void **)&Bparcsr);
11589566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_MatMatMult(Aparcsr, Bparcsr, &ABparcsr));
11599566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ABparcsr, MATHYPRE, PETSC_OWN_POINTER, &D));
11604222ddf1SHong Zhang 
1161d501dc42Sstefano_zampini   /* need to use HeaderReplace because HeaderMerge messes up with the communicator */
11624222ddf1SHong Zhang   product    = C->product; /* save it from MatHeaderReplace() */
11634222ddf1SHong Zhang   C->product = NULL;
11649566063dSJacob Faibussowitsch   PetscCall(MatHeaderReplace(C, &D));
11654222ddf1SHong Zhang   C->product             = product;
1166d501dc42Sstefano_zampini   C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE;
11674222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
11683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1169d501dc42Sstefano_zampini }
1170d501dc42Sstefano_zampini 
1171d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultNumeric_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, Mat D)
1172d71ae5a4SJacob Faibussowitsch {
117320e1dc0dSstefano_zampini   Mat                 E;
11746abb4441SStefano Zampini   hypre_ParCSRMatrix *hA, *hB, *hC, *hABC = NULL;
117520e1dc0dSstefano_zampini 
117620e1dc0dSstefano_zampini   PetscFunctionBegin;
11779566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
11789566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(B, &hB));
11799566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(C, &hC));
11809566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(hA, hB, hC, &hABC));
11819566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hABC, MATAIJ, PETSC_OWN_POINTER, &E));
11829566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(D, &E));
11839566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
11849566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(B, &hB));
11859566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(C, &hC));
11863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
118720e1dc0dSstefano_zampini }
118820e1dc0dSstefano_zampini 
1189d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultSymbolic_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, PetscReal fill, Mat D)
1190d71ae5a4SJacob Faibussowitsch {
119120e1dc0dSstefano_zampini   PetscFunctionBegin;
11929566063dSJacob Faibussowitsch   PetscCall(MatSetType(D, MATAIJ));
11933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
119420e1dc0dSstefano_zampini }
119520e1dc0dSstefano_zampini 
1196d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_AB_HYPRE(Mat C)
1197d71ae5a4SJacob Faibussowitsch {
11984222ddf1SHong Zhang   PetscFunctionBegin;
11994222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
12003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12014222ddf1SHong Zhang }
12024222ddf1SHong Zhang 
1203d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_AB(Mat C)
1204d71ae5a4SJacob Faibussowitsch {
12054222ddf1SHong Zhang   Mat_Product *product = C->product;
12064222ddf1SHong Zhang   PetscBool    Ahypre;
12074222ddf1SHong Zhang 
12084222ddf1SHong Zhang   PetscFunctionBegin;
12099566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)product->A, MATHYPRE, &Ahypre));
12104222ddf1SHong Zhang   if (Ahypre) { /* A is a Hypre matrix */
12119566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
12124222ddf1SHong Zhang     C->ops->productsymbolic = MatProductSymbolic_AB_HYPRE;
12134222ddf1SHong Zhang     C->ops->matmultnumeric  = MatMatMultNumeric_HYPRE_HYPRE;
12143ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
12156718818eSStefano Zampini   }
12163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12174222ddf1SHong Zhang }
12184222ddf1SHong Zhang 
1219d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_PtAP_HYPRE(Mat C)
1220d71ae5a4SJacob Faibussowitsch {
12214222ddf1SHong Zhang   PetscFunctionBegin;
12224222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
12233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12244222ddf1SHong Zhang }
12254222ddf1SHong Zhang 
1226d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_PtAP(Mat C)
1227d71ae5a4SJacob Faibussowitsch {
12284222ddf1SHong Zhang   Mat_Product *product = C->product;
12294222ddf1SHong Zhang   PetscBool    flg;
12304222ddf1SHong Zhang   PetscInt     type        = 0;
12314222ddf1SHong Zhang   const char  *outTypes[4] = {"aij", "seqaij", "mpiaij", "hypre"};
12324222ddf1SHong Zhang   PetscInt     ntype       = 4;
12334222ddf1SHong Zhang   Mat          A           = product->A;
12344222ddf1SHong Zhang   PetscBool    Ahypre;
12354222ddf1SHong Zhang 
12364222ddf1SHong Zhang   PetscFunctionBegin;
12379566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &Ahypre));
12384222ddf1SHong Zhang   if (Ahypre) { /* A is a Hypre matrix */
12399566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
12404222ddf1SHong Zhang     C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE;
12414222ddf1SHong Zhang     C->ops->ptapnumeric     = MatPtAPNumeric_HYPRE_HYPRE;
12423ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
12434222ddf1SHong Zhang   }
12444222ddf1SHong Zhang 
12454222ddf1SHong Zhang   /* A is AIJ, P is Hypre, C = PtAP can be either AIJ or Hypre format */
12464222ddf1SHong Zhang   /* Get runtime option */
12474222ddf1SHong Zhang   if (product->api_user) {
1248d0609cedSBarry Smith     PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatPtAP_HYPRE", "Mat");
12499566063dSJacob Faibussowitsch     PetscCall(PetscOptionsEList("-matptap_hypre_outtype", "MatPtAP outtype", "MatPtAP outtype", outTypes, ntype, outTypes[type], &type, &flg));
1250d0609cedSBarry Smith     PetscOptionsEnd();
12514222ddf1SHong Zhang   } else {
1252d0609cedSBarry Smith     PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatProduct_PtAP_HYPRE", "Mat");
12539566063dSJacob Faibussowitsch     PetscCall(PetscOptionsEList("-mat_product_algorithm_hypre_outtype", "MatProduct_PtAP outtype", "MatProduct_PtAP", outTypes, ntype, outTypes[type], &type, &flg));
1254d0609cedSBarry Smith     PetscOptionsEnd();
12554222ddf1SHong Zhang   }
12564222ddf1SHong Zhang 
12574222ddf1SHong Zhang   if (type == 0 || type == 1 || type == 2) {
12589566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATAIJ));
12594222ddf1SHong Zhang   } else if (type == 3) {
12609566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
12614222ddf1SHong Zhang   } else SETERRQ(PetscObjectComm((PetscObject)C), PETSC_ERR_SUP, "MatPtAP outtype is not supported");
12624222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE;
12634222ddf1SHong Zhang   C->ops->ptapnumeric     = MatPtAPNumeric_AIJ_HYPRE;
12643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12654222ddf1SHong Zhang }
12664222ddf1SHong Zhang 
1267d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE(Mat C)
1268d71ae5a4SJacob Faibussowitsch {
12694222ddf1SHong Zhang   Mat_Product *product = C->product;
12704222ddf1SHong Zhang 
12714222ddf1SHong Zhang   PetscFunctionBegin;
12724222ddf1SHong Zhang   switch (product->type) {
1273d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AB:
1274d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_HYPRE_AB(C));
1275d71ae5a4SJacob Faibussowitsch     break;
1276d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_PtAP:
1277d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_HYPRE_PtAP(C));
1278d71ae5a4SJacob Faibussowitsch     break;
1279d71ae5a4SJacob Faibussowitsch   default:
1280d71ae5a4SJacob Faibussowitsch     break;
12814222ddf1SHong Zhang   }
12823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12834222ddf1SHong Zhang }
12844222ddf1SHong Zhang 
1285d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTranspose_HYPRE(Mat A, Vec x, Vec y)
1286d71ae5a4SJacob Faibussowitsch {
128763c07aadSStefano Zampini   PetscFunctionBegin;
12889566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_TRUE));
12893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
129063c07aadSStefano Zampini }
129163c07aadSStefano Zampini 
1292d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_HYPRE(Mat A, Vec x, Vec y)
1293d71ae5a4SJacob Faibussowitsch {
129463c07aadSStefano Zampini   PetscFunctionBegin;
12959566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_FALSE));
12963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
129763c07aadSStefano Zampini }
129863c07aadSStefano Zampini 
1299d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultAdd_HYPRE(Mat A, Vec x, Vec y, Vec z)
1300d71ae5a4SJacob Faibussowitsch {
1301414bd5c3SStefano Zampini   PetscFunctionBegin;
130248a46eb9SPierre Jolivet   if (y != z) PetscCall(VecCopy(y, z));
13039566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_FALSE));
13043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1305414bd5c3SStefano Zampini }
1306414bd5c3SStefano Zampini 
1307d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTransposeAdd_HYPRE(Mat A, Vec x, Vec y, Vec z)
1308d71ae5a4SJacob Faibussowitsch {
1309414bd5c3SStefano Zampini   PetscFunctionBegin;
131048a46eb9SPierre Jolivet   if (y != z) PetscCall(VecCopy(y, z));
13119566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_TRUE));
13123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1313414bd5c3SStefano Zampini }
1314414bd5c3SStefano Zampini 
1315414bd5c3SStefano Zampini /* y = a * A * x + b * y or y = a * A^t * x + b * y depending on trans */
1316d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_MultKernel_Private(Mat A, HYPRE_Complex a, Vec x, HYPRE_Complex b, Vec y, PetscBool trans)
1317d71ae5a4SJacob Faibussowitsch {
131863c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE *)A->data;
131963c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
132063c07aadSStefano Zampini   hypre_ParVector    *hx, *hy;
132163c07aadSStefano Zampini 
132263c07aadSStefano Zampini   PetscFunctionBegin;
132363c07aadSStefano Zampini   if (trans) {
13249566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorPushVecRead(hA->b, x));
13259566063dSJacob Faibussowitsch     if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->x, y));
13269566063dSJacob Faibussowitsch     else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->x, y));
1327792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hx);
1328792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hy);
132963c07aadSStefano Zampini   } else {
13309566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorPushVecRead(hA->x, x));
13319566063dSJacob Faibussowitsch     if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->b, y));
13329566063dSJacob Faibussowitsch     else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->b, y));
1333792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hx);
1334792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hy);
133563c07aadSStefano Zampini   }
1336792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
13376ea7df73SStefano Zampini   if (trans) {
1338792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMatvecT, a, parcsr, hx, b, hy);
13396ea7df73SStefano Zampini   } else {
1340792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMatvec, a, parcsr, hx, b, hy);
13416ea7df73SStefano Zampini   }
13429566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hA->x));
13439566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hA->b));
13443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
134563c07aadSStefano Zampini }
134663c07aadSStefano Zampini 
1347d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_HYPRE(Mat A)
1348d71ae5a4SJacob Faibussowitsch {
134963c07aadSStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
135063c07aadSStefano Zampini 
135163c07aadSStefano Zampini   PetscFunctionBegin;
13529566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&hA->x));
13539566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&hA->b));
135406977982Sstefanozampini   PetscCall(MatHYPRE_DestroyCOOMat(A)); /* must be called before destroying the individual CSR */
1355978814f1SStefano Zampini   if (hA->ij) {
1356978814f1SStefano Zampini     if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL;
1357792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixDestroy, hA->ij);
1358978814f1SStefano Zampini   }
13599566063dSJacob Faibussowitsch   if (hA->comm) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)A), &hA->comm));
1360c69f721fSFande Kong 
13619566063dSJacob Faibussowitsch   PetscCall(MatStashDestroy_Private(&A->stash));
13629566063dSJacob Faibussowitsch   PetscCall(PetscFree(hA->array));
1363a32e9c99SJunchao Zhang   if (hA->rows_d) PetscStackCallExternalVoid("hypre_Free", hypre_Free(hA->rows_d, HYPRE_MEMORY_DEVICE));
1364c69f721fSFande Kong 
13659566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_aij_C", NULL));
13669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_is_C", NULL));
13679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_hypre_C", NULL));
13689566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaij_hypre_C", NULL));
136906977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijhipsparse_hypre_C", NULL));
137006977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaijhipsparse_hypre_C", NULL));
137106977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijcusparse_hypre_C", NULL));
137206977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaijcusparse_hypre_C", NULL));
13739566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPRESetPreallocation_C", NULL));
13749566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPREGetParCSR_C", NULL));
13755fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL));
13765fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL));
13779566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->data));
13783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
137963c07aadSStefano Zampini }
138063c07aadSStefano Zampini 
1381d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetUp_HYPRE(Mat A)
1382d71ae5a4SJacob Faibussowitsch {
13834ec6421dSstefano_zampini   PetscFunctionBegin;
138406977982Sstefanozampini   if (!A->preallocated) PetscCall(MatHYPRESetPreallocation(A, PETSC_DEFAULT, NULL, PETSC_DEFAULT, NULL));
13853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13864ec6421dSstefano_zampini }
13874ec6421dSstefano_zampini 
13886ea7df73SStefano Zampini //TODO FIX hypre_CSRMatrixMatvecOutOfPlace
13896ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
1390d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatBindToCPU_HYPRE(Mat A, PetscBool bind)
1391d71ae5a4SJacob Faibussowitsch {
13926ea7df73SStefano Zampini   Mat_HYPRE           *hA   = (Mat_HYPRE *)A->data;
13936ea7df73SStefano Zampini   HYPRE_MemoryLocation hmem = bind ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE;
13946ea7df73SStefano Zampini 
13956ea7df73SStefano Zampini   PetscFunctionBegin;
13966ea7df73SStefano Zampini   A->boundtocpu = bind;
13975fbaff96SJunchao Zhang   if (hA->ij && hypre_IJMatrixAssembleFlag(hA->ij) && hmem != hypre_IJMatrixMemoryLocation(hA->ij)) {
13986ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
1399792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
1400792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMigrate, parcsr, hmem);
14016ea7df73SStefano Zampini   }
14029566063dSJacob Faibussowitsch   if (hA->x) PetscCall(VecHYPRE_IJBindToCPU(hA->x, bind));
14039566063dSJacob Faibussowitsch   if (hA->b) PetscCall(VecHYPRE_IJBindToCPU(hA->b, bind));
14043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14056ea7df73SStefano Zampini }
14066ea7df73SStefano Zampini #endif
14076ea7df73SStefano Zampini 
1408d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_HYPRE(Mat A, MatAssemblyType mode)
1409d71ae5a4SJacob Faibussowitsch {
141063c07aadSStefano Zampini   Mat_HYPRE   *hA = (Mat_HYPRE *)A->data;
1411c69f721fSFande Kong   PetscMPIInt  n;
1412c69f721fSFande Kong   PetscInt     i, j, rstart, ncols, flg;
1413c69f721fSFande Kong   PetscInt    *row, *col;
1414c69f721fSFande Kong   PetscScalar *val;
141563c07aadSStefano Zampini 
141663c07aadSStefano Zampini   PetscFunctionBegin;
141708401ef6SPierre Jolivet   PetscCheck(mode != MAT_FLUSH_ASSEMBLY, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_FLUSH_ASSEMBLY currently not supported with MATHYPRE");
1418c69f721fSFande Kong 
1419c69f721fSFande Kong   if (!A->nooffprocentries) {
1420c69f721fSFande Kong     while (1) {
14219566063dSJacob Faibussowitsch       PetscCall(MatStashScatterGetMesg_Private(&A->stash, &n, &row, &col, &val, &flg));
1422c69f721fSFande Kong       if (!flg) break;
1423c69f721fSFande Kong 
1424c69f721fSFande Kong       for (i = 0; i < n;) {
1425c69f721fSFande Kong         /* Now identify the consecutive vals belonging to the same row */
1426c69f721fSFande Kong         for (j = i, rstart = row[j]; j < n; j++) {
1427c69f721fSFande Kong           if (row[j] != rstart) break;
1428c69f721fSFande Kong         }
1429c69f721fSFande Kong         if (j < n) ncols = j - i;
1430c69f721fSFande Kong         else ncols = n - i;
1431c69f721fSFande Kong         /* Now assemble all these values with a single function call */
14329566063dSJacob Faibussowitsch         PetscCall(MatSetValues_HYPRE(A, 1, row + i, ncols, col + i, val + i, A->insertmode));
1433c69f721fSFande Kong 
1434c69f721fSFande Kong         i = j;
1435c69f721fSFande Kong       }
1436c69f721fSFande Kong     }
14379566063dSJacob Faibussowitsch     PetscCall(MatStashScatterEnd_Private(&A->stash));
1438c69f721fSFande Kong   }
1439c69f721fSFande Kong 
1440792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixAssemble, hA->ij);
1441336664bdSPierre Jolivet   /* The assembly routine destroys the aux_matrix, we recreate it here by calling HYPRE_IJMatrixInitialize */
1442336664bdSPierre 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 */
1443651b1cf9SStefano Zampini   if (!A->sortedfull) {
1444af1cf968SStefano Zampini     hypre_AuxParCSRMatrix *aux_matrix;
1445af1cf968SStefano Zampini 
1446af1cf968SStefano Zampini     /* call destroy just to make sure we do not leak anything */
1447af1cf968SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
1448792fecdfSBarry Smith     PetscCallExternal(hypre_AuxParCSRMatrixDestroy, aux_matrix);
1449af1cf968SStefano Zampini     hypre_IJMatrixTranslator(hA->ij) = NULL;
1450af1cf968SStefano Zampini 
1451af1cf968SStefano Zampini     /* Initialize with assembled flag -> it only recreates the aux_par_matrix */
1452792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij);
1453af1cf968SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
14546ea7df73SStefano Zampini     if (aux_matrix) {
1455af1cf968SStefano Zampini       hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1; /* see comment in MatHYPRESetPreallocation_HYPRE */
145622235d61SPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
1457792fecdfSBarry Smith       PetscCallExternal(hypre_AuxParCSRMatrixInitialize, aux_matrix);
145822235d61SPierre Jolivet #else
1459792fecdfSBarry Smith       PetscCallExternal(hypre_AuxParCSRMatrixInitialize_v2, aux_matrix, HYPRE_MEMORY_HOST);
146022235d61SPierre Jolivet #endif
1461af1cf968SStefano Zampini     }
14626ea7df73SStefano Zampini   }
14636ea7df73SStefano Zampini   {
14646ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
14656ea7df73SStefano Zampini 
1466792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
1467792fecdfSBarry Smith     if (!hypre_ParCSRMatrixCommPkg(parcsr)) PetscCallExternal(hypre_MatvecCommPkgCreate, parcsr);
14686ea7df73SStefano Zampini   }
14699566063dSJacob Faibussowitsch   if (!hA->x) PetscCall(VecHYPRE_IJVectorCreate(A->cmap, &hA->x));
14709566063dSJacob Faibussowitsch   if (!hA->b) PetscCall(VecHYPRE_IJVectorCreate(A->rmap, &hA->b));
14716ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
14729566063dSJacob Faibussowitsch   PetscCall(MatBindToCPU_HYPRE(A, A->boundtocpu));
14736ea7df73SStefano Zampini #endif
14743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
147563c07aadSStefano Zampini }
147663c07aadSStefano Zampini 
1477d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetArray_HYPRE(Mat A, PetscInt size, void **array)
1478d71ae5a4SJacob Faibussowitsch {
1479c69f721fSFande Kong   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1480c69f721fSFande Kong 
1481c69f721fSFande Kong   PetscFunctionBegin;
1482651b1cf9SStefano Zampini   PetscCheck(hA->array_available, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Temporary space is in use");
1483c69f721fSFande Kong 
1484651b1cf9SStefano Zampini   if (hA->array_size >= size) {
148539accc25SStefano Zampini     *array = hA->array;
148639accc25SStefano Zampini   } else {
14879566063dSJacob Faibussowitsch     PetscCall(PetscFree(hA->array));
1488651b1cf9SStefano Zampini     hA->array_size = size;
1489651b1cf9SStefano Zampini     PetscCall(PetscMalloc(hA->array_size, &hA->array));
1490c69f721fSFande Kong     *array = hA->array;
1491c69f721fSFande Kong   }
1492c69f721fSFande Kong 
1493651b1cf9SStefano Zampini   hA->array_available = PETSC_FALSE;
14943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1495c69f721fSFande Kong }
1496c69f721fSFande Kong 
1497d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreArray_HYPRE(Mat A, void **array)
1498d71ae5a4SJacob Faibussowitsch {
1499c69f721fSFande Kong   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1500c69f721fSFande Kong 
1501c69f721fSFande Kong   PetscFunctionBegin;
1502c69f721fSFande Kong   *array              = NULL;
1503651b1cf9SStefano Zampini   hA->array_available = PETSC_TRUE;
15043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1505c69f721fSFande Kong }
1506c69f721fSFande Kong 
1507d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_HYPRE(Mat A, PetscInt nr, const PetscInt rows[], PetscInt nc, const PetscInt cols[], const PetscScalar v[], InsertMode ins)
1508d71ae5a4SJacob Faibussowitsch {
1509d975228cSstefano_zampini   Mat_HYPRE     *hA   = (Mat_HYPRE *)A->data;
1510d975228cSstefano_zampini   PetscScalar   *vals = (PetscScalar *)v;
151139accc25SStefano Zampini   HYPRE_Complex *sscr;
1512c69f721fSFande Kong   PetscInt      *cscr[2];
1513c69f721fSFande Kong   PetscInt       i, nzc;
1514651b1cf9SStefano Zampini   PetscInt       rst = A->rmap->rstart, ren = A->rmap->rend;
151508defe43SFande Kong   void          *array = NULL;
1516d975228cSstefano_zampini 
1517d975228cSstefano_zampini   PetscFunctionBegin;
15189566063dSJacob Faibussowitsch   PetscCall(MatGetArray_HYPRE(A, sizeof(PetscInt) * (2 * nc) + sizeof(HYPRE_Complex) * nc * nr, &array));
1519c69f721fSFande Kong   cscr[0] = (PetscInt *)array;
1520c69f721fSFande Kong   cscr[1] = ((PetscInt *)array) + nc;
152139accc25SStefano Zampini   sscr    = (HYPRE_Complex *)(((PetscInt *)array) + nc * 2);
1522d975228cSstefano_zampini   for (i = 0, nzc = 0; i < nc; i++) {
1523d975228cSstefano_zampini     if (cols[i] >= 0) {
1524d975228cSstefano_zampini       cscr[0][nzc]   = cols[i];
1525d975228cSstefano_zampini       cscr[1][nzc++] = i;
1526d975228cSstefano_zampini     }
1527d975228cSstefano_zampini   }
1528c69f721fSFande Kong   if (!nzc) {
15299566063dSJacob Faibussowitsch     PetscCall(MatRestoreArray_HYPRE(A, &array));
15303ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1531c69f721fSFande Kong   }
1532d975228cSstefano_zampini 
15336ea7df73SStefano Zampini #if 0 //defined(PETSC_HAVE_HYPRE_DEVICE)
15346ea7df73SStefano Zampini   if (HYPRE_MEMORY_HOST != hypre_IJMatrixMemoryLocation(hA->ij)) {
15356ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
15366ea7df73SStefano Zampini 
1537792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject,hA->ij,(void**)&parcsr);
1538792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMigrate,parcsr, HYPRE_MEMORY_HOST);
15396ea7df73SStefano Zampini   }
15406ea7df73SStefano Zampini #endif
15416ea7df73SStefano Zampini 
1542d975228cSstefano_zampini   if (ins == ADD_VALUES) {
1543d975228cSstefano_zampini     for (i = 0; i < nr; i++) {
15446ea7df73SStefano Zampini       if (rows[i] >= 0) {
1545d975228cSstefano_zampini         PetscInt  j;
15462cf14000SStefano Zampini         HYPRE_Int hnc = (HYPRE_Int)nzc;
15472cf14000SStefano Zampini 
1548651b1cf9SStefano Zampini         if (!nzc) continue;
1549651b1cf9SStefano Zampini         /* nonlocal values */
1550651b1cf9SStefano Zampini         if (rows[i] < rst || rows[i] >= ren) {
1551651b1cf9SStefano 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]);
1552651b1cf9SStefano Zampini           if (hA->donotstash) continue;
1553651b1cf9SStefano Zampini         }
1554aed4548fSBarry 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]);
15559566063dSJacob Faibussowitsch         for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j]));
1556792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixAddToValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr);
1557d975228cSstefano_zampini       }
1558d975228cSstefano_zampini       vals += nc;
1559d975228cSstefano_zampini     }
1560d975228cSstefano_zampini   } else { /* INSERT_VALUES */
1561d975228cSstefano_zampini     for (i = 0; i < nr; i++) {
15626ea7df73SStefano Zampini       if (rows[i] >= 0) {
1563d975228cSstefano_zampini         PetscInt  j;
15642cf14000SStefano Zampini         HYPRE_Int hnc = (HYPRE_Int)nzc;
15652cf14000SStefano Zampini 
1566651b1cf9SStefano Zampini         if (!nzc) continue;
1567aed4548fSBarry 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]);
15689566063dSJacob Faibussowitsch         for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j]));
1569c69f721fSFande Kong         /* nonlocal values */
1570651b1cf9SStefano Zampini         if (rows[i] < rst || rows[i] >= ren) {
1571651b1cf9SStefano 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]);
1572651b1cf9SStefano Zampini           if (!hA->donotstash) PetscCall(MatStashValuesRow_Private(&A->stash, rows[i], nzc, cscr[0], (PetscScalar *)sscr, PETSC_FALSE));
1573651b1cf9SStefano Zampini         }
1574c69f721fSFande Kong         /* local values */
1575651b1cf9SStefano Zampini         else
1576651b1cf9SStefano Zampini           PetscCallExternal(HYPRE_IJMatrixSetValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr);
1577d975228cSstefano_zampini       }
1578d975228cSstefano_zampini       vals += nc;
1579d975228cSstefano_zampini     }
1580d975228cSstefano_zampini   }
1581c69f721fSFande Kong 
15829566063dSJacob Faibussowitsch   PetscCall(MatRestoreArray_HYPRE(A, &array));
15833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1584d975228cSstefano_zampini }
1585d975228cSstefano_zampini 
1586d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRESetPreallocation_HYPRE(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[])
1587d71ae5a4SJacob Faibussowitsch {
1588d975228cSstefano_zampini   Mat_HYPRE  *hA = (Mat_HYPRE *)A->data;
15897d968826Sstefano_zampini   HYPRE_Int  *hdnnz, *honnz;
159006a29025Sstefano_zampini   PetscInt    i, rs, re, cs, ce, bs;
1591d975228cSstefano_zampini   PetscMPIInt size;
1592d975228cSstefano_zampini 
1593d975228cSstefano_zampini   PetscFunctionBegin;
15949566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
15959566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
1596d975228cSstefano_zampini   rs = A->rmap->rstart;
1597d975228cSstefano_zampini   re = A->rmap->rend;
1598d975228cSstefano_zampini   cs = A->cmap->rstart;
1599d975228cSstefano_zampini   ce = A->cmap->rend;
1600d975228cSstefano_zampini   if (!hA->ij) {
1601792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rs, re - 1, cs, ce - 1, &hA->ij);
1602792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR);
1603d975228cSstefano_zampini   } else {
16042cf14000SStefano Zampini     HYPRE_BigInt hrs, hre, hcs, hce;
1605792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetLocalRange, hA->ij, &hrs, &hre, &hcs, &hce);
1606aed4548fSBarry 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);
1607aed4548fSBarry 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);
1608d975228cSstefano_zampini   }
160906977982Sstefanozampini   PetscCall(MatHYPRE_DestroyCOOMat(A));
16109566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(A, &bs));
161106a29025Sstefano_zampini   if (dnz == PETSC_DEFAULT || dnz == PETSC_DECIDE) dnz = 10 * bs;
161206a29025Sstefano_zampini   if (onz == PETSC_DEFAULT || onz == PETSC_DECIDE) onz = 10 * bs;
161306a29025Sstefano_zampini 
1614d975228cSstefano_zampini   if (!dnnz) {
16159566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->rmap->n, &hdnnz));
1616d975228cSstefano_zampini     for (i = 0; i < A->rmap->n; i++) hdnnz[i] = dnz;
1617d975228cSstefano_zampini   } else {
16187d968826Sstefano_zampini     hdnnz = (HYPRE_Int *)dnnz;
1619d975228cSstefano_zampini   }
16209566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
1621d975228cSstefano_zampini   if (size > 1) {
1622ddbeb582SStefano Zampini     hypre_AuxParCSRMatrix *aux_matrix;
1623d975228cSstefano_zampini     if (!onnz) {
16249566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(A->rmap->n, &honnz));
1625d975228cSstefano_zampini       for (i = 0; i < A->rmap->n; i++) honnz[i] = onz;
162622235d61SPierre Jolivet     } else honnz = (HYPRE_Int *)onnz;
1627ddbeb582SStefano Zampini     /* SetDiagOffdSizes sets hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0, since it seems
1628ddbeb582SStefano Zampini        they assume the user will input the entire row values, properly sorted
1629336664bdSPierre Jolivet        In PETSc, we don't make such an assumption and set this flag to 1,
1630336664bdSPierre Jolivet        unless the option MAT_SORTED_FULL is set to true.
1631ddbeb582SStefano Zampini        Also, to avoid possible memory leaks, we destroy and recreate the translator
1632ddbeb582SStefano Zampini        This has to be done here, as HYPRE_IJMatrixInitialize will properly initialize
1633ddbeb582SStefano Zampini        the IJ matrix for us */
1634ddbeb582SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
1635ddbeb582SStefano Zampini     hypre_AuxParCSRMatrixDestroy(aux_matrix);
1636ddbeb582SStefano Zampini     hypre_IJMatrixTranslator(hA->ij) = NULL;
1637792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, hA->ij, hdnnz, honnz);
1638ddbeb582SStefano Zampini     aux_matrix                               = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
1639651b1cf9SStefano Zampini     hypre_AuxParCSRMatrixNeedAux(aux_matrix) = !A->sortedfull;
1640d975228cSstefano_zampini   } else {
1641d975228cSstefano_zampini     honnz = NULL;
1642792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetRowSizes, hA->ij, hdnnz);
1643d975228cSstefano_zampini   }
1644ddbeb582SStefano Zampini 
1645af1cf968SStefano Zampini   /* reset assembled flag and call the initialize method */
1646af1cf968SStefano Zampini   hypre_IJMatrixAssembleFlag(hA->ij) = 0;
16476ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
1648792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij);
16496ea7df73SStefano Zampini #else
1650792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize_v2, hA->ij, HYPRE_MEMORY_HOST);
16516ea7df73SStefano Zampini #endif
165248a46eb9SPierre Jolivet   if (!dnnz) PetscCall(PetscFree(hdnnz));
165348a46eb9SPierre Jolivet   if (!onnz && honnz) PetscCall(PetscFree(honnz));
1654af1cf968SStefano Zampini   /* Match AIJ logic */
165506a29025Sstefano_zampini   A->preallocated = PETSC_TRUE;
1656af1cf968SStefano Zampini   A->assembled    = PETSC_FALSE;
16573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1658d975228cSstefano_zampini }
1659d975228cSstefano_zampini 
1660d975228cSstefano_zampini /*@C
1661d975228cSstefano_zampini   MatHYPRESetPreallocation - Preallocates memory for a sparse parallel matrix in HYPRE IJ format
1662d975228cSstefano_zampini 
1663c3339decSBarry Smith   Collective
1664d975228cSstefano_zampini 
1665d975228cSstefano_zampini   Input Parameters:
1666d975228cSstefano_zampini + A    - the matrix
1667d975228cSstefano_zampini . dnz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1668d975228cSstefano_zampini           (same value is used for all local rows)
1669d975228cSstefano_zampini . dnnz - array containing the number of nonzeros in the various rows of the
1670d975228cSstefano_zampini           DIAGONAL portion of the local submatrix (possibly different for each row)
16712ef1f0ffSBarry Smith           or `NULL` (`PETSC_NULL_INTEGER` in Fortran), if `d_nz` is used to specify the nonzero structure.
16722ef1f0ffSBarry Smith           The size of this array is equal to the number of local rows, i.e `m`.
1673d975228cSstefano_zampini           For matrices that will be factored, you must leave room for (and set)
1674d975228cSstefano_zampini           the diagonal entry even if it is zero.
1675d975228cSstefano_zampini . onz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1676d975228cSstefano_zampini           submatrix (same value is used for all local rows).
1677d975228cSstefano_zampini - onnz - array containing the number of nonzeros in the various rows of the
1678d975228cSstefano_zampini           OFF-DIAGONAL portion of the local submatrix (possibly different for
16792ef1f0ffSBarry Smith           each row) or `NULL` (`PETSC_NULL_INTEGER` in Fortran), if `o_nz` is used to specify the nonzero
1680d975228cSstefano_zampini           structure. The size of this array is equal to the number
16812ef1f0ffSBarry Smith           of local rows, i.e `m`.
1682d975228cSstefano_zampini 
16832fe279fdSBarry Smith   Level: intermediate
16842fe279fdSBarry Smith 
168511a5261eSBarry Smith   Note:
16862ef1f0ffSBarry Smith   If the *nnz parameter is given then the *nz parameter is ignored; for sequential matrices, `onz` and `onnz` are ignored.
1687d975228cSstefano_zampini 
16881cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatMPIAIJSetPreallocation()`, `MATHYPRE`, `MATAIJ`
1689d975228cSstefano_zampini @*/
1690d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHYPRESetPreallocation(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[])
1691d71ae5a4SJacob Faibussowitsch {
1692d975228cSstefano_zampini   PetscFunctionBegin;
1693d975228cSstefano_zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1694d975228cSstefano_zampini   PetscValidType(A, 1);
1695cac4c232SBarry Smith   PetscTryMethod(A, "MatHYPRESetPreallocation_C", (Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]), (A, dnz, dnnz, onz, onnz));
16963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1697d975228cSstefano_zampini }
1698d975228cSstefano_zampini 
169920f4b53cSBarry Smith /*@C
17002ef1f0ffSBarry Smith   MatCreateFromParCSR - Creates a `Mat` from a `hypre_ParCSRMatrix`
1701225daaf8SStefano Zampini 
1702225daaf8SStefano Zampini   Collective
1703225daaf8SStefano Zampini 
1704225daaf8SStefano Zampini   Input Parameters:
17052ef1f0ffSBarry Smith + parcsr   - the pointer to the `hypre_ParCSRMatrix`
17062ef1f0ffSBarry Smith . mtype    - matrix type to be created. Currently `MATAIJ`, `MATIS` and `MATHYPRE` are supported.
170720f4b53cSBarry Smith - copymode - PETSc copying options, see  `PetscCopyMode`
1708225daaf8SStefano Zampini 
1709225daaf8SStefano Zampini   Output Parameter:
1710225daaf8SStefano Zampini . A - the matrix
1711225daaf8SStefano Zampini 
1712225daaf8SStefano Zampini   Level: intermediate
1713225daaf8SStefano Zampini 
17141cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatHYPRE`, `PetscCopyMode`
171520f4b53cSBarry Smith @*/
1716d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreateFromParCSR(hypre_ParCSRMatrix *parcsr, MatType mtype, PetscCopyMode copymode, Mat *A)
1717d71ae5a4SJacob Faibussowitsch {
1718225daaf8SStefano Zampini   Mat        T;
1719978814f1SStefano Zampini   Mat_HYPRE *hA;
1720978814f1SStefano Zampini   MPI_Comm   comm;
1721978814f1SStefano Zampini   PetscInt   rstart, rend, cstart, cend, M, N;
1722d248a85cSRichard Tran Mills   PetscBool  isseqaij, isseqaijmkl, ismpiaij, isaij, ishyp, isis;
1723978814f1SStefano Zampini 
1724978814f1SStefano Zampini   PetscFunctionBegin;
1725978814f1SStefano Zampini   comm = hypre_ParCSRMatrixComm(parcsr);
17269566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQAIJ, &isseqaij));
17279566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQAIJMKL, &isseqaijmkl));
17289566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPIAIJ, &ismpiaij));
17299566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATAIJ, &isaij));
17309566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATHYPRE, &ishyp));
17319566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATIS, &isis));
1732d248a85cSRichard Tran Mills   isaij = (PetscBool)(isseqaij || isseqaijmkl || ismpiaij || isaij);
17336ea7df73SStefano Zampini   /* TODO */
1734aed4548fSBarry 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);
1735978814f1SStefano Zampini   /* access ParCSRMatrix */
1736978814f1SStefano Zampini   rstart = hypre_ParCSRMatrixFirstRowIndex(parcsr);
1737978814f1SStefano Zampini   rend   = hypre_ParCSRMatrixLastRowIndex(parcsr);
1738978814f1SStefano Zampini   cstart = hypre_ParCSRMatrixFirstColDiag(parcsr);
1739978814f1SStefano Zampini   cend   = hypre_ParCSRMatrixLastColDiag(parcsr);
1740978814f1SStefano Zampini   M      = hypre_ParCSRMatrixGlobalNumRows(parcsr);
1741978814f1SStefano Zampini   N      = hypre_ParCSRMatrixGlobalNumCols(parcsr);
1742978814f1SStefano Zampini 
1743fa92c42cSstefano_zampini   /* fix for empty local rows/columns */
1744fa92c42cSstefano_zampini   if (rend < rstart) rend = rstart;
1745fa92c42cSstefano_zampini   if (cend < cstart) cend = cstart;
1746fa92c42cSstefano_zampini 
1747e6471dc9SStefano Zampini   /* PETSc convention */
1748e6471dc9SStefano Zampini   rend++;
1749e6471dc9SStefano Zampini   cend++;
1750e6471dc9SStefano Zampini   rend = PetscMin(rend, M);
1751e6471dc9SStefano Zampini   cend = PetscMin(cend, N);
1752e6471dc9SStefano Zampini 
1753978814f1SStefano Zampini   /* create PETSc matrix with MatHYPRE */
17549566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, &T));
17559566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(T, rend - rstart, cend - cstart, M, N));
17569566063dSJacob Faibussowitsch   PetscCall(MatSetType(T, MATHYPRE));
1757f4f49eeaSPierre Jolivet   hA = (Mat_HYPRE *)T->data;
1758978814f1SStefano Zampini 
1759978814f1SStefano Zampini   /* create HYPRE_IJMatrix */
1760792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rstart, rend - 1, cstart, cend - 1, &hA->ij);
1761792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR);
176245b8d346SStefano Zampini 
176345b8d346SStefano Zampini   /* create new ParCSR object if needed */
176445b8d346SStefano Zampini   if (ishyp && copymode == PETSC_COPY_VALUES) {
176545b8d346SStefano Zampini     hypre_ParCSRMatrix *new_parcsr;
17666ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0)
176745b8d346SStefano Zampini     hypre_CSRMatrix *hdiag, *hoffd, *ndiag, *noffd;
176845b8d346SStefano Zampini 
17690e6427aaSSatish Balay     new_parcsr = hypre_ParCSRMatrixClone(parcsr, 0);
177045b8d346SStefano Zampini     hdiag      = hypre_ParCSRMatrixDiag(parcsr);
177145b8d346SStefano Zampini     hoffd      = hypre_ParCSRMatrixOffd(parcsr);
177245b8d346SStefano Zampini     ndiag      = hypre_ParCSRMatrixDiag(new_parcsr);
177345b8d346SStefano Zampini     noffd      = hypre_ParCSRMatrixOffd(new_parcsr);
17749566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hypre_CSRMatrixData(ndiag), hypre_CSRMatrixData(hdiag), hypre_CSRMatrixNumNonzeros(hdiag)));
17759566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hypre_CSRMatrixData(noffd), hypre_CSRMatrixData(hoffd), hypre_CSRMatrixNumNonzeros(hoffd)));
17766ea7df73SStefano Zampini #else
17776ea7df73SStefano Zampini     new_parcsr = hypre_ParCSRMatrixClone(parcsr, 1);
17786ea7df73SStefano Zampini #endif
177945b8d346SStefano Zampini     parcsr   = new_parcsr;
178045b8d346SStefano Zampini     copymode = PETSC_OWN_POINTER;
178145b8d346SStefano Zampini   }
1782978814f1SStefano Zampini 
1783978814f1SStefano Zampini   /* set ParCSR object */
1784978814f1SStefano Zampini   hypre_IJMatrixObject(hA->ij) = parcsr;
17854ec6421dSstefano_zampini   T->preallocated              = PETSC_TRUE;
1786978814f1SStefano Zampini 
1787978814f1SStefano Zampini   /* set assembled flag */
1788978814f1SStefano Zampini   hypre_IJMatrixAssembleFlag(hA->ij) = 1;
17896ea7df73SStefano Zampini #if 0
1790792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize,hA->ij);
17916ea7df73SStefano Zampini #endif
1792225daaf8SStefano Zampini   if (ishyp) {
17936d2a658fSstefano_zampini     PetscMPIInt myid = 0;
17946d2a658fSstefano_zampini 
17956d2a658fSstefano_zampini     /* make sure we always have row_starts and col_starts available */
179648a46eb9SPierre Jolivet     if (HYPRE_AssumedPartitionCheck()) PetscCallMPI(MPI_Comm_rank(comm, &myid));
1797a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
17986d2a658fSstefano_zampini     if (!hypre_ParCSRMatrixOwnsColStarts(parcsr)) {
17996d2a658fSstefano_zampini       PetscLayout map;
18006d2a658fSstefano_zampini 
18019566063dSJacob Faibussowitsch       PetscCall(MatGetLayouts(T, NULL, &map));
18029566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetUp(map));
18032cf14000SStefano Zampini       hypre_ParCSRMatrixColStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid);
18046d2a658fSstefano_zampini     }
18056d2a658fSstefano_zampini     if (!hypre_ParCSRMatrixOwnsRowStarts(parcsr)) {
18066d2a658fSstefano_zampini       PetscLayout map;
18076d2a658fSstefano_zampini 
18089566063dSJacob Faibussowitsch       PetscCall(MatGetLayouts(T, &map, NULL));
18099566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetUp(map));
18102cf14000SStefano Zampini       hypre_ParCSRMatrixRowStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid);
18116d2a658fSstefano_zampini     }
1812a1d2239cSSatish Balay #endif
1813978814f1SStefano Zampini     /* prevent from freeing the pointer */
1814978814f1SStefano Zampini     if (copymode == PETSC_USE_POINTER) hA->inner_free = PETSC_FALSE;
1815225daaf8SStefano Zampini     *A = T;
18169566063dSJacob Faibussowitsch     PetscCall(MatSetOption(*A, MAT_SORTED_FULL, PETSC_TRUE));
18179566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(*A, MAT_FINAL_ASSEMBLY));
18189566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(*A, MAT_FINAL_ASSEMBLY));
1819bb4689ddSStefano Zampini   } else if (isaij) {
1820bb4689ddSStefano Zampini     if (copymode != PETSC_OWN_POINTER) {
1821225daaf8SStefano Zampini       /* prevent from freeing the pointer */
1822225daaf8SStefano Zampini       hA->inner_free = PETSC_FALSE;
18239566063dSJacob Faibussowitsch       PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INITIAL_MATRIX, A));
18249566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&T));
1825225daaf8SStefano Zampini     } else { /* AIJ return type with PETSC_OWN_POINTER */
18269566063dSJacob Faibussowitsch       PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INPLACE_MATRIX, &T));
1827225daaf8SStefano Zampini       *A = T;
1828225daaf8SStefano Zampini     }
1829bb4689ddSStefano Zampini   } else if (isis) {
18309566063dSJacob Faibussowitsch     PetscCall(MatConvert_HYPRE_IS(T, MATIS, MAT_INITIAL_MATRIX, A));
18318cfe8d00SStefano Zampini     if (copymode != PETSC_OWN_POINTER) hA->inner_free = PETSC_FALSE;
18329566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&T));
1833bb4689ddSStefano Zampini   }
18343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1835978814f1SStefano Zampini }
1836978814f1SStefano Zampini 
1837d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPREGetParCSR_HYPRE(Mat A, hypre_ParCSRMatrix **parcsr)
1838d71ae5a4SJacob Faibussowitsch {
1839dd9c0a25Sstefano_zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1840dd9c0a25Sstefano_zampini   HYPRE_Int  type;
1841dd9c0a25Sstefano_zampini 
1842dd9c0a25Sstefano_zampini   PetscFunctionBegin;
184328b400f6SJacob Faibussowitsch   PetscCheck(hA->ij, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "HYPRE_IJMatrix not present");
1844792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
184508401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "HYPRE_IJMatrix is not of type HYPRE_PARCSR");
1846792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)parcsr);
18473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1848dd9c0a25Sstefano_zampini }
1849dd9c0a25Sstefano_zampini 
185020f4b53cSBarry Smith /*@C
1851dd9c0a25Sstefano_zampini   MatHYPREGetParCSR - Gets the pointer to the ParCSR matrix
1852dd9c0a25Sstefano_zampini 
18532ef1f0ffSBarry Smith   Not Collective
1854dd9c0a25Sstefano_zampini 
185520f4b53cSBarry Smith   Input Parameter:
185620f4b53cSBarry Smith . A - the `MATHYPRE` object
1857dd9c0a25Sstefano_zampini 
1858dd9c0a25Sstefano_zampini   Output Parameter:
18592ef1f0ffSBarry Smith . parcsr - the pointer to the `hypre_ParCSRMatrix`
1860dd9c0a25Sstefano_zampini 
1861dd9c0a25Sstefano_zampini   Level: intermediate
1862dd9c0a25Sstefano_zampini 
18631cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatHYPRE`, `PetscCopyMode`
186420f4b53cSBarry Smith @*/
1865d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHYPREGetParCSR(Mat A, hypre_ParCSRMatrix **parcsr)
1866d71ae5a4SJacob Faibussowitsch {
1867dd9c0a25Sstefano_zampini   PetscFunctionBegin;
1868dd9c0a25Sstefano_zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1869dd9c0a25Sstefano_zampini   PetscValidType(A, 1);
1870cac4c232SBarry Smith   PetscUseMethod(A, "MatHYPREGetParCSR_C", (Mat, hypre_ParCSRMatrix **), (A, parcsr));
18713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1872dd9c0a25Sstefano_zampini }
1873dd9c0a25Sstefano_zampini 
1874d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_HYPRE(Mat A, PetscBool *missing, PetscInt *dd)
1875d71ae5a4SJacob Faibussowitsch {
187668ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
187768ec7858SStefano Zampini   hypre_CSRMatrix    *ha;
187868ec7858SStefano Zampini   PetscInt            rst;
187968ec7858SStefano Zampini 
188068ec7858SStefano Zampini   PetscFunctionBegin;
188108401ef6SPierre Jolivet   PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented with non-square diagonal blocks");
18829566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &rst, NULL));
18839566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
188468ec7858SStefano Zampini   if (missing) *missing = PETSC_FALSE;
188568ec7858SStefano Zampini   if (dd) *dd = -1;
188668ec7858SStefano Zampini   ha = hypre_ParCSRMatrixDiag(parcsr);
188768ec7858SStefano Zampini   if (ha) {
188868299464SStefano Zampini     PetscInt   size, i;
188968299464SStefano Zampini     HYPRE_Int *ii, *jj;
189068ec7858SStefano Zampini 
189168ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
189268ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
189368ec7858SStefano Zampini     jj   = hypre_CSRMatrixJ(ha);
189468ec7858SStefano Zampini     for (i = 0; i < size; i++) {
189568ec7858SStefano Zampini       PetscInt  j;
189668ec7858SStefano Zampini       PetscBool found = PETSC_FALSE;
189768ec7858SStefano Zampini 
18989371c9d4SSatish Balay       for (j = ii[i]; j < ii[i + 1] && !found; j++) found = (jj[j] == i) ? PETSC_TRUE : PETSC_FALSE;
189968ec7858SStefano Zampini 
190068ec7858SStefano Zampini       if (!found) {
19013ba16761SJacob Faibussowitsch         PetscCall(PetscInfo(A, "Matrix is missing local diagonal entry %" PetscInt_FMT "\n", i));
190268ec7858SStefano Zampini         if (missing) *missing = PETSC_TRUE;
190368ec7858SStefano Zampini         if (dd) *dd = i + rst;
19043ba16761SJacob Faibussowitsch         PetscFunctionReturn(PETSC_SUCCESS);
190568ec7858SStefano Zampini       }
190668ec7858SStefano Zampini     }
190768ec7858SStefano Zampini     if (!size) {
19083ba16761SJacob Faibussowitsch       PetscCall(PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n"));
190968ec7858SStefano Zampini       if (missing) *missing = PETSC_TRUE;
191068ec7858SStefano Zampini       if (dd) *dd = rst;
191168ec7858SStefano Zampini     }
191268ec7858SStefano Zampini   } else {
19133ba16761SJacob Faibussowitsch     PetscCall(PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n"));
191468ec7858SStefano Zampini     if (missing) *missing = PETSC_TRUE;
191568ec7858SStefano Zampini     if (dd) *dd = rst;
191668ec7858SStefano Zampini   }
19173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
191868ec7858SStefano Zampini }
191968ec7858SStefano Zampini 
1920d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatScale_HYPRE(Mat A, PetscScalar s)
1921d71ae5a4SJacob Faibussowitsch {
192268ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
19236ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
192468ec7858SStefano Zampini   hypre_CSRMatrix *ha;
19256ea7df73SStefano Zampini #endif
192639accc25SStefano Zampini   HYPRE_Complex hs;
192768ec7858SStefano Zampini 
192868ec7858SStefano Zampini   PetscFunctionBegin;
19299566063dSJacob Faibussowitsch   PetscCall(PetscHYPREScalarCast(s, &hs));
19309566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
19316ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 19, 0)
1932792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixScale, parcsr, hs);
19336ea7df73SStefano Zampini #else /* diagonal part */
193468ec7858SStefano Zampini   ha = hypre_ParCSRMatrixDiag(parcsr);
193568ec7858SStefano Zampini   if (ha) {
193668299464SStefano Zampini     PetscInt       size, i;
193768299464SStefano Zampini     HYPRE_Int     *ii;
193839accc25SStefano Zampini     HYPRE_Complex *a;
193968ec7858SStefano Zampini 
194068ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
194168ec7858SStefano Zampini     a    = hypre_CSRMatrixData(ha);
194268ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
194339accc25SStefano Zampini     for (i = 0; i < ii[size]; i++) a[i] *= hs;
194468ec7858SStefano Zampini   }
19454cf0e950SBarry Smith   /* off-diagonal part */
194668ec7858SStefano Zampini   ha = hypre_ParCSRMatrixOffd(parcsr);
194768ec7858SStefano Zampini   if (ha) {
194868299464SStefano Zampini     PetscInt       size, i;
194968299464SStefano Zampini     HYPRE_Int     *ii;
195039accc25SStefano Zampini     HYPRE_Complex *a;
195168ec7858SStefano Zampini 
195268ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
195368ec7858SStefano Zampini     a    = hypre_CSRMatrixData(ha);
195468ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
195539accc25SStefano Zampini     for (i = 0; i < ii[size]; i++) a[i] *= hs;
195668ec7858SStefano Zampini   }
19576ea7df73SStefano Zampini #endif
19583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
195968ec7858SStefano Zampini }
196068ec7858SStefano Zampini 
1961d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_HYPRE(Mat A, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
1962d71ae5a4SJacob Faibussowitsch {
196368ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
196468299464SStefano Zampini   HYPRE_Int          *lrows;
196568299464SStefano Zampini   PetscInt            rst, ren, i;
196668ec7858SStefano Zampini 
196768ec7858SStefano Zampini   PetscFunctionBegin;
196808401ef6SPierre Jolivet   PetscCheck(!x && !b, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "To be implemented");
19699566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
19709566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numRows, &lrows));
19719566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &rst, &ren));
197268ec7858SStefano Zampini   for (i = 0; i < numRows; i++) {
19737a46b595SBarry Smith     PetscCheck(rows[i] >= rst && rows[i] < ren, PETSC_COMM_SELF, PETSC_ERR_SUP, "Non-local rows not yet supported");
197468ec7858SStefano Zampini     lrows[i] = rows[i] - rst;
197568ec7858SStefano Zampini   }
1976792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixEliminateRowsCols, parcsr, numRows, lrows);
19779566063dSJacob Faibussowitsch   PetscCall(PetscFree(lrows));
19783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
197968ec7858SStefano Zampini }
198068ec7858SStefano Zampini 
1981d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPRE_CSRMatrix(hypre_CSRMatrix *ha)
1982d71ae5a4SJacob Faibussowitsch {
1983c69f721fSFande Kong   PetscFunctionBegin;
1984c69f721fSFande Kong   if (ha) {
1985c69f721fSFande Kong     HYPRE_Int     *ii, size;
1986c69f721fSFande Kong     HYPRE_Complex *a;
1987c69f721fSFande Kong 
1988c69f721fSFande Kong     size = hypre_CSRMatrixNumRows(ha);
1989c69f721fSFande Kong     a    = hypre_CSRMatrixData(ha);
1990c69f721fSFande Kong     ii   = hypre_CSRMatrixI(ha);
1991c69f721fSFande Kong 
19929566063dSJacob Faibussowitsch     if (a) PetscCall(PetscArrayzero(a, ii[size]));
1993c69f721fSFande Kong   }
19943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1995c69f721fSFande Kong }
1996c69f721fSFande Kong 
199766976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPRE(Mat A)
1998d71ae5a4SJacob Faibussowitsch {
19996ea7df73SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
20006ea7df73SStefano Zampini 
20016ea7df73SStefano Zampini   PetscFunctionBegin;
20026ea7df73SStefano Zampini   if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(hA->ij)) {
2003792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetConstantValues, hA->ij, 0.0);
20046ea7df73SStefano Zampini   } else {
2005c69f721fSFande Kong     hypre_ParCSRMatrix *parcsr;
2006c69f721fSFande Kong 
20079566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
20089566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr)));
20099566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr)));
20106ea7df73SStefano Zampini   }
20113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2012c69f721fSFande Kong }
2013c69f721fSFande Kong 
2014d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_HYPRE_CSRMatrix(hypre_CSRMatrix *hA, PetscInt N, const PetscInt rows[], HYPRE_Complex diag)
2015d71ae5a4SJacob Faibussowitsch {
201639accc25SStefano Zampini   PetscInt       ii;
201739accc25SStefano Zampini   HYPRE_Int     *i, *j;
201839accc25SStefano Zampini   HYPRE_Complex *a;
2019c69f721fSFande Kong 
2020c69f721fSFande Kong   PetscFunctionBegin;
20213ba16761SJacob Faibussowitsch   if (!hA) PetscFunctionReturn(PETSC_SUCCESS);
2022c69f721fSFande Kong 
202339accc25SStefano Zampini   i = hypre_CSRMatrixI(hA);
202439accc25SStefano Zampini   j = hypre_CSRMatrixJ(hA);
2025c69f721fSFande Kong   a = hypre_CSRMatrixData(hA);
2026a32e9c99SJunchao Zhang #if defined(PETSC_HAVE_HYPRE_DEVICE)
2027a32e9c99SJunchao Zhang   if (HYPRE_MEMORY_DEVICE == hypre_CSRMatrixMemoryLocation(hA)) {
2028a32e9c99SJunchao Zhang   #if defined(HYPRE_USING_CUDA)
2029a32e9c99SJunchao Zhang     MatZeroRows_CUDA(N, rows, i, j, a, diag);
2030a32e9c99SJunchao Zhang   #elif defined(HYPRE_USING_HIP)
2031a32e9c99SJunchao Zhang     MatZeroRows_HIP(N, rows, i, j, a, diag);
2032a32e9c99SJunchao Zhang   #elif defined(PETSC_HAVE_KOKKOS)
2033a32e9c99SJunchao Zhang     MatZeroRows_Kokkos(N, rows, i, j, a, diag);
2034a32e9c99SJunchao Zhang   #else
2035a32e9c99SJunchao Zhang     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for MatZeroRows on a hypre matrix in this memory location");
2036a32e9c99SJunchao Zhang   #endif
2037a32e9c99SJunchao Zhang   } else
2038a32e9c99SJunchao Zhang #endif
2039a32e9c99SJunchao Zhang   {
2040c69f721fSFande Kong     for (ii = 0; ii < N; ii++) {
204139accc25SStefano Zampini       HYPRE_Int jj, ibeg, iend, irow;
204239accc25SStefano Zampini 
2043c69f721fSFande Kong       irow = rows[ii];
2044c69f721fSFande Kong       ibeg = i[irow];
2045c69f721fSFande Kong       iend = i[irow + 1];
2046c69f721fSFande Kong       for (jj = ibeg; jj < iend; jj++)
2047c69f721fSFande Kong         if (j[jj] == irow) a[jj] = diag;
2048c69f721fSFande Kong         else a[jj] = 0.0;
2049c69f721fSFande Kong     }
2050a32e9c99SJunchao Zhang   }
20513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2052c69f721fSFande Kong }
2053c69f721fSFande Kong 
2054d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_HYPRE(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
2055d71ae5a4SJacob Faibussowitsch {
2056c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
2057a32e9c99SJunchao Zhang   PetscInt           *lrows, len, *lrows2;
205839accc25SStefano Zampini   HYPRE_Complex       hdiag;
2059c69f721fSFande Kong 
2060c69f721fSFande Kong   PetscFunctionBegin;
206108401ef6SPierre Jolivet   PetscCheck(!x && !b, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Does not support to modify the solution and the right hand size");
20629566063dSJacob Faibussowitsch   PetscCall(PetscHYPREScalarCast(diag, &hdiag));
2063c69f721fSFande Kong   /* retrieve the internal matrix */
20649566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
2065c69f721fSFande Kong   /* get locally owned rows */
20669566063dSJacob Faibussowitsch   PetscCall(MatZeroRowsMapLocal_Private(A, N, rows, &len, &lrows));
2067a32e9c99SJunchao Zhang 
2068a32e9c99SJunchao Zhang #if defined(PETSC_HAVE_HYPRE_DEVICE)
2069a32e9c99SJunchao Zhang   if (HYPRE_MEMORY_DEVICE == hypre_CSRMatrixMemoryLocation(hypre_ParCSRMatrixDiag(parcsr))) {
2070a32e9c99SJunchao Zhang     Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
2071a32e9c99SJunchao Zhang     PetscInt   m;
2072a32e9c99SJunchao Zhang     PetscCall(MatGetLocalSize(A, &m, NULL));
2073a32e9c99SJunchao Zhang     if (!hA->rows_d) {
2074a32e9c99SJunchao Zhang       hA->rows_d = hypre_TAlloc(PetscInt, m, HYPRE_MEMORY_DEVICE);
2075a32e9c99SJunchao Zhang       if (m) PetscCheck(hA->rows_d, PETSC_COMM_SELF, PETSC_ERR_MEM, "HYPRE_TAlloc failed");
2076a32e9c99SJunchao Zhang     }
2077a32e9c99SJunchao Zhang     PetscCheck(len <= m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Too many rows in rows[]");
2078a32e9c99SJunchao Zhang     PetscStackCallExternalVoid("hypre_Memcpy", hypre_Memcpy(hA->rows_d, lrows, sizeof(PetscInt) * len, HYPRE_MEMORY_DEVICE, HYPRE_MEMORY_HOST));
2079a32e9c99SJunchao Zhang     lrows2 = hA->rows_d;
2080a32e9c99SJunchao Zhang   } else
2081a32e9c99SJunchao Zhang #endif
2082a32e9c99SJunchao Zhang   {
2083a32e9c99SJunchao Zhang     lrows2 = lrows;
2084a32e9c99SJunchao Zhang   }
2085a32e9c99SJunchao Zhang 
2086c69f721fSFande Kong   /* zero diagonal part */
2087a32e9c99SJunchao Zhang   PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr), len, lrows2, hdiag));
2088c69f721fSFande Kong   /* zero off-diagonal part */
2089a32e9c99SJunchao Zhang   PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr), len, lrows2, 0.0));
2090c69f721fSFande Kong 
20919566063dSJacob Faibussowitsch   PetscCall(PetscFree(lrows));
20923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2093c69f721fSFande Kong }
2094c69f721fSFande Kong 
2095d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_HYPRE(Mat mat, MatAssemblyType mode)
2096d71ae5a4SJacob Faibussowitsch {
2097c69f721fSFande Kong   PetscFunctionBegin;
20983ba16761SJacob Faibussowitsch   if (mat->nooffprocentries) PetscFunctionReturn(PETSC_SUCCESS);
2099c69f721fSFande Kong 
21009566063dSJacob Faibussowitsch   PetscCall(MatStashScatterBegin_Private(mat, &mat->stash, mat->rmap->range));
21013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2102c69f721fSFande Kong }
2103c69f721fSFande Kong 
2104d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
2105d71ae5a4SJacob Faibussowitsch {
2106c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
21072cf14000SStefano Zampini   HYPRE_Int           hnz;
2108c69f721fSFande Kong 
2109c69f721fSFande Kong   PetscFunctionBegin;
2110c69f721fSFande Kong   /* retrieve the internal matrix */
21119566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
2112c69f721fSFande Kong   /* call HYPRE API */
2113792fecdfSBarry Smith   PetscCallExternal(HYPRE_ParCSRMatrixGetRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v);
21142cf14000SStefano Zampini   if (nz) *nz = (PetscInt)hnz;
21153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2116c69f721fSFande Kong }
2117c69f721fSFande Kong 
2118d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
2119d71ae5a4SJacob Faibussowitsch {
2120c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
21212cf14000SStefano Zampini   HYPRE_Int           hnz;
2122c69f721fSFande Kong 
2123c69f721fSFande Kong   PetscFunctionBegin;
2124c69f721fSFande Kong   /* retrieve the internal matrix */
21259566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
2126c69f721fSFande Kong   /* call HYPRE API */
21272cf14000SStefano Zampini   hnz = nz ? (HYPRE_Int)(*nz) : 0;
2128792fecdfSBarry Smith   PetscCallExternal(HYPRE_ParCSRMatrixRestoreRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v);
21293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2130c69f721fSFande Kong }
2131c69f721fSFande Kong 
2132d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetValues_HYPRE(Mat A, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2133d71ae5a4SJacob Faibussowitsch {
213445b8d346SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
2135c69f721fSFande Kong   PetscInt   i;
21361d4906efSStefano Zampini 
2137c69f721fSFande Kong   PetscFunctionBegin;
21383ba16761SJacob Faibussowitsch   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2139c69f721fSFande Kong   /* Ignore negative row indices
2140c69f721fSFande Kong    * And negative column indices should be automatically ignored in hypre
2141c69f721fSFande Kong    * */
21422cf14000SStefano Zampini   for (i = 0; i < m; i++) {
21432cf14000SStefano Zampini     if (idxm[i] >= 0) {
21442cf14000SStefano Zampini       HYPRE_Int hn = (HYPRE_Int)n;
2145792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetValues, hA->ij, 1, &hn, (HYPRE_BigInt *)&idxm[i], (HYPRE_BigInt *)idxn, (HYPRE_Complex *)(v + i * n));
21462cf14000SStefano Zampini     }
21472cf14000SStefano Zampini   }
21483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2149c69f721fSFande Kong }
2150c69f721fSFande Kong 
2151d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_HYPRE(Mat A, MatOption op, PetscBool flg)
2152d71ae5a4SJacob Faibussowitsch {
2153ddbeb582SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
2154ddbeb582SStefano Zampini 
2155ddbeb582SStefano Zampini   PetscFunctionBegin;
2156c6698e78SStefano Zampini   switch (op) {
2157ddbeb582SStefano Zampini   case MAT_NO_OFF_PROC_ENTRIES:
215848a46eb9SPierre Jolivet     if (flg) PetscCallExternal(HYPRE_IJMatrixSetMaxOffProcElmts, hA->ij, 0);
2159ddbeb582SStefano Zampini     break;
2160651b1cf9SStefano Zampini   case MAT_IGNORE_OFF_PROC_ENTRIES:
2161651b1cf9SStefano Zampini     hA->donotstash = flg;
2162d71ae5a4SJacob Faibussowitsch     break;
2163d71ae5a4SJacob Faibussowitsch   default:
2164d71ae5a4SJacob Faibussowitsch     break;
2165ddbeb582SStefano Zampini   }
21663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2167ddbeb582SStefano Zampini }
2168c69f721fSFande Kong 
2169d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_HYPRE(Mat A, PetscViewer view)
2170d71ae5a4SJacob Faibussowitsch {
217145b8d346SStefano Zampini   PetscViewerFormat format;
217245b8d346SStefano Zampini 
217345b8d346SStefano Zampini   PetscFunctionBegin;
21749566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(view, &format));
21753ba16761SJacob Faibussowitsch   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(PETSC_SUCCESS);
217645b8d346SStefano Zampini   if (format != PETSC_VIEWER_NATIVE) {
21776ea7df73SStefano Zampini     Mat                 B;
21786ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
21796ea7df73SStefano Zampini     PetscErrorCode (*mview)(Mat, PetscViewer) = NULL;
21806ea7df73SStefano Zampini 
21819566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
21829566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(parcsr, MATAIJ, PETSC_USE_POINTER, &B));
21839566063dSJacob Faibussowitsch     PetscCall(MatGetOperation(B, MATOP_VIEW, (void (**)(void)) & mview));
218428b400f6SJacob Faibussowitsch     PetscCheck(mview, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Missing view operation");
21859566063dSJacob Faibussowitsch     PetscCall((*mview)(B, view));
21869566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
218745b8d346SStefano Zampini   } else {
218845b8d346SStefano Zampini     Mat_HYPRE  *hA = (Mat_HYPRE *)A->data;
218945b8d346SStefano Zampini     PetscMPIInt size;
219045b8d346SStefano Zampini     PetscBool   isascii;
219145b8d346SStefano Zampini     const char *filename;
219245b8d346SStefano Zampini 
219345b8d346SStefano Zampini     /* HYPRE uses only text files */
21949566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERASCII, &isascii));
219528b400f6SJacob Faibussowitsch     PetscCheck(isascii, PetscObjectComm((PetscObject)view), PETSC_ERR_SUP, "PetscViewerType %s: native HYPRE format needs PETSCVIEWERASCII", ((PetscObject)view)->type_name);
21969566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileGetName(view, &filename));
2197792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixPrint, hA->ij, filename);
21989566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(hA->comm, &size));
219945b8d346SStefano Zampini     if (size > 1) {
22009566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(view, "Matrix files: %s.%05d ... %s.%05d\n", filename, 0, filename, size - 1));
220145b8d346SStefano Zampini     } else {
22029566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(view, "Matrix file: %s.%05d\n", filename, 0));
220345b8d346SStefano Zampini     }
220445b8d346SStefano Zampini   }
22053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
220645b8d346SStefano Zampini }
220745b8d346SStefano Zampini 
2208d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCopy_HYPRE(Mat A, Mat B, MatStructure str)
2209d71ae5a4SJacob Faibussowitsch {
2210465edc17SStefano Zampini   hypre_ParCSRMatrix *acsr, *bcsr;
2211465edc17SStefano Zampini 
2212465edc17SStefano Zampini   PetscFunctionBegin;
2213465edc17SStefano Zampini   if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) {
22149566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &acsr));
22159566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(B, &bcsr));
2216792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixCopy, acsr, bcsr, 1);
22179566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_SORTED_FULL, PETSC_TRUE)); /* "perfect" preallocation, so no need for hypre_AuxParCSRMatrixNeedAux */
22189566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
22199566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
2220465edc17SStefano Zampini   } else {
22219566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
2222465edc17SStefano Zampini   }
22233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2224465edc17SStefano Zampini }
2225465edc17SStefano Zampini 
2226d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_HYPRE(Mat A, Vec d)
2227d71ae5a4SJacob Faibussowitsch {
22286305df00SStefano Zampini   hypre_ParCSRMatrix *parcsr;
22296305df00SStefano Zampini   hypre_CSRMatrix    *dmat;
223039accc25SStefano Zampini   HYPRE_Complex      *a;
22316305df00SStefano Zampini   PetscBool           cong;
22326305df00SStefano Zampini 
22336305df00SStefano Zampini   PetscFunctionBegin;
22349566063dSJacob Faibussowitsch   PetscCall(MatHasCongruentLayouts(A, &cong));
223528b400f6SJacob Faibussowitsch   PetscCheck(cong, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only for square matrices with same local distributions of rows and columns");
22369566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
22376305df00SStefano Zampini   dmat = hypre_ParCSRMatrixDiag(parcsr);
22386305df00SStefano Zampini   if (dmat) {
223906977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
224006977982Sstefanozampini     HYPRE_MemoryLocation mem = hypre_CSRMatrixMemoryLocation(dmat);
224106977982Sstefanozampini #else
224206977982Sstefanozampini     HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST;
224306977982Sstefanozampini #endif
224406977982Sstefanozampini 
224506977982Sstefanozampini     if (mem != HYPRE_MEMORY_HOST) PetscCall(VecGetArrayWriteAndMemType(d, (PetscScalar **)&a, NULL));
224606977982Sstefanozampini     else PetscCall(VecGetArrayWrite(d, (PetscScalar **)&a));
224706977982Sstefanozampini     hypre_CSRMatrixExtractDiagonal(dmat, a, 0);
224806977982Sstefanozampini     if (mem != HYPRE_MEMORY_HOST) PetscCall(VecRestoreArrayWriteAndMemType(d, (PetscScalar **)&a));
224906977982Sstefanozampini     else PetscCall(VecRestoreArrayWrite(d, (PetscScalar **)&a));
22506305df00SStefano Zampini   }
22513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22526305df00SStefano Zampini }
22536305df00SStefano Zampini 
2254363d496dSStefano Zampini #include <petscblaslapack.h>
2255363d496dSStefano Zampini 
2256d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAXPY_HYPRE(Mat Y, PetscScalar a, Mat X, MatStructure str)
2257d71ae5a4SJacob Faibussowitsch {
2258363d496dSStefano Zampini   PetscFunctionBegin;
22596ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
22606ea7df73SStefano Zampini   {
22616ea7df73SStefano Zampini     Mat                 B;
22626ea7df73SStefano Zampini     hypre_ParCSRMatrix *x, *y, *z;
22636ea7df73SStefano Zampini 
22649566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(Y, &y));
22659566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(X, &x));
2266792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixAdd, 1.0, y, 1.0, x, &z);
22679566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(z, MATHYPRE, PETSC_OWN_POINTER, &B));
22689566063dSJacob Faibussowitsch     PetscCall(MatHeaderMerge(Y, &B));
22696ea7df73SStefano Zampini   }
22706ea7df73SStefano Zampini #else
2271363d496dSStefano Zampini   if (str == SAME_NONZERO_PATTERN) {
2272363d496dSStefano Zampini     hypre_ParCSRMatrix *x, *y;
2273363d496dSStefano Zampini     hypre_CSRMatrix    *xloc, *yloc;
2274363d496dSStefano Zampini     PetscInt            xnnz, ynnz;
227539accc25SStefano Zampini     HYPRE_Complex      *xarr, *yarr;
2276363d496dSStefano Zampini     PetscBLASInt        one = 1, bnz;
2277363d496dSStefano Zampini 
22789566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(Y, &y));
22799566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(X, &x));
2280363d496dSStefano Zampini 
2281363d496dSStefano Zampini     /* diagonal block */
2282363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixDiag(x);
2283363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixDiag(y);
2284363d496dSStefano Zampini     xnnz = 0;
2285363d496dSStefano Zampini     ynnz = 0;
2286363d496dSStefano Zampini     xarr = NULL;
2287363d496dSStefano Zampini     yarr = NULL;
2288363d496dSStefano Zampini     if (xloc) {
228939accc25SStefano Zampini       xarr = hypre_CSRMatrixData(xloc);
2290363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
2291363d496dSStefano Zampini     }
2292363d496dSStefano Zampini     if (yloc) {
229339accc25SStefano Zampini       yarr = hypre_CSRMatrixData(yloc);
2294363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
2295363d496dSStefano Zampini     }
229608401ef6SPierre Jolivet     PetscCheck(xnnz == ynnz, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Different number of nonzeros in diagonal block %" PetscInt_FMT " != %" PetscInt_FMT, xnnz, ynnz);
22979566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(xnnz, &bnz));
2298792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one));
2299363d496dSStefano Zampini 
2300363d496dSStefano Zampini     /* off-diagonal block */
2301363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixOffd(x);
2302363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixOffd(y);
2303363d496dSStefano Zampini     xnnz = 0;
2304363d496dSStefano Zampini     ynnz = 0;
2305363d496dSStefano Zampini     xarr = NULL;
2306363d496dSStefano Zampini     yarr = NULL;
2307363d496dSStefano Zampini     if (xloc) {
230839accc25SStefano Zampini       xarr = hypre_CSRMatrixData(xloc);
2309363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
2310363d496dSStefano Zampini     }
2311363d496dSStefano Zampini     if (yloc) {
231239accc25SStefano Zampini       yarr = hypre_CSRMatrixData(yloc);
2313363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
2314363d496dSStefano Zampini     }
231508401ef6SPierre 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);
23169566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(xnnz, &bnz));
2317792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one));
2318363d496dSStefano Zampini   } else if (str == SUBSET_NONZERO_PATTERN) {
23199566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic(Y, a, X, str));
2320363d496dSStefano Zampini   } else {
2321363d496dSStefano Zampini     Mat B;
2322363d496dSStefano Zampini 
23239566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic_Preallocate(Y, X, &B));
23249566063dSJacob Faibussowitsch     PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str));
23259566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(Y, &B));
2326363d496dSStefano Zampini   }
23276ea7df73SStefano Zampini #endif
23283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2329363d496dSStefano Zampini }
2330363d496dSStefano Zampini 
23312c4ab24aSJunchao Zhang static PetscErrorCode MatDuplicate_HYPRE(Mat A, MatDuplicateOption op, Mat *B)
23322c4ab24aSJunchao Zhang {
23332c4ab24aSJunchao Zhang   hypre_ParCSRMatrix *parcsr = NULL;
23342c4ab24aSJunchao Zhang   PetscCopyMode       cpmode;
23352c4ab24aSJunchao Zhang   Mat_HYPRE          *hA;
23362c4ab24aSJunchao Zhang 
23372c4ab24aSJunchao Zhang   PetscFunctionBegin;
23382c4ab24aSJunchao Zhang   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
23392c4ab24aSJunchao Zhang   if (op == MAT_DO_NOT_COPY_VALUES || op == MAT_SHARE_NONZERO_PATTERN) {
23402c4ab24aSJunchao Zhang     parcsr = hypre_ParCSRMatrixClone(parcsr, 0);
23412c4ab24aSJunchao Zhang     cpmode = PETSC_OWN_POINTER;
23422c4ab24aSJunchao Zhang   } else {
23432c4ab24aSJunchao Zhang     cpmode = PETSC_COPY_VALUES;
23442c4ab24aSJunchao Zhang   }
23452c4ab24aSJunchao Zhang   PetscCall(MatCreateFromParCSR(parcsr, MATHYPRE, cpmode, B));
23462c4ab24aSJunchao Zhang   hA = (Mat_HYPRE *)A->data;
23472c4ab24aSJunchao Zhang   if (hA->cooMat) {
234806977982Sstefanozampini     Mat_HYPRE *hB = (Mat_HYPRE *)((*B)->data);
2349b73e3080SStefano Zampini     op            = (op == MAT_DO_NOT_COPY_VALUES) ? op : MAT_COPY_VALUES;
2350b73e3080SStefano Zampini     /* Cannot simply increase the reference count of hA->cooMat, since B needs to share cooMat's data array */
235106977982Sstefanozampini     PetscCall(MatDuplicate(hA->cooMat, op, &hB->cooMat));
235206977982Sstefanozampini     PetscCall(MatHYPRE_AttachCOOMat(*B));
23532c4ab24aSJunchao Zhang   }
23542c4ab24aSJunchao Zhang   PetscFunctionReturn(PETSC_SUCCESS);
23552c4ab24aSJunchao Zhang }
23562c4ab24aSJunchao Zhang 
2357d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetPreallocationCOO_HYPRE(Mat mat, PetscCount coo_n, PetscInt coo_i[], PetscInt coo_j[])
2358d71ae5a4SJacob Faibussowitsch {
235906977982Sstefanozampini   Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data;
23605fbaff96SJunchao Zhang 
23615fbaff96SJunchao Zhang   PetscFunctionBegin;
2362651b1cf9SStefano Zampini   /* Build an agent matrix cooMat with AIJ format
23635fbaff96SJunchao 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.
23645fbaff96SJunchao Zhang    */
236506977982Sstefanozampini   PetscCall(MatHYPRE_CreateCOOMat(mat));
236606977982Sstefanozampini   PetscCall(MatSetOption(hmat->cooMat, MAT_IGNORE_OFF_PROC_ENTRIES, hmat->donotstash));
236706977982Sstefanozampini   PetscCall(MatSetOption(hmat->cooMat, MAT_NO_OFF_PROC_ENTRIES, mat->nooffprocentries));
2368651b1cf9SStefano Zampini 
2369651b1cf9SStefano Zampini   /* MatSetPreallocationCOO_SeqAIJ and MatSetPreallocationCOO_MPIAIJ uses this specific
2370651b1cf9SStefano Zampini      name to automatically put the diagonal entries first */
237106977982Sstefanozampini   PetscCall(PetscObjectSetName((PetscObject)hmat->cooMat, "_internal_COO_mat_for_hypre"));
237206977982Sstefanozampini   PetscCall(MatSetPreallocationCOO(hmat->cooMat, coo_n, coo_i, coo_j));
237306977982Sstefanozampini   hmat->cooMat->assembled = PETSC_TRUE;
23745fbaff96SJunchao Zhang 
23755fbaff96SJunchao Zhang   /* Copy the sparsity pattern from cooMat to hypre IJMatrix hmat->ij */
23765fbaff96SJunchao Zhang   PetscCall(MatSetOption(mat, MAT_SORTED_FULL, PETSC_TRUE));
237706977982Sstefanozampini   PetscCall(MatHYPRE_CreateFromMat(hmat->cooMat, hmat));      /* Create hmat->ij and preallocate it */
237806977982Sstefanozampini   PetscCall(MatHYPRE_IJMatrixCopyIJ(hmat->cooMat, hmat->ij)); /* Copy A's (i,j) to hmat->ij */
23795fbaff96SJunchao Zhang 
23805fbaff96SJunchao Zhang   mat->preallocated = PETSC_TRUE;
23815fbaff96SJunchao Zhang   PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
23825fbaff96SJunchao Zhang   PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); /* Migrate mat to device if it is bound to. Hypre builds its own SpMV context here */
23835fbaff96SJunchao Zhang 
23842c4ab24aSJunchao Zhang   /* Attach cooMat to mat */
238506977982Sstefanozampini   PetscCall(MatHYPRE_AttachCOOMat(mat));
23863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23875fbaff96SJunchao Zhang }
23885fbaff96SJunchao Zhang 
2389d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesCOO_HYPRE(Mat mat, const PetscScalar v[], InsertMode imode)
2390d71ae5a4SJacob Faibussowitsch {
23915fbaff96SJunchao Zhang   Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data;
23925fbaff96SJunchao Zhang 
23935fbaff96SJunchao Zhang   PetscFunctionBegin;
2394b73e3080SStefano Zampini   PetscCheck(hmat->cooMat, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet");
23955fbaff96SJunchao Zhang   PetscCall(MatSetValuesCOO(hmat->cooMat, v, imode));
2396651b1cf9SStefano Zampini   PetscCall(MatViewFromOptions(hmat->cooMat, (PetscObject)mat, "-cooMat_view"));
23973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23985fbaff96SJunchao Zhang }
23995fbaff96SJunchao Zhang 
2400a055b5aaSBarry Smith /*MC
24012ef1f0ffSBarry Smith    MATHYPRE - "hypre" - A matrix type to be used for sequential and parallel sparse matrices
2402a055b5aaSBarry Smith           based on the hypre IJ interface.
2403a055b5aaSBarry Smith 
2404a055b5aaSBarry Smith    Level: intermediate
2405a055b5aaSBarry Smith 
24061cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatHYPRESetPreallocation`
2407a055b5aaSBarry Smith M*/
2408a055b5aaSBarry Smith 
2409d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_HYPRE(Mat B)
2410d71ae5a4SJacob Faibussowitsch {
241163c07aadSStefano Zampini   Mat_HYPRE *hB;
241263c07aadSStefano Zampini 
241363c07aadSStefano Zampini   PetscFunctionBegin;
24144dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&hB));
24156ea7df73SStefano Zampini 
2416978814f1SStefano Zampini   hB->inner_free      = PETSC_TRUE;
2417651b1cf9SStefano Zampini   hB->array_available = PETSC_TRUE;
2418978814f1SStefano Zampini 
241963c07aadSStefano Zampini   B->data = (void *)hB;
242063c07aadSStefano Zampini 
24219566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(B->ops, sizeof(struct _MatOps)));
242263c07aadSStefano Zampini   B->ops->mult                  = MatMult_HYPRE;
242363c07aadSStefano Zampini   B->ops->multtranspose         = MatMultTranspose_HYPRE;
2424414bd5c3SStefano Zampini   B->ops->multadd               = MatMultAdd_HYPRE;
2425414bd5c3SStefano Zampini   B->ops->multtransposeadd      = MatMultTransposeAdd_HYPRE;
242663c07aadSStefano Zampini   B->ops->setup                 = MatSetUp_HYPRE;
242763c07aadSStefano Zampini   B->ops->destroy               = MatDestroy_HYPRE;
242863c07aadSStefano Zampini   B->ops->assemblyend           = MatAssemblyEnd_HYPRE;
2429c69f721fSFande Kong   B->ops->assemblybegin         = MatAssemblyBegin_HYPRE;
2430d975228cSstefano_zampini   B->ops->setvalues             = MatSetValues_HYPRE;
243168ec7858SStefano Zampini   B->ops->missingdiagonal       = MatMissingDiagonal_HYPRE;
243268ec7858SStefano Zampini   B->ops->scale                 = MatScale_HYPRE;
243368ec7858SStefano Zampini   B->ops->zerorowscolumns       = MatZeroRowsColumns_HYPRE;
2434c69f721fSFande Kong   B->ops->zeroentries           = MatZeroEntries_HYPRE;
2435c69f721fSFande Kong   B->ops->zerorows              = MatZeroRows_HYPRE;
2436c69f721fSFande Kong   B->ops->getrow                = MatGetRow_HYPRE;
2437c69f721fSFande Kong   B->ops->restorerow            = MatRestoreRow_HYPRE;
2438c69f721fSFande Kong   B->ops->getvalues             = MatGetValues_HYPRE;
2439ddbeb582SStefano Zampini   B->ops->setoption             = MatSetOption_HYPRE;
244045b8d346SStefano Zampini   B->ops->duplicate             = MatDuplicate_HYPRE;
2441465edc17SStefano Zampini   B->ops->copy                  = MatCopy_HYPRE;
244245b8d346SStefano Zampini   B->ops->view                  = MatView_HYPRE;
24436305df00SStefano Zampini   B->ops->getdiagonal           = MatGetDiagonal_HYPRE;
2444363d496dSStefano Zampini   B->ops->axpy                  = MatAXPY_HYPRE;
24454222ddf1SHong Zhang   B->ops->productsetfromoptions = MatProductSetFromOptions_HYPRE;
24466ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
24476ea7df73SStefano Zampini   B->ops->bindtocpu = MatBindToCPU_HYPRE;
24486ea7df73SStefano Zampini   B->boundtocpu     = PETSC_FALSE;
24496ea7df73SStefano Zampini #endif
245045b8d346SStefano Zampini 
245145b8d346SStefano Zampini   /* build cache for off array entries formed */
24529566063dSJacob Faibussowitsch   PetscCall(MatStashCreate_Private(PetscObjectComm((PetscObject)B), 1, &B->stash));
245363c07aadSStefano Zampini 
24549566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)B), &hB->comm));
24559566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRE));
24569566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_aij_C", MatConvert_HYPRE_AIJ));
24579566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_is_C", MatConvert_HYPRE_IS));
24589566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_hypre_C", MatProductSetFromOptions_HYPRE));
24599566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaij_hypre_C", MatProductSetFromOptions_HYPRE));
24609566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPRESetPreallocation_C", MatHYPRESetPreallocation_HYPRE));
24619566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPREGetParCSR_C", MatHYPREGetParCSR_HYPRE));
24625fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_HYPRE));
24635fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetValuesCOO_C", MatSetValuesCOO_HYPRE));
24646ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
24656ea7df73SStefano Zampini   #if defined(HYPRE_USING_HIP)
246606977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijhipsparse_hypre_C", MatProductSetFromOptions_HYPRE));
246706977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaijhipsparse_hypre_C", MatProductSetFromOptions_HYPRE));
24689566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP));
24699566063dSJacob Faibussowitsch   PetscCall(MatSetVecType(B, VECHIP));
24706ea7df73SStefano Zampini   #endif
24716ea7df73SStefano Zampini   #if defined(HYPRE_USING_CUDA)
247206977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijcusparse_hypre_C", MatProductSetFromOptions_HYPRE));
247306977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaijcusparse_hypre_C", MatProductSetFromOptions_HYPRE));
24749566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
24759566063dSJacob Faibussowitsch   PetscCall(MatSetVecType(B, VECCUDA));
24766ea7df73SStefano Zampini   #endif
24776ea7df73SStefano Zampini #endif
2478ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
24793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
248063c07aadSStefano Zampini }
2481