xref: /petsc/src/mat/impls/hypre/mhypre.c (revision d718548593d9c489c5a95a5041602602f6eb0ed9)
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);
14887ef5fa6SStefano 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 
4961c265611SJunchao Zhang // Build COO's coordinate list i[], j[] based on CSR's i[], j[] arrays and the number of local rows 'n'
49706977982Sstefanozampini static PetscErrorCode CSRtoCOO_Private(PetscInt n, const PetscInt ii[], const PetscInt jj[], PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j)
49806977982Sstefanozampini {
49906977982Sstefanozampini   PetscInt *cooi, *cooj;
50006977982Sstefanozampini 
50106977982Sstefanozampini   PetscFunctionBegin;
50206977982Sstefanozampini   *ncoo = ii[n];
50306977982Sstefanozampini   PetscCall(PetscMalloc2(*ncoo, &cooi, *ncoo, &cooj));
50406977982Sstefanozampini   for (PetscInt i = 0; i < n; i++) {
50506977982Sstefanozampini     for (PetscInt j = ii[i]; j < ii[i + 1]; j++) cooi[j] = i;
50606977982Sstefanozampini   }
50706977982Sstefanozampini   PetscCall(PetscArraycpy(cooj, jj, *ncoo));
50806977982Sstefanozampini   *coo_i = cooi;
50906977982Sstefanozampini   *coo_j = cooj;
51006977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
51106977982Sstefanozampini }
51206977982Sstefanozampini 
5131c265611SJunchao Zhang // Similar to CSRtoCOO_Private, but the CSR's i[], j[] are of type HYPRE_Int
51406977982Sstefanozampini static PetscErrorCode CSRtoCOO_HYPRE_Int_Private(PetscInt n, const HYPRE_Int ii[], const HYPRE_Int jj[], PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j)
51506977982Sstefanozampini {
51606977982Sstefanozampini   PetscInt *cooi, *cooj;
51706977982Sstefanozampini 
51806977982Sstefanozampini   PetscFunctionBegin;
51906977982Sstefanozampini   *ncoo = ii[n];
52006977982Sstefanozampini   PetscCall(PetscMalloc2(*ncoo, &cooi, *ncoo, &cooj));
52106977982Sstefanozampini   for (PetscInt i = 0; i < n; i++) {
52206977982Sstefanozampini     for (HYPRE_Int j = ii[i]; j < ii[i + 1]; j++) cooi[j] = i;
52306977982Sstefanozampini   }
52406977982Sstefanozampini   for (PetscCount i = 0; i < *ncoo; i++) cooj[i] = jj[i];
52506977982Sstefanozampini   *coo_i = cooi;
52606977982Sstefanozampini   *coo_j = cooj;
52706977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
52806977982Sstefanozampini }
52906977982Sstefanozampini 
5301c265611SJunchao Zhang // Build a COO data structure for the seqaij matrix, as if the nonzeros are laid out in the same order as in the CSR
53106977982Sstefanozampini static PetscErrorCode MatSeqAIJGetCOO_Private(Mat A, PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j)
53206977982Sstefanozampini {
53306977982Sstefanozampini   PetscInt        n;
53406977982Sstefanozampini   const PetscInt *ii, *jj;
53506977982Sstefanozampini   PetscBool       done;
53606977982Sstefanozampini 
53706977982Sstefanozampini   PetscFunctionBegin;
53806977982Sstefanozampini   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &done));
53906977982Sstefanozampini   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Failure for MatGetRowIJ");
54006977982Sstefanozampini   PetscCall(CSRtoCOO_Private(n, ii, jj, ncoo, coo_i, coo_j));
54106977982Sstefanozampini   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &done));
54206977982Sstefanozampini   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Failure for MatRestoreRowIJ");
54306977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
54406977982Sstefanozampini }
54506977982Sstefanozampini 
5461c265611SJunchao Zhang // Build a COO data structure for the hypreCSRMatrix, as if the nonzeros are laid out in the same order as in the hypreCSRMatrix
54706977982Sstefanozampini static PetscErrorCode hypreCSRMatrixGetCOO_Private(hypre_CSRMatrix *A, PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j)
54806977982Sstefanozampini {
54906977982Sstefanozampini   PetscInt             n = hypre_CSRMatrixNumRows(A);
55006977982Sstefanozampini   HYPRE_Int           *ii, *jj;
55106977982Sstefanozampini   HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST;
55206977982Sstefanozampini 
55306977982Sstefanozampini   PetscFunctionBegin;
55406977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
55506977982Sstefanozampini   mem = hypre_CSRMatrixMemoryLocation(A);
55606977982Sstefanozampini   if (mem != HYPRE_MEMORY_HOST) {
55706977982Sstefanozampini     PetscCount nnz = hypre_CSRMatrixNumNonzeros(A);
55806977982Sstefanozampini     PetscCall(PetscMalloc2(n + 1, &ii, nnz, &jj));
55906977982Sstefanozampini     hypre_TMemcpy(ii, hypre_CSRMatrixI(A), HYPRE_Int, n + 1, HYPRE_MEMORY_HOST, mem);
56006977982Sstefanozampini     hypre_TMemcpy(jj, hypre_CSRMatrixJ(A), HYPRE_Int, nnz, HYPRE_MEMORY_HOST, mem);
56106977982Sstefanozampini   } else {
56206977982Sstefanozampini #else
56306977982Sstefanozampini   {
56406977982Sstefanozampini #endif
56506977982Sstefanozampini     ii = hypre_CSRMatrixI(A);
56606977982Sstefanozampini     jj = hypre_CSRMatrixJ(A);
56706977982Sstefanozampini   }
56806977982Sstefanozampini   PetscCall(CSRtoCOO_HYPRE_Int_Private(n, ii, jj, ncoo, coo_i, coo_j));
56906977982Sstefanozampini   if (mem != HYPRE_MEMORY_HOST) PetscCall(PetscFree2(ii, jj));
57006977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
57106977982Sstefanozampini }
57206977982Sstefanozampini 
57306977982Sstefanozampini static PetscErrorCode MatSetValuesCOOFromCSRMatrix_Private(Mat A, hypre_CSRMatrix *H)
57406977982Sstefanozampini {
57506977982Sstefanozampini   PetscBool            iscpu = PETSC_TRUE;
57606977982Sstefanozampini   PetscScalar         *a;
57706977982Sstefanozampini   HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST;
57806977982Sstefanozampini 
57906977982Sstefanozampini   PetscFunctionBegin;
58006977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
58106977982Sstefanozampini   mem = hypre_CSRMatrixMemoryLocation(H);
58206977982Sstefanozampini   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATSEQAIJ, &iscpu));
58306977982Sstefanozampini #endif
58406977982Sstefanozampini   if (iscpu && mem != HYPRE_MEMORY_HOST) {
58506977982Sstefanozampini     PetscCount nnz = hypre_CSRMatrixNumNonzeros(H);
58606977982Sstefanozampini     PetscCall(PetscMalloc1(nnz, &a));
58706977982Sstefanozampini     hypre_TMemcpy(a, hypre_CSRMatrixData(H), PetscScalar, nnz, HYPRE_MEMORY_HOST, mem);
58806977982Sstefanozampini   } else {
58906977982Sstefanozampini     a = (PetscScalar *)hypre_CSRMatrixData(H);
59006977982Sstefanozampini   }
59106977982Sstefanozampini   PetscCall(MatSetValuesCOO(A, a, INSERT_VALUES));
59206977982Sstefanozampini   if (iscpu && mem != HYPRE_MEMORY_HOST) PetscCall(PetscFree(a));
593b73e3080SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
594b73e3080SStefano Zampini }
595b73e3080SStefano Zampini 
596b73e3080SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType type, MatReuse reuse, Mat *B)
597b73e3080SStefano Zampini {
598b73e3080SStefano Zampini   MPI_Comm     comm = PetscObjectComm((PetscObject)A);
59906977982Sstefanozampini   Mat          M = NULL, dH = NULL, oH = NULL, dA = NULL, oA = NULL;
600*d7185485SAlex Lindsay   PetscBool    ismpiaij, issbaij, isbaij, boundtocpu = PETSC_TRUE;
601b73e3080SStefano Zampini   Mat_HYPRE   *hA;
602*d7185485SAlex Lindsay   PetscMemType memtype = PETSC_MEMTYPE_HOST;
603b73e3080SStefano Zampini 
604b73e3080SStefano Zampini   PetscFunctionBegin;
605*d7185485SAlex Lindsay   if (PetscDefined(HAVE_HYPRE_DEVICE)) {
606*d7185485SAlex Lindsay     PetscCall(MatGetCurrentMemType(A, &memtype));
607*d7185485SAlex Lindsay     PetscHYPREInitialize();
608*d7185485SAlex Lindsay     boundtocpu = PetscMemTypeHost(memtype) ? PETSC_TRUE : PETSC_FALSE;
609*d7185485SAlex Lindsay     PetscCallExternal(HYPRE_SetMemoryLocation, boundtocpu ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE);
610*d7185485SAlex Lindsay   }
611*d7185485SAlex Lindsay 
612b73e3080SStefano Zampini   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &issbaij, MATSEQSBAIJ, MATMPIBAIJ, ""));
613b73e3080SStefano Zampini   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &isbaij, MATSEQBAIJ, MATMPIBAIJ, ""));
614b73e3080SStefano Zampini   if (isbaij || issbaij) { /* handle BAIJ and SBAIJ */
615b73e3080SStefano Zampini     PetscBool ismpi;
616b73e3080SStefano Zampini     MatType   newtype;
617b73e3080SStefano Zampini 
618b73e3080SStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &ismpi, MATMPISBAIJ, MATMPIBAIJ, ""));
619b73e3080SStefano Zampini     newtype = ismpi ? MATMPIAIJ : MATSEQAIJ;
62063c07aadSStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
621b73e3080SStefano Zampini       PetscCall(MatConvert(*B, newtype, MAT_INPLACE_MATRIX, B));
622b73e3080SStefano Zampini       PetscCall(MatConvert(A, newtype, MAT_REUSE_MATRIX, B));
623b73e3080SStefano Zampini       PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B));
624b73e3080SStefano Zampini     } else if (reuse == MAT_INITIAL_MATRIX) {
625b73e3080SStefano Zampini       PetscCall(MatConvert(A, newtype, MAT_INITIAL_MATRIX, B));
626b73e3080SStefano Zampini       PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B));
62763c07aadSStefano Zampini     } else {
628b73e3080SStefano Zampini       PetscCall(MatConvert(A, newtype, MAT_INPLACE_MATRIX, &A));
629b73e3080SStefano Zampini       PetscCall(MatConvert(A, MATHYPRE, MAT_INPLACE_MATRIX, &A));
630b73e3080SStefano Zampini     }
631*d7185485SAlex Lindsay #if defined(PETSC_HAVE_DEVICE)
632*d7185485SAlex Lindsay     (*B)->boundtocpu = boundtocpu;
633*d7185485SAlex Lindsay #endif
634b73e3080SStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
635b73e3080SStefano Zampini   }
63606977982Sstefanozampini 
63706977982Sstefanozampini   dA = A;
638b73e3080SStefano Zampini   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
639b73e3080SStefano Zampini   if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(A, &dA, &oA, NULL));
64006977982Sstefanozampini 
641b73e3080SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
64206977982Sstefanozampini     PetscCount coo_n;
64306977982Sstefanozampini     PetscInt  *coo_i, *coo_j;
64406977982Sstefanozampini 
6459566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm, &M));
6469566063dSJacob Faibussowitsch     PetscCall(MatSetType(M, MATHYPRE));
6479566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(M, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
648b73e3080SStefano Zampini     PetscCall(MatSetOption(M, MAT_SORTED_FULL, PETSC_TRUE));
649b73e3080SStefano Zampini     PetscCall(MatSetOption(M, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE));
650b73e3080SStefano Zampini 
651b73e3080SStefano Zampini     hA = (Mat_HYPRE *)M->data;
65206977982Sstefanozampini     PetscCall(MatHYPRE_CreateFromMat(A, hA));
65306977982Sstefanozampini     PetscCall(MatHYPRE_IJMatrixCopyIJ(A, hA->ij));
65406977982Sstefanozampini 
65506977982Sstefanozampini     PetscCall(MatHYPRE_CreateCOOMat(M));
65606977982Sstefanozampini 
65706977982Sstefanozampini     dH = hA->cooMat;
65806977982Sstefanozampini     PetscCall(PetscObjectBaseTypeCompare((PetscObject)hA->cooMat, MATMPIAIJ, &ismpiaij));
65906977982Sstefanozampini     if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(hA->cooMat, &dH, &oH, NULL));
66006977982Sstefanozampini 
66106977982Sstefanozampini     PetscCall(PetscObjectSetName((PetscObject)dH, "_internal_COO_mat_for_hypre"));
66206977982Sstefanozampini     PetscCall(MatSeqAIJGetCOO_Private(dA, &coo_n, &coo_i, &coo_j));
66306977982Sstefanozampini     PetscCall(MatSetPreallocationCOO(dH, coo_n, coo_i, coo_j));
66406977982Sstefanozampini     PetscCall(PetscFree2(coo_i, coo_j));
66506977982Sstefanozampini     if (oH) {
66606977982Sstefanozampini       PetscCall(PetscLayoutDestroy(&oH->cmap));
66706977982Sstefanozampini       PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)oH), oA->cmap->n, oA->cmap->n, 1, &oH->cmap));
66806977982Sstefanozampini       PetscCall(MatSeqAIJGetCOO_Private(oA, &coo_n, &coo_i, &coo_j));
66906977982Sstefanozampini       PetscCall(MatSetPreallocationCOO(oH, coo_n, coo_i, coo_j));
67006977982Sstefanozampini       PetscCall(PetscFree2(coo_i, coo_j));
67106977982Sstefanozampini     }
67206977982Sstefanozampini     hA->cooMat->assembled = PETSC_TRUE;
67306977982Sstefanozampini 
674b73e3080SStefano Zampini     M->preallocated = PETSC_TRUE;
67506977982Sstefanozampini     PetscCall(MatAssemblyBegin(M, MAT_FINAL_ASSEMBLY));
67606977982Sstefanozampini     PetscCall(MatAssemblyEnd(M, MAT_FINAL_ASSEMBLY));
67706977982Sstefanozampini 
67806977982Sstefanozampini     PetscCall(MatHYPRE_AttachCOOMat(M));
67984d4e069SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) *B = M;
680b73e3080SStefano Zampini   } else M = *B;
681b73e3080SStefano Zampini 
682b73e3080SStefano Zampini   hA = (Mat_HYPRE *)M->data;
68306977982Sstefanozampini   PetscCheck(hA->cooMat, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet");
68406977982Sstefanozampini 
68506977982Sstefanozampini   dH = hA->cooMat;
68606977982Sstefanozampini   PetscCall(PetscObjectBaseTypeCompare((PetscObject)hA->cooMat, MATMPIAIJ, &ismpiaij));
68706977982Sstefanozampini   if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(hA->cooMat, &dH, &oH, NULL));
68806977982Sstefanozampini 
68906977982Sstefanozampini   PetscScalar *a;
69006977982Sstefanozampini   PetscCall(MatSeqAIJGetCSRAndMemType(dA, NULL, NULL, &a, NULL));
69106977982Sstefanozampini   PetscCall(MatSetValuesCOO(dH, a, INSERT_VALUES));
69206977982Sstefanozampini   if (oH) {
69306977982Sstefanozampini     PetscCall(MatSeqAIJGetCSRAndMemType(oA, NULL, NULL, &a, NULL));
69406977982Sstefanozampini     PetscCall(MatSetValuesCOO(oH, a, INSERT_VALUES));
69506977982Sstefanozampini   }
696b73e3080SStefano Zampini 
69748a46eb9SPierre Jolivet   if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &M));
698*d7185485SAlex Lindsay #if defined(PETSC_HAVE_DEVICE)
699*d7185485SAlex Lindsay   (*B)->boundtocpu = boundtocpu;
700*d7185485SAlex Lindsay #endif
7013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
70263c07aadSStefano Zampini }
70363c07aadSStefano Zampini 
704d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_HYPRE_AIJ(Mat A, MatType mtype, MatReuse reuse, Mat *B)
705d71ae5a4SJacob Faibussowitsch {
70606977982Sstefanozampini   Mat                 M, dA = NULL, oA = NULL;
70763c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
70806977982Sstefanozampini   hypre_CSRMatrix    *dH, *oH;
70963c07aadSStefano Zampini   MPI_Comm            comm;
71006977982Sstefanozampini   PetscBool           ismpiaij, isseqaij;
71163c07aadSStefano Zampini 
71263c07aadSStefano Zampini   PetscFunctionBegin;
71363c07aadSStefano Zampini   comm = PetscObjectComm((PetscObject)A);
71463c07aadSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
7159566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATMPIAIJ, &ismpiaij));
7169566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATSEQAIJ, &isseqaij));
71706977982Sstefanozampini     PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Only MATMPIAIJ or MATSEQAIJ base types are supported");
71863c07aadSStefano Zampini   }
71906977982Sstefanozampini   PetscCall(MatHYPREGetParCSR(A, &parcsr));
7206ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
72106977982Sstefanozampini   if (HYPRE_MEMORY_DEVICE == hypre_ParCSRMatrixMemoryLocation(parcsr)) {
72206977982Sstefanozampini     PetscBool isaij;
72306977982Sstefanozampini 
72406977982Sstefanozampini     PetscCall(PetscStrcmp(mtype, MATAIJ, &isaij));
72506977982Sstefanozampini     if (isaij) {
72606977982Sstefanozampini       PetscMPIInt size;
72706977982Sstefanozampini 
7289566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_size(comm, &size));
72906977982Sstefanozampini   #if defined(HYPRE_USING_HIP)
73006977982Sstefanozampini       mtype = size > 1 ? MATMPIAIJHIPSPARSE : MATSEQAIJHIPSPARSE;
73106977982Sstefanozampini   #elif defined(HYPRE_USING_CUDA)
73206977982Sstefanozampini       mtype = size > 1 ? MATMPIAIJCUSPARSE : MATSEQAIJCUSPARSE;
73306977982Sstefanozampini   #else
73406977982Sstefanozampini       mtype = size > 1 ? MATMPIAIJ : MATSEQAIJ;
73506977982Sstefanozampini   #endif
73663c07aadSStefano Zampini     }
73763c07aadSStefano Zampini   }
73806977982Sstefanozampini #endif
73906977982Sstefanozampini   dH = hypre_ParCSRMatrixDiag(parcsr);
74006977982Sstefanozampini   oH = hypre_ParCSRMatrixOffd(parcsr);
7419371c9d4SSatish Balay   if (reuse != MAT_REUSE_MATRIX) {
74206977982Sstefanozampini     PetscCount coo_n;
74306977982Sstefanozampini     PetscInt  *coo_i, *coo_j;
74463c07aadSStefano Zampini 
74506977982Sstefanozampini     PetscCall(MatCreate(comm, &M));
74606977982Sstefanozampini     PetscCall(MatSetType(M, mtype));
74706977982Sstefanozampini     PetscCall(MatSetSizes(M, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
74806977982Sstefanozampini     PetscCall(MatMPIAIJSetPreallocation(M, 0, NULL, 0, NULL));
74963c07aadSStefano Zampini 
75006977982Sstefanozampini     dA = M;
75106977982Sstefanozampini     PetscCall(PetscObjectBaseTypeCompare((PetscObject)M, MATMPIAIJ, &ismpiaij));
75206977982Sstefanozampini     if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(M, &dA, &oA, NULL));
753a16187a7SStefano Zampini 
75406977982Sstefanozampini     PetscCall(hypreCSRMatrixGetCOO_Private(dH, &coo_n, &coo_i, &coo_j));
75506977982Sstefanozampini     PetscCall(MatSetPreallocationCOO(dA, coo_n, coo_i, coo_j));
75606977982Sstefanozampini     PetscCall(PetscFree2(coo_i, coo_j));
75706977982Sstefanozampini     if (ismpiaij) {
75806977982Sstefanozampini       HYPRE_Int nc = hypre_CSRMatrixNumCols(oH);
759a16187a7SStefano Zampini 
76006977982Sstefanozampini       PetscCall(PetscLayoutDestroy(&oA->cmap));
76106977982Sstefanozampini       PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)oA), nc, nc, 1, &oA->cmap));
76206977982Sstefanozampini       PetscCall(hypreCSRMatrixGetCOO_Private(oH, &coo_n, &coo_i, &coo_j));
76306977982Sstefanozampini       PetscCall(MatSetPreallocationCOO(oA, coo_n, coo_i, coo_j));
76406977982Sstefanozampini       PetscCall(PetscFree2(coo_i, coo_j));
765a16187a7SStefano Zampini 
76606977982Sstefanozampini       /* garray */
767f4f49eeaSPierre Jolivet       Mat_MPIAIJ   *aij    = (Mat_MPIAIJ *)M->data;
76806977982Sstefanozampini       HYPRE_BigInt *harray = hypre_ParCSRMatrixColMapOffd(parcsr);
76906977982Sstefanozampini       PetscInt     *garray;
77006977982Sstefanozampini 
77106977982Sstefanozampini       PetscCall(PetscFree(aij->garray));
77206977982Sstefanozampini       PetscCall(PetscMalloc1(nc, &garray));
77306977982Sstefanozampini       for (HYPRE_Int i = 0; i < nc; i++) garray[i] = (PetscInt)harray[i];
77406977982Sstefanozampini       aij->garray = garray;
77506977982Sstefanozampini       PetscCall(MatSetUpMultiply_MPIAIJ(M));
776a16187a7SStefano Zampini     }
77706977982Sstefanozampini     if (reuse == MAT_INITIAL_MATRIX) *B = M;
77806977982Sstefanozampini   } else M = *B;
779225daaf8SStefano Zampini 
78006977982Sstefanozampini   dA = M;
78106977982Sstefanozampini   PetscCall(PetscObjectBaseTypeCompare((PetscObject)M, MATMPIAIJ, &ismpiaij));
78206977982Sstefanozampini   if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(M, &dA, &oA, NULL));
78306977982Sstefanozampini   PetscCall(MatSetValuesCOOFromCSRMatrix_Private(dA, dH));
78406977982Sstefanozampini   if (oA) PetscCall(MatSetValuesCOOFromCSRMatrix_Private(oA, oH));
78506977982Sstefanozampini   M->assembled = PETSC_TRUE;
78606977982Sstefanozampini   if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &M));
7873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
78863c07aadSStefano Zampini }
78963c07aadSStefano Zampini 
790d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJGetParCSR_Private(Mat A, hypre_ParCSRMatrix **hA)
791d71ae5a4SJacob Faibussowitsch {
792613e5ff0Sstefano_zampini   hypre_ParCSRMatrix *tA;
793c1a070e6SStefano Zampini   hypre_CSRMatrix    *hdiag, *hoffd;
794c1a070e6SStefano Zampini   Mat_SeqAIJ         *diag, *offd;
7952cf14000SStefano Zampini   PetscInt           *garray, i, noffd, dnnz, onnz, *row_starts, *col_starts;
796c1a070e6SStefano Zampini   MPI_Comm            comm = PetscObjectComm((PetscObject)A);
797613e5ff0Sstefano_zampini   PetscBool           ismpiaij, isseqaij;
7982cf14000SStefano Zampini   PetscBool           sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
7996ea7df73SStefano Zampini   HYPRE_Int          *hdi = NULL, *hdj = NULL, *hoi = NULL, *hoj = NULL;
8005c97c10fSStefano Zampini   PetscInt           *pdi = NULL, *pdj = NULL, *poi = NULL, *poj = NULL;
80106977982Sstefanozampini   PetscBool           iscuda, iship;
80206977982Sstefanozampini #if defined(PETSC_HAVE_DEVICE) && defined(PETSC_HAVE_HYPRE_DEVICE)
80306977982Sstefanozampini   PetscBool boundtocpu = A->boundtocpu;
80406977982Sstefanozampini #else
80506977982Sstefanozampini   PetscBool boundtocpu = PETSC_TRUE;
8066ea7df73SStefano Zampini #endif
807c1a070e6SStefano Zampini 
808c1a070e6SStefano Zampini   PetscFunctionBegin;
8099566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
8109566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isseqaij));
81108401ef6SPierre Jolivet   PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Unsupported type %s", ((PetscObject)A)->type_name);
812b655ebf8SZach Atkins   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, ""));
813b655ebf8SZach Atkins   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iship, MATSEQAIJHIPSPARSE, MATMPIAIJHIPSPARSE, ""));
814ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
815c1a070e6SStefano Zampini   if (ismpiaij) {
816f4f49eeaSPierre Jolivet     Mat_MPIAIJ *a = (Mat_MPIAIJ *)A->data;
817c1a070e6SStefano Zampini 
818c1a070e6SStefano Zampini     diag = (Mat_SeqAIJ *)a->A->data;
819c1a070e6SStefano Zampini     offd = (Mat_SeqAIJ *)a->B->data;
82006977982Sstefanozampini     if (!boundtocpu && (iscuda || iship)) {
82106977982Sstefanozampini #if defined(HYPRE_USING_CUDA) && defined(PETSC_HAVE_CUDA)
82206977982Sstefanozampini       if (iscuda) {
8236ea7df73SStefano Zampini         sameint = PETSC_TRUE;
8249566063dSJacob Faibussowitsch         PetscCall(MatSeqAIJCUSPARSEGetIJ(a->A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
8259566063dSJacob Faibussowitsch         PetscCall(MatSeqAIJCUSPARSEGetIJ(a->B, PETSC_FALSE, (const HYPRE_Int **)&hoi, (const HYPRE_Int **)&hoj));
82606977982Sstefanozampini       }
8276ea7df73SStefano Zampini #endif
82806977982Sstefanozampini #if defined(HYPRE_USING_HIP) && defined(PETSC_HAVE_HIP)
82906977982Sstefanozampini       if (iship) {
83006977982Sstefanozampini         sameint = PETSC_TRUE;
83106977982Sstefanozampini         PetscCall(MatSeqAIJHIPSPARSEGetIJ(a->A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
83206977982Sstefanozampini         PetscCall(MatSeqAIJHIPSPARSEGetIJ(a->B, PETSC_FALSE, (const HYPRE_Int **)&hoi, (const HYPRE_Int **)&hoj));
83306977982Sstefanozampini       }
83406977982Sstefanozampini #endif
83506977982Sstefanozampini     } else {
83606977982Sstefanozampini       boundtocpu = PETSC_TRUE;
8376ea7df73SStefano Zampini       pdi        = diag->i;
8386ea7df73SStefano Zampini       pdj        = diag->j;
8396ea7df73SStefano Zampini       poi        = offd->i;
8406ea7df73SStefano Zampini       poj        = offd->j;
8416ea7df73SStefano Zampini       if (sameint) {
8426ea7df73SStefano Zampini         hdi = (HYPRE_Int *)pdi;
8436ea7df73SStefano Zampini         hdj = (HYPRE_Int *)pdj;
8446ea7df73SStefano Zampini         hoi = (HYPRE_Int *)poi;
8456ea7df73SStefano Zampini         hoj = (HYPRE_Int *)poj;
8466ea7df73SStefano Zampini       }
8476ea7df73SStefano Zampini     }
848c1a070e6SStefano Zampini     garray = a->garray;
849c1a070e6SStefano Zampini     noffd  = a->B->cmap->N;
850c1a070e6SStefano Zampini     dnnz   = diag->nz;
851c1a070e6SStefano Zampini     onnz   = offd->nz;
852c1a070e6SStefano Zampini   } else {
853c1a070e6SStefano Zampini     diag = (Mat_SeqAIJ *)A->data;
854c1a070e6SStefano Zampini     offd = NULL;
85506977982Sstefanozampini     if (!boundtocpu && (iscuda || iship)) {
85606977982Sstefanozampini #if defined(HYPRE_USING_CUDA) && defined(PETSC_HAVE_CUDA)
85706977982Sstefanozampini       if (iscuda) {
8586ea7df73SStefano Zampini         sameint = PETSC_TRUE;
8599566063dSJacob Faibussowitsch         PetscCall(MatSeqAIJCUSPARSEGetIJ(A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
86006977982Sstefanozampini       }
8616ea7df73SStefano Zampini #endif
86206977982Sstefanozampini #if defined(HYPRE_USING_HIP) && defined(PETSC_HAVE_HIP)
86306977982Sstefanozampini       if (iship) {
86406977982Sstefanozampini         sameint = PETSC_TRUE;
86506977982Sstefanozampini         PetscCall(MatSeqAIJHIPSPARSEGetIJ(A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
86606977982Sstefanozampini       }
86706977982Sstefanozampini #endif
86806977982Sstefanozampini     } else {
86906977982Sstefanozampini       boundtocpu = PETSC_TRUE;
8706ea7df73SStefano Zampini       pdi        = diag->i;
8716ea7df73SStefano Zampini       pdj        = diag->j;
8726ea7df73SStefano Zampini       if (sameint) {
8736ea7df73SStefano Zampini         hdi = (HYPRE_Int *)pdi;
8746ea7df73SStefano Zampini         hdj = (HYPRE_Int *)pdj;
8756ea7df73SStefano Zampini       }
8766ea7df73SStefano Zampini     }
877c1a070e6SStefano Zampini     garray = NULL;
878c1a070e6SStefano Zampini     noffd  = 0;
879c1a070e6SStefano Zampini     dnnz   = diag->nz;
880c1a070e6SStefano Zampini     onnz   = 0;
881c1a070e6SStefano Zampini   }
882225daaf8SStefano Zampini 
883c1a070e6SStefano Zampini   /* create a temporary ParCSR */
884c1a070e6SStefano Zampini   if (HYPRE_AssumedPartitionCheck()) {
885c1a070e6SStefano Zampini     PetscMPIInt myid;
886c1a070e6SStefano Zampini 
8879566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &myid));
888c1a070e6SStefano Zampini     row_starts = A->rmap->range + myid;
889c1a070e6SStefano Zampini     col_starts = A->cmap->range + myid;
890c1a070e6SStefano Zampini   } else {
891c1a070e6SStefano Zampini     row_starts = A->rmap->range;
892c1a070e6SStefano Zampini     col_starts = A->cmap->range;
893c1a070e6SStefano Zampini   }
8942cf14000SStefano Zampini   tA = hypre_ParCSRMatrixCreate(comm, A->rmap->N, A->cmap->N, (HYPRE_BigInt *)row_starts, (HYPRE_BigInt *)col_starts, noffd, dnnz, onnz);
895a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
896c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetRowStartsOwner(tA, 0);
897c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetColStartsOwner(tA, 0);
898a1d2239cSSatish Balay #endif
899c1a070e6SStefano Zampini 
900225daaf8SStefano Zampini   /* set diagonal part */
901c1a070e6SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(tA);
9026ea7df73SStefano Zampini   if (!sameint) { /* malloc CSR pointers */
9039566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(A->rmap->n + 1, &hdi, dnnz, &hdj));
904f4f49eeaSPierre Jolivet     for (i = 0; i < A->rmap->n + 1; i++) hdi[i] = (HYPRE_Int)pdi[i];
905f4f49eeaSPierre Jolivet     for (i = 0; i < dnnz; i++) hdj[i] = (HYPRE_Int)pdj[i];
9062cf14000SStefano Zampini   }
9076ea7df73SStefano Zampini   hypre_CSRMatrixI(hdiag)           = hdi;
9086ea7df73SStefano Zampini   hypre_CSRMatrixJ(hdiag)           = hdj;
90939accc25SStefano Zampini   hypre_CSRMatrixData(hdiag)        = (HYPRE_Complex *)diag->a;
910c1a070e6SStefano Zampini   hypre_CSRMatrixNumNonzeros(hdiag) = diag->nz;
911c1a070e6SStefano Zampini   hypre_CSRMatrixSetRownnz(hdiag);
912c1a070e6SStefano Zampini   hypre_CSRMatrixSetDataOwner(hdiag, 0);
913c1a070e6SStefano Zampini 
9144cf0e950SBarry Smith   /* set off-diagonal part */
915c1a070e6SStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(tA);
916c1a070e6SStefano Zampini   if (offd) {
9176ea7df73SStefano Zampini     if (!sameint) { /* malloc CSR pointers */
9189566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(A->rmap->n + 1, &hoi, onnz, &hoj));
919f4f49eeaSPierre Jolivet       for (i = 0; i < A->rmap->n + 1; i++) hoi[i] = (HYPRE_Int)poi[i];
920f4f49eeaSPierre Jolivet       for (i = 0; i < onnz; i++) hoj[i] = (HYPRE_Int)poj[i];
9212cf14000SStefano Zampini     }
9226ea7df73SStefano Zampini     hypre_CSRMatrixI(hoffd)           = hoi;
9236ea7df73SStefano Zampini     hypre_CSRMatrixJ(hoffd)           = hoj;
92439accc25SStefano Zampini     hypre_CSRMatrixData(hoffd)        = (HYPRE_Complex *)offd->a;
925c1a070e6SStefano Zampini     hypre_CSRMatrixNumNonzeros(hoffd) = offd->nz;
926c1a070e6SStefano Zampini     hypre_CSRMatrixSetRownnz(hoffd);
927c1a070e6SStefano Zampini     hypre_CSRMatrixSetDataOwner(hoffd, 0);
9286ea7df73SStefano Zampini   }
9296ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
93006977982Sstefanozampini   PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, !boundtocpu ? HYPRE_MEMORY_DEVICE : HYPRE_MEMORY_HOST);
9316ea7df73SStefano Zampini #else
9326ea7df73SStefano Zampini   #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0)
933792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixInitialize, tA);
9346ea7df73SStefano Zampini   #else
935792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, HYPRE_MEMORY_HOST);
9366ea7df73SStefano Zampini   #endif
9376ea7df73SStefano Zampini #endif
9386ea7df73SStefano Zampini   hypre_TFree(hypre_ParCSRMatrixColMapOffd(tA), HYPRE_MEMORY_HOST);
939c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetNumNonzeros(tA);
9402cf14000SStefano Zampini   hypre_ParCSRMatrixColMapOffd(tA) = (HYPRE_BigInt *)garray;
941792fecdfSBarry Smith   if (!hypre_ParCSRMatrixCommPkg(tA)) PetscCallExternal(hypre_MatvecCommPkgCreate, tA);
942613e5ff0Sstefano_zampini   *hA = tA;
9433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
944613e5ff0Sstefano_zampini }
945c1a070e6SStefano Zampini 
946d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJRestoreParCSR_Private(Mat A, hypre_ParCSRMatrix **hA)
947d71ae5a4SJacob Faibussowitsch {
948613e5ff0Sstefano_zampini   hypre_CSRMatrix *hdiag, *hoffd;
9496ea7df73SStefano Zampini   PetscBool        ismpiaij, sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
950b655ebf8SZach Atkins   PetscBool        iscuda, iship;
951c1a070e6SStefano Zampini 
952613e5ff0Sstefano_zampini   PetscFunctionBegin;
9539566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
9549566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, ""));
955b655ebf8SZach Atkins   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iship, MATSEQAIJHIPSPARSE, MATMPIAIJHIPSPARSE, ""));
956b655ebf8SZach Atkins #if defined(HYPRE_USING_CUDA) && defined(PETSC_HAVE_CUDA)
9576ea7df73SStefano Zampini   if (iscuda) sameint = PETSC_TRUE;
958b655ebf8SZach Atkins #elif defined(HYPRE_USING_HIP) && defined(PETSC_HAVE_HIP)
959b655ebf8SZach Atkins   if (iship) sameint = PETSC_TRUE;
9606ea7df73SStefano Zampini #endif
961613e5ff0Sstefano_zampini   hdiag = hypre_ParCSRMatrixDiag(*hA);
962613e5ff0Sstefano_zampini   hoffd = hypre_ParCSRMatrixOffd(*hA);
9636ea7df73SStefano Zampini   /* free temporary memory allocated by PETSc
9646ea7df73SStefano Zampini      set pointers to NULL before destroying tA */
9652cf14000SStefano Zampini   if (!sameint) {
9662cf14000SStefano Zampini     HYPRE_Int *hi, *hj;
9672cf14000SStefano Zampini 
9682cf14000SStefano Zampini     hi = hypre_CSRMatrixI(hdiag);
9692cf14000SStefano Zampini     hj = hypre_CSRMatrixJ(hdiag);
9709566063dSJacob Faibussowitsch     PetscCall(PetscFree2(hi, hj));
9716ea7df73SStefano Zampini     if (ismpiaij) {
9722cf14000SStefano Zampini       hi = hypre_CSRMatrixI(hoffd);
9732cf14000SStefano Zampini       hj = hypre_CSRMatrixJ(hoffd);
9749566063dSJacob Faibussowitsch       PetscCall(PetscFree2(hi, hj));
9752cf14000SStefano Zampini     }
9762cf14000SStefano Zampini   }
977c1a070e6SStefano Zampini   hypre_CSRMatrixI(hdiag)    = NULL;
978c1a070e6SStefano Zampini   hypre_CSRMatrixJ(hdiag)    = NULL;
979c1a070e6SStefano Zampini   hypre_CSRMatrixData(hdiag) = NULL;
9806ea7df73SStefano Zampini   if (ismpiaij) {
981c1a070e6SStefano Zampini     hypre_CSRMatrixI(hoffd)    = NULL;
982c1a070e6SStefano Zampini     hypre_CSRMatrixJ(hoffd)    = NULL;
983c1a070e6SStefano Zampini     hypre_CSRMatrixData(hoffd) = NULL;
9846ea7df73SStefano Zampini   }
985613e5ff0Sstefano_zampini   hypre_ParCSRMatrixColMapOffd(*hA) = NULL;
986613e5ff0Sstefano_zampini   hypre_ParCSRMatrixDestroy(*hA);
987613e5ff0Sstefano_zampini   *hA = NULL;
9883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
989613e5ff0Sstefano_zampini }
990613e5ff0Sstefano_zampini 
991613e5ff0Sstefano_zampini /* calls RAP from BoomerAMG:
9923dad0653Sstefano_zampini    the resulting ParCSR will not own the column and row starts
9936ea7df73SStefano Zampini    It looks like we don't need to have the diagonal entries ordered first */
994d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_RAP(hypre_ParCSRMatrix *hR, hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hP, hypre_ParCSRMatrix **hRAP)
995d71ae5a4SJacob Faibussowitsch {
996a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
997613e5ff0Sstefano_zampini   HYPRE_Int P_owns_col_starts, R_owns_row_starts;
998a1d2239cSSatish Balay #endif
999613e5ff0Sstefano_zampini 
1000613e5ff0Sstefano_zampini   PetscFunctionBegin;
1001a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
1002613e5ff0Sstefano_zampini   P_owns_col_starts = hypre_ParCSRMatrixOwnsColStarts(hP);
1003613e5ff0Sstefano_zampini   R_owns_row_starts = hypre_ParCSRMatrixOwnsRowStarts(hR);
1004a1d2239cSSatish Balay #endif
10056ea7df73SStefano Zampini   /* can be replaced by version test later */
10066ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
1007792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParCSRMatrixRAP");
10086ea7df73SStefano Zampini   *hRAP = hypre_ParCSRMatrixRAP(hR, hA, hP);
10096ea7df73SStefano Zampini   PetscStackPop;
10106ea7df73SStefano Zampini #else
1011792fecdfSBarry Smith   PetscCallExternal(hypre_BoomerAMGBuildCoarseOperator, hR, hA, hP, hRAP);
1012792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixSetNumNonzeros, *hRAP);
10136ea7df73SStefano Zampini #endif
1014613e5ff0Sstefano_zampini   /* hypre_BoomerAMGBuildCoarseOperator steals the col_starts from P and the row_starts from R */
1015a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
1016613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetRowStartsOwner(*hRAP, 0);
1017613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetColStartsOwner(*hRAP, 0);
1018613e5ff0Sstefano_zampini   if (P_owns_col_starts) hypre_ParCSRMatrixSetColStartsOwner(hP, 1);
1019613e5ff0Sstefano_zampini   if (R_owns_row_starts) hypre_ParCSRMatrixSetRowStartsOwner(hR, 1);
1020a1d2239cSSatish Balay #endif
10213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1022613e5ff0Sstefano_zampini }
1023613e5ff0Sstefano_zampini 
1024d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat P, Mat C)
1025d71ae5a4SJacob Faibussowitsch {
10266f231fbdSstefano_zampini   Mat                 B;
10276abb4441SStefano Zampini   hypre_ParCSRMatrix *hA, *hP, *hPtAP = NULL;
10284222ddf1SHong Zhang   Mat_Product        *product = C->product;
1029613e5ff0Sstefano_zampini 
1030613e5ff0Sstefano_zampini   PetscFunctionBegin;
10319566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
10329566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(P, &hP));
10339566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(hP, hA, hP, &hPtAP));
10349566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hPtAP, MATAIJ, PETSC_OWN_POINTER, &B));
10354222ddf1SHong Zhang 
10369566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
10374222ddf1SHong Zhang   C->product = product;
10384222ddf1SHong Zhang 
10399566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
10409566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(P, &hP));
10413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10426f231fbdSstefano_zampini }
10436f231fbdSstefano_zampini 
1044d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatPtAPSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat P, PetscReal fill, Mat C)
1045d71ae5a4SJacob Faibussowitsch {
10466f231fbdSstefano_zampini   PetscFunctionBegin;
10479566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATAIJ));
10484222ddf1SHong Zhang   C->ops->ptapnumeric    = MatPtAPNumeric_AIJ_AIJ_wHYPRE;
10494222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
10503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1051613e5ff0Sstefano_zampini }
1052613e5ff0Sstefano_zampini 
1053d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_HYPRE(Mat A, Mat P, Mat C)
1054d71ae5a4SJacob Faibussowitsch {
10554cc28894Sstefano_zampini   Mat                 B;
10564cc28894Sstefano_zampini   Mat_HYPRE          *hP;
10576abb4441SStefano Zampini   hypre_ParCSRMatrix *hA = NULL, *Pparcsr, *ptapparcsr = NULL;
1058613e5ff0Sstefano_zampini   HYPRE_Int           type;
1059613e5ff0Sstefano_zampini   MPI_Comm            comm = PetscObjectComm((PetscObject)A);
10604cc28894Sstefano_zampini   PetscBool           ishypre;
1061613e5ff0Sstefano_zampini 
1062613e5ff0Sstefano_zampini   PetscFunctionBegin;
10639566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre));
106428b400f6SJacob Faibussowitsch   PetscCheck(ishypre, comm, PETSC_ERR_USER, "P should be of type %s", MATHYPRE);
10654cc28894Sstefano_zampini   hP = (Mat_HYPRE *)P->data;
1066792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type);
106708401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1068792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr);
1069613e5ff0Sstefano_zampini 
10709566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
10719566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, hA, Pparcsr, &ptapparcsr));
10729566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
1073225daaf8SStefano Zampini 
10744cc28894Sstefano_zampini   /* create temporary matrix and merge to C */
10759566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ptapparcsr, ((PetscObject)C)->type_name, PETSC_OWN_POINTER, &B));
10769566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
10773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10784cc28894Sstefano_zampini }
10794cc28894Sstefano_zampini 
1080d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_HYPRE_HYPRE(Mat A, Mat P, Mat C)
1081d71ae5a4SJacob Faibussowitsch {
10824cc28894Sstefano_zampini   Mat                 B;
10836abb4441SStefano Zampini   hypre_ParCSRMatrix *Aparcsr, *Pparcsr, *ptapparcsr = NULL;
10844cc28894Sstefano_zampini   Mat_HYPRE          *hA, *hP;
10854cc28894Sstefano_zampini   PetscBool           ishypre;
10864cc28894Sstefano_zampini   HYPRE_Int           type;
10874cc28894Sstefano_zampini 
10884cc28894Sstefano_zampini   PetscFunctionBegin;
10899566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre));
109028b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)P), PETSC_ERR_USER, "P should be of type %s", MATHYPRE);
10919566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
109228b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE);
10934cc28894Sstefano_zampini   hA = (Mat_HYPRE *)A->data;
10944cc28894Sstefano_zampini   hP = (Mat_HYPRE *)P->data;
1095792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
109608401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1097792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type);
109808401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)P), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1099792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr);
1100792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr);
11019566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, Aparcsr, Pparcsr, &ptapparcsr));
11029566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ptapparcsr, MATHYPRE, PETSC_OWN_POINTER, &B));
11039566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
11043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11054cc28894Sstefano_zampini }
11064cc28894Sstefano_zampini 
1107d501dc42Sstefano_zampini /* calls hypre_ParMatmul
1108d501dc42Sstefano_zampini    hypre_ParMatMul uses hypre_ParMatrixCreate with the communicator of hA
11093dad0653Sstefano_zampini    hypre_ParMatrixCreate does not duplicate the communicator
11106ea7df73SStefano Zampini    It looks like we don't need to have the diagonal entries ordered first */
1111d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_MatMatMult(hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hB, hypre_ParCSRMatrix **hAB)
1112d71ae5a4SJacob Faibussowitsch {
1113d501dc42Sstefano_zampini   PetscFunctionBegin;
11146ea7df73SStefano Zampini   /* can be replaced by version test later */
11156ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
1116792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParCSRMatMat");
11176ea7df73SStefano Zampini   *hAB = hypre_ParCSRMatMat(hA, hB);
11186ea7df73SStefano Zampini #else
1119792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParMatmul");
1120d501dc42Sstefano_zampini   *hAB = hypre_ParMatmul(hA, hB);
11216ea7df73SStefano Zampini #endif
1122d501dc42Sstefano_zampini   PetscStackPop;
11233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1124d501dc42Sstefano_zampini }
1125d501dc42Sstefano_zampini 
1126d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C)
1127d71ae5a4SJacob Faibussowitsch {
11285e5acdf2Sstefano_zampini   Mat                 D;
1129d501dc42Sstefano_zampini   hypre_ParCSRMatrix *hA, *hB, *hAB = NULL;
11304222ddf1SHong Zhang   Mat_Product        *product = C->product;
11315e5acdf2Sstefano_zampini 
11325e5acdf2Sstefano_zampini   PetscFunctionBegin;
11339566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
11349566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(B, &hB));
11359566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_MatMatMult(hA, hB, &hAB));
11369566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hAB, MATAIJ, PETSC_OWN_POINTER, &D));
11374222ddf1SHong Zhang 
11389566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &D));
11394222ddf1SHong Zhang   C->product = product;
11404222ddf1SHong Zhang 
11419566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
11429566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(B, &hB));
11433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11445e5acdf2Sstefano_zampini }
11455e5acdf2Sstefano_zampini 
1146d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatMatMultSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat B, PetscReal fill, Mat C)
1147d71ae5a4SJacob Faibussowitsch {
11485e5acdf2Sstefano_zampini   PetscFunctionBegin;
11499566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATAIJ));
11504222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_AIJ_AIJ_wHYPRE;
11514222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
11523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11535e5acdf2Sstefano_zampini }
11545e5acdf2Sstefano_zampini 
1155d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_HYPRE_HYPRE(Mat A, Mat B, Mat C)
1156d71ae5a4SJacob Faibussowitsch {
1157d501dc42Sstefano_zampini   Mat                 D;
1158d501dc42Sstefano_zampini   hypre_ParCSRMatrix *Aparcsr, *Bparcsr, *ABparcsr = NULL;
1159d501dc42Sstefano_zampini   Mat_HYPRE          *hA, *hB;
1160d501dc42Sstefano_zampini   PetscBool           ishypre;
1161d501dc42Sstefano_zampini   HYPRE_Int           type;
11624222ddf1SHong Zhang   Mat_Product        *product;
1163d501dc42Sstefano_zampini 
1164d501dc42Sstefano_zampini   PetscFunctionBegin;
11659566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)B, MATHYPRE, &ishypre));
116628b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)B), PETSC_ERR_USER, "B should be of type %s", MATHYPRE);
11679566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
116828b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE);
1169d501dc42Sstefano_zampini   hA = (Mat_HYPRE *)A->data;
1170d501dc42Sstefano_zampini   hB = (Mat_HYPRE *)B->data;
1171792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
117208401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1173792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hB->ij, &type);
117408401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1175792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr);
1176792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hB->ij, (void **)&Bparcsr);
11779566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_MatMatMult(Aparcsr, Bparcsr, &ABparcsr));
11789566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ABparcsr, MATHYPRE, PETSC_OWN_POINTER, &D));
11794222ddf1SHong Zhang 
1180d501dc42Sstefano_zampini   /* need to use HeaderReplace because HeaderMerge messes up with the communicator */
11814222ddf1SHong Zhang   product    = C->product; /* save it from MatHeaderReplace() */
11824222ddf1SHong Zhang   C->product = NULL;
11839566063dSJacob Faibussowitsch   PetscCall(MatHeaderReplace(C, &D));
11844222ddf1SHong Zhang   C->product             = product;
1185d501dc42Sstefano_zampini   C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE;
11864222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
11873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1188d501dc42Sstefano_zampini }
1189d501dc42Sstefano_zampini 
1190d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultNumeric_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, Mat D)
1191d71ae5a4SJacob Faibussowitsch {
119220e1dc0dSstefano_zampini   Mat                 E;
11936abb4441SStefano Zampini   hypre_ParCSRMatrix *hA, *hB, *hC, *hABC = NULL;
119420e1dc0dSstefano_zampini 
119520e1dc0dSstefano_zampini   PetscFunctionBegin;
11969566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
11979566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(B, &hB));
11989566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(C, &hC));
11999566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(hA, hB, hC, &hABC));
12009566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hABC, MATAIJ, PETSC_OWN_POINTER, &E));
12019566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(D, &E));
12029566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
12039566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(B, &hB));
12049566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(C, &hC));
12053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
120620e1dc0dSstefano_zampini }
120720e1dc0dSstefano_zampini 
1208d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultSymbolic_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, PetscReal fill, Mat D)
1209d71ae5a4SJacob Faibussowitsch {
121020e1dc0dSstefano_zampini   PetscFunctionBegin;
12119566063dSJacob Faibussowitsch   PetscCall(MatSetType(D, MATAIJ));
12123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
121320e1dc0dSstefano_zampini }
121420e1dc0dSstefano_zampini 
1215d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_AB_HYPRE(Mat C)
1216d71ae5a4SJacob Faibussowitsch {
12174222ddf1SHong Zhang   PetscFunctionBegin;
12184222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
12193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12204222ddf1SHong Zhang }
12214222ddf1SHong Zhang 
1222d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_AB(Mat C)
1223d71ae5a4SJacob Faibussowitsch {
12244222ddf1SHong Zhang   Mat_Product *product = C->product;
12254222ddf1SHong Zhang   PetscBool    Ahypre;
12264222ddf1SHong Zhang 
12274222ddf1SHong Zhang   PetscFunctionBegin;
12289566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)product->A, MATHYPRE, &Ahypre));
12294222ddf1SHong Zhang   if (Ahypre) { /* A is a Hypre matrix */
12309566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
12314222ddf1SHong Zhang     C->ops->productsymbolic = MatProductSymbolic_AB_HYPRE;
12324222ddf1SHong Zhang     C->ops->matmultnumeric  = MatMatMultNumeric_HYPRE_HYPRE;
12333ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
12346718818eSStefano Zampini   }
12353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12364222ddf1SHong Zhang }
12374222ddf1SHong Zhang 
1238d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_PtAP_HYPRE(Mat C)
1239d71ae5a4SJacob Faibussowitsch {
12404222ddf1SHong Zhang   PetscFunctionBegin;
12414222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
12423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12434222ddf1SHong Zhang }
12444222ddf1SHong Zhang 
1245d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_PtAP(Mat C)
1246d71ae5a4SJacob Faibussowitsch {
12474222ddf1SHong Zhang   Mat_Product *product = C->product;
12484222ddf1SHong Zhang   PetscBool    flg;
12494222ddf1SHong Zhang   PetscInt     type        = 0;
12504222ddf1SHong Zhang   const char  *outTypes[4] = {"aij", "seqaij", "mpiaij", "hypre"};
12514222ddf1SHong Zhang   PetscInt     ntype       = 4;
12524222ddf1SHong Zhang   Mat          A           = product->A;
12534222ddf1SHong Zhang   PetscBool    Ahypre;
12544222ddf1SHong Zhang 
12554222ddf1SHong Zhang   PetscFunctionBegin;
12569566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &Ahypre));
12574222ddf1SHong Zhang   if (Ahypre) { /* A is a Hypre matrix */
12589566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
12594222ddf1SHong Zhang     C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE;
12604222ddf1SHong Zhang     C->ops->ptapnumeric     = MatPtAPNumeric_HYPRE_HYPRE;
12613ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
12624222ddf1SHong Zhang   }
12634222ddf1SHong Zhang 
12644222ddf1SHong Zhang   /* A is AIJ, P is Hypre, C = PtAP can be either AIJ or Hypre format */
12654222ddf1SHong Zhang   /* Get runtime option */
12664222ddf1SHong Zhang   if (product->api_user) {
1267d0609cedSBarry Smith     PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatPtAP_HYPRE", "Mat");
12689566063dSJacob Faibussowitsch     PetscCall(PetscOptionsEList("-matptap_hypre_outtype", "MatPtAP outtype", "MatPtAP outtype", outTypes, ntype, outTypes[type], &type, &flg));
1269d0609cedSBarry Smith     PetscOptionsEnd();
12704222ddf1SHong Zhang   } else {
1271d0609cedSBarry Smith     PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatProduct_PtAP_HYPRE", "Mat");
12729566063dSJacob Faibussowitsch     PetscCall(PetscOptionsEList("-mat_product_algorithm_hypre_outtype", "MatProduct_PtAP outtype", "MatProduct_PtAP", outTypes, ntype, outTypes[type], &type, &flg));
1273d0609cedSBarry Smith     PetscOptionsEnd();
12744222ddf1SHong Zhang   }
12754222ddf1SHong Zhang 
12764222ddf1SHong Zhang   if (type == 0 || type == 1 || type == 2) {
12779566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATAIJ));
12784222ddf1SHong Zhang   } else if (type == 3) {
12799566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
12804222ddf1SHong Zhang   } else SETERRQ(PetscObjectComm((PetscObject)C), PETSC_ERR_SUP, "MatPtAP outtype is not supported");
12814222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE;
12824222ddf1SHong Zhang   C->ops->ptapnumeric     = MatPtAPNumeric_AIJ_HYPRE;
12833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12844222ddf1SHong Zhang }
12854222ddf1SHong Zhang 
1286d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE(Mat C)
1287d71ae5a4SJacob Faibussowitsch {
12884222ddf1SHong Zhang   Mat_Product *product = C->product;
12894222ddf1SHong Zhang 
12904222ddf1SHong Zhang   PetscFunctionBegin;
12914222ddf1SHong Zhang   switch (product->type) {
1292d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AB:
1293d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_HYPRE_AB(C));
1294d71ae5a4SJacob Faibussowitsch     break;
1295d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_PtAP:
1296d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_HYPRE_PtAP(C));
1297d71ae5a4SJacob Faibussowitsch     break;
1298d71ae5a4SJacob Faibussowitsch   default:
1299d71ae5a4SJacob Faibussowitsch     break;
13004222ddf1SHong Zhang   }
13013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13024222ddf1SHong Zhang }
13034222ddf1SHong Zhang 
1304d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTranspose_HYPRE(Mat A, Vec x, Vec y)
1305d71ae5a4SJacob Faibussowitsch {
130663c07aadSStefano Zampini   PetscFunctionBegin;
13079566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_TRUE));
13083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
130963c07aadSStefano Zampini }
131063c07aadSStefano Zampini 
1311d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_HYPRE(Mat A, Vec x, Vec y)
1312d71ae5a4SJacob Faibussowitsch {
131363c07aadSStefano Zampini   PetscFunctionBegin;
13149566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_FALSE));
13153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
131663c07aadSStefano Zampini }
131763c07aadSStefano Zampini 
1318d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultAdd_HYPRE(Mat A, Vec x, Vec y, Vec z)
1319d71ae5a4SJacob Faibussowitsch {
1320414bd5c3SStefano Zampini   PetscFunctionBegin;
132148a46eb9SPierre Jolivet   if (y != z) PetscCall(VecCopy(y, z));
13229566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_FALSE));
13233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1324414bd5c3SStefano Zampini }
1325414bd5c3SStefano Zampini 
1326d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTransposeAdd_HYPRE(Mat A, Vec x, Vec y, Vec z)
1327d71ae5a4SJacob Faibussowitsch {
1328414bd5c3SStefano Zampini   PetscFunctionBegin;
132948a46eb9SPierre Jolivet   if (y != z) PetscCall(VecCopy(y, z));
13309566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_TRUE));
13313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1332414bd5c3SStefano Zampini }
1333414bd5c3SStefano Zampini 
1334414bd5c3SStefano Zampini /* y = a * A * x + b * y or y = a * A^t * x + b * y depending on trans */
1335d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_MultKernel_Private(Mat A, HYPRE_Complex a, Vec x, HYPRE_Complex b, Vec y, PetscBool trans)
1336d71ae5a4SJacob Faibussowitsch {
133763c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE *)A->data;
133863c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
133963c07aadSStefano Zampini   hypre_ParVector    *hx, *hy;
134063c07aadSStefano Zampini 
134163c07aadSStefano Zampini   PetscFunctionBegin;
134263c07aadSStefano Zampini   if (trans) {
13439566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorPushVecRead(hA->b, x));
13449566063dSJacob Faibussowitsch     if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->x, y));
13459566063dSJacob Faibussowitsch     else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->x, y));
1346792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hx);
1347792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hy);
134863c07aadSStefano Zampini   } else {
13499566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorPushVecRead(hA->x, x));
13509566063dSJacob Faibussowitsch     if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->b, y));
13519566063dSJacob Faibussowitsch     else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->b, y));
1352792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hx);
1353792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hy);
135463c07aadSStefano Zampini   }
1355792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
13566ea7df73SStefano Zampini   if (trans) {
1357792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMatvecT, a, parcsr, hx, b, hy);
13586ea7df73SStefano Zampini   } else {
1359792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMatvec, a, parcsr, hx, b, hy);
13606ea7df73SStefano Zampini   }
13619566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hA->x));
13629566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hA->b));
13633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
136463c07aadSStefano Zampini }
136563c07aadSStefano Zampini 
1366d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_HYPRE(Mat A)
1367d71ae5a4SJacob Faibussowitsch {
136863c07aadSStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
136963c07aadSStefano Zampini 
137063c07aadSStefano Zampini   PetscFunctionBegin;
13719566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&hA->x));
13729566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&hA->b));
137306977982Sstefanozampini   PetscCall(MatHYPRE_DestroyCOOMat(A)); /* must be called before destroying the individual CSR */
1374978814f1SStefano Zampini   if (hA->ij) {
1375978814f1SStefano Zampini     if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL;
1376792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixDestroy, hA->ij);
1377978814f1SStefano Zampini   }
13789566063dSJacob Faibussowitsch   if (hA->comm) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)A), &hA->comm));
1379c69f721fSFande Kong 
13809566063dSJacob Faibussowitsch   PetscCall(MatStashDestroy_Private(&A->stash));
13819566063dSJacob Faibussowitsch   PetscCall(PetscFree(hA->array));
1382a32e9c99SJunchao Zhang   if (hA->rows_d) PetscStackCallExternalVoid("hypre_Free", hypre_Free(hA->rows_d, HYPRE_MEMORY_DEVICE));
1383c69f721fSFande Kong 
13849566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_aij_C", NULL));
13859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_is_C", NULL));
13869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_hypre_C", NULL));
13879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaij_hypre_C", NULL));
138806977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijhipsparse_hypre_C", NULL));
138906977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaijhipsparse_hypre_C", NULL));
139006977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijcusparse_hypre_C", NULL));
139106977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaijcusparse_hypre_C", NULL));
13929566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPRESetPreallocation_C", NULL));
13939566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPREGetParCSR_C", NULL));
13945fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL));
13955fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL));
13969566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->data));
13973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
139863c07aadSStefano Zampini }
139963c07aadSStefano Zampini 
1400d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetUp_HYPRE(Mat A)
1401d71ae5a4SJacob Faibussowitsch {
14024ec6421dSstefano_zampini   PetscFunctionBegin;
140306977982Sstefanozampini   if (!A->preallocated) PetscCall(MatHYPRESetPreallocation(A, PETSC_DEFAULT, NULL, PETSC_DEFAULT, NULL));
14043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14054ec6421dSstefano_zampini }
14064ec6421dSstefano_zampini 
14076ea7df73SStefano Zampini //TODO FIX hypre_CSRMatrixMatvecOutOfPlace
14086ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
1409d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatBindToCPU_HYPRE(Mat A, PetscBool bind)
1410d71ae5a4SJacob Faibussowitsch {
14116ea7df73SStefano Zampini   Mat_HYPRE           *hA   = (Mat_HYPRE *)A->data;
14126ea7df73SStefano Zampini   HYPRE_MemoryLocation hmem = bind ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE;
14136ea7df73SStefano Zampini 
14146ea7df73SStefano Zampini   PetscFunctionBegin;
14156ea7df73SStefano Zampini   A->boundtocpu = bind;
14165fbaff96SJunchao Zhang   if (hA->ij && hypre_IJMatrixAssembleFlag(hA->ij) && hmem != hypre_IJMatrixMemoryLocation(hA->ij)) {
14176ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
1418792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
1419792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMigrate, parcsr, hmem);
14206ea7df73SStefano Zampini   }
14219566063dSJacob Faibussowitsch   if (hA->x) PetscCall(VecHYPRE_IJBindToCPU(hA->x, bind));
14229566063dSJacob Faibussowitsch   if (hA->b) PetscCall(VecHYPRE_IJBindToCPU(hA->b, bind));
14233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14246ea7df73SStefano Zampini }
14256ea7df73SStefano Zampini #endif
14266ea7df73SStefano Zampini 
1427d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_HYPRE(Mat A, MatAssemblyType mode)
1428d71ae5a4SJacob Faibussowitsch {
142963c07aadSStefano Zampini   Mat_HYPRE   *hA = (Mat_HYPRE *)A->data;
1430c69f721fSFande Kong   PetscMPIInt  n;
1431c69f721fSFande Kong   PetscInt     i, j, rstart, ncols, flg;
1432c69f721fSFande Kong   PetscInt    *row, *col;
1433c69f721fSFande Kong   PetscScalar *val;
143463c07aadSStefano Zampini 
143563c07aadSStefano Zampini   PetscFunctionBegin;
143608401ef6SPierre Jolivet   PetscCheck(mode != MAT_FLUSH_ASSEMBLY, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_FLUSH_ASSEMBLY currently not supported with MATHYPRE");
1437c69f721fSFande Kong 
1438c69f721fSFande Kong   if (!A->nooffprocentries) {
1439c69f721fSFande Kong     while (1) {
14409566063dSJacob Faibussowitsch       PetscCall(MatStashScatterGetMesg_Private(&A->stash, &n, &row, &col, &val, &flg));
1441c69f721fSFande Kong       if (!flg) break;
1442c69f721fSFande Kong 
1443c69f721fSFande Kong       for (i = 0; i < n;) {
1444c69f721fSFande Kong         /* Now identify the consecutive vals belonging to the same row */
1445c69f721fSFande Kong         for (j = i, rstart = row[j]; j < n; j++) {
1446c69f721fSFande Kong           if (row[j] != rstart) break;
1447c69f721fSFande Kong         }
1448c69f721fSFande Kong         if (j < n) ncols = j - i;
1449c69f721fSFande Kong         else ncols = n - i;
1450c69f721fSFande Kong         /* Now assemble all these values with a single function call */
14519566063dSJacob Faibussowitsch         PetscCall(MatSetValues_HYPRE(A, 1, row + i, ncols, col + i, val + i, A->insertmode));
1452c69f721fSFande Kong 
1453c69f721fSFande Kong         i = j;
1454c69f721fSFande Kong       }
1455c69f721fSFande Kong     }
14569566063dSJacob Faibussowitsch     PetscCall(MatStashScatterEnd_Private(&A->stash));
1457c69f721fSFande Kong   }
1458c69f721fSFande Kong 
1459792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixAssemble, hA->ij);
1460336664bdSPierre Jolivet   /* The assembly routine destroys the aux_matrix, we recreate it here by calling HYPRE_IJMatrixInitialize */
1461336664bdSPierre 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 */
1462651b1cf9SStefano Zampini   if (!A->sortedfull) {
1463af1cf968SStefano Zampini     hypre_AuxParCSRMatrix *aux_matrix;
1464af1cf968SStefano Zampini 
1465af1cf968SStefano Zampini     /* call destroy just to make sure we do not leak anything */
1466af1cf968SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
1467792fecdfSBarry Smith     PetscCallExternal(hypre_AuxParCSRMatrixDestroy, aux_matrix);
1468af1cf968SStefano Zampini     hypre_IJMatrixTranslator(hA->ij) = NULL;
1469af1cf968SStefano Zampini 
1470af1cf968SStefano Zampini     /* Initialize with assembled flag -> it only recreates the aux_par_matrix */
1471792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij);
1472af1cf968SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
14736ea7df73SStefano Zampini     if (aux_matrix) {
1474af1cf968SStefano Zampini       hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1; /* see comment in MatHYPRESetPreallocation_HYPRE */
147522235d61SPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
1476792fecdfSBarry Smith       PetscCallExternal(hypre_AuxParCSRMatrixInitialize, aux_matrix);
147722235d61SPierre Jolivet #else
1478792fecdfSBarry Smith       PetscCallExternal(hypre_AuxParCSRMatrixInitialize_v2, aux_matrix, HYPRE_MEMORY_HOST);
147922235d61SPierre Jolivet #endif
1480af1cf968SStefano Zampini     }
14816ea7df73SStefano Zampini   }
14826ea7df73SStefano Zampini   {
14836ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
14846ea7df73SStefano Zampini 
1485792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
1486792fecdfSBarry Smith     if (!hypre_ParCSRMatrixCommPkg(parcsr)) PetscCallExternal(hypre_MatvecCommPkgCreate, parcsr);
14876ea7df73SStefano Zampini   }
14889566063dSJacob Faibussowitsch   if (!hA->x) PetscCall(VecHYPRE_IJVectorCreate(A->cmap, &hA->x));
14899566063dSJacob Faibussowitsch   if (!hA->b) PetscCall(VecHYPRE_IJVectorCreate(A->rmap, &hA->b));
14906ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
14919566063dSJacob Faibussowitsch   PetscCall(MatBindToCPU_HYPRE(A, A->boundtocpu));
14926ea7df73SStefano Zampini #endif
14933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
149463c07aadSStefano Zampini }
149563c07aadSStefano Zampini 
1496d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetArray_HYPRE(Mat A, PetscInt size, void **array)
1497d71ae5a4SJacob Faibussowitsch {
1498c69f721fSFande Kong   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1499c69f721fSFande Kong 
1500c69f721fSFande Kong   PetscFunctionBegin;
1501651b1cf9SStefano Zampini   PetscCheck(hA->array_available, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Temporary space is in use");
1502c69f721fSFande Kong 
1503651b1cf9SStefano Zampini   if (hA->array_size >= size) {
150439accc25SStefano Zampini     *array = hA->array;
150539accc25SStefano Zampini   } else {
15069566063dSJacob Faibussowitsch     PetscCall(PetscFree(hA->array));
1507651b1cf9SStefano Zampini     hA->array_size = size;
1508651b1cf9SStefano Zampini     PetscCall(PetscMalloc(hA->array_size, &hA->array));
1509c69f721fSFande Kong     *array = hA->array;
1510c69f721fSFande Kong   }
1511c69f721fSFande Kong 
1512651b1cf9SStefano Zampini   hA->array_available = PETSC_FALSE;
15133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1514c69f721fSFande Kong }
1515c69f721fSFande Kong 
1516d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreArray_HYPRE(Mat A, void **array)
1517d71ae5a4SJacob Faibussowitsch {
1518c69f721fSFande Kong   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1519c69f721fSFande Kong 
1520c69f721fSFande Kong   PetscFunctionBegin;
1521c69f721fSFande Kong   *array              = NULL;
1522651b1cf9SStefano Zampini   hA->array_available = PETSC_TRUE;
15233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1524c69f721fSFande Kong }
1525c69f721fSFande Kong 
1526d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_HYPRE(Mat A, PetscInt nr, const PetscInt rows[], PetscInt nc, const PetscInt cols[], const PetscScalar v[], InsertMode ins)
1527d71ae5a4SJacob Faibussowitsch {
1528d975228cSstefano_zampini   Mat_HYPRE     *hA   = (Mat_HYPRE *)A->data;
1529d975228cSstefano_zampini   PetscScalar   *vals = (PetscScalar *)v;
153039accc25SStefano Zampini   HYPRE_Complex *sscr;
1531c69f721fSFande Kong   PetscInt      *cscr[2];
1532c69f721fSFande Kong   PetscInt       i, nzc;
1533651b1cf9SStefano Zampini   PetscInt       rst = A->rmap->rstart, ren = A->rmap->rend;
153408defe43SFande Kong   void          *array = NULL;
1535d975228cSstefano_zampini 
1536d975228cSstefano_zampini   PetscFunctionBegin;
15379566063dSJacob Faibussowitsch   PetscCall(MatGetArray_HYPRE(A, sizeof(PetscInt) * (2 * nc) + sizeof(HYPRE_Complex) * nc * nr, &array));
1538c69f721fSFande Kong   cscr[0] = (PetscInt *)array;
1539c69f721fSFande Kong   cscr[1] = ((PetscInt *)array) + nc;
154039accc25SStefano Zampini   sscr    = (HYPRE_Complex *)(((PetscInt *)array) + nc * 2);
1541d975228cSstefano_zampini   for (i = 0, nzc = 0; i < nc; i++) {
1542d975228cSstefano_zampini     if (cols[i] >= 0) {
1543d975228cSstefano_zampini       cscr[0][nzc]   = cols[i];
1544d975228cSstefano_zampini       cscr[1][nzc++] = i;
1545d975228cSstefano_zampini     }
1546d975228cSstefano_zampini   }
1547c69f721fSFande Kong   if (!nzc) {
15489566063dSJacob Faibussowitsch     PetscCall(MatRestoreArray_HYPRE(A, &array));
15493ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1550c69f721fSFande Kong   }
1551d975228cSstefano_zampini 
15526ea7df73SStefano Zampini #if 0 //defined(PETSC_HAVE_HYPRE_DEVICE)
15536ea7df73SStefano Zampini   if (HYPRE_MEMORY_HOST != hypre_IJMatrixMemoryLocation(hA->ij)) {
15546ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
15556ea7df73SStefano Zampini 
1556792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject,hA->ij,(void**)&parcsr);
1557792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMigrate,parcsr, HYPRE_MEMORY_HOST);
15586ea7df73SStefano Zampini   }
15596ea7df73SStefano Zampini #endif
15606ea7df73SStefano Zampini 
1561d975228cSstefano_zampini   if (ins == ADD_VALUES) {
1562d975228cSstefano_zampini     for (i = 0; i < nr; i++) {
15636ea7df73SStefano Zampini       if (rows[i] >= 0) {
1564d975228cSstefano_zampini         PetscInt  j;
15652cf14000SStefano Zampini         HYPRE_Int hnc = (HYPRE_Int)nzc;
15662cf14000SStefano Zampini 
1567651b1cf9SStefano Zampini         if (!nzc) continue;
1568651b1cf9SStefano Zampini         /* nonlocal values */
1569651b1cf9SStefano Zampini         if (rows[i] < rst || rows[i] >= ren) {
1570651b1cf9SStefano Zampini           PetscCheck(!A->nooffprocentries, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Setting off process row %" PetscInt_FMT " even though MatSetOption(,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE) was set", rows[i]);
1571651b1cf9SStefano Zampini           if (hA->donotstash) continue;
1572651b1cf9SStefano Zampini         }
1573aed4548fSBarry 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]);
15749566063dSJacob Faibussowitsch         for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j]));
1575792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixAddToValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr);
1576d975228cSstefano_zampini       }
1577d975228cSstefano_zampini       vals += nc;
1578d975228cSstefano_zampini     }
1579d975228cSstefano_zampini   } else { /* INSERT_VALUES */
1580d975228cSstefano_zampini     for (i = 0; i < nr; i++) {
15816ea7df73SStefano Zampini       if (rows[i] >= 0) {
1582d975228cSstefano_zampini         PetscInt  j;
15832cf14000SStefano Zampini         HYPRE_Int hnc = (HYPRE_Int)nzc;
15842cf14000SStefano Zampini 
1585651b1cf9SStefano Zampini         if (!nzc) continue;
1586aed4548fSBarry 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]);
15879566063dSJacob Faibussowitsch         for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j]));
1588c69f721fSFande Kong         /* nonlocal values */
1589651b1cf9SStefano Zampini         if (rows[i] < rst || rows[i] >= ren) {
1590651b1cf9SStefano 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]);
1591651b1cf9SStefano Zampini           if (!hA->donotstash) PetscCall(MatStashValuesRow_Private(&A->stash, rows[i], nzc, cscr[0], (PetscScalar *)sscr, PETSC_FALSE));
1592651b1cf9SStefano Zampini         }
1593c69f721fSFande Kong         /* local values */
1594651b1cf9SStefano Zampini         else
1595651b1cf9SStefano Zampini           PetscCallExternal(HYPRE_IJMatrixSetValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr);
1596d975228cSstefano_zampini       }
1597d975228cSstefano_zampini       vals += nc;
1598d975228cSstefano_zampini     }
1599d975228cSstefano_zampini   }
1600c69f721fSFande Kong 
16019566063dSJacob Faibussowitsch   PetscCall(MatRestoreArray_HYPRE(A, &array));
16023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1603d975228cSstefano_zampini }
1604d975228cSstefano_zampini 
1605d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRESetPreallocation_HYPRE(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[])
1606d71ae5a4SJacob Faibussowitsch {
1607d975228cSstefano_zampini   Mat_HYPRE  *hA = (Mat_HYPRE *)A->data;
16087d968826Sstefano_zampini   HYPRE_Int  *hdnnz, *honnz;
160906a29025Sstefano_zampini   PetscInt    i, rs, re, cs, ce, bs;
1610d975228cSstefano_zampini   PetscMPIInt size;
1611d975228cSstefano_zampini 
1612d975228cSstefano_zampini   PetscFunctionBegin;
16139566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
16149566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
1615d975228cSstefano_zampini   rs = A->rmap->rstart;
1616d975228cSstefano_zampini   re = A->rmap->rend;
1617d975228cSstefano_zampini   cs = A->cmap->rstart;
1618d975228cSstefano_zampini   ce = A->cmap->rend;
1619d975228cSstefano_zampini   if (!hA->ij) {
1620792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rs, re - 1, cs, ce - 1, &hA->ij);
1621792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR);
1622d975228cSstefano_zampini   } else {
16232cf14000SStefano Zampini     HYPRE_BigInt hrs, hre, hcs, hce;
1624792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetLocalRange, hA->ij, &hrs, &hre, &hcs, &hce);
1625aed4548fSBarry 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);
1626aed4548fSBarry 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);
1627d975228cSstefano_zampini   }
162806977982Sstefanozampini   PetscCall(MatHYPRE_DestroyCOOMat(A));
16299566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(A, &bs));
163006a29025Sstefano_zampini   if (dnz == PETSC_DEFAULT || dnz == PETSC_DECIDE) dnz = 10 * bs;
163106a29025Sstefano_zampini   if (onz == PETSC_DEFAULT || onz == PETSC_DECIDE) onz = 10 * bs;
163206a29025Sstefano_zampini 
1633d975228cSstefano_zampini   if (!dnnz) {
16349566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->rmap->n, &hdnnz));
1635d975228cSstefano_zampini     for (i = 0; i < A->rmap->n; i++) hdnnz[i] = dnz;
1636d975228cSstefano_zampini   } else {
16377d968826Sstefano_zampini     hdnnz = (HYPRE_Int *)dnnz;
1638d975228cSstefano_zampini   }
16399566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
1640d975228cSstefano_zampini   if (size > 1) {
1641ddbeb582SStefano Zampini     hypre_AuxParCSRMatrix *aux_matrix;
1642d975228cSstefano_zampini     if (!onnz) {
16439566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(A->rmap->n, &honnz));
1644d975228cSstefano_zampini       for (i = 0; i < A->rmap->n; i++) honnz[i] = onz;
164522235d61SPierre Jolivet     } else honnz = (HYPRE_Int *)onnz;
1646ddbeb582SStefano Zampini     /* SetDiagOffdSizes sets hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0, since it seems
1647ddbeb582SStefano Zampini        they assume the user will input the entire row values, properly sorted
1648336664bdSPierre Jolivet        In PETSc, we don't make such an assumption and set this flag to 1,
1649336664bdSPierre Jolivet        unless the option MAT_SORTED_FULL is set to true.
1650ddbeb582SStefano Zampini        Also, to avoid possible memory leaks, we destroy and recreate the translator
1651ddbeb582SStefano Zampini        This has to be done here, as HYPRE_IJMatrixInitialize will properly initialize
1652ddbeb582SStefano Zampini        the IJ matrix for us */
1653ddbeb582SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
1654ddbeb582SStefano Zampini     hypre_AuxParCSRMatrixDestroy(aux_matrix);
1655ddbeb582SStefano Zampini     hypre_IJMatrixTranslator(hA->ij) = NULL;
1656792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, hA->ij, hdnnz, honnz);
1657ddbeb582SStefano Zampini     aux_matrix                               = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
1658651b1cf9SStefano Zampini     hypre_AuxParCSRMatrixNeedAux(aux_matrix) = !A->sortedfull;
1659d975228cSstefano_zampini   } else {
1660d975228cSstefano_zampini     honnz = NULL;
1661792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetRowSizes, hA->ij, hdnnz);
1662d975228cSstefano_zampini   }
1663ddbeb582SStefano Zampini 
1664af1cf968SStefano Zampini   /* reset assembled flag and call the initialize method */
1665af1cf968SStefano Zampini   hypre_IJMatrixAssembleFlag(hA->ij) = 0;
16666ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
1667792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij);
16686ea7df73SStefano Zampini #else
1669792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize_v2, hA->ij, HYPRE_MEMORY_HOST);
16706ea7df73SStefano Zampini #endif
167148a46eb9SPierre Jolivet   if (!dnnz) PetscCall(PetscFree(hdnnz));
167248a46eb9SPierre Jolivet   if (!onnz && honnz) PetscCall(PetscFree(honnz));
1673af1cf968SStefano Zampini   /* Match AIJ logic */
167406a29025Sstefano_zampini   A->preallocated = PETSC_TRUE;
1675af1cf968SStefano Zampini   A->assembled    = PETSC_FALSE;
16763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1677d975228cSstefano_zampini }
1678d975228cSstefano_zampini 
1679d975228cSstefano_zampini /*@C
1680d975228cSstefano_zampini   MatHYPRESetPreallocation - Preallocates memory for a sparse parallel matrix in HYPRE IJ format
1681d975228cSstefano_zampini 
1682c3339decSBarry Smith   Collective
1683d975228cSstefano_zampini 
1684d975228cSstefano_zampini   Input Parameters:
1685d975228cSstefano_zampini + A    - the matrix
1686d975228cSstefano_zampini . dnz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1687d975228cSstefano_zampini           (same value is used for all local rows)
1688d975228cSstefano_zampini . dnnz - array containing the number of nonzeros in the various rows of the
1689d975228cSstefano_zampini           DIAGONAL portion of the local submatrix (possibly different for each row)
16902ef1f0ffSBarry Smith           or `NULL` (`PETSC_NULL_INTEGER` in Fortran), if `d_nz` is used to specify the nonzero structure.
16912ef1f0ffSBarry Smith           The size of this array is equal to the number of local rows, i.e `m`.
1692d975228cSstefano_zampini           For matrices that will be factored, you must leave room for (and set)
1693d975228cSstefano_zampini           the diagonal entry even if it is zero.
1694d975228cSstefano_zampini . onz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1695d975228cSstefano_zampini           submatrix (same value is used for all local rows).
1696d975228cSstefano_zampini - onnz - array containing the number of nonzeros in the various rows of the
1697d975228cSstefano_zampini           OFF-DIAGONAL portion of the local submatrix (possibly different for
16982ef1f0ffSBarry Smith           each row) or `NULL` (`PETSC_NULL_INTEGER` in Fortran), if `o_nz` is used to specify the nonzero
1699d975228cSstefano_zampini           structure. The size of this array is equal to the number
17002ef1f0ffSBarry Smith           of local rows, i.e `m`.
1701d975228cSstefano_zampini 
17022fe279fdSBarry Smith   Level: intermediate
17032fe279fdSBarry Smith 
170411a5261eSBarry Smith   Note:
17052ef1f0ffSBarry Smith   If the *nnz parameter is given then the *nz parameter is ignored; for sequential matrices, `onz` and `onnz` are ignored.
1706d975228cSstefano_zampini 
17071cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatMPIAIJSetPreallocation()`, `MATHYPRE`, `MATAIJ`
1708d975228cSstefano_zampini @*/
1709d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHYPRESetPreallocation(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[])
1710d71ae5a4SJacob Faibussowitsch {
1711d975228cSstefano_zampini   PetscFunctionBegin;
1712d975228cSstefano_zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1713d975228cSstefano_zampini   PetscValidType(A, 1);
1714cac4c232SBarry Smith   PetscTryMethod(A, "MatHYPRESetPreallocation_C", (Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]), (A, dnz, dnnz, onz, onnz));
17153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1716d975228cSstefano_zampini }
1717d975228cSstefano_zampini 
171820f4b53cSBarry Smith /*@C
17192ef1f0ffSBarry Smith   MatCreateFromParCSR - Creates a `Mat` from a `hypre_ParCSRMatrix`
1720225daaf8SStefano Zampini 
1721225daaf8SStefano Zampini   Collective
1722225daaf8SStefano Zampini 
1723225daaf8SStefano Zampini   Input Parameters:
17242ef1f0ffSBarry Smith + parcsr   - the pointer to the `hypre_ParCSRMatrix`
17252ef1f0ffSBarry Smith . mtype    - matrix type to be created. Currently `MATAIJ`, `MATIS` and `MATHYPRE` are supported.
172620f4b53cSBarry Smith - copymode - PETSc copying options, see  `PetscCopyMode`
1727225daaf8SStefano Zampini 
1728225daaf8SStefano Zampini   Output Parameter:
1729225daaf8SStefano Zampini . A - the matrix
1730225daaf8SStefano Zampini 
1731225daaf8SStefano Zampini   Level: intermediate
1732225daaf8SStefano Zampini 
1733bfe80ac4SPierre Jolivet .seealso: [](ch_matrices), `Mat`, `MATHYPRE`, `PetscCopyMode`
173420f4b53cSBarry Smith @*/
1735d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreateFromParCSR(hypre_ParCSRMatrix *parcsr, MatType mtype, PetscCopyMode copymode, Mat *A)
1736d71ae5a4SJacob Faibussowitsch {
1737225daaf8SStefano Zampini   Mat        T;
1738978814f1SStefano Zampini   Mat_HYPRE *hA;
1739978814f1SStefano Zampini   MPI_Comm   comm;
1740978814f1SStefano Zampini   PetscInt   rstart, rend, cstart, cend, M, N;
1741d248a85cSRichard Tran Mills   PetscBool  isseqaij, isseqaijmkl, ismpiaij, isaij, ishyp, isis;
1742978814f1SStefano Zampini 
1743978814f1SStefano Zampini   PetscFunctionBegin;
1744978814f1SStefano Zampini   comm = hypre_ParCSRMatrixComm(parcsr);
17459566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQAIJ, &isseqaij));
17469566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQAIJMKL, &isseqaijmkl));
17479566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPIAIJ, &ismpiaij));
17489566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATAIJ, &isaij));
17499566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATHYPRE, &ishyp));
17509566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATIS, &isis));
1751d248a85cSRichard Tran Mills   isaij = (PetscBool)(isseqaij || isseqaijmkl || ismpiaij || isaij);
17526ea7df73SStefano Zampini   /* TODO */
1753aed4548fSBarry 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);
1754978814f1SStefano Zampini   /* access ParCSRMatrix */
1755978814f1SStefano Zampini   rstart = hypre_ParCSRMatrixFirstRowIndex(parcsr);
1756978814f1SStefano Zampini   rend   = hypre_ParCSRMatrixLastRowIndex(parcsr);
1757978814f1SStefano Zampini   cstart = hypre_ParCSRMatrixFirstColDiag(parcsr);
1758978814f1SStefano Zampini   cend   = hypre_ParCSRMatrixLastColDiag(parcsr);
1759978814f1SStefano Zampini   M      = hypre_ParCSRMatrixGlobalNumRows(parcsr);
1760978814f1SStefano Zampini   N      = hypre_ParCSRMatrixGlobalNumCols(parcsr);
1761978814f1SStefano Zampini 
1762978814f1SStefano Zampini   /* create PETSc matrix with MatHYPRE */
17639566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, &T));
1764c2886e86SStefano Zampini   PetscCall(MatSetSizes(T, PetscMax(rend - rstart + 1, 0), PetscMax(cend - cstart + 1, 0), M, N));
17659566063dSJacob Faibussowitsch   PetscCall(MatSetType(T, MATHYPRE));
1766f4f49eeaSPierre Jolivet   hA = (Mat_HYPRE *)T->data;
1767978814f1SStefano Zampini 
1768978814f1SStefano Zampini   /* create HYPRE_IJMatrix */
1769c2886e86SStefano Zampini   PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rstart, rend, cstart, cend, &hA->ij);
1770792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR);
177145b8d346SStefano Zampini 
177245b8d346SStefano Zampini   /* create new ParCSR object if needed */
177345b8d346SStefano Zampini   if (ishyp && copymode == PETSC_COPY_VALUES) {
177445b8d346SStefano Zampini     hypre_ParCSRMatrix *new_parcsr;
17756ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0)
177645b8d346SStefano Zampini     hypre_CSRMatrix *hdiag, *hoffd, *ndiag, *noffd;
177745b8d346SStefano Zampini 
17780e6427aaSSatish Balay     new_parcsr = hypre_ParCSRMatrixClone(parcsr, 0);
177945b8d346SStefano Zampini     hdiag      = hypre_ParCSRMatrixDiag(parcsr);
178045b8d346SStefano Zampini     hoffd      = hypre_ParCSRMatrixOffd(parcsr);
178145b8d346SStefano Zampini     ndiag      = hypre_ParCSRMatrixDiag(new_parcsr);
178245b8d346SStefano Zampini     noffd      = hypre_ParCSRMatrixOffd(new_parcsr);
17839566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hypre_CSRMatrixData(ndiag), hypre_CSRMatrixData(hdiag), hypre_CSRMatrixNumNonzeros(hdiag)));
17849566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hypre_CSRMatrixData(noffd), hypre_CSRMatrixData(hoffd), hypre_CSRMatrixNumNonzeros(hoffd)));
17856ea7df73SStefano Zampini #else
17866ea7df73SStefano Zampini     new_parcsr = hypre_ParCSRMatrixClone(parcsr, 1);
17876ea7df73SStefano Zampini #endif
178845b8d346SStefano Zampini     parcsr   = new_parcsr;
178945b8d346SStefano Zampini     copymode = PETSC_OWN_POINTER;
179045b8d346SStefano Zampini   }
1791978814f1SStefano Zampini 
1792978814f1SStefano Zampini   /* set ParCSR object */
1793978814f1SStefano Zampini   hypre_IJMatrixObject(hA->ij) = parcsr;
17944ec6421dSstefano_zampini   T->preallocated              = PETSC_TRUE;
1795978814f1SStefano Zampini 
1796978814f1SStefano Zampini   /* set assembled flag */
1797978814f1SStefano Zampini   hypre_IJMatrixAssembleFlag(hA->ij) = 1;
17986ea7df73SStefano Zampini #if 0
1799792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize,hA->ij);
18006ea7df73SStefano Zampini #endif
1801225daaf8SStefano Zampini   if (ishyp) {
18026d2a658fSstefano_zampini     PetscMPIInt myid = 0;
18036d2a658fSstefano_zampini 
18046d2a658fSstefano_zampini     /* make sure we always have row_starts and col_starts available */
180548a46eb9SPierre Jolivet     if (HYPRE_AssumedPartitionCheck()) PetscCallMPI(MPI_Comm_rank(comm, &myid));
1806a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
18076d2a658fSstefano_zampini     if (!hypre_ParCSRMatrixOwnsColStarts(parcsr)) {
18086d2a658fSstefano_zampini       PetscLayout map;
18096d2a658fSstefano_zampini 
18109566063dSJacob Faibussowitsch       PetscCall(MatGetLayouts(T, NULL, &map));
18119566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetUp(map));
18122cf14000SStefano Zampini       hypre_ParCSRMatrixColStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid);
18136d2a658fSstefano_zampini     }
18146d2a658fSstefano_zampini     if (!hypre_ParCSRMatrixOwnsRowStarts(parcsr)) {
18156d2a658fSstefano_zampini       PetscLayout map;
18166d2a658fSstefano_zampini 
18179566063dSJacob Faibussowitsch       PetscCall(MatGetLayouts(T, &map, NULL));
18189566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetUp(map));
18192cf14000SStefano Zampini       hypre_ParCSRMatrixRowStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid);
18206d2a658fSstefano_zampini     }
1821a1d2239cSSatish Balay #endif
1822978814f1SStefano Zampini     /* prevent from freeing the pointer */
1823978814f1SStefano Zampini     if (copymode == PETSC_USE_POINTER) hA->inner_free = PETSC_FALSE;
1824225daaf8SStefano Zampini     *A = T;
18259566063dSJacob Faibussowitsch     PetscCall(MatSetOption(*A, MAT_SORTED_FULL, PETSC_TRUE));
18269566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(*A, MAT_FINAL_ASSEMBLY));
18279566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(*A, MAT_FINAL_ASSEMBLY));
1828bb4689ddSStefano Zampini   } else if (isaij) {
1829bb4689ddSStefano Zampini     if (copymode != PETSC_OWN_POINTER) {
1830225daaf8SStefano Zampini       /* prevent from freeing the pointer */
1831225daaf8SStefano Zampini       hA->inner_free = PETSC_FALSE;
18329566063dSJacob Faibussowitsch       PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INITIAL_MATRIX, A));
18339566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&T));
1834225daaf8SStefano Zampini     } else { /* AIJ return type with PETSC_OWN_POINTER */
18359566063dSJacob Faibussowitsch       PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INPLACE_MATRIX, &T));
1836225daaf8SStefano Zampini       *A = T;
1837225daaf8SStefano Zampini     }
1838bb4689ddSStefano Zampini   } else if (isis) {
18399566063dSJacob Faibussowitsch     PetscCall(MatConvert_HYPRE_IS(T, MATIS, MAT_INITIAL_MATRIX, A));
18408cfe8d00SStefano Zampini     if (copymode != PETSC_OWN_POINTER) hA->inner_free = PETSC_FALSE;
18419566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&T));
1842bb4689ddSStefano Zampini   }
18433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1844978814f1SStefano Zampini }
1845978814f1SStefano Zampini 
1846d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPREGetParCSR_HYPRE(Mat A, hypre_ParCSRMatrix **parcsr)
1847d71ae5a4SJacob Faibussowitsch {
1848dd9c0a25Sstefano_zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1849dd9c0a25Sstefano_zampini   HYPRE_Int  type;
1850dd9c0a25Sstefano_zampini 
1851dd9c0a25Sstefano_zampini   PetscFunctionBegin;
185228b400f6SJacob Faibussowitsch   PetscCheck(hA->ij, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "HYPRE_IJMatrix not present");
1853792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
185408401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "HYPRE_IJMatrix is not of type HYPRE_PARCSR");
1855792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)parcsr);
18563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1857dd9c0a25Sstefano_zampini }
1858dd9c0a25Sstefano_zampini 
185920f4b53cSBarry Smith /*@C
1860dd9c0a25Sstefano_zampini   MatHYPREGetParCSR - Gets the pointer to the ParCSR matrix
1861dd9c0a25Sstefano_zampini 
1862cc4c1da9SBarry Smith   Not Collective, No Fortran Support
1863dd9c0a25Sstefano_zampini 
186420f4b53cSBarry Smith   Input Parameter:
186520f4b53cSBarry Smith . A - the `MATHYPRE` object
1866dd9c0a25Sstefano_zampini 
1867dd9c0a25Sstefano_zampini   Output Parameter:
18682ef1f0ffSBarry Smith . parcsr - the pointer to the `hypre_ParCSRMatrix`
1869dd9c0a25Sstefano_zampini 
1870dd9c0a25Sstefano_zampini   Level: intermediate
1871dd9c0a25Sstefano_zampini 
1872bfe80ac4SPierre Jolivet .seealso: [](ch_matrices), `Mat`, `MATHYPRE`, `PetscCopyMode`
187320f4b53cSBarry Smith @*/
1874d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHYPREGetParCSR(Mat A, hypre_ParCSRMatrix **parcsr)
1875d71ae5a4SJacob Faibussowitsch {
1876dd9c0a25Sstefano_zampini   PetscFunctionBegin;
1877dd9c0a25Sstefano_zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1878dd9c0a25Sstefano_zampini   PetscValidType(A, 1);
1879cac4c232SBarry Smith   PetscUseMethod(A, "MatHYPREGetParCSR_C", (Mat, hypre_ParCSRMatrix **), (A, parcsr));
18803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1881dd9c0a25Sstefano_zampini }
1882dd9c0a25Sstefano_zampini 
1883d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_HYPRE(Mat A, PetscBool *missing, PetscInt *dd)
1884d71ae5a4SJacob Faibussowitsch {
188568ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
188668ec7858SStefano Zampini   hypre_CSRMatrix    *ha;
188768ec7858SStefano Zampini   PetscInt            rst;
188868ec7858SStefano Zampini 
188968ec7858SStefano Zampini   PetscFunctionBegin;
189008401ef6SPierre Jolivet   PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented with non-square diagonal blocks");
18919566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &rst, NULL));
18929566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
189368ec7858SStefano Zampini   if (missing) *missing = PETSC_FALSE;
189468ec7858SStefano Zampini   if (dd) *dd = -1;
189568ec7858SStefano Zampini   ha = hypre_ParCSRMatrixDiag(parcsr);
189668ec7858SStefano Zampini   if (ha) {
189768299464SStefano Zampini     PetscInt   size, i;
189868299464SStefano Zampini     HYPRE_Int *ii, *jj;
189968ec7858SStefano Zampini 
190068ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
190168ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
190268ec7858SStefano Zampini     jj   = hypre_CSRMatrixJ(ha);
190368ec7858SStefano Zampini     for (i = 0; i < size; i++) {
190468ec7858SStefano Zampini       PetscInt  j;
190568ec7858SStefano Zampini       PetscBool found = PETSC_FALSE;
190668ec7858SStefano Zampini 
19079371c9d4SSatish Balay       for (j = ii[i]; j < ii[i + 1] && !found; j++) found = (jj[j] == i) ? PETSC_TRUE : PETSC_FALSE;
190868ec7858SStefano Zampini 
190968ec7858SStefano Zampini       if (!found) {
19103ba16761SJacob Faibussowitsch         PetscCall(PetscInfo(A, "Matrix is missing local diagonal entry %" PetscInt_FMT "\n", i));
191168ec7858SStefano Zampini         if (missing) *missing = PETSC_TRUE;
191268ec7858SStefano Zampini         if (dd) *dd = i + rst;
19133ba16761SJacob Faibussowitsch         PetscFunctionReturn(PETSC_SUCCESS);
191468ec7858SStefano Zampini       }
191568ec7858SStefano Zampini     }
191668ec7858SStefano Zampini     if (!size) {
19173ba16761SJacob Faibussowitsch       PetscCall(PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n"));
191868ec7858SStefano Zampini       if (missing) *missing = PETSC_TRUE;
191968ec7858SStefano Zampini       if (dd) *dd = rst;
192068ec7858SStefano Zampini     }
192168ec7858SStefano Zampini   } else {
19223ba16761SJacob Faibussowitsch     PetscCall(PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n"));
192368ec7858SStefano Zampini     if (missing) *missing = PETSC_TRUE;
192468ec7858SStefano Zampini     if (dd) *dd = rst;
192568ec7858SStefano Zampini   }
19263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
192768ec7858SStefano Zampini }
192868ec7858SStefano Zampini 
1929d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatScale_HYPRE(Mat A, PetscScalar s)
1930d71ae5a4SJacob Faibussowitsch {
193168ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
19326ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
193368ec7858SStefano Zampini   hypre_CSRMatrix *ha;
19346ea7df73SStefano Zampini #endif
193539accc25SStefano Zampini   HYPRE_Complex hs;
193668ec7858SStefano Zampini 
193768ec7858SStefano Zampini   PetscFunctionBegin;
19389566063dSJacob Faibussowitsch   PetscCall(PetscHYPREScalarCast(s, &hs));
19399566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
19406ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 19, 0)
1941792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixScale, parcsr, hs);
19426ea7df73SStefano Zampini #else /* diagonal part */
194368ec7858SStefano Zampini   ha = hypre_ParCSRMatrixDiag(parcsr);
194468ec7858SStefano Zampini   if (ha) {
194568299464SStefano Zampini     PetscInt       size, i;
194668299464SStefano Zampini     HYPRE_Int     *ii;
194739accc25SStefano Zampini     HYPRE_Complex *a;
194868ec7858SStefano Zampini 
194968ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
195068ec7858SStefano Zampini     a    = hypre_CSRMatrixData(ha);
195168ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
195239accc25SStefano Zampini     for (i = 0; i < ii[size]; i++) a[i] *= hs;
195368ec7858SStefano Zampini   }
19544cf0e950SBarry Smith   /* off-diagonal part */
195568ec7858SStefano Zampini   ha = hypre_ParCSRMatrixOffd(parcsr);
195668ec7858SStefano Zampini   if (ha) {
195768299464SStefano Zampini     PetscInt       size, i;
195868299464SStefano Zampini     HYPRE_Int     *ii;
195939accc25SStefano Zampini     HYPRE_Complex *a;
196068ec7858SStefano Zampini 
196168ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
196268ec7858SStefano Zampini     a    = hypre_CSRMatrixData(ha);
196368ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
196439accc25SStefano Zampini     for (i = 0; i < ii[size]; i++) a[i] *= hs;
196568ec7858SStefano Zampini   }
19666ea7df73SStefano Zampini #endif
19673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
196868ec7858SStefano Zampini }
196968ec7858SStefano Zampini 
1970d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_HYPRE(Mat A, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
1971d71ae5a4SJacob Faibussowitsch {
197268ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
197368299464SStefano Zampini   HYPRE_Int          *lrows;
197468299464SStefano Zampini   PetscInt            rst, ren, i;
197568ec7858SStefano Zampini 
197668ec7858SStefano Zampini   PetscFunctionBegin;
197708401ef6SPierre Jolivet   PetscCheck(!x && !b, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "To be implemented");
19789566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
19799566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numRows, &lrows));
19809566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &rst, &ren));
198168ec7858SStefano Zampini   for (i = 0; i < numRows; i++) {
19827a46b595SBarry Smith     PetscCheck(rows[i] >= rst && rows[i] < ren, PETSC_COMM_SELF, PETSC_ERR_SUP, "Non-local rows not yet supported");
198368ec7858SStefano Zampini     lrows[i] = rows[i] - rst;
198468ec7858SStefano Zampini   }
1985792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixEliminateRowsCols, parcsr, numRows, lrows);
19869566063dSJacob Faibussowitsch   PetscCall(PetscFree(lrows));
19873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
198868ec7858SStefano Zampini }
198968ec7858SStefano Zampini 
1990d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPRE_CSRMatrix(hypre_CSRMatrix *ha)
1991d71ae5a4SJacob Faibussowitsch {
1992c69f721fSFande Kong   PetscFunctionBegin;
1993c69f721fSFande Kong   if (ha) {
1994c69f721fSFande Kong     HYPRE_Int     *ii, size;
1995c69f721fSFande Kong     HYPRE_Complex *a;
1996c69f721fSFande Kong 
1997c69f721fSFande Kong     size = hypre_CSRMatrixNumRows(ha);
1998c69f721fSFande Kong     a    = hypre_CSRMatrixData(ha);
1999c69f721fSFande Kong     ii   = hypre_CSRMatrixI(ha);
2000c69f721fSFande Kong 
20019566063dSJacob Faibussowitsch     if (a) PetscCall(PetscArrayzero(a, ii[size]));
2002c69f721fSFande Kong   }
20033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2004c69f721fSFande Kong }
2005c69f721fSFande Kong 
200666976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPRE(Mat A)
2007d71ae5a4SJacob Faibussowitsch {
20086ea7df73SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
20096ea7df73SStefano Zampini 
20106ea7df73SStefano Zampini   PetscFunctionBegin;
20116ea7df73SStefano Zampini   if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(hA->ij)) {
2012792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetConstantValues, hA->ij, 0.0);
20136ea7df73SStefano Zampini   } else {
2014c69f721fSFande Kong     hypre_ParCSRMatrix *parcsr;
2015c69f721fSFande Kong 
20169566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
20179566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr)));
20189566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr)));
20196ea7df73SStefano Zampini   }
20203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2021c69f721fSFande Kong }
2022c69f721fSFande Kong 
2023d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_HYPRE_CSRMatrix(hypre_CSRMatrix *hA, PetscInt N, const PetscInt rows[], HYPRE_Complex diag)
2024d71ae5a4SJacob Faibussowitsch {
202539accc25SStefano Zampini   PetscInt       ii;
202639accc25SStefano Zampini   HYPRE_Int     *i, *j;
202739accc25SStefano Zampini   HYPRE_Complex *a;
2028c69f721fSFande Kong 
2029c69f721fSFande Kong   PetscFunctionBegin;
20303ba16761SJacob Faibussowitsch   if (!hA) PetscFunctionReturn(PETSC_SUCCESS);
2031c69f721fSFande Kong 
203239accc25SStefano Zampini   i = hypre_CSRMatrixI(hA);
203339accc25SStefano Zampini   j = hypre_CSRMatrixJ(hA);
2034c69f721fSFande Kong   a = hypre_CSRMatrixData(hA);
2035a32e9c99SJunchao Zhang #if defined(PETSC_HAVE_HYPRE_DEVICE)
2036a32e9c99SJunchao Zhang   if (HYPRE_MEMORY_DEVICE == hypre_CSRMatrixMemoryLocation(hA)) {
2037a32e9c99SJunchao Zhang   #if defined(HYPRE_USING_CUDA)
2038a32e9c99SJunchao Zhang     MatZeroRows_CUDA(N, rows, i, j, a, diag);
2039a32e9c99SJunchao Zhang   #elif defined(HYPRE_USING_HIP)
2040a32e9c99SJunchao Zhang     MatZeroRows_HIP(N, rows, i, j, a, diag);
2041a32e9c99SJunchao Zhang   #elif defined(PETSC_HAVE_KOKKOS)
2042a32e9c99SJunchao Zhang     MatZeroRows_Kokkos(N, rows, i, j, a, diag);
2043a32e9c99SJunchao Zhang   #else
2044a32e9c99SJunchao Zhang     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for MatZeroRows on a hypre matrix in this memory location");
2045a32e9c99SJunchao Zhang   #endif
2046a32e9c99SJunchao Zhang   } else
2047a32e9c99SJunchao Zhang #endif
2048a32e9c99SJunchao Zhang   {
2049c69f721fSFande Kong     for (ii = 0; ii < N; ii++) {
205039accc25SStefano Zampini       HYPRE_Int jj, ibeg, iend, irow;
205139accc25SStefano Zampini 
2052c69f721fSFande Kong       irow = rows[ii];
2053c69f721fSFande Kong       ibeg = i[irow];
2054c69f721fSFande Kong       iend = i[irow + 1];
2055c69f721fSFande Kong       for (jj = ibeg; jj < iend; jj++)
2056c69f721fSFande Kong         if (j[jj] == irow) a[jj] = diag;
2057c69f721fSFande Kong         else a[jj] = 0.0;
2058c69f721fSFande Kong     }
2059a32e9c99SJunchao Zhang   }
20603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2061c69f721fSFande Kong }
2062c69f721fSFande Kong 
2063d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_HYPRE(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
2064d71ae5a4SJacob Faibussowitsch {
2065c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
2066a32e9c99SJunchao Zhang   PetscInt           *lrows, len, *lrows2;
206739accc25SStefano Zampini   HYPRE_Complex       hdiag;
2068c69f721fSFande Kong 
2069c69f721fSFande Kong   PetscFunctionBegin;
207008401ef6SPierre Jolivet   PetscCheck(!x && !b, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Does not support to modify the solution and the right hand size");
20719566063dSJacob Faibussowitsch   PetscCall(PetscHYPREScalarCast(diag, &hdiag));
2072c69f721fSFande Kong   /* retrieve the internal matrix */
20739566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
2074c69f721fSFande Kong   /* get locally owned rows */
20759566063dSJacob Faibussowitsch   PetscCall(MatZeroRowsMapLocal_Private(A, N, rows, &len, &lrows));
2076a32e9c99SJunchao Zhang 
2077a32e9c99SJunchao Zhang #if defined(PETSC_HAVE_HYPRE_DEVICE)
2078a32e9c99SJunchao Zhang   if (HYPRE_MEMORY_DEVICE == hypre_CSRMatrixMemoryLocation(hypre_ParCSRMatrixDiag(parcsr))) {
2079a32e9c99SJunchao Zhang     Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
2080a32e9c99SJunchao Zhang     PetscInt   m;
2081a32e9c99SJunchao Zhang     PetscCall(MatGetLocalSize(A, &m, NULL));
2082a32e9c99SJunchao Zhang     if (!hA->rows_d) {
2083a32e9c99SJunchao Zhang       hA->rows_d = hypre_TAlloc(PetscInt, m, HYPRE_MEMORY_DEVICE);
2084a32e9c99SJunchao Zhang       if (m) PetscCheck(hA->rows_d, PETSC_COMM_SELF, PETSC_ERR_MEM, "HYPRE_TAlloc failed");
2085a32e9c99SJunchao Zhang     }
2086a32e9c99SJunchao Zhang     PetscCheck(len <= m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Too many rows in rows[]");
2087a32e9c99SJunchao Zhang     PetscStackCallExternalVoid("hypre_Memcpy", hypre_Memcpy(hA->rows_d, lrows, sizeof(PetscInt) * len, HYPRE_MEMORY_DEVICE, HYPRE_MEMORY_HOST));
2088a32e9c99SJunchao Zhang     lrows2 = hA->rows_d;
2089a32e9c99SJunchao Zhang   } else
2090a32e9c99SJunchao Zhang #endif
2091a32e9c99SJunchao Zhang   {
2092a32e9c99SJunchao Zhang     lrows2 = lrows;
2093a32e9c99SJunchao Zhang   }
2094a32e9c99SJunchao Zhang 
2095c69f721fSFande Kong   /* zero diagonal part */
2096a32e9c99SJunchao Zhang   PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr), len, lrows2, hdiag));
2097c69f721fSFande Kong   /* zero off-diagonal part */
2098a32e9c99SJunchao Zhang   PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr), len, lrows2, 0.0));
2099c69f721fSFande Kong 
21009566063dSJacob Faibussowitsch   PetscCall(PetscFree(lrows));
21013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2102c69f721fSFande Kong }
2103c69f721fSFande Kong 
2104d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_HYPRE(Mat mat, MatAssemblyType mode)
2105d71ae5a4SJacob Faibussowitsch {
2106c69f721fSFande Kong   PetscFunctionBegin;
21073ba16761SJacob Faibussowitsch   if (mat->nooffprocentries) PetscFunctionReturn(PETSC_SUCCESS);
2108c69f721fSFande Kong 
21099566063dSJacob Faibussowitsch   PetscCall(MatStashScatterBegin_Private(mat, &mat->stash, mat->rmap->range));
21103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2111c69f721fSFande Kong }
2112c69f721fSFande Kong 
2113d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
2114d71ae5a4SJacob Faibussowitsch {
2115c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
21162cf14000SStefano Zampini   HYPRE_Int           hnz;
2117c69f721fSFande Kong 
2118c69f721fSFande Kong   PetscFunctionBegin;
2119c69f721fSFande Kong   /* retrieve the internal matrix */
21209566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
2121c69f721fSFande Kong   /* call HYPRE API */
2122792fecdfSBarry Smith   PetscCallExternal(HYPRE_ParCSRMatrixGetRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v);
21232cf14000SStefano Zampini   if (nz) *nz = (PetscInt)hnz;
21243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2125c69f721fSFande Kong }
2126c69f721fSFande Kong 
2127d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
2128d71ae5a4SJacob Faibussowitsch {
2129c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
21302cf14000SStefano Zampini   HYPRE_Int           hnz;
2131c69f721fSFande Kong 
2132c69f721fSFande Kong   PetscFunctionBegin;
2133c69f721fSFande Kong   /* retrieve the internal matrix */
21349566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
2135c69f721fSFande Kong   /* call HYPRE API */
21362cf14000SStefano Zampini   hnz = nz ? (HYPRE_Int)(*nz) : 0;
2137792fecdfSBarry Smith   PetscCallExternal(HYPRE_ParCSRMatrixRestoreRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v);
21383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2139c69f721fSFande Kong }
2140c69f721fSFande Kong 
2141d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetValues_HYPRE(Mat A, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2142d71ae5a4SJacob Faibussowitsch {
214345b8d346SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
2144c69f721fSFande Kong   PetscInt   i;
21451d4906efSStefano Zampini 
2146c69f721fSFande Kong   PetscFunctionBegin;
21473ba16761SJacob Faibussowitsch   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2148c69f721fSFande Kong   /* Ignore negative row indices
2149c69f721fSFande Kong    * And negative column indices should be automatically ignored in hypre
2150c69f721fSFande Kong    * */
21512cf14000SStefano Zampini   for (i = 0; i < m; i++) {
21522cf14000SStefano Zampini     if (idxm[i] >= 0) {
21532cf14000SStefano Zampini       HYPRE_Int hn = (HYPRE_Int)n;
2154792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetValues, hA->ij, 1, &hn, (HYPRE_BigInt *)&idxm[i], (HYPRE_BigInt *)idxn, (HYPRE_Complex *)(v + i * n));
21552cf14000SStefano Zampini     }
21562cf14000SStefano Zampini   }
21573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2158c69f721fSFande Kong }
2159c69f721fSFande Kong 
2160d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_HYPRE(Mat A, MatOption op, PetscBool flg)
2161d71ae5a4SJacob Faibussowitsch {
2162ddbeb582SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
2163ddbeb582SStefano Zampini 
2164ddbeb582SStefano Zampini   PetscFunctionBegin;
2165c6698e78SStefano Zampini   switch (op) {
2166ddbeb582SStefano Zampini   case MAT_NO_OFF_PROC_ENTRIES:
216748a46eb9SPierre Jolivet     if (flg) PetscCallExternal(HYPRE_IJMatrixSetMaxOffProcElmts, hA->ij, 0);
2168ddbeb582SStefano Zampini     break;
2169651b1cf9SStefano Zampini   case MAT_IGNORE_OFF_PROC_ENTRIES:
2170651b1cf9SStefano Zampini     hA->donotstash = flg;
2171d71ae5a4SJacob Faibussowitsch     break;
2172d71ae5a4SJacob Faibussowitsch   default:
2173d71ae5a4SJacob Faibussowitsch     break;
2174ddbeb582SStefano Zampini   }
21753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2176ddbeb582SStefano Zampini }
2177c69f721fSFande Kong 
2178d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_HYPRE(Mat A, PetscViewer view)
2179d71ae5a4SJacob Faibussowitsch {
218045b8d346SStefano Zampini   PetscViewerFormat format;
218145b8d346SStefano Zampini 
218245b8d346SStefano Zampini   PetscFunctionBegin;
21839566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(view, &format));
21843ba16761SJacob Faibussowitsch   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(PETSC_SUCCESS);
218545b8d346SStefano Zampini   if (format != PETSC_VIEWER_NATIVE) {
21866ea7df73SStefano Zampini     Mat                 B;
21876ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
21886ea7df73SStefano Zampini     PetscErrorCode (*mview)(Mat, PetscViewer) = NULL;
21896ea7df73SStefano Zampini 
21909566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
21919566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(parcsr, MATAIJ, PETSC_USE_POINTER, &B));
21929566063dSJacob Faibussowitsch     PetscCall(MatGetOperation(B, MATOP_VIEW, (void (**)(void))&mview));
219328b400f6SJacob Faibussowitsch     PetscCheck(mview, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Missing view operation");
21949566063dSJacob Faibussowitsch     PetscCall((*mview)(B, view));
21959566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
219645b8d346SStefano Zampini   } else {
219745b8d346SStefano Zampini     Mat_HYPRE  *hA = (Mat_HYPRE *)A->data;
219845b8d346SStefano Zampini     PetscMPIInt size;
219945b8d346SStefano Zampini     PetscBool   isascii;
220045b8d346SStefano Zampini     const char *filename;
220145b8d346SStefano Zampini 
220245b8d346SStefano Zampini     /* HYPRE uses only text files */
22039566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERASCII, &isascii));
220428b400f6SJacob Faibussowitsch     PetscCheck(isascii, PetscObjectComm((PetscObject)view), PETSC_ERR_SUP, "PetscViewerType %s: native HYPRE format needs PETSCVIEWERASCII", ((PetscObject)view)->type_name);
22059566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileGetName(view, &filename));
2206792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixPrint, hA->ij, filename);
22079566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(hA->comm, &size));
220845b8d346SStefano Zampini     if (size > 1) {
22099566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(view, "Matrix files: %s.%05d ... %s.%05d\n", filename, 0, filename, size - 1));
221045b8d346SStefano Zampini     } else {
22119566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(view, "Matrix file: %s.%05d\n", filename, 0));
221245b8d346SStefano Zampini     }
221345b8d346SStefano Zampini   }
22143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
221545b8d346SStefano Zampini }
221645b8d346SStefano Zampini 
2217d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCopy_HYPRE(Mat A, Mat B, MatStructure str)
2218d71ae5a4SJacob Faibussowitsch {
2219465edc17SStefano Zampini   hypre_ParCSRMatrix *acsr, *bcsr;
2220465edc17SStefano Zampini 
2221465edc17SStefano Zampini   PetscFunctionBegin;
2222465edc17SStefano Zampini   if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) {
22239566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &acsr));
22249566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(B, &bcsr));
2225792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixCopy, acsr, bcsr, 1);
22269566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_SORTED_FULL, PETSC_TRUE)); /* "perfect" preallocation, so no need for hypre_AuxParCSRMatrixNeedAux */
22279566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
22289566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
2229465edc17SStefano Zampini   } else {
22309566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
2231465edc17SStefano Zampini   }
22323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2233465edc17SStefano Zampini }
2234465edc17SStefano Zampini 
2235d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_HYPRE(Mat A, Vec d)
2236d71ae5a4SJacob Faibussowitsch {
22376305df00SStefano Zampini   hypre_ParCSRMatrix *parcsr;
22386305df00SStefano Zampini   hypre_CSRMatrix    *dmat;
223939accc25SStefano Zampini   HYPRE_Complex      *a;
22406305df00SStefano Zampini   PetscBool           cong;
22416305df00SStefano Zampini 
22426305df00SStefano Zampini   PetscFunctionBegin;
22439566063dSJacob Faibussowitsch   PetscCall(MatHasCongruentLayouts(A, &cong));
224428b400f6SJacob Faibussowitsch   PetscCheck(cong, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only for square matrices with same local distributions of rows and columns");
22459566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
22466305df00SStefano Zampini   dmat = hypre_ParCSRMatrixDiag(parcsr);
22476305df00SStefano Zampini   if (dmat) {
224806977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
224906977982Sstefanozampini     HYPRE_MemoryLocation mem = hypre_CSRMatrixMemoryLocation(dmat);
225006977982Sstefanozampini #else
225106977982Sstefanozampini     HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST;
225206977982Sstefanozampini #endif
225306977982Sstefanozampini 
225406977982Sstefanozampini     if (mem != HYPRE_MEMORY_HOST) PetscCall(VecGetArrayWriteAndMemType(d, (PetscScalar **)&a, NULL));
225506977982Sstefanozampini     else PetscCall(VecGetArrayWrite(d, (PetscScalar **)&a));
225606977982Sstefanozampini     hypre_CSRMatrixExtractDiagonal(dmat, a, 0);
225706977982Sstefanozampini     if (mem != HYPRE_MEMORY_HOST) PetscCall(VecRestoreArrayWriteAndMemType(d, (PetscScalar **)&a));
225806977982Sstefanozampini     else PetscCall(VecRestoreArrayWrite(d, (PetscScalar **)&a));
22596305df00SStefano Zampini   }
22603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22616305df00SStefano Zampini }
22626305df00SStefano Zampini 
2263363d496dSStefano Zampini #include <petscblaslapack.h>
2264363d496dSStefano Zampini 
2265d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAXPY_HYPRE(Mat Y, PetscScalar a, Mat X, MatStructure str)
2266d71ae5a4SJacob Faibussowitsch {
2267363d496dSStefano Zampini   PetscFunctionBegin;
22686ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
22696ea7df73SStefano Zampini   {
22706ea7df73SStefano Zampini     Mat                 B;
22716ea7df73SStefano Zampini     hypre_ParCSRMatrix *x, *y, *z;
22726ea7df73SStefano Zampini 
22739566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(Y, &y));
22749566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(X, &x));
2275792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixAdd, 1.0, y, 1.0, x, &z);
22769566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(z, MATHYPRE, PETSC_OWN_POINTER, &B));
22779566063dSJacob Faibussowitsch     PetscCall(MatHeaderMerge(Y, &B));
22786ea7df73SStefano Zampini   }
22796ea7df73SStefano Zampini #else
2280363d496dSStefano Zampini   if (str == SAME_NONZERO_PATTERN) {
2281363d496dSStefano Zampini     hypre_ParCSRMatrix *x, *y;
2282363d496dSStefano Zampini     hypre_CSRMatrix    *xloc, *yloc;
2283363d496dSStefano Zampini     PetscInt            xnnz, ynnz;
228439accc25SStefano Zampini     HYPRE_Complex      *xarr, *yarr;
2285363d496dSStefano Zampini     PetscBLASInt        one = 1, bnz;
2286363d496dSStefano Zampini 
22879566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(Y, &y));
22889566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(X, &x));
2289363d496dSStefano Zampini 
2290363d496dSStefano Zampini     /* diagonal block */
2291363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixDiag(x);
2292363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixDiag(y);
2293363d496dSStefano Zampini     xnnz = 0;
2294363d496dSStefano Zampini     ynnz = 0;
2295363d496dSStefano Zampini     xarr = NULL;
2296363d496dSStefano Zampini     yarr = NULL;
2297363d496dSStefano Zampini     if (xloc) {
229839accc25SStefano Zampini       xarr = hypre_CSRMatrixData(xloc);
2299363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
2300363d496dSStefano Zampini     }
2301363d496dSStefano Zampini     if (yloc) {
230239accc25SStefano Zampini       yarr = hypre_CSRMatrixData(yloc);
2303363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
2304363d496dSStefano Zampini     }
230508401ef6SPierre Jolivet     PetscCheck(xnnz == ynnz, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Different number of nonzeros in diagonal block %" PetscInt_FMT " != %" PetscInt_FMT, xnnz, ynnz);
23069566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(xnnz, &bnz));
2307792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one));
2308363d496dSStefano Zampini 
2309363d496dSStefano Zampini     /* off-diagonal block */
2310363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixOffd(x);
2311363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixOffd(y);
2312363d496dSStefano Zampini     xnnz = 0;
2313363d496dSStefano Zampini     ynnz = 0;
2314363d496dSStefano Zampini     xarr = NULL;
2315363d496dSStefano Zampini     yarr = NULL;
2316363d496dSStefano Zampini     if (xloc) {
231739accc25SStefano Zampini       xarr = hypre_CSRMatrixData(xloc);
2318363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
2319363d496dSStefano Zampini     }
2320363d496dSStefano Zampini     if (yloc) {
232139accc25SStefano Zampini       yarr = hypre_CSRMatrixData(yloc);
2322363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
2323363d496dSStefano Zampini     }
232408401ef6SPierre 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);
23259566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(xnnz, &bnz));
2326792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one));
2327363d496dSStefano Zampini   } else if (str == SUBSET_NONZERO_PATTERN) {
23289566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic(Y, a, X, str));
2329363d496dSStefano Zampini   } else {
2330363d496dSStefano Zampini     Mat B;
2331363d496dSStefano Zampini 
23329566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic_Preallocate(Y, X, &B));
23339566063dSJacob Faibussowitsch     PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str));
23349566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(Y, &B));
2335363d496dSStefano Zampini   }
23366ea7df73SStefano Zampini #endif
23373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2338363d496dSStefano Zampini }
2339363d496dSStefano Zampini 
23402c4ab24aSJunchao Zhang static PetscErrorCode MatDuplicate_HYPRE(Mat A, MatDuplicateOption op, Mat *B)
23412c4ab24aSJunchao Zhang {
23422c4ab24aSJunchao Zhang   hypre_ParCSRMatrix *parcsr = NULL;
23432c4ab24aSJunchao Zhang   PetscCopyMode       cpmode;
23442c4ab24aSJunchao Zhang   Mat_HYPRE          *hA;
23452c4ab24aSJunchao Zhang 
23462c4ab24aSJunchao Zhang   PetscFunctionBegin;
23472c4ab24aSJunchao Zhang   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
23482c4ab24aSJunchao Zhang   if (op == MAT_DO_NOT_COPY_VALUES || op == MAT_SHARE_NONZERO_PATTERN) {
23492c4ab24aSJunchao Zhang     parcsr = hypre_ParCSRMatrixClone(parcsr, 0);
23502c4ab24aSJunchao Zhang     cpmode = PETSC_OWN_POINTER;
23512c4ab24aSJunchao Zhang   } else {
23522c4ab24aSJunchao Zhang     cpmode = PETSC_COPY_VALUES;
23532c4ab24aSJunchao Zhang   }
23542c4ab24aSJunchao Zhang   PetscCall(MatCreateFromParCSR(parcsr, MATHYPRE, cpmode, B));
23552c4ab24aSJunchao Zhang   hA = (Mat_HYPRE *)A->data;
23562c4ab24aSJunchao Zhang   if (hA->cooMat) {
235706977982Sstefanozampini     Mat_HYPRE *hB = (Mat_HYPRE *)((*B)->data);
2358b73e3080SStefano Zampini     op            = (op == MAT_DO_NOT_COPY_VALUES) ? op : MAT_COPY_VALUES;
2359b73e3080SStefano Zampini     /* Cannot simply increase the reference count of hA->cooMat, since B needs to share cooMat's data array */
236006977982Sstefanozampini     PetscCall(MatDuplicate(hA->cooMat, op, &hB->cooMat));
236106977982Sstefanozampini     PetscCall(MatHYPRE_AttachCOOMat(*B));
23622c4ab24aSJunchao Zhang   }
23632c4ab24aSJunchao Zhang   PetscFunctionReturn(PETSC_SUCCESS);
23642c4ab24aSJunchao Zhang }
23652c4ab24aSJunchao Zhang 
2366d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetPreallocationCOO_HYPRE(Mat mat, PetscCount coo_n, PetscInt coo_i[], PetscInt coo_j[])
2367d71ae5a4SJacob Faibussowitsch {
236806977982Sstefanozampini   Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data;
23695fbaff96SJunchao Zhang 
23705fbaff96SJunchao Zhang   PetscFunctionBegin;
2371651b1cf9SStefano Zampini   /* Build an agent matrix cooMat with AIJ format
23725fbaff96SJunchao 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.
23735fbaff96SJunchao Zhang    */
237406977982Sstefanozampini   PetscCall(MatHYPRE_CreateCOOMat(mat));
237506977982Sstefanozampini   PetscCall(MatSetOption(hmat->cooMat, MAT_IGNORE_OFF_PROC_ENTRIES, hmat->donotstash));
237606977982Sstefanozampini   PetscCall(MatSetOption(hmat->cooMat, MAT_NO_OFF_PROC_ENTRIES, mat->nooffprocentries));
2377651b1cf9SStefano Zampini 
2378651b1cf9SStefano Zampini   /* MatSetPreallocationCOO_SeqAIJ and MatSetPreallocationCOO_MPIAIJ uses this specific
2379651b1cf9SStefano Zampini      name to automatically put the diagonal entries first */
238006977982Sstefanozampini   PetscCall(PetscObjectSetName((PetscObject)hmat->cooMat, "_internal_COO_mat_for_hypre"));
238106977982Sstefanozampini   PetscCall(MatSetPreallocationCOO(hmat->cooMat, coo_n, coo_i, coo_j));
238206977982Sstefanozampini   hmat->cooMat->assembled = PETSC_TRUE;
23835fbaff96SJunchao Zhang 
23845fbaff96SJunchao Zhang   /* Copy the sparsity pattern from cooMat to hypre IJMatrix hmat->ij */
23855fbaff96SJunchao Zhang   PetscCall(MatSetOption(mat, MAT_SORTED_FULL, PETSC_TRUE));
238606977982Sstefanozampini   PetscCall(MatHYPRE_CreateFromMat(hmat->cooMat, hmat));      /* Create hmat->ij and preallocate it */
238706977982Sstefanozampini   PetscCall(MatHYPRE_IJMatrixCopyIJ(hmat->cooMat, hmat->ij)); /* Copy A's (i,j) to hmat->ij */
23885fbaff96SJunchao Zhang 
23895fbaff96SJunchao Zhang   mat->preallocated = PETSC_TRUE;
23905fbaff96SJunchao Zhang   PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
23915fbaff96SJunchao Zhang   PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); /* Migrate mat to device if it is bound to. Hypre builds its own SpMV context here */
23925fbaff96SJunchao Zhang 
23932c4ab24aSJunchao Zhang   /* Attach cooMat to mat */
239406977982Sstefanozampini   PetscCall(MatHYPRE_AttachCOOMat(mat));
23953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23965fbaff96SJunchao Zhang }
23975fbaff96SJunchao Zhang 
2398d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesCOO_HYPRE(Mat mat, const PetscScalar v[], InsertMode imode)
2399d71ae5a4SJacob Faibussowitsch {
24005fbaff96SJunchao Zhang   Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data;
24015fbaff96SJunchao Zhang 
24025fbaff96SJunchao Zhang   PetscFunctionBegin;
2403b73e3080SStefano Zampini   PetscCheck(hmat->cooMat, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet");
24045fbaff96SJunchao Zhang   PetscCall(MatSetValuesCOO(hmat->cooMat, v, imode));
2405651b1cf9SStefano Zampini   PetscCall(MatViewFromOptions(hmat->cooMat, (PetscObject)mat, "-cooMat_view"));
24063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24075fbaff96SJunchao Zhang }
24085fbaff96SJunchao Zhang 
240903db1824SAlex Lindsay static PetscErrorCode MatGetCurrentMemType_HYPRE(Mat A, PetscMemType *m)
241003db1824SAlex Lindsay {
241103db1824SAlex Lindsay   PetscBool petsconcpu;
241203db1824SAlex Lindsay 
241303db1824SAlex Lindsay   PetscFunctionBegin;
241403db1824SAlex Lindsay   PetscCall(MatBoundToCPU(A, &petsconcpu));
241503db1824SAlex Lindsay   if (PetscDefined(HAVE_HYPRE_DEVICE)) {
241603db1824SAlex Lindsay     PetscBool            hypreoncpu;
241703db1824SAlex Lindsay     HYPRE_MemoryLocation hyprememloc;
241803db1824SAlex Lindsay 
241903db1824SAlex Lindsay     PetscCallExternal(HYPRE_GetMemoryLocation, &hyprememloc);
242003db1824SAlex Lindsay     PetscCheck(hyprememloc != HYPRE_MEMORY_UNDEFINED, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "hypre memory shold already be initialized");
242103db1824SAlex Lindsay     hypreoncpu = hyprememloc == HYPRE_MEMORY_HOST ? PETSC_TRUE : PETSC_FALSE;
242203db1824SAlex Lindsay     PetscCheck(petsconcpu == hypreoncpu, PetscObjectComm((PetscObject)A), PETSC_ERR_USER_INPUT, "PETSc and hypre memory location do not agree. This may happen if using multiple hypre matrices with mismatchiing memory locations");
242303db1824SAlex Lindsay   }
242403db1824SAlex Lindsay   *m = petsconcpu ? PETSC_MEMTYPE_HOST : PETSC_MEMTYPE_DEVICE;
242503db1824SAlex Lindsay   PetscFunctionReturn(PETSC_SUCCESS);
242603db1824SAlex Lindsay }
242703db1824SAlex Lindsay 
2428a055b5aaSBarry Smith /*MC
24292ef1f0ffSBarry Smith    MATHYPRE - "hypre" - A matrix type to be used for sequential and parallel sparse matrices
2430a055b5aaSBarry Smith           based on the hypre IJ interface.
2431a055b5aaSBarry Smith 
2432a055b5aaSBarry Smith    Level: intermediate
2433a055b5aaSBarry Smith 
24341cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatHYPRESetPreallocation`
2435a055b5aaSBarry Smith M*/
2436d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_HYPRE(Mat B)
2437d71ae5a4SJacob Faibussowitsch {
243863c07aadSStefano Zampini   Mat_HYPRE *hB;
2439a9e6c71bSAlex Lindsay #if defined(PETSC_HAVE_HYPRE_DEVICE)
2440a9e6c71bSAlex Lindsay   HYPRE_MemoryLocation memory_location;
2441a9e6c71bSAlex Lindsay #endif
244263c07aadSStefano Zampini 
244363c07aadSStefano Zampini   PetscFunctionBegin;
2444a9e6c71bSAlex Lindsay   PetscHYPREInitialize();
24454dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&hB));
24466ea7df73SStefano Zampini 
2447978814f1SStefano Zampini   hB->inner_free      = PETSC_TRUE;
2448651b1cf9SStefano Zampini   hB->array_available = PETSC_TRUE;
2449978814f1SStefano Zampini 
245063c07aadSStefano Zampini   B->data = (void *)hB;
245163c07aadSStefano Zampini 
24529566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(B->ops, sizeof(struct _MatOps)));
245363c07aadSStefano Zampini   B->ops->mult                  = MatMult_HYPRE;
245463c07aadSStefano Zampini   B->ops->multtranspose         = MatMultTranspose_HYPRE;
2455414bd5c3SStefano Zampini   B->ops->multadd               = MatMultAdd_HYPRE;
2456414bd5c3SStefano Zampini   B->ops->multtransposeadd      = MatMultTransposeAdd_HYPRE;
245763c07aadSStefano Zampini   B->ops->setup                 = MatSetUp_HYPRE;
245863c07aadSStefano Zampini   B->ops->destroy               = MatDestroy_HYPRE;
245963c07aadSStefano Zampini   B->ops->assemblyend           = MatAssemblyEnd_HYPRE;
2460c69f721fSFande Kong   B->ops->assemblybegin         = MatAssemblyBegin_HYPRE;
2461d975228cSstefano_zampini   B->ops->setvalues             = MatSetValues_HYPRE;
246268ec7858SStefano Zampini   B->ops->missingdiagonal       = MatMissingDiagonal_HYPRE;
246368ec7858SStefano Zampini   B->ops->scale                 = MatScale_HYPRE;
246468ec7858SStefano Zampini   B->ops->zerorowscolumns       = MatZeroRowsColumns_HYPRE;
2465c69f721fSFande Kong   B->ops->zeroentries           = MatZeroEntries_HYPRE;
2466c69f721fSFande Kong   B->ops->zerorows              = MatZeroRows_HYPRE;
2467c69f721fSFande Kong   B->ops->getrow                = MatGetRow_HYPRE;
2468c69f721fSFande Kong   B->ops->restorerow            = MatRestoreRow_HYPRE;
2469c69f721fSFande Kong   B->ops->getvalues             = MatGetValues_HYPRE;
2470ddbeb582SStefano Zampini   B->ops->setoption             = MatSetOption_HYPRE;
247145b8d346SStefano Zampini   B->ops->duplicate             = MatDuplicate_HYPRE;
2472465edc17SStefano Zampini   B->ops->copy                  = MatCopy_HYPRE;
247345b8d346SStefano Zampini   B->ops->view                  = MatView_HYPRE;
24746305df00SStefano Zampini   B->ops->getdiagonal           = MatGetDiagonal_HYPRE;
2475363d496dSStefano Zampini   B->ops->axpy                  = MatAXPY_HYPRE;
24764222ddf1SHong Zhang   B->ops->productsetfromoptions = MatProductSetFromOptions_HYPRE;
247703db1824SAlex Lindsay   B->ops->getcurrentmemtype     = MatGetCurrentMemType_HYPRE;
24786ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
24796ea7df73SStefano Zampini   B->ops->bindtocpu = MatBindToCPU_HYPRE;
2480a9e6c71bSAlex Lindsay   /* Get hypre's default memory location. Users can control this using the corresponding HYPRE_SetMemoryLocation API */
2481a9e6c71bSAlex Lindsay   PetscCallExternal(HYPRE_GetMemoryLocation, &memory_location);
2482a9e6c71bSAlex Lindsay   B->boundtocpu = (memory_location == HYPRE_MEMORY_HOST) ? PETSC_TRUE : PETSC_FALSE;
24836ea7df73SStefano Zampini #endif
248445b8d346SStefano Zampini 
248545b8d346SStefano Zampini   /* build cache for off array entries formed */
24869566063dSJacob Faibussowitsch   PetscCall(MatStashCreate_Private(PetscObjectComm((PetscObject)B), 1, &B->stash));
248763c07aadSStefano Zampini 
24889566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)B), &hB->comm));
24899566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRE));
24909566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_aij_C", MatConvert_HYPRE_AIJ));
24919566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_is_C", MatConvert_HYPRE_IS));
24929566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_hypre_C", MatProductSetFromOptions_HYPRE));
24939566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaij_hypre_C", MatProductSetFromOptions_HYPRE));
24949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPRESetPreallocation_C", MatHYPRESetPreallocation_HYPRE));
24959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPREGetParCSR_C", MatHYPREGetParCSR_HYPRE));
24965fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_HYPRE));
24975fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetValuesCOO_C", MatSetValuesCOO_HYPRE));
24986ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
24996ea7df73SStefano Zampini   #if defined(HYPRE_USING_HIP)
250006977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijhipsparse_hypre_C", MatProductSetFromOptions_HYPRE));
250106977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaijhipsparse_hypre_C", MatProductSetFromOptions_HYPRE));
25029566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP));
25039566063dSJacob Faibussowitsch   PetscCall(MatSetVecType(B, VECHIP));
25046ea7df73SStefano Zampini   #endif
25056ea7df73SStefano Zampini   #if defined(HYPRE_USING_CUDA)
250606977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijcusparse_hypre_C", MatProductSetFromOptions_HYPRE));
250706977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaijcusparse_hypre_C", MatProductSetFromOptions_HYPRE));
25089566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
25099566063dSJacob Faibussowitsch   PetscCall(MatSetVecType(B, VECCUDA));
25106ea7df73SStefano Zampini   #endif
25116ea7df73SStefano Zampini #endif
25123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
251363c07aadSStefano Zampini }
2514