xref: /petsc/src/mat/impls/hypre/mhypre.c (revision e64794e4e0b181328b5d79973a03ee824bee75ee)
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;
423*e64794e4SJunchao Zhang   #elif defined(HYPRE_USING_SYCL) && defined(PETSC_HAVE_KOKKOS_KERNELS)
424*e64794e4SJunchao Zhang     matType = MATAIJKOKKOS;
42506977982Sstefanozampini   #else
426*e64794e4SJunchao Zhang     SETERRQ(comm, PETSC_ERR_SUP, "No HYPRE device available. Suggest re-installing with Kokkos Kernels");
42706977982Sstefanozampini   #endif
428b73e3080SStefano Zampini   }
42906977982Sstefanozampini #endif
43006977982Sstefanozampini 
43106977982Sstefanozampini   /* Do COO preallocation through cooMat */
43206977982Sstefanozampini   PetscCall(MatHYPRE_DestroyCOOMat(mat));
43306977982Sstefanozampini   PetscCall(MatCreate(comm, &hmat->cooMat));
43406977982Sstefanozampini   PetscCall(MatSetType(hmat->cooMat, matType));
43506977982Sstefanozampini   PetscCall(MatSetLayouts(hmat->cooMat, rmap, cmap));
43606977982Sstefanozampini 
43706977982Sstefanozampini   /* allocate local matrices if needed */
43806977982Sstefanozampini   PetscCall(MatMPIAIJSetPreallocation(hmat->cooMat, 0, NULL, 0, NULL));
43906977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
44006977982Sstefanozampini }
44106977982Sstefanozampini 
44206977982Sstefanozampini /* Attach cooMat data array to hypre matrix.
44306977982Sstefanozampini    When AIJCUPMSPARSE will support raw device pointers and not THRUSTARRAY
44406977982Sstefanozampini    we should swap the arrays: i.e., attach hypre matrix array to cooMat
44506977982Sstefanozampini    This is because hypre should be in charge of handling the memory,
44606977982Sstefanozampini    cooMat is only a way to reuse PETSc COO code.
44706977982Sstefanozampini    attaching the memory will then be done at MatSetValuesCOO time and it will dynamically
44806977982Sstefanozampini    support hypre matrix migrating to host.
44906977982Sstefanozampini */
45006977982Sstefanozampini static PetscErrorCode MatHYPRE_AttachCOOMat(Mat mat)
45106977982Sstefanozampini {
45206977982Sstefanozampini   Mat_HYPRE           *hmat = (Mat_HYPRE *)mat->data;
45306977982Sstefanozampini   hypre_CSRMatrix     *diag, *offd;
45406977982Sstefanozampini   hypre_ParCSRMatrix  *parCSR;
45506977982Sstefanozampini   HYPRE_MemoryLocation hmem = HYPRE_MEMORY_HOST;
45606977982Sstefanozampini   PetscMemType         pmem;
45706977982Sstefanozampini   Mat                  A, B;
45806977982Sstefanozampini   PetscScalar         *a;
45906977982Sstefanozampini   PetscMPIInt          size;
46006977982Sstefanozampini   MPI_Comm             comm;
46106977982Sstefanozampini 
46206977982Sstefanozampini   PetscFunctionBegin;
46306977982Sstefanozampini   PetscCheck(hmat->cooMat, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet");
46406977982Sstefanozampini   if (hmat->cooMatAttached) PetscFunctionReturn(PETSC_SUCCESS);
46506977982Sstefanozampini   PetscCheck(hmat->cooMat->preallocated, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix is not preallocated");
46606977982Sstefanozampini   PetscCall(PetscObjectSetName((PetscObject)hmat->cooMat, "_internal_COO_mat_for_hypre"));
46706977982Sstefanozampini   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
46806977982Sstefanozampini   PetscCallMPI(MPI_Comm_size(comm, &size));
46906977982Sstefanozampini 
47006977982Sstefanozampini   /* Alias cooMat's data array to IJMatrix's */
47106977982Sstefanozampini   PetscCallExternal(HYPRE_IJMatrixGetObject, hmat->ij, (void **)&parCSR);
47206977982Sstefanozampini   diag = hypre_ParCSRMatrixDiag(parCSR);
47306977982Sstefanozampini   offd = hypre_ParCSRMatrixOffd(parCSR);
47406977982Sstefanozampini 
47506977982Sstefanozampini   A = (size == 1) ? hmat->cooMat : ((Mat_MPIAIJ *)hmat->cooMat->data)->A;
47606977982Sstefanozampini   B = (size == 1) ? NULL : ((Mat_MPIAIJ *)hmat->cooMat->data)->B;
47706977982Sstefanozampini 
47806977982Sstefanozampini   PetscCall(PetscObjectSetName((PetscObject)A, "_internal_COO_mat_for_hypre"));
47906977982Sstefanozampini   hmem = hypre_CSRMatrixMemoryLocation(diag);
48006977982Sstefanozampini   PetscCall(MatSeqAIJGetCSRAndMemType(A, NULL, NULL, &a, &pmem));
48106977982Sstefanozampini   PetscAssert((PetscMemTypeHost(pmem) && hmem == HYPRE_MEMORY_HOST) || (PetscMemTypeDevice(pmem) && hmem == HYPRE_MEMORY_DEVICE), comm, PETSC_ERR_PLIB, "PETSc and hypre's memory types mismatch");
48206977982Sstefanozampini   PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(diag), hmem));
48306977982Sstefanozampini   hypre_CSRMatrixData(diag)     = (HYPRE_Complex *)a;
48406977982Sstefanozampini   hypre_CSRMatrixOwnsData(diag) = 0; /* Take ownership of (j,a) away from hypre. As a result, we need to free them on our own */
48506977982Sstefanozampini 
48606977982Sstefanozampini   if (B) {
48706977982Sstefanozampini     hmem = hypre_CSRMatrixMemoryLocation(offd);
48806977982Sstefanozampini     PetscCall(MatSeqAIJGetCSRAndMemType(B, NULL, NULL, &a, &pmem));
48906977982Sstefanozampini     PetscAssert((PetscMemTypeHost(pmem) && hmem == HYPRE_MEMORY_HOST) || (PetscMemTypeDevice(pmem) && hmem == HYPRE_MEMORY_DEVICE), comm, PETSC_ERR_PLIB, "PETSc and hypre's memory types mismatch");
49006977982Sstefanozampini     PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(offd), hmem));
49106977982Sstefanozampini     hypre_CSRMatrixData(offd)     = (HYPRE_Complex *)a;
49206977982Sstefanozampini     hypre_CSRMatrixOwnsData(offd) = 0;
49306977982Sstefanozampini   }
49406977982Sstefanozampini   hmat->cooMatAttached = PETSC_TRUE;
49506977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
49606977982Sstefanozampini }
49706977982Sstefanozampini 
4981c265611SJunchao Zhang // Build COO's coordinate list i[], j[] based on CSR's i[], j[] arrays and the number of local rows 'n'
49906977982Sstefanozampini static PetscErrorCode CSRtoCOO_Private(PetscInt n, const PetscInt ii[], const PetscInt jj[], PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j)
50006977982Sstefanozampini {
50106977982Sstefanozampini   PetscInt *cooi, *cooj;
50206977982Sstefanozampini 
50306977982Sstefanozampini   PetscFunctionBegin;
50406977982Sstefanozampini   *ncoo = ii[n];
50506977982Sstefanozampini   PetscCall(PetscMalloc2(*ncoo, &cooi, *ncoo, &cooj));
50606977982Sstefanozampini   for (PetscInt i = 0; i < n; i++) {
50706977982Sstefanozampini     for (PetscInt j = ii[i]; j < ii[i + 1]; j++) cooi[j] = i;
50806977982Sstefanozampini   }
50906977982Sstefanozampini   PetscCall(PetscArraycpy(cooj, jj, *ncoo));
51006977982Sstefanozampini   *coo_i = cooi;
51106977982Sstefanozampini   *coo_j = cooj;
51206977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
51306977982Sstefanozampini }
51406977982Sstefanozampini 
5151c265611SJunchao Zhang // Similar to CSRtoCOO_Private, but the CSR's i[], j[] are of type HYPRE_Int
51606977982Sstefanozampini static PetscErrorCode CSRtoCOO_HYPRE_Int_Private(PetscInt n, const HYPRE_Int ii[], const HYPRE_Int jj[], PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j)
51706977982Sstefanozampini {
51806977982Sstefanozampini   PetscInt *cooi, *cooj;
51906977982Sstefanozampini 
52006977982Sstefanozampini   PetscFunctionBegin;
52106977982Sstefanozampini   *ncoo = ii[n];
52206977982Sstefanozampini   PetscCall(PetscMalloc2(*ncoo, &cooi, *ncoo, &cooj));
52306977982Sstefanozampini   for (PetscInt i = 0; i < n; i++) {
52406977982Sstefanozampini     for (HYPRE_Int j = ii[i]; j < ii[i + 1]; j++) cooi[j] = i;
52506977982Sstefanozampini   }
52606977982Sstefanozampini   for (PetscCount i = 0; i < *ncoo; i++) cooj[i] = jj[i];
52706977982Sstefanozampini   *coo_i = cooi;
52806977982Sstefanozampini   *coo_j = cooj;
52906977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
53006977982Sstefanozampini }
53106977982Sstefanozampini 
5321c265611SJunchao 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
53306977982Sstefanozampini static PetscErrorCode MatSeqAIJGetCOO_Private(Mat A, PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j)
53406977982Sstefanozampini {
53506977982Sstefanozampini   PetscInt        n;
53606977982Sstefanozampini   const PetscInt *ii, *jj;
53706977982Sstefanozampini   PetscBool       done;
53806977982Sstefanozampini 
53906977982Sstefanozampini   PetscFunctionBegin;
54006977982Sstefanozampini   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &done));
54106977982Sstefanozampini   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Failure for MatGetRowIJ");
54206977982Sstefanozampini   PetscCall(CSRtoCOO_Private(n, ii, jj, ncoo, coo_i, coo_j));
54306977982Sstefanozampini   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &done));
54406977982Sstefanozampini   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Failure for MatRestoreRowIJ");
54506977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
54606977982Sstefanozampini }
54706977982Sstefanozampini 
5481c265611SJunchao Zhang // Build a COO data structure for the hypreCSRMatrix, as if the nonzeros are laid out in the same order as in the hypreCSRMatrix
54906977982Sstefanozampini static PetscErrorCode hypreCSRMatrixGetCOO_Private(hypre_CSRMatrix *A, PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j)
55006977982Sstefanozampini {
55106977982Sstefanozampini   PetscInt             n = hypre_CSRMatrixNumRows(A);
55206977982Sstefanozampini   HYPRE_Int           *ii, *jj;
55306977982Sstefanozampini   HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST;
55406977982Sstefanozampini 
55506977982Sstefanozampini   PetscFunctionBegin;
55606977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
55706977982Sstefanozampini   mem = hypre_CSRMatrixMemoryLocation(A);
55806977982Sstefanozampini   if (mem != HYPRE_MEMORY_HOST) {
55906977982Sstefanozampini     PetscCount nnz = hypre_CSRMatrixNumNonzeros(A);
56006977982Sstefanozampini     PetscCall(PetscMalloc2(n + 1, &ii, nnz, &jj));
56106977982Sstefanozampini     hypre_TMemcpy(ii, hypre_CSRMatrixI(A), HYPRE_Int, n + 1, HYPRE_MEMORY_HOST, mem);
56206977982Sstefanozampini     hypre_TMemcpy(jj, hypre_CSRMatrixJ(A), HYPRE_Int, nnz, HYPRE_MEMORY_HOST, mem);
56306977982Sstefanozampini   } else {
56406977982Sstefanozampini #else
56506977982Sstefanozampini   {
56606977982Sstefanozampini #endif
56706977982Sstefanozampini     ii = hypre_CSRMatrixI(A);
56806977982Sstefanozampini     jj = hypre_CSRMatrixJ(A);
56906977982Sstefanozampini   }
57006977982Sstefanozampini   PetscCall(CSRtoCOO_HYPRE_Int_Private(n, ii, jj, ncoo, coo_i, coo_j));
57106977982Sstefanozampini   if (mem != HYPRE_MEMORY_HOST) PetscCall(PetscFree2(ii, jj));
57206977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
57306977982Sstefanozampini }
57406977982Sstefanozampini 
57506977982Sstefanozampini static PetscErrorCode MatSetValuesCOOFromCSRMatrix_Private(Mat A, hypre_CSRMatrix *H)
57606977982Sstefanozampini {
57706977982Sstefanozampini   PetscBool            iscpu = PETSC_TRUE;
57806977982Sstefanozampini   PetscScalar         *a;
57906977982Sstefanozampini   HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST;
58006977982Sstefanozampini 
58106977982Sstefanozampini   PetscFunctionBegin;
58206977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
58306977982Sstefanozampini   mem = hypre_CSRMatrixMemoryLocation(H);
58406977982Sstefanozampini   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATSEQAIJ, &iscpu));
58506977982Sstefanozampini #endif
58606977982Sstefanozampini   if (iscpu && mem != HYPRE_MEMORY_HOST) {
58706977982Sstefanozampini     PetscCount nnz = hypre_CSRMatrixNumNonzeros(H);
58806977982Sstefanozampini     PetscCall(PetscMalloc1(nnz, &a));
58906977982Sstefanozampini     hypre_TMemcpy(a, hypre_CSRMatrixData(H), PetscScalar, nnz, HYPRE_MEMORY_HOST, mem);
59006977982Sstefanozampini   } else {
59106977982Sstefanozampini     a = (PetscScalar *)hypre_CSRMatrixData(H);
59206977982Sstefanozampini   }
59306977982Sstefanozampini   PetscCall(MatSetValuesCOO(A, a, INSERT_VALUES));
59406977982Sstefanozampini   if (iscpu && mem != HYPRE_MEMORY_HOST) PetscCall(PetscFree(a));
595b73e3080SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
596b73e3080SStefano Zampini }
597b73e3080SStefano Zampini 
598b73e3080SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType type, MatReuse reuse, Mat *B)
599b73e3080SStefano Zampini {
600b73e3080SStefano Zampini   MPI_Comm     comm = PetscObjectComm((PetscObject)A);
60106977982Sstefanozampini   Mat          M = NULL, dH = NULL, oH = NULL, dA = NULL, oA = NULL;
602d7185485SAlex Lindsay   PetscBool    ismpiaij, issbaij, isbaij, boundtocpu = PETSC_TRUE;
603b73e3080SStefano Zampini   Mat_HYPRE   *hA;
604d7185485SAlex Lindsay   PetscMemType memtype = PETSC_MEMTYPE_HOST;
605b73e3080SStefano Zampini 
606b73e3080SStefano Zampini   PetscFunctionBegin;
607d7185485SAlex Lindsay   if (PetscDefined(HAVE_HYPRE_DEVICE)) {
608d7185485SAlex Lindsay     PetscCall(MatGetCurrentMemType(A, &memtype));
609d7185485SAlex Lindsay     PetscHYPREInitialize();
610d7185485SAlex Lindsay     boundtocpu = PetscMemTypeHost(memtype) ? PETSC_TRUE : PETSC_FALSE;
611d7185485SAlex Lindsay     PetscCallExternal(HYPRE_SetMemoryLocation, boundtocpu ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE);
612d7185485SAlex Lindsay   }
613d7185485SAlex Lindsay 
614b73e3080SStefano Zampini   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &issbaij, MATSEQSBAIJ, MATMPIBAIJ, ""));
615b73e3080SStefano Zampini   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &isbaij, MATSEQBAIJ, MATMPIBAIJ, ""));
616b73e3080SStefano Zampini   if (isbaij || issbaij) { /* handle BAIJ and SBAIJ */
617b73e3080SStefano Zampini     PetscBool ismpi;
618b73e3080SStefano Zampini     MatType   newtype;
619b73e3080SStefano Zampini 
620b73e3080SStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &ismpi, MATMPISBAIJ, MATMPIBAIJ, ""));
621b73e3080SStefano Zampini     newtype = ismpi ? MATMPIAIJ : MATSEQAIJ;
62263c07aadSStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
623b73e3080SStefano Zampini       PetscCall(MatConvert(*B, newtype, MAT_INPLACE_MATRIX, B));
624b73e3080SStefano Zampini       PetscCall(MatConvert(A, newtype, MAT_REUSE_MATRIX, B));
625b73e3080SStefano Zampini       PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B));
626b73e3080SStefano Zampini     } else if (reuse == MAT_INITIAL_MATRIX) {
627b73e3080SStefano Zampini       PetscCall(MatConvert(A, newtype, MAT_INITIAL_MATRIX, B));
628b73e3080SStefano Zampini       PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B));
62963c07aadSStefano Zampini     } else {
630b73e3080SStefano Zampini       PetscCall(MatConvert(A, newtype, MAT_INPLACE_MATRIX, &A));
631b73e3080SStefano Zampini       PetscCall(MatConvert(A, MATHYPRE, MAT_INPLACE_MATRIX, &A));
632b73e3080SStefano Zampini     }
633d7185485SAlex Lindsay #if defined(PETSC_HAVE_DEVICE)
634d7185485SAlex Lindsay     (*B)->boundtocpu = boundtocpu;
635d7185485SAlex Lindsay #endif
636b73e3080SStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
637b73e3080SStefano Zampini   }
63806977982Sstefanozampini 
63906977982Sstefanozampini   dA = A;
640b73e3080SStefano Zampini   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
641b73e3080SStefano Zampini   if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(A, &dA, &oA, NULL));
64206977982Sstefanozampini 
643b73e3080SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
64406977982Sstefanozampini     PetscCount coo_n;
64506977982Sstefanozampini     PetscInt  *coo_i, *coo_j;
64606977982Sstefanozampini 
6479566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm, &M));
6489566063dSJacob Faibussowitsch     PetscCall(MatSetType(M, MATHYPRE));
6499566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(M, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
650b73e3080SStefano Zampini     PetscCall(MatSetOption(M, MAT_SORTED_FULL, PETSC_TRUE));
651b73e3080SStefano Zampini     PetscCall(MatSetOption(M, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE));
652b73e3080SStefano Zampini 
653b73e3080SStefano Zampini     hA = (Mat_HYPRE *)M->data;
65406977982Sstefanozampini     PetscCall(MatHYPRE_CreateFromMat(A, hA));
65506977982Sstefanozampini     PetscCall(MatHYPRE_IJMatrixCopyIJ(A, hA->ij));
65606977982Sstefanozampini 
65706977982Sstefanozampini     PetscCall(MatHYPRE_CreateCOOMat(M));
65806977982Sstefanozampini 
65906977982Sstefanozampini     dH = hA->cooMat;
66006977982Sstefanozampini     PetscCall(PetscObjectBaseTypeCompare((PetscObject)hA->cooMat, MATMPIAIJ, &ismpiaij));
66106977982Sstefanozampini     if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(hA->cooMat, &dH, &oH, NULL));
66206977982Sstefanozampini 
66306977982Sstefanozampini     PetscCall(PetscObjectSetName((PetscObject)dH, "_internal_COO_mat_for_hypre"));
66406977982Sstefanozampini     PetscCall(MatSeqAIJGetCOO_Private(dA, &coo_n, &coo_i, &coo_j));
66506977982Sstefanozampini     PetscCall(MatSetPreallocationCOO(dH, coo_n, coo_i, coo_j));
66606977982Sstefanozampini     PetscCall(PetscFree2(coo_i, coo_j));
66706977982Sstefanozampini     if (oH) {
66806977982Sstefanozampini       PetscCall(PetscLayoutDestroy(&oH->cmap));
66906977982Sstefanozampini       PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)oH), oA->cmap->n, oA->cmap->n, 1, &oH->cmap));
67006977982Sstefanozampini       PetscCall(MatSeqAIJGetCOO_Private(oA, &coo_n, &coo_i, &coo_j));
67106977982Sstefanozampini       PetscCall(MatSetPreallocationCOO(oH, coo_n, coo_i, coo_j));
67206977982Sstefanozampini       PetscCall(PetscFree2(coo_i, coo_j));
67306977982Sstefanozampini     }
67406977982Sstefanozampini     hA->cooMat->assembled = PETSC_TRUE;
67506977982Sstefanozampini 
676b73e3080SStefano Zampini     M->preallocated = PETSC_TRUE;
67706977982Sstefanozampini     PetscCall(MatAssemblyBegin(M, MAT_FINAL_ASSEMBLY));
67806977982Sstefanozampini     PetscCall(MatAssemblyEnd(M, MAT_FINAL_ASSEMBLY));
67906977982Sstefanozampini 
68006977982Sstefanozampini     PetscCall(MatHYPRE_AttachCOOMat(M));
68184d4e069SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) *B = M;
682b73e3080SStefano Zampini   } else M = *B;
683b73e3080SStefano Zampini 
684b73e3080SStefano Zampini   hA = (Mat_HYPRE *)M->data;
68506977982Sstefanozampini   PetscCheck(hA->cooMat, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet");
68606977982Sstefanozampini 
68706977982Sstefanozampini   dH = hA->cooMat;
68806977982Sstefanozampini   PetscCall(PetscObjectBaseTypeCompare((PetscObject)hA->cooMat, MATMPIAIJ, &ismpiaij));
68906977982Sstefanozampini   if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(hA->cooMat, &dH, &oH, NULL));
69006977982Sstefanozampini 
69106977982Sstefanozampini   PetscScalar *a;
69206977982Sstefanozampini   PetscCall(MatSeqAIJGetCSRAndMemType(dA, NULL, NULL, &a, NULL));
69306977982Sstefanozampini   PetscCall(MatSetValuesCOO(dH, a, INSERT_VALUES));
69406977982Sstefanozampini   if (oH) {
69506977982Sstefanozampini     PetscCall(MatSeqAIJGetCSRAndMemType(oA, NULL, NULL, &a, NULL));
69606977982Sstefanozampini     PetscCall(MatSetValuesCOO(oH, a, INSERT_VALUES));
69706977982Sstefanozampini   }
698b73e3080SStefano Zampini 
69948a46eb9SPierre Jolivet   if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &M));
700d7185485SAlex Lindsay #if defined(PETSC_HAVE_DEVICE)
701d7185485SAlex Lindsay   (*B)->boundtocpu = boundtocpu;
702d7185485SAlex Lindsay #endif
7033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
70463c07aadSStefano Zampini }
70563c07aadSStefano Zampini 
706d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_HYPRE_AIJ(Mat A, MatType mtype, MatReuse reuse, Mat *B)
707d71ae5a4SJacob Faibussowitsch {
70806977982Sstefanozampini   Mat                 M, dA = NULL, oA = NULL;
70963c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
71006977982Sstefanozampini   hypre_CSRMatrix    *dH, *oH;
71163c07aadSStefano Zampini   MPI_Comm            comm;
71206977982Sstefanozampini   PetscBool           ismpiaij, isseqaij;
71363c07aadSStefano Zampini 
71463c07aadSStefano Zampini   PetscFunctionBegin;
71563c07aadSStefano Zampini   comm = PetscObjectComm((PetscObject)A);
71663c07aadSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
7179566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATMPIAIJ, &ismpiaij));
7189566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATSEQAIJ, &isseqaij));
71906977982Sstefanozampini     PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Only MATMPIAIJ or MATSEQAIJ base types are supported");
72063c07aadSStefano Zampini   }
72106977982Sstefanozampini   PetscCall(MatHYPREGetParCSR(A, &parcsr));
7226ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
72306977982Sstefanozampini   if (HYPRE_MEMORY_DEVICE == hypre_ParCSRMatrixMemoryLocation(parcsr)) {
72406977982Sstefanozampini     PetscBool isaij;
72506977982Sstefanozampini 
72606977982Sstefanozampini     PetscCall(PetscStrcmp(mtype, MATAIJ, &isaij));
72706977982Sstefanozampini     if (isaij) {
72806977982Sstefanozampini       PetscMPIInt size;
72906977982Sstefanozampini 
7309566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_size(comm, &size));
73106977982Sstefanozampini   #if defined(HYPRE_USING_HIP)
73206977982Sstefanozampini       mtype = size > 1 ? MATMPIAIJHIPSPARSE : MATSEQAIJHIPSPARSE;
73306977982Sstefanozampini   #elif defined(HYPRE_USING_CUDA)
73406977982Sstefanozampini       mtype = size > 1 ? MATMPIAIJCUSPARSE : MATSEQAIJCUSPARSE;
73506977982Sstefanozampini   #else
73606977982Sstefanozampini       mtype = size > 1 ? MATMPIAIJ : MATSEQAIJ;
73706977982Sstefanozampini   #endif
73863c07aadSStefano Zampini     }
73963c07aadSStefano Zampini   }
74006977982Sstefanozampini #endif
74106977982Sstefanozampini   dH = hypre_ParCSRMatrixDiag(parcsr);
74206977982Sstefanozampini   oH = hypre_ParCSRMatrixOffd(parcsr);
7439371c9d4SSatish Balay   if (reuse != MAT_REUSE_MATRIX) {
74406977982Sstefanozampini     PetscCount coo_n;
74506977982Sstefanozampini     PetscInt  *coo_i, *coo_j;
74663c07aadSStefano Zampini 
74706977982Sstefanozampini     PetscCall(MatCreate(comm, &M));
74806977982Sstefanozampini     PetscCall(MatSetType(M, mtype));
74906977982Sstefanozampini     PetscCall(MatSetSizes(M, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
75006977982Sstefanozampini     PetscCall(MatMPIAIJSetPreallocation(M, 0, NULL, 0, NULL));
75163c07aadSStefano Zampini 
75206977982Sstefanozampini     dA = M;
75306977982Sstefanozampini     PetscCall(PetscObjectBaseTypeCompare((PetscObject)M, MATMPIAIJ, &ismpiaij));
75406977982Sstefanozampini     if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(M, &dA, &oA, NULL));
755a16187a7SStefano Zampini 
75606977982Sstefanozampini     PetscCall(hypreCSRMatrixGetCOO_Private(dH, &coo_n, &coo_i, &coo_j));
75706977982Sstefanozampini     PetscCall(MatSetPreallocationCOO(dA, coo_n, coo_i, coo_j));
75806977982Sstefanozampini     PetscCall(PetscFree2(coo_i, coo_j));
75906977982Sstefanozampini     if (ismpiaij) {
76006977982Sstefanozampini       HYPRE_Int nc = hypre_CSRMatrixNumCols(oH);
761a16187a7SStefano Zampini 
76206977982Sstefanozampini       PetscCall(PetscLayoutDestroy(&oA->cmap));
76306977982Sstefanozampini       PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)oA), nc, nc, 1, &oA->cmap));
76406977982Sstefanozampini       PetscCall(hypreCSRMatrixGetCOO_Private(oH, &coo_n, &coo_i, &coo_j));
76506977982Sstefanozampini       PetscCall(MatSetPreallocationCOO(oA, coo_n, coo_i, coo_j));
76606977982Sstefanozampini       PetscCall(PetscFree2(coo_i, coo_j));
767a16187a7SStefano Zampini 
76806977982Sstefanozampini       /* garray */
769f4f49eeaSPierre Jolivet       Mat_MPIAIJ   *aij    = (Mat_MPIAIJ *)M->data;
77006977982Sstefanozampini       HYPRE_BigInt *harray = hypre_ParCSRMatrixColMapOffd(parcsr);
77106977982Sstefanozampini       PetscInt     *garray;
77206977982Sstefanozampini 
77306977982Sstefanozampini       PetscCall(PetscFree(aij->garray));
77406977982Sstefanozampini       PetscCall(PetscMalloc1(nc, &garray));
77506977982Sstefanozampini       for (HYPRE_Int i = 0; i < nc; i++) garray[i] = (PetscInt)harray[i];
77606977982Sstefanozampini       aij->garray = garray;
77706977982Sstefanozampini       PetscCall(MatSetUpMultiply_MPIAIJ(M));
778a16187a7SStefano Zampini     }
77906977982Sstefanozampini     if (reuse == MAT_INITIAL_MATRIX) *B = M;
78006977982Sstefanozampini   } else M = *B;
781225daaf8SStefano Zampini 
78206977982Sstefanozampini   dA = M;
78306977982Sstefanozampini   PetscCall(PetscObjectBaseTypeCompare((PetscObject)M, MATMPIAIJ, &ismpiaij));
78406977982Sstefanozampini   if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(M, &dA, &oA, NULL));
78506977982Sstefanozampini   PetscCall(MatSetValuesCOOFromCSRMatrix_Private(dA, dH));
78606977982Sstefanozampini   if (oA) PetscCall(MatSetValuesCOOFromCSRMatrix_Private(oA, oH));
78706977982Sstefanozampini   M->assembled = PETSC_TRUE;
78806977982Sstefanozampini   if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &M));
7893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
79063c07aadSStefano Zampini }
79163c07aadSStefano Zampini 
792d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJGetParCSR_Private(Mat A, hypre_ParCSRMatrix **hA)
793d71ae5a4SJacob Faibussowitsch {
794613e5ff0Sstefano_zampini   hypre_ParCSRMatrix *tA;
795c1a070e6SStefano Zampini   hypre_CSRMatrix    *hdiag, *hoffd;
796c1a070e6SStefano Zampini   Mat_SeqAIJ         *diag, *offd;
7972cf14000SStefano Zampini   PetscInt           *garray, i, noffd, dnnz, onnz, *row_starts, *col_starts;
798c1a070e6SStefano Zampini   MPI_Comm            comm = PetscObjectComm((PetscObject)A);
799613e5ff0Sstefano_zampini   PetscBool           ismpiaij, isseqaij;
8002cf14000SStefano Zampini   PetscBool           sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
8016ea7df73SStefano Zampini   HYPRE_Int          *hdi = NULL, *hdj = NULL, *hoi = NULL, *hoj = NULL;
8025c97c10fSStefano Zampini   PetscInt           *pdi = NULL, *pdj = NULL, *poi = NULL, *poj = NULL;
80306977982Sstefanozampini   PetscBool           iscuda, iship;
80406977982Sstefanozampini #if defined(PETSC_HAVE_DEVICE) && defined(PETSC_HAVE_HYPRE_DEVICE)
80506977982Sstefanozampini   PetscBool boundtocpu = A->boundtocpu;
80606977982Sstefanozampini #else
80706977982Sstefanozampini   PetscBool boundtocpu = PETSC_TRUE;
8086ea7df73SStefano Zampini #endif
809c1a070e6SStefano Zampini 
810c1a070e6SStefano Zampini   PetscFunctionBegin;
8119566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
8129566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isseqaij));
81308401ef6SPierre Jolivet   PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Unsupported type %s", ((PetscObject)A)->type_name);
814b655ebf8SZach Atkins   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, ""));
815b655ebf8SZach Atkins   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iship, MATSEQAIJHIPSPARSE, MATMPIAIJHIPSPARSE, ""));
816ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
817c1a070e6SStefano Zampini   if (ismpiaij) {
818f4f49eeaSPierre Jolivet     Mat_MPIAIJ *a = (Mat_MPIAIJ *)A->data;
819c1a070e6SStefano Zampini 
820c1a070e6SStefano Zampini     diag = (Mat_SeqAIJ *)a->A->data;
821c1a070e6SStefano Zampini     offd = (Mat_SeqAIJ *)a->B->data;
82206977982Sstefanozampini     if (!boundtocpu && (iscuda || iship)) {
82306977982Sstefanozampini #if defined(HYPRE_USING_CUDA) && defined(PETSC_HAVE_CUDA)
82406977982Sstefanozampini       if (iscuda) {
8256ea7df73SStefano Zampini         sameint = PETSC_TRUE;
8269566063dSJacob Faibussowitsch         PetscCall(MatSeqAIJCUSPARSEGetIJ(a->A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
8279566063dSJacob Faibussowitsch         PetscCall(MatSeqAIJCUSPARSEGetIJ(a->B, PETSC_FALSE, (const HYPRE_Int **)&hoi, (const HYPRE_Int **)&hoj));
82806977982Sstefanozampini       }
8296ea7df73SStefano Zampini #endif
83006977982Sstefanozampini #if defined(HYPRE_USING_HIP) && defined(PETSC_HAVE_HIP)
83106977982Sstefanozampini       if (iship) {
83206977982Sstefanozampini         sameint = PETSC_TRUE;
83306977982Sstefanozampini         PetscCall(MatSeqAIJHIPSPARSEGetIJ(a->A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
83406977982Sstefanozampini         PetscCall(MatSeqAIJHIPSPARSEGetIJ(a->B, PETSC_FALSE, (const HYPRE_Int **)&hoi, (const HYPRE_Int **)&hoj));
83506977982Sstefanozampini       }
83606977982Sstefanozampini #endif
83706977982Sstefanozampini     } else {
83806977982Sstefanozampini       boundtocpu = PETSC_TRUE;
8396ea7df73SStefano Zampini       pdi        = diag->i;
8406ea7df73SStefano Zampini       pdj        = diag->j;
8416ea7df73SStefano Zampini       poi        = offd->i;
8426ea7df73SStefano Zampini       poj        = offd->j;
8436ea7df73SStefano Zampini       if (sameint) {
8446ea7df73SStefano Zampini         hdi = (HYPRE_Int *)pdi;
8456ea7df73SStefano Zampini         hdj = (HYPRE_Int *)pdj;
8466ea7df73SStefano Zampini         hoi = (HYPRE_Int *)poi;
8476ea7df73SStefano Zampini         hoj = (HYPRE_Int *)poj;
8486ea7df73SStefano Zampini       }
8496ea7df73SStefano Zampini     }
850c1a070e6SStefano Zampini     garray = a->garray;
851c1a070e6SStefano Zampini     noffd  = a->B->cmap->N;
852c1a070e6SStefano Zampini     dnnz   = diag->nz;
853c1a070e6SStefano Zampini     onnz   = offd->nz;
854c1a070e6SStefano Zampini   } else {
855c1a070e6SStefano Zampini     diag = (Mat_SeqAIJ *)A->data;
856c1a070e6SStefano Zampini     offd = NULL;
85706977982Sstefanozampini     if (!boundtocpu && (iscuda || iship)) {
85806977982Sstefanozampini #if defined(HYPRE_USING_CUDA) && defined(PETSC_HAVE_CUDA)
85906977982Sstefanozampini       if (iscuda) {
8606ea7df73SStefano Zampini         sameint = PETSC_TRUE;
8619566063dSJacob Faibussowitsch         PetscCall(MatSeqAIJCUSPARSEGetIJ(A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
86206977982Sstefanozampini       }
8636ea7df73SStefano Zampini #endif
86406977982Sstefanozampini #if defined(HYPRE_USING_HIP) && defined(PETSC_HAVE_HIP)
86506977982Sstefanozampini       if (iship) {
86606977982Sstefanozampini         sameint = PETSC_TRUE;
86706977982Sstefanozampini         PetscCall(MatSeqAIJHIPSPARSEGetIJ(A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
86806977982Sstefanozampini       }
86906977982Sstefanozampini #endif
87006977982Sstefanozampini     } else {
87106977982Sstefanozampini       boundtocpu = PETSC_TRUE;
8726ea7df73SStefano Zampini       pdi        = diag->i;
8736ea7df73SStefano Zampini       pdj        = diag->j;
8746ea7df73SStefano Zampini       if (sameint) {
8756ea7df73SStefano Zampini         hdi = (HYPRE_Int *)pdi;
8766ea7df73SStefano Zampini         hdj = (HYPRE_Int *)pdj;
8776ea7df73SStefano Zampini       }
8786ea7df73SStefano Zampini     }
879c1a070e6SStefano Zampini     garray = NULL;
880c1a070e6SStefano Zampini     noffd  = 0;
881c1a070e6SStefano Zampini     dnnz   = diag->nz;
882c1a070e6SStefano Zampini     onnz   = 0;
883c1a070e6SStefano Zampini   }
884225daaf8SStefano Zampini 
885c1a070e6SStefano Zampini   /* create a temporary ParCSR */
886c1a070e6SStefano Zampini   if (HYPRE_AssumedPartitionCheck()) {
887c1a070e6SStefano Zampini     PetscMPIInt myid;
888c1a070e6SStefano Zampini 
8899566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &myid));
890c1a070e6SStefano Zampini     row_starts = A->rmap->range + myid;
891c1a070e6SStefano Zampini     col_starts = A->cmap->range + myid;
892c1a070e6SStefano Zampini   } else {
893c1a070e6SStefano Zampini     row_starts = A->rmap->range;
894c1a070e6SStefano Zampini     col_starts = A->cmap->range;
895c1a070e6SStefano Zampini   }
8962cf14000SStefano Zampini   tA = hypre_ParCSRMatrixCreate(comm, A->rmap->N, A->cmap->N, (HYPRE_BigInt *)row_starts, (HYPRE_BigInt *)col_starts, noffd, dnnz, onnz);
897a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
898c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetRowStartsOwner(tA, 0);
899c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetColStartsOwner(tA, 0);
900a1d2239cSSatish Balay #endif
901c1a070e6SStefano Zampini 
902225daaf8SStefano Zampini   /* set diagonal part */
903c1a070e6SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(tA);
9046ea7df73SStefano Zampini   if (!sameint) { /* malloc CSR pointers */
9059566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(A->rmap->n + 1, &hdi, dnnz, &hdj));
906f4f49eeaSPierre Jolivet     for (i = 0; i < A->rmap->n + 1; i++) hdi[i] = (HYPRE_Int)pdi[i];
907f4f49eeaSPierre Jolivet     for (i = 0; i < dnnz; i++) hdj[i] = (HYPRE_Int)pdj[i];
9082cf14000SStefano Zampini   }
9096ea7df73SStefano Zampini   hypre_CSRMatrixI(hdiag)           = hdi;
9106ea7df73SStefano Zampini   hypre_CSRMatrixJ(hdiag)           = hdj;
91139accc25SStefano Zampini   hypre_CSRMatrixData(hdiag)        = (HYPRE_Complex *)diag->a;
912c1a070e6SStefano Zampini   hypre_CSRMatrixNumNonzeros(hdiag) = diag->nz;
913c1a070e6SStefano Zampini   hypre_CSRMatrixSetRownnz(hdiag);
914c1a070e6SStefano Zampini   hypre_CSRMatrixSetDataOwner(hdiag, 0);
915c1a070e6SStefano Zampini 
9164cf0e950SBarry Smith   /* set off-diagonal part */
917c1a070e6SStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(tA);
918c1a070e6SStefano Zampini   if (offd) {
9196ea7df73SStefano Zampini     if (!sameint) { /* malloc CSR pointers */
9209566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(A->rmap->n + 1, &hoi, onnz, &hoj));
921f4f49eeaSPierre Jolivet       for (i = 0; i < A->rmap->n + 1; i++) hoi[i] = (HYPRE_Int)poi[i];
922f4f49eeaSPierre Jolivet       for (i = 0; i < onnz; i++) hoj[i] = (HYPRE_Int)poj[i];
9232cf14000SStefano Zampini     }
9246ea7df73SStefano Zampini     hypre_CSRMatrixI(hoffd)           = hoi;
9256ea7df73SStefano Zampini     hypre_CSRMatrixJ(hoffd)           = hoj;
92639accc25SStefano Zampini     hypre_CSRMatrixData(hoffd)        = (HYPRE_Complex *)offd->a;
927c1a070e6SStefano Zampini     hypre_CSRMatrixNumNonzeros(hoffd) = offd->nz;
928c1a070e6SStefano Zampini     hypre_CSRMatrixSetRownnz(hoffd);
929c1a070e6SStefano Zampini     hypre_CSRMatrixSetDataOwner(hoffd, 0);
9306ea7df73SStefano Zampini   }
9316ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
93206977982Sstefanozampini   PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, !boundtocpu ? HYPRE_MEMORY_DEVICE : HYPRE_MEMORY_HOST);
9336ea7df73SStefano Zampini #else
9346ea7df73SStefano Zampini   #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0)
935792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixInitialize, tA);
9366ea7df73SStefano Zampini   #else
937792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, HYPRE_MEMORY_HOST);
9386ea7df73SStefano Zampini   #endif
9396ea7df73SStefano Zampini #endif
9406ea7df73SStefano Zampini   hypre_TFree(hypre_ParCSRMatrixColMapOffd(tA), HYPRE_MEMORY_HOST);
941c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetNumNonzeros(tA);
9422cf14000SStefano Zampini   hypre_ParCSRMatrixColMapOffd(tA) = (HYPRE_BigInt *)garray;
943792fecdfSBarry Smith   if (!hypre_ParCSRMatrixCommPkg(tA)) PetscCallExternal(hypre_MatvecCommPkgCreate, tA);
944613e5ff0Sstefano_zampini   *hA = tA;
9453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
946613e5ff0Sstefano_zampini }
947c1a070e6SStefano Zampini 
948d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJRestoreParCSR_Private(Mat A, hypre_ParCSRMatrix **hA)
949d71ae5a4SJacob Faibussowitsch {
950613e5ff0Sstefano_zampini   hypre_CSRMatrix *hdiag, *hoffd;
9516ea7df73SStefano Zampini   PetscBool        ismpiaij, sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
952b655ebf8SZach Atkins   PetscBool        iscuda, iship;
953c1a070e6SStefano Zampini 
954613e5ff0Sstefano_zampini   PetscFunctionBegin;
9559566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
9569566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, ""));
957b655ebf8SZach Atkins   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iship, MATSEQAIJHIPSPARSE, MATMPIAIJHIPSPARSE, ""));
958b655ebf8SZach Atkins #if defined(HYPRE_USING_CUDA) && defined(PETSC_HAVE_CUDA)
9596ea7df73SStefano Zampini   if (iscuda) sameint = PETSC_TRUE;
960b655ebf8SZach Atkins #elif defined(HYPRE_USING_HIP) && defined(PETSC_HAVE_HIP)
961b655ebf8SZach Atkins   if (iship) sameint = PETSC_TRUE;
9626ea7df73SStefano Zampini #endif
963613e5ff0Sstefano_zampini   hdiag = hypre_ParCSRMatrixDiag(*hA);
964613e5ff0Sstefano_zampini   hoffd = hypre_ParCSRMatrixOffd(*hA);
9656ea7df73SStefano Zampini   /* free temporary memory allocated by PETSc
9666ea7df73SStefano Zampini      set pointers to NULL before destroying tA */
9672cf14000SStefano Zampini   if (!sameint) {
9682cf14000SStefano Zampini     HYPRE_Int *hi, *hj;
9692cf14000SStefano Zampini 
9702cf14000SStefano Zampini     hi = hypre_CSRMatrixI(hdiag);
9712cf14000SStefano Zampini     hj = hypre_CSRMatrixJ(hdiag);
9729566063dSJacob Faibussowitsch     PetscCall(PetscFree2(hi, hj));
9736ea7df73SStefano Zampini     if (ismpiaij) {
9742cf14000SStefano Zampini       hi = hypre_CSRMatrixI(hoffd);
9752cf14000SStefano Zampini       hj = hypre_CSRMatrixJ(hoffd);
9769566063dSJacob Faibussowitsch       PetscCall(PetscFree2(hi, hj));
9772cf14000SStefano Zampini     }
9782cf14000SStefano Zampini   }
979c1a070e6SStefano Zampini   hypre_CSRMatrixI(hdiag)    = NULL;
980c1a070e6SStefano Zampini   hypre_CSRMatrixJ(hdiag)    = NULL;
981c1a070e6SStefano Zampini   hypre_CSRMatrixData(hdiag) = NULL;
9826ea7df73SStefano Zampini   if (ismpiaij) {
983c1a070e6SStefano Zampini     hypre_CSRMatrixI(hoffd)    = NULL;
984c1a070e6SStefano Zampini     hypre_CSRMatrixJ(hoffd)    = NULL;
985c1a070e6SStefano Zampini     hypre_CSRMatrixData(hoffd) = NULL;
9866ea7df73SStefano Zampini   }
987613e5ff0Sstefano_zampini   hypre_ParCSRMatrixColMapOffd(*hA) = NULL;
988613e5ff0Sstefano_zampini   hypre_ParCSRMatrixDestroy(*hA);
989613e5ff0Sstefano_zampini   *hA = NULL;
9903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
991613e5ff0Sstefano_zampini }
992613e5ff0Sstefano_zampini 
993613e5ff0Sstefano_zampini /* calls RAP from BoomerAMG:
9943dad0653Sstefano_zampini    the resulting ParCSR will not own the column and row starts
9956ea7df73SStefano Zampini    It looks like we don't need to have the diagonal entries ordered first */
996d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_RAP(hypre_ParCSRMatrix *hR, hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hP, hypre_ParCSRMatrix **hRAP)
997d71ae5a4SJacob Faibussowitsch {
998a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
999613e5ff0Sstefano_zampini   HYPRE_Int P_owns_col_starts, R_owns_row_starts;
1000a1d2239cSSatish Balay #endif
1001613e5ff0Sstefano_zampini 
1002613e5ff0Sstefano_zampini   PetscFunctionBegin;
1003a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
1004613e5ff0Sstefano_zampini   P_owns_col_starts = hypre_ParCSRMatrixOwnsColStarts(hP);
1005613e5ff0Sstefano_zampini   R_owns_row_starts = hypre_ParCSRMatrixOwnsRowStarts(hR);
1006a1d2239cSSatish Balay #endif
10076ea7df73SStefano Zampini   /* can be replaced by version test later */
10086ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
1009792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParCSRMatrixRAP");
10106ea7df73SStefano Zampini   *hRAP = hypre_ParCSRMatrixRAP(hR, hA, hP);
10116ea7df73SStefano Zampini   PetscStackPop;
10126ea7df73SStefano Zampini #else
1013792fecdfSBarry Smith   PetscCallExternal(hypre_BoomerAMGBuildCoarseOperator, hR, hA, hP, hRAP);
1014792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixSetNumNonzeros, *hRAP);
10156ea7df73SStefano Zampini #endif
1016613e5ff0Sstefano_zampini   /* hypre_BoomerAMGBuildCoarseOperator steals the col_starts from P and the row_starts from R */
1017a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
1018613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetRowStartsOwner(*hRAP, 0);
1019613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetColStartsOwner(*hRAP, 0);
1020613e5ff0Sstefano_zampini   if (P_owns_col_starts) hypre_ParCSRMatrixSetColStartsOwner(hP, 1);
1021613e5ff0Sstefano_zampini   if (R_owns_row_starts) hypre_ParCSRMatrixSetRowStartsOwner(hR, 1);
1022a1d2239cSSatish Balay #endif
10233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1024613e5ff0Sstefano_zampini }
1025613e5ff0Sstefano_zampini 
1026d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat P, Mat C)
1027d71ae5a4SJacob Faibussowitsch {
10286f231fbdSstefano_zampini   Mat                 B;
10296abb4441SStefano Zampini   hypre_ParCSRMatrix *hA, *hP, *hPtAP = NULL;
10304222ddf1SHong Zhang   Mat_Product        *product = C->product;
1031613e5ff0Sstefano_zampini 
1032613e5ff0Sstefano_zampini   PetscFunctionBegin;
10339566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
10349566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(P, &hP));
10359566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(hP, hA, hP, &hPtAP));
10369566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hPtAP, MATAIJ, PETSC_OWN_POINTER, &B));
10374222ddf1SHong Zhang 
10389566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
10394222ddf1SHong Zhang   C->product = product;
10404222ddf1SHong Zhang 
10419566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
10429566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(P, &hP));
10433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10446f231fbdSstefano_zampini }
10456f231fbdSstefano_zampini 
1046d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatPtAPSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat P, PetscReal fill, Mat C)
1047d71ae5a4SJacob Faibussowitsch {
10486f231fbdSstefano_zampini   PetscFunctionBegin;
10499566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATAIJ));
10504222ddf1SHong Zhang   C->ops->ptapnumeric    = MatPtAPNumeric_AIJ_AIJ_wHYPRE;
10514222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
10523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1053613e5ff0Sstefano_zampini }
1054613e5ff0Sstefano_zampini 
1055d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_HYPRE(Mat A, Mat P, Mat C)
1056d71ae5a4SJacob Faibussowitsch {
10574cc28894Sstefano_zampini   Mat                 B;
10584cc28894Sstefano_zampini   Mat_HYPRE          *hP;
10596abb4441SStefano Zampini   hypre_ParCSRMatrix *hA = NULL, *Pparcsr, *ptapparcsr = NULL;
1060613e5ff0Sstefano_zampini   HYPRE_Int           type;
1061613e5ff0Sstefano_zampini   MPI_Comm            comm = PetscObjectComm((PetscObject)A);
10624cc28894Sstefano_zampini   PetscBool           ishypre;
1063613e5ff0Sstefano_zampini 
1064613e5ff0Sstefano_zampini   PetscFunctionBegin;
10659566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre));
106628b400f6SJacob Faibussowitsch   PetscCheck(ishypre, comm, PETSC_ERR_USER, "P should be of type %s", MATHYPRE);
10674cc28894Sstefano_zampini   hP = (Mat_HYPRE *)P->data;
1068792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type);
106908401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1070792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr);
1071613e5ff0Sstefano_zampini 
10729566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
10739566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, hA, Pparcsr, &ptapparcsr));
10749566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
1075225daaf8SStefano Zampini 
10764cc28894Sstefano_zampini   /* create temporary matrix and merge to C */
10779566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ptapparcsr, ((PetscObject)C)->type_name, PETSC_OWN_POINTER, &B));
10789566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
10793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10804cc28894Sstefano_zampini }
10814cc28894Sstefano_zampini 
1082d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_HYPRE_HYPRE(Mat A, Mat P, Mat C)
1083d71ae5a4SJacob Faibussowitsch {
10844cc28894Sstefano_zampini   Mat                 B;
10856abb4441SStefano Zampini   hypre_ParCSRMatrix *Aparcsr, *Pparcsr, *ptapparcsr = NULL;
10864cc28894Sstefano_zampini   Mat_HYPRE          *hA, *hP;
10874cc28894Sstefano_zampini   PetscBool           ishypre;
10884cc28894Sstefano_zampini   HYPRE_Int           type;
10894cc28894Sstefano_zampini 
10904cc28894Sstefano_zampini   PetscFunctionBegin;
10919566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre));
109228b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)P), PETSC_ERR_USER, "P should be of type %s", MATHYPRE);
10939566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
109428b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE);
10954cc28894Sstefano_zampini   hA = (Mat_HYPRE *)A->data;
10964cc28894Sstefano_zampini   hP = (Mat_HYPRE *)P->data;
1097792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
109808401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1099792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type);
110008401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)P), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1101792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr);
1102792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr);
11039566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, Aparcsr, Pparcsr, &ptapparcsr));
11049566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ptapparcsr, MATHYPRE, PETSC_OWN_POINTER, &B));
11059566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
11063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11074cc28894Sstefano_zampini }
11084cc28894Sstefano_zampini 
1109d501dc42Sstefano_zampini /* calls hypre_ParMatmul
1110d501dc42Sstefano_zampini    hypre_ParMatMul uses hypre_ParMatrixCreate with the communicator of hA
11113dad0653Sstefano_zampini    hypre_ParMatrixCreate does not duplicate the communicator
11126ea7df73SStefano Zampini    It looks like we don't need to have the diagonal entries ordered first */
1113d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_MatMatMult(hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hB, hypre_ParCSRMatrix **hAB)
1114d71ae5a4SJacob Faibussowitsch {
1115d501dc42Sstefano_zampini   PetscFunctionBegin;
11166ea7df73SStefano Zampini   /* can be replaced by version test later */
11176ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
1118792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParCSRMatMat");
11196ea7df73SStefano Zampini   *hAB = hypre_ParCSRMatMat(hA, hB);
11206ea7df73SStefano Zampini #else
1121792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParMatmul");
1122d501dc42Sstefano_zampini   *hAB = hypre_ParMatmul(hA, hB);
11236ea7df73SStefano Zampini #endif
1124d501dc42Sstefano_zampini   PetscStackPop;
11253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1126d501dc42Sstefano_zampini }
1127d501dc42Sstefano_zampini 
1128d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C)
1129d71ae5a4SJacob Faibussowitsch {
11305e5acdf2Sstefano_zampini   Mat                 D;
1131d501dc42Sstefano_zampini   hypre_ParCSRMatrix *hA, *hB, *hAB = NULL;
11324222ddf1SHong Zhang   Mat_Product        *product = C->product;
11335e5acdf2Sstefano_zampini 
11345e5acdf2Sstefano_zampini   PetscFunctionBegin;
11359566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
11369566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(B, &hB));
11379566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_MatMatMult(hA, hB, &hAB));
11389566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hAB, MATAIJ, PETSC_OWN_POINTER, &D));
11394222ddf1SHong Zhang 
11409566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &D));
11414222ddf1SHong Zhang   C->product = product;
11424222ddf1SHong Zhang 
11439566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
11449566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(B, &hB));
11453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11465e5acdf2Sstefano_zampini }
11475e5acdf2Sstefano_zampini 
1148d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatMatMultSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat B, PetscReal fill, Mat C)
1149d71ae5a4SJacob Faibussowitsch {
11505e5acdf2Sstefano_zampini   PetscFunctionBegin;
11519566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATAIJ));
11524222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_AIJ_AIJ_wHYPRE;
11534222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
11543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11555e5acdf2Sstefano_zampini }
11565e5acdf2Sstefano_zampini 
1157d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_HYPRE_HYPRE(Mat A, Mat B, Mat C)
1158d71ae5a4SJacob Faibussowitsch {
1159d501dc42Sstefano_zampini   Mat                 D;
1160d501dc42Sstefano_zampini   hypre_ParCSRMatrix *Aparcsr, *Bparcsr, *ABparcsr = NULL;
1161d501dc42Sstefano_zampini   Mat_HYPRE          *hA, *hB;
1162d501dc42Sstefano_zampini   PetscBool           ishypre;
1163d501dc42Sstefano_zampini   HYPRE_Int           type;
11644222ddf1SHong Zhang   Mat_Product        *product;
1165d501dc42Sstefano_zampini 
1166d501dc42Sstefano_zampini   PetscFunctionBegin;
11679566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)B, MATHYPRE, &ishypre));
116828b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)B), PETSC_ERR_USER, "B should be of type %s", MATHYPRE);
11699566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
117028b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE);
1171d501dc42Sstefano_zampini   hA = (Mat_HYPRE *)A->data;
1172d501dc42Sstefano_zampini   hB = (Mat_HYPRE *)B->data;
1173792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
117408401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1175792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hB->ij, &type);
117608401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1177792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr);
1178792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hB->ij, (void **)&Bparcsr);
11799566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_MatMatMult(Aparcsr, Bparcsr, &ABparcsr));
11809566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ABparcsr, MATHYPRE, PETSC_OWN_POINTER, &D));
11814222ddf1SHong Zhang 
1182d501dc42Sstefano_zampini   /* need to use HeaderReplace because HeaderMerge messes up with the communicator */
11834222ddf1SHong Zhang   product    = C->product; /* save it from MatHeaderReplace() */
11844222ddf1SHong Zhang   C->product = NULL;
11859566063dSJacob Faibussowitsch   PetscCall(MatHeaderReplace(C, &D));
11864222ddf1SHong Zhang   C->product             = product;
1187d501dc42Sstefano_zampini   C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE;
11884222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
11893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1190d501dc42Sstefano_zampini }
1191d501dc42Sstefano_zampini 
1192d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultNumeric_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, Mat D)
1193d71ae5a4SJacob Faibussowitsch {
119420e1dc0dSstefano_zampini   Mat                 E;
11956abb4441SStefano Zampini   hypre_ParCSRMatrix *hA, *hB, *hC, *hABC = NULL;
119620e1dc0dSstefano_zampini 
119720e1dc0dSstefano_zampini   PetscFunctionBegin;
11989566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
11999566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(B, &hB));
12009566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(C, &hC));
12019566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(hA, hB, hC, &hABC));
12029566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hABC, MATAIJ, PETSC_OWN_POINTER, &E));
12039566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(D, &E));
12049566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
12059566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(B, &hB));
12069566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(C, &hC));
12073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
120820e1dc0dSstefano_zampini }
120920e1dc0dSstefano_zampini 
1210d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultSymbolic_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, PetscReal fill, Mat D)
1211d71ae5a4SJacob Faibussowitsch {
121220e1dc0dSstefano_zampini   PetscFunctionBegin;
12139566063dSJacob Faibussowitsch   PetscCall(MatSetType(D, MATAIJ));
12143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
121520e1dc0dSstefano_zampini }
121620e1dc0dSstefano_zampini 
1217d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_AB_HYPRE(Mat C)
1218d71ae5a4SJacob Faibussowitsch {
12194222ddf1SHong Zhang   PetscFunctionBegin;
12204222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
12213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12224222ddf1SHong Zhang }
12234222ddf1SHong Zhang 
1224d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_AB(Mat C)
1225d71ae5a4SJacob Faibussowitsch {
12264222ddf1SHong Zhang   Mat_Product *product = C->product;
12274222ddf1SHong Zhang   PetscBool    Ahypre;
12284222ddf1SHong Zhang 
12294222ddf1SHong Zhang   PetscFunctionBegin;
12309566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)product->A, MATHYPRE, &Ahypre));
12314222ddf1SHong Zhang   if (Ahypre) { /* A is a Hypre matrix */
12329566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
12334222ddf1SHong Zhang     C->ops->productsymbolic = MatProductSymbolic_AB_HYPRE;
12344222ddf1SHong Zhang     C->ops->matmultnumeric  = MatMatMultNumeric_HYPRE_HYPRE;
12353ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
12366718818eSStefano Zampini   }
12373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12384222ddf1SHong Zhang }
12394222ddf1SHong Zhang 
1240d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_PtAP_HYPRE(Mat C)
1241d71ae5a4SJacob Faibussowitsch {
12424222ddf1SHong Zhang   PetscFunctionBegin;
12434222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
12443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12454222ddf1SHong Zhang }
12464222ddf1SHong Zhang 
1247d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_PtAP(Mat C)
1248d71ae5a4SJacob Faibussowitsch {
12494222ddf1SHong Zhang   Mat_Product *product = C->product;
12504222ddf1SHong Zhang   PetscBool    flg;
12514222ddf1SHong Zhang   PetscInt     type        = 0;
12524222ddf1SHong Zhang   const char  *outTypes[4] = {"aij", "seqaij", "mpiaij", "hypre"};
12534222ddf1SHong Zhang   PetscInt     ntype       = 4;
12544222ddf1SHong Zhang   Mat          A           = product->A;
12554222ddf1SHong Zhang   PetscBool    Ahypre;
12564222ddf1SHong Zhang 
12574222ddf1SHong Zhang   PetscFunctionBegin;
12589566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &Ahypre));
12594222ddf1SHong Zhang   if (Ahypre) { /* A is a Hypre matrix */
12609566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
12614222ddf1SHong Zhang     C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE;
12624222ddf1SHong Zhang     C->ops->ptapnumeric     = MatPtAPNumeric_HYPRE_HYPRE;
12633ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
12644222ddf1SHong Zhang   }
12654222ddf1SHong Zhang 
12664222ddf1SHong Zhang   /* A is AIJ, P is Hypre, C = PtAP can be either AIJ or Hypre format */
12674222ddf1SHong Zhang   /* Get runtime option */
12684222ddf1SHong Zhang   if (product->api_user) {
1269d0609cedSBarry Smith     PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatPtAP_HYPRE", "Mat");
12709566063dSJacob Faibussowitsch     PetscCall(PetscOptionsEList("-matptap_hypre_outtype", "MatPtAP outtype", "MatPtAP outtype", outTypes, ntype, outTypes[type], &type, &flg));
1271d0609cedSBarry Smith     PetscOptionsEnd();
12724222ddf1SHong Zhang   } else {
1273d0609cedSBarry Smith     PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatProduct_PtAP_HYPRE", "Mat");
12749566063dSJacob Faibussowitsch     PetscCall(PetscOptionsEList("-mat_product_algorithm_hypre_outtype", "MatProduct_PtAP outtype", "MatProduct_PtAP", outTypes, ntype, outTypes[type], &type, &flg));
1275d0609cedSBarry Smith     PetscOptionsEnd();
12764222ddf1SHong Zhang   }
12774222ddf1SHong Zhang 
12784222ddf1SHong Zhang   if (type == 0 || type == 1 || type == 2) {
12799566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATAIJ));
12804222ddf1SHong Zhang   } else if (type == 3) {
12819566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
12824222ddf1SHong Zhang   } else SETERRQ(PetscObjectComm((PetscObject)C), PETSC_ERR_SUP, "MatPtAP outtype is not supported");
12834222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE;
12844222ddf1SHong Zhang   C->ops->ptapnumeric     = MatPtAPNumeric_AIJ_HYPRE;
12853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12864222ddf1SHong Zhang }
12874222ddf1SHong Zhang 
1288d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE(Mat C)
1289d71ae5a4SJacob Faibussowitsch {
12904222ddf1SHong Zhang   Mat_Product *product = C->product;
12914222ddf1SHong Zhang 
12924222ddf1SHong Zhang   PetscFunctionBegin;
12934222ddf1SHong Zhang   switch (product->type) {
1294d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AB:
1295d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_HYPRE_AB(C));
1296d71ae5a4SJacob Faibussowitsch     break;
1297d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_PtAP:
1298d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_HYPRE_PtAP(C));
1299d71ae5a4SJacob Faibussowitsch     break;
1300d71ae5a4SJacob Faibussowitsch   default:
1301d71ae5a4SJacob Faibussowitsch     break;
13024222ddf1SHong Zhang   }
13033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13044222ddf1SHong Zhang }
13054222ddf1SHong Zhang 
1306d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTranspose_HYPRE(Mat A, Vec x, Vec y)
1307d71ae5a4SJacob Faibussowitsch {
130863c07aadSStefano Zampini   PetscFunctionBegin;
13099566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_TRUE));
13103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
131163c07aadSStefano Zampini }
131263c07aadSStefano Zampini 
1313d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_HYPRE(Mat A, Vec x, Vec y)
1314d71ae5a4SJacob Faibussowitsch {
131563c07aadSStefano Zampini   PetscFunctionBegin;
13169566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_FALSE));
13173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
131863c07aadSStefano Zampini }
131963c07aadSStefano Zampini 
1320d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultAdd_HYPRE(Mat A, Vec x, Vec y, Vec z)
1321d71ae5a4SJacob Faibussowitsch {
1322414bd5c3SStefano Zampini   PetscFunctionBegin;
132348a46eb9SPierre Jolivet   if (y != z) PetscCall(VecCopy(y, z));
13249566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_FALSE));
13253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1326414bd5c3SStefano Zampini }
1327414bd5c3SStefano Zampini 
1328d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTransposeAdd_HYPRE(Mat A, Vec x, Vec y, Vec z)
1329d71ae5a4SJacob Faibussowitsch {
1330414bd5c3SStefano Zampini   PetscFunctionBegin;
133148a46eb9SPierre Jolivet   if (y != z) PetscCall(VecCopy(y, z));
13329566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_TRUE));
13333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1334414bd5c3SStefano Zampini }
1335414bd5c3SStefano Zampini 
1336414bd5c3SStefano Zampini /* y = a * A * x + b * y or y = a * A^t * x + b * y depending on trans */
1337d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_MultKernel_Private(Mat A, HYPRE_Complex a, Vec x, HYPRE_Complex b, Vec y, PetscBool trans)
1338d71ae5a4SJacob Faibussowitsch {
133963c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE *)A->data;
134063c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
134163c07aadSStefano Zampini   hypre_ParVector    *hx, *hy;
134263c07aadSStefano Zampini 
134363c07aadSStefano Zampini   PetscFunctionBegin;
134463c07aadSStefano Zampini   if (trans) {
13459566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorPushVecRead(hA->b, x));
13469566063dSJacob Faibussowitsch     if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->x, y));
13479566063dSJacob Faibussowitsch     else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->x, y));
1348792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hx);
1349792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hy);
135063c07aadSStefano Zampini   } else {
13519566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorPushVecRead(hA->x, x));
13529566063dSJacob Faibussowitsch     if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->b, y));
13539566063dSJacob Faibussowitsch     else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->b, y));
1354792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hx);
1355792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hy);
135663c07aadSStefano Zampini   }
1357792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
13586ea7df73SStefano Zampini   if (trans) {
1359792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMatvecT, a, parcsr, hx, b, hy);
13606ea7df73SStefano Zampini   } else {
1361792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMatvec, a, parcsr, hx, b, hy);
13626ea7df73SStefano Zampini   }
13639566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hA->x));
13649566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hA->b));
13653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
136663c07aadSStefano Zampini }
136763c07aadSStefano Zampini 
1368d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_HYPRE(Mat A)
1369d71ae5a4SJacob Faibussowitsch {
137063c07aadSStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
137163c07aadSStefano Zampini 
137263c07aadSStefano Zampini   PetscFunctionBegin;
13739566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&hA->x));
13749566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&hA->b));
137506977982Sstefanozampini   PetscCall(MatHYPRE_DestroyCOOMat(A)); /* must be called before destroying the individual CSR */
1376978814f1SStefano Zampini   if (hA->ij) {
1377978814f1SStefano Zampini     if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL;
1378792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixDestroy, hA->ij);
1379978814f1SStefano Zampini   }
13809566063dSJacob Faibussowitsch   if (hA->comm) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)A), &hA->comm));
1381c69f721fSFande Kong 
13829566063dSJacob Faibussowitsch   PetscCall(MatStashDestroy_Private(&A->stash));
13839566063dSJacob Faibussowitsch   PetscCall(PetscFree(hA->array));
1384a32e9c99SJunchao Zhang   if (hA->rows_d) PetscStackCallExternalVoid("hypre_Free", hypre_Free(hA->rows_d, HYPRE_MEMORY_DEVICE));
1385c69f721fSFande Kong 
13869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_aij_C", NULL));
13879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_is_C", NULL));
13889566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_hypre_C", NULL));
13899566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaij_hypre_C", NULL));
139006977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijhipsparse_hypre_C", NULL));
139106977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaijhipsparse_hypre_C", NULL));
139206977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijcusparse_hypre_C", NULL));
139306977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaijcusparse_hypre_C", NULL));
13949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPRESetPreallocation_C", NULL));
13959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPREGetParCSR_C", NULL));
13965fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL));
13975fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL));
13989566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->data));
13993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
140063c07aadSStefano Zampini }
140163c07aadSStefano Zampini 
1402d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetUp_HYPRE(Mat A)
1403d71ae5a4SJacob Faibussowitsch {
14044ec6421dSstefano_zampini   PetscFunctionBegin;
140506977982Sstefanozampini   if (!A->preallocated) PetscCall(MatHYPRESetPreallocation(A, PETSC_DEFAULT, NULL, PETSC_DEFAULT, NULL));
14063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14074ec6421dSstefano_zampini }
14084ec6421dSstefano_zampini 
14096ea7df73SStefano Zampini //TODO FIX hypre_CSRMatrixMatvecOutOfPlace
14106ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
1411d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatBindToCPU_HYPRE(Mat A, PetscBool bind)
1412d71ae5a4SJacob Faibussowitsch {
14136ea7df73SStefano Zampini   Mat_HYPRE           *hA   = (Mat_HYPRE *)A->data;
14146ea7df73SStefano Zampini   HYPRE_MemoryLocation hmem = bind ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE;
14156ea7df73SStefano Zampini 
14166ea7df73SStefano Zampini   PetscFunctionBegin;
14176ea7df73SStefano Zampini   A->boundtocpu = bind;
14185fbaff96SJunchao Zhang   if (hA->ij && hypre_IJMatrixAssembleFlag(hA->ij) && hmem != hypre_IJMatrixMemoryLocation(hA->ij)) {
14196ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
1420792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
1421792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMigrate, parcsr, hmem);
14226ea7df73SStefano Zampini   }
14239566063dSJacob Faibussowitsch   if (hA->x) PetscCall(VecHYPRE_IJBindToCPU(hA->x, bind));
14249566063dSJacob Faibussowitsch   if (hA->b) PetscCall(VecHYPRE_IJBindToCPU(hA->b, bind));
14253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14266ea7df73SStefano Zampini }
14276ea7df73SStefano Zampini #endif
14286ea7df73SStefano Zampini 
1429d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_HYPRE(Mat A, MatAssemblyType mode)
1430d71ae5a4SJacob Faibussowitsch {
143163c07aadSStefano Zampini   Mat_HYPRE   *hA = (Mat_HYPRE *)A->data;
1432c69f721fSFande Kong   PetscMPIInt  n;
1433c69f721fSFande Kong   PetscInt     i, j, rstart, ncols, flg;
1434c69f721fSFande Kong   PetscInt    *row, *col;
1435c69f721fSFande Kong   PetscScalar *val;
143663c07aadSStefano Zampini 
143763c07aadSStefano Zampini   PetscFunctionBegin;
143808401ef6SPierre Jolivet   PetscCheck(mode != MAT_FLUSH_ASSEMBLY, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_FLUSH_ASSEMBLY currently not supported with MATHYPRE");
1439c69f721fSFande Kong 
1440c69f721fSFande Kong   if (!A->nooffprocentries) {
1441c69f721fSFande Kong     while (1) {
14429566063dSJacob Faibussowitsch       PetscCall(MatStashScatterGetMesg_Private(&A->stash, &n, &row, &col, &val, &flg));
1443c69f721fSFande Kong       if (!flg) break;
1444c69f721fSFande Kong 
1445c69f721fSFande Kong       for (i = 0; i < n;) {
1446c69f721fSFande Kong         /* Now identify the consecutive vals belonging to the same row */
1447c69f721fSFande Kong         for (j = i, rstart = row[j]; j < n; j++) {
1448c69f721fSFande Kong           if (row[j] != rstart) break;
1449c69f721fSFande Kong         }
1450c69f721fSFande Kong         if (j < n) ncols = j - i;
1451c69f721fSFande Kong         else ncols = n - i;
1452c69f721fSFande Kong         /* Now assemble all these values with a single function call */
14539566063dSJacob Faibussowitsch         PetscCall(MatSetValues_HYPRE(A, 1, row + i, ncols, col + i, val + i, A->insertmode));
1454c69f721fSFande Kong 
1455c69f721fSFande Kong         i = j;
1456c69f721fSFande Kong       }
1457c69f721fSFande Kong     }
14589566063dSJacob Faibussowitsch     PetscCall(MatStashScatterEnd_Private(&A->stash));
1459c69f721fSFande Kong   }
1460c69f721fSFande Kong 
1461792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixAssemble, hA->ij);
1462336664bdSPierre Jolivet   /* The assembly routine destroys the aux_matrix, we recreate it here by calling HYPRE_IJMatrixInitialize */
1463336664bdSPierre 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 */
1464651b1cf9SStefano Zampini   if (!A->sortedfull) {
1465af1cf968SStefano Zampini     hypre_AuxParCSRMatrix *aux_matrix;
1466af1cf968SStefano Zampini 
1467af1cf968SStefano Zampini     /* call destroy just to make sure we do not leak anything */
1468af1cf968SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
1469792fecdfSBarry Smith     PetscCallExternal(hypre_AuxParCSRMatrixDestroy, aux_matrix);
1470af1cf968SStefano Zampini     hypre_IJMatrixTranslator(hA->ij) = NULL;
1471af1cf968SStefano Zampini 
1472af1cf968SStefano Zampini     /* Initialize with assembled flag -> it only recreates the aux_par_matrix */
1473792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij);
1474af1cf968SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
14756ea7df73SStefano Zampini     if (aux_matrix) {
1476af1cf968SStefano Zampini       hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1; /* see comment in MatHYPRESetPreallocation_HYPRE */
147722235d61SPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
1478792fecdfSBarry Smith       PetscCallExternal(hypre_AuxParCSRMatrixInitialize, aux_matrix);
147922235d61SPierre Jolivet #else
1480792fecdfSBarry Smith       PetscCallExternal(hypre_AuxParCSRMatrixInitialize_v2, aux_matrix, HYPRE_MEMORY_HOST);
148122235d61SPierre Jolivet #endif
1482af1cf968SStefano Zampini     }
14836ea7df73SStefano Zampini   }
14846ea7df73SStefano Zampini   {
14856ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
14866ea7df73SStefano Zampini 
1487792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
1488792fecdfSBarry Smith     if (!hypre_ParCSRMatrixCommPkg(parcsr)) PetscCallExternal(hypre_MatvecCommPkgCreate, parcsr);
14896ea7df73SStefano Zampini   }
14909566063dSJacob Faibussowitsch   if (!hA->x) PetscCall(VecHYPRE_IJVectorCreate(A->cmap, &hA->x));
14919566063dSJacob Faibussowitsch   if (!hA->b) PetscCall(VecHYPRE_IJVectorCreate(A->rmap, &hA->b));
14926ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
14939566063dSJacob Faibussowitsch   PetscCall(MatBindToCPU_HYPRE(A, A->boundtocpu));
14946ea7df73SStefano Zampini #endif
14953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
149663c07aadSStefano Zampini }
149763c07aadSStefano Zampini 
1498d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetArray_HYPRE(Mat A, PetscInt size, void **array)
1499d71ae5a4SJacob Faibussowitsch {
1500c69f721fSFande Kong   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1501c69f721fSFande Kong 
1502c69f721fSFande Kong   PetscFunctionBegin;
1503651b1cf9SStefano Zampini   PetscCheck(hA->array_available, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Temporary space is in use");
1504c69f721fSFande Kong 
1505651b1cf9SStefano Zampini   if (hA->array_size >= size) {
150639accc25SStefano Zampini     *array = hA->array;
150739accc25SStefano Zampini   } else {
15089566063dSJacob Faibussowitsch     PetscCall(PetscFree(hA->array));
1509651b1cf9SStefano Zampini     hA->array_size = size;
1510651b1cf9SStefano Zampini     PetscCall(PetscMalloc(hA->array_size, &hA->array));
1511c69f721fSFande Kong     *array = hA->array;
1512c69f721fSFande Kong   }
1513c69f721fSFande Kong 
1514651b1cf9SStefano Zampini   hA->array_available = PETSC_FALSE;
15153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1516c69f721fSFande Kong }
1517c69f721fSFande Kong 
1518d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreArray_HYPRE(Mat A, void **array)
1519d71ae5a4SJacob Faibussowitsch {
1520c69f721fSFande Kong   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1521c69f721fSFande Kong 
1522c69f721fSFande Kong   PetscFunctionBegin;
1523c69f721fSFande Kong   *array              = NULL;
1524651b1cf9SStefano Zampini   hA->array_available = PETSC_TRUE;
15253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1526c69f721fSFande Kong }
1527c69f721fSFande Kong 
1528d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_HYPRE(Mat A, PetscInt nr, const PetscInt rows[], PetscInt nc, const PetscInt cols[], const PetscScalar v[], InsertMode ins)
1529d71ae5a4SJacob Faibussowitsch {
1530d975228cSstefano_zampini   Mat_HYPRE     *hA   = (Mat_HYPRE *)A->data;
1531d975228cSstefano_zampini   PetscScalar   *vals = (PetscScalar *)v;
153239accc25SStefano Zampini   HYPRE_Complex *sscr;
1533c69f721fSFande Kong   PetscInt      *cscr[2];
1534c69f721fSFande Kong   PetscInt       i, nzc;
1535651b1cf9SStefano Zampini   PetscInt       rst = A->rmap->rstart, ren = A->rmap->rend;
153608defe43SFande Kong   void          *array = NULL;
1537d975228cSstefano_zampini 
1538d975228cSstefano_zampini   PetscFunctionBegin;
15399566063dSJacob Faibussowitsch   PetscCall(MatGetArray_HYPRE(A, sizeof(PetscInt) * (2 * nc) + sizeof(HYPRE_Complex) * nc * nr, &array));
1540c69f721fSFande Kong   cscr[0] = (PetscInt *)array;
1541c69f721fSFande Kong   cscr[1] = ((PetscInt *)array) + nc;
154239accc25SStefano Zampini   sscr    = (HYPRE_Complex *)(((PetscInt *)array) + nc * 2);
1543d975228cSstefano_zampini   for (i = 0, nzc = 0; i < nc; i++) {
1544d975228cSstefano_zampini     if (cols[i] >= 0) {
1545d975228cSstefano_zampini       cscr[0][nzc]   = cols[i];
1546d975228cSstefano_zampini       cscr[1][nzc++] = i;
1547d975228cSstefano_zampini     }
1548d975228cSstefano_zampini   }
1549c69f721fSFande Kong   if (!nzc) {
15509566063dSJacob Faibussowitsch     PetscCall(MatRestoreArray_HYPRE(A, &array));
15513ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1552c69f721fSFande Kong   }
1553d975228cSstefano_zampini 
15546ea7df73SStefano Zampini #if 0 //defined(PETSC_HAVE_HYPRE_DEVICE)
15556ea7df73SStefano Zampini   if (HYPRE_MEMORY_HOST != hypre_IJMatrixMemoryLocation(hA->ij)) {
15566ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
15576ea7df73SStefano Zampini 
1558792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject,hA->ij,(void**)&parcsr);
1559792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMigrate,parcsr, HYPRE_MEMORY_HOST);
15606ea7df73SStefano Zampini   }
15616ea7df73SStefano Zampini #endif
15626ea7df73SStefano Zampini 
1563d975228cSstefano_zampini   if (ins == ADD_VALUES) {
1564d975228cSstefano_zampini     for (i = 0; i < nr; i++) {
15656ea7df73SStefano Zampini       if (rows[i] >= 0) {
1566d975228cSstefano_zampini         PetscInt  j;
15672cf14000SStefano Zampini         HYPRE_Int hnc = (HYPRE_Int)nzc;
15682cf14000SStefano Zampini 
1569651b1cf9SStefano Zampini         if (!nzc) continue;
1570651b1cf9SStefano Zampini         /* nonlocal values */
1571651b1cf9SStefano Zampini         if (rows[i] < rst || rows[i] >= ren) {
1572651b1cf9SStefano 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]);
1573651b1cf9SStefano Zampini           if (hA->donotstash) continue;
1574651b1cf9SStefano Zampini         }
1575aed4548fSBarry 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]);
15769566063dSJacob Faibussowitsch         for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j]));
1577792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixAddToValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr);
1578d975228cSstefano_zampini       }
1579d975228cSstefano_zampini       vals += nc;
1580d975228cSstefano_zampini     }
1581d975228cSstefano_zampini   } else { /* INSERT_VALUES */
1582d975228cSstefano_zampini     for (i = 0; i < nr; i++) {
15836ea7df73SStefano Zampini       if (rows[i] >= 0) {
1584d975228cSstefano_zampini         PetscInt  j;
15852cf14000SStefano Zampini         HYPRE_Int hnc = (HYPRE_Int)nzc;
15862cf14000SStefano Zampini 
1587651b1cf9SStefano Zampini         if (!nzc) continue;
1588aed4548fSBarry 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]);
15899566063dSJacob Faibussowitsch         for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j]));
1590c69f721fSFande Kong         /* nonlocal values */
1591651b1cf9SStefano Zampini         if (rows[i] < rst || rows[i] >= ren) {
1592651b1cf9SStefano 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]);
1593651b1cf9SStefano Zampini           if (!hA->donotstash) PetscCall(MatStashValuesRow_Private(&A->stash, rows[i], nzc, cscr[0], (PetscScalar *)sscr, PETSC_FALSE));
1594651b1cf9SStefano Zampini         }
1595c69f721fSFande Kong         /* local values */
1596651b1cf9SStefano Zampini         else
1597651b1cf9SStefano Zampini           PetscCallExternal(HYPRE_IJMatrixSetValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr);
1598d975228cSstefano_zampini       }
1599d975228cSstefano_zampini       vals += nc;
1600d975228cSstefano_zampini     }
1601d975228cSstefano_zampini   }
1602c69f721fSFande Kong 
16039566063dSJacob Faibussowitsch   PetscCall(MatRestoreArray_HYPRE(A, &array));
16043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1605d975228cSstefano_zampini }
1606d975228cSstefano_zampini 
1607d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRESetPreallocation_HYPRE(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[])
1608d71ae5a4SJacob Faibussowitsch {
1609d975228cSstefano_zampini   Mat_HYPRE  *hA = (Mat_HYPRE *)A->data;
16107d968826Sstefano_zampini   HYPRE_Int  *hdnnz, *honnz;
161106a29025Sstefano_zampini   PetscInt    i, rs, re, cs, ce, bs;
1612d975228cSstefano_zampini   PetscMPIInt size;
1613d975228cSstefano_zampini 
1614d975228cSstefano_zampini   PetscFunctionBegin;
16159566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
16169566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
1617d975228cSstefano_zampini   rs = A->rmap->rstart;
1618d975228cSstefano_zampini   re = A->rmap->rend;
1619d975228cSstefano_zampini   cs = A->cmap->rstart;
1620d975228cSstefano_zampini   ce = A->cmap->rend;
1621d975228cSstefano_zampini   if (!hA->ij) {
1622792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rs, re - 1, cs, ce - 1, &hA->ij);
1623792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR);
1624d975228cSstefano_zampini   } else {
16252cf14000SStefano Zampini     HYPRE_BigInt hrs, hre, hcs, hce;
1626792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetLocalRange, hA->ij, &hrs, &hre, &hcs, &hce);
1627aed4548fSBarry 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);
1628aed4548fSBarry 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);
1629d975228cSstefano_zampini   }
163006977982Sstefanozampini   PetscCall(MatHYPRE_DestroyCOOMat(A));
16319566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(A, &bs));
163206a29025Sstefano_zampini   if (dnz == PETSC_DEFAULT || dnz == PETSC_DECIDE) dnz = 10 * bs;
163306a29025Sstefano_zampini   if (onz == PETSC_DEFAULT || onz == PETSC_DECIDE) onz = 10 * bs;
163406a29025Sstefano_zampini 
1635d975228cSstefano_zampini   if (!dnnz) {
16369566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->rmap->n, &hdnnz));
1637d975228cSstefano_zampini     for (i = 0; i < A->rmap->n; i++) hdnnz[i] = dnz;
1638d975228cSstefano_zampini   } else {
16397d968826Sstefano_zampini     hdnnz = (HYPRE_Int *)dnnz;
1640d975228cSstefano_zampini   }
16419566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
1642d975228cSstefano_zampini   if (size > 1) {
1643ddbeb582SStefano Zampini     hypre_AuxParCSRMatrix *aux_matrix;
1644d975228cSstefano_zampini     if (!onnz) {
16459566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(A->rmap->n, &honnz));
1646d975228cSstefano_zampini       for (i = 0; i < A->rmap->n; i++) honnz[i] = onz;
164722235d61SPierre Jolivet     } else honnz = (HYPRE_Int *)onnz;
1648ddbeb582SStefano Zampini     /* SetDiagOffdSizes sets hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0, since it seems
1649ddbeb582SStefano Zampini        they assume the user will input the entire row values, properly sorted
1650336664bdSPierre Jolivet        In PETSc, we don't make such an assumption and set this flag to 1,
1651336664bdSPierre Jolivet        unless the option MAT_SORTED_FULL is set to true.
1652ddbeb582SStefano Zampini        Also, to avoid possible memory leaks, we destroy and recreate the translator
1653ddbeb582SStefano Zampini        This has to be done here, as HYPRE_IJMatrixInitialize will properly initialize
1654ddbeb582SStefano Zampini        the IJ matrix for us */
1655ddbeb582SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
1656ddbeb582SStefano Zampini     hypre_AuxParCSRMatrixDestroy(aux_matrix);
1657ddbeb582SStefano Zampini     hypre_IJMatrixTranslator(hA->ij) = NULL;
1658792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, hA->ij, hdnnz, honnz);
1659ddbeb582SStefano Zampini     aux_matrix                               = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
1660651b1cf9SStefano Zampini     hypre_AuxParCSRMatrixNeedAux(aux_matrix) = !A->sortedfull;
1661d975228cSstefano_zampini   } else {
1662d975228cSstefano_zampini     honnz = NULL;
1663792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetRowSizes, hA->ij, hdnnz);
1664d975228cSstefano_zampini   }
1665ddbeb582SStefano Zampini 
1666af1cf968SStefano Zampini   /* reset assembled flag and call the initialize method */
1667af1cf968SStefano Zampini   hypre_IJMatrixAssembleFlag(hA->ij) = 0;
16686ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
1669792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij);
16706ea7df73SStefano Zampini #else
1671792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize_v2, hA->ij, HYPRE_MEMORY_HOST);
16726ea7df73SStefano Zampini #endif
167348a46eb9SPierre Jolivet   if (!dnnz) PetscCall(PetscFree(hdnnz));
167448a46eb9SPierre Jolivet   if (!onnz && honnz) PetscCall(PetscFree(honnz));
1675af1cf968SStefano Zampini   /* Match AIJ logic */
167606a29025Sstefano_zampini   A->preallocated = PETSC_TRUE;
1677af1cf968SStefano Zampini   A->assembled    = PETSC_FALSE;
16783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1679d975228cSstefano_zampini }
1680d975228cSstefano_zampini 
1681d975228cSstefano_zampini /*@C
1682d975228cSstefano_zampini   MatHYPRESetPreallocation - Preallocates memory for a sparse parallel matrix in HYPRE IJ format
1683d975228cSstefano_zampini 
1684c3339decSBarry Smith   Collective
1685d975228cSstefano_zampini 
1686d975228cSstefano_zampini   Input Parameters:
1687d975228cSstefano_zampini + A    - the matrix
1688d975228cSstefano_zampini . dnz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1689d975228cSstefano_zampini           (same value is used for all local rows)
1690d975228cSstefano_zampini . dnnz - array containing the number of nonzeros in the various rows of the
1691d975228cSstefano_zampini           DIAGONAL portion of the local submatrix (possibly different for each row)
16922ef1f0ffSBarry Smith           or `NULL` (`PETSC_NULL_INTEGER` in Fortran), if `d_nz` is used to specify the nonzero structure.
16932ef1f0ffSBarry Smith           The size of this array is equal to the number of local rows, i.e `m`.
1694d975228cSstefano_zampini           For matrices that will be factored, you must leave room for (and set)
1695d975228cSstefano_zampini           the diagonal entry even if it is zero.
1696d975228cSstefano_zampini . onz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1697d975228cSstefano_zampini           submatrix (same value is used for all local rows).
1698d975228cSstefano_zampini - onnz - array containing the number of nonzeros in the various rows of the
1699d975228cSstefano_zampini           OFF-DIAGONAL portion of the local submatrix (possibly different for
17002ef1f0ffSBarry Smith           each row) or `NULL` (`PETSC_NULL_INTEGER` in Fortran), if `o_nz` is used to specify the nonzero
1701d975228cSstefano_zampini           structure. The size of this array is equal to the number
17022ef1f0ffSBarry Smith           of local rows, i.e `m`.
1703d975228cSstefano_zampini 
17042fe279fdSBarry Smith   Level: intermediate
17052fe279fdSBarry Smith 
170611a5261eSBarry Smith   Note:
17072ef1f0ffSBarry Smith   If the *nnz parameter is given then the *nz parameter is ignored; for sequential matrices, `onz` and `onnz` are ignored.
1708d975228cSstefano_zampini 
17091cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatMPIAIJSetPreallocation()`, `MATHYPRE`, `MATAIJ`
1710d975228cSstefano_zampini @*/
1711d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHYPRESetPreallocation(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[])
1712d71ae5a4SJacob Faibussowitsch {
1713d975228cSstefano_zampini   PetscFunctionBegin;
1714d975228cSstefano_zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1715d975228cSstefano_zampini   PetscValidType(A, 1);
1716cac4c232SBarry Smith   PetscTryMethod(A, "MatHYPRESetPreallocation_C", (Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]), (A, dnz, dnnz, onz, onnz));
17173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1718d975228cSstefano_zampini }
1719d975228cSstefano_zampini 
172020f4b53cSBarry Smith /*@C
17212ef1f0ffSBarry Smith   MatCreateFromParCSR - Creates a `Mat` from a `hypre_ParCSRMatrix`
1722225daaf8SStefano Zampini 
1723225daaf8SStefano Zampini   Collective
1724225daaf8SStefano Zampini 
1725225daaf8SStefano Zampini   Input Parameters:
17262ef1f0ffSBarry Smith + parcsr   - the pointer to the `hypre_ParCSRMatrix`
17272ef1f0ffSBarry Smith . mtype    - matrix type to be created. Currently `MATAIJ`, `MATIS` and `MATHYPRE` are supported.
172820f4b53cSBarry Smith - copymode - PETSc copying options, see  `PetscCopyMode`
1729225daaf8SStefano Zampini 
1730225daaf8SStefano Zampini   Output Parameter:
1731225daaf8SStefano Zampini . A - the matrix
1732225daaf8SStefano Zampini 
1733225daaf8SStefano Zampini   Level: intermediate
1734225daaf8SStefano Zampini 
1735bfe80ac4SPierre Jolivet .seealso: [](ch_matrices), `Mat`, `MATHYPRE`, `PetscCopyMode`
173620f4b53cSBarry Smith @*/
1737d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreateFromParCSR(hypre_ParCSRMatrix *parcsr, MatType mtype, PetscCopyMode copymode, Mat *A)
1738d71ae5a4SJacob Faibussowitsch {
1739225daaf8SStefano Zampini   Mat        T;
1740978814f1SStefano Zampini   Mat_HYPRE *hA;
1741978814f1SStefano Zampini   MPI_Comm   comm;
1742978814f1SStefano Zampini   PetscInt   rstart, rend, cstart, cend, M, N;
1743d248a85cSRichard Tran Mills   PetscBool  isseqaij, isseqaijmkl, ismpiaij, isaij, ishyp, isis;
1744978814f1SStefano Zampini 
1745978814f1SStefano Zampini   PetscFunctionBegin;
1746978814f1SStefano Zampini   comm = hypre_ParCSRMatrixComm(parcsr);
17479566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQAIJ, &isseqaij));
17489566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQAIJMKL, &isseqaijmkl));
17499566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPIAIJ, &ismpiaij));
17509566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATAIJ, &isaij));
17519566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATHYPRE, &ishyp));
17529566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATIS, &isis));
1753d248a85cSRichard Tran Mills   isaij = (PetscBool)(isseqaij || isseqaijmkl || ismpiaij || isaij);
17546ea7df73SStefano Zampini   /* TODO */
1755aed4548fSBarry 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);
1756978814f1SStefano Zampini   /* access ParCSRMatrix */
1757978814f1SStefano Zampini   rstart = hypre_ParCSRMatrixFirstRowIndex(parcsr);
1758978814f1SStefano Zampini   rend   = hypre_ParCSRMatrixLastRowIndex(parcsr);
1759978814f1SStefano Zampini   cstart = hypre_ParCSRMatrixFirstColDiag(parcsr);
1760978814f1SStefano Zampini   cend   = hypre_ParCSRMatrixLastColDiag(parcsr);
1761978814f1SStefano Zampini   M      = hypre_ParCSRMatrixGlobalNumRows(parcsr);
1762978814f1SStefano Zampini   N      = hypre_ParCSRMatrixGlobalNumCols(parcsr);
1763978814f1SStefano Zampini 
1764978814f1SStefano Zampini   /* create PETSc matrix with MatHYPRE */
17659566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, &T));
1766c2886e86SStefano Zampini   PetscCall(MatSetSizes(T, PetscMax(rend - rstart + 1, 0), PetscMax(cend - cstart + 1, 0), M, N));
17679566063dSJacob Faibussowitsch   PetscCall(MatSetType(T, MATHYPRE));
1768f4f49eeaSPierre Jolivet   hA = (Mat_HYPRE *)T->data;
1769978814f1SStefano Zampini 
1770978814f1SStefano Zampini   /* create HYPRE_IJMatrix */
1771c2886e86SStefano Zampini   PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rstart, rend, cstart, cend, &hA->ij);
1772792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR);
177345b8d346SStefano Zampini 
177445b8d346SStefano Zampini   /* create new ParCSR object if needed */
177545b8d346SStefano Zampini   if (ishyp && copymode == PETSC_COPY_VALUES) {
177645b8d346SStefano Zampini     hypre_ParCSRMatrix *new_parcsr;
17776ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0)
177845b8d346SStefano Zampini     hypre_CSRMatrix *hdiag, *hoffd, *ndiag, *noffd;
177945b8d346SStefano Zampini 
17800e6427aaSSatish Balay     new_parcsr = hypre_ParCSRMatrixClone(parcsr, 0);
178145b8d346SStefano Zampini     hdiag      = hypre_ParCSRMatrixDiag(parcsr);
178245b8d346SStefano Zampini     hoffd      = hypre_ParCSRMatrixOffd(parcsr);
178345b8d346SStefano Zampini     ndiag      = hypre_ParCSRMatrixDiag(new_parcsr);
178445b8d346SStefano Zampini     noffd      = hypre_ParCSRMatrixOffd(new_parcsr);
17859566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hypre_CSRMatrixData(ndiag), hypre_CSRMatrixData(hdiag), hypre_CSRMatrixNumNonzeros(hdiag)));
17869566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hypre_CSRMatrixData(noffd), hypre_CSRMatrixData(hoffd), hypre_CSRMatrixNumNonzeros(hoffd)));
17876ea7df73SStefano Zampini #else
17886ea7df73SStefano Zampini     new_parcsr = hypre_ParCSRMatrixClone(parcsr, 1);
17896ea7df73SStefano Zampini #endif
179045b8d346SStefano Zampini     parcsr   = new_parcsr;
179145b8d346SStefano Zampini     copymode = PETSC_OWN_POINTER;
179245b8d346SStefano Zampini   }
1793978814f1SStefano Zampini 
1794978814f1SStefano Zampini   /* set ParCSR object */
1795978814f1SStefano Zampini   hypre_IJMatrixObject(hA->ij) = parcsr;
17964ec6421dSstefano_zampini   T->preallocated              = PETSC_TRUE;
1797978814f1SStefano Zampini 
1798978814f1SStefano Zampini   /* set assembled flag */
1799978814f1SStefano Zampini   hypre_IJMatrixAssembleFlag(hA->ij) = 1;
18006ea7df73SStefano Zampini #if 0
1801792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize,hA->ij);
18026ea7df73SStefano Zampini #endif
1803225daaf8SStefano Zampini   if (ishyp) {
18046d2a658fSstefano_zampini     PetscMPIInt myid = 0;
18056d2a658fSstefano_zampini 
18066d2a658fSstefano_zampini     /* make sure we always have row_starts and col_starts available */
180748a46eb9SPierre Jolivet     if (HYPRE_AssumedPartitionCheck()) PetscCallMPI(MPI_Comm_rank(comm, &myid));
1808a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
18096d2a658fSstefano_zampini     if (!hypre_ParCSRMatrixOwnsColStarts(parcsr)) {
18106d2a658fSstefano_zampini       PetscLayout map;
18116d2a658fSstefano_zampini 
18129566063dSJacob Faibussowitsch       PetscCall(MatGetLayouts(T, NULL, &map));
18139566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetUp(map));
18142cf14000SStefano Zampini       hypre_ParCSRMatrixColStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid);
18156d2a658fSstefano_zampini     }
18166d2a658fSstefano_zampini     if (!hypre_ParCSRMatrixOwnsRowStarts(parcsr)) {
18176d2a658fSstefano_zampini       PetscLayout map;
18186d2a658fSstefano_zampini 
18199566063dSJacob Faibussowitsch       PetscCall(MatGetLayouts(T, &map, NULL));
18209566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetUp(map));
18212cf14000SStefano Zampini       hypre_ParCSRMatrixRowStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid);
18226d2a658fSstefano_zampini     }
1823a1d2239cSSatish Balay #endif
1824978814f1SStefano Zampini     /* prevent from freeing the pointer */
1825978814f1SStefano Zampini     if (copymode == PETSC_USE_POINTER) hA->inner_free = PETSC_FALSE;
1826225daaf8SStefano Zampini     *A = T;
18279566063dSJacob Faibussowitsch     PetscCall(MatSetOption(*A, MAT_SORTED_FULL, PETSC_TRUE));
18289566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(*A, MAT_FINAL_ASSEMBLY));
18299566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(*A, MAT_FINAL_ASSEMBLY));
1830bb4689ddSStefano Zampini   } else if (isaij) {
1831bb4689ddSStefano Zampini     if (copymode != PETSC_OWN_POINTER) {
1832225daaf8SStefano Zampini       /* prevent from freeing the pointer */
1833225daaf8SStefano Zampini       hA->inner_free = PETSC_FALSE;
18349566063dSJacob Faibussowitsch       PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INITIAL_MATRIX, A));
18359566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&T));
1836225daaf8SStefano Zampini     } else { /* AIJ return type with PETSC_OWN_POINTER */
18379566063dSJacob Faibussowitsch       PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INPLACE_MATRIX, &T));
1838225daaf8SStefano Zampini       *A = T;
1839225daaf8SStefano Zampini     }
1840bb4689ddSStefano Zampini   } else if (isis) {
18419566063dSJacob Faibussowitsch     PetscCall(MatConvert_HYPRE_IS(T, MATIS, MAT_INITIAL_MATRIX, A));
18428cfe8d00SStefano Zampini     if (copymode != PETSC_OWN_POINTER) hA->inner_free = PETSC_FALSE;
18439566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&T));
1844bb4689ddSStefano Zampini   }
18453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1846978814f1SStefano Zampini }
1847978814f1SStefano Zampini 
1848d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPREGetParCSR_HYPRE(Mat A, hypre_ParCSRMatrix **parcsr)
1849d71ae5a4SJacob Faibussowitsch {
1850dd9c0a25Sstefano_zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1851dd9c0a25Sstefano_zampini   HYPRE_Int  type;
1852dd9c0a25Sstefano_zampini 
1853dd9c0a25Sstefano_zampini   PetscFunctionBegin;
185428b400f6SJacob Faibussowitsch   PetscCheck(hA->ij, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "HYPRE_IJMatrix not present");
1855792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
185608401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "HYPRE_IJMatrix is not of type HYPRE_PARCSR");
1857792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)parcsr);
18583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1859dd9c0a25Sstefano_zampini }
1860dd9c0a25Sstefano_zampini 
186120f4b53cSBarry Smith /*@C
1862dd9c0a25Sstefano_zampini   MatHYPREGetParCSR - Gets the pointer to the ParCSR matrix
1863dd9c0a25Sstefano_zampini 
1864cc4c1da9SBarry Smith   Not Collective, No Fortran Support
1865dd9c0a25Sstefano_zampini 
186620f4b53cSBarry Smith   Input Parameter:
186720f4b53cSBarry Smith . A - the `MATHYPRE` object
1868dd9c0a25Sstefano_zampini 
1869dd9c0a25Sstefano_zampini   Output Parameter:
18702ef1f0ffSBarry Smith . parcsr - the pointer to the `hypre_ParCSRMatrix`
1871dd9c0a25Sstefano_zampini 
1872dd9c0a25Sstefano_zampini   Level: intermediate
1873dd9c0a25Sstefano_zampini 
1874bfe80ac4SPierre Jolivet .seealso: [](ch_matrices), `Mat`, `MATHYPRE`, `PetscCopyMode`
187520f4b53cSBarry Smith @*/
1876d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHYPREGetParCSR(Mat A, hypre_ParCSRMatrix **parcsr)
1877d71ae5a4SJacob Faibussowitsch {
1878dd9c0a25Sstefano_zampini   PetscFunctionBegin;
1879dd9c0a25Sstefano_zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1880dd9c0a25Sstefano_zampini   PetscValidType(A, 1);
1881cac4c232SBarry Smith   PetscUseMethod(A, "MatHYPREGetParCSR_C", (Mat, hypre_ParCSRMatrix **), (A, parcsr));
18823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1883dd9c0a25Sstefano_zampini }
1884dd9c0a25Sstefano_zampini 
1885d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_HYPRE(Mat A, PetscBool *missing, PetscInt *dd)
1886d71ae5a4SJacob Faibussowitsch {
188768ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
188868ec7858SStefano Zampini   hypre_CSRMatrix    *ha;
188968ec7858SStefano Zampini   PetscInt            rst;
189068ec7858SStefano Zampini 
189168ec7858SStefano Zampini   PetscFunctionBegin;
189208401ef6SPierre Jolivet   PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented with non-square diagonal blocks");
18939566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &rst, NULL));
18949566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
189568ec7858SStefano Zampini   if (missing) *missing = PETSC_FALSE;
189668ec7858SStefano Zampini   if (dd) *dd = -1;
189768ec7858SStefano Zampini   ha = hypre_ParCSRMatrixDiag(parcsr);
189868ec7858SStefano Zampini   if (ha) {
189968299464SStefano Zampini     PetscInt   size, i;
190068299464SStefano Zampini     HYPRE_Int *ii, *jj;
190168ec7858SStefano Zampini 
190268ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
190368ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
190468ec7858SStefano Zampini     jj   = hypre_CSRMatrixJ(ha);
190568ec7858SStefano Zampini     for (i = 0; i < size; i++) {
190668ec7858SStefano Zampini       PetscInt  j;
190768ec7858SStefano Zampini       PetscBool found = PETSC_FALSE;
190868ec7858SStefano Zampini 
19099371c9d4SSatish Balay       for (j = ii[i]; j < ii[i + 1] && !found; j++) found = (jj[j] == i) ? PETSC_TRUE : PETSC_FALSE;
191068ec7858SStefano Zampini 
191168ec7858SStefano Zampini       if (!found) {
19123ba16761SJacob Faibussowitsch         PetscCall(PetscInfo(A, "Matrix is missing local diagonal entry %" PetscInt_FMT "\n", i));
191368ec7858SStefano Zampini         if (missing) *missing = PETSC_TRUE;
191468ec7858SStefano Zampini         if (dd) *dd = i + rst;
19153ba16761SJacob Faibussowitsch         PetscFunctionReturn(PETSC_SUCCESS);
191668ec7858SStefano Zampini       }
191768ec7858SStefano Zampini     }
191868ec7858SStefano Zampini     if (!size) {
19193ba16761SJacob Faibussowitsch       PetscCall(PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n"));
192068ec7858SStefano Zampini       if (missing) *missing = PETSC_TRUE;
192168ec7858SStefano Zampini       if (dd) *dd = rst;
192268ec7858SStefano Zampini     }
192368ec7858SStefano Zampini   } else {
19243ba16761SJacob Faibussowitsch     PetscCall(PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n"));
192568ec7858SStefano Zampini     if (missing) *missing = PETSC_TRUE;
192668ec7858SStefano Zampini     if (dd) *dd = rst;
192768ec7858SStefano Zampini   }
19283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
192968ec7858SStefano Zampini }
193068ec7858SStefano Zampini 
1931d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatScale_HYPRE(Mat A, PetscScalar s)
1932d71ae5a4SJacob Faibussowitsch {
193368ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
19346ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
193568ec7858SStefano Zampini   hypre_CSRMatrix *ha;
19366ea7df73SStefano Zampini #endif
193739accc25SStefano Zampini   HYPRE_Complex hs;
193868ec7858SStefano Zampini 
193968ec7858SStefano Zampini   PetscFunctionBegin;
19409566063dSJacob Faibussowitsch   PetscCall(PetscHYPREScalarCast(s, &hs));
19419566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
19426ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 19, 0)
1943792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixScale, parcsr, hs);
19446ea7df73SStefano Zampini #else /* diagonal part */
194568ec7858SStefano Zampini   ha = hypre_ParCSRMatrixDiag(parcsr);
194668ec7858SStefano Zampini   if (ha) {
194768299464SStefano Zampini     PetscInt       size, i;
194868299464SStefano Zampini     HYPRE_Int     *ii;
194939accc25SStefano Zampini     HYPRE_Complex *a;
195068ec7858SStefano Zampini 
195168ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
195268ec7858SStefano Zampini     a    = hypre_CSRMatrixData(ha);
195368ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
195439accc25SStefano Zampini     for (i = 0; i < ii[size]; i++) a[i] *= hs;
195568ec7858SStefano Zampini   }
19564cf0e950SBarry Smith   /* off-diagonal part */
195768ec7858SStefano Zampini   ha = hypre_ParCSRMatrixOffd(parcsr);
195868ec7858SStefano Zampini   if (ha) {
195968299464SStefano Zampini     PetscInt       size, i;
196068299464SStefano Zampini     HYPRE_Int     *ii;
196139accc25SStefano Zampini     HYPRE_Complex *a;
196268ec7858SStefano Zampini 
196368ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
196468ec7858SStefano Zampini     a    = hypre_CSRMatrixData(ha);
196568ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
196639accc25SStefano Zampini     for (i = 0; i < ii[size]; i++) a[i] *= hs;
196768ec7858SStefano Zampini   }
19686ea7df73SStefano Zampini #endif
19693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
197068ec7858SStefano Zampini }
197168ec7858SStefano Zampini 
1972d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_HYPRE(Mat A, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
1973d71ae5a4SJacob Faibussowitsch {
197468ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
197568299464SStefano Zampini   HYPRE_Int          *lrows;
197668299464SStefano Zampini   PetscInt            rst, ren, i;
197768ec7858SStefano Zampini 
197868ec7858SStefano Zampini   PetscFunctionBegin;
197908401ef6SPierre Jolivet   PetscCheck(!x && !b, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "To be implemented");
19809566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
19819566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numRows, &lrows));
19829566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &rst, &ren));
198368ec7858SStefano Zampini   for (i = 0; i < numRows; i++) {
19847a46b595SBarry Smith     PetscCheck(rows[i] >= rst && rows[i] < ren, PETSC_COMM_SELF, PETSC_ERR_SUP, "Non-local rows not yet supported");
198568ec7858SStefano Zampini     lrows[i] = rows[i] - rst;
198668ec7858SStefano Zampini   }
1987792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixEliminateRowsCols, parcsr, numRows, lrows);
19889566063dSJacob Faibussowitsch   PetscCall(PetscFree(lrows));
19893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
199068ec7858SStefano Zampini }
199168ec7858SStefano Zampini 
1992d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPRE_CSRMatrix(hypre_CSRMatrix *ha)
1993d71ae5a4SJacob Faibussowitsch {
1994c69f721fSFande Kong   PetscFunctionBegin;
1995c69f721fSFande Kong   if (ha) {
1996c69f721fSFande Kong     HYPRE_Int     *ii, size;
1997c69f721fSFande Kong     HYPRE_Complex *a;
1998c69f721fSFande Kong 
1999c69f721fSFande Kong     size = hypre_CSRMatrixNumRows(ha);
2000c69f721fSFande Kong     a    = hypre_CSRMatrixData(ha);
2001c69f721fSFande Kong     ii   = hypre_CSRMatrixI(ha);
2002c69f721fSFande Kong 
20039566063dSJacob Faibussowitsch     if (a) PetscCall(PetscArrayzero(a, ii[size]));
2004c69f721fSFande Kong   }
20053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2006c69f721fSFande Kong }
2007c69f721fSFande Kong 
200866976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPRE(Mat A)
2009d71ae5a4SJacob Faibussowitsch {
20106ea7df73SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
20116ea7df73SStefano Zampini 
20126ea7df73SStefano Zampini   PetscFunctionBegin;
20136ea7df73SStefano Zampini   if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(hA->ij)) {
2014792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetConstantValues, hA->ij, 0.0);
20156ea7df73SStefano Zampini   } else {
2016c69f721fSFande Kong     hypre_ParCSRMatrix *parcsr;
2017c69f721fSFande Kong 
20189566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
20199566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr)));
20209566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr)));
20216ea7df73SStefano Zampini   }
20223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2023c69f721fSFande Kong }
2024c69f721fSFande Kong 
2025d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_HYPRE_CSRMatrix(hypre_CSRMatrix *hA, PetscInt N, const PetscInt rows[], HYPRE_Complex diag)
2026d71ae5a4SJacob Faibussowitsch {
202739accc25SStefano Zampini   PetscInt       ii;
202839accc25SStefano Zampini   HYPRE_Int     *i, *j;
202939accc25SStefano Zampini   HYPRE_Complex *a;
2030c69f721fSFande Kong 
2031c69f721fSFande Kong   PetscFunctionBegin;
20323ba16761SJacob Faibussowitsch   if (!hA) PetscFunctionReturn(PETSC_SUCCESS);
2033c69f721fSFande Kong 
203439accc25SStefano Zampini   i = hypre_CSRMatrixI(hA);
203539accc25SStefano Zampini   j = hypre_CSRMatrixJ(hA);
2036c69f721fSFande Kong   a = hypre_CSRMatrixData(hA);
2037a32e9c99SJunchao Zhang #if defined(PETSC_HAVE_HYPRE_DEVICE)
2038a32e9c99SJunchao Zhang   if (HYPRE_MEMORY_DEVICE == hypre_CSRMatrixMemoryLocation(hA)) {
2039a32e9c99SJunchao Zhang   #if defined(HYPRE_USING_CUDA)
2040a32e9c99SJunchao Zhang     MatZeroRows_CUDA(N, rows, i, j, a, diag);
2041a32e9c99SJunchao Zhang   #elif defined(HYPRE_USING_HIP)
2042a32e9c99SJunchao Zhang     MatZeroRows_HIP(N, rows, i, j, a, diag);
2043a32e9c99SJunchao Zhang   #elif defined(PETSC_HAVE_KOKKOS)
2044a32e9c99SJunchao Zhang     MatZeroRows_Kokkos(N, rows, i, j, a, diag);
2045a32e9c99SJunchao Zhang   #else
2046a32e9c99SJunchao Zhang     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for MatZeroRows on a hypre matrix in this memory location");
2047a32e9c99SJunchao Zhang   #endif
2048a32e9c99SJunchao Zhang   } else
2049a32e9c99SJunchao Zhang #endif
2050a32e9c99SJunchao Zhang   {
2051c69f721fSFande Kong     for (ii = 0; ii < N; ii++) {
205239accc25SStefano Zampini       HYPRE_Int jj, ibeg, iend, irow;
205339accc25SStefano Zampini 
2054c69f721fSFande Kong       irow = rows[ii];
2055c69f721fSFande Kong       ibeg = i[irow];
2056c69f721fSFande Kong       iend = i[irow + 1];
2057c69f721fSFande Kong       for (jj = ibeg; jj < iend; jj++)
2058c69f721fSFande Kong         if (j[jj] == irow) a[jj] = diag;
2059c69f721fSFande Kong         else a[jj] = 0.0;
2060c69f721fSFande Kong     }
2061a32e9c99SJunchao Zhang   }
20623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2063c69f721fSFande Kong }
2064c69f721fSFande Kong 
2065d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_HYPRE(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
2066d71ae5a4SJacob Faibussowitsch {
2067c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
2068a32e9c99SJunchao Zhang   PetscInt           *lrows, len, *lrows2;
206939accc25SStefano Zampini   HYPRE_Complex       hdiag;
2070c69f721fSFande Kong 
2071c69f721fSFande Kong   PetscFunctionBegin;
207208401ef6SPierre Jolivet   PetscCheck(!x && !b, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Does not support to modify the solution and the right hand size");
20739566063dSJacob Faibussowitsch   PetscCall(PetscHYPREScalarCast(diag, &hdiag));
2074c69f721fSFande Kong   /* retrieve the internal matrix */
20759566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
2076c69f721fSFande Kong   /* get locally owned rows */
20779566063dSJacob Faibussowitsch   PetscCall(MatZeroRowsMapLocal_Private(A, N, rows, &len, &lrows));
2078a32e9c99SJunchao Zhang 
2079a32e9c99SJunchao Zhang #if defined(PETSC_HAVE_HYPRE_DEVICE)
2080a32e9c99SJunchao Zhang   if (HYPRE_MEMORY_DEVICE == hypre_CSRMatrixMemoryLocation(hypre_ParCSRMatrixDiag(parcsr))) {
2081a32e9c99SJunchao Zhang     Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
2082a32e9c99SJunchao Zhang     PetscInt   m;
2083a32e9c99SJunchao Zhang     PetscCall(MatGetLocalSize(A, &m, NULL));
2084a32e9c99SJunchao Zhang     if (!hA->rows_d) {
2085a32e9c99SJunchao Zhang       hA->rows_d = hypre_TAlloc(PetscInt, m, HYPRE_MEMORY_DEVICE);
2086a32e9c99SJunchao Zhang       if (m) PetscCheck(hA->rows_d, PETSC_COMM_SELF, PETSC_ERR_MEM, "HYPRE_TAlloc failed");
2087a32e9c99SJunchao Zhang     }
2088a32e9c99SJunchao Zhang     PetscCheck(len <= m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Too many rows in rows[]");
2089a32e9c99SJunchao Zhang     PetscStackCallExternalVoid("hypre_Memcpy", hypre_Memcpy(hA->rows_d, lrows, sizeof(PetscInt) * len, HYPRE_MEMORY_DEVICE, HYPRE_MEMORY_HOST));
2090a32e9c99SJunchao Zhang     lrows2 = hA->rows_d;
2091a32e9c99SJunchao Zhang   } else
2092a32e9c99SJunchao Zhang #endif
2093a32e9c99SJunchao Zhang   {
2094a32e9c99SJunchao Zhang     lrows2 = lrows;
2095a32e9c99SJunchao Zhang   }
2096a32e9c99SJunchao Zhang 
2097c69f721fSFande Kong   /* zero diagonal part */
2098a32e9c99SJunchao Zhang   PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr), len, lrows2, hdiag));
2099c69f721fSFande Kong   /* zero off-diagonal part */
2100a32e9c99SJunchao Zhang   PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr), len, lrows2, 0.0));
2101c69f721fSFande Kong 
21029566063dSJacob Faibussowitsch   PetscCall(PetscFree(lrows));
21033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2104c69f721fSFande Kong }
2105c69f721fSFande Kong 
2106d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_HYPRE(Mat mat, MatAssemblyType mode)
2107d71ae5a4SJacob Faibussowitsch {
2108c69f721fSFande Kong   PetscFunctionBegin;
21093ba16761SJacob Faibussowitsch   if (mat->nooffprocentries) PetscFunctionReturn(PETSC_SUCCESS);
2110c69f721fSFande Kong 
21119566063dSJacob Faibussowitsch   PetscCall(MatStashScatterBegin_Private(mat, &mat->stash, mat->rmap->range));
21123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2113c69f721fSFande Kong }
2114c69f721fSFande Kong 
2115d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
2116d71ae5a4SJacob Faibussowitsch {
2117c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
21182cf14000SStefano Zampini   HYPRE_Int           hnz;
2119c69f721fSFande Kong 
2120c69f721fSFande Kong   PetscFunctionBegin;
2121c69f721fSFande Kong   /* retrieve the internal matrix */
21229566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
2123c69f721fSFande Kong   /* call HYPRE API */
2124792fecdfSBarry Smith   PetscCallExternal(HYPRE_ParCSRMatrixGetRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v);
21252cf14000SStefano Zampini   if (nz) *nz = (PetscInt)hnz;
21263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2127c69f721fSFande Kong }
2128c69f721fSFande Kong 
2129d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
2130d71ae5a4SJacob Faibussowitsch {
2131c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
21322cf14000SStefano Zampini   HYPRE_Int           hnz;
2133c69f721fSFande Kong 
2134c69f721fSFande Kong   PetscFunctionBegin;
2135c69f721fSFande Kong   /* retrieve the internal matrix */
21369566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
2137c69f721fSFande Kong   /* call HYPRE API */
21382cf14000SStefano Zampini   hnz = nz ? (HYPRE_Int)(*nz) : 0;
2139792fecdfSBarry Smith   PetscCallExternal(HYPRE_ParCSRMatrixRestoreRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v);
21403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2141c69f721fSFande Kong }
2142c69f721fSFande Kong 
2143d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetValues_HYPRE(Mat A, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2144d71ae5a4SJacob Faibussowitsch {
214545b8d346SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
2146c69f721fSFande Kong   PetscInt   i;
21471d4906efSStefano Zampini 
2148c69f721fSFande Kong   PetscFunctionBegin;
21493ba16761SJacob Faibussowitsch   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2150c69f721fSFande Kong   /* Ignore negative row indices
2151c69f721fSFande Kong    * And negative column indices should be automatically ignored in hypre
2152c69f721fSFande Kong    * */
21532cf14000SStefano Zampini   for (i = 0; i < m; i++) {
21542cf14000SStefano Zampini     if (idxm[i] >= 0) {
21552cf14000SStefano Zampini       HYPRE_Int hn = (HYPRE_Int)n;
2156792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetValues, hA->ij, 1, &hn, (HYPRE_BigInt *)&idxm[i], (HYPRE_BigInt *)idxn, (HYPRE_Complex *)(v + i * n));
21572cf14000SStefano Zampini     }
21582cf14000SStefano Zampini   }
21593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2160c69f721fSFande Kong }
2161c69f721fSFande Kong 
2162d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_HYPRE(Mat A, MatOption op, PetscBool flg)
2163d71ae5a4SJacob Faibussowitsch {
2164ddbeb582SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
2165ddbeb582SStefano Zampini 
2166ddbeb582SStefano Zampini   PetscFunctionBegin;
2167c6698e78SStefano Zampini   switch (op) {
2168ddbeb582SStefano Zampini   case MAT_NO_OFF_PROC_ENTRIES:
216948a46eb9SPierre Jolivet     if (flg) PetscCallExternal(HYPRE_IJMatrixSetMaxOffProcElmts, hA->ij, 0);
2170ddbeb582SStefano Zampini     break;
2171651b1cf9SStefano Zampini   case MAT_IGNORE_OFF_PROC_ENTRIES:
2172651b1cf9SStefano Zampini     hA->donotstash = flg;
2173d71ae5a4SJacob Faibussowitsch     break;
2174d71ae5a4SJacob Faibussowitsch   default:
2175d71ae5a4SJacob Faibussowitsch     break;
2176ddbeb582SStefano Zampini   }
21773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2178ddbeb582SStefano Zampini }
2179c69f721fSFande Kong 
2180d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_HYPRE(Mat A, PetscViewer view)
2181d71ae5a4SJacob Faibussowitsch {
218245b8d346SStefano Zampini   PetscViewerFormat format;
218345b8d346SStefano Zampini 
218445b8d346SStefano Zampini   PetscFunctionBegin;
21859566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(view, &format));
21863ba16761SJacob Faibussowitsch   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(PETSC_SUCCESS);
218745b8d346SStefano Zampini   if (format != PETSC_VIEWER_NATIVE) {
21886ea7df73SStefano Zampini     Mat                 B;
21896ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
21906ea7df73SStefano Zampini     PetscErrorCode (*mview)(Mat, PetscViewer) = NULL;
21916ea7df73SStefano Zampini 
21929566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
21939566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(parcsr, MATAIJ, PETSC_USE_POINTER, &B));
21949566063dSJacob Faibussowitsch     PetscCall(MatGetOperation(B, MATOP_VIEW, (void (**)(void))&mview));
219528b400f6SJacob Faibussowitsch     PetscCheck(mview, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Missing view operation");
21969566063dSJacob Faibussowitsch     PetscCall((*mview)(B, view));
21979566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
219845b8d346SStefano Zampini   } else {
219945b8d346SStefano Zampini     Mat_HYPRE  *hA = (Mat_HYPRE *)A->data;
220045b8d346SStefano Zampini     PetscMPIInt size;
220145b8d346SStefano Zampini     PetscBool   isascii;
220245b8d346SStefano Zampini     const char *filename;
220345b8d346SStefano Zampini 
220445b8d346SStefano Zampini     /* HYPRE uses only text files */
22059566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERASCII, &isascii));
220628b400f6SJacob Faibussowitsch     PetscCheck(isascii, PetscObjectComm((PetscObject)view), PETSC_ERR_SUP, "PetscViewerType %s: native HYPRE format needs PETSCVIEWERASCII", ((PetscObject)view)->type_name);
22079566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileGetName(view, &filename));
2208792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixPrint, hA->ij, filename);
22099566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(hA->comm, &size));
221045b8d346SStefano Zampini     if (size > 1) {
22119566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(view, "Matrix files: %s.%05d ... %s.%05d\n", filename, 0, filename, size - 1));
221245b8d346SStefano Zampini     } else {
22139566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(view, "Matrix file: %s.%05d\n", filename, 0));
221445b8d346SStefano Zampini     }
221545b8d346SStefano Zampini   }
22163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
221745b8d346SStefano Zampini }
221845b8d346SStefano Zampini 
2219d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCopy_HYPRE(Mat A, Mat B, MatStructure str)
2220d71ae5a4SJacob Faibussowitsch {
2221465edc17SStefano Zampini   hypre_ParCSRMatrix *acsr, *bcsr;
2222465edc17SStefano Zampini 
2223465edc17SStefano Zampini   PetscFunctionBegin;
2224465edc17SStefano Zampini   if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) {
22259566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &acsr));
22269566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(B, &bcsr));
2227792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixCopy, acsr, bcsr, 1);
22289566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_SORTED_FULL, PETSC_TRUE)); /* "perfect" preallocation, so no need for hypre_AuxParCSRMatrixNeedAux */
22299566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
22309566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
2231465edc17SStefano Zampini   } else {
22329566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
2233465edc17SStefano Zampini   }
22343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2235465edc17SStefano Zampini }
2236465edc17SStefano Zampini 
2237d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_HYPRE(Mat A, Vec d)
2238d71ae5a4SJacob Faibussowitsch {
22396305df00SStefano Zampini   hypre_ParCSRMatrix *parcsr;
22406305df00SStefano Zampini   hypre_CSRMatrix    *dmat;
224139accc25SStefano Zampini   HYPRE_Complex      *a;
22426305df00SStefano Zampini   PetscBool           cong;
22436305df00SStefano Zampini 
22446305df00SStefano Zampini   PetscFunctionBegin;
22459566063dSJacob Faibussowitsch   PetscCall(MatHasCongruentLayouts(A, &cong));
224628b400f6SJacob Faibussowitsch   PetscCheck(cong, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only for square matrices with same local distributions of rows and columns");
22479566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
22486305df00SStefano Zampini   dmat = hypre_ParCSRMatrixDiag(parcsr);
22496305df00SStefano Zampini   if (dmat) {
225006977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
225106977982Sstefanozampini     HYPRE_MemoryLocation mem = hypre_CSRMatrixMemoryLocation(dmat);
225206977982Sstefanozampini #else
225306977982Sstefanozampini     HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST;
225406977982Sstefanozampini #endif
225506977982Sstefanozampini 
225606977982Sstefanozampini     if (mem != HYPRE_MEMORY_HOST) PetscCall(VecGetArrayWriteAndMemType(d, (PetscScalar **)&a, NULL));
225706977982Sstefanozampini     else PetscCall(VecGetArrayWrite(d, (PetscScalar **)&a));
225806977982Sstefanozampini     hypre_CSRMatrixExtractDiagonal(dmat, a, 0);
225906977982Sstefanozampini     if (mem != HYPRE_MEMORY_HOST) PetscCall(VecRestoreArrayWriteAndMemType(d, (PetscScalar **)&a));
226006977982Sstefanozampini     else PetscCall(VecRestoreArrayWrite(d, (PetscScalar **)&a));
22616305df00SStefano Zampini   }
22623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22636305df00SStefano Zampini }
22646305df00SStefano Zampini 
2265363d496dSStefano Zampini #include <petscblaslapack.h>
2266363d496dSStefano Zampini 
2267d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAXPY_HYPRE(Mat Y, PetscScalar a, Mat X, MatStructure str)
2268d71ae5a4SJacob Faibussowitsch {
2269363d496dSStefano Zampini   PetscFunctionBegin;
22706ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
22716ea7df73SStefano Zampini   {
22726ea7df73SStefano Zampini     Mat                 B;
22736ea7df73SStefano Zampini     hypre_ParCSRMatrix *x, *y, *z;
22746ea7df73SStefano Zampini 
22759566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(Y, &y));
22769566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(X, &x));
2277792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixAdd, 1.0, y, 1.0, x, &z);
22789566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(z, MATHYPRE, PETSC_OWN_POINTER, &B));
22799566063dSJacob Faibussowitsch     PetscCall(MatHeaderMerge(Y, &B));
22806ea7df73SStefano Zampini   }
22816ea7df73SStefano Zampini #else
2282363d496dSStefano Zampini   if (str == SAME_NONZERO_PATTERN) {
2283363d496dSStefano Zampini     hypre_ParCSRMatrix *x, *y;
2284363d496dSStefano Zampini     hypre_CSRMatrix    *xloc, *yloc;
2285363d496dSStefano Zampini     PetscInt            xnnz, ynnz;
228639accc25SStefano Zampini     HYPRE_Complex      *xarr, *yarr;
2287363d496dSStefano Zampini     PetscBLASInt        one = 1, bnz;
2288363d496dSStefano Zampini 
22899566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(Y, &y));
22909566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(X, &x));
2291363d496dSStefano Zampini 
2292363d496dSStefano Zampini     /* diagonal block */
2293363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixDiag(x);
2294363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixDiag(y);
2295363d496dSStefano Zampini     xnnz = 0;
2296363d496dSStefano Zampini     ynnz = 0;
2297363d496dSStefano Zampini     xarr = NULL;
2298363d496dSStefano Zampini     yarr = NULL;
2299363d496dSStefano Zampini     if (xloc) {
230039accc25SStefano Zampini       xarr = hypre_CSRMatrixData(xloc);
2301363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
2302363d496dSStefano Zampini     }
2303363d496dSStefano Zampini     if (yloc) {
230439accc25SStefano Zampini       yarr = hypre_CSRMatrixData(yloc);
2305363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
2306363d496dSStefano Zampini     }
230708401ef6SPierre Jolivet     PetscCheck(xnnz == ynnz, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Different number of nonzeros in diagonal block %" PetscInt_FMT " != %" PetscInt_FMT, xnnz, ynnz);
23089566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(xnnz, &bnz));
2309792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one));
2310363d496dSStefano Zampini 
2311363d496dSStefano Zampini     /* off-diagonal block */
2312363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixOffd(x);
2313363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixOffd(y);
2314363d496dSStefano Zampini     xnnz = 0;
2315363d496dSStefano Zampini     ynnz = 0;
2316363d496dSStefano Zampini     xarr = NULL;
2317363d496dSStefano Zampini     yarr = NULL;
2318363d496dSStefano Zampini     if (xloc) {
231939accc25SStefano Zampini       xarr = hypre_CSRMatrixData(xloc);
2320363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
2321363d496dSStefano Zampini     }
2322363d496dSStefano Zampini     if (yloc) {
232339accc25SStefano Zampini       yarr = hypre_CSRMatrixData(yloc);
2324363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
2325363d496dSStefano Zampini     }
232608401ef6SPierre 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);
23279566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(xnnz, &bnz));
2328792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one));
2329363d496dSStefano Zampini   } else if (str == SUBSET_NONZERO_PATTERN) {
23309566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic(Y, a, X, str));
2331363d496dSStefano Zampini   } else {
2332363d496dSStefano Zampini     Mat B;
2333363d496dSStefano Zampini 
23349566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic_Preallocate(Y, X, &B));
23359566063dSJacob Faibussowitsch     PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str));
23369566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(Y, &B));
2337363d496dSStefano Zampini   }
23386ea7df73SStefano Zampini #endif
23393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2340363d496dSStefano Zampini }
2341363d496dSStefano Zampini 
23422c4ab24aSJunchao Zhang static PetscErrorCode MatDuplicate_HYPRE(Mat A, MatDuplicateOption op, Mat *B)
23432c4ab24aSJunchao Zhang {
23442c4ab24aSJunchao Zhang   hypre_ParCSRMatrix *parcsr = NULL;
23452c4ab24aSJunchao Zhang   PetscCopyMode       cpmode;
23462c4ab24aSJunchao Zhang   Mat_HYPRE          *hA;
23472c4ab24aSJunchao Zhang 
23482c4ab24aSJunchao Zhang   PetscFunctionBegin;
23492c4ab24aSJunchao Zhang   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
23502c4ab24aSJunchao Zhang   if (op == MAT_DO_NOT_COPY_VALUES || op == MAT_SHARE_NONZERO_PATTERN) {
23512c4ab24aSJunchao Zhang     parcsr = hypre_ParCSRMatrixClone(parcsr, 0);
23522c4ab24aSJunchao Zhang     cpmode = PETSC_OWN_POINTER;
23532c4ab24aSJunchao Zhang   } else {
23542c4ab24aSJunchao Zhang     cpmode = PETSC_COPY_VALUES;
23552c4ab24aSJunchao Zhang   }
23562c4ab24aSJunchao Zhang   PetscCall(MatCreateFromParCSR(parcsr, MATHYPRE, cpmode, B));
23572c4ab24aSJunchao Zhang   hA = (Mat_HYPRE *)A->data;
23582c4ab24aSJunchao Zhang   if (hA->cooMat) {
235906977982Sstefanozampini     Mat_HYPRE *hB = (Mat_HYPRE *)((*B)->data);
2360b73e3080SStefano Zampini     op            = (op == MAT_DO_NOT_COPY_VALUES) ? op : MAT_COPY_VALUES;
2361b73e3080SStefano Zampini     /* Cannot simply increase the reference count of hA->cooMat, since B needs to share cooMat's data array */
236206977982Sstefanozampini     PetscCall(MatDuplicate(hA->cooMat, op, &hB->cooMat));
236306977982Sstefanozampini     PetscCall(MatHYPRE_AttachCOOMat(*B));
23642c4ab24aSJunchao Zhang   }
23652c4ab24aSJunchao Zhang   PetscFunctionReturn(PETSC_SUCCESS);
23662c4ab24aSJunchao Zhang }
23672c4ab24aSJunchao Zhang 
2368d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetPreallocationCOO_HYPRE(Mat mat, PetscCount coo_n, PetscInt coo_i[], PetscInt coo_j[])
2369d71ae5a4SJacob Faibussowitsch {
237006977982Sstefanozampini   Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data;
23715fbaff96SJunchao Zhang 
23725fbaff96SJunchao Zhang   PetscFunctionBegin;
2373651b1cf9SStefano Zampini   /* Build an agent matrix cooMat with AIJ format
23745fbaff96SJunchao 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.
23755fbaff96SJunchao Zhang    */
237606977982Sstefanozampini   PetscCall(MatHYPRE_CreateCOOMat(mat));
237706977982Sstefanozampini   PetscCall(MatSetOption(hmat->cooMat, MAT_IGNORE_OFF_PROC_ENTRIES, hmat->donotstash));
237806977982Sstefanozampini   PetscCall(MatSetOption(hmat->cooMat, MAT_NO_OFF_PROC_ENTRIES, mat->nooffprocentries));
2379651b1cf9SStefano Zampini 
2380651b1cf9SStefano Zampini   /* MatSetPreallocationCOO_SeqAIJ and MatSetPreallocationCOO_MPIAIJ uses this specific
2381651b1cf9SStefano Zampini      name to automatically put the diagonal entries first */
238206977982Sstefanozampini   PetscCall(PetscObjectSetName((PetscObject)hmat->cooMat, "_internal_COO_mat_for_hypre"));
238306977982Sstefanozampini   PetscCall(MatSetPreallocationCOO(hmat->cooMat, coo_n, coo_i, coo_j));
238406977982Sstefanozampini   hmat->cooMat->assembled = PETSC_TRUE;
23855fbaff96SJunchao Zhang 
23865fbaff96SJunchao Zhang   /* Copy the sparsity pattern from cooMat to hypre IJMatrix hmat->ij */
23875fbaff96SJunchao Zhang   PetscCall(MatSetOption(mat, MAT_SORTED_FULL, PETSC_TRUE));
238806977982Sstefanozampini   PetscCall(MatHYPRE_CreateFromMat(hmat->cooMat, hmat));      /* Create hmat->ij and preallocate it */
238906977982Sstefanozampini   PetscCall(MatHYPRE_IJMatrixCopyIJ(hmat->cooMat, hmat->ij)); /* Copy A's (i,j) to hmat->ij */
23905fbaff96SJunchao Zhang 
23915fbaff96SJunchao Zhang   mat->preallocated = PETSC_TRUE;
23925fbaff96SJunchao Zhang   PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
23935fbaff96SJunchao Zhang   PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); /* Migrate mat to device if it is bound to. Hypre builds its own SpMV context here */
23945fbaff96SJunchao Zhang 
23952c4ab24aSJunchao Zhang   /* Attach cooMat to mat */
239606977982Sstefanozampini   PetscCall(MatHYPRE_AttachCOOMat(mat));
23973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23985fbaff96SJunchao Zhang }
23995fbaff96SJunchao Zhang 
2400d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesCOO_HYPRE(Mat mat, const PetscScalar v[], InsertMode imode)
2401d71ae5a4SJacob Faibussowitsch {
24025fbaff96SJunchao Zhang   Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data;
24035fbaff96SJunchao Zhang 
24045fbaff96SJunchao Zhang   PetscFunctionBegin;
2405b73e3080SStefano Zampini   PetscCheck(hmat->cooMat, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet");
24065fbaff96SJunchao Zhang   PetscCall(MatSetValuesCOO(hmat->cooMat, v, imode));
2407651b1cf9SStefano Zampini   PetscCall(MatViewFromOptions(hmat->cooMat, (PetscObject)mat, "-cooMat_view"));
24083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24095fbaff96SJunchao Zhang }
24105fbaff96SJunchao Zhang 
241103db1824SAlex Lindsay static PetscErrorCode MatGetCurrentMemType_HYPRE(Mat A, PetscMemType *m)
241203db1824SAlex Lindsay {
241303db1824SAlex Lindsay   PetscBool petsconcpu;
241403db1824SAlex Lindsay 
241503db1824SAlex Lindsay   PetscFunctionBegin;
241603db1824SAlex Lindsay   PetscCall(MatBoundToCPU(A, &petsconcpu));
241703db1824SAlex Lindsay   *m = petsconcpu ? PETSC_MEMTYPE_HOST : PETSC_MEMTYPE_DEVICE;
241803db1824SAlex Lindsay   PetscFunctionReturn(PETSC_SUCCESS);
241903db1824SAlex Lindsay }
242003db1824SAlex Lindsay 
2421a055b5aaSBarry Smith /*MC
24222ef1f0ffSBarry Smith    MATHYPRE - "hypre" - A matrix type to be used for sequential and parallel sparse matrices
2423a055b5aaSBarry Smith           based on the hypre IJ interface.
2424a055b5aaSBarry Smith 
2425a055b5aaSBarry Smith    Level: intermediate
2426a055b5aaSBarry Smith 
24271cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatHYPRESetPreallocation`
2428a055b5aaSBarry Smith M*/
2429d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_HYPRE(Mat B)
2430d71ae5a4SJacob Faibussowitsch {
243163c07aadSStefano Zampini   Mat_HYPRE *hB;
2432a9e6c71bSAlex Lindsay #if defined(PETSC_HAVE_HYPRE_DEVICE)
2433a9e6c71bSAlex Lindsay   HYPRE_MemoryLocation memory_location;
2434a9e6c71bSAlex Lindsay #endif
243563c07aadSStefano Zampini 
243663c07aadSStefano Zampini   PetscFunctionBegin;
2437a9e6c71bSAlex Lindsay   PetscHYPREInitialize();
24384dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&hB));
24396ea7df73SStefano Zampini 
2440978814f1SStefano Zampini   hB->inner_free      = PETSC_TRUE;
2441651b1cf9SStefano Zampini   hB->array_available = PETSC_TRUE;
2442978814f1SStefano Zampini 
244363c07aadSStefano Zampini   B->data = (void *)hB;
244463c07aadSStefano Zampini 
24459566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(B->ops, sizeof(struct _MatOps)));
244663c07aadSStefano Zampini   B->ops->mult                  = MatMult_HYPRE;
244763c07aadSStefano Zampini   B->ops->multtranspose         = MatMultTranspose_HYPRE;
2448414bd5c3SStefano Zampini   B->ops->multadd               = MatMultAdd_HYPRE;
2449414bd5c3SStefano Zampini   B->ops->multtransposeadd      = MatMultTransposeAdd_HYPRE;
245063c07aadSStefano Zampini   B->ops->setup                 = MatSetUp_HYPRE;
245163c07aadSStefano Zampini   B->ops->destroy               = MatDestroy_HYPRE;
245263c07aadSStefano Zampini   B->ops->assemblyend           = MatAssemblyEnd_HYPRE;
2453c69f721fSFande Kong   B->ops->assemblybegin         = MatAssemblyBegin_HYPRE;
2454d975228cSstefano_zampini   B->ops->setvalues             = MatSetValues_HYPRE;
245568ec7858SStefano Zampini   B->ops->missingdiagonal       = MatMissingDiagonal_HYPRE;
245668ec7858SStefano Zampini   B->ops->scale                 = MatScale_HYPRE;
245768ec7858SStefano Zampini   B->ops->zerorowscolumns       = MatZeroRowsColumns_HYPRE;
2458c69f721fSFande Kong   B->ops->zeroentries           = MatZeroEntries_HYPRE;
2459c69f721fSFande Kong   B->ops->zerorows              = MatZeroRows_HYPRE;
2460c69f721fSFande Kong   B->ops->getrow                = MatGetRow_HYPRE;
2461c69f721fSFande Kong   B->ops->restorerow            = MatRestoreRow_HYPRE;
2462c69f721fSFande Kong   B->ops->getvalues             = MatGetValues_HYPRE;
2463ddbeb582SStefano Zampini   B->ops->setoption             = MatSetOption_HYPRE;
246445b8d346SStefano Zampini   B->ops->duplicate             = MatDuplicate_HYPRE;
2465465edc17SStefano Zampini   B->ops->copy                  = MatCopy_HYPRE;
246645b8d346SStefano Zampini   B->ops->view                  = MatView_HYPRE;
24676305df00SStefano Zampini   B->ops->getdiagonal           = MatGetDiagonal_HYPRE;
2468363d496dSStefano Zampini   B->ops->axpy                  = MatAXPY_HYPRE;
24694222ddf1SHong Zhang   B->ops->productsetfromoptions = MatProductSetFromOptions_HYPRE;
247003db1824SAlex Lindsay   B->ops->getcurrentmemtype     = MatGetCurrentMemType_HYPRE;
24716ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
24726ea7df73SStefano Zampini   B->ops->bindtocpu = MatBindToCPU_HYPRE;
2473a9e6c71bSAlex Lindsay   /* Get hypre's default memory location. Users can control this using the corresponding HYPRE_SetMemoryLocation API */
2474a9e6c71bSAlex Lindsay   PetscCallExternal(HYPRE_GetMemoryLocation, &memory_location);
2475a9e6c71bSAlex Lindsay   B->boundtocpu = (memory_location == HYPRE_MEMORY_HOST) ? PETSC_TRUE : PETSC_FALSE;
24766ea7df73SStefano Zampini #endif
247745b8d346SStefano Zampini 
247845b8d346SStefano Zampini   /* build cache for off array entries formed */
24799566063dSJacob Faibussowitsch   PetscCall(MatStashCreate_Private(PetscObjectComm((PetscObject)B), 1, &B->stash));
248063c07aadSStefano Zampini 
24819566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)B), &hB->comm));
24829566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRE));
24839566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_aij_C", MatConvert_HYPRE_AIJ));
24849566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_is_C", MatConvert_HYPRE_IS));
24859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_hypre_C", MatProductSetFromOptions_HYPRE));
24869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaij_hypre_C", MatProductSetFromOptions_HYPRE));
24879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPRESetPreallocation_C", MatHYPRESetPreallocation_HYPRE));
24889566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPREGetParCSR_C", MatHYPREGetParCSR_HYPRE));
24895fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_HYPRE));
24905fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetValuesCOO_C", MatSetValuesCOO_HYPRE));
24916ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
24926ea7df73SStefano Zampini   #if defined(HYPRE_USING_HIP)
249306977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijhipsparse_hypre_C", MatProductSetFromOptions_HYPRE));
249406977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaijhipsparse_hypre_C", MatProductSetFromOptions_HYPRE));
24959566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP));
24969566063dSJacob Faibussowitsch   PetscCall(MatSetVecType(B, VECHIP));
24976ea7df73SStefano Zampini   #endif
24986ea7df73SStefano Zampini   #if defined(HYPRE_USING_CUDA)
249906977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijcusparse_hypre_C", MatProductSetFromOptions_HYPRE));
250006977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaijcusparse_hypre_C", MatProductSetFromOptions_HYPRE));
25019566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
25029566063dSJacob Faibussowitsch   PetscCall(MatSetVecType(B, VECCUDA));
25036ea7df73SStefano Zampini   #endif
25046ea7df73SStefano Zampini #endif
25053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
250663c07aadSStefano Zampini }
2507