xref: /petsc/src/mat/impls/hypre/mhypre.c (revision 1c265611c3247aab058ed5a2cf81d2df6e2d1334)
163c07aadSStefano Zampini /*
263c07aadSStefano Zampini     Creates hypre ijmatrix from PETSc matrix
363c07aadSStefano Zampini */
4225daaf8SStefano Zampini 
5c6698e78SStefano Zampini #include <petscpkg_version.h>
639accc25SStefano Zampini #include <petsc/private/petschypre.h>
7dd9c0a25Sstefano_zampini #include <petscmathypre.h>
863c07aadSStefano Zampini #include <petsc/private/matimpl.h>
9a4af0ceeSJacob Faibussowitsch #include <petsc/private/deviceimpl.h>
1063c07aadSStefano Zampini #include <../src/mat/impls/hypre/mhypre.h>
1163c07aadSStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
1258968eb6SStefano Zampini #include <../src/vec/vec/impls/hypre/vhyp.h>
1358968eb6SStefano Zampini #include <HYPRE.h>
14c1a070e6SStefano Zampini #include <HYPRE_utilities.h>
15cd8bc7baSStefano Zampini #include <_hypre_parcsr_ls.h>
1668ec7858SStefano Zampini #include <_hypre_sstruct_ls.h>
1763c07aadSStefano Zampini 
180e6427aaSSatish Balay #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0)
190e6427aaSSatish Balay   #define hypre_ParCSRMatrixClone(A, B) hypre_ParCSRMatrixCompleteClone(A)
200e6427aaSSatish Balay #endif
210e6427aaSSatish Balay 
2263c07aadSStefano Zampini static PetscErrorCode MatHYPRE_CreateFromMat(Mat, Mat_HYPRE *);
2363c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat, Mat, HYPRE_IJMatrix);
24b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_MPIAIJ(Mat, HYPRE_IJMatrix);
25b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_SeqAIJ(Mat, HYPRE_IJMatrix);
2639accc25SStefano Zampini static PetscErrorCode MatHYPRE_MultKernel_Private(Mat, HYPRE_Complex, Vec, HYPRE_Complex, Vec, PetscBool);
276ea7df73SStefano Zampini static PetscErrorCode MatSetValues_HYPRE(Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[], const PetscScalar[], InsertMode ins);
2863c07aadSStefano Zampini 
29d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat A_d, Mat A_o, HYPRE_IJMatrix ij)
30d71ae5a4SJacob Faibussowitsch {
3163c07aadSStefano Zampini   PetscInt        i, n_d, n_o;
3263c07aadSStefano Zampini   const PetscInt *ia_d, *ia_o;
3363c07aadSStefano Zampini   PetscBool       done_d = PETSC_FALSE, done_o = PETSC_FALSE;
342cf14000SStefano Zampini   HYPRE_Int      *nnz_d = NULL, *nnz_o = NULL;
3563c07aadSStefano Zampini 
3663c07aadSStefano Zampini   PetscFunctionBegin;
3763c07aadSStefano Zampini   if (A_d) { /* determine number of nonzero entries in local diagonal part */
389566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(A_d, 0, PETSC_FALSE, PETSC_FALSE, &n_d, &ia_d, NULL, &done_d));
3963c07aadSStefano Zampini     if (done_d) {
409566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(n_d, &nnz_d));
41ad540459SPierre Jolivet       for (i = 0; i < n_d; i++) nnz_d[i] = ia_d[i + 1] - ia_d[i];
4263c07aadSStefano Zampini     }
439566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowIJ(A_d, 0, PETSC_FALSE, PETSC_FALSE, NULL, &ia_d, NULL, &done_d));
4463c07aadSStefano Zampini   }
4563c07aadSStefano Zampini   if (A_o) { /* determine number of nonzero entries in local off-diagonal part */
469566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(A_o, 0, PETSC_FALSE, PETSC_FALSE, &n_o, &ia_o, NULL, &done_o));
4763c07aadSStefano Zampini     if (done_o) {
489566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(n_o, &nnz_o));
49ad540459SPierre Jolivet       for (i = 0; i < n_o; i++) nnz_o[i] = ia_o[i + 1] - ia_o[i];
5063c07aadSStefano Zampini     }
519566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowIJ(A_o, 0, PETSC_FALSE, PETSC_FALSE, &n_o, &ia_o, NULL, &done_o));
5263c07aadSStefano Zampini   }
5363c07aadSStefano Zampini   if (done_d) {    /* set number of nonzeros in HYPRE IJ matrix */
5463c07aadSStefano Zampini     if (!done_o) { /* only diagonal part */
559566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(n_d, &nnz_o));
5663c07aadSStefano Zampini     }
57c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0)
58c6698e78SStefano Zampini     { /* If we don't do this, the columns of the matrix will be all zeros! */
59c6698e78SStefano Zampini       hypre_AuxParCSRMatrix *aux_matrix;
60c6698e78SStefano Zampini       aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij);
61c6698e78SStefano Zampini       hypre_AuxParCSRMatrixDestroy(aux_matrix);
62c6698e78SStefano Zampini       hypre_IJMatrixTranslator(ij) = NULL;
63792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, ij, nnz_d, nnz_o);
6422235d61SPierre Jolivet       /* it seems they partially fixed it in 2.19.0 */
6522235d61SPierre Jolivet   #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
66c6698e78SStefano Zampini       aux_matrix                               = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij);
67c6698e78SStefano Zampini       hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1;
6822235d61SPierre Jolivet   #endif
69c6698e78SStefano Zampini     }
70c6698e78SStefano Zampini #else
71792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, ij, nnz_d, nnz_o);
72c6698e78SStefano Zampini #endif
739566063dSJacob Faibussowitsch     PetscCall(PetscFree(nnz_d));
749566063dSJacob Faibussowitsch     PetscCall(PetscFree(nnz_o));
7563c07aadSStefano Zampini   }
763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7763c07aadSStefano Zampini }
7863c07aadSStefano Zampini 
79d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_CreateFromMat(Mat A, Mat_HYPRE *hA)
80d71ae5a4SJacob Faibussowitsch {
8163c07aadSStefano Zampini   PetscInt rstart, rend, cstart, cend;
8263c07aadSStefano Zampini 
8363c07aadSStefano Zampini   PetscFunctionBegin;
849566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
859566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
8663c07aadSStefano Zampini   rstart = A->rmap->rstart;
8763c07aadSStefano Zampini   rend   = A->rmap->rend;
8863c07aadSStefano Zampini   cstart = A->cmap->rstart;
8963c07aadSStefano Zampini   cend   = A->cmap->rend;
90ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
91651b1cf9SStefano Zampini   if (hA->ij) {
92651b1cf9SStefano Zampini     if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL;
93651b1cf9SStefano Zampini     PetscCallExternal(HYPRE_IJMatrixDestroy, hA->ij);
94651b1cf9SStefano Zampini   }
95792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rstart, rend - 1, cstart, cend - 1, &hA->ij);
96792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR);
9763c07aadSStefano Zampini   {
9863c07aadSStefano Zampini     PetscBool       same;
9963c07aadSStefano Zampini     Mat             A_d, A_o;
10063c07aadSStefano Zampini     const PetscInt *colmap;
1019566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &same));
10263c07aadSStefano Zampini     if (same) {
1039566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJGetSeqAIJ(A, &A_d, &A_o, &colmap));
1049566063dSJacob Faibussowitsch       PetscCall(MatHYPRE_IJMatrixPreallocate(A_d, A_o, hA->ij));
1053ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
10663c07aadSStefano Zampini     }
1079566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIBAIJ, &same));
10863c07aadSStefano Zampini     if (same) {
1099566063dSJacob Faibussowitsch       PetscCall(MatMPIBAIJGetSeqBAIJ(A, &A_d, &A_o, &colmap));
1109566063dSJacob Faibussowitsch       PetscCall(MatHYPRE_IJMatrixPreallocate(A_d, A_o, hA->ij));
1113ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
11263c07aadSStefano Zampini     }
1139566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &same));
11463c07aadSStefano Zampini     if (same) {
1159566063dSJacob Faibussowitsch       PetscCall(MatHYPRE_IJMatrixPreallocate(A, NULL, hA->ij));
1163ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
11763c07aadSStefano Zampini     }
1189566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQBAIJ, &same));
11963c07aadSStefano Zampini     if (same) {
1209566063dSJacob Faibussowitsch       PetscCall(MatHYPRE_IJMatrixPreallocate(A, NULL, hA->ij));
1213ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
12263c07aadSStefano Zampini     }
12363c07aadSStefano Zampini   }
1243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12563c07aadSStefano Zampini }
12663c07aadSStefano Zampini 
127b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ(Mat A, HYPRE_IJMatrix ij)
128d71ae5a4SJacob Faibussowitsch {
12963c07aadSStefano Zampini   PetscBool flg;
13063c07aadSStefano Zampini 
13163c07aadSStefano Zampini   PetscFunctionBegin;
1326ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
133792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize, ij);
1346ea7df73SStefano Zampini #else
135792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize_v2, ij, HYPRE_MEMORY_HOST);
1366ea7df73SStefano Zampini #endif
1379566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &flg));
138b73e3080SStefano Zampini   if (flg) {
139b73e3080SStefano Zampini     PetscCall(MatHYPRE_IJMatrixCopyIJ_MPIAIJ(A, ij));
1403ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
14163c07aadSStefano Zampini   }
1429566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &flg));
14363c07aadSStefano Zampini   if (flg) {
144b73e3080SStefano Zampini     PetscCall(MatHYPRE_IJMatrixCopyIJ_SeqAIJ(A, ij));
1453ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
14663c07aadSStefano Zampini   }
147b73e3080SStefano Zampini   PetscCheck(PETSC_FALSE, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "No support for matrix type %s", ((PetscObject)A)->type_name);
14887ef5fa6SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
14963c07aadSStefano Zampini }
15063c07aadSStefano Zampini 
151b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_SeqAIJ(Mat A, HYPRE_IJMatrix ij)
152d71ae5a4SJacob Faibussowitsch {
15363c07aadSStefano Zampini   Mat_SeqAIJ            *pdiag = (Mat_SeqAIJ *)A->data;
15458968eb6SStefano Zampini   HYPRE_Int              type;
15563c07aadSStefano Zampini   hypre_ParCSRMatrix    *par_matrix;
15663c07aadSStefano Zampini   hypre_AuxParCSRMatrix *aux_matrix;
15763c07aadSStefano Zampini   hypre_CSRMatrix       *hdiag;
1582cf14000SStefano Zampini   PetscBool              sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
15963c07aadSStefano Zampini 
16063c07aadSStefano Zampini   PetscFunctionBegin;
161792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type);
16208401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
163792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix);
16463c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(par_matrix);
16563c07aadSStefano Zampini   /*
16663c07aadSStefano Zampini        this is the Hack part where we monkey directly with the hypre datastructures
16763c07aadSStefano Zampini   */
1682cf14000SStefano Zampini   if (sameint) {
1699566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hdiag->i, pdiag->i, A->rmap->n + 1));
1709566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hdiag->j, pdiag->j, pdiag->nz));
1712cf14000SStefano Zampini   } else {
1722cf14000SStefano Zampini     PetscInt i;
1732cf14000SStefano Zampini 
1742cf14000SStefano Zampini     for (i = 0; i < A->rmap->n + 1; i++) hdiag->i[i] = (HYPRE_Int)pdiag->i[i];
1752cf14000SStefano Zampini     for (i = 0; i < pdiag->nz; i++) hdiag->j[i] = (HYPRE_Int)pdiag->j[i];
1762cf14000SStefano Zampini   }
1776ea7df73SStefano Zampini 
178ea9daf28SStefano Zampini   aux_matrix                               = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij);
17963c07aadSStefano Zampini   hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
1803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18163c07aadSStefano Zampini }
18263c07aadSStefano Zampini 
183b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_MPIAIJ(Mat A, HYPRE_IJMatrix ij)
184d71ae5a4SJacob Faibussowitsch {
18563c07aadSStefano Zampini   Mat_MPIAIJ            *pA = (Mat_MPIAIJ *)A->data;
18663c07aadSStefano Zampini   Mat_SeqAIJ            *pdiag, *poffd;
18763c07aadSStefano Zampini   PetscInt               i, *garray = pA->garray, *jj, cstart, *pjj;
1882cf14000SStefano Zampini   HYPRE_Int             *hjj, type;
18963c07aadSStefano Zampini   hypre_ParCSRMatrix    *par_matrix;
19063c07aadSStefano Zampini   hypre_AuxParCSRMatrix *aux_matrix;
19163c07aadSStefano Zampini   hypre_CSRMatrix       *hdiag, *hoffd;
1922cf14000SStefano Zampini   PetscBool              sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
19363c07aadSStefano Zampini 
19463c07aadSStefano Zampini   PetscFunctionBegin;
19563c07aadSStefano Zampini   pdiag = (Mat_SeqAIJ *)pA->A->data;
19663c07aadSStefano Zampini   poffd = (Mat_SeqAIJ *)pA->B->data;
197da81f932SPierre Jolivet   /* cstart is only valid for square MPIAIJ laid out in the usual way */
1989566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &cstart, NULL));
19963c07aadSStefano Zampini 
200792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type);
20108401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
202792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix);
20363c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(par_matrix);
20463c07aadSStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(par_matrix);
20563c07aadSStefano Zampini 
2062cf14000SStefano Zampini   if (sameint) {
2079566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hdiag->i, pdiag->i, pA->A->rmap->n + 1));
2082cf14000SStefano Zampini   } else {
209f4f49eeaSPierre Jolivet     for (i = 0; i < pA->A->rmap->n + 1; i++) hdiag->i[i] = (HYPRE_Int)pdiag->i[i];
2102cf14000SStefano Zampini   }
211b73e3080SStefano Zampini 
2122cf14000SStefano Zampini   hjj = hdiag->j;
2132cf14000SStefano Zampini   pjj = pdiag->j;
214c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0)
2152cf14000SStefano Zampini   for (i = 0; i < pdiag->nz; i++) hjj[i] = pjj[i];
216c6698e78SStefano Zampini #else
2172cf14000SStefano Zampini   for (i = 0; i < pdiag->nz; i++) hjj[i] = cstart + pjj[i];
218c6698e78SStefano Zampini #endif
2192cf14000SStefano Zampini   if (sameint) {
2209566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hoffd->i, poffd->i, pA->A->rmap->n + 1));
2212cf14000SStefano Zampini   } else {
222f4f49eeaSPierre Jolivet     for (i = 0; i < pA->A->rmap->n + 1; i++) hoffd->i[i] = (HYPRE_Int)poffd->i[i];
2232cf14000SStefano Zampini   }
2242cf14000SStefano Zampini 
22506977982Sstefanozampini   jj = (PetscInt *)hoffd->j;
226c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0)
227792fecdfSBarry Smith   PetscCallExternal(hypre_CSRMatrixBigInitialize, hoffd);
228c6698e78SStefano Zampini   jj = (PetscInt *)hoffd->big_j;
229c6698e78SStefano Zampini #endif
2302cf14000SStefano Zampini   pjj = poffd->j;
23163c07aadSStefano Zampini   for (i = 0; i < poffd->nz; i++) jj[i] = garray[pjj[i]];
232c6698e78SStefano Zampini 
233ea9daf28SStefano Zampini   aux_matrix                               = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij);
23463c07aadSStefano Zampini   hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
2353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23663c07aadSStefano Zampini }
23763c07aadSStefano Zampini 
238d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_HYPRE_IS(Mat A, MatType mtype, MatReuse reuse, Mat *B)
239d71ae5a4SJacob Faibussowitsch {
240f4f49eeaSPierre Jolivet   Mat_HYPRE             *mhA = (Mat_HYPRE *)A->data;
2412df22349SStefano Zampini   Mat                    lA;
2422df22349SStefano Zampini   ISLocalToGlobalMapping rl2g, cl2g;
2432df22349SStefano Zampini   IS                     is;
2442df22349SStefano Zampini   hypre_ParCSRMatrix    *hA;
2452df22349SStefano Zampini   hypre_CSRMatrix       *hdiag, *hoffd;
2462df22349SStefano Zampini   MPI_Comm               comm;
24739accc25SStefano Zampini   HYPRE_Complex         *hdd, *hod, *aa;
24839accc25SStefano Zampini   PetscScalar           *data;
2492cf14000SStefano Zampini   HYPRE_BigInt          *col_map_offd;
2502cf14000SStefano Zampini   HYPRE_Int             *hdi, *hdj, *hoi, *hoj;
2512df22349SStefano Zampini   PetscInt              *ii, *jj, *iptr, *jptr;
2522df22349SStefano Zampini   PetscInt               cum, dr, dc, oc, str, stc, nnz, i, jd, jo, M, N;
25358968eb6SStefano Zampini   HYPRE_Int              type;
25406977982Sstefanozampini   MatType                lmattype   = NULL;
25506977982Sstefanozampini   PetscBool              freeparcsr = PETSC_FALSE;
2562df22349SStefano Zampini 
2572df22349SStefano Zampini   PetscFunctionBegin;
258a1787963SStefano Zampini   comm = PetscObjectComm((PetscObject)A);
259792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, mhA->ij, &type);
26008401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
261792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, mhA->ij, (void **)&hA);
26206977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
26306977982Sstefanozampini   if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(mhA->ij)) {
26406977982Sstefanozampini     /* Support by copying back on the host and copy to GPU
26506977982Sstefanozampini        Kind of inefficient, but this is the best we can do now */
26606977982Sstefanozampini   #if defined(HYPRE_USING_HIP)
26706977982Sstefanozampini     lmattype = MATSEQAIJHIPSPARSE;
26806977982Sstefanozampini   #elif defined(HYPRE_USING_CUDA)
26906977982Sstefanozampini     lmattype = MATSEQAIJCUSPARSE;
27006977982Sstefanozampini   #endif
27106977982Sstefanozampini     hA         = hypre_ParCSRMatrixClone_v2(hA, 1, HYPRE_MEMORY_HOST);
27206977982Sstefanozampini     freeparcsr = PETSC_TRUE;
27306977982Sstefanozampini   }
27406977982Sstefanozampini #endif
2752df22349SStefano Zampini   M     = hypre_ParCSRMatrixGlobalNumRows(hA);
2762df22349SStefano Zampini   N     = hypre_ParCSRMatrixGlobalNumCols(hA);
2772df22349SStefano Zampini   str   = hypre_ParCSRMatrixFirstRowIndex(hA);
2782df22349SStefano Zampini   stc   = hypre_ParCSRMatrixFirstColDiag(hA);
2792df22349SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(hA);
2802df22349SStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(hA);
2812df22349SStefano Zampini   dr    = hypre_CSRMatrixNumRows(hdiag);
2822df22349SStefano Zampini   dc    = hypre_CSRMatrixNumCols(hdiag);
2832df22349SStefano Zampini   nnz   = hypre_CSRMatrixNumNonzeros(hdiag);
2842df22349SStefano Zampini   hdi   = hypre_CSRMatrixI(hdiag);
2852df22349SStefano Zampini   hdj   = hypre_CSRMatrixJ(hdiag);
2862df22349SStefano Zampini   hdd   = hypre_CSRMatrixData(hdiag);
2872df22349SStefano Zampini   oc    = hypre_CSRMatrixNumCols(hoffd);
2882df22349SStefano Zampini   nnz += hypre_CSRMatrixNumNonzeros(hoffd);
2892df22349SStefano Zampini   hoi = hypre_CSRMatrixI(hoffd);
2902df22349SStefano Zampini   hoj = hypre_CSRMatrixJ(hoffd);
2912df22349SStefano Zampini   hod = hypre_CSRMatrixData(hoffd);
2922df22349SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
2932df22349SStefano Zampini     PetscInt *aux;
2942df22349SStefano Zampini 
2952df22349SStefano Zampini     /* generate l2g maps for rows and cols */
2969566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(comm, dr, str, 1, &is));
2979566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g));
2989566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
2992df22349SStefano Zampini     col_map_offd = hypre_ParCSRMatrixColMapOffd(hA);
3009566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dc + oc, &aux));
3012df22349SStefano Zampini     for (i = 0; i < dc; i++) aux[i] = i + stc;
3022df22349SStefano Zampini     for (i = 0; i < oc; i++) aux[i + dc] = col_map_offd[i];
3039566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, dc + oc, aux, PETSC_OWN_POINTER, &is));
3049566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g));
3059566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
3062df22349SStefano Zampini     /* create MATIS object */
3079566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm, B));
3089566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(*B, dr, dc, M, N));
3099566063dSJacob Faibussowitsch     PetscCall(MatSetType(*B, MATIS));
3109566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(*B, rl2g, cl2g));
3119566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
3129566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
3132df22349SStefano Zampini 
3142df22349SStefano Zampini     /* allocate CSR for local matrix */
3159566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dr + 1, &iptr));
3169566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &jptr));
3179566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &data));
3182df22349SStefano Zampini   } else {
3192df22349SStefano Zampini     PetscInt  nr;
3202df22349SStefano Zampini     PetscBool done;
3219566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(*B, &lA));
3229566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(lA, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&iptr, (const PetscInt **)&jptr, &done));
32308401ef6SPierre Jolivet     PetscCheck(nr == dr, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of rows in local mat! %" PetscInt_FMT " != %" PetscInt_FMT, nr, dr);
32408401ef6SPierre Jolivet     PetscCheck(iptr[nr] >= nnz, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of nonzeros in local mat! reuse %" PetscInt_FMT " requested %" PetscInt_FMT, iptr[nr], nnz);
32506977982Sstefanozampini     PetscCall(MatSeqAIJGetArrayWrite(lA, &data));
3262df22349SStefano Zampini   }
3272df22349SStefano Zampini   /* merge local matrices */
3282df22349SStefano Zampini   ii  = iptr;
3292df22349SStefano Zampini   jj  = jptr;
33039accc25SStefano Zampini   aa  = (HYPRE_Complex *)data; /* this cast fixes the clang error when doing the assignments below: implicit conversion from 'HYPRE_Complex' (aka '_Complex double') to 'double' is not permitted in C++ */
3312df22349SStefano Zampini   *ii = *(hdi++) + *(hoi++);
3322df22349SStefano Zampini   for (jd = 0, jo = 0, cum = 0; *ii < nnz; cum++) {
33339accc25SStefano Zampini     PetscScalar *aold = (PetscScalar *)aa;
3342df22349SStefano Zampini     PetscInt    *jold = jj, nc = jd + jo;
3359371c9d4SSatish Balay     for (; jd < *hdi; jd++) {
3369371c9d4SSatish Balay       *jj++ = *hdj++;
3379371c9d4SSatish Balay       *aa++ = *hdd++;
3389371c9d4SSatish Balay     }
3399371c9d4SSatish Balay     for (; jo < *hoi; jo++) {
3409371c9d4SSatish Balay       *jj++ = *hoj++ + dc;
3419371c9d4SSatish Balay       *aa++ = *hod++;
3429371c9d4SSatish Balay     }
3432df22349SStefano Zampini     *(++ii) = *(hdi++) + *(hoi++);
3449566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithScalarArray(jd + jo - nc, jold, aold));
3452df22349SStefano Zampini   }
3462df22349SStefano Zampini   for (; cum < dr; cum++) *(++ii) = nnz;
3472df22349SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
348a033916dSStefano Zampini     Mat_SeqAIJ *a;
349a033916dSStefano Zampini 
3509566063dSJacob Faibussowitsch     PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, dr, dc + oc, iptr, jptr, data, &lA));
351a033916dSStefano Zampini     /* hack SeqAIJ */
352f4f49eeaSPierre Jolivet     a          = (Mat_SeqAIJ *)lA->data;
353a033916dSStefano Zampini     a->free_a  = PETSC_TRUE;
354a033916dSStefano Zampini     a->free_ij = PETSC_TRUE;
35506977982Sstefanozampini     if (lmattype) PetscCall(MatConvert(lA, lmattype, MAT_INPLACE_MATRIX, &lA));
35606977982Sstefanozampini     PetscCall(MatISSetLocalMat(*B, lA));
3579566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&lA));
35806977982Sstefanozampini   } else {
35906977982Sstefanozampini     PetscCall(MatSeqAIJRestoreArrayWrite(lA, &data));
3602df22349SStefano Zampini   }
3619566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY));
3629566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY));
36348a46eb9SPierre Jolivet   if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, B));
36406977982Sstefanozampini   if (freeparcsr) PetscCallExternal(hypre_ParCSRMatrixDestroy, hA);
3653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3662df22349SStefano Zampini }
3672df22349SStefano Zampini 
36806977982Sstefanozampini static PetscErrorCode MatHYPRE_DestroyCOOMat(Mat mat)
369d71ae5a4SJacob Faibussowitsch {
37006977982Sstefanozampini   Mat_HYPRE *hA = (Mat_HYPRE *)mat->data;
37163c07aadSStefano Zampini 
37263c07aadSStefano Zampini   PetscFunctionBegin;
37306977982Sstefanozampini   if (hA->cooMat) { /* If cooMat is present we need to destroy the column indices */
37406977982Sstefanozampini     PetscCall(MatDestroy(&hA->cooMat));
37506977982Sstefanozampini     if (hA->cooMatAttached) {
37606977982Sstefanozampini       hypre_CSRMatrix     *csr;
37706977982Sstefanozampini       hypre_ParCSRMatrix  *parcsr;
37806977982Sstefanozampini       HYPRE_MemoryLocation mem;
37906977982Sstefanozampini 
38006977982Sstefanozampini       PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
38106977982Sstefanozampini       csr = hypre_ParCSRMatrixDiag(parcsr);
38206977982Sstefanozampini       if (csr) {
38306977982Sstefanozampini         mem = hypre_CSRMatrixMemoryLocation(csr);
38406977982Sstefanozampini         PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixJ(csr), mem));
38506977982Sstefanozampini         PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixBigJ(csr), mem));
386b73e3080SStefano Zampini       }
38706977982Sstefanozampini       csr = hypre_ParCSRMatrixOffd(parcsr);
38806977982Sstefanozampini       if (csr) {
38906977982Sstefanozampini         mem = hypre_CSRMatrixMemoryLocation(csr);
39006977982Sstefanozampini         PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixJ(csr), mem));
39106977982Sstefanozampini         PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixBigJ(csr), mem));
392b73e3080SStefano Zampini       }
393b73e3080SStefano Zampini     }
39406977982Sstefanozampini   }
39506977982Sstefanozampini   hA->cooMatAttached = PETSC_FALSE;
396b73e3080SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
397b73e3080SStefano Zampini }
398b73e3080SStefano Zampini 
39906977982Sstefanozampini static PetscErrorCode MatHYPRE_CreateCOOMat(Mat mat)
400b73e3080SStefano Zampini {
40106977982Sstefanozampini   MPI_Comm    comm;
40206977982Sstefanozampini   PetscMPIInt size;
40306977982Sstefanozampini   PetscLayout rmap, cmap;
40406977982Sstefanozampini   Mat_HYPRE  *hmat    = (Mat_HYPRE *)mat->data;
40506977982Sstefanozampini   MatType     matType = MATAIJ; /* default type of cooMat */
406b73e3080SStefano Zampini 
407b73e3080SStefano Zampini   PetscFunctionBegin;
40806977982Sstefanozampini   /* Build an agent matrix cooMat with AIJ format
40906977982Sstefanozampini      It has the same sparsity pattern as mat, and also shares the data array with mat. We use cooMat to do the COO work.
41006977982Sstefanozampini    */
41106977982Sstefanozampini   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
41206977982Sstefanozampini   PetscCallMPI(MPI_Comm_size(comm, &size));
41306977982Sstefanozampini   PetscCall(PetscLayoutSetUp(mat->rmap));
41406977982Sstefanozampini   PetscCall(PetscLayoutSetUp(mat->cmap));
41506977982Sstefanozampini   PetscCall(MatGetLayouts(mat, &rmap, &cmap));
416b73e3080SStefano Zampini 
41706977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
41806977982Sstefanozampini   if (!mat->boundtocpu) { /* mat will be on device, so will cooMat */
41906977982Sstefanozampini   #if defined(HYPRE_USING_HIP)
42006977982Sstefanozampini     matType = MATAIJHIPSPARSE;
42106977982Sstefanozampini   #elif defined(HYPRE_USING_CUDA)
42206977982Sstefanozampini     matType = MATAIJCUSPARSE;
42306977982Sstefanozampini   #else
42406977982Sstefanozampini     SETERRQ(comm, PETSC_ERR_SUP, "Do not know the HYPRE device");
42506977982Sstefanozampini   #endif
426b73e3080SStefano Zampini   }
42706977982Sstefanozampini #endif
42806977982Sstefanozampini 
42906977982Sstefanozampini   /* Do COO preallocation through cooMat */
43006977982Sstefanozampini   PetscCall(MatHYPRE_DestroyCOOMat(mat));
43106977982Sstefanozampini   PetscCall(MatCreate(comm, &hmat->cooMat));
43206977982Sstefanozampini   PetscCall(MatSetType(hmat->cooMat, matType));
43306977982Sstefanozampini   PetscCall(MatSetLayouts(hmat->cooMat, rmap, cmap));
43406977982Sstefanozampini 
43506977982Sstefanozampini   /* allocate local matrices if needed */
43606977982Sstefanozampini   PetscCall(MatMPIAIJSetPreallocation(hmat->cooMat, 0, NULL, 0, NULL));
43706977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
43806977982Sstefanozampini }
43906977982Sstefanozampini 
44006977982Sstefanozampini /* Attach cooMat data array to hypre matrix.
44106977982Sstefanozampini    When AIJCUPMSPARSE will support raw device pointers and not THRUSTARRAY
44206977982Sstefanozampini    we should swap the arrays: i.e., attach hypre matrix array to cooMat
44306977982Sstefanozampini    This is because hypre should be in charge of handling the memory,
44406977982Sstefanozampini    cooMat is only a way to reuse PETSc COO code.
44506977982Sstefanozampini    attaching the memory will then be done at MatSetValuesCOO time and it will dynamically
44606977982Sstefanozampini    support hypre matrix migrating to host.
44706977982Sstefanozampini */
44806977982Sstefanozampini static PetscErrorCode MatHYPRE_AttachCOOMat(Mat mat)
44906977982Sstefanozampini {
45006977982Sstefanozampini   Mat_HYPRE           *hmat = (Mat_HYPRE *)mat->data;
45106977982Sstefanozampini   hypre_CSRMatrix     *diag, *offd;
45206977982Sstefanozampini   hypre_ParCSRMatrix  *parCSR;
45306977982Sstefanozampini   HYPRE_MemoryLocation hmem = HYPRE_MEMORY_HOST;
45406977982Sstefanozampini   PetscMemType         pmem;
45506977982Sstefanozampini   Mat                  A, B;
45606977982Sstefanozampini   PetscScalar         *a;
45706977982Sstefanozampini   PetscMPIInt          size;
45806977982Sstefanozampini   MPI_Comm             comm;
45906977982Sstefanozampini 
46006977982Sstefanozampini   PetscFunctionBegin;
46106977982Sstefanozampini   PetscCheck(hmat->cooMat, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet");
46206977982Sstefanozampini   if (hmat->cooMatAttached) PetscFunctionReturn(PETSC_SUCCESS);
46306977982Sstefanozampini   PetscCheck(hmat->cooMat->preallocated, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix is not preallocated");
46406977982Sstefanozampini   PetscCall(PetscObjectSetName((PetscObject)hmat->cooMat, "_internal_COO_mat_for_hypre"));
46506977982Sstefanozampini   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
46606977982Sstefanozampini   PetscCallMPI(MPI_Comm_size(comm, &size));
46706977982Sstefanozampini 
46806977982Sstefanozampini   /* Alias cooMat's data array to IJMatrix's */
46906977982Sstefanozampini   PetscCallExternal(HYPRE_IJMatrixGetObject, hmat->ij, (void **)&parCSR);
47006977982Sstefanozampini   diag = hypre_ParCSRMatrixDiag(parCSR);
47106977982Sstefanozampini   offd = hypre_ParCSRMatrixOffd(parCSR);
47206977982Sstefanozampini 
47306977982Sstefanozampini   A = (size == 1) ? hmat->cooMat : ((Mat_MPIAIJ *)hmat->cooMat->data)->A;
47406977982Sstefanozampini   B = (size == 1) ? NULL : ((Mat_MPIAIJ *)hmat->cooMat->data)->B;
47506977982Sstefanozampini 
47606977982Sstefanozampini   PetscCall(PetscObjectSetName((PetscObject)A, "_internal_COO_mat_for_hypre"));
47706977982Sstefanozampini   hmem = hypre_CSRMatrixMemoryLocation(diag);
47806977982Sstefanozampini   PetscCall(MatSeqAIJGetCSRAndMemType(A, NULL, NULL, &a, &pmem));
47906977982Sstefanozampini   PetscAssert((PetscMemTypeHost(pmem) && hmem == HYPRE_MEMORY_HOST) || (PetscMemTypeDevice(pmem) && hmem == HYPRE_MEMORY_DEVICE), comm, PETSC_ERR_PLIB, "PETSc and hypre's memory types mismatch");
48006977982Sstefanozampini   PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(diag), hmem));
48106977982Sstefanozampini   hypre_CSRMatrixData(diag)     = (HYPRE_Complex *)a;
48206977982Sstefanozampini   hypre_CSRMatrixOwnsData(diag) = 0; /* Take ownership of (j,a) away from hypre. As a result, we need to free them on our own */
48306977982Sstefanozampini 
48406977982Sstefanozampini   if (B) {
48506977982Sstefanozampini     hmem = hypre_CSRMatrixMemoryLocation(offd);
48606977982Sstefanozampini     PetscCall(MatSeqAIJGetCSRAndMemType(B, NULL, NULL, &a, &pmem));
48706977982Sstefanozampini     PetscAssert((PetscMemTypeHost(pmem) && hmem == HYPRE_MEMORY_HOST) || (PetscMemTypeDevice(pmem) && hmem == HYPRE_MEMORY_DEVICE), comm, PETSC_ERR_PLIB, "PETSc and hypre's memory types mismatch");
48806977982Sstefanozampini     PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(offd), hmem));
48906977982Sstefanozampini     hypre_CSRMatrixData(offd)     = (HYPRE_Complex *)a;
49006977982Sstefanozampini     hypre_CSRMatrixOwnsData(offd) = 0;
49106977982Sstefanozampini   }
49206977982Sstefanozampini   hmat->cooMatAttached = PETSC_TRUE;
49306977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
49406977982Sstefanozampini }
49506977982Sstefanozampini 
496*1c265611SJunchao Zhang // Build COO's coordinate list i[], j[] based on CSR's i[], j[] arrays and the number of local rows 'n'
49706977982Sstefanozampini static PetscErrorCode CSRtoCOO_Private(PetscInt n, const PetscInt ii[], const PetscInt jj[], PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j)
49806977982Sstefanozampini {
49906977982Sstefanozampini   PetscInt *cooi, *cooj;
50006977982Sstefanozampini 
50106977982Sstefanozampini   PetscFunctionBegin;
50206977982Sstefanozampini   *ncoo = ii[n];
50306977982Sstefanozampini   PetscCall(PetscMalloc2(*ncoo, &cooi, *ncoo, &cooj));
50406977982Sstefanozampini   for (PetscInt i = 0; i < n; i++) {
50506977982Sstefanozampini     for (PetscInt j = ii[i]; j < ii[i + 1]; j++) cooi[j] = i;
50606977982Sstefanozampini   }
50706977982Sstefanozampini   PetscCall(PetscArraycpy(cooj, jj, *ncoo));
50806977982Sstefanozampini   *coo_i = cooi;
50906977982Sstefanozampini   *coo_j = cooj;
51006977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
51106977982Sstefanozampini }
51206977982Sstefanozampini 
513*1c265611SJunchao Zhang // Similar to CSRtoCOO_Private, but the CSR's i[], j[] are of type HYPRE_Int
51406977982Sstefanozampini static PetscErrorCode CSRtoCOO_HYPRE_Int_Private(PetscInt n, const HYPRE_Int ii[], const HYPRE_Int jj[], PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j)
51506977982Sstefanozampini {
51606977982Sstefanozampini   PetscInt *cooi, *cooj;
51706977982Sstefanozampini 
51806977982Sstefanozampini   PetscFunctionBegin;
51906977982Sstefanozampini   *ncoo = ii[n];
52006977982Sstefanozampini   PetscCall(PetscMalloc2(*ncoo, &cooi, *ncoo, &cooj));
52106977982Sstefanozampini   for (PetscInt i = 0; i < n; i++) {
52206977982Sstefanozampini     for (HYPRE_Int j = ii[i]; j < ii[i + 1]; j++) cooi[j] = i;
52306977982Sstefanozampini   }
52406977982Sstefanozampini   for (PetscCount i = 0; i < *ncoo; i++) cooj[i] = jj[i];
52506977982Sstefanozampini   *coo_i = cooi;
52606977982Sstefanozampini   *coo_j = cooj;
52706977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
52806977982Sstefanozampini }
52906977982Sstefanozampini 
530*1c265611SJunchao Zhang // Build a COO data structure for the seqaij matrix, as if the nonzeros are laid out in the same order as in the CSR
53106977982Sstefanozampini static PetscErrorCode MatSeqAIJGetCOO_Private(Mat A, PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j)
53206977982Sstefanozampini {
53306977982Sstefanozampini   PetscInt        n;
53406977982Sstefanozampini   const PetscInt *ii, *jj;
53506977982Sstefanozampini   PetscBool       done;
53606977982Sstefanozampini 
53706977982Sstefanozampini   PetscFunctionBegin;
53806977982Sstefanozampini   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &done));
53906977982Sstefanozampini   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Failure for MatGetRowIJ");
54006977982Sstefanozampini   PetscCall(CSRtoCOO_Private(n, ii, jj, ncoo, coo_i, coo_j));
54106977982Sstefanozampini   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &done));
54206977982Sstefanozampini   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Failure for MatRestoreRowIJ");
54306977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
54406977982Sstefanozampini }
54506977982Sstefanozampini 
546*1c265611SJunchao Zhang // Build a COO data structure for the hypreCSRMatrix, as if the nonzeros are laid out in the same order as in the hypreCSRMatrix
54706977982Sstefanozampini static PetscErrorCode hypreCSRMatrixGetCOO_Private(hypre_CSRMatrix *A, PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j)
54806977982Sstefanozampini {
54906977982Sstefanozampini   PetscInt             n = hypre_CSRMatrixNumRows(A);
55006977982Sstefanozampini   HYPRE_Int           *ii, *jj;
55106977982Sstefanozampini   HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST;
55206977982Sstefanozampini 
55306977982Sstefanozampini   PetscFunctionBegin;
55406977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
55506977982Sstefanozampini   mem = hypre_CSRMatrixMemoryLocation(A);
55606977982Sstefanozampini   if (mem != HYPRE_MEMORY_HOST) {
55706977982Sstefanozampini     PetscCount nnz = hypre_CSRMatrixNumNonzeros(A);
55806977982Sstefanozampini     PetscCall(PetscMalloc2(n + 1, &ii, nnz, &jj));
55906977982Sstefanozampini     hypre_TMemcpy(ii, hypre_CSRMatrixI(A), HYPRE_Int, n + 1, HYPRE_MEMORY_HOST, mem);
56006977982Sstefanozampini     hypre_TMemcpy(jj, hypre_CSRMatrixJ(A), HYPRE_Int, nnz, HYPRE_MEMORY_HOST, mem);
56106977982Sstefanozampini   } else {
56206977982Sstefanozampini #else
56306977982Sstefanozampini   {
56406977982Sstefanozampini #endif
56506977982Sstefanozampini     ii = hypre_CSRMatrixI(A);
56606977982Sstefanozampini     jj = hypre_CSRMatrixJ(A);
56706977982Sstefanozampini   }
56806977982Sstefanozampini   PetscCall(CSRtoCOO_HYPRE_Int_Private(n, ii, jj, ncoo, coo_i, coo_j));
56906977982Sstefanozampini   if (mem != HYPRE_MEMORY_HOST) PetscCall(PetscFree2(ii, jj));
57006977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
57106977982Sstefanozampini }
57206977982Sstefanozampini 
57306977982Sstefanozampini static PetscErrorCode MatSetValuesCOOFromCSRMatrix_Private(Mat A, hypre_CSRMatrix *H)
57406977982Sstefanozampini {
57506977982Sstefanozampini   PetscBool            iscpu = PETSC_TRUE;
57606977982Sstefanozampini   PetscScalar         *a;
57706977982Sstefanozampini   HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST;
57806977982Sstefanozampini 
57906977982Sstefanozampini   PetscFunctionBegin;
58006977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
58106977982Sstefanozampini   mem = hypre_CSRMatrixMemoryLocation(H);
58206977982Sstefanozampini   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATSEQAIJ, &iscpu));
58306977982Sstefanozampini #endif
58406977982Sstefanozampini   if (iscpu && mem != HYPRE_MEMORY_HOST) {
58506977982Sstefanozampini     PetscCount nnz = hypre_CSRMatrixNumNonzeros(H);
58606977982Sstefanozampini     PetscCall(PetscMalloc1(nnz, &a));
58706977982Sstefanozampini     hypre_TMemcpy(a, hypre_CSRMatrixData(H), PetscScalar, nnz, HYPRE_MEMORY_HOST, mem);
58806977982Sstefanozampini   } else {
58906977982Sstefanozampini     a = (PetscScalar *)hypre_CSRMatrixData(H);
59006977982Sstefanozampini   }
59106977982Sstefanozampini   PetscCall(MatSetValuesCOO(A, a, INSERT_VALUES));
59206977982Sstefanozampini   if (iscpu && mem != HYPRE_MEMORY_HOST) PetscCall(PetscFree(a));
593b73e3080SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
594b73e3080SStefano Zampini }
595b73e3080SStefano Zampini 
596b73e3080SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType type, MatReuse reuse, Mat *B)
597b73e3080SStefano Zampini {
598b73e3080SStefano Zampini   MPI_Comm   comm = PetscObjectComm((PetscObject)A);
59906977982Sstefanozampini   Mat        M = NULL, dH = NULL, oH = NULL, dA = NULL, oA = NULL;
600b73e3080SStefano Zampini   PetscBool  ismpiaij, issbaij, isbaij;
601b73e3080SStefano Zampini   Mat_HYPRE *hA;
602b73e3080SStefano Zampini 
603b73e3080SStefano Zampini   PetscFunctionBegin;
604b73e3080SStefano Zampini   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &issbaij, MATSEQSBAIJ, MATMPIBAIJ, ""));
605b73e3080SStefano Zampini   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &isbaij, MATSEQBAIJ, MATMPIBAIJ, ""));
606b73e3080SStefano Zampini   if (isbaij || issbaij) { /* handle BAIJ and SBAIJ */
607b73e3080SStefano Zampini     PetscBool ismpi;
608b73e3080SStefano Zampini     MatType   newtype;
609b73e3080SStefano Zampini 
610b73e3080SStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &ismpi, MATMPISBAIJ, MATMPIBAIJ, ""));
611b73e3080SStefano Zampini     newtype = ismpi ? MATMPIAIJ : MATSEQAIJ;
61263c07aadSStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
613b73e3080SStefano Zampini       PetscCall(MatConvert(*B, newtype, MAT_INPLACE_MATRIX, B));
614b73e3080SStefano Zampini       PetscCall(MatConvert(A, newtype, MAT_REUSE_MATRIX, B));
615b73e3080SStefano Zampini       PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B));
616b73e3080SStefano Zampini     } else if (reuse == MAT_INITIAL_MATRIX) {
617b73e3080SStefano Zampini       PetscCall(MatConvert(A, newtype, MAT_INITIAL_MATRIX, B));
618b73e3080SStefano Zampini       PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B));
61963c07aadSStefano Zampini     } else {
620b73e3080SStefano Zampini       PetscCall(MatConvert(A, newtype, MAT_INPLACE_MATRIX, &A));
621b73e3080SStefano Zampini       PetscCall(MatConvert(A, MATHYPRE, MAT_INPLACE_MATRIX, &A));
622b73e3080SStefano Zampini     }
623b73e3080SStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
624b73e3080SStefano Zampini   }
62506977982Sstefanozampini 
62606977982Sstefanozampini   dA = A;
627b73e3080SStefano Zampini   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
628b73e3080SStefano Zampini   if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(A, &dA, &oA, NULL));
62906977982Sstefanozampini 
630b73e3080SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
63106977982Sstefanozampini     PetscCount coo_n;
63206977982Sstefanozampini     PetscInt  *coo_i, *coo_j;
63306977982Sstefanozampini 
6349566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm, &M));
6359566063dSJacob Faibussowitsch     PetscCall(MatSetType(M, MATHYPRE));
6369566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(M, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
637b73e3080SStefano Zampini     PetscCall(MatSetOption(M, MAT_SORTED_FULL, PETSC_TRUE));
638b73e3080SStefano Zampini     PetscCall(MatSetOption(M, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE));
639b73e3080SStefano Zampini 
640b73e3080SStefano Zampini     hA = (Mat_HYPRE *)M->data;
64106977982Sstefanozampini     PetscCall(MatHYPRE_CreateFromMat(A, hA));
64206977982Sstefanozampini     PetscCall(MatHYPRE_IJMatrixCopyIJ(A, hA->ij));
64306977982Sstefanozampini 
64406977982Sstefanozampini     PetscCall(MatHYPRE_CreateCOOMat(M));
64506977982Sstefanozampini 
64606977982Sstefanozampini     dH = hA->cooMat;
64706977982Sstefanozampini     PetscCall(PetscObjectBaseTypeCompare((PetscObject)hA->cooMat, MATMPIAIJ, &ismpiaij));
64806977982Sstefanozampini     if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(hA->cooMat, &dH, &oH, NULL));
64906977982Sstefanozampini 
65006977982Sstefanozampini     PetscCall(PetscObjectSetName((PetscObject)dH, "_internal_COO_mat_for_hypre"));
65106977982Sstefanozampini     PetscCall(MatSeqAIJGetCOO_Private(dA, &coo_n, &coo_i, &coo_j));
65206977982Sstefanozampini     PetscCall(MatSetPreallocationCOO(dH, coo_n, coo_i, coo_j));
65306977982Sstefanozampini     PetscCall(PetscFree2(coo_i, coo_j));
65406977982Sstefanozampini     if (oH) {
65506977982Sstefanozampini       PetscCall(PetscLayoutDestroy(&oH->cmap));
65606977982Sstefanozampini       PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)oH), oA->cmap->n, oA->cmap->n, 1, &oH->cmap));
65706977982Sstefanozampini       PetscCall(MatSeqAIJGetCOO_Private(oA, &coo_n, &coo_i, &coo_j));
65806977982Sstefanozampini       PetscCall(MatSetPreallocationCOO(oH, coo_n, coo_i, coo_j));
65906977982Sstefanozampini       PetscCall(PetscFree2(coo_i, coo_j));
66006977982Sstefanozampini     }
66106977982Sstefanozampini     hA->cooMat->assembled = PETSC_TRUE;
66206977982Sstefanozampini 
663b73e3080SStefano Zampini     M->preallocated = PETSC_TRUE;
66406977982Sstefanozampini     PetscCall(MatAssemblyBegin(M, MAT_FINAL_ASSEMBLY));
66506977982Sstefanozampini     PetscCall(MatAssemblyEnd(M, MAT_FINAL_ASSEMBLY));
66606977982Sstefanozampini 
66706977982Sstefanozampini     PetscCall(MatHYPRE_AttachCOOMat(M));
66884d4e069SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) *B = M;
669b73e3080SStefano Zampini   } else M = *B;
670b73e3080SStefano Zampini 
671b73e3080SStefano Zampini   hA = (Mat_HYPRE *)M->data;
67206977982Sstefanozampini   PetscCheck(hA->cooMat, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet");
67306977982Sstefanozampini 
67406977982Sstefanozampini   dH = hA->cooMat;
67506977982Sstefanozampini   PetscCall(PetscObjectBaseTypeCompare((PetscObject)hA->cooMat, MATMPIAIJ, &ismpiaij));
67606977982Sstefanozampini   if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(hA->cooMat, &dH, &oH, NULL));
67706977982Sstefanozampini 
67806977982Sstefanozampini   PetscScalar *a;
67906977982Sstefanozampini   PetscCall(MatSeqAIJGetCSRAndMemType(dA, NULL, NULL, &a, NULL));
68006977982Sstefanozampini   PetscCall(MatSetValuesCOO(dH, a, INSERT_VALUES));
68106977982Sstefanozampini   if (oH) {
68206977982Sstefanozampini     PetscCall(MatSeqAIJGetCSRAndMemType(oA, NULL, NULL, &a, NULL));
68306977982Sstefanozampini     PetscCall(MatSetValuesCOO(oH, a, INSERT_VALUES));
68406977982Sstefanozampini   }
685b73e3080SStefano Zampini 
68648a46eb9SPierre Jolivet   if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &M));
6873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
68863c07aadSStefano Zampini }
68963c07aadSStefano Zampini 
690d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_HYPRE_AIJ(Mat A, MatType mtype, MatReuse reuse, Mat *B)
691d71ae5a4SJacob Faibussowitsch {
69206977982Sstefanozampini   Mat                 M, dA = NULL, oA = NULL;
69363c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
69406977982Sstefanozampini   hypre_CSRMatrix    *dH, *oH;
69563c07aadSStefano Zampini   MPI_Comm            comm;
69606977982Sstefanozampini   PetscBool           ismpiaij, isseqaij;
69763c07aadSStefano Zampini 
69863c07aadSStefano Zampini   PetscFunctionBegin;
69963c07aadSStefano Zampini   comm = PetscObjectComm((PetscObject)A);
70063c07aadSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
7019566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATMPIAIJ, &ismpiaij));
7029566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATSEQAIJ, &isseqaij));
70306977982Sstefanozampini     PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Only MATMPIAIJ or MATSEQAIJ base types are supported");
70463c07aadSStefano Zampini   }
70506977982Sstefanozampini   PetscCall(MatHYPREGetParCSR(A, &parcsr));
7066ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
70706977982Sstefanozampini   if (HYPRE_MEMORY_DEVICE == hypre_ParCSRMatrixMemoryLocation(parcsr)) {
70806977982Sstefanozampini     PetscBool isaij;
70906977982Sstefanozampini 
71006977982Sstefanozampini     PetscCall(PetscStrcmp(mtype, MATAIJ, &isaij));
71106977982Sstefanozampini     if (isaij) {
71206977982Sstefanozampini       PetscMPIInt size;
71306977982Sstefanozampini 
7149566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_size(comm, &size));
71506977982Sstefanozampini   #if defined(HYPRE_USING_HIP)
71606977982Sstefanozampini       mtype = size > 1 ? MATMPIAIJHIPSPARSE : MATSEQAIJHIPSPARSE;
71706977982Sstefanozampini   #elif defined(HYPRE_USING_CUDA)
71806977982Sstefanozampini       mtype = size > 1 ? MATMPIAIJCUSPARSE : MATSEQAIJCUSPARSE;
71906977982Sstefanozampini   #else
72006977982Sstefanozampini       mtype = size > 1 ? MATMPIAIJ : MATSEQAIJ;
72106977982Sstefanozampini   #endif
72263c07aadSStefano Zampini     }
72363c07aadSStefano Zampini   }
72406977982Sstefanozampini #endif
72506977982Sstefanozampini   dH = hypre_ParCSRMatrixDiag(parcsr);
72606977982Sstefanozampini   oH = hypre_ParCSRMatrixOffd(parcsr);
7279371c9d4SSatish Balay   if (reuse != MAT_REUSE_MATRIX) {
72806977982Sstefanozampini     PetscCount coo_n;
72906977982Sstefanozampini     PetscInt  *coo_i, *coo_j;
73063c07aadSStefano Zampini 
73106977982Sstefanozampini     PetscCall(MatCreate(comm, &M));
73206977982Sstefanozampini     PetscCall(MatSetType(M, mtype));
73306977982Sstefanozampini     PetscCall(MatSetSizes(M, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
73406977982Sstefanozampini     PetscCall(MatMPIAIJSetPreallocation(M, 0, NULL, 0, NULL));
73563c07aadSStefano Zampini 
73606977982Sstefanozampini     dA = M;
73706977982Sstefanozampini     PetscCall(PetscObjectBaseTypeCompare((PetscObject)M, MATMPIAIJ, &ismpiaij));
73806977982Sstefanozampini     if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(M, &dA, &oA, NULL));
739a16187a7SStefano Zampini 
74006977982Sstefanozampini     PetscCall(hypreCSRMatrixGetCOO_Private(dH, &coo_n, &coo_i, &coo_j));
74106977982Sstefanozampini     PetscCall(MatSetPreallocationCOO(dA, coo_n, coo_i, coo_j));
74206977982Sstefanozampini     PetscCall(PetscFree2(coo_i, coo_j));
74306977982Sstefanozampini     if (ismpiaij) {
74406977982Sstefanozampini       HYPRE_Int nc = hypre_CSRMatrixNumCols(oH);
745a16187a7SStefano Zampini 
74606977982Sstefanozampini       PetscCall(PetscLayoutDestroy(&oA->cmap));
74706977982Sstefanozampini       PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)oA), nc, nc, 1, &oA->cmap));
74806977982Sstefanozampini       PetscCall(hypreCSRMatrixGetCOO_Private(oH, &coo_n, &coo_i, &coo_j));
74906977982Sstefanozampini       PetscCall(MatSetPreallocationCOO(oA, coo_n, coo_i, coo_j));
75006977982Sstefanozampini       PetscCall(PetscFree2(coo_i, coo_j));
751a16187a7SStefano Zampini 
75206977982Sstefanozampini       /* garray */
753f4f49eeaSPierre Jolivet       Mat_MPIAIJ   *aij    = (Mat_MPIAIJ *)M->data;
75406977982Sstefanozampini       HYPRE_BigInt *harray = hypre_ParCSRMatrixColMapOffd(parcsr);
75506977982Sstefanozampini       PetscInt     *garray;
75606977982Sstefanozampini 
75706977982Sstefanozampini       PetscCall(PetscFree(aij->garray));
75806977982Sstefanozampini       PetscCall(PetscMalloc1(nc, &garray));
75906977982Sstefanozampini       for (HYPRE_Int i = 0; i < nc; i++) garray[i] = (PetscInt)harray[i];
76006977982Sstefanozampini       aij->garray = garray;
76106977982Sstefanozampini       PetscCall(MatSetUpMultiply_MPIAIJ(M));
762a16187a7SStefano Zampini     }
76306977982Sstefanozampini     if (reuse == MAT_INITIAL_MATRIX) *B = M;
76406977982Sstefanozampini   } else M = *B;
765225daaf8SStefano Zampini 
76606977982Sstefanozampini   dA = M;
76706977982Sstefanozampini   PetscCall(PetscObjectBaseTypeCompare((PetscObject)M, MATMPIAIJ, &ismpiaij));
76806977982Sstefanozampini   if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(M, &dA, &oA, NULL));
76906977982Sstefanozampini   PetscCall(MatSetValuesCOOFromCSRMatrix_Private(dA, dH));
77006977982Sstefanozampini   if (oA) PetscCall(MatSetValuesCOOFromCSRMatrix_Private(oA, oH));
77106977982Sstefanozampini   M->assembled = PETSC_TRUE;
77206977982Sstefanozampini   if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &M));
7733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
77463c07aadSStefano Zampini }
77563c07aadSStefano Zampini 
776d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJGetParCSR_Private(Mat A, hypre_ParCSRMatrix **hA)
777d71ae5a4SJacob Faibussowitsch {
778613e5ff0Sstefano_zampini   hypre_ParCSRMatrix *tA;
779c1a070e6SStefano Zampini   hypre_CSRMatrix    *hdiag, *hoffd;
780c1a070e6SStefano Zampini   Mat_SeqAIJ         *diag, *offd;
7812cf14000SStefano Zampini   PetscInt           *garray, i, noffd, dnnz, onnz, *row_starts, *col_starts;
782c1a070e6SStefano Zampini   MPI_Comm            comm = PetscObjectComm((PetscObject)A);
783613e5ff0Sstefano_zampini   PetscBool           ismpiaij, isseqaij;
7842cf14000SStefano Zampini   PetscBool           sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
7856ea7df73SStefano Zampini   HYPRE_Int          *hdi = NULL, *hdj = NULL, *hoi = NULL, *hoj = NULL;
7865c97c10fSStefano Zampini   PetscInt           *pdi = NULL, *pdj = NULL, *poi = NULL, *poj = NULL;
78706977982Sstefanozampini   PetscBool           iscuda, iship;
78806977982Sstefanozampini #if defined(PETSC_HAVE_DEVICE) && defined(PETSC_HAVE_HYPRE_DEVICE)
78906977982Sstefanozampini   PetscBool boundtocpu = A->boundtocpu;
79006977982Sstefanozampini #else
79106977982Sstefanozampini   PetscBool boundtocpu = PETSC_TRUE;
7926ea7df73SStefano Zampini #endif
793c1a070e6SStefano Zampini 
794c1a070e6SStefano Zampini   PetscFunctionBegin;
7959566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
7969566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isseqaij));
79708401ef6SPierre Jolivet   PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Unsupported type %s", ((PetscObject)A)->type_name);
79806977982Sstefanozampini   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iscuda, MATSEQAIJHIPSPARSE, MATMPIAIJCUSPARSE, ""));
79906977982Sstefanozampini   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iship, MATSEQAIJCUSPARSE, MATMPIAIJHIPSPARSE, ""));
800ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
801c1a070e6SStefano Zampini   if (ismpiaij) {
802f4f49eeaSPierre Jolivet     Mat_MPIAIJ *a = (Mat_MPIAIJ *)A->data;
803c1a070e6SStefano Zampini 
804c1a070e6SStefano Zampini     diag = (Mat_SeqAIJ *)a->A->data;
805c1a070e6SStefano Zampini     offd = (Mat_SeqAIJ *)a->B->data;
80606977982Sstefanozampini     if (!boundtocpu && (iscuda || iship)) {
80706977982Sstefanozampini #if defined(HYPRE_USING_CUDA) && defined(PETSC_HAVE_CUDA)
80806977982Sstefanozampini       if (iscuda) {
8096ea7df73SStefano Zampini         sameint = PETSC_TRUE;
8109566063dSJacob Faibussowitsch         PetscCall(MatSeqAIJCUSPARSEGetIJ(a->A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
8119566063dSJacob Faibussowitsch         PetscCall(MatSeqAIJCUSPARSEGetIJ(a->B, PETSC_FALSE, (const HYPRE_Int **)&hoi, (const HYPRE_Int **)&hoj));
81206977982Sstefanozampini       }
8136ea7df73SStefano Zampini #endif
81406977982Sstefanozampini #if defined(HYPRE_USING_HIP) && defined(PETSC_HAVE_HIP)
81506977982Sstefanozampini       if (iship) {
81606977982Sstefanozampini         sameint = PETSC_TRUE;
81706977982Sstefanozampini         PetscCall(MatSeqAIJHIPSPARSEGetIJ(a->A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
81806977982Sstefanozampini         PetscCall(MatSeqAIJHIPSPARSEGetIJ(a->B, PETSC_FALSE, (const HYPRE_Int **)&hoi, (const HYPRE_Int **)&hoj));
81906977982Sstefanozampini       }
82006977982Sstefanozampini #endif
82106977982Sstefanozampini     } else {
82206977982Sstefanozampini       boundtocpu = PETSC_TRUE;
8236ea7df73SStefano Zampini       pdi        = diag->i;
8246ea7df73SStefano Zampini       pdj        = diag->j;
8256ea7df73SStefano Zampini       poi        = offd->i;
8266ea7df73SStefano Zampini       poj        = offd->j;
8276ea7df73SStefano Zampini       if (sameint) {
8286ea7df73SStefano Zampini         hdi = (HYPRE_Int *)pdi;
8296ea7df73SStefano Zampini         hdj = (HYPRE_Int *)pdj;
8306ea7df73SStefano Zampini         hoi = (HYPRE_Int *)poi;
8316ea7df73SStefano Zampini         hoj = (HYPRE_Int *)poj;
8326ea7df73SStefano Zampini       }
8336ea7df73SStefano Zampini     }
834c1a070e6SStefano Zampini     garray = a->garray;
835c1a070e6SStefano Zampini     noffd  = a->B->cmap->N;
836c1a070e6SStefano Zampini     dnnz   = diag->nz;
837c1a070e6SStefano Zampini     onnz   = offd->nz;
838c1a070e6SStefano Zampini   } else {
839c1a070e6SStefano Zampini     diag = (Mat_SeqAIJ *)A->data;
840c1a070e6SStefano Zampini     offd = NULL;
84106977982Sstefanozampini     if (!boundtocpu && (iscuda || iship)) {
84206977982Sstefanozampini #if defined(HYPRE_USING_CUDA) && defined(PETSC_HAVE_CUDA)
84306977982Sstefanozampini       if (iscuda) {
8446ea7df73SStefano Zampini         sameint = PETSC_TRUE;
8459566063dSJacob Faibussowitsch         PetscCall(MatSeqAIJCUSPARSEGetIJ(A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
84606977982Sstefanozampini       }
8476ea7df73SStefano Zampini #endif
84806977982Sstefanozampini #if defined(HYPRE_USING_HIP) && defined(PETSC_HAVE_HIP)
84906977982Sstefanozampini       if (iship) {
85006977982Sstefanozampini         sameint = PETSC_TRUE;
85106977982Sstefanozampini         PetscCall(MatSeqAIJHIPSPARSEGetIJ(A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
85206977982Sstefanozampini       }
85306977982Sstefanozampini #endif
85406977982Sstefanozampini     } else {
85506977982Sstefanozampini       boundtocpu = PETSC_TRUE;
8566ea7df73SStefano Zampini       pdi        = diag->i;
8576ea7df73SStefano Zampini       pdj        = diag->j;
8586ea7df73SStefano Zampini       if (sameint) {
8596ea7df73SStefano Zampini         hdi = (HYPRE_Int *)pdi;
8606ea7df73SStefano Zampini         hdj = (HYPRE_Int *)pdj;
8616ea7df73SStefano Zampini       }
8626ea7df73SStefano Zampini     }
863c1a070e6SStefano Zampini     garray = NULL;
864c1a070e6SStefano Zampini     noffd  = 0;
865c1a070e6SStefano Zampini     dnnz   = diag->nz;
866c1a070e6SStefano Zampini     onnz   = 0;
867c1a070e6SStefano Zampini   }
868225daaf8SStefano Zampini 
869c1a070e6SStefano Zampini   /* create a temporary ParCSR */
870c1a070e6SStefano Zampini   if (HYPRE_AssumedPartitionCheck()) {
871c1a070e6SStefano Zampini     PetscMPIInt myid;
872c1a070e6SStefano Zampini 
8739566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &myid));
874c1a070e6SStefano Zampini     row_starts = A->rmap->range + myid;
875c1a070e6SStefano Zampini     col_starts = A->cmap->range + myid;
876c1a070e6SStefano Zampini   } else {
877c1a070e6SStefano Zampini     row_starts = A->rmap->range;
878c1a070e6SStefano Zampini     col_starts = A->cmap->range;
879c1a070e6SStefano Zampini   }
8802cf14000SStefano Zampini   tA = hypre_ParCSRMatrixCreate(comm, A->rmap->N, A->cmap->N, (HYPRE_BigInt *)row_starts, (HYPRE_BigInt *)col_starts, noffd, dnnz, onnz);
881a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
882c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetRowStartsOwner(tA, 0);
883c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetColStartsOwner(tA, 0);
884a1d2239cSSatish Balay #endif
885c1a070e6SStefano Zampini 
886225daaf8SStefano Zampini   /* set diagonal part */
887c1a070e6SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(tA);
8886ea7df73SStefano Zampini   if (!sameint) { /* malloc CSR pointers */
8899566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(A->rmap->n + 1, &hdi, dnnz, &hdj));
890f4f49eeaSPierre Jolivet     for (i = 0; i < A->rmap->n + 1; i++) hdi[i] = (HYPRE_Int)pdi[i];
891f4f49eeaSPierre Jolivet     for (i = 0; i < dnnz; i++) hdj[i] = (HYPRE_Int)pdj[i];
8922cf14000SStefano Zampini   }
8936ea7df73SStefano Zampini   hypre_CSRMatrixI(hdiag)           = hdi;
8946ea7df73SStefano Zampini   hypre_CSRMatrixJ(hdiag)           = hdj;
89539accc25SStefano Zampini   hypre_CSRMatrixData(hdiag)        = (HYPRE_Complex *)diag->a;
896c1a070e6SStefano Zampini   hypre_CSRMatrixNumNonzeros(hdiag) = diag->nz;
897c1a070e6SStefano Zampini   hypre_CSRMatrixSetRownnz(hdiag);
898c1a070e6SStefano Zampini   hypre_CSRMatrixSetDataOwner(hdiag, 0);
899c1a070e6SStefano Zampini 
9004cf0e950SBarry Smith   /* set off-diagonal part */
901c1a070e6SStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(tA);
902c1a070e6SStefano Zampini   if (offd) {
9036ea7df73SStefano Zampini     if (!sameint) { /* malloc CSR pointers */
9049566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(A->rmap->n + 1, &hoi, onnz, &hoj));
905f4f49eeaSPierre Jolivet       for (i = 0; i < A->rmap->n + 1; i++) hoi[i] = (HYPRE_Int)poi[i];
906f4f49eeaSPierre Jolivet       for (i = 0; i < onnz; i++) hoj[i] = (HYPRE_Int)poj[i];
9072cf14000SStefano Zampini     }
9086ea7df73SStefano Zampini     hypre_CSRMatrixI(hoffd)           = hoi;
9096ea7df73SStefano Zampini     hypre_CSRMatrixJ(hoffd)           = hoj;
91039accc25SStefano Zampini     hypre_CSRMatrixData(hoffd)        = (HYPRE_Complex *)offd->a;
911c1a070e6SStefano Zampini     hypre_CSRMatrixNumNonzeros(hoffd) = offd->nz;
912c1a070e6SStefano Zampini     hypre_CSRMatrixSetRownnz(hoffd);
913c1a070e6SStefano Zampini     hypre_CSRMatrixSetDataOwner(hoffd, 0);
9146ea7df73SStefano Zampini   }
9156ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
91606977982Sstefanozampini   PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, !boundtocpu ? HYPRE_MEMORY_DEVICE : HYPRE_MEMORY_HOST);
9176ea7df73SStefano Zampini #else
9186ea7df73SStefano Zampini   #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0)
919792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixInitialize, tA);
9206ea7df73SStefano Zampini   #else
921792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, HYPRE_MEMORY_HOST);
9226ea7df73SStefano Zampini   #endif
9236ea7df73SStefano Zampini #endif
9246ea7df73SStefano Zampini   hypre_TFree(hypre_ParCSRMatrixColMapOffd(tA), HYPRE_MEMORY_HOST);
925c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetNumNonzeros(tA);
9262cf14000SStefano Zampini   hypre_ParCSRMatrixColMapOffd(tA) = (HYPRE_BigInt *)garray;
927792fecdfSBarry Smith   if (!hypre_ParCSRMatrixCommPkg(tA)) PetscCallExternal(hypre_MatvecCommPkgCreate, tA);
928613e5ff0Sstefano_zampini   *hA = tA;
9293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
930613e5ff0Sstefano_zampini }
931c1a070e6SStefano Zampini 
932d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJRestoreParCSR_Private(Mat A, hypre_ParCSRMatrix **hA)
933d71ae5a4SJacob Faibussowitsch {
934613e5ff0Sstefano_zampini   hypre_CSRMatrix *hdiag, *hoffd;
9356ea7df73SStefano Zampini   PetscBool        ismpiaij, sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
9366ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
9376ea7df73SStefano Zampini   PetscBool iscuda = PETSC_FALSE;
9386ea7df73SStefano Zampini #endif
939c1a070e6SStefano Zampini 
940613e5ff0Sstefano_zampini   PetscFunctionBegin;
9419566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
9426ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
9439566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, ""));
9446ea7df73SStefano Zampini   if (iscuda) sameint = PETSC_TRUE;
9456ea7df73SStefano Zampini #endif
946613e5ff0Sstefano_zampini   hdiag = hypre_ParCSRMatrixDiag(*hA);
947613e5ff0Sstefano_zampini   hoffd = hypre_ParCSRMatrixOffd(*hA);
9486ea7df73SStefano Zampini   /* free temporary memory allocated by PETSc
9496ea7df73SStefano Zampini      set pointers to NULL before destroying tA */
9502cf14000SStefano Zampini   if (!sameint) {
9512cf14000SStefano Zampini     HYPRE_Int *hi, *hj;
9522cf14000SStefano Zampini 
9532cf14000SStefano Zampini     hi = hypre_CSRMatrixI(hdiag);
9542cf14000SStefano Zampini     hj = hypre_CSRMatrixJ(hdiag);
9559566063dSJacob Faibussowitsch     PetscCall(PetscFree2(hi, hj));
9566ea7df73SStefano Zampini     if (ismpiaij) {
9572cf14000SStefano Zampini       hi = hypre_CSRMatrixI(hoffd);
9582cf14000SStefano Zampini       hj = hypre_CSRMatrixJ(hoffd);
9599566063dSJacob Faibussowitsch       PetscCall(PetscFree2(hi, hj));
9602cf14000SStefano Zampini     }
9612cf14000SStefano Zampini   }
962c1a070e6SStefano Zampini   hypre_CSRMatrixI(hdiag)    = NULL;
963c1a070e6SStefano Zampini   hypre_CSRMatrixJ(hdiag)    = NULL;
964c1a070e6SStefano Zampini   hypre_CSRMatrixData(hdiag) = NULL;
9656ea7df73SStefano Zampini   if (ismpiaij) {
966c1a070e6SStefano Zampini     hypre_CSRMatrixI(hoffd)    = NULL;
967c1a070e6SStefano Zampini     hypre_CSRMatrixJ(hoffd)    = NULL;
968c1a070e6SStefano Zampini     hypre_CSRMatrixData(hoffd) = NULL;
9696ea7df73SStefano Zampini   }
970613e5ff0Sstefano_zampini   hypre_ParCSRMatrixColMapOffd(*hA) = NULL;
971613e5ff0Sstefano_zampini   hypre_ParCSRMatrixDestroy(*hA);
972613e5ff0Sstefano_zampini   *hA = NULL;
9733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
974613e5ff0Sstefano_zampini }
975613e5ff0Sstefano_zampini 
976613e5ff0Sstefano_zampini /* calls RAP from BoomerAMG:
9773dad0653Sstefano_zampini    the resulting ParCSR will not own the column and row starts
9786ea7df73SStefano Zampini    It looks like we don't need to have the diagonal entries ordered first */
979d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_RAP(hypre_ParCSRMatrix *hR, hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hP, hypre_ParCSRMatrix **hRAP)
980d71ae5a4SJacob Faibussowitsch {
981a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
982613e5ff0Sstefano_zampini   HYPRE_Int P_owns_col_starts, R_owns_row_starts;
983a1d2239cSSatish Balay #endif
984613e5ff0Sstefano_zampini 
985613e5ff0Sstefano_zampini   PetscFunctionBegin;
986a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
987613e5ff0Sstefano_zampini   P_owns_col_starts = hypre_ParCSRMatrixOwnsColStarts(hP);
988613e5ff0Sstefano_zampini   R_owns_row_starts = hypre_ParCSRMatrixOwnsRowStarts(hR);
989a1d2239cSSatish Balay #endif
9906ea7df73SStefano Zampini   /* can be replaced by version test later */
9916ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
992792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParCSRMatrixRAP");
9936ea7df73SStefano Zampini   *hRAP = hypre_ParCSRMatrixRAP(hR, hA, hP);
9946ea7df73SStefano Zampini   PetscStackPop;
9956ea7df73SStefano Zampini #else
996792fecdfSBarry Smith   PetscCallExternal(hypre_BoomerAMGBuildCoarseOperator, hR, hA, hP, hRAP);
997792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixSetNumNonzeros, *hRAP);
9986ea7df73SStefano Zampini #endif
999613e5ff0Sstefano_zampini   /* hypre_BoomerAMGBuildCoarseOperator steals the col_starts from P and the row_starts from R */
1000a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
1001613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetRowStartsOwner(*hRAP, 0);
1002613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetColStartsOwner(*hRAP, 0);
1003613e5ff0Sstefano_zampini   if (P_owns_col_starts) hypre_ParCSRMatrixSetColStartsOwner(hP, 1);
1004613e5ff0Sstefano_zampini   if (R_owns_row_starts) hypre_ParCSRMatrixSetRowStartsOwner(hR, 1);
1005a1d2239cSSatish Balay #endif
10063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1007613e5ff0Sstefano_zampini }
1008613e5ff0Sstefano_zampini 
1009d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat P, Mat C)
1010d71ae5a4SJacob Faibussowitsch {
10116f231fbdSstefano_zampini   Mat                 B;
10126abb4441SStefano Zampini   hypre_ParCSRMatrix *hA, *hP, *hPtAP = NULL;
10134222ddf1SHong Zhang   Mat_Product        *product = C->product;
1014613e5ff0Sstefano_zampini 
1015613e5ff0Sstefano_zampini   PetscFunctionBegin;
10169566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
10179566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(P, &hP));
10189566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(hP, hA, hP, &hPtAP));
10199566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hPtAP, MATAIJ, PETSC_OWN_POINTER, &B));
10204222ddf1SHong Zhang 
10219566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
10224222ddf1SHong Zhang   C->product = product;
10234222ddf1SHong Zhang 
10249566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
10259566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(P, &hP));
10263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10276f231fbdSstefano_zampini }
10286f231fbdSstefano_zampini 
1029d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatPtAPSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat P, PetscReal fill, Mat C)
1030d71ae5a4SJacob Faibussowitsch {
10316f231fbdSstefano_zampini   PetscFunctionBegin;
10329566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATAIJ));
10334222ddf1SHong Zhang   C->ops->ptapnumeric    = MatPtAPNumeric_AIJ_AIJ_wHYPRE;
10344222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
10353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1036613e5ff0Sstefano_zampini }
1037613e5ff0Sstefano_zampini 
1038d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_HYPRE(Mat A, Mat P, Mat C)
1039d71ae5a4SJacob Faibussowitsch {
10404cc28894Sstefano_zampini   Mat                 B;
10414cc28894Sstefano_zampini   Mat_HYPRE          *hP;
10426abb4441SStefano Zampini   hypre_ParCSRMatrix *hA = NULL, *Pparcsr, *ptapparcsr = NULL;
1043613e5ff0Sstefano_zampini   HYPRE_Int           type;
1044613e5ff0Sstefano_zampini   MPI_Comm            comm = PetscObjectComm((PetscObject)A);
10454cc28894Sstefano_zampini   PetscBool           ishypre;
1046613e5ff0Sstefano_zampini 
1047613e5ff0Sstefano_zampini   PetscFunctionBegin;
10489566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre));
104928b400f6SJacob Faibussowitsch   PetscCheck(ishypre, comm, PETSC_ERR_USER, "P should be of type %s", MATHYPRE);
10504cc28894Sstefano_zampini   hP = (Mat_HYPRE *)P->data;
1051792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type);
105208401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1053792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr);
1054613e5ff0Sstefano_zampini 
10559566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
10569566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, hA, Pparcsr, &ptapparcsr));
10579566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
1058225daaf8SStefano Zampini 
10594cc28894Sstefano_zampini   /* create temporary matrix and merge to C */
10609566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ptapparcsr, ((PetscObject)C)->type_name, PETSC_OWN_POINTER, &B));
10619566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
10623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10634cc28894Sstefano_zampini }
10644cc28894Sstefano_zampini 
1065d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_HYPRE_HYPRE(Mat A, Mat P, Mat C)
1066d71ae5a4SJacob Faibussowitsch {
10674cc28894Sstefano_zampini   Mat                 B;
10686abb4441SStefano Zampini   hypre_ParCSRMatrix *Aparcsr, *Pparcsr, *ptapparcsr = NULL;
10694cc28894Sstefano_zampini   Mat_HYPRE          *hA, *hP;
10704cc28894Sstefano_zampini   PetscBool           ishypre;
10714cc28894Sstefano_zampini   HYPRE_Int           type;
10724cc28894Sstefano_zampini 
10734cc28894Sstefano_zampini   PetscFunctionBegin;
10749566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre));
107528b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)P), PETSC_ERR_USER, "P should be of type %s", MATHYPRE);
10769566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
107728b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE);
10784cc28894Sstefano_zampini   hA = (Mat_HYPRE *)A->data;
10794cc28894Sstefano_zampini   hP = (Mat_HYPRE *)P->data;
1080792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
108108401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1082792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type);
108308401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)P), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1084792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr);
1085792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr);
10869566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, Aparcsr, Pparcsr, &ptapparcsr));
10879566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ptapparcsr, MATHYPRE, PETSC_OWN_POINTER, &B));
10889566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
10893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10904cc28894Sstefano_zampini }
10914cc28894Sstefano_zampini 
1092d501dc42Sstefano_zampini /* calls hypre_ParMatmul
1093d501dc42Sstefano_zampini    hypre_ParMatMul uses hypre_ParMatrixCreate with the communicator of hA
10943dad0653Sstefano_zampini    hypre_ParMatrixCreate does not duplicate the communicator
10956ea7df73SStefano Zampini    It looks like we don't need to have the diagonal entries ordered first */
1096d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_MatMatMult(hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hB, hypre_ParCSRMatrix **hAB)
1097d71ae5a4SJacob Faibussowitsch {
1098d501dc42Sstefano_zampini   PetscFunctionBegin;
10996ea7df73SStefano Zampini   /* can be replaced by version test later */
11006ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
1101792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParCSRMatMat");
11026ea7df73SStefano Zampini   *hAB = hypre_ParCSRMatMat(hA, hB);
11036ea7df73SStefano Zampini #else
1104792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParMatmul");
1105d501dc42Sstefano_zampini   *hAB = hypre_ParMatmul(hA, hB);
11066ea7df73SStefano Zampini #endif
1107d501dc42Sstefano_zampini   PetscStackPop;
11083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1109d501dc42Sstefano_zampini }
1110d501dc42Sstefano_zampini 
1111d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C)
1112d71ae5a4SJacob Faibussowitsch {
11135e5acdf2Sstefano_zampini   Mat                 D;
1114d501dc42Sstefano_zampini   hypre_ParCSRMatrix *hA, *hB, *hAB = NULL;
11154222ddf1SHong Zhang   Mat_Product        *product = C->product;
11165e5acdf2Sstefano_zampini 
11175e5acdf2Sstefano_zampini   PetscFunctionBegin;
11189566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
11199566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(B, &hB));
11209566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_MatMatMult(hA, hB, &hAB));
11219566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hAB, MATAIJ, PETSC_OWN_POINTER, &D));
11224222ddf1SHong Zhang 
11239566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &D));
11244222ddf1SHong Zhang   C->product = product;
11254222ddf1SHong Zhang 
11269566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
11279566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(B, &hB));
11283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11295e5acdf2Sstefano_zampini }
11305e5acdf2Sstefano_zampini 
1131d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatMatMultSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat B, PetscReal fill, Mat C)
1132d71ae5a4SJacob Faibussowitsch {
11335e5acdf2Sstefano_zampini   PetscFunctionBegin;
11349566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATAIJ));
11354222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_AIJ_AIJ_wHYPRE;
11364222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
11373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11385e5acdf2Sstefano_zampini }
11395e5acdf2Sstefano_zampini 
1140d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_HYPRE_HYPRE(Mat A, Mat B, Mat C)
1141d71ae5a4SJacob Faibussowitsch {
1142d501dc42Sstefano_zampini   Mat                 D;
1143d501dc42Sstefano_zampini   hypre_ParCSRMatrix *Aparcsr, *Bparcsr, *ABparcsr = NULL;
1144d501dc42Sstefano_zampini   Mat_HYPRE          *hA, *hB;
1145d501dc42Sstefano_zampini   PetscBool           ishypre;
1146d501dc42Sstefano_zampini   HYPRE_Int           type;
11474222ddf1SHong Zhang   Mat_Product        *product;
1148d501dc42Sstefano_zampini 
1149d501dc42Sstefano_zampini   PetscFunctionBegin;
11509566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)B, MATHYPRE, &ishypre));
115128b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)B), PETSC_ERR_USER, "B should be of type %s", MATHYPRE);
11529566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
115328b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE);
1154d501dc42Sstefano_zampini   hA = (Mat_HYPRE *)A->data;
1155d501dc42Sstefano_zampini   hB = (Mat_HYPRE *)B->data;
1156792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
115708401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1158792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hB->ij, &type);
115908401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1160792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr);
1161792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hB->ij, (void **)&Bparcsr);
11629566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_MatMatMult(Aparcsr, Bparcsr, &ABparcsr));
11639566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ABparcsr, MATHYPRE, PETSC_OWN_POINTER, &D));
11644222ddf1SHong Zhang 
1165d501dc42Sstefano_zampini   /* need to use HeaderReplace because HeaderMerge messes up with the communicator */
11664222ddf1SHong Zhang   product    = C->product; /* save it from MatHeaderReplace() */
11674222ddf1SHong Zhang   C->product = NULL;
11689566063dSJacob Faibussowitsch   PetscCall(MatHeaderReplace(C, &D));
11694222ddf1SHong Zhang   C->product             = product;
1170d501dc42Sstefano_zampini   C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE;
11714222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
11723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1173d501dc42Sstefano_zampini }
1174d501dc42Sstefano_zampini 
1175d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultNumeric_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, Mat D)
1176d71ae5a4SJacob Faibussowitsch {
117720e1dc0dSstefano_zampini   Mat                 E;
11786abb4441SStefano Zampini   hypre_ParCSRMatrix *hA, *hB, *hC, *hABC = NULL;
117920e1dc0dSstefano_zampini 
118020e1dc0dSstefano_zampini   PetscFunctionBegin;
11819566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
11829566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(B, &hB));
11839566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(C, &hC));
11849566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(hA, hB, hC, &hABC));
11859566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hABC, MATAIJ, PETSC_OWN_POINTER, &E));
11869566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(D, &E));
11879566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
11889566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(B, &hB));
11899566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(C, &hC));
11903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
119120e1dc0dSstefano_zampini }
119220e1dc0dSstefano_zampini 
1193d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultSymbolic_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, PetscReal fill, Mat D)
1194d71ae5a4SJacob Faibussowitsch {
119520e1dc0dSstefano_zampini   PetscFunctionBegin;
11969566063dSJacob Faibussowitsch   PetscCall(MatSetType(D, MATAIJ));
11973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
119820e1dc0dSstefano_zampini }
119920e1dc0dSstefano_zampini 
1200d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_AB_HYPRE(Mat C)
1201d71ae5a4SJacob Faibussowitsch {
12024222ddf1SHong Zhang   PetscFunctionBegin;
12034222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
12043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12054222ddf1SHong Zhang }
12064222ddf1SHong Zhang 
1207d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_AB(Mat C)
1208d71ae5a4SJacob Faibussowitsch {
12094222ddf1SHong Zhang   Mat_Product *product = C->product;
12104222ddf1SHong Zhang   PetscBool    Ahypre;
12114222ddf1SHong Zhang 
12124222ddf1SHong Zhang   PetscFunctionBegin;
12139566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)product->A, MATHYPRE, &Ahypre));
12144222ddf1SHong Zhang   if (Ahypre) { /* A is a Hypre matrix */
12159566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
12164222ddf1SHong Zhang     C->ops->productsymbolic = MatProductSymbolic_AB_HYPRE;
12174222ddf1SHong Zhang     C->ops->matmultnumeric  = MatMatMultNumeric_HYPRE_HYPRE;
12183ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
12196718818eSStefano Zampini   }
12203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12214222ddf1SHong Zhang }
12224222ddf1SHong Zhang 
1223d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_PtAP_HYPRE(Mat C)
1224d71ae5a4SJacob Faibussowitsch {
12254222ddf1SHong Zhang   PetscFunctionBegin;
12264222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
12273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12284222ddf1SHong Zhang }
12294222ddf1SHong Zhang 
1230d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_PtAP(Mat C)
1231d71ae5a4SJacob Faibussowitsch {
12324222ddf1SHong Zhang   Mat_Product *product = C->product;
12334222ddf1SHong Zhang   PetscBool    flg;
12344222ddf1SHong Zhang   PetscInt     type        = 0;
12354222ddf1SHong Zhang   const char  *outTypes[4] = {"aij", "seqaij", "mpiaij", "hypre"};
12364222ddf1SHong Zhang   PetscInt     ntype       = 4;
12374222ddf1SHong Zhang   Mat          A           = product->A;
12384222ddf1SHong Zhang   PetscBool    Ahypre;
12394222ddf1SHong Zhang 
12404222ddf1SHong Zhang   PetscFunctionBegin;
12419566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &Ahypre));
12424222ddf1SHong Zhang   if (Ahypre) { /* A is a Hypre matrix */
12439566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
12444222ddf1SHong Zhang     C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE;
12454222ddf1SHong Zhang     C->ops->ptapnumeric     = MatPtAPNumeric_HYPRE_HYPRE;
12463ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
12474222ddf1SHong Zhang   }
12484222ddf1SHong Zhang 
12494222ddf1SHong Zhang   /* A is AIJ, P is Hypre, C = PtAP can be either AIJ or Hypre format */
12504222ddf1SHong Zhang   /* Get runtime option */
12514222ddf1SHong Zhang   if (product->api_user) {
1252d0609cedSBarry Smith     PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatPtAP_HYPRE", "Mat");
12539566063dSJacob Faibussowitsch     PetscCall(PetscOptionsEList("-matptap_hypre_outtype", "MatPtAP outtype", "MatPtAP outtype", outTypes, ntype, outTypes[type], &type, &flg));
1254d0609cedSBarry Smith     PetscOptionsEnd();
12554222ddf1SHong Zhang   } else {
1256d0609cedSBarry Smith     PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatProduct_PtAP_HYPRE", "Mat");
12579566063dSJacob Faibussowitsch     PetscCall(PetscOptionsEList("-mat_product_algorithm_hypre_outtype", "MatProduct_PtAP outtype", "MatProduct_PtAP", outTypes, ntype, outTypes[type], &type, &flg));
1258d0609cedSBarry Smith     PetscOptionsEnd();
12594222ddf1SHong Zhang   }
12604222ddf1SHong Zhang 
12614222ddf1SHong Zhang   if (type == 0 || type == 1 || type == 2) {
12629566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATAIJ));
12634222ddf1SHong Zhang   } else if (type == 3) {
12649566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
12654222ddf1SHong Zhang   } else SETERRQ(PetscObjectComm((PetscObject)C), PETSC_ERR_SUP, "MatPtAP outtype is not supported");
12664222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE;
12674222ddf1SHong Zhang   C->ops->ptapnumeric     = MatPtAPNumeric_AIJ_HYPRE;
12683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12694222ddf1SHong Zhang }
12704222ddf1SHong Zhang 
1271d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE(Mat C)
1272d71ae5a4SJacob Faibussowitsch {
12734222ddf1SHong Zhang   Mat_Product *product = C->product;
12744222ddf1SHong Zhang 
12754222ddf1SHong Zhang   PetscFunctionBegin;
12764222ddf1SHong Zhang   switch (product->type) {
1277d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AB:
1278d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_HYPRE_AB(C));
1279d71ae5a4SJacob Faibussowitsch     break;
1280d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_PtAP:
1281d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_HYPRE_PtAP(C));
1282d71ae5a4SJacob Faibussowitsch     break;
1283d71ae5a4SJacob Faibussowitsch   default:
1284d71ae5a4SJacob Faibussowitsch     break;
12854222ddf1SHong Zhang   }
12863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12874222ddf1SHong Zhang }
12884222ddf1SHong Zhang 
1289d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTranspose_HYPRE(Mat A, Vec x, Vec y)
1290d71ae5a4SJacob Faibussowitsch {
129163c07aadSStefano Zampini   PetscFunctionBegin;
12929566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_TRUE));
12933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
129463c07aadSStefano Zampini }
129563c07aadSStefano Zampini 
1296d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_HYPRE(Mat A, Vec x, Vec y)
1297d71ae5a4SJacob Faibussowitsch {
129863c07aadSStefano Zampini   PetscFunctionBegin;
12999566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_FALSE));
13003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
130163c07aadSStefano Zampini }
130263c07aadSStefano Zampini 
1303d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultAdd_HYPRE(Mat A, Vec x, Vec y, Vec z)
1304d71ae5a4SJacob Faibussowitsch {
1305414bd5c3SStefano Zampini   PetscFunctionBegin;
130648a46eb9SPierre Jolivet   if (y != z) PetscCall(VecCopy(y, z));
13079566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_FALSE));
13083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1309414bd5c3SStefano Zampini }
1310414bd5c3SStefano Zampini 
1311d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTransposeAdd_HYPRE(Mat A, Vec x, Vec y, Vec z)
1312d71ae5a4SJacob Faibussowitsch {
1313414bd5c3SStefano Zampini   PetscFunctionBegin;
131448a46eb9SPierre Jolivet   if (y != z) PetscCall(VecCopy(y, z));
13159566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_TRUE));
13163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1317414bd5c3SStefano Zampini }
1318414bd5c3SStefano Zampini 
1319414bd5c3SStefano Zampini /* y = a * A * x + b * y or y = a * A^t * x + b * y depending on trans */
1320d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_MultKernel_Private(Mat A, HYPRE_Complex a, Vec x, HYPRE_Complex b, Vec y, PetscBool trans)
1321d71ae5a4SJacob Faibussowitsch {
132263c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE *)A->data;
132363c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
132463c07aadSStefano Zampini   hypre_ParVector    *hx, *hy;
132563c07aadSStefano Zampini 
132663c07aadSStefano Zampini   PetscFunctionBegin;
132763c07aadSStefano Zampini   if (trans) {
13289566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorPushVecRead(hA->b, x));
13299566063dSJacob Faibussowitsch     if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->x, y));
13309566063dSJacob Faibussowitsch     else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->x, y));
1331792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hx);
1332792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hy);
133363c07aadSStefano Zampini   } else {
13349566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorPushVecRead(hA->x, x));
13359566063dSJacob Faibussowitsch     if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->b, y));
13369566063dSJacob Faibussowitsch     else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->b, y));
1337792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hx);
1338792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hy);
133963c07aadSStefano Zampini   }
1340792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
13416ea7df73SStefano Zampini   if (trans) {
1342792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMatvecT, a, parcsr, hx, b, hy);
13436ea7df73SStefano Zampini   } else {
1344792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMatvec, a, parcsr, hx, b, hy);
13456ea7df73SStefano Zampini   }
13469566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hA->x));
13479566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hA->b));
13483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
134963c07aadSStefano Zampini }
135063c07aadSStefano Zampini 
1351d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_HYPRE(Mat A)
1352d71ae5a4SJacob Faibussowitsch {
135363c07aadSStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
135463c07aadSStefano Zampini 
135563c07aadSStefano Zampini   PetscFunctionBegin;
13569566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&hA->x));
13579566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&hA->b));
135806977982Sstefanozampini   PetscCall(MatHYPRE_DestroyCOOMat(A)); /* must be called before destroying the individual CSR */
1359978814f1SStefano Zampini   if (hA->ij) {
1360978814f1SStefano Zampini     if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL;
1361792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixDestroy, hA->ij);
1362978814f1SStefano Zampini   }
13639566063dSJacob Faibussowitsch   if (hA->comm) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)A), &hA->comm));
1364c69f721fSFande Kong 
13659566063dSJacob Faibussowitsch   PetscCall(MatStashDestroy_Private(&A->stash));
13669566063dSJacob Faibussowitsch   PetscCall(PetscFree(hA->array));
1367a32e9c99SJunchao Zhang   if (hA->rows_d) PetscStackCallExternalVoid("hypre_Free", hypre_Free(hA->rows_d, HYPRE_MEMORY_DEVICE));
1368c69f721fSFande Kong 
13699566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_aij_C", NULL));
13709566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_is_C", NULL));
13719566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_hypre_C", NULL));
13729566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaij_hypre_C", NULL));
137306977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijhipsparse_hypre_C", NULL));
137406977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaijhipsparse_hypre_C", NULL));
137506977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijcusparse_hypre_C", NULL));
137606977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaijcusparse_hypre_C", NULL));
13779566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPRESetPreallocation_C", NULL));
13789566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPREGetParCSR_C", NULL));
13795fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL));
13805fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL));
13819566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->data));
13823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
138363c07aadSStefano Zampini }
138463c07aadSStefano Zampini 
1385d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetUp_HYPRE(Mat A)
1386d71ae5a4SJacob Faibussowitsch {
13874ec6421dSstefano_zampini   PetscFunctionBegin;
138806977982Sstefanozampini   if (!A->preallocated) PetscCall(MatHYPRESetPreallocation(A, PETSC_DEFAULT, NULL, PETSC_DEFAULT, NULL));
13893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13904ec6421dSstefano_zampini }
13914ec6421dSstefano_zampini 
13926ea7df73SStefano Zampini //TODO FIX hypre_CSRMatrixMatvecOutOfPlace
13936ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
1394d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatBindToCPU_HYPRE(Mat A, PetscBool bind)
1395d71ae5a4SJacob Faibussowitsch {
13966ea7df73SStefano Zampini   Mat_HYPRE           *hA   = (Mat_HYPRE *)A->data;
13976ea7df73SStefano Zampini   HYPRE_MemoryLocation hmem = bind ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE;
13986ea7df73SStefano Zampini 
13996ea7df73SStefano Zampini   PetscFunctionBegin;
14006ea7df73SStefano Zampini   A->boundtocpu = bind;
14015fbaff96SJunchao Zhang   if (hA->ij && hypre_IJMatrixAssembleFlag(hA->ij) && hmem != hypre_IJMatrixMemoryLocation(hA->ij)) {
14026ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
1403792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
1404792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMigrate, parcsr, hmem);
14056ea7df73SStefano Zampini   }
14069566063dSJacob Faibussowitsch   if (hA->x) PetscCall(VecHYPRE_IJBindToCPU(hA->x, bind));
14079566063dSJacob Faibussowitsch   if (hA->b) PetscCall(VecHYPRE_IJBindToCPU(hA->b, bind));
14083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14096ea7df73SStefano Zampini }
14106ea7df73SStefano Zampini #endif
14116ea7df73SStefano Zampini 
1412d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_HYPRE(Mat A, MatAssemblyType mode)
1413d71ae5a4SJacob Faibussowitsch {
141463c07aadSStefano Zampini   Mat_HYPRE   *hA = (Mat_HYPRE *)A->data;
1415c69f721fSFande Kong   PetscMPIInt  n;
1416c69f721fSFande Kong   PetscInt     i, j, rstart, ncols, flg;
1417c69f721fSFande Kong   PetscInt    *row, *col;
1418c69f721fSFande Kong   PetscScalar *val;
141963c07aadSStefano Zampini 
142063c07aadSStefano Zampini   PetscFunctionBegin;
142108401ef6SPierre Jolivet   PetscCheck(mode != MAT_FLUSH_ASSEMBLY, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_FLUSH_ASSEMBLY currently not supported with MATHYPRE");
1422c69f721fSFande Kong 
1423c69f721fSFande Kong   if (!A->nooffprocentries) {
1424c69f721fSFande Kong     while (1) {
14259566063dSJacob Faibussowitsch       PetscCall(MatStashScatterGetMesg_Private(&A->stash, &n, &row, &col, &val, &flg));
1426c69f721fSFande Kong       if (!flg) break;
1427c69f721fSFande Kong 
1428c69f721fSFande Kong       for (i = 0; i < n;) {
1429c69f721fSFande Kong         /* Now identify the consecutive vals belonging to the same row */
1430c69f721fSFande Kong         for (j = i, rstart = row[j]; j < n; j++) {
1431c69f721fSFande Kong           if (row[j] != rstart) break;
1432c69f721fSFande Kong         }
1433c69f721fSFande Kong         if (j < n) ncols = j - i;
1434c69f721fSFande Kong         else ncols = n - i;
1435c69f721fSFande Kong         /* Now assemble all these values with a single function call */
14369566063dSJacob Faibussowitsch         PetscCall(MatSetValues_HYPRE(A, 1, row + i, ncols, col + i, val + i, A->insertmode));
1437c69f721fSFande Kong 
1438c69f721fSFande Kong         i = j;
1439c69f721fSFande Kong       }
1440c69f721fSFande Kong     }
14419566063dSJacob Faibussowitsch     PetscCall(MatStashScatterEnd_Private(&A->stash));
1442c69f721fSFande Kong   }
1443c69f721fSFande Kong 
1444792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixAssemble, hA->ij);
1445336664bdSPierre Jolivet   /* The assembly routine destroys the aux_matrix, we recreate it here by calling HYPRE_IJMatrixInitialize */
1446336664bdSPierre 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 */
1447651b1cf9SStefano Zampini   if (!A->sortedfull) {
1448af1cf968SStefano Zampini     hypre_AuxParCSRMatrix *aux_matrix;
1449af1cf968SStefano Zampini 
1450af1cf968SStefano Zampini     /* call destroy just to make sure we do not leak anything */
1451af1cf968SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
1452792fecdfSBarry Smith     PetscCallExternal(hypre_AuxParCSRMatrixDestroy, aux_matrix);
1453af1cf968SStefano Zampini     hypre_IJMatrixTranslator(hA->ij) = NULL;
1454af1cf968SStefano Zampini 
1455af1cf968SStefano Zampini     /* Initialize with assembled flag -> it only recreates the aux_par_matrix */
1456792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij);
1457af1cf968SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
14586ea7df73SStefano Zampini     if (aux_matrix) {
1459af1cf968SStefano Zampini       hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1; /* see comment in MatHYPRESetPreallocation_HYPRE */
146022235d61SPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
1461792fecdfSBarry Smith       PetscCallExternal(hypre_AuxParCSRMatrixInitialize, aux_matrix);
146222235d61SPierre Jolivet #else
1463792fecdfSBarry Smith       PetscCallExternal(hypre_AuxParCSRMatrixInitialize_v2, aux_matrix, HYPRE_MEMORY_HOST);
146422235d61SPierre Jolivet #endif
1465af1cf968SStefano Zampini     }
14666ea7df73SStefano Zampini   }
14676ea7df73SStefano Zampini   {
14686ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
14696ea7df73SStefano Zampini 
1470792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
1471792fecdfSBarry Smith     if (!hypre_ParCSRMatrixCommPkg(parcsr)) PetscCallExternal(hypre_MatvecCommPkgCreate, parcsr);
14726ea7df73SStefano Zampini   }
14739566063dSJacob Faibussowitsch   if (!hA->x) PetscCall(VecHYPRE_IJVectorCreate(A->cmap, &hA->x));
14749566063dSJacob Faibussowitsch   if (!hA->b) PetscCall(VecHYPRE_IJVectorCreate(A->rmap, &hA->b));
14756ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
14769566063dSJacob Faibussowitsch   PetscCall(MatBindToCPU_HYPRE(A, A->boundtocpu));
14776ea7df73SStefano Zampini #endif
14783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
147963c07aadSStefano Zampini }
148063c07aadSStefano Zampini 
1481d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetArray_HYPRE(Mat A, PetscInt size, void **array)
1482d71ae5a4SJacob Faibussowitsch {
1483c69f721fSFande Kong   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1484c69f721fSFande Kong 
1485c69f721fSFande Kong   PetscFunctionBegin;
1486651b1cf9SStefano Zampini   PetscCheck(hA->array_available, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Temporary space is in use");
1487c69f721fSFande Kong 
1488651b1cf9SStefano Zampini   if (hA->array_size >= size) {
148939accc25SStefano Zampini     *array = hA->array;
149039accc25SStefano Zampini   } else {
14919566063dSJacob Faibussowitsch     PetscCall(PetscFree(hA->array));
1492651b1cf9SStefano Zampini     hA->array_size = size;
1493651b1cf9SStefano Zampini     PetscCall(PetscMalloc(hA->array_size, &hA->array));
1494c69f721fSFande Kong     *array = hA->array;
1495c69f721fSFande Kong   }
1496c69f721fSFande Kong 
1497651b1cf9SStefano Zampini   hA->array_available = PETSC_FALSE;
14983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1499c69f721fSFande Kong }
1500c69f721fSFande Kong 
1501d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreArray_HYPRE(Mat A, void **array)
1502d71ae5a4SJacob Faibussowitsch {
1503c69f721fSFande Kong   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1504c69f721fSFande Kong 
1505c69f721fSFande Kong   PetscFunctionBegin;
1506c69f721fSFande Kong   *array              = NULL;
1507651b1cf9SStefano Zampini   hA->array_available = PETSC_TRUE;
15083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1509c69f721fSFande Kong }
1510c69f721fSFande Kong 
1511d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_HYPRE(Mat A, PetscInt nr, const PetscInt rows[], PetscInt nc, const PetscInt cols[], const PetscScalar v[], InsertMode ins)
1512d71ae5a4SJacob Faibussowitsch {
1513d975228cSstefano_zampini   Mat_HYPRE     *hA   = (Mat_HYPRE *)A->data;
1514d975228cSstefano_zampini   PetscScalar   *vals = (PetscScalar *)v;
151539accc25SStefano Zampini   HYPRE_Complex *sscr;
1516c69f721fSFande Kong   PetscInt      *cscr[2];
1517c69f721fSFande Kong   PetscInt       i, nzc;
1518651b1cf9SStefano Zampini   PetscInt       rst = A->rmap->rstart, ren = A->rmap->rend;
151908defe43SFande Kong   void          *array = NULL;
1520d975228cSstefano_zampini 
1521d975228cSstefano_zampini   PetscFunctionBegin;
15229566063dSJacob Faibussowitsch   PetscCall(MatGetArray_HYPRE(A, sizeof(PetscInt) * (2 * nc) + sizeof(HYPRE_Complex) * nc * nr, &array));
1523c69f721fSFande Kong   cscr[0] = (PetscInt *)array;
1524c69f721fSFande Kong   cscr[1] = ((PetscInt *)array) + nc;
152539accc25SStefano Zampini   sscr    = (HYPRE_Complex *)(((PetscInt *)array) + nc * 2);
1526d975228cSstefano_zampini   for (i = 0, nzc = 0; i < nc; i++) {
1527d975228cSstefano_zampini     if (cols[i] >= 0) {
1528d975228cSstefano_zampini       cscr[0][nzc]   = cols[i];
1529d975228cSstefano_zampini       cscr[1][nzc++] = i;
1530d975228cSstefano_zampini     }
1531d975228cSstefano_zampini   }
1532c69f721fSFande Kong   if (!nzc) {
15339566063dSJacob Faibussowitsch     PetscCall(MatRestoreArray_HYPRE(A, &array));
15343ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1535c69f721fSFande Kong   }
1536d975228cSstefano_zampini 
15376ea7df73SStefano Zampini #if 0 //defined(PETSC_HAVE_HYPRE_DEVICE)
15386ea7df73SStefano Zampini   if (HYPRE_MEMORY_HOST != hypre_IJMatrixMemoryLocation(hA->ij)) {
15396ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
15406ea7df73SStefano Zampini 
1541792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject,hA->ij,(void**)&parcsr);
1542792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMigrate,parcsr, HYPRE_MEMORY_HOST);
15436ea7df73SStefano Zampini   }
15446ea7df73SStefano Zampini #endif
15456ea7df73SStefano Zampini 
1546d975228cSstefano_zampini   if (ins == ADD_VALUES) {
1547d975228cSstefano_zampini     for (i = 0; i < nr; i++) {
15486ea7df73SStefano Zampini       if (rows[i] >= 0) {
1549d975228cSstefano_zampini         PetscInt  j;
15502cf14000SStefano Zampini         HYPRE_Int hnc = (HYPRE_Int)nzc;
15512cf14000SStefano Zampini 
1552651b1cf9SStefano Zampini         if (!nzc) continue;
1553651b1cf9SStefano Zampini         /* nonlocal values */
1554651b1cf9SStefano Zampini         if (rows[i] < rst || rows[i] >= ren) {
1555651b1cf9SStefano 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]);
1556651b1cf9SStefano Zampini           if (hA->donotstash) continue;
1557651b1cf9SStefano Zampini         }
1558aed4548fSBarry 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]);
15599566063dSJacob Faibussowitsch         for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j]));
1560792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixAddToValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr);
1561d975228cSstefano_zampini       }
1562d975228cSstefano_zampini       vals += nc;
1563d975228cSstefano_zampini     }
1564d975228cSstefano_zampini   } else { /* INSERT_VALUES */
1565d975228cSstefano_zampini     for (i = 0; i < nr; i++) {
15666ea7df73SStefano Zampini       if (rows[i] >= 0) {
1567d975228cSstefano_zampini         PetscInt  j;
15682cf14000SStefano Zampini         HYPRE_Int hnc = (HYPRE_Int)nzc;
15692cf14000SStefano Zampini 
1570651b1cf9SStefano Zampini         if (!nzc) continue;
1571aed4548fSBarry 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]);
15729566063dSJacob Faibussowitsch         for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j]));
1573c69f721fSFande Kong         /* nonlocal values */
1574651b1cf9SStefano Zampini         if (rows[i] < rst || rows[i] >= ren) {
1575651b1cf9SStefano 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]);
1576651b1cf9SStefano Zampini           if (!hA->donotstash) PetscCall(MatStashValuesRow_Private(&A->stash, rows[i], nzc, cscr[0], (PetscScalar *)sscr, PETSC_FALSE));
1577651b1cf9SStefano Zampini         }
1578c69f721fSFande Kong         /* local values */
1579651b1cf9SStefano Zampini         else
1580651b1cf9SStefano Zampini           PetscCallExternal(HYPRE_IJMatrixSetValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr);
1581d975228cSstefano_zampini       }
1582d975228cSstefano_zampini       vals += nc;
1583d975228cSstefano_zampini     }
1584d975228cSstefano_zampini   }
1585c69f721fSFande Kong 
15869566063dSJacob Faibussowitsch   PetscCall(MatRestoreArray_HYPRE(A, &array));
15873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1588d975228cSstefano_zampini }
1589d975228cSstefano_zampini 
1590d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRESetPreallocation_HYPRE(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[])
1591d71ae5a4SJacob Faibussowitsch {
1592d975228cSstefano_zampini   Mat_HYPRE  *hA = (Mat_HYPRE *)A->data;
15937d968826Sstefano_zampini   HYPRE_Int  *hdnnz, *honnz;
159406a29025Sstefano_zampini   PetscInt    i, rs, re, cs, ce, bs;
1595d975228cSstefano_zampini   PetscMPIInt size;
1596d975228cSstefano_zampini 
1597d975228cSstefano_zampini   PetscFunctionBegin;
15989566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
15999566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
1600d975228cSstefano_zampini   rs = A->rmap->rstart;
1601d975228cSstefano_zampini   re = A->rmap->rend;
1602d975228cSstefano_zampini   cs = A->cmap->rstart;
1603d975228cSstefano_zampini   ce = A->cmap->rend;
1604d975228cSstefano_zampini   if (!hA->ij) {
1605792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rs, re - 1, cs, ce - 1, &hA->ij);
1606792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR);
1607d975228cSstefano_zampini   } else {
16082cf14000SStefano Zampini     HYPRE_BigInt hrs, hre, hcs, hce;
1609792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetLocalRange, hA->ij, &hrs, &hre, &hcs, &hce);
1610aed4548fSBarry 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);
1611aed4548fSBarry 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);
1612d975228cSstefano_zampini   }
161306977982Sstefanozampini   PetscCall(MatHYPRE_DestroyCOOMat(A));
16149566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(A, &bs));
161506a29025Sstefano_zampini   if (dnz == PETSC_DEFAULT || dnz == PETSC_DECIDE) dnz = 10 * bs;
161606a29025Sstefano_zampini   if (onz == PETSC_DEFAULT || onz == PETSC_DECIDE) onz = 10 * bs;
161706a29025Sstefano_zampini 
1618d975228cSstefano_zampini   if (!dnnz) {
16199566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->rmap->n, &hdnnz));
1620d975228cSstefano_zampini     for (i = 0; i < A->rmap->n; i++) hdnnz[i] = dnz;
1621d975228cSstefano_zampini   } else {
16227d968826Sstefano_zampini     hdnnz = (HYPRE_Int *)dnnz;
1623d975228cSstefano_zampini   }
16249566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
1625d975228cSstefano_zampini   if (size > 1) {
1626ddbeb582SStefano Zampini     hypre_AuxParCSRMatrix *aux_matrix;
1627d975228cSstefano_zampini     if (!onnz) {
16289566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(A->rmap->n, &honnz));
1629d975228cSstefano_zampini       for (i = 0; i < A->rmap->n; i++) honnz[i] = onz;
163022235d61SPierre Jolivet     } else honnz = (HYPRE_Int *)onnz;
1631ddbeb582SStefano Zampini     /* SetDiagOffdSizes sets hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0, since it seems
1632ddbeb582SStefano Zampini        they assume the user will input the entire row values, properly sorted
1633336664bdSPierre Jolivet        In PETSc, we don't make such an assumption and set this flag to 1,
1634336664bdSPierre Jolivet        unless the option MAT_SORTED_FULL is set to true.
1635ddbeb582SStefano Zampini        Also, to avoid possible memory leaks, we destroy and recreate the translator
1636ddbeb582SStefano Zampini        This has to be done here, as HYPRE_IJMatrixInitialize will properly initialize
1637ddbeb582SStefano Zampini        the IJ matrix for us */
1638ddbeb582SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
1639ddbeb582SStefano Zampini     hypre_AuxParCSRMatrixDestroy(aux_matrix);
1640ddbeb582SStefano Zampini     hypre_IJMatrixTranslator(hA->ij) = NULL;
1641792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, hA->ij, hdnnz, honnz);
1642ddbeb582SStefano Zampini     aux_matrix                               = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
1643651b1cf9SStefano Zampini     hypre_AuxParCSRMatrixNeedAux(aux_matrix) = !A->sortedfull;
1644d975228cSstefano_zampini   } else {
1645d975228cSstefano_zampini     honnz = NULL;
1646792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetRowSizes, hA->ij, hdnnz);
1647d975228cSstefano_zampini   }
1648ddbeb582SStefano Zampini 
1649af1cf968SStefano Zampini   /* reset assembled flag and call the initialize method */
1650af1cf968SStefano Zampini   hypre_IJMatrixAssembleFlag(hA->ij) = 0;
16516ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
1652792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij);
16536ea7df73SStefano Zampini #else
1654792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize_v2, hA->ij, HYPRE_MEMORY_HOST);
16556ea7df73SStefano Zampini #endif
165648a46eb9SPierre Jolivet   if (!dnnz) PetscCall(PetscFree(hdnnz));
165748a46eb9SPierre Jolivet   if (!onnz && honnz) PetscCall(PetscFree(honnz));
1658af1cf968SStefano Zampini   /* Match AIJ logic */
165906a29025Sstefano_zampini   A->preallocated = PETSC_TRUE;
1660af1cf968SStefano Zampini   A->assembled    = PETSC_FALSE;
16613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1662d975228cSstefano_zampini }
1663d975228cSstefano_zampini 
1664d975228cSstefano_zampini /*@C
1665d975228cSstefano_zampini   MatHYPRESetPreallocation - Preallocates memory for a sparse parallel matrix in HYPRE IJ format
1666d975228cSstefano_zampini 
1667c3339decSBarry Smith   Collective
1668d975228cSstefano_zampini 
1669d975228cSstefano_zampini   Input Parameters:
1670d975228cSstefano_zampini + A    - the matrix
1671d975228cSstefano_zampini . dnz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1672d975228cSstefano_zampini           (same value is used for all local rows)
1673d975228cSstefano_zampini . dnnz - array containing the number of nonzeros in the various rows of the
1674d975228cSstefano_zampini           DIAGONAL portion of the local submatrix (possibly different for each row)
16752ef1f0ffSBarry Smith           or `NULL` (`PETSC_NULL_INTEGER` in Fortran), if `d_nz` is used to specify the nonzero structure.
16762ef1f0ffSBarry Smith           The size of this array is equal to the number of local rows, i.e `m`.
1677d975228cSstefano_zampini           For matrices that will be factored, you must leave room for (and set)
1678d975228cSstefano_zampini           the diagonal entry even if it is zero.
1679d975228cSstefano_zampini . onz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1680d975228cSstefano_zampini           submatrix (same value is used for all local rows).
1681d975228cSstefano_zampini - onnz - array containing the number of nonzeros in the various rows of the
1682d975228cSstefano_zampini           OFF-DIAGONAL portion of the local submatrix (possibly different for
16832ef1f0ffSBarry Smith           each row) or `NULL` (`PETSC_NULL_INTEGER` in Fortran), if `o_nz` is used to specify the nonzero
1684d975228cSstefano_zampini           structure. The size of this array is equal to the number
16852ef1f0ffSBarry Smith           of local rows, i.e `m`.
1686d975228cSstefano_zampini 
16872fe279fdSBarry Smith   Level: intermediate
16882fe279fdSBarry Smith 
168911a5261eSBarry Smith   Note:
16902ef1f0ffSBarry Smith   If the *nnz parameter is given then the *nz parameter is ignored; for sequential matrices, `onz` and `onnz` are ignored.
1691d975228cSstefano_zampini 
16921cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatMPIAIJSetPreallocation()`, `MATHYPRE`, `MATAIJ`
1693d975228cSstefano_zampini @*/
1694d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHYPRESetPreallocation(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[])
1695d71ae5a4SJacob Faibussowitsch {
1696d975228cSstefano_zampini   PetscFunctionBegin;
1697d975228cSstefano_zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1698d975228cSstefano_zampini   PetscValidType(A, 1);
1699cac4c232SBarry Smith   PetscTryMethod(A, "MatHYPRESetPreallocation_C", (Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]), (A, dnz, dnnz, onz, onnz));
17003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1701d975228cSstefano_zampini }
1702d975228cSstefano_zampini 
170320f4b53cSBarry Smith /*@C
17042ef1f0ffSBarry Smith   MatCreateFromParCSR - Creates a `Mat` from a `hypre_ParCSRMatrix`
1705225daaf8SStefano Zampini 
1706225daaf8SStefano Zampini   Collective
1707225daaf8SStefano Zampini 
1708225daaf8SStefano Zampini   Input Parameters:
17092ef1f0ffSBarry Smith + parcsr   - the pointer to the `hypre_ParCSRMatrix`
17102ef1f0ffSBarry Smith . mtype    - matrix type to be created. Currently `MATAIJ`, `MATIS` and `MATHYPRE` are supported.
171120f4b53cSBarry Smith - copymode - PETSc copying options, see  `PetscCopyMode`
1712225daaf8SStefano Zampini 
1713225daaf8SStefano Zampini   Output Parameter:
1714225daaf8SStefano Zampini . A - the matrix
1715225daaf8SStefano Zampini 
1716225daaf8SStefano Zampini   Level: intermediate
1717225daaf8SStefano Zampini 
17181cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatHYPRE`, `PetscCopyMode`
171920f4b53cSBarry Smith @*/
1720d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreateFromParCSR(hypre_ParCSRMatrix *parcsr, MatType mtype, PetscCopyMode copymode, Mat *A)
1721d71ae5a4SJacob Faibussowitsch {
1722225daaf8SStefano Zampini   Mat        T;
1723978814f1SStefano Zampini   Mat_HYPRE *hA;
1724978814f1SStefano Zampini   MPI_Comm   comm;
1725978814f1SStefano Zampini   PetscInt   rstart, rend, cstart, cend, M, N;
1726d248a85cSRichard Tran Mills   PetscBool  isseqaij, isseqaijmkl, ismpiaij, isaij, ishyp, isis;
1727978814f1SStefano Zampini 
1728978814f1SStefano Zampini   PetscFunctionBegin;
1729978814f1SStefano Zampini   comm = hypre_ParCSRMatrixComm(parcsr);
17309566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQAIJ, &isseqaij));
17319566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQAIJMKL, &isseqaijmkl));
17329566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPIAIJ, &ismpiaij));
17339566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATAIJ, &isaij));
17349566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATHYPRE, &ishyp));
17359566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATIS, &isis));
1736d248a85cSRichard Tran Mills   isaij = (PetscBool)(isseqaij || isseqaijmkl || ismpiaij || isaij);
17376ea7df73SStefano Zampini   /* TODO */
1738aed4548fSBarry 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);
1739978814f1SStefano Zampini   /* access ParCSRMatrix */
1740978814f1SStefano Zampini   rstart = hypre_ParCSRMatrixFirstRowIndex(parcsr);
1741978814f1SStefano Zampini   rend   = hypre_ParCSRMatrixLastRowIndex(parcsr);
1742978814f1SStefano Zampini   cstart = hypre_ParCSRMatrixFirstColDiag(parcsr);
1743978814f1SStefano Zampini   cend   = hypre_ParCSRMatrixLastColDiag(parcsr);
1744978814f1SStefano Zampini   M      = hypre_ParCSRMatrixGlobalNumRows(parcsr);
1745978814f1SStefano Zampini   N      = hypre_ParCSRMatrixGlobalNumCols(parcsr);
1746978814f1SStefano Zampini 
1747fa92c42cSstefano_zampini   /* fix for empty local rows/columns */
1748fa92c42cSstefano_zampini   if (rend < rstart) rend = rstart;
1749fa92c42cSstefano_zampini   if (cend < cstart) cend = cstart;
1750fa92c42cSstefano_zampini 
1751e6471dc9SStefano Zampini   /* PETSc convention */
1752e6471dc9SStefano Zampini   rend++;
1753e6471dc9SStefano Zampini   cend++;
1754e6471dc9SStefano Zampini   rend = PetscMin(rend, M);
1755e6471dc9SStefano Zampini   cend = PetscMin(cend, N);
1756e6471dc9SStefano Zampini 
1757978814f1SStefano Zampini   /* create PETSc matrix with MatHYPRE */
17589566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, &T));
17599566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(T, rend - rstart, cend - cstart, M, N));
17609566063dSJacob Faibussowitsch   PetscCall(MatSetType(T, MATHYPRE));
1761f4f49eeaSPierre Jolivet   hA = (Mat_HYPRE *)T->data;
1762978814f1SStefano Zampini 
1763978814f1SStefano Zampini   /* create HYPRE_IJMatrix */
1764792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rstart, rend - 1, cstart, cend - 1, &hA->ij);
1765792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR);
176645b8d346SStefano Zampini 
176745b8d346SStefano Zampini   /* create new ParCSR object if needed */
176845b8d346SStefano Zampini   if (ishyp && copymode == PETSC_COPY_VALUES) {
176945b8d346SStefano Zampini     hypre_ParCSRMatrix *new_parcsr;
17706ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0)
177145b8d346SStefano Zampini     hypre_CSRMatrix *hdiag, *hoffd, *ndiag, *noffd;
177245b8d346SStefano Zampini 
17730e6427aaSSatish Balay     new_parcsr = hypre_ParCSRMatrixClone(parcsr, 0);
177445b8d346SStefano Zampini     hdiag      = hypre_ParCSRMatrixDiag(parcsr);
177545b8d346SStefano Zampini     hoffd      = hypre_ParCSRMatrixOffd(parcsr);
177645b8d346SStefano Zampini     ndiag      = hypre_ParCSRMatrixDiag(new_parcsr);
177745b8d346SStefano Zampini     noffd      = hypre_ParCSRMatrixOffd(new_parcsr);
17789566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hypre_CSRMatrixData(ndiag), hypre_CSRMatrixData(hdiag), hypre_CSRMatrixNumNonzeros(hdiag)));
17799566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hypre_CSRMatrixData(noffd), hypre_CSRMatrixData(hoffd), hypre_CSRMatrixNumNonzeros(hoffd)));
17806ea7df73SStefano Zampini #else
17816ea7df73SStefano Zampini     new_parcsr = hypre_ParCSRMatrixClone(parcsr, 1);
17826ea7df73SStefano Zampini #endif
178345b8d346SStefano Zampini     parcsr   = new_parcsr;
178445b8d346SStefano Zampini     copymode = PETSC_OWN_POINTER;
178545b8d346SStefano Zampini   }
1786978814f1SStefano Zampini 
1787978814f1SStefano Zampini   /* set ParCSR object */
1788978814f1SStefano Zampini   hypre_IJMatrixObject(hA->ij) = parcsr;
17894ec6421dSstefano_zampini   T->preallocated              = PETSC_TRUE;
1790978814f1SStefano Zampini 
1791978814f1SStefano Zampini   /* set assembled flag */
1792978814f1SStefano Zampini   hypre_IJMatrixAssembleFlag(hA->ij) = 1;
17936ea7df73SStefano Zampini #if 0
1794792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize,hA->ij);
17956ea7df73SStefano Zampini #endif
1796225daaf8SStefano Zampini   if (ishyp) {
17976d2a658fSstefano_zampini     PetscMPIInt myid = 0;
17986d2a658fSstefano_zampini 
17996d2a658fSstefano_zampini     /* make sure we always have row_starts and col_starts available */
180048a46eb9SPierre Jolivet     if (HYPRE_AssumedPartitionCheck()) PetscCallMPI(MPI_Comm_rank(comm, &myid));
1801a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
18026d2a658fSstefano_zampini     if (!hypre_ParCSRMatrixOwnsColStarts(parcsr)) {
18036d2a658fSstefano_zampini       PetscLayout map;
18046d2a658fSstefano_zampini 
18059566063dSJacob Faibussowitsch       PetscCall(MatGetLayouts(T, NULL, &map));
18069566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetUp(map));
18072cf14000SStefano Zampini       hypre_ParCSRMatrixColStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid);
18086d2a658fSstefano_zampini     }
18096d2a658fSstefano_zampini     if (!hypre_ParCSRMatrixOwnsRowStarts(parcsr)) {
18106d2a658fSstefano_zampini       PetscLayout map;
18116d2a658fSstefano_zampini 
18129566063dSJacob Faibussowitsch       PetscCall(MatGetLayouts(T, &map, NULL));
18139566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetUp(map));
18142cf14000SStefano Zampini       hypre_ParCSRMatrixRowStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid);
18156d2a658fSstefano_zampini     }
1816a1d2239cSSatish Balay #endif
1817978814f1SStefano Zampini     /* prevent from freeing the pointer */
1818978814f1SStefano Zampini     if (copymode == PETSC_USE_POINTER) hA->inner_free = PETSC_FALSE;
1819225daaf8SStefano Zampini     *A = T;
18209566063dSJacob Faibussowitsch     PetscCall(MatSetOption(*A, MAT_SORTED_FULL, PETSC_TRUE));
18219566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(*A, MAT_FINAL_ASSEMBLY));
18229566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(*A, MAT_FINAL_ASSEMBLY));
1823bb4689ddSStefano Zampini   } else if (isaij) {
1824bb4689ddSStefano Zampini     if (copymode != PETSC_OWN_POINTER) {
1825225daaf8SStefano Zampini       /* prevent from freeing the pointer */
1826225daaf8SStefano Zampini       hA->inner_free = PETSC_FALSE;
18279566063dSJacob Faibussowitsch       PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INITIAL_MATRIX, A));
18289566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&T));
1829225daaf8SStefano Zampini     } else { /* AIJ return type with PETSC_OWN_POINTER */
18309566063dSJacob Faibussowitsch       PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INPLACE_MATRIX, &T));
1831225daaf8SStefano Zampini       *A = T;
1832225daaf8SStefano Zampini     }
1833bb4689ddSStefano Zampini   } else if (isis) {
18349566063dSJacob Faibussowitsch     PetscCall(MatConvert_HYPRE_IS(T, MATIS, MAT_INITIAL_MATRIX, A));
18358cfe8d00SStefano Zampini     if (copymode != PETSC_OWN_POINTER) hA->inner_free = PETSC_FALSE;
18369566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&T));
1837bb4689ddSStefano Zampini   }
18383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1839978814f1SStefano Zampini }
1840978814f1SStefano Zampini 
1841d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPREGetParCSR_HYPRE(Mat A, hypre_ParCSRMatrix **parcsr)
1842d71ae5a4SJacob Faibussowitsch {
1843dd9c0a25Sstefano_zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1844dd9c0a25Sstefano_zampini   HYPRE_Int  type;
1845dd9c0a25Sstefano_zampini 
1846dd9c0a25Sstefano_zampini   PetscFunctionBegin;
184728b400f6SJacob Faibussowitsch   PetscCheck(hA->ij, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "HYPRE_IJMatrix not present");
1848792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
184908401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "HYPRE_IJMatrix is not of type HYPRE_PARCSR");
1850792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)parcsr);
18513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1852dd9c0a25Sstefano_zampini }
1853dd9c0a25Sstefano_zampini 
185420f4b53cSBarry Smith /*@C
1855dd9c0a25Sstefano_zampini   MatHYPREGetParCSR - Gets the pointer to the ParCSR matrix
1856dd9c0a25Sstefano_zampini 
1857cc4c1da9SBarry Smith   Not Collective, No Fortran Support
1858dd9c0a25Sstefano_zampini 
185920f4b53cSBarry Smith   Input Parameter:
186020f4b53cSBarry Smith . A - the `MATHYPRE` object
1861dd9c0a25Sstefano_zampini 
1862dd9c0a25Sstefano_zampini   Output Parameter:
18632ef1f0ffSBarry Smith . parcsr - the pointer to the `hypre_ParCSRMatrix`
1864dd9c0a25Sstefano_zampini 
1865dd9c0a25Sstefano_zampini   Level: intermediate
1866dd9c0a25Sstefano_zampini 
18671cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatHYPRE`, `PetscCopyMode`
186820f4b53cSBarry Smith @*/
1869d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHYPREGetParCSR(Mat A, hypre_ParCSRMatrix **parcsr)
1870d71ae5a4SJacob Faibussowitsch {
1871dd9c0a25Sstefano_zampini   PetscFunctionBegin;
1872dd9c0a25Sstefano_zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1873dd9c0a25Sstefano_zampini   PetscValidType(A, 1);
1874cac4c232SBarry Smith   PetscUseMethod(A, "MatHYPREGetParCSR_C", (Mat, hypre_ParCSRMatrix **), (A, parcsr));
18753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1876dd9c0a25Sstefano_zampini }
1877dd9c0a25Sstefano_zampini 
1878d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_HYPRE(Mat A, PetscBool *missing, PetscInt *dd)
1879d71ae5a4SJacob Faibussowitsch {
188068ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
188168ec7858SStefano Zampini   hypre_CSRMatrix    *ha;
188268ec7858SStefano Zampini   PetscInt            rst;
188368ec7858SStefano Zampini 
188468ec7858SStefano Zampini   PetscFunctionBegin;
188508401ef6SPierre Jolivet   PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented with non-square diagonal blocks");
18869566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &rst, NULL));
18879566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
188868ec7858SStefano Zampini   if (missing) *missing = PETSC_FALSE;
188968ec7858SStefano Zampini   if (dd) *dd = -1;
189068ec7858SStefano Zampini   ha = hypre_ParCSRMatrixDiag(parcsr);
189168ec7858SStefano Zampini   if (ha) {
189268299464SStefano Zampini     PetscInt   size, i;
189368299464SStefano Zampini     HYPRE_Int *ii, *jj;
189468ec7858SStefano Zampini 
189568ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
189668ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
189768ec7858SStefano Zampini     jj   = hypre_CSRMatrixJ(ha);
189868ec7858SStefano Zampini     for (i = 0; i < size; i++) {
189968ec7858SStefano Zampini       PetscInt  j;
190068ec7858SStefano Zampini       PetscBool found = PETSC_FALSE;
190168ec7858SStefano Zampini 
19029371c9d4SSatish Balay       for (j = ii[i]; j < ii[i + 1] && !found; j++) found = (jj[j] == i) ? PETSC_TRUE : PETSC_FALSE;
190368ec7858SStefano Zampini 
190468ec7858SStefano Zampini       if (!found) {
19053ba16761SJacob Faibussowitsch         PetscCall(PetscInfo(A, "Matrix is missing local diagonal entry %" PetscInt_FMT "\n", i));
190668ec7858SStefano Zampini         if (missing) *missing = PETSC_TRUE;
190768ec7858SStefano Zampini         if (dd) *dd = i + rst;
19083ba16761SJacob Faibussowitsch         PetscFunctionReturn(PETSC_SUCCESS);
190968ec7858SStefano Zampini       }
191068ec7858SStefano Zampini     }
191168ec7858SStefano Zampini     if (!size) {
19123ba16761SJacob Faibussowitsch       PetscCall(PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n"));
191368ec7858SStefano Zampini       if (missing) *missing = PETSC_TRUE;
191468ec7858SStefano Zampini       if (dd) *dd = rst;
191568ec7858SStefano Zampini     }
191668ec7858SStefano Zampini   } else {
19173ba16761SJacob Faibussowitsch     PetscCall(PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n"));
191868ec7858SStefano Zampini     if (missing) *missing = PETSC_TRUE;
191968ec7858SStefano Zampini     if (dd) *dd = rst;
192068ec7858SStefano Zampini   }
19213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
192268ec7858SStefano Zampini }
192368ec7858SStefano Zampini 
1924d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatScale_HYPRE(Mat A, PetscScalar s)
1925d71ae5a4SJacob Faibussowitsch {
192668ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
19276ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
192868ec7858SStefano Zampini   hypre_CSRMatrix *ha;
19296ea7df73SStefano Zampini #endif
193039accc25SStefano Zampini   HYPRE_Complex hs;
193168ec7858SStefano Zampini 
193268ec7858SStefano Zampini   PetscFunctionBegin;
19339566063dSJacob Faibussowitsch   PetscCall(PetscHYPREScalarCast(s, &hs));
19349566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
19356ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 19, 0)
1936792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixScale, parcsr, hs);
19376ea7df73SStefano Zampini #else /* diagonal part */
193868ec7858SStefano Zampini   ha = hypre_ParCSRMatrixDiag(parcsr);
193968ec7858SStefano Zampini   if (ha) {
194068299464SStefano Zampini     PetscInt       size, i;
194168299464SStefano Zampini     HYPRE_Int     *ii;
194239accc25SStefano Zampini     HYPRE_Complex *a;
194368ec7858SStefano Zampini 
194468ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
194568ec7858SStefano Zampini     a    = hypre_CSRMatrixData(ha);
194668ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
194739accc25SStefano Zampini     for (i = 0; i < ii[size]; i++) a[i] *= hs;
194868ec7858SStefano Zampini   }
19494cf0e950SBarry Smith   /* off-diagonal part */
195068ec7858SStefano Zampini   ha = hypre_ParCSRMatrixOffd(parcsr);
195168ec7858SStefano Zampini   if (ha) {
195268299464SStefano Zampini     PetscInt       size, i;
195368299464SStefano Zampini     HYPRE_Int     *ii;
195439accc25SStefano Zampini     HYPRE_Complex *a;
195568ec7858SStefano Zampini 
195668ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
195768ec7858SStefano Zampini     a    = hypre_CSRMatrixData(ha);
195868ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
195939accc25SStefano Zampini     for (i = 0; i < ii[size]; i++) a[i] *= hs;
196068ec7858SStefano Zampini   }
19616ea7df73SStefano Zampini #endif
19623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
196368ec7858SStefano Zampini }
196468ec7858SStefano Zampini 
1965d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_HYPRE(Mat A, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
1966d71ae5a4SJacob Faibussowitsch {
196768ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
196868299464SStefano Zampini   HYPRE_Int          *lrows;
196968299464SStefano Zampini   PetscInt            rst, ren, i;
197068ec7858SStefano Zampini 
197168ec7858SStefano Zampini   PetscFunctionBegin;
197208401ef6SPierre Jolivet   PetscCheck(!x && !b, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "To be implemented");
19739566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
19749566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numRows, &lrows));
19759566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &rst, &ren));
197668ec7858SStefano Zampini   for (i = 0; i < numRows; i++) {
19777a46b595SBarry Smith     PetscCheck(rows[i] >= rst && rows[i] < ren, PETSC_COMM_SELF, PETSC_ERR_SUP, "Non-local rows not yet supported");
197868ec7858SStefano Zampini     lrows[i] = rows[i] - rst;
197968ec7858SStefano Zampini   }
1980792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixEliminateRowsCols, parcsr, numRows, lrows);
19819566063dSJacob Faibussowitsch   PetscCall(PetscFree(lrows));
19823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
198368ec7858SStefano Zampini }
198468ec7858SStefano Zampini 
1985d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPRE_CSRMatrix(hypre_CSRMatrix *ha)
1986d71ae5a4SJacob Faibussowitsch {
1987c69f721fSFande Kong   PetscFunctionBegin;
1988c69f721fSFande Kong   if (ha) {
1989c69f721fSFande Kong     HYPRE_Int     *ii, size;
1990c69f721fSFande Kong     HYPRE_Complex *a;
1991c69f721fSFande Kong 
1992c69f721fSFande Kong     size = hypre_CSRMatrixNumRows(ha);
1993c69f721fSFande Kong     a    = hypre_CSRMatrixData(ha);
1994c69f721fSFande Kong     ii   = hypre_CSRMatrixI(ha);
1995c69f721fSFande Kong 
19969566063dSJacob Faibussowitsch     if (a) PetscCall(PetscArrayzero(a, ii[size]));
1997c69f721fSFande Kong   }
19983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1999c69f721fSFande Kong }
2000c69f721fSFande Kong 
200166976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPRE(Mat A)
2002d71ae5a4SJacob Faibussowitsch {
20036ea7df73SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
20046ea7df73SStefano Zampini 
20056ea7df73SStefano Zampini   PetscFunctionBegin;
20066ea7df73SStefano Zampini   if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(hA->ij)) {
2007792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetConstantValues, hA->ij, 0.0);
20086ea7df73SStefano Zampini   } else {
2009c69f721fSFande Kong     hypre_ParCSRMatrix *parcsr;
2010c69f721fSFande Kong 
20119566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
20129566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr)));
20139566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr)));
20146ea7df73SStefano Zampini   }
20153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2016c69f721fSFande Kong }
2017c69f721fSFande Kong 
2018d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_HYPRE_CSRMatrix(hypre_CSRMatrix *hA, PetscInt N, const PetscInt rows[], HYPRE_Complex diag)
2019d71ae5a4SJacob Faibussowitsch {
202039accc25SStefano Zampini   PetscInt       ii;
202139accc25SStefano Zampini   HYPRE_Int     *i, *j;
202239accc25SStefano Zampini   HYPRE_Complex *a;
2023c69f721fSFande Kong 
2024c69f721fSFande Kong   PetscFunctionBegin;
20253ba16761SJacob Faibussowitsch   if (!hA) PetscFunctionReturn(PETSC_SUCCESS);
2026c69f721fSFande Kong 
202739accc25SStefano Zampini   i = hypre_CSRMatrixI(hA);
202839accc25SStefano Zampini   j = hypre_CSRMatrixJ(hA);
2029c69f721fSFande Kong   a = hypre_CSRMatrixData(hA);
2030a32e9c99SJunchao Zhang #if defined(PETSC_HAVE_HYPRE_DEVICE)
2031a32e9c99SJunchao Zhang   if (HYPRE_MEMORY_DEVICE == hypre_CSRMatrixMemoryLocation(hA)) {
2032a32e9c99SJunchao Zhang   #if defined(HYPRE_USING_CUDA)
2033a32e9c99SJunchao Zhang     MatZeroRows_CUDA(N, rows, i, j, a, diag);
2034a32e9c99SJunchao Zhang   #elif defined(HYPRE_USING_HIP)
2035a32e9c99SJunchao Zhang     MatZeroRows_HIP(N, rows, i, j, a, diag);
2036a32e9c99SJunchao Zhang   #elif defined(PETSC_HAVE_KOKKOS)
2037a32e9c99SJunchao Zhang     MatZeroRows_Kokkos(N, rows, i, j, a, diag);
2038a32e9c99SJunchao Zhang   #else
2039a32e9c99SJunchao Zhang     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for MatZeroRows on a hypre matrix in this memory location");
2040a32e9c99SJunchao Zhang   #endif
2041a32e9c99SJunchao Zhang   } else
2042a32e9c99SJunchao Zhang #endif
2043a32e9c99SJunchao Zhang   {
2044c69f721fSFande Kong     for (ii = 0; ii < N; ii++) {
204539accc25SStefano Zampini       HYPRE_Int jj, ibeg, iend, irow;
204639accc25SStefano Zampini 
2047c69f721fSFande Kong       irow = rows[ii];
2048c69f721fSFande Kong       ibeg = i[irow];
2049c69f721fSFande Kong       iend = i[irow + 1];
2050c69f721fSFande Kong       for (jj = ibeg; jj < iend; jj++)
2051c69f721fSFande Kong         if (j[jj] == irow) a[jj] = diag;
2052c69f721fSFande Kong         else a[jj] = 0.0;
2053c69f721fSFande Kong     }
2054a32e9c99SJunchao Zhang   }
20553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2056c69f721fSFande Kong }
2057c69f721fSFande Kong 
2058d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_HYPRE(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
2059d71ae5a4SJacob Faibussowitsch {
2060c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
2061a32e9c99SJunchao Zhang   PetscInt           *lrows, len, *lrows2;
206239accc25SStefano Zampini   HYPRE_Complex       hdiag;
2063c69f721fSFande Kong 
2064c69f721fSFande Kong   PetscFunctionBegin;
206508401ef6SPierre Jolivet   PetscCheck(!x && !b, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Does not support to modify the solution and the right hand size");
20669566063dSJacob Faibussowitsch   PetscCall(PetscHYPREScalarCast(diag, &hdiag));
2067c69f721fSFande Kong   /* retrieve the internal matrix */
20689566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
2069c69f721fSFande Kong   /* get locally owned rows */
20709566063dSJacob Faibussowitsch   PetscCall(MatZeroRowsMapLocal_Private(A, N, rows, &len, &lrows));
2071a32e9c99SJunchao Zhang 
2072a32e9c99SJunchao Zhang #if defined(PETSC_HAVE_HYPRE_DEVICE)
2073a32e9c99SJunchao Zhang   if (HYPRE_MEMORY_DEVICE == hypre_CSRMatrixMemoryLocation(hypre_ParCSRMatrixDiag(parcsr))) {
2074a32e9c99SJunchao Zhang     Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
2075a32e9c99SJunchao Zhang     PetscInt   m;
2076a32e9c99SJunchao Zhang     PetscCall(MatGetLocalSize(A, &m, NULL));
2077a32e9c99SJunchao Zhang     if (!hA->rows_d) {
2078a32e9c99SJunchao Zhang       hA->rows_d = hypre_TAlloc(PetscInt, m, HYPRE_MEMORY_DEVICE);
2079a32e9c99SJunchao Zhang       if (m) PetscCheck(hA->rows_d, PETSC_COMM_SELF, PETSC_ERR_MEM, "HYPRE_TAlloc failed");
2080a32e9c99SJunchao Zhang     }
2081a32e9c99SJunchao Zhang     PetscCheck(len <= m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Too many rows in rows[]");
2082a32e9c99SJunchao Zhang     PetscStackCallExternalVoid("hypre_Memcpy", hypre_Memcpy(hA->rows_d, lrows, sizeof(PetscInt) * len, HYPRE_MEMORY_DEVICE, HYPRE_MEMORY_HOST));
2083a32e9c99SJunchao Zhang     lrows2 = hA->rows_d;
2084a32e9c99SJunchao Zhang   } else
2085a32e9c99SJunchao Zhang #endif
2086a32e9c99SJunchao Zhang   {
2087a32e9c99SJunchao Zhang     lrows2 = lrows;
2088a32e9c99SJunchao Zhang   }
2089a32e9c99SJunchao Zhang 
2090c69f721fSFande Kong   /* zero diagonal part */
2091a32e9c99SJunchao Zhang   PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr), len, lrows2, hdiag));
2092c69f721fSFande Kong   /* zero off-diagonal part */
2093a32e9c99SJunchao Zhang   PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr), len, lrows2, 0.0));
2094c69f721fSFande Kong 
20959566063dSJacob Faibussowitsch   PetscCall(PetscFree(lrows));
20963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2097c69f721fSFande Kong }
2098c69f721fSFande Kong 
2099d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_HYPRE(Mat mat, MatAssemblyType mode)
2100d71ae5a4SJacob Faibussowitsch {
2101c69f721fSFande Kong   PetscFunctionBegin;
21023ba16761SJacob Faibussowitsch   if (mat->nooffprocentries) PetscFunctionReturn(PETSC_SUCCESS);
2103c69f721fSFande Kong 
21049566063dSJacob Faibussowitsch   PetscCall(MatStashScatterBegin_Private(mat, &mat->stash, mat->rmap->range));
21053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2106c69f721fSFande Kong }
2107c69f721fSFande Kong 
2108d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
2109d71ae5a4SJacob Faibussowitsch {
2110c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
21112cf14000SStefano Zampini   HYPRE_Int           hnz;
2112c69f721fSFande Kong 
2113c69f721fSFande Kong   PetscFunctionBegin;
2114c69f721fSFande Kong   /* retrieve the internal matrix */
21159566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
2116c69f721fSFande Kong   /* call HYPRE API */
2117792fecdfSBarry Smith   PetscCallExternal(HYPRE_ParCSRMatrixGetRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v);
21182cf14000SStefano Zampini   if (nz) *nz = (PetscInt)hnz;
21193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2120c69f721fSFande Kong }
2121c69f721fSFande Kong 
2122d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
2123d71ae5a4SJacob Faibussowitsch {
2124c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
21252cf14000SStefano Zampini   HYPRE_Int           hnz;
2126c69f721fSFande Kong 
2127c69f721fSFande Kong   PetscFunctionBegin;
2128c69f721fSFande Kong   /* retrieve the internal matrix */
21299566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
2130c69f721fSFande Kong   /* call HYPRE API */
21312cf14000SStefano Zampini   hnz = nz ? (HYPRE_Int)(*nz) : 0;
2132792fecdfSBarry Smith   PetscCallExternal(HYPRE_ParCSRMatrixRestoreRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v);
21333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2134c69f721fSFande Kong }
2135c69f721fSFande Kong 
2136d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetValues_HYPRE(Mat A, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2137d71ae5a4SJacob Faibussowitsch {
213845b8d346SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
2139c69f721fSFande Kong   PetscInt   i;
21401d4906efSStefano Zampini 
2141c69f721fSFande Kong   PetscFunctionBegin;
21423ba16761SJacob Faibussowitsch   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2143c69f721fSFande Kong   /* Ignore negative row indices
2144c69f721fSFande Kong    * And negative column indices should be automatically ignored in hypre
2145c69f721fSFande Kong    * */
21462cf14000SStefano Zampini   for (i = 0; i < m; i++) {
21472cf14000SStefano Zampini     if (idxm[i] >= 0) {
21482cf14000SStefano Zampini       HYPRE_Int hn = (HYPRE_Int)n;
2149792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetValues, hA->ij, 1, &hn, (HYPRE_BigInt *)&idxm[i], (HYPRE_BigInt *)idxn, (HYPRE_Complex *)(v + i * n));
21502cf14000SStefano Zampini     }
21512cf14000SStefano Zampini   }
21523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2153c69f721fSFande Kong }
2154c69f721fSFande Kong 
2155d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_HYPRE(Mat A, MatOption op, PetscBool flg)
2156d71ae5a4SJacob Faibussowitsch {
2157ddbeb582SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
2158ddbeb582SStefano Zampini 
2159ddbeb582SStefano Zampini   PetscFunctionBegin;
2160c6698e78SStefano Zampini   switch (op) {
2161ddbeb582SStefano Zampini   case MAT_NO_OFF_PROC_ENTRIES:
216248a46eb9SPierre Jolivet     if (flg) PetscCallExternal(HYPRE_IJMatrixSetMaxOffProcElmts, hA->ij, 0);
2163ddbeb582SStefano Zampini     break;
2164651b1cf9SStefano Zampini   case MAT_IGNORE_OFF_PROC_ENTRIES:
2165651b1cf9SStefano Zampini     hA->donotstash = flg;
2166d71ae5a4SJacob Faibussowitsch     break;
2167d71ae5a4SJacob Faibussowitsch   default:
2168d71ae5a4SJacob Faibussowitsch     break;
2169ddbeb582SStefano Zampini   }
21703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2171ddbeb582SStefano Zampini }
2172c69f721fSFande Kong 
2173d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_HYPRE(Mat A, PetscViewer view)
2174d71ae5a4SJacob Faibussowitsch {
217545b8d346SStefano Zampini   PetscViewerFormat format;
217645b8d346SStefano Zampini 
217745b8d346SStefano Zampini   PetscFunctionBegin;
21789566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(view, &format));
21793ba16761SJacob Faibussowitsch   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(PETSC_SUCCESS);
218045b8d346SStefano Zampini   if (format != PETSC_VIEWER_NATIVE) {
21816ea7df73SStefano Zampini     Mat                 B;
21826ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
21836ea7df73SStefano Zampini     PetscErrorCode (*mview)(Mat, PetscViewer) = NULL;
21846ea7df73SStefano Zampini 
21859566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
21869566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(parcsr, MATAIJ, PETSC_USE_POINTER, &B));
21879566063dSJacob Faibussowitsch     PetscCall(MatGetOperation(B, MATOP_VIEW, (void (**)(void))&mview));
218828b400f6SJacob Faibussowitsch     PetscCheck(mview, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Missing view operation");
21899566063dSJacob Faibussowitsch     PetscCall((*mview)(B, view));
21909566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
219145b8d346SStefano Zampini   } else {
219245b8d346SStefano Zampini     Mat_HYPRE  *hA = (Mat_HYPRE *)A->data;
219345b8d346SStefano Zampini     PetscMPIInt size;
219445b8d346SStefano Zampini     PetscBool   isascii;
219545b8d346SStefano Zampini     const char *filename;
219645b8d346SStefano Zampini 
219745b8d346SStefano Zampini     /* HYPRE uses only text files */
21989566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERASCII, &isascii));
219928b400f6SJacob Faibussowitsch     PetscCheck(isascii, PetscObjectComm((PetscObject)view), PETSC_ERR_SUP, "PetscViewerType %s: native HYPRE format needs PETSCVIEWERASCII", ((PetscObject)view)->type_name);
22009566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileGetName(view, &filename));
2201792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixPrint, hA->ij, filename);
22029566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(hA->comm, &size));
220345b8d346SStefano Zampini     if (size > 1) {
22049566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(view, "Matrix files: %s.%05d ... %s.%05d\n", filename, 0, filename, size - 1));
220545b8d346SStefano Zampini     } else {
22069566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(view, "Matrix file: %s.%05d\n", filename, 0));
220745b8d346SStefano Zampini     }
220845b8d346SStefano Zampini   }
22093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
221045b8d346SStefano Zampini }
221145b8d346SStefano Zampini 
2212d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCopy_HYPRE(Mat A, Mat B, MatStructure str)
2213d71ae5a4SJacob Faibussowitsch {
2214465edc17SStefano Zampini   hypre_ParCSRMatrix *acsr, *bcsr;
2215465edc17SStefano Zampini 
2216465edc17SStefano Zampini   PetscFunctionBegin;
2217465edc17SStefano Zampini   if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) {
22189566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &acsr));
22199566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(B, &bcsr));
2220792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixCopy, acsr, bcsr, 1);
22219566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_SORTED_FULL, PETSC_TRUE)); /* "perfect" preallocation, so no need for hypre_AuxParCSRMatrixNeedAux */
22229566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
22239566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
2224465edc17SStefano Zampini   } else {
22259566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
2226465edc17SStefano Zampini   }
22273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2228465edc17SStefano Zampini }
2229465edc17SStefano Zampini 
2230d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_HYPRE(Mat A, Vec d)
2231d71ae5a4SJacob Faibussowitsch {
22326305df00SStefano Zampini   hypre_ParCSRMatrix *parcsr;
22336305df00SStefano Zampini   hypre_CSRMatrix    *dmat;
223439accc25SStefano Zampini   HYPRE_Complex      *a;
22356305df00SStefano Zampini   PetscBool           cong;
22366305df00SStefano Zampini 
22376305df00SStefano Zampini   PetscFunctionBegin;
22389566063dSJacob Faibussowitsch   PetscCall(MatHasCongruentLayouts(A, &cong));
223928b400f6SJacob Faibussowitsch   PetscCheck(cong, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only for square matrices with same local distributions of rows and columns");
22409566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
22416305df00SStefano Zampini   dmat = hypre_ParCSRMatrixDiag(parcsr);
22426305df00SStefano Zampini   if (dmat) {
224306977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
224406977982Sstefanozampini     HYPRE_MemoryLocation mem = hypre_CSRMatrixMemoryLocation(dmat);
224506977982Sstefanozampini #else
224606977982Sstefanozampini     HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST;
224706977982Sstefanozampini #endif
224806977982Sstefanozampini 
224906977982Sstefanozampini     if (mem != HYPRE_MEMORY_HOST) PetscCall(VecGetArrayWriteAndMemType(d, (PetscScalar **)&a, NULL));
225006977982Sstefanozampini     else PetscCall(VecGetArrayWrite(d, (PetscScalar **)&a));
225106977982Sstefanozampini     hypre_CSRMatrixExtractDiagonal(dmat, a, 0);
225206977982Sstefanozampini     if (mem != HYPRE_MEMORY_HOST) PetscCall(VecRestoreArrayWriteAndMemType(d, (PetscScalar **)&a));
225306977982Sstefanozampini     else PetscCall(VecRestoreArrayWrite(d, (PetscScalar **)&a));
22546305df00SStefano Zampini   }
22553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22566305df00SStefano Zampini }
22576305df00SStefano Zampini 
2258363d496dSStefano Zampini #include <petscblaslapack.h>
2259363d496dSStefano Zampini 
2260d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAXPY_HYPRE(Mat Y, PetscScalar a, Mat X, MatStructure str)
2261d71ae5a4SJacob Faibussowitsch {
2262363d496dSStefano Zampini   PetscFunctionBegin;
22636ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
22646ea7df73SStefano Zampini   {
22656ea7df73SStefano Zampini     Mat                 B;
22666ea7df73SStefano Zampini     hypre_ParCSRMatrix *x, *y, *z;
22676ea7df73SStefano Zampini 
22689566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(Y, &y));
22699566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(X, &x));
2270792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixAdd, 1.0, y, 1.0, x, &z);
22719566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(z, MATHYPRE, PETSC_OWN_POINTER, &B));
22729566063dSJacob Faibussowitsch     PetscCall(MatHeaderMerge(Y, &B));
22736ea7df73SStefano Zampini   }
22746ea7df73SStefano Zampini #else
2275363d496dSStefano Zampini   if (str == SAME_NONZERO_PATTERN) {
2276363d496dSStefano Zampini     hypre_ParCSRMatrix *x, *y;
2277363d496dSStefano Zampini     hypre_CSRMatrix    *xloc, *yloc;
2278363d496dSStefano Zampini     PetscInt            xnnz, ynnz;
227939accc25SStefano Zampini     HYPRE_Complex      *xarr, *yarr;
2280363d496dSStefano Zampini     PetscBLASInt        one = 1, bnz;
2281363d496dSStefano Zampini 
22829566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(Y, &y));
22839566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(X, &x));
2284363d496dSStefano Zampini 
2285363d496dSStefano Zampini     /* diagonal block */
2286363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixDiag(x);
2287363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixDiag(y);
2288363d496dSStefano Zampini     xnnz = 0;
2289363d496dSStefano Zampini     ynnz = 0;
2290363d496dSStefano Zampini     xarr = NULL;
2291363d496dSStefano Zampini     yarr = NULL;
2292363d496dSStefano Zampini     if (xloc) {
229339accc25SStefano Zampini       xarr = hypre_CSRMatrixData(xloc);
2294363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
2295363d496dSStefano Zampini     }
2296363d496dSStefano Zampini     if (yloc) {
229739accc25SStefano Zampini       yarr = hypre_CSRMatrixData(yloc);
2298363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
2299363d496dSStefano Zampini     }
230008401ef6SPierre Jolivet     PetscCheck(xnnz == ynnz, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Different number of nonzeros in diagonal block %" PetscInt_FMT " != %" PetscInt_FMT, xnnz, ynnz);
23019566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(xnnz, &bnz));
2302792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one));
2303363d496dSStefano Zampini 
2304363d496dSStefano Zampini     /* off-diagonal block */
2305363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixOffd(x);
2306363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixOffd(y);
2307363d496dSStefano Zampini     xnnz = 0;
2308363d496dSStefano Zampini     ynnz = 0;
2309363d496dSStefano Zampini     xarr = NULL;
2310363d496dSStefano Zampini     yarr = NULL;
2311363d496dSStefano Zampini     if (xloc) {
231239accc25SStefano Zampini       xarr = hypre_CSRMatrixData(xloc);
2313363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
2314363d496dSStefano Zampini     }
2315363d496dSStefano Zampini     if (yloc) {
231639accc25SStefano Zampini       yarr = hypre_CSRMatrixData(yloc);
2317363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
2318363d496dSStefano Zampini     }
231908401ef6SPierre 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);
23209566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(xnnz, &bnz));
2321792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one));
2322363d496dSStefano Zampini   } else if (str == SUBSET_NONZERO_PATTERN) {
23239566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic(Y, a, X, str));
2324363d496dSStefano Zampini   } else {
2325363d496dSStefano Zampini     Mat B;
2326363d496dSStefano Zampini 
23279566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic_Preallocate(Y, X, &B));
23289566063dSJacob Faibussowitsch     PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str));
23299566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(Y, &B));
2330363d496dSStefano Zampini   }
23316ea7df73SStefano Zampini #endif
23323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2333363d496dSStefano Zampini }
2334363d496dSStefano Zampini 
23352c4ab24aSJunchao Zhang static PetscErrorCode MatDuplicate_HYPRE(Mat A, MatDuplicateOption op, Mat *B)
23362c4ab24aSJunchao Zhang {
23372c4ab24aSJunchao Zhang   hypre_ParCSRMatrix *parcsr = NULL;
23382c4ab24aSJunchao Zhang   PetscCopyMode       cpmode;
23392c4ab24aSJunchao Zhang   Mat_HYPRE          *hA;
23402c4ab24aSJunchao Zhang 
23412c4ab24aSJunchao Zhang   PetscFunctionBegin;
23422c4ab24aSJunchao Zhang   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
23432c4ab24aSJunchao Zhang   if (op == MAT_DO_NOT_COPY_VALUES || op == MAT_SHARE_NONZERO_PATTERN) {
23442c4ab24aSJunchao Zhang     parcsr = hypre_ParCSRMatrixClone(parcsr, 0);
23452c4ab24aSJunchao Zhang     cpmode = PETSC_OWN_POINTER;
23462c4ab24aSJunchao Zhang   } else {
23472c4ab24aSJunchao Zhang     cpmode = PETSC_COPY_VALUES;
23482c4ab24aSJunchao Zhang   }
23492c4ab24aSJunchao Zhang   PetscCall(MatCreateFromParCSR(parcsr, MATHYPRE, cpmode, B));
23502c4ab24aSJunchao Zhang   hA = (Mat_HYPRE *)A->data;
23512c4ab24aSJunchao Zhang   if (hA->cooMat) {
235206977982Sstefanozampini     Mat_HYPRE *hB = (Mat_HYPRE *)((*B)->data);
2353b73e3080SStefano Zampini     op            = (op == MAT_DO_NOT_COPY_VALUES) ? op : MAT_COPY_VALUES;
2354b73e3080SStefano Zampini     /* Cannot simply increase the reference count of hA->cooMat, since B needs to share cooMat's data array */
235506977982Sstefanozampini     PetscCall(MatDuplicate(hA->cooMat, op, &hB->cooMat));
235606977982Sstefanozampini     PetscCall(MatHYPRE_AttachCOOMat(*B));
23572c4ab24aSJunchao Zhang   }
23582c4ab24aSJunchao Zhang   PetscFunctionReturn(PETSC_SUCCESS);
23592c4ab24aSJunchao Zhang }
23602c4ab24aSJunchao Zhang 
2361d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetPreallocationCOO_HYPRE(Mat mat, PetscCount coo_n, PetscInt coo_i[], PetscInt coo_j[])
2362d71ae5a4SJacob Faibussowitsch {
236306977982Sstefanozampini   Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data;
23645fbaff96SJunchao Zhang 
23655fbaff96SJunchao Zhang   PetscFunctionBegin;
2366651b1cf9SStefano Zampini   /* Build an agent matrix cooMat with AIJ format
23675fbaff96SJunchao 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.
23685fbaff96SJunchao Zhang    */
236906977982Sstefanozampini   PetscCall(MatHYPRE_CreateCOOMat(mat));
237006977982Sstefanozampini   PetscCall(MatSetOption(hmat->cooMat, MAT_IGNORE_OFF_PROC_ENTRIES, hmat->donotstash));
237106977982Sstefanozampini   PetscCall(MatSetOption(hmat->cooMat, MAT_NO_OFF_PROC_ENTRIES, mat->nooffprocentries));
2372651b1cf9SStefano Zampini 
2373651b1cf9SStefano Zampini   /* MatSetPreallocationCOO_SeqAIJ and MatSetPreallocationCOO_MPIAIJ uses this specific
2374651b1cf9SStefano Zampini      name to automatically put the diagonal entries first */
237506977982Sstefanozampini   PetscCall(PetscObjectSetName((PetscObject)hmat->cooMat, "_internal_COO_mat_for_hypre"));
237606977982Sstefanozampini   PetscCall(MatSetPreallocationCOO(hmat->cooMat, coo_n, coo_i, coo_j));
237706977982Sstefanozampini   hmat->cooMat->assembled = PETSC_TRUE;
23785fbaff96SJunchao Zhang 
23795fbaff96SJunchao Zhang   /* Copy the sparsity pattern from cooMat to hypre IJMatrix hmat->ij */
23805fbaff96SJunchao Zhang   PetscCall(MatSetOption(mat, MAT_SORTED_FULL, PETSC_TRUE));
238106977982Sstefanozampini   PetscCall(MatHYPRE_CreateFromMat(hmat->cooMat, hmat));      /* Create hmat->ij and preallocate it */
238206977982Sstefanozampini   PetscCall(MatHYPRE_IJMatrixCopyIJ(hmat->cooMat, hmat->ij)); /* Copy A's (i,j) to hmat->ij */
23835fbaff96SJunchao Zhang 
23845fbaff96SJunchao Zhang   mat->preallocated = PETSC_TRUE;
23855fbaff96SJunchao Zhang   PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
23865fbaff96SJunchao Zhang   PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); /* Migrate mat to device if it is bound to. Hypre builds its own SpMV context here */
23875fbaff96SJunchao Zhang 
23882c4ab24aSJunchao Zhang   /* Attach cooMat to mat */
238906977982Sstefanozampini   PetscCall(MatHYPRE_AttachCOOMat(mat));
23903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23915fbaff96SJunchao Zhang }
23925fbaff96SJunchao Zhang 
2393d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesCOO_HYPRE(Mat mat, const PetscScalar v[], InsertMode imode)
2394d71ae5a4SJacob Faibussowitsch {
23955fbaff96SJunchao Zhang   Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data;
23965fbaff96SJunchao Zhang 
23975fbaff96SJunchao Zhang   PetscFunctionBegin;
2398b73e3080SStefano Zampini   PetscCheck(hmat->cooMat, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet");
23995fbaff96SJunchao Zhang   PetscCall(MatSetValuesCOO(hmat->cooMat, v, imode));
2400651b1cf9SStefano Zampini   PetscCall(MatViewFromOptions(hmat->cooMat, (PetscObject)mat, "-cooMat_view"));
24013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24025fbaff96SJunchao Zhang }
24035fbaff96SJunchao Zhang 
2404a055b5aaSBarry Smith /*MC
24052ef1f0ffSBarry Smith    MATHYPRE - "hypre" - A matrix type to be used for sequential and parallel sparse matrices
2406a055b5aaSBarry Smith           based on the hypre IJ interface.
2407a055b5aaSBarry Smith 
2408a055b5aaSBarry Smith    Level: intermediate
2409a055b5aaSBarry Smith 
24101cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatHYPRESetPreallocation`
2411a055b5aaSBarry Smith M*/
2412a055b5aaSBarry Smith 
2413d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_HYPRE(Mat B)
2414d71ae5a4SJacob Faibussowitsch {
241563c07aadSStefano Zampini   Mat_HYPRE *hB;
2416a9e6c71bSAlex Lindsay #if defined(PETSC_HAVE_HYPRE_DEVICE)
2417a9e6c71bSAlex Lindsay   HYPRE_MemoryLocation memory_location;
2418a9e6c71bSAlex Lindsay #endif
241963c07aadSStefano Zampini 
242063c07aadSStefano Zampini   PetscFunctionBegin;
2421a9e6c71bSAlex Lindsay   PetscHYPREInitialize();
24224dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&hB));
24236ea7df73SStefano Zampini 
2424978814f1SStefano Zampini   hB->inner_free      = PETSC_TRUE;
2425651b1cf9SStefano Zampini   hB->array_available = PETSC_TRUE;
2426978814f1SStefano Zampini 
242763c07aadSStefano Zampini   B->data = (void *)hB;
242863c07aadSStefano Zampini 
24299566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(B->ops, sizeof(struct _MatOps)));
243063c07aadSStefano Zampini   B->ops->mult                  = MatMult_HYPRE;
243163c07aadSStefano Zampini   B->ops->multtranspose         = MatMultTranspose_HYPRE;
2432414bd5c3SStefano Zampini   B->ops->multadd               = MatMultAdd_HYPRE;
2433414bd5c3SStefano Zampini   B->ops->multtransposeadd      = MatMultTransposeAdd_HYPRE;
243463c07aadSStefano Zampini   B->ops->setup                 = MatSetUp_HYPRE;
243563c07aadSStefano Zampini   B->ops->destroy               = MatDestroy_HYPRE;
243663c07aadSStefano Zampini   B->ops->assemblyend           = MatAssemblyEnd_HYPRE;
2437c69f721fSFande Kong   B->ops->assemblybegin         = MatAssemblyBegin_HYPRE;
2438d975228cSstefano_zampini   B->ops->setvalues             = MatSetValues_HYPRE;
243968ec7858SStefano Zampini   B->ops->missingdiagonal       = MatMissingDiagonal_HYPRE;
244068ec7858SStefano Zampini   B->ops->scale                 = MatScale_HYPRE;
244168ec7858SStefano Zampini   B->ops->zerorowscolumns       = MatZeroRowsColumns_HYPRE;
2442c69f721fSFande Kong   B->ops->zeroentries           = MatZeroEntries_HYPRE;
2443c69f721fSFande Kong   B->ops->zerorows              = MatZeroRows_HYPRE;
2444c69f721fSFande Kong   B->ops->getrow                = MatGetRow_HYPRE;
2445c69f721fSFande Kong   B->ops->restorerow            = MatRestoreRow_HYPRE;
2446c69f721fSFande Kong   B->ops->getvalues             = MatGetValues_HYPRE;
2447ddbeb582SStefano Zampini   B->ops->setoption             = MatSetOption_HYPRE;
244845b8d346SStefano Zampini   B->ops->duplicate             = MatDuplicate_HYPRE;
2449465edc17SStefano Zampini   B->ops->copy                  = MatCopy_HYPRE;
245045b8d346SStefano Zampini   B->ops->view                  = MatView_HYPRE;
24516305df00SStefano Zampini   B->ops->getdiagonal           = MatGetDiagonal_HYPRE;
2452363d496dSStefano Zampini   B->ops->axpy                  = MatAXPY_HYPRE;
24534222ddf1SHong Zhang   B->ops->productsetfromoptions = MatProductSetFromOptions_HYPRE;
24546ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
24556ea7df73SStefano Zampini   B->ops->bindtocpu = MatBindToCPU_HYPRE;
2456a9e6c71bSAlex Lindsay   /* Get hypre's default memory location. Users can control this using the corresponding HYPRE_SetMemoryLocation API */
2457a9e6c71bSAlex Lindsay   PetscCallExternal(HYPRE_GetMemoryLocation, &memory_location);
2458a9e6c71bSAlex Lindsay   B->boundtocpu = (memory_location == HYPRE_MEMORY_HOST) ? PETSC_TRUE : PETSC_FALSE;
24596ea7df73SStefano Zampini #endif
246045b8d346SStefano Zampini 
246145b8d346SStefano Zampini   /* build cache for off array entries formed */
24629566063dSJacob Faibussowitsch   PetscCall(MatStashCreate_Private(PetscObjectComm((PetscObject)B), 1, &B->stash));
246363c07aadSStefano Zampini 
24649566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)B), &hB->comm));
24659566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRE));
24669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_aij_C", MatConvert_HYPRE_AIJ));
24679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_is_C", MatConvert_HYPRE_IS));
24689566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_hypre_C", MatProductSetFromOptions_HYPRE));
24699566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaij_hypre_C", MatProductSetFromOptions_HYPRE));
24709566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPRESetPreallocation_C", MatHYPRESetPreallocation_HYPRE));
24719566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPREGetParCSR_C", MatHYPREGetParCSR_HYPRE));
24725fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_HYPRE));
24735fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetValuesCOO_C", MatSetValuesCOO_HYPRE));
24746ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
24756ea7df73SStefano Zampini   #if defined(HYPRE_USING_HIP)
247606977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijhipsparse_hypre_C", MatProductSetFromOptions_HYPRE));
247706977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaijhipsparse_hypre_C", MatProductSetFromOptions_HYPRE));
24789566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP));
24799566063dSJacob Faibussowitsch   PetscCall(MatSetVecType(B, VECHIP));
24806ea7df73SStefano Zampini   #endif
24816ea7df73SStefano Zampini   #if defined(HYPRE_USING_CUDA)
248206977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijcusparse_hypre_C", MatProductSetFromOptions_HYPRE));
248306977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaijcusparse_hypre_C", MatProductSetFromOptions_HYPRE));
24849566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
24859566063dSJacob Faibussowitsch   PetscCall(MatSetVecType(B, VECCUDA));
24866ea7df73SStefano Zampini   #endif
24876ea7df73SStefano Zampini #endif
24883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
248963c07aadSStefano Zampini }
2490