xref: /petsc/src/mat/impls/hypre/mhypre.c (revision 06977982913c3aebee464d9f4c9f5c3699a59e57)
163c07aadSStefano Zampini 
263c07aadSStefano Zampini /*
363c07aadSStefano Zampini     Creates hypre ijmatrix from PETSc matrix
463c07aadSStefano Zampini */
5225daaf8SStefano Zampini 
6c6698e78SStefano Zampini #include <petscpkg_version.h>
739accc25SStefano Zampini #include <petsc/private/petschypre.h>
8dd9c0a25Sstefano_zampini #include <petscmathypre.h>
963c07aadSStefano Zampini #include <petsc/private/matimpl.h>
10a4af0ceeSJacob Faibussowitsch #include <petsc/private/deviceimpl.h>
1163c07aadSStefano Zampini #include <../src/mat/impls/hypre/mhypre.h>
1263c07aadSStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
1358968eb6SStefano Zampini #include <../src/vec/vec/impls/hypre/vhyp.h>
1458968eb6SStefano Zampini #include <HYPRE.h>
15c1a070e6SStefano Zampini #include <HYPRE_utilities.h>
16cd8bc7baSStefano Zampini #include <_hypre_parcsr_ls.h>
1768ec7858SStefano Zampini #include <_hypre_sstruct_ls.h>
1863c07aadSStefano Zampini 
190e6427aaSSatish Balay #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0)
200e6427aaSSatish Balay   #define hypre_ParCSRMatrixClone(A, B) hypre_ParCSRMatrixCompleteClone(A)
210e6427aaSSatish Balay #endif
220e6427aaSSatish Balay 
2363c07aadSStefano Zampini static PetscErrorCode MatHYPRE_CreateFromMat(Mat, Mat_HYPRE *);
2463c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat, Mat, HYPRE_IJMatrix);
25b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_MPIAIJ(Mat, HYPRE_IJMatrix);
26b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_SeqAIJ(Mat, HYPRE_IJMatrix);
2739accc25SStefano Zampini static PetscErrorCode MatHYPRE_MultKernel_Private(Mat, HYPRE_Complex, Vec, HYPRE_Complex, Vec, PetscBool);
286ea7df73SStefano Zampini static PetscErrorCode MatSetValues_HYPRE(Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[], const PetscScalar[], InsertMode ins);
2963c07aadSStefano Zampini 
30d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat A_d, Mat A_o, HYPRE_IJMatrix ij)
31d71ae5a4SJacob Faibussowitsch {
3263c07aadSStefano Zampini   PetscInt        i, n_d, n_o;
3363c07aadSStefano Zampini   const PetscInt *ia_d, *ia_o;
3463c07aadSStefano Zampini   PetscBool       done_d = PETSC_FALSE, done_o = PETSC_FALSE;
352cf14000SStefano Zampini   HYPRE_Int      *nnz_d = NULL, *nnz_o = NULL;
3663c07aadSStefano Zampini 
3763c07aadSStefano Zampini   PetscFunctionBegin;
3863c07aadSStefano Zampini   if (A_d) { /* determine number of nonzero entries in local diagonal part */
399566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(A_d, 0, PETSC_FALSE, PETSC_FALSE, &n_d, &ia_d, NULL, &done_d));
4063c07aadSStefano Zampini     if (done_d) {
419566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(n_d, &nnz_d));
42ad540459SPierre Jolivet       for (i = 0; i < n_d; i++) nnz_d[i] = ia_d[i + 1] - ia_d[i];
4363c07aadSStefano Zampini     }
449566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowIJ(A_d, 0, PETSC_FALSE, PETSC_FALSE, NULL, &ia_d, NULL, &done_d));
4563c07aadSStefano Zampini   }
4663c07aadSStefano Zampini   if (A_o) { /* determine number of nonzero entries in local off-diagonal part */
479566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(A_o, 0, PETSC_FALSE, PETSC_FALSE, &n_o, &ia_o, NULL, &done_o));
4863c07aadSStefano Zampini     if (done_o) {
499566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(n_o, &nnz_o));
50ad540459SPierre Jolivet       for (i = 0; i < n_o; i++) nnz_o[i] = ia_o[i + 1] - ia_o[i];
5163c07aadSStefano Zampini     }
529566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowIJ(A_o, 0, PETSC_FALSE, PETSC_FALSE, &n_o, &ia_o, NULL, &done_o));
5363c07aadSStefano Zampini   }
5463c07aadSStefano Zampini   if (done_d) {    /* set number of nonzeros in HYPRE IJ matrix */
5563c07aadSStefano Zampini     if (!done_o) { /* only diagonal part */
569566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(n_d, &nnz_o));
5763c07aadSStefano Zampini     }
58c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0)
59c6698e78SStefano Zampini     { /* If we don't do this, the columns of the matrix will be all zeros! */
60c6698e78SStefano Zampini       hypre_AuxParCSRMatrix *aux_matrix;
61c6698e78SStefano Zampini       aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij);
62c6698e78SStefano Zampini       hypre_AuxParCSRMatrixDestroy(aux_matrix);
63c6698e78SStefano Zampini       hypre_IJMatrixTranslator(ij) = NULL;
64792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, ij, nnz_d, nnz_o);
6522235d61SPierre Jolivet       /* it seems they partially fixed it in 2.19.0 */
6622235d61SPierre Jolivet   #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
67c6698e78SStefano Zampini       aux_matrix                               = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij);
68c6698e78SStefano Zampini       hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1;
6922235d61SPierre Jolivet   #endif
70c6698e78SStefano Zampini     }
71c6698e78SStefano Zampini #else
72792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, ij, nnz_d, nnz_o);
73c6698e78SStefano Zampini #endif
749566063dSJacob Faibussowitsch     PetscCall(PetscFree(nnz_d));
759566063dSJacob Faibussowitsch     PetscCall(PetscFree(nnz_o));
7663c07aadSStefano Zampini   }
773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7863c07aadSStefano Zampini }
7963c07aadSStefano Zampini 
80d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_CreateFromMat(Mat A, Mat_HYPRE *hA)
81d71ae5a4SJacob Faibussowitsch {
8263c07aadSStefano Zampini   PetscInt rstart, rend, cstart, cend;
8363c07aadSStefano Zampini 
8463c07aadSStefano Zampini   PetscFunctionBegin;
859566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
869566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
8763c07aadSStefano Zampini   rstart = A->rmap->rstart;
8863c07aadSStefano Zampini   rend   = A->rmap->rend;
8963c07aadSStefano Zampini   cstart = A->cmap->rstart;
9063c07aadSStefano Zampini   cend   = A->cmap->rend;
91ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
92651b1cf9SStefano Zampini   if (hA->ij) {
93651b1cf9SStefano Zampini     if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL;
94651b1cf9SStefano Zampini     PetscCallExternal(HYPRE_IJMatrixDestroy, hA->ij);
95651b1cf9SStefano Zampini   }
96792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rstart, rend - 1, cstart, cend - 1, &hA->ij);
97792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR);
9863c07aadSStefano Zampini   {
9963c07aadSStefano Zampini     PetscBool       same;
10063c07aadSStefano Zampini     Mat             A_d, A_o;
10163c07aadSStefano Zampini     const PetscInt *colmap;
1029566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &same));
10363c07aadSStefano Zampini     if (same) {
1049566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJGetSeqAIJ(A, &A_d, &A_o, &colmap));
1059566063dSJacob Faibussowitsch       PetscCall(MatHYPRE_IJMatrixPreallocate(A_d, A_o, hA->ij));
1063ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
10763c07aadSStefano Zampini     }
1089566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIBAIJ, &same));
10963c07aadSStefano Zampini     if (same) {
1109566063dSJacob Faibussowitsch       PetscCall(MatMPIBAIJGetSeqBAIJ(A, &A_d, &A_o, &colmap));
1119566063dSJacob Faibussowitsch       PetscCall(MatHYPRE_IJMatrixPreallocate(A_d, A_o, hA->ij));
1123ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
11363c07aadSStefano Zampini     }
1149566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &same));
11563c07aadSStefano Zampini     if (same) {
1169566063dSJacob Faibussowitsch       PetscCall(MatHYPRE_IJMatrixPreallocate(A, NULL, hA->ij));
1173ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
11863c07aadSStefano Zampini     }
1199566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQBAIJ, &same));
12063c07aadSStefano Zampini     if (same) {
1219566063dSJacob Faibussowitsch       PetscCall(MatHYPRE_IJMatrixPreallocate(A, NULL, hA->ij));
1223ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
12363c07aadSStefano Zampini     }
12463c07aadSStefano Zampini   }
1253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12663c07aadSStefano Zampini }
12763c07aadSStefano Zampini 
128b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ(Mat A, HYPRE_IJMatrix ij)
129d71ae5a4SJacob Faibussowitsch {
13063c07aadSStefano Zampini   PetscBool flg;
13163c07aadSStefano Zampini 
13263c07aadSStefano Zampini   PetscFunctionBegin;
1336ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
134792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize, ij);
1356ea7df73SStefano Zampini #else
136792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize_v2, ij, HYPRE_MEMORY_HOST);
1376ea7df73SStefano Zampini #endif
1389566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &flg));
139b73e3080SStefano Zampini   if (flg) {
140b73e3080SStefano Zampini     PetscCall(MatHYPRE_IJMatrixCopyIJ_MPIAIJ(A, ij));
1413ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
14263c07aadSStefano Zampini   }
1439566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &flg));
14463c07aadSStefano Zampini   if (flg) {
145b73e3080SStefano Zampini     PetscCall(MatHYPRE_IJMatrixCopyIJ_SeqAIJ(A, ij));
1463ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
14763c07aadSStefano Zampini   }
148b73e3080SStefano Zampini   PetscCheck(PETSC_FALSE, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "No support for matrix type %s", ((PetscObject)A)->type_name);
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 {
2092cf14000SStefano Zampini     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 {
2222cf14000SStefano Zampini     for (i = 0; i < pA->A->rmap->n + 1; i++) hoffd->i[i] = (HYPRE_Int)(poffd->i[i]);
2232cf14000SStefano Zampini   }
2242cf14000SStefano Zampini 
225*06977982Sstefanozampini   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 {
2402df22349SStefano Zampini   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;
254*06977982Sstefanozampini   MatType                lmattype   = NULL;
255*06977982Sstefanozampini   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);
262*06977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
263*06977982Sstefanozampini   if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(mhA->ij)) {
264*06977982Sstefanozampini     /* Support by copying back on the host and copy to GPU
265*06977982Sstefanozampini        Kind of inefficient, but this is the best we can do now */
266*06977982Sstefanozampini   #if defined(HYPRE_USING_HIP)
267*06977982Sstefanozampini     lmattype = MATSEQAIJHIPSPARSE;
268*06977982Sstefanozampini   #elif defined(HYPRE_USING_CUDA)
269*06977982Sstefanozampini     lmattype = MATSEQAIJCUSPARSE;
270*06977982Sstefanozampini   #endif
271*06977982Sstefanozampini     hA         = hypre_ParCSRMatrixClone_v2(hA, 1, HYPRE_MEMORY_HOST);
272*06977982Sstefanozampini     freeparcsr = PETSC_TRUE;
273*06977982Sstefanozampini   }
274*06977982Sstefanozampini #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);
325*06977982Sstefanozampini     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 */
352a033916dSStefano Zampini     a          = (Mat_SeqAIJ *)(lA->data);
353a033916dSStefano Zampini     a->free_a  = PETSC_TRUE;
354a033916dSStefano Zampini     a->free_ij = PETSC_TRUE;
355*06977982Sstefanozampini     if (lmattype) PetscCall(MatConvert(lA, lmattype, MAT_INPLACE_MATRIX, &lA));
356*06977982Sstefanozampini     PetscCall(MatISSetLocalMat(*B, lA));
3579566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&lA));
358*06977982Sstefanozampini   } else {
359*06977982Sstefanozampini     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));
364*06977982Sstefanozampini   if (freeparcsr) PetscCallExternal(hypre_ParCSRMatrixDestroy, hA);
3653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3662df22349SStefano Zampini }
3672df22349SStefano Zampini 
368*06977982Sstefanozampini static PetscErrorCode MatHYPRE_DestroyCOOMat(Mat mat)
369d71ae5a4SJacob Faibussowitsch {
370*06977982Sstefanozampini   Mat_HYPRE *hA = (Mat_HYPRE *)mat->data;
37163c07aadSStefano Zampini 
37263c07aadSStefano Zampini   PetscFunctionBegin;
373*06977982Sstefanozampini   if (hA->cooMat) { /* If cooMat is present we need to destroy the column indices */
374*06977982Sstefanozampini     PetscCall(MatDestroy(&hA->cooMat));
375*06977982Sstefanozampini     if (hA->cooMatAttached) {
376*06977982Sstefanozampini       hypre_CSRMatrix     *csr;
377*06977982Sstefanozampini       hypre_ParCSRMatrix  *parcsr;
378*06977982Sstefanozampini       HYPRE_MemoryLocation mem;
379*06977982Sstefanozampini 
380*06977982Sstefanozampini       PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
381*06977982Sstefanozampini       csr = hypre_ParCSRMatrixDiag(parcsr);
382*06977982Sstefanozampini       if (csr) {
383*06977982Sstefanozampini         mem = hypre_CSRMatrixMemoryLocation(csr);
384*06977982Sstefanozampini         PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixJ(csr), mem));
385*06977982Sstefanozampini         PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixBigJ(csr), mem));
386b73e3080SStefano Zampini       }
387*06977982Sstefanozampini       csr = hypre_ParCSRMatrixOffd(parcsr);
388*06977982Sstefanozampini       if (csr) {
389*06977982Sstefanozampini         mem = hypre_CSRMatrixMemoryLocation(csr);
390*06977982Sstefanozampini         PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixJ(csr), mem));
391*06977982Sstefanozampini         PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixBigJ(csr), mem));
392b73e3080SStefano Zampini       }
393b73e3080SStefano Zampini     }
394*06977982Sstefanozampini   }
395*06977982Sstefanozampini   hA->cooMatAttached = PETSC_FALSE;
396b73e3080SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
397b73e3080SStefano Zampini }
398b73e3080SStefano Zampini 
399*06977982Sstefanozampini static PetscErrorCode MatHYPRE_CreateCOOMat(Mat mat)
400b73e3080SStefano Zampini {
401*06977982Sstefanozampini   MPI_Comm    comm;
402*06977982Sstefanozampini   PetscMPIInt size;
403*06977982Sstefanozampini   PetscLayout rmap, cmap;
404*06977982Sstefanozampini   Mat_HYPRE  *hmat    = (Mat_HYPRE *)mat->data;
405*06977982Sstefanozampini   MatType     matType = MATAIJ; /* default type of cooMat */
406b73e3080SStefano Zampini 
407b73e3080SStefano Zampini   PetscFunctionBegin;
408*06977982Sstefanozampini   /* Build an agent matrix cooMat with AIJ format
409*06977982Sstefanozampini      It has the same sparsity pattern as mat, and also shares the data array with mat. We use cooMat to do the COO work.
410*06977982Sstefanozampini    */
411*06977982Sstefanozampini   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
412*06977982Sstefanozampini   PetscCallMPI(MPI_Comm_size(comm, &size));
413*06977982Sstefanozampini   PetscCall(PetscLayoutSetUp(mat->rmap));
414*06977982Sstefanozampini   PetscCall(PetscLayoutSetUp(mat->cmap));
415*06977982Sstefanozampini   PetscCall(MatGetLayouts(mat, &rmap, &cmap));
416b73e3080SStefano Zampini 
417*06977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
418*06977982Sstefanozampini   if (!mat->boundtocpu) { /* mat will be on device, so will cooMat */
419*06977982Sstefanozampini   #if defined(HYPRE_USING_HIP)
420*06977982Sstefanozampini     matType = MATAIJHIPSPARSE;
421*06977982Sstefanozampini   #elif defined(HYPRE_USING_CUDA)
422*06977982Sstefanozampini     matType  = MATAIJCUSPARSE;
423*06977982Sstefanozampini   #else
424*06977982Sstefanozampini     SETERRQ(comm, PETSC_ERR_SUP, "Do not know the HYPRE device");
425*06977982Sstefanozampini   #endif
426b73e3080SStefano Zampini   }
427*06977982Sstefanozampini #endif
428*06977982Sstefanozampini 
429*06977982Sstefanozampini   /* Do COO preallocation through cooMat */
430*06977982Sstefanozampini   PetscCall(MatHYPRE_DestroyCOOMat(mat));
431*06977982Sstefanozampini   PetscCall(MatCreate(comm, &hmat->cooMat));
432*06977982Sstefanozampini   PetscCall(MatSetType(hmat->cooMat, matType));
433*06977982Sstefanozampini   PetscCall(MatSetLayouts(hmat->cooMat, rmap, cmap));
434*06977982Sstefanozampini 
435*06977982Sstefanozampini   /* allocate local matrices if needed */
436*06977982Sstefanozampini   PetscCall(MatMPIAIJSetPreallocation(hmat->cooMat, 0, NULL, 0, NULL));
437*06977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
438*06977982Sstefanozampini }
439*06977982Sstefanozampini 
440*06977982Sstefanozampini /* Attach cooMat data array to hypre matrix.
441*06977982Sstefanozampini    When AIJCUPMSPARSE will support raw device pointers and not THRUSTARRAY
442*06977982Sstefanozampini    we should swap the arrays: i.e., attach hypre matrix array to cooMat
443*06977982Sstefanozampini    This is because hypre should be in charge of handling the memory,
444*06977982Sstefanozampini    cooMat is only a way to reuse PETSc COO code.
445*06977982Sstefanozampini    attaching the memory will then be done at MatSetValuesCOO time and it will dynamically
446*06977982Sstefanozampini    support hypre matrix migrating to host.
447*06977982Sstefanozampini */
448*06977982Sstefanozampini static PetscErrorCode MatHYPRE_AttachCOOMat(Mat mat)
449*06977982Sstefanozampini {
450*06977982Sstefanozampini   Mat_HYPRE           *hmat = (Mat_HYPRE *)mat->data;
451*06977982Sstefanozampini   hypre_CSRMatrix     *diag, *offd;
452*06977982Sstefanozampini   hypre_ParCSRMatrix  *parCSR;
453*06977982Sstefanozampini   HYPRE_MemoryLocation hmem = HYPRE_MEMORY_HOST;
454*06977982Sstefanozampini   PetscMemType         pmem;
455*06977982Sstefanozampini   Mat                  A, B;
456*06977982Sstefanozampini   PetscScalar         *a;
457*06977982Sstefanozampini   PetscMPIInt          size;
458*06977982Sstefanozampini   MPI_Comm             comm;
459*06977982Sstefanozampini 
460*06977982Sstefanozampini   PetscFunctionBegin;
461*06977982Sstefanozampini   PetscCheck(hmat->cooMat, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet");
462*06977982Sstefanozampini   if (hmat->cooMatAttached) PetscFunctionReturn(PETSC_SUCCESS);
463*06977982Sstefanozampini   PetscCheck(hmat->cooMat->preallocated, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix is not preallocated");
464*06977982Sstefanozampini   PetscCall(PetscObjectSetName((PetscObject)hmat->cooMat, "_internal_COO_mat_for_hypre"));
465*06977982Sstefanozampini   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
466*06977982Sstefanozampini   PetscCallMPI(MPI_Comm_size(comm, &size));
467*06977982Sstefanozampini 
468*06977982Sstefanozampini   /* Alias cooMat's data array to IJMatrix's */
469*06977982Sstefanozampini   PetscCallExternal(HYPRE_IJMatrixGetObject, hmat->ij, (void **)&parCSR);
470*06977982Sstefanozampini   diag = hypre_ParCSRMatrixDiag(parCSR);
471*06977982Sstefanozampini   offd = hypre_ParCSRMatrixOffd(parCSR);
472*06977982Sstefanozampini 
473*06977982Sstefanozampini   A = (size == 1) ? hmat->cooMat : ((Mat_MPIAIJ *)hmat->cooMat->data)->A;
474*06977982Sstefanozampini   B = (size == 1) ? NULL : ((Mat_MPIAIJ *)hmat->cooMat->data)->B;
475*06977982Sstefanozampini 
476*06977982Sstefanozampini   PetscCall(PetscObjectSetName((PetscObject)A, "_internal_COO_mat_for_hypre"));
477*06977982Sstefanozampini   hmem = hypre_CSRMatrixMemoryLocation(diag);
478*06977982Sstefanozampini   PetscCall(MatSeqAIJGetCSRAndMemType(A, NULL, NULL, &a, &pmem));
479*06977982Sstefanozampini   PetscAssert((PetscMemTypeHost(pmem) && hmem == HYPRE_MEMORY_HOST) || (PetscMemTypeDevice(pmem) && hmem == HYPRE_MEMORY_DEVICE), comm, PETSC_ERR_PLIB, "PETSc and hypre's memory types mismatch");
480*06977982Sstefanozampini   PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(diag), hmem));
481*06977982Sstefanozampini   hypre_CSRMatrixData(diag)     = (HYPRE_Complex *)a;
482*06977982Sstefanozampini   hypre_CSRMatrixOwnsData(diag) = 0; /* Take ownership of (j,a) away from hypre. As a result, we need to free them on our own */
483*06977982Sstefanozampini 
484*06977982Sstefanozampini   if (B) {
485*06977982Sstefanozampini     hmem = hypre_CSRMatrixMemoryLocation(offd);
486*06977982Sstefanozampini     PetscCall(MatSeqAIJGetCSRAndMemType(B, NULL, NULL, &a, &pmem));
487*06977982Sstefanozampini     PetscAssert((PetscMemTypeHost(pmem) && hmem == HYPRE_MEMORY_HOST) || (PetscMemTypeDevice(pmem) && hmem == HYPRE_MEMORY_DEVICE), comm, PETSC_ERR_PLIB, "PETSc and hypre's memory types mismatch");
488*06977982Sstefanozampini     PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(offd), hmem));
489*06977982Sstefanozampini     hypre_CSRMatrixData(offd)     = (HYPRE_Complex *)a;
490*06977982Sstefanozampini     hypre_CSRMatrixOwnsData(offd) = 0;
491*06977982Sstefanozampini   }
492*06977982Sstefanozampini   hmat->cooMatAttached = PETSC_TRUE;
493*06977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
494*06977982Sstefanozampini }
495*06977982Sstefanozampini 
496*06977982Sstefanozampini static PetscErrorCode CSRtoCOO_Private(PetscInt n, const PetscInt ii[], const PetscInt jj[], PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j)
497*06977982Sstefanozampini {
498*06977982Sstefanozampini   PetscInt *cooi, *cooj;
499*06977982Sstefanozampini 
500*06977982Sstefanozampini   PetscFunctionBegin;
501*06977982Sstefanozampini   *ncoo = ii[n];
502*06977982Sstefanozampini   PetscCall(PetscMalloc2(*ncoo, &cooi, *ncoo, &cooj));
503*06977982Sstefanozampini   for (PetscInt i = 0; i < n; i++) {
504*06977982Sstefanozampini     for (PetscInt j = ii[i]; j < ii[i + 1]; j++) cooi[j] = i;
505*06977982Sstefanozampini   }
506*06977982Sstefanozampini   PetscCall(PetscArraycpy(cooj, jj, *ncoo));
507*06977982Sstefanozampini   *coo_i = cooi;
508*06977982Sstefanozampini   *coo_j = cooj;
509*06977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
510*06977982Sstefanozampini }
511*06977982Sstefanozampini 
512*06977982Sstefanozampini static PetscErrorCode CSRtoCOO_HYPRE_Int_Private(PetscInt n, const HYPRE_Int ii[], const HYPRE_Int jj[], PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j)
513*06977982Sstefanozampini {
514*06977982Sstefanozampini   PetscInt *cooi, *cooj;
515*06977982Sstefanozampini 
516*06977982Sstefanozampini   PetscFunctionBegin;
517*06977982Sstefanozampini   *ncoo = ii[n];
518*06977982Sstefanozampini   PetscCall(PetscMalloc2(*ncoo, &cooi, *ncoo, &cooj));
519*06977982Sstefanozampini   for (PetscInt i = 0; i < n; i++) {
520*06977982Sstefanozampini     for (HYPRE_Int j = ii[i]; j < ii[i + 1]; j++) cooi[j] = i;
521*06977982Sstefanozampini   }
522*06977982Sstefanozampini   for (PetscCount i = 0; i < *ncoo; i++) cooj[i] = jj[i];
523*06977982Sstefanozampini   *coo_i = cooi;
524*06977982Sstefanozampini   *coo_j = cooj;
525*06977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
526*06977982Sstefanozampini }
527*06977982Sstefanozampini 
528*06977982Sstefanozampini static PetscErrorCode MatSeqAIJGetCOO_Private(Mat A, PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j)
529*06977982Sstefanozampini {
530*06977982Sstefanozampini   PetscInt        n;
531*06977982Sstefanozampini   const PetscInt *ii, *jj;
532*06977982Sstefanozampini   PetscBool       done;
533*06977982Sstefanozampini 
534*06977982Sstefanozampini   PetscFunctionBegin;
535*06977982Sstefanozampini   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &done));
536*06977982Sstefanozampini   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Failure for MatGetRowIJ");
537*06977982Sstefanozampini   PetscCall(CSRtoCOO_Private(n, ii, jj, ncoo, coo_i, coo_j));
538*06977982Sstefanozampini   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ii, &jj, &done));
539*06977982Sstefanozampini   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Failure for MatRestoreRowIJ");
540*06977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
541*06977982Sstefanozampini }
542*06977982Sstefanozampini 
543*06977982Sstefanozampini static PetscErrorCode hypreCSRMatrixGetCOO_Private(hypre_CSRMatrix *A, PetscCount *ncoo, PetscInt **coo_i, PetscInt **coo_j)
544*06977982Sstefanozampini {
545*06977982Sstefanozampini   PetscInt             n = hypre_CSRMatrixNumRows(A);
546*06977982Sstefanozampini   HYPRE_Int           *ii, *jj;
547*06977982Sstefanozampini   HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST;
548*06977982Sstefanozampini 
549*06977982Sstefanozampini   PetscFunctionBegin;
550*06977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
551*06977982Sstefanozampini   mem = hypre_CSRMatrixMemoryLocation(A);
552*06977982Sstefanozampini   if (mem != HYPRE_MEMORY_HOST) {
553*06977982Sstefanozampini     PetscCount nnz = hypre_CSRMatrixNumNonzeros(A);
554*06977982Sstefanozampini     PetscCall(PetscMalloc2(n + 1, &ii, nnz, &jj));
555*06977982Sstefanozampini     hypre_TMemcpy(ii, hypre_CSRMatrixI(A), HYPRE_Int, n + 1, HYPRE_MEMORY_HOST, mem);
556*06977982Sstefanozampini     hypre_TMemcpy(jj, hypre_CSRMatrixJ(A), HYPRE_Int, nnz, HYPRE_MEMORY_HOST, mem);
557*06977982Sstefanozampini   } else {
558*06977982Sstefanozampini #else
559*06977982Sstefanozampini   {
560*06977982Sstefanozampini #endif
561*06977982Sstefanozampini     ii = hypre_CSRMatrixI(A);
562*06977982Sstefanozampini     jj = hypre_CSRMatrixJ(A);
563*06977982Sstefanozampini   }
564*06977982Sstefanozampini   PetscCall(CSRtoCOO_HYPRE_Int_Private(n, ii, jj, ncoo, coo_i, coo_j));
565*06977982Sstefanozampini   if (mem != HYPRE_MEMORY_HOST) PetscCall(PetscFree2(ii, jj));
566*06977982Sstefanozampini   PetscFunctionReturn(PETSC_SUCCESS);
567*06977982Sstefanozampini }
568*06977982Sstefanozampini 
569*06977982Sstefanozampini static PetscErrorCode MatSetValuesCOOFromCSRMatrix_Private(Mat A, hypre_CSRMatrix *H)
570*06977982Sstefanozampini {
571*06977982Sstefanozampini   PetscBool            iscpu = PETSC_TRUE;
572*06977982Sstefanozampini   PetscScalar         *a;
573*06977982Sstefanozampini   HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST;
574*06977982Sstefanozampini 
575*06977982Sstefanozampini   PetscFunctionBegin;
576*06977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
577*06977982Sstefanozampini   mem = hypre_CSRMatrixMemoryLocation(H);
578*06977982Sstefanozampini   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATSEQAIJ, &iscpu));
579*06977982Sstefanozampini #endif
580*06977982Sstefanozampini   if (iscpu && mem != HYPRE_MEMORY_HOST) {
581*06977982Sstefanozampini     PetscCount nnz = hypre_CSRMatrixNumNonzeros(H);
582*06977982Sstefanozampini     PetscCall(PetscMalloc1(nnz, &a));
583*06977982Sstefanozampini     hypre_TMemcpy(a, hypre_CSRMatrixData(H), PetscScalar, nnz, HYPRE_MEMORY_HOST, mem);
584*06977982Sstefanozampini   } else {
585*06977982Sstefanozampini     a = (PetscScalar *)hypre_CSRMatrixData(H);
586*06977982Sstefanozampini   }
587*06977982Sstefanozampini   PetscCall(MatSetValuesCOO(A, a, INSERT_VALUES));
588*06977982Sstefanozampini   if (iscpu && mem != HYPRE_MEMORY_HOST) PetscCall(PetscFree(a));
589b73e3080SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
590b73e3080SStefano Zampini }
591b73e3080SStefano Zampini 
592b73e3080SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType type, MatReuse reuse, Mat *B)
593b73e3080SStefano Zampini {
594b73e3080SStefano Zampini   MPI_Comm   comm = PetscObjectComm((PetscObject)A);
595*06977982Sstefanozampini   Mat        M = NULL, dH = NULL, oH = NULL, dA = NULL, oA = NULL;
596b73e3080SStefano Zampini   PetscBool  ismpiaij, issbaij, isbaij;
597b73e3080SStefano Zampini   Mat_HYPRE *hA;
598b73e3080SStefano Zampini 
599b73e3080SStefano Zampini   PetscFunctionBegin;
600b73e3080SStefano Zampini   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &issbaij, MATSEQSBAIJ, MATMPIBAIJ, ""));
601b73e3080SStefano Zampini   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &isbaij, MATSEQBAIJ, MATMPIBAIJ, ""));
602b73e3080SStefano Zampini   if (isbaij || issbaij) { /* handle BAIJ and SBAIJ */
603b73e3080SStefano Zampini     PetscBool ismpi;
604b73e3080SStefano Zampini     MatType   newtype;
605b73e3080SStefano Zampini 
606b73e3080SStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &ismpi, MATMPISBAIJ, MATMPIBAIJ, ""));
607b73e3080SStefano Zampini     newtype = ismpi ? MATMPIAIJ : MATSEQAIJ;
60863c07aadSStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
609b73e3080SStefano Zampini       PetscCall(MatConvert(*B, newtype, MAT_INPLACE_MATRIX, B));
610b73e3080SStefano Zampini       PetscCall(MatConvert(A, newtype, MAT_REUSE_MATRIX, B));
611b73e3080SStefano Zampini       PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B));
612b73e3080SStefano Zampini     } else if (reuse == MAT_INITIAL_MATRIX) {
613b73e3080SStefano Zampini       PetscCall(MatConvert(A, newtype, MAT_INITIAL_MATRIX, B));
614b73e3080SStefano Zampini       PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B));
61563c07aadSStefano Zampini     } else {
616b73e3080SStefano Zampini       PetscCall(MatConvert(A, newtype, MAT_INPLACE_MATRIX, &A));
617b73e3080SStefano Zampini       PetscCall(MatConvert(A, MATHYPRE, MAT_INPLACE_MATRIX, &A));
618b73e3080SStefano Zampini     }
619b73e3080SStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
620b73e3080SStefano Zampini   }
621*06977982Sstefanozampini 
622*06977982Sstefanozampini   dA = A;
623b73e3080SStefano Zampini   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
624b73e3080SStefano Zampini   if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(A, &dA, &oA, NULL));
625*06977982Sstefanozampini 
626b73e3080SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
627*06977982Sstefanozampini     PetscCount coo_n;
628*06977982Sstefanozampini     PetscInt  *coo_i, *coo_j;
629*06977982Sstefanozampini 
6309566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm, &M));
6319566063dSJacob Faibussowitsch     PetscCall(MatSetType(M, MATHYPRE));
6329566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(M, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
633b73e3080SStefano Zampini     PetscCall(MatSetOption(M, MAT_SORTED_FULL, PETSC_TRUE));
634b73e3080SStefano Zampini     PetscCall(MatSetOption(M, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE));
635b73e3080SStefano Zampini 
636b73e3080SStefano Zampini     hA = (Mat_HYPRE *)M->data;
637*06977982Sstefanozampini     PetscCall(MatHYPRE_CreateFromMat(A, hA));
638*06977982Sstefanozampini     PetscCall(MatHYPRE_IJMatrixCopyIJ(A, hA->ij));
639*06977982Sstefanozampini 
640*06977982Sstefanozampini     PetscCall(MatHYPRE_CreateCOOMat(M));
641*06977982Sstefanozampini 
642*06977982Sstefanozampini     dH = hA->cooMat;
643*06977982Sstefanozampini     PetscCall(PetscObjectBaseTypeCompare((PetscObject)hA->cooMat, MATMPIAIJ, &ismpiaij));
644*06977982Sstefanozampini     if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(hA->cooMat, &dH, &oH, NULL));
645*06977982Sstefanozampini 
646*06977982Sstefanozampini     PetscCall(PetscObjectSetName((PetscObject)dH, "_internal_COO_mat_for_hypre"));
647*06977982Sstefanozampini     PetscCall(MatSeqAIJGetCOO_Private(dA, &coo_n, &coo_i, &coo_j));
648*06977982Sstefanozampini     PetscCall(MatSetPreallocationCOO(dH, coo_n, coo_i, coo_j));
649*06977982Sstefanozampini     PetscCall(PetscFree2(coo_i, coo_j));
650*06977982Sstefanozampini     if (oH) {
651*06977982Sstefanozampini       PetscCall(PetscLayoutDestroy(&oH->cmap));
652*06977982Sstefanozampini       PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)oH), oA->cmap->n, oA->cmap->n, 1, &oH->cmap));
653*06977982Sstefanozampini       PetscCall(MatSeqAIJGetCOO_Private(oA, &coo_n, &coo_i, &coo_j));
654*06977982Sstefanozampini       PetscCall(MatSetPreallocationCOO(oH, coo_n, coo_i, coo_j));
655*06977982Sstefanozampini       PetscCall(PetscFree2(coo_i, coo_j));
656*06977982Sstefanozampini     }
657*06977982Sstefanozampini     hA->cooMat->assembled = PETSC_TRUE;
658*06977982Sstefanozampini 
659b73e3080SStefano Zampini     M->preallocated = PETSC_TRUE;
660*06977982Sstefanozampini     PetscCall(MatAssemblyBegin(M, MAT_FINAL_ASSEMBLY));
661*06977982Sstefanozampini     PetscCall(MatAssemblyEnd(M, MAT_FINAL_ASSEMBLY));
662*06977982Sstefanozampini 
663*06977982Sstefanozampini     PetscCall(MatHYPRE_AttachCOOMat(M));
66484d4e069SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) *B = M;
665b73e3080SStefano Zampini   } else M = *B;
666b73e3080SStefano Zampini 
667b73e3080SStefano Zampini   hA = (Mat_HYPRE *)M->data;
668*06977982Sstefanozampini   PetscCheck(hA->cooMat, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet");
669*06977982Sstefanozampini 
670*06977982Sstefanozampini   dH = hA->cooMat;
671*06977982Sstefanozampini   PetscCall(PetscObjectBaseTypeCompare((PetscObject)hA->cooMat, MATMPIAIJ, &ismpiaij));
672*06977982Sstefanozampini   if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(hA->cooMat, &dH, &oH, NULL));
673*06977982Sstefanozampini 
674*06977982Sstefanozampini   PetscScalar *a;
675*06977982Sstefanozampini   PetscCall(MatSeqAIJGetCSRAndMemType(dA, NULL, NULL, &a, NULL));
676*06977982Sstefanozampini   PetscCall(MatSetValuesCOO(dH, a, INSERT_VALUES));
677*06977982Sstefanozampini   if (oH) {
678*06977982Sstefanozampini     PetscCall(MatSeqAIJGetCSRAndMemType(oA, NULL, NULL, &a, NULL));
679*06977982Sstefanozampini     PetscCall(MatSetValuesCOO(oH, a, INSERT_VALUES));
680*06977982Sstefanozampini   }
681b73e3080SStefano Zampini 
68248a46eb9SPierre Jolivet   if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &M));
6833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
68463c07aadSStefano Zampini }
68563c07aadSStefano Zampini 
686d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_HYPRE_AIJ(Mat A, MatType mtype, MatReuse reuse, Mat *B)
687d71ae5a4SJacob Faibussowitsch {
688*06977982Sstefanozampini   Mat                 M, dA = NULL, oA = NULL;
68963c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
690*06977982Sstefanozampini   hypre_CSRMatrix    *dH, *oH;
69163c07aadSStefano Zampini   MPI_Comm            comm;
692*06977982Sstefanozampini   PetscBool           ismpiaij, isseqaij;
69363c07aadSStefano Zampini 
69463c07aadSStefano Zampini   PetscFunctionBegin;
69563c07aadSStefano Zampini   comm = PetscObjectComm((PetscObject)A);
69663c07aadSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
6979566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATMPIAIJ, &ismpiaij));
6989566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATSEQAIJ, &isseqaij));
699*06977982Sstefanozampini     PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Only MATMPIAIJ or MATSEQAIJ base types are supported");
70063c07aadSStefano Zampini   }
701*06977982Sstefanozampini   PetscCall(MatHYPREGetParCSR(A, &parcsr));
7026ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
703*06977982Sstefanozampini   if (HYPRE_MEMORY_DEVICE == hypre_ParCSRMatrixMemoryLocation(parcsr)) {
704*06977982Sstefanozampini     PetscBool isaij;
705*06977982Sstefanozampini 
706*06977982Sstefanozampini     PetscCall(PetscStrcmp(mtype, MATAIJ, &isaij));
707*06977982Sstefanozampini     if (isaij) {
708*06977982Sstefanozampini       PetscMPIInt size;
709*06977982Sstefanozampini 
7109566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_size(comm, &size));
711*06977982Sstefanozampini   #if defined(HYPRE_USING_HIP)
712*06977982Sstefanozampini       mtype = size > 1 ? MATMPIAIJHIPSPARSE : MATSEQAIJHIPSPARSE;
713*06977982Sstefanozampini   #elif defined(HYPRE_USING_CUDA)
714*06977982Sstefanozampini       mtype = size > 1 ? MATMPIAIJCUSPARSE : MATSEQAIJCUSPARSE;
715*06977982Sstefanozampini   #else
716*06977982Sstefanozampini       mtype = size > 1 ? MATMPIAIJ : MATSEQAIJ;
717*06977982Sstefanozampini   #endif
71863c07aadSStefano Zampini     }
71963c07aadSStefano Zampini   }
720*06977982Sstefanozampini #endif
721*06977982Sstefanozampini   dH = hypre_ParCSRMatrixDiag(parcsr);
722*06977982Sstefanozampini   oH = hypre_ParCSRMatrixOffd(parcsr);
7239371c9d4SSatish Balay   if (reuse != MAT_REUSE_MATRIX) {
724*06977982Sstefanozampini     PetscCount coo_n;
725*06977982Sstefanozampini     PetscInt  *coo_i, *coo_j;
72663c07aadSStefano Zampini 
727*06977982Sstefanozampini     PetscCall(MatCreate(comm, &M));
728*06977982Sstefanozampini     PetscCall(MatSetType(M, mtype));
729*06977982Sstefanozampini     PetscCall(MatSetSizes(M, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
730*06977982Sstefanozampini     PetscCall(MatMPIAIJSetPreallocation(M, 0, NULL, 0, NULL));
73163c07aadSStefano Zampini 
732*06977982Sstefanozampini     dA = M;
733*06977982Sstefanozampini     PetscCall(PetscObjectBaseTypeCompare((PetscObject)M, MATMPIAIJ, &ismpiaij));
734*06977982Sstefanozampini     if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(M, &dA, &oA, NULL));
735a16187a7SStefano Zampini 
736*06977982Sstefanozampini     PetscCall(hypreCSRMatrixGetCOO_Private(dH, &coo_n, &coo_i, &coo_j));
737*06977982Sstefanozampini     PetscCall(MatSetPreallocationCOO(dA, coo_n, coo_i, coo_j));
738*06977982Sstefanozampini     PetscCall(PetscFree2(coo_i, coo_j));
739*06977982Sstefanozampini     if (ismpiaij) {
740*06977982Sstefanozampini       HYPRE_Int nc = hypre_CSRMatrixNumCols(oH);
741a16187a7SStefano Zampini 
742*06977982Sstefanozampini       PetscCall(PetscLayoutDestroy(&oA->cmap));
743*06977982Sstefanozampini       PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)oA), nc, nc, 1, &oA->cmap));
744*06977982Sstefanozampini       PetscCall(hypreCSRMatrixGetCOO_Private(oH, &coo_n, &coo_i, &coo_j));
745*06977982Sstefanozampini       PetscCall(MatSetPreallocationCOO(oA, coo_n, coo_i, coo_j));
746*06977982Sstefanozampini       PetscCall(PetscFree2(coo_i, coo_j));
747a16187a7SStefano Zampini 
748*06977982Sstefanozampini       /* garray */
749*06977982Sstefanozampini       Mat_MPIAIJ   *aij    = (Mat_MPIAIJ *)(M->data);
750*06977982Sstefanozampini       HYPRE_BigInt *harray = hypre_ParCSRMatrixColMapOffd(parcsr);
751*06977982Sstefanozampini       PetscInt     *garray;
752*06977982Sstefanozampini 
753*06977982Sstefanozampini       PetscCall(PetscFree(aij->garray));
754*06977982Sstefanozampini       PetscCall(PetscMalloc1(nc, &garray));
755*06977982Sstefanozampini       for (HYPRE_Int i = 0; i < nc; i++) garray[i] = (PetscInt)harray[i];
756*06977982Sstefanozampini       aij->garray = garray;
757*06977982Sstefanozampini       PetscCall(MatSetUpMultiply_MPIAIJ(M));
758a16187a7SStefano Zampini     }
759*06977982Sstefanozampini     if (reuse == MAT_INITIAL_MATRIX) *B = M;
760*06977982Sstefanozampini   } else M = *B;
761225daaf8SStefano Zampini 
762*06977982Sstefanozampini   dA = M;
763*06977982Sstefanozampini   PetscCall(PetscObjectBaseTypeCompare((PetscObject)M, MATMPIAIJ, &ismpiaij));
764*06977982Sstefanozampini   if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(M, &dA, &oA, NULL));
765*06977982Sstefanozampini   PetscCall(MatSetValuesCOOFromCSRMatrix_Private(dA, dH));
766*06977982Sstefanozampini   if (oA) PetscCall(MatSetValuesCOOFromCSRMatrix_Private(oA, oH));
767*06977982Sstefanozampini   M->assembled = PETSC_TRUE;
768*06977982Sstefanozampini   if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &M));
7693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
77063c07aadSStefano Zampini }
77163c07aadSStefano Zampini 
772d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJGetParCSR_Private(Mat A, hypre_ParCSRMatrix **hA)
773d71ae5a4SJacob Faibussowitsch {
774613e5ff0Sstefano_zampini   hypre_ParCSRMatrix *tA;
775c1a070e6SStefano Zampini   hypre_CSRMatrix    *hdiag, *hoffd;
776c1a070e6SStefano Zampini   Mat_SeqAIJ         *diag, *offd;
7772cf14000SStefano Zampini   PetscInt           *garray, i, noffd, dnnz, onnz, *row_starts, *col_starts;
778c1a070e6SStefano Zampini   MPI_Comm            comm = PetscObjectComm((PetscObject)A);
779613e5ff0Sstefano_zampini   PetscBool           ismpiaij, isseqaij;
7802cf14000SStefano Zampini   PetscBool           sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
7816ea7df73SStefano Zampini   HYPRE_Int          *hdi = NULL, *hdj = NULL, *hoi = NULL, *hoj = NULL;
7825c97c10fSStefano Zampini   PetscInt           *pdi = NULL, *pdj = NULL, *poi = NULL, *poj = NULL;
783*06977982Sstefanozampini   PetscBool           iscuda, iship;
784*06977982Sstefanozampini #if defined(PETSC_HAVE_DEVICE) && defined(PETSC_HAVE_HYPRE_DEVICE)
785*06977982Sstefanozampini   PetscBool boundtocpu = A->boundtocpu;
786*06977982Sstefanozampini #else
787*06977982Sstefanozampini   PetscBool boundtocpu = PETSC_TRUE;
7886ea7df73SStefano Zampini #endif
789c1a070e6SStefano Zampini 
790c1a070e6SStefano Zampini   PetscFunctionBegin;
7919566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
7929566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isseqaij));
79308401ef6SPierre Jolivet   PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Unsupported type %s", ((PetscObject)A)->type_name);
794*06977982Sstefanozampini   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iscuda, MATSEQAIJHIPSPARSE, MATMPIAIJCUSPARSE, ""));
795*06977982Sstefanozampini   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iship, MATSEQAIJCUSPARSE, MATMPIAIJHIPSPARSE, ""));
796ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
797c1a070e6SStefano Zampini   if (ismpiaij) {
798c1a070e6SStefano Zampini     Mat_MPIAIJ *a = (Mat_MPIAIJ *)(A->data);
799c1a070e6SStefano Zampini 
800c1a070e6SStefano Zampini     diag = (Mat_SeqAIJ *)a->A->data;
801c1a070e6SStefano Zampini     offd = (Mat_SeqAIJ *)a->B->data;
802*06977982Sstefanozampini     if (!boundtocpu && (iscuda || iship)) {
803*06977982Sstefanozampini #if defined(HYPRE_USING_CUDA) && defined(PETSC_HAVE_CUDA)
804*06977982Sstefanozampini       if (iscuda) {
8056ea7df73SStefano Zampini         sameint = PETSC_TRUE;
8069566063dSJacob Faibussowitsch         PetscCall(MatSeqAIJCUSPARSEGetIJ(a->A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
8079566063dSJacob Faibussowitsch         PetscCall(MatSeqAIJCUSPARSEGetIJ(a->B, PETSC_FALSE, (const HYPRE_Int **)&hoi, (const HYPRE_Int **)&hoj));
808*06977982Sstefanozampini       }
8096ea7df73SStefano Zampini #endif
810*06977982Sstefanozampini #if defined(HYPRE_USING_HIP) && defined(PETSC_HAVE_HIP)
811*06977982Sstefanozampini       if (iship) {
812*06977982Sstefanozampini         sameint = PETSC_TRUE;
813*06977982Sstefanozampini         PetscCall(MatSeqAIJHIPSPARSEGetIJ(a->A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
814*06977982Sstefanozampini         PetscCall(MatSeqAIJHIPSPARSEGetIJ(a->B, PETSC_FALSE, (const HYPRE_Int **)&hoi, (const HYPRE_Int **)&hoj));
815*06977982Sstefanozampini       }
816*06977982Sstefanozampini #endif
817*06977982Sstefanozampini     } else {
818*06977982Sstefanozampini       boundtocpu = PETSC_TRUE;
8196ea7df73SStefano Zampini       pdi        = diag->i;
8206ea7df73SStefano Zampini       pdj        = diag->j;
8216ea7df73SStefano Zampini       poi        = offd->i;
8226ea7df73SStefano Zampini       poj        = offd->j;
8236ea7df73SStefano Zampini       if (sameint) {
8246ea7df73SStefano Zampini         hdi = (HYPRE_Int *)pdi;
8256ea7df73SStefano Zampini         hdj = (HYPRE_Int *)pdj;
8266ea7df73SStefano Zampini         hoi = (HYPRE_Int *)poi;
8276ea7df73SStefano Zampini         hoj = (HYPRE_Int *)poj;
8286ea7df73SStefano Zampini       }
8296ea7df73SStefano Zampini     }
830c1a070e6SStefano Zampini     garray = a->garray;
831c1a070e6SStefano Zampini     noffd  = a->B->cmap->N;
832c1a070e6SStefano Zampini     dnnz   = diag->nz;
833c1a070e6SStefano Zampini     onnz   = offd->nz;
834c1a070e6SStefano Zampini   } else {
835c1a070e6SStefano Zampini     diag = (Mat_SeqAIJ *)A->data;
836c1a070e6SStefano Zampini     offd = NULL;
837*06977982Sstefanozampini     if (!boundtocpu && (iscuda || iship)) {
838*06977982Sstefanozampini #if defined(HYPRE_USING_CUDA) && defined(PETSC_HAVE_CUDA)
839*06977982Sstefanozampini       if (iscuda) {
8406ea7df73SStefano Zampini         sameint = PETSC_TRUE;
8419566063dSJacob Faibussowitsch         PetscCall(MatSeqAIJCUSPARSEGetIJ(A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
842*06977982Sstefanozampini       }
8436ea7df73SStefano Zampini #endif
844*06977982Sstefanozampini #if defined(HYPRE_USING_HIP) && defined(PETSC_HAVE_HIP)
845*06977982Sstefanozampini       if (iship) {
846*06977982Sstefanozampini         sameint = PETSC_TRUE;
847*06977982Sstefanozampini         PetscCall(MatSeqAIJHIPSPARSEGetIJ(A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
848*06977982Sstefanozampini       }
849*06977982Sstefanozampini #endif
850*06977982Sstefanozampini     } else {
851*06977982Sstefanozampini       boundtocpu = PETSC_TRUE;
8526ea7df73SStefano Zampini       pdi        = diag->i;
8536ea7df73SStefano Zampini       pdj        = diag->j;
8546ea7df73SStefano Zampini       if (sameint) {
8556ea7df73SStefano Zampini         hdi = (HYPRE_Int *)pdi;
8566ea7df73SStefano Zampini         hdj = (HYPRE_Int *)pdj;
8576ea7df73SStefano Zampini       }
8586ea7df73SStefano Zampini     }
859c1a070e6SStefano Zampini     garray = NULL;
860c1a070e6SStefano Zampini     noffd  = 0;
861c1a070e6SStefano Zampini     dnnz   = diag->nz;
862c1a070e6SStefano Zampini     onnz   = 0;
863c1a070e6SStefano Zampini   }
864225daaf8SStefano Zampini 
865c1a070e6SStefano Zampini   /* create a temporary ParCSR */
866c1a070e6SStefano Zampini   if (HYPRE_AssumedPartitionCheck()) {
867c1a070e6SStefano Zampini     PetscMPIInt myid;
868c1a070e6SStefano Zampini 
8699566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &myid));
870c1a070e6SStefano Zampini     row_starts = A->rmap->range + myid;
871c1a070e6SStefano Zampini     col_starts = A->cmap->range + myid;
872c1a070e6SStefano Zampini   } else {
873c1a070e6SStefano Zampini     row_starts = A->rmap->range;
874c1a070e6SStefano Zampini     col_starts = A->cmap->range;
875c1a070e6SStefano Zampini   }
8762cf14000SStefano Zampini   tA = hypre_ParCSRMatrixCreate(comm, A->rmap->N, A->cmap->N, (HYPRE_BigInt *)row_starts, (HYPRE_BigInt *)col_starts, noffd, dnnz, onnz);
877a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
878c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetRowStartsOwner(tA, 0);
879c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetColStartsOwner(tA, 0);
880a1d2239cSSatish Balay #endif
881c1a070e6SStefano Zampini 
882225daaf8SStefano Zampini   /* set diagonal part */
883c1a070e6SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(tA);
8846ea7df73SStefano Zampini   if (!sameint) { /* malloc CSR pointers */
8859566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(A->rmap->n + 1, &hdi, dnnz, &hdj));
8866ea7df73SStefano Zampini     for (i = 0; i < A->rmap->n + 1; i++) hdi[i] = (HYPRE_Int)(pdi[i]);
8876ea7df73SStefano Zampini     for (i = 0; i < dnnz; i++) hdj[i] = (HYPRE_Int)(pdj[i]);
8882cf14000SStefano Zampini   }
8896ea7df73SStefano Zampini   hypre_CSRMatrixI(hdiag)           = hdi;
8906ea7df73SStefano Zampini   hypre_CSRMatrixJ(hdiag)           = hdj;
89139accc25SStefano Zampini   hypre_CSRMatrixData(hdiag)        = (HYPRE_Complex *)diag->a;
892c1a070e6SStefano Zampini   hypre_CSRMatrixNumNonzeros(hdiag) = diag->nz;
893c1a070e6SStefano Zampini   hypre_CSRMatrixSetRownnz(hdiag);
894c1a070e6SStefano Zampini   hypre_CSRMatrixSetDataOwner(hdiag, 0);
895c1a070e6SStefano Zampini 
896225daaf8SStefano Zampini   /* set offdiagonal part */
897c1a070e6SStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(tA);
898c1a070e6SStefano Zampini   if (offd) {
8996ea7df73SStefano Zampini     if (!sameint) { /* malloc CSR pointers */
9009566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(A->rmap->n + 1, &hoi, onnz, &hoj));
9016ea7df73SStefano Zampini       for (i = 0; i < A->rmap->n + 1; i++) hoi[i] = (HYPRE_Int)(poi[i]);
9026ea7df73SStefano Zampini       for (i = 0; i < onnz; i++) hoj[i] = (HYPRE_Int)(poj[i]);
9032cf14000SStefano Zampini     }
9046ea7df73SStefano Zampini     hypre_CSRMatrixI(hoffd)           = hoi;
9056ea7df73SStefano Zampini     hypre_CSRMatrixJ(hoffd)           = hoj;
90639accc25SStefano Zampini     hypre_CSRMatrixData(hoffd)        = (HYPRE_Complex *)offd->a;
907c1a070e6SStefano Zampini     hypre_CSRMatrixNumNonzeros(hoffd) = offd->nz;
908c1a070e6SStefano Zampini     hypre_CSRMatrixSetRownnz(hoffd);
909c1a070e6SStefano Zampini     hypre_CSRMatrixSetDataOwner(hoffd, 0);
9106ea7df73SStefano Zampini   }
9116ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
912*06977982Sstefanozampini   PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, !boundtocpu ? HYPRE_MEMORY_DEVICE : HYPRE_MEMORY_HOST);
9136ea7df73SStefano Zampini #else
9146ea7df73SStefano Zampini   #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0)
915792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixInitialize, tA);
9166ea7df73SStefano Zampini   #else
917792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, HYPRE_MEMORY_HOST);
9186ea7df73SStefano Zampini   #endif
9196ea7df73SStefano Zampini #endif
9206ea7df73SStefano Zampini   hypre_TFree(hypre_ParCSRMatrixColMapOffd(tA), HYPRE_MEMORY_HOST);
921c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetNumNonzeros(tA);
9222cf14000SStefano Zampini   hypre_ParCSRMatrixColMapOffd(tA) = (HYPRE_BigInt *)garray;
923792fecdfSBarry Smith   if (!hypre_ParCSRMatrixCommPkg(tA)) PetscCallExternal(hypre_MatvecCommPkgCreate, tA);
924613e5ff0Sstefano_zampini   *hA = tA;
9253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
926613e5ff0Sstefano_zampini }
927c1a070e6SStefano Zampini 
928d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJRestoreParCSR_Private(Mat A, hypre_ParCSRMatrix **hA)
929d71ae5a4SJacob Faibussowitsch {
930613e5ff0Sstefano_zampini   hypre_CSRMatrix *hdiag, *hoffd;
9316ea7df73SStefano Zampini   PetscBool        ismpiaij, sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
9326ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
9336ea7df73SStefano Zampini   PetscBool iscuda = PETSC_FALSE;
9346ea7df73SStefano Zampini #endif
935c1a070e6SStefano Zampini 
936613e5ff0Sstefano_zampini   PetscFunctionBegin;
9379566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
9386ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
9399566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, ""));
9406ea7df73SStefano Zampini   if (iscuda) sameint = PETSC_TRUE;
9416ea7df73SStefano Zampini #endif
942613e5ff0Sstefano_zampini   hdiag = hypre_ParCSRMatrixDiag(*hA);
943613e5ff0Sstefano_zampini   hoffd = hypre_ParCSRMatrixOffd(*hA);
9446ea7df73SStefano Zampini   /* free temporary memory allocated by PETSc
9456ea7df73SStefano Zampini      set pointers to NULL before destroying tA */
9462cf14000SStefano Zampini   if (!sameint) {
9472cf14000SStefano Zampini     HYPRE_Int *hi, *hj;
9482cf14000SStefano Zampini 
9492cf14000SStefano Zampini     hi = hypre_CSRMatrixI(hdiag);
9502cf14000SStefano Zampini     hj = hypre_CSRMatrixJ(hdiag);
9519566063dSJacob Faibussowitsch     PetscCall(PetscFree2(hi, hj));
9526ea7df73SStefano Zampini     if (ismpiaij) {
9532cf14000SStefano Zampini       hi = hypre_CSRMatrixI(hoffd);
9542cf14000SStefano Zampini       hj = hypre_CSRMatrixJ(hoffd);
9559566063dSJacob Faibussowitsch       PetscCall(PetscFree2(hi, hj));
9562cf14000SStefano Zampini     }
9572cf14000SStefano Zampini   }
958c1a070e6SStefano Zampini   hypre_CSRMatrixI(hdiag)    = NULL;
959c1a070e6SStefano Zampini   hypre_CSRMatrixJ(hdiag)    = NULL;
960c1a070e6SStefano Zampini   hypre_CSRMatrixData(hdiag) = NULL;
9616ea7df73SStefano Zampini   if (ismpiaij) {
962c1a070e6SStefano Zampini     hypre_CSRMatrixI(hoffd)    = NULL;
963c1a070e6SStefano Zampini     hypre_CSRMatrixJ(hoffd)    = NULL;
964c1a070e6SStefano Zampini     hypre_CSRMatrixData(hoffd) = NULL;
9656ea7df73SStefano Zampini   }
966613e5ff0Sstefano_zampini   hypre_ParCSRMatrixColMapOffd(*hA) = NULL;
967613e5ff0Sstefano_zampini   hypre_ParCSRMatrixDestroy(*hA);
968613e5ff0Sstefano_zampini   *hA = NULL;
9693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
970613e5ff0Sstefano_zampini }
971613e5ff0Sstefano_zampini 
972613e5ff0Sstefano_zampini /* calls RAP from BoomerAMG:
9733dad0653Sstefano_zampini    the resulting ParCSR will not own the column and row starts
9746ea7df73SStefano Zampini    It looks like we don't need to have the diagonal entries ordered first */
975d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_RAP(hypre_ParCSRMatrix *hR, hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hP, hypre_ParCSRMatrix **hRAP)
976d71ae5a4SJacob Faibussowitsch {
977a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
978613e5ff0Sstefano_zampini   HYPRE_Int P_owns_col_starts, R_owns_row_starts;
979a1d2239cSSatish Balay #endif
980613e5ff0Sstefano_zampini 
981613e5ff0Sstefano_zampini   PetscFunctionBegin;
982a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
983613e5ff0Sstefano_zampini   P_owns_col_starts = hypre_ParCSRMatrixOwnsColStarts(hP);
984613e5ff0Sstefano_zampini   R_owns_row_starts = hypre_ParCSRMatrixOwnsRowStarts(hR);
985a1d2239cSSatish Balay #endif
9866ea7df73SStefano Zampini   /* can be replaced by version test later */
9876ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
988792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParCSRMatrixRAP");
9896ea7df73SStefano Zampini   *hRAP = hypre_ParCSRMatrixRAP(hR, hA, hP);
9906ea7df73SStefano Zampini   PetscStackPop;
9916ea7df73SStefano Zampini #else
992792fecdfSBarry Smith   PetscCallExternal(hypre_BoomerAMGBuildCoarseOperator, hR, hA, hP, hRAP);
993792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixSetNumNonzeros, *hRAP);
9946ea7df73SStefano Zampini #endif
995613e5ff0Sstefano_zampini   /* hypre_BoomerAMGBuildCoarseOperator steals the col_starts from P and the row_starts from R */
996a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
997613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetRowStartsOwner(*hRAP, 0);
998613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetColStartsOwner(*hRAP, 0);
999613e5ff0Sstefano_zampini   if (P_owns_col_starts) hypre_ParCSRMatrixSetColStartsOwner(hP, 1);
1000613e5ff0Sstefano_zampini   if (R_owns_row_starts) hypre_ParCSRMatrixSetRowStartsOwner(hR, 1);
1001a1d2239cSSatish Balay #endif
10023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1003613e5ff0Sstefano_zampini }
1004613e5ff0Sstefano_zampini 
1005d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat P, Mat C)
1006d71ae5a4SJacob Faibussowitsch {
10076f231fbdSstefano_zampini   Mat                 B;
10086abb4441SStefano Zampini   hypre_ParCSRMatrix *hA, *hP, *hPtAP = NULL;
10094222ddf1SHong Zhang   Mat_Product        *product = C->product;
1010613e5ff0Sstefano_zampini 
1011613e5ff0Sstefano_zampini   PetscFunctionBegin;
10129566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
10139566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(P, &hP));
10149566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(hP, hA, hP, &hPtAP));
10159566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hPtAP, MATAIJ, PETSC_OWN_POINTER, &B));
10164222ddf1SHong Zhang 
10179566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
10184222ddf1SHong Zhang   C->product = product;
10194222ddf1SHong Zhang 
10209566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
10219566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(P, &hP));
10223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10236f231fbdSstefano_zampini }
10246f231fbdSstefano_zampini 
1025d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatPtAPSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat P, PetscReal fill, Mat C)
1026d71ae5a4SJacob Faibussowitsch {
10276f231fbdSstefano_zampini   PetscFunctionBegin;
10289566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATAIJ));
10294222ddf1SHong Zhang   C->ops->ptapnumeric    = MatPtAPNumeric_AIJ_AIJ_wHYPRE;
10304222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
10313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1032613e5ff0Sstefano_zampini }
1033613e5ff0Sstefano_zampini 
1034d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_HYPRE(Mat A, Mat P, Mat C)
1035d71ae5a4SJacob Faibussowitsch {
10364cc28894Sstefano_zampini   Mat                 B;
10374cc28894Sstefano_zampini   Mat_HYPRE          *hP;
10386abb4441SStefano Zampini   hypre_ParCSRMatrix *hA = NULL, *Pparcsr, *ptapparcsr = NULL;
1039613e5ff0Sstefano_zampini   HYPRE_Int           type;
1040613e5ff0Sstefano_zampini   MPI_Comm            comm = PetscObjectComm((PetscObject)A);
10414cc28894Sstefano_zampini   PetscBool           ishypre;
1042613e5ff0Sstefano_zampini 
1043613e5ff0Sstefano_zampini   PetscFunctionBegin;
10449566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre));
104528b400f6SJacob Faibussowitsch   PetscCheck(ishypre, comm, PETSC_ERR_USER, "P should be of type %s", MATHYPRE);
10464cc28894Sstefano_zampini   hP = (Mat_HYPRE *)P->data;
1047792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type);
104808401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1049792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr);
1050613e5ff0Sstefano_zampini 
10519566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
10529566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, hA, Pparcsr, &ptapparcsr));
10539566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
1054225daaf8SStefano Zampini 
10554cc28894Sstefano_zampini   /* create temporary matrix and merge to C */
10569566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ptapparcsr, ((PetscObject)C)->type_name, PETSC_OWN_POINTER, &B));
10579566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
10583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10594cc28894Sstefano_zampini }
10604cc28894Sstefano_zampini 
1061d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_HYPRE_HYPRE(Mat A, Mat P, Mat C)
1062d71ae5a4SJacob Faibussowitsch {
10634cc28894Sstefano_zampini   Mat                 B;
10646abb4441SStefano Zampini   hypre_ParCSRMatrix *Aparcsr, *Pparcsr, *ptapparcsr = NULL;
10654cc28894Sstefano_zampini   Mat_HYPRE          *hA, *hP;
10664cc28894Sstefano_zampini   PetscBool           ishypre;
10674cc28894Sstefano_zampini   HYPRE_Int           type;
10684cc28894Sstefano_zampini 
10694cc28894Sstefano_zampini   PetscFunctionBegin;
10709566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre));
107128b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)P), PETSC_ERR_USER, "P should be of type %s", MATHYPRE);
10729566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
107328b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE);
10744cc28894Sstefano_zampini   hA = (Mat_HYPRE *)A->data;
10754cc28894Sstefano_zampini   hP = (Mat_HYPRE *)P->data;
1076792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
107708401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1078792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type);
107908401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)P), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1080792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr);
1081792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr);
10829566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, Aparcsr, Pparcsr, &ptapparcsr));
10839566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ptapparcsr, MATHYPRE, PETSC_OWN_POINTER, &B));
10849566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
10853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10864cc28894Sstefano_zampini }
10874cc28894Sstefano_zampini 
1088d501dc42Sstefano_zampini /* calls hypre_ParMatmul
1089d501dc42Sstefano_zampini    hypre_ParMatMul uses hypre_ParMatrixCreate with the communicator of hA
10903dad0653Sstefano_zampini    hypre_ParMatrixCreate does not duplicate the communicator
10916ea7df73SStefano Zampini    It looks like we don't need to have the diagonal entries ordered first */
1092d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_MatMatMult(hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hB, hypre_ParCSRMatrix **hAB)
1093d71ae5a4SJacob Faibussowitsch {
1094d501dc42Sstefano_zampini   PetscFunctionBegin;
10956ea7df73SStefano Zampini   /* can be replaced by version test later */
10966ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
1097792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParCSRMatMat");
10986ea7df73SStefano Zampini   *hAB = hypre_ParCSRMatMat(hA, hB);
10996ea7df73SStefano Zampini #else
1100792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParMatmul");
1101d501dc42Sstefano_zampini   *hAB = hypre_ParMatmul(hA, hB);
11026ea7df73SStefano Zampini #endif
1103d501dc42Sstefano_zampini   PetscStackPop;
11043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1105d501dc42Sstefano_zampini }
1106d501dc42Sstefano_zampini 
1107d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C)
1108d71ae5a4SJacob Faibussowitsch {
11095e5acdf2Sstefano_zampini   Mat                 D;
1110d501dc42Sstefano_zampini   hypre_ParCSRMatrix *hA, *hB, *hAB = NULL;
11114222ddf1SHong Zhang   Mat_Product        *product = C->product;
11125e5acdf2Sstefano_zampini 
11135e5acdf2Sstefano_zampini   PetscFunctionBegin;
11149566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
11159566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(B, &hB));
11169566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_MatMatMult(hA, hB, &hAB));
11179566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hAB, MATAIJ, PETSC_OWN_POINTER, &D));
11184222ddf1SHong Zhang 
11199566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &D));
11204222ddf1SHong Zhang   C->product = product;
11214222ddf1SHong Zhang 
11229566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
11239566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(B, &hB));
11243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11255e5acdf2Sstefano_zampini }
11265e5acdf2Sstefano_zampini 
1127d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatMatMultSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat B, PetscReal fill, Mat C)
1128d71ae5a4SJacob Faibussowitsch {
11295e5acdf2Sstefano_zampini   PetscFunctionBegin;
11309566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATAIJ));
11314222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_AIJ_AIJ_wHYPRE;
11324222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
11333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11345e5acdf2Sstefano_zampini }
11355e5acdf2Sstefano_zampini 
1136d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_HYPRE_HYPRE(Mat A, Mat B, Mat C)
1137d71ae5a4SJacob Faibussowitsch {
1138d501dc42Sstefano_zampini   Mat                 D;
1139d501dc42Sstefano_zampini   hypre_ParCSRMatrix *Aparcsr, *Bparcsr, *ABparcsr = NULL;
1140d501dc42Sstefano_zampini   Mat_HYPRE          *hA, *hB;
1141d501dc42Sstefano_zampini   PetscBool           ishypre;
1142d501dc42Sstefano_zampini   HYPRE_Int           type;
11434222ddf1SHong Zhang   Mat_Product        *product;
1144d501dc42Sstefano_zampini 
1145d501dc42Sstefano_zampini   PetscFunctionBegin;
11469566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)B, MATHYPRE, &ishypre));
114728b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)B), PETSC_ERR_USER, "B should be of type %s", MATHYPRE);
11489566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
114928b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE);
1150d501dc42Sstefano_zampini   hA = (Mat_HYPRE *)A->data;
1151d501dc42Sstefano_zampini   hB = (Mat_HYPRE *)B->data;
1152792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
115308401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1154792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hB->ij, &type);
115508401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1156792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr);
1157792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hB->ij, (void **)&Bparcsr);
11589566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_MatMatMult(Aparcsr, Bparcsr, &ABparcsr));
11599566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ABparcsr, MATHYPRE, PETSC_OWN_POINTER, &D));
11604222ddf1SHong Zhang 
1161d501dc42Sstefano_zampini   /* need to use HeaderReplace because HeaderMerge messes up with the communicator */
11624222ddf1SHong Zhang   product    = C->product; /* save it from MatHeaderReplace() */
11634222ddf1SHong Zhang   C->product = NULL;
11649566063dSJacob Faibussowitsch   PetscCall(MatHeaderReplace(C, &D));
11654222ddf1SHong Zhang   C->product             = product;
1166d501dc42Sstefano_zampini   C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE;
11674222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
11683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1169d501dc42Sstefano_zampini }
1170d501dc42Sstefano_zampini 
1171d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultNumeric_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, Mat D)
1172d71ae5a4SJacob Faibussowitsch {
117320e1dc0dSstefano_zampini   Mat                 E;
11746abb4441SStefano Zampini   hypre_ParCSRMatrix *hA, *hB, *hC, *hABC = NULL;
117520e1dc0dSstefano_zampini 
117620e1dc0dSstefano_zampini   PetscFunctionBegin;
11779566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
11789566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(B, &hB));
11799566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(C, &hC));
11809566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(hA, hB, hC, &hABC));
11819566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hABC, MATAIJ, PETSC_OWN_POINTER, &E));
11829566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(D, &E));
11839566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
11849566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(B, &hB));
11859566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(C, &hC));
11863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
118720e1dc0dSstefano_zampini }
118820e1dc0dSstefano_zampini 
1189d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultSymbolic_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, PetscReal fill, Mat D)
1190d71ae5a4SJacob Faibussowitsch {
119120e1dc0dSstefano_zampini   PetscFunctionBegin;
11929566063dSJacob Faibussowitsch   PetscCall(MatSetType(D, MATAIJ));
11933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
119420e1dc0dSstefano_zampini }
119520e1dc0dSstefano_zampini 
1196d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_AB_HYPRE(Mat C)
1197d71ae5a4SJacob Faibussowitsch {
11984222ddf1SHong Zhang   PetscFunctionBegin;
11994222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
12003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12014222ddf1SHong Zhang }
12024222ddf1SHong Zhang 
1203d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_AB(Mat C)
1204d71ae5a4SJacob Faibussowitsch {
12054222ddf1SHong Zhang   Mat_Product *product = C->product;
12064222ddf1SHong Zhang   PetscBool    Ahypre;
12074222ddf1SHong Zhang 
12084222ddf1SHong Zhang   PetscFunctionBegin;
12099566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)product->A, MATHYPRE, &Ahypre));
12104222ddf1SHong Zhang   if (Ahypre) { /* A is a Hypre matrix */
12119566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
12124222ddf1SHong Zhang     C->ops->productsymbolic = MatProductSymbolic_AB_HYPRE;
12134222ddf1SHong Zhang     C->ops->matmultnumeric  = MatMatMultNumeric_HYPRE_HYPRE;
12143ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
12156718818eSStefano Zampini   }
12163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12174222ddf1SHong Zhang }
12184222ddf1SHong Zhang 
1219d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_PtAP_HYPRE(Mat C)
1220d71ae5a4SJacob Faibussowitsch {
12214222ddf1SHong Zhang   PetscFunctionBegin;
12224222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
12233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12244222ddf1SHong Zhang }
12254222ddf1SHong Zhang 
1226d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_PtAP(Mat C)
1227d71ae5a4SJacob Faibussowitsch {
12284222ddf1SHong Zhang   Mat_Product *product = C->product;
12294222ddf1SHong Zhang   PetscBool    flg;
12304222ddf1SHong Zhang   PetscInt     type        = 0;
12314222ddf1SHong Zhang   const char  *outTypes[4] = {"aij", "seqaij", "mpiaij", "hypre"};
12324222ddf1SHong Zhang   PetscInt     ntype       = 4;
12334222ddf1SHong Zhang   Mat          A           = product->A;
12344222ddf1SHong Zhang   PetscBool    Ahypre;
12354222ddf1SHong Zhang 
12364222ddf1SHong Zhang   PetscFunctionBegin;
12379566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &Ahypre));
12384222ddf1SHong Zhang   if (Ahypre) { /* A is a Hypre matrix */
12399566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
12404222ddf1SHong Zhang     C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE;
12414222ddf1SHong Zhang     C->ops->ptapnumeric     = MatPtAPNumeric_HYPRE_HYPRE;
12423ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
12434222ddf1SHong Zhang   }
12444222ddf1SHong Zhang 
12454222ddf1SHong Zhang   /* A is AIJ, P is Hypre, C = PtAP can be either AIJ or Hypre format */
12464222ddf1SHong Zhang   /* Get runtime option */
12474222ddf1SHong Zhang   if (product->api_user) {
1248d0609cedSBarry Smith     PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatPtAP_HYPRE", "Mat");
12499566063dSJacob Faibussowitsch     PetscCall(PetscOptionsEList("-matptap_hypre_outtype", "MatPtAP outtype", "MatPtAP outtype", outTypes, ntype, outTypes[type], &type, &flg));
1250d0609cedSBarry Smith     PetscOptionsEnd();
12514222ddf1SHong Zhang   } else {
1252d0609cedSBarry Smith     PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatProduct_PtAP_HYPRE", "Mat");
12539566063dSJacob Faibussowitsch     PetscCall(PetscOptionsEList("-mat_product_algorithm_hypre_outtype", "MatProduct_PtAP outtype", "MatProduct_PtAP", outTypes, ntype, outTypes[type], &type, &flg));
1254d0609cedSBarry Smith     PetscOptionsEnd();
12554222ddf1SHong Zhang   }
12564222ddf1SHong Zhang 
12574222ddf1SHong Zhang   if (type == 0 || type == 1 || type == 2) {
12589566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATAIJ));
12594222ddf1SHong Zhang   } else if (type == 3) {
12609566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
12614222ddf1SHong Zhang   } else SETERRQ(PetscObjectComm((PetscObject)C), PETSC_ERR_SUP, "MatPtAP outtype is not supported");
12624222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE;
12634222ddf1SHong Zhang   C->ops->ptapnumeric     = MatPtAPNumeric_AIJ_HYPRE;
12643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12654222ddf1SHong Zhang }
12664222ddf1SHong Zhang 
1267d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE(Mat C)
1268d71ae5a4SJacob Faibussowitsch {
12694222ddf1SHong Zhang   Mat_Product *product = C->product;
12704222ddf1SHong Zhang 
12714222ddf1SHong Zhang   PetscFunctionBegin;
12724222ddf1SHong Zhang   switch (product->type) {
1273d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AB:
1274d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_HYPRE_AB(C));
1275d71ae5a4SJacob Faibussowitsch     break;
1276d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_PtAP:
1277d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_HYPRE_PtAP(C));
1278d71ae5a4SJacob Faibussowitsch     break;
1279d71ae5a4SJacob Faibussowitsch   default:
1280d71ae5a4SJacob Faibussowitsch     break;
12814222ddf1SHong Zhang   }
12823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12834222ddf1SHong Zhang }
12844222ddf1SHong Zhang 
1285d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTranspose_HYPRE(Mat A, Vec x, Vec y)
1286d71ae5a4SJacob Faibussowitsch {
128763c07aadSStefano Zampini   PetscFunctionBegin;
12889566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_TRUE));
12893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
129063c07aadSStefano Zampini }
129163c07aadSStefano Zampini 
1292d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_HYPRE(Mat A, Vec x, Vec y)
1293d71ae5a4SJacob Faibussowitsch {
129463c07aadSStefano Zampini   PetscFunctionBegin;
12959566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_FALSE));
12963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
129763c07aadSStefano Zampini }
129863c07aadSStefano Zampini 
1299d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultAdd_HYPRE(Mat A, Vec x, Vec y, Vec z)
1300d71ae5a4SJacob Faibussowitsch {
1301414bd5c3SStefano Zampini   PetscFunctionBegin;
130248a46eb9SPierre Jolivet   if (y != z) PetscCall(VecCopy(y, z));
13039566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_FALSE));
13043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1305414bd5c3SStefano Zampini }
1306414bd5c3SStefano Zampini 
1307d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTransposeAdd_HYPRE(Mat A, Vec x, Vec y, Vec z)
1308d71ae5a4SJacob Faibussowitsch {
1309414bd5c3SStefano Zampini   PetscFunctionBegin;
131048a46eb9SPierre Jolivet   if (y != z) PetscCall(VecCopy(y, z));
13119566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_TRUE));
13123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1313414bd5c3SStefano Zampini }
1314414bd5c3SStefano Zampini 
1315414bd5c3SStefano Zampini /* y = a * A * x + b * y or y = a * A^t * x + b * y depending on trans */
1316d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_MultKernel_Private(Mat A, HYPRE_Complex a, Vec x, HYPRE_Complex b, Vec y, PetscBool trans)
1317d71ae5a4SJacob Faibussowitsch {
131863c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE *)A->data;
131963c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
132063c07aadSStefano Zampini   hypre_ParVector    *hx, *hy;
132163c07aadSStefano Zampini 
132263c07aadSStefano Zampini   PetscFunctionBegin;
132363c07aadSStefano Zampini   if (trans) {
13249566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorPushVecRead(hA->b, x));
13259566063dSJacob Faibussowitsch     if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->x, y));
13269566063dSJacob Faibussowitsch     else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->x, y));
1327792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hx);
1328792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hy);
132963c07aadSStefano Zampini   } else {
13309566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorPushVecRead(hA->x, x));
13319566063dSJacob Faibussowitsch     if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->b, y));
13329566063dSJacob Faibussowitsch     else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->b, y));
1333792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hx);
1334792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hy);
133563c07aadSStefano Zampini   }
1336792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
13376ea7df73SStefano Zampini   if (trans) {
1338792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMatvecT, a, parcsr, hx, b, hy);
13396ea7df73SStefano Zampini   } else {
1340792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMatvec, a, parcsr, hx, b, hy);
13416ea7df73SStefano Zampini   }
13429566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hA->x));
13439566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hA->b));
13443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
134563c07aadSStefano Zampini }
134663c07aadSStefano Zampini 
1347d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_HYPRE(Mat A)
1348d71ae5a4SJacob Faibussowitsch {
134963c07aadSStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
135063c07aadSStefano Zampini 
135163c07aadSStefano Zampini   PetscFunctionBegin;
13529566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&hA->x));
13539566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&hA->b));
1354*06977982Sstefanozampini   PetscCall(MatHYPRE_DestroyCOOMat(A)); /* must be called before destroying the individual CSR */
1355978814f1SStefano Zampini   if (hA->ij) {
1356978814f1SStefano Zampini     if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL;
1357792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixDestroy, hA->ij);
1358978814f1SStefano Zampini   }
13599566063dSJacob Faibussowitsch   if (hA->comm) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)A), &hA->comm));
1360c69f721fSFande Kong 
13619566063dSJacob Faibussowitsch   PetscCall(MatStashDestroy_Private(&A->stash));
13629566063dSJacob Faibussowitsch   PetscCall(PetscFree(hA->array));
1363c69f721fSFande Kong 
13649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_aij_C", NULL));
13659566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_is_C", NULL));
13669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_hypre_C", NULL));
13679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaij_hypre_C", NULL));
1368*06977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijhipsparse_hypre_C", NULL));
1369*06977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaijhipsparse_hypre_C", NULL));
1370*06977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaijcusparse_hypre_C", NULL));
1371*06977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaijcusparse_hypre_C", NULL));
13729566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPRESetPreallocation_C", NULL));
13739566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPREGetParCSR_C", NULL));
13745fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL));
13755fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL));
13769566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->data));
13773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
137863c07aadSStefano Zampini }
137963c07aadSStefano Zampini 
1380d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetUp_HYPRE(Mat A)
1381d71ae5a4SJacob Faibussowitsch {
13824ec6421dSstefano_zampini   PetscFunctionBegin;
1383*06977982Sstefanozampini   if (!A->preallocated) PetscCall(MatHYPRESetPreallocation(A, PETSC_DEFAULT, NULL, PETSC_DEFAULT, NULL));
13843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13854ec6421dSstefano_zampini }
13864ec6421dSstefano_zampini 
13876ea7df73SStefano Zampini //TODO FIX hypre_CSRMatrixMatvecOutOfPlace
13886ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
1389d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatBindToCPU_HYPRE(Mat A, PetscBool bind)
1390d71ae5a4SJacob Faibussowitsch {
13916ea7df73SStefano Zampini   Mat_HYPRE           *hA   = (Mat_HYPRE *)A->data;
13926ea7df73SStefano Zampini   HYPRE_MemoryLocation hmem = bind ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE;
13936ea7df73SStefano Zampini 
13946ea7df73SStefano Zampini   PetscFunctionBegin;
13956ea7df73SStefano Zampini   A->boundtocpu = bind;
13965fbaff96SJunchao Zhang   if (hA->ij && hypre_IJMatrixAssembleFlag(hA->ij) && hmem != hypre_IJMatrixMemoryLocation(hA->ij)) {
13976ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
1398792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
1399792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMigrate, parcsr, hmem);
14006ea7df73SStefano Zampini   }
14019566063dSJacob Faibussowitsch   if (hA->x) PetscCall(VecHYPRE_IJBindToCPU(hA->x, bind));
14029566063dSJacob Faibussowitsch   if (hA->b) PetscCall(VecHYPRE_IJBindToCPU(hA->b, bind));
14033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14046ea7df73SStefano Zampini }
14056ea7df73SStefano Zampini #endif
14066ea7df73SStefano Zampini 
1407d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_HYPRE(Mat A, MatAssemblyType mode)
1408d71ae5a4SJacob Faibussowitsch {
140963c07aadSStefano Zampini   Mat_HYPRE   *hA = (Mat_HYPRE *)A->data;
1410c69f721fSFande Kong   PetscMPIInt  n;
1411c69f721fSFande Kong   PetscInt     i, j, rstart, ncols, flg;
1412c69f721fSFande Kong   PetscInt    *row, *col;
1413c69f721fSFande Kong   PetscScalar *val;
141463c07aadSStefano Zampini 
141563c07aadSStefano Zampini   PetscFunctionBegin;
141608401ef6SPierre Jolivet   PetscCheck(mode != MAT_FLUSH_ASSEMBLY, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_FLUSH_ASSEMBLY currently not supported with MATHYPRE");
1417c69f721fSFande Kong 
1418c69f721fSFande Kong   if (!A->nooffprocentries) {
1419c69f721fSFande Kong     while (1) {
14209566063dSJacob Faibussowitsch       PetscCall(MatStashScatterGetMesg_Private(&A->stash, &n, &row, &col, &val, &flg));
1421c69f721fSFande Kong       if (!flg) break;
1422c69f721fSFande Kong 
1423c69f721fSFande Kong       for (i = 0; i < n;) {
1424c69f721fSFande Kong         /* Now identify the consecutive vals belonging to the same row */
1425c69f721fSFande Kong         for (j = i, rstart = row[j]; j < n; j++) {
1426c69f721fSFande Kong           if (row[j] != rstart) break;
1427c69f721fSFande Kong         }
1428c69f721fSFande Kong         if (j < n) ncols = j - i;
1429c69f721fSFande Kong         else ncols = n - i;
1430c69f721fSFande Kong         /* Now assemble all these values with a single function call */
14319566063dSJacob Faibussowitsch         PetscCall(MatSetValues_HYPRE(A, 1, row + i, ncols, col + i, val + i, A->insertmode));
1432c69f721fSFande Kong 
1433c69f721fSFande Kong         i = j;
1434c69f721fSFande Kong       }
1435c69f721fSFande Kong     }
14369566063dSJacob Faibussowitsch     PetscCall(MatStashScatterEnd_Private(&A->stash));
1437c69f721fSFande Kong   }
1438c69f721fSFande Kong 
1439792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixAssemble, hA->ij);
1440336664bdSPierre Jolivet   /* The assembly routine destroys the aux_matrix, we recreate it here by calling HYPRE_IJMatrixInitialize */
1441336664bdSPierre Jolivet   /* If the option MAT_SORTED_FULL is set to true, the indices and values can be passed to hypre directly, so we don't need the aux_matrix */
1442651b1cf9SStefano Zampini   if (!A->sortedfull) {
1443af1cf968SStefano Zampini     hypre_AuxParCSRMatrix *aux_matrix;
1444af1cf968SStefano Zampini 
1445af1cf968SStefano Zampini     /* call destroy just to make sure we do not leak anything */
1446af1cf968SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
1447792fecdfSBarry Smith     PetscCallExternal(hypre_AuxParCSRMatrixDestroy, aux_matrix);
1448af1cf968SStefano Zampini     hypre_IJMatrixTranslator(hA->ij) = NULL;
1449af1cf968SStefano Zampini 
1450af1cf968SStefano Zampini     /* Initialize with assembled flag -> it only recreates the aux_par_matrix */
1451792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij);
1452af1cf968SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
14536ea7df73SStefano Zampini     if (aux_matrix) {
1454af1cf968SStefano Zampini       hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1; /* see comment in MatHYPRESetPreallocation_HYPRE */
145522235d61SPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
1456792fecdfSBarry Smith       PetscCallExternal(hypre_AuxParCSRMatrixInitialize, aux_matrix);
145722235d61SPierre Jolivet #else
1458792fecdfSBarry Smith       PetscCallExternal(hypre_AuxParCSRMatrixInitialize_v2, aux_matrix, HYPRE_MEMORY_HOST);
145922235d61SPierre Jolivet #endif
1460af1cf968SStefano Zampini     }
14616ea7df73SStefano Zampini   }
14626ea7df73SStefano Zampini   {
14636ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
14646ea7df73SStefano Zampini 
1465792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
1466792fecdfSBarry Smith     if (!hypre_ParCSRMatrixCommPkg(parcsr)) PetscCallExternal(hypre_MatvecCommPkgCreate, parcsr);
14676ea7df73SStefano Zampini   }
14689566063dSJacob Faibussowitsch   if (!hA->x) PetscCall(VecHYPRE_IJVectorCreate(A->cmap, &hA->x));
14699566063dSJacob Faibussowitsch   if (!hA->b) PetscCall(VecHYPRE_IJVectorCreate(A->rmap, &hA->b));
14706ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
14719566063dSJacob Faibussowitsch   PetscCall(MatBindToCPU_HYPRE(A, A->boundtocpu));
14726ea7df73SStefano Zampini #endif
14733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
147463c07aadSStefano Zampini }
147563c07aadSStefano Zampini 
1476d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetArray_HYPRE(Mat A, PetscInt size, void **array)
1477d71ae5a4SJacob Faibussowitsch {
1478c69f721fSFande Kong   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1479c69f721fSFande Kong 
1480c69f721fSFande Kong   PetscFunctionBegin;
1481651b1cf9SStefano Zampini   PetscCheck(hA->array_available, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Temporary space is in use");
1482c69f721fSFande Kong 
1483651b1cf9SStefano Zampini   if (hA->array_size >= size) {
148439accc25SStefano Zampini     *array = hA->array;
148539accc25SStefano Zampini   } else {
14869566063dSJacob Faibussowitsch     PetscCall(PetscFree(hA->array));
1487651b1cf9SStefano Zampini     hA->array_size = size;
1488651b1cf9SStefano Zampini     PetscCall(PetscMalloc(hA->array_size, &hA->array));
1489c69f721fSFande Kong     *array = hA->array;
1490c69f721fSFande Kong   }
1491c69f721fSFande Kong 
1492651b1cf9SStefano Zampini   hA->array_available = PETSC_FALSE;
14933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1494c69f721fSFande Kong }
1495c69f721fSFande Kong 
1496d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreArray_HYPRE(Mat A, void **array)
1497d71ae5a4SJacob Faibussowitsch {
1498c69f721fSFande Kong   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1499c69f721fSFande Kong 
1500c69f721fSFande Kong   PetscFunctionBegin;
1501c69f721fSFande Kong   *array              = NULL;
1502651b1cf9SStefano Zampini   hA->array_available = PETSC_TRUE;
15033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1504c69f721fSFande Kong }
1505c69f721fSFande Kong 
1506d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_HYPRE(Mat A, PetscInt nr, const PetscInt rows[], PetscInt nc, const PetscInt cols[], const PetscScalar v[], InsertMode ins)
1507d71ae5a4SJacob Faibussowitsch {
1508d975228cSstefano_zampini   Mat_HYPRE     *hA   = (Mat_HYPRE *)A->data;
1509d975228cSstefano_zampini   PetscScalar   *vals = (PetscScalar *)v;
151039accc25SStefano Zampini   HYPRE_Complex *sscr;
1511c69f721fSFande Kong   PetscInt      *cscr[2];
1512c69f721fSFande Kong   PetscInt       i, nzc;
1513651b1cf9SStefano Zampini   PetscInt       rst = A->rmap->rstart, ren = A->rmap->rend;
151408defe43SFande Kong   void          *array = NULL;
1515d975228cSstefano_zampini 
1516d975228cSstefano_zampini   PetscFunctionBegin;
15179566063dSJacob Faibussowitsch   PetscCall(MatGetArray_HYPRE(A, sizeof(PetscInt) * (2 * nc) + sizeof(HYPRE_Complex) * nc * nr, &array));
1518c69f721fSFande Kong   cscr[0] = (PetscInt *)array;
1519c69f721fSFande Kong   cscr[1] = ((PetscInt *)array) + nc;
152039accc25SStefano Zampini   sscr    = (HYPRE_Complex *)(((PetscInt *)array) + nc * 2);
1521d975228cSstefano_zampini   for (i = 0, nzc = 0; i < nc; i++) {
1522d975228cSstefano_zampini     if (cols[i] >= 0) {
1523d975228cSstefano_zampini       cscr[0][nzc]   = cols[i];
1524d975228cSstefano_zampini       cscr[1][nzc++] = i;
1525d975228cSstefano_zampini     }
1526d975228cSstefano_zampini   }
1527c69f721fSFande Kong   if (!nzc) {
15289566063dSJacob Faibussowitsch     PetscCall(MatRestoreArray_HYPRE(A, &array));
15293ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1530c69f721fSFande Kong   }
1531d975228cSstefano_zampini 
15326ea7df73SStefano Zampini #if 0 //defined(PETSC_HAVE_HYPRE_DEVICE)
15336ea7df73SStefano Zampini   if (HYPRE_MEMORY_HOST != hypre_IJMatrixMemoryLocation(hA->ij)) {
15346ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
15356ea7df73SStefano Zampini 
1536792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject,hA->ij,(void**)&parcsr);
1537792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMigrate,parcsr, HYPRE_MEMORY_HOST);
15386ea7df73SStefano Zampini   }
15396ea7df73SStefano Zampini #endif
15406ea7df73SStefano Zampini 
1541d975228cSstefano_zampini   if (ins == ADD_VALUES) {
1542d975228cSstefano_zampini     for (i = 0; i < nr; i++) {
15436ea7df73SStefano Zampini       if (rows[i] >= 0) {
1544d975228cSstefano_zampini         PetscInt  j;
15452cf14000SStefano Zampini         HYPRE_Int hnc = (HYPRE_Int)nzc;
15462cf14000SStefano Zampini 
1547651b1cf9SStefano Zampini         if (!nzc) continue;
1548651b1cf9SStefano Zampini         /* nonlocal values */
1549651b1cf9SStefano Zampini         if (rows[i] < rst || rows[i] >= ren) {
1550651b1cf9SStefano Zampini           PetscCheck(!A->nooffprocentries, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Setting off process row %" PetscInt_FMT " even though MatSetOption(,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE) was set", rows[i]);
1551651b1cf9SStefano Zampini           if (hA->donotstash) continue;
1552651b1cf9SStefano Zampini         }
1553aed4548fSBarry Smith         PetscCheck((PetscInt)hnc == nzc, PETSC_COMM_SELF, PETSC_ERR_SUP, "Hypre overflow! number of columns %" PetscInt_FMT " for row %" PetscInt_FMT, nzc, rows[i]);
15549566063dSJacob Faibussowitsch         for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j]));
1555792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixAddToValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr);
1556d975228cSstefano_zampini       }
1557d975228cSstefano_zampini       vals += nc;
1558d975228cSstefano_zampini     }
1559d975228cSstefano_zampini   } else { /* INSERT_VALUES */
1560d975228cSstefano_zampini     for (i = 0; i < nr; i++) {
15616ea7df73SStefano Zampini       if (rows[i] >= 0) {
1562d975228cSstefano_zampini         PetscInt  j;
15632cf14000SStefano Zampini         HYPRE_Int hnc = (HYPRE_Int)nzc;
15642cf14000SStefano Zampini 
1565651b1cf9SStefano Zampini         if (!nzc) continue;
1566aed4548fSBarry Smith         PetscCheck((PetscInt)hnc == nzc, PETSC_COMM_SELF, PETSC_ERR_SUP, "Hypre overflow! number of columns %" PetscInt_FMT " for row %" PetscInt_FMT, nzc, rows[i]);
15679566063dSJacob Faibussowitsch         for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j]));
1568c69f721fSFande Kong         /* nonlocal values */
1569651b1cf9SStefano Zampini         if (rows[i] < rst || rows[i] >= ren) {
1570651b1cf9SStefano Zampini           PetscCheck(!A->nooffprocentries, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Setting off process row %" PetscInt_FMT " even though MatSetOption(,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE) was set", rows[i]);
1571651b1cf9SStefano Zampini           if (!hA->donotstash) PetscCall(MatStashValuesRow_Private(&A->stash, rows[i], nzc, cscr[0], (PetscScalar *)sscr, PETSC_FALSE));
1572651b1cf9SStefano Zampini         }
1573c69f721fSFande Kong         /* local values */
1574651b1cf9SStefano Zampini         else
1575651b1cf9SStefano Zampini           PetscCallExternal(HYPRE_IJMatrixSetValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr);
1576d975228cSstefano_zampini       }
1577d975228cSstefano_zampini       vals += nc;
1578d975228cSstefano_zampini     }
1579d975228cSstefano_zampini   }
1580c69f721fSFande Kong 
15819566063dSJacob Faibussowitsch   PetscCall(MatRestoreArray_HYPRE(A, &array));
15823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1583d975228cSstefano_zampini }
1584d975228cSstefano_zampini 
1585d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRESetPreallocation_HYPRE(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[])
1586d71ae5a4SJacob Faibussowitsch {
1587d975228cSstefano_zampini   Mat_HYPRE  *hA = (Mat_HYPRE *)A->data;
15887d968826Sstefano_zampini   HYPRE_Int  *hdnnz, *honnz;
158906a29025Sstefano_zampini   PetscInt    i, rs, re, cs, ce, bs;
1590d975228cSstefano_zampini   PetscMPIInt size;
1591d975228cSstefano_zampini 
1592d975228cSstefano_zampini   PetscFunctionBegin;
15939566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
15949566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
1595d975228cSstefano_zampini   rs = A->rmap->rstart;
1596d975228cSstefano_zampini   re = A->rmap->rend;
1597d975228cSstefano_zampini   cs = A->cmap->rstart;
1598d975228cSstefano_zampini   ce = A->cmap->rend;
1599d975228cSstefano_zampini   if (!hA->ij) {
1600792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rs, re - 1, cs, ce - 1, &hA->ij);
1601792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR);
1602d975228cSstefano_zampini   } else {
16032cf14000SStefano Zampini     HYPRE_BigInt hrs, hre, hcs, hce;
1604792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetLocalRange, hA->ij, &hrs, &hre, &hcs, &hce);
1605aed4548fSBarry Smith     PetscCheck(hre - hrs + 1 == re - rs, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent local rows: IJMatrix [%" PetscHYPRE_BigInt_FMT ",%" PetscHYPRE_BigInt_FMT "), PETSc [%" PetscInt_FMT ",%" PetscInt_FMT ")", hrs, hre + 1, rs, re);
1606aed4548fSBarry Smith     PetscCheck(hce - hcs + 1 == ce - cs, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Inconsistent local cols: IJMatrix [%" PetscHYPRE_BigInt_FMT ",%" PetscHYPRE_BigInt_FMT "), PETSc [%" PetscInt_FMT ",%" PetscInt_FMT ")", hcs, hce + 1, cs, ce);
1607d975228cSstefano_zampini   }
1608*06977982Sstefanozampini   PetscCall(MatHYPRE_DestroyCOOMat(A));
16099566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(A, &bs));
161006a29025Sstefano_zampini   if (dnz == PETSC_DEFAULT || dnz == PETSC_DECIDE) dnz = 10 * bs;
161106a29025Sstefano_zampini   if (onz == PETSC_DEFAULT || onz == PETSC_DECIDE) onz = 10 * bs;
161206a29025Sstefano_zampini 
1613d975228cSstefano_zampini   if (!dnnz) {
16149566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->rmap->n, &hdnnz));
1615d975228cSstefano_zampini     for (i = 0; i < A->rmap->n; i++) hdnnz[i] = dnz;
1616d975228cSstefano_zampini   } else {
16177d968826Sstefano_zampini     hdnnz = (HYPRE_Int *)dnnz;
1618d975228cSstefano_zampini   }
16199566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
1620d975228cSstefano_zampini   if (size > 1) {
1621ddbeb582SStefano Zampini     hypre_AuxParCSRMatrix *aux_matrix;
1622d975228cSstefano_zampini     if (!onnz) {
16239566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(A->rmap->n, &honnz));
1624d975228cSstefano_zampini       for (i = 0; i < A->rmap->n; i++) honnz[i] = onz;
162522235d61SPierre Jolivet     } else honnz = (HYPRE_Int *)onnz;
1626ddbeb582SStefano Zampini     /* SetDiagOffdSizes sets hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0, since it seems
1627ddbeb582SStefano Zampini        they assume the user will input the entire row values, properly sorted
1628336664bdSPierre Jolivet        In PETSc, we don't make such an assumption and set this flag to 1,
1629336664bdSPierre Jolivet        unless the option MAT_SORTED_FULL is set to true.
1630ddbeb582SStefano Zampini        Also, to avoid possible memory leaks, we destroy and recreate the translator
1631ddbeb582SStefano Zampini        This has to be done here, as HYPRE_IJMatrixInitialize will properly initialize
1632ddbeb582SStefano Zampini        the IJ matrix for us */
1633ddbeb582SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
1634ddbeb582SStefano Zampini     hypre_AuxParCSRMatrixDestroy(aux_matrix);
1635ddbeb582SStefano Zampini     hypre_IJMatrixTranslator(hA->ij) = NULL;
1636792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, hA->ij, hdnnz, honnz);
1637ddbeb582SStefano Zampini     aux_matrix                               = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
1638651b1cf9SStefano Zampini     hypre_AuxParCSRMatrixNeedAux(aux_matrix) = !A->sortedfull;
1639d975228cSstefano_zampini   } else {
1640d975228cSstefano_zampini     honnz = NULL;
1641792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetRowSizes, hA->ij, hdnnz);
1642d975228cSstefano_zampini   }
1643ddbeb582SStefano Zampini 
1644af1cf968SStefano Zampini   /* reset assembled flag and call the initialize method */
1645af1cf968SStefano Zampini   hypre_IJMatrixAssembleFlag(hA->ij) = 0;
16466ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
1647792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij);
16486ea7df73SStefano Zampini #else
1649792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize_v2, hA->ij, HYPRE_MEMORY_HOST);
16506ea7df73SStefano Zampini #endif
165148a46eb9SPierre Jolivet   if (!dnnz) PetscCall(PetscFree(hdnnz));
165248a46eb9SPierre Jolivet   if (!onnz && honnz) PetscCall(PetscFree(honnz));
1653af1cf968SStefano Zampini   /* Match AIJ logic */
165406a29025Sstefano_zampini   A->preallocated = PETSC_TRUE;
1655af1cf968SStefano Zampini   A->assembled    = PETSC_FALSE;
16563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1657d975228cSstefano_zampini }
1658d975228cSstefano_zampini 
1659d975228cSstefano_zampini /*@C
1660d975228cSstefano_zampini    MatHYPRESetPreallocation - Preallocates memory for a sparse parallel matrix in HYPRE IJ format
1661d975228cSstefano_zampini 
1662c3339decSBarry Smith    Collective
1663d975228cSstefano_zampini 
1664d975228cSstefano_zampini    Input Parameters:
1665d975228cSstefano_zampini +  A - the matrix
1666d975228cSstefano_zampini .  dnz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1667d975228cSstefano_zampini           (same value is used for all local rows)
1668d975228cSstefano_zampini .  dnnz - array containing the number of nonzeros in the various rows of the
1669d975228cSstefano_zampini           DIAGONAL portion of the local submatrix (possibly different for each row)
16702ef1f0ffSBarry Smith           or `NULL` (`PETSC_NULL_INTEGER` in Fortran), if `d_nz` is used to specify the nonzero structure.
16712ef1f0ffSBarry Smith           The size of this array is equal to the number of local rows, i.e `m`.
1672d975228cSstefano_zampini           For matrices that will be factored, you must leave room for (and set)
1673d975228cSstefano_zampini           the diagonal entry even if it is zero.
1674d975228cSstefano_zampini .  onz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1675d975228cSstefano_zampini           submatrix (same value is used for all local rows).
1676d975228cSstefano_zampini -  onnz - array containing the number of nonzeros in the various rows of the
1677d975228cSstefano_zampini           OFF-DIAGONAL portion of the local submatrix (possibly different for
16782ef1f0ffSBarry Smith           each row) or `NULL` (`PETSC_NULL_INTEGER` in Fortran), if `o_nz` is used to specify the nonzero
1679d975228cSstefano_zampini           structure. The size of this array is equal to the number
16802ef1f0ffSBarry Smith           of local rows, i.e `m`.
1681d975228cSstefano_zampini 
16822fe279fdSBarry Smith    Level: intermediate
16832fe279fdSBarry Smith 
168411a5261eSBarry Smith    Note:
16852ef1f0ffSBarry Smith     If the *nnz parameter is given then the *nz parameter is ignored; for sequential matrices, `onz` and `onnz` are ignored.
1686d975228cSstefano_zampini 
16871cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatMPIAIJSetPreallocation()`, `MATHYPRE`, `MATAIJ`
1688d975228cSstefano_zampini @*/
1689d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHYPRESetPreallocation(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[])
1690d71ae5a4SJacob Faibussowitsch {
1691d975228cSstefano_zampini   PetscFunctionBegin;
1692d975228cSstefano_zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1693d975228cSstefano_zampini   PetscValidType(A, 1);
1694cac4c232SBarry Smith   PetscTryMethod(A, "MatHYPRESetPreallocation_C", (Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]), (A, dnz, dnnz, onz, onnz));
16953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1696d975228cSstefano_zampini }
1697d975228cSstefano_zampini 
169820f4b53cSBarry Smith /*@C
16992ef1f0ffSBarry Smith    MatCreateFromParCSR - Creates a `Mat` from a `hypre_ParCSRMatrix`
1700225daaf8SStefano Zampini 
1701225daaf8SStefano Zampini    Collective
1702225daaf8SStefano Zampini 
1703225daaf8SStefano Zampini    Input Parameters:
17042ef1f0ffSBarry Smith +  parcsr   - the pointer to the `hypre_ParCSRMatrix`
17052ef1f0ffSBarry Smith .  mtype    - matrix type to be created. Currently `MATAIJ`, `MATIS` and `MATHYPRE` are supported.
170620f4b53cSBarry Smith -  copymode - PETSc copying options, see  `PetscCopyMode`
1707225daaf8SStefano Zampini 
1708225daaf8SStefano Zampini    Output Parameter:
1709225daaf8SStefano Zampini .  A  - the matrix
1710225daaf8SStefano Zampini 
1711225daaf8SStefano Zampini    Level: intermediate
1712225daaf8SStefano Zampini 
17131cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatHYPRE`, `PetscCopyMode`
171420f4b53cSBarry Smith @*/
1715d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreateFromParCSR(hypre_ParCSRMatrix *parcsr, MatType mtype, PetscCopyMode copymode, Mat *A)
1716d71ae5a4SJacob Faibussowitsch {
1717225daaf8SStefano Zampini   Mat        T;
1718978814f1SStefano Zampini   Mat_HYPRE *hA;
1719978814f1SStefano Zampini   MPI_Comm   comm;
1720978814f1SStefano Zampini   PetscInt   rstart, rend, cstart, cend, M, N;
1721d248a85cSRichard Tran Mills   PetscBool  isseqaij, isseqaijmkl, ismpiaij, isaij, ishyp, isis;
1722978814f1SStefano Zampini 
1723978814f1SStefano Zampini   PetscFunctionBegin;
1724978814f1SStefano Zampini   comm = hypre_ParCSRMatrixComm(parcsr);
17259566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQAIJ, &isseqaij));
17269566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQAIJMKL, &isseqaijmkl));
17279566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPIAIJ, &ismpiaij));
17289566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATAIJ, &isaij));
17299566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATHYPRE, &ishyp));
17309566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATIS, &isis));
1731d248a85cSRichard Tran Mills   isaij = (PetscBool)(isseqaij || isseqaijmkl || ismpiaij || isaij);
17326ea7df73SStefano Zampini   /* TODO */
1733aed4548fSBarry Smith   PetscCheck(isaij || ishyp || isis, comm, PETSC_ERR_SUP, "Unsupported MatType %s! Supported types are %s, %s, %s, %s, %s, and %s", mtype, MATAIJ, MATSEQAIJ, MATSEQAIJMKL, MATMPIAIJ, MATIS, MATHYPRE);
1734978814f1SStefano Zampini   /* access ParCSRMatrix */
1735978814f1SStefano Zampini   rstart = hypre_ParCSRMatrixFirstRowIndex(parcsr);
1736978814f1SStefano Zampini   rend   = hypre_ParCSRMatrixLastRowIndex(parcsr);
1737978814f1SStefano Zampini   cstart = hypre_ParCSRMatrixFirstColDiag(parcsr);
1738978814f1SStefano Zampini   cend   = hypre_ParCSRMatrixLastColDiag(parcsr);
1739978814f1SStefano Zampini   M      = hypre_ParCSRMatrixGlobalNumRows(parcsr);
1740978814f1SStefano Zampini   N      = hypre_ParCSRMatrixGlobalNumCols(parcsr);
1741978814f1SStefano Zampini 
1742fa92c42cSstefano_zampini   /* fix for empty local rows/columns */
1743fa92c42cSstefano_zampini   if (rend < rstart) rend = rstart;
1744fa92c42cSstefano_zampini   if (cend < cstart) cend = cstart;
1745fa92c42cSstefano_zampini 
1746e6471dc9SStefano Zampini   /* PETSc convention */
1747e6471dc9SStefano Zampini   rend++;
1748e6471dc9SStefano Zampini   cend++;
1749e6471dc9SStefano Zampini   rend = PetscMin(rend, M);
1750e6471dc9SStefano Zampini   cend = PetscMin(cend, N);
1751e6471dc9SStefano Zampini 
1752978814f1SStefano Zampini   /* create PETSc matrix with MatHYPRE */
17539566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, &T));
17549566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(T, rend - rstart, cend - cstart, M, N));
17559566063dSJacob Faibussowitsch   PetscCall(MatSetType(T, MATHYPRE));
1756225daaf8SStefano Zampini   hA = (Mat_HYPRE *)(T->data);
1757978814f1SStefano Zampini 
1758978814f1SStefano Zampini   /* create HYPRE_IJMatrix */
1759792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rstart, rend - 1, cstart, cend - 1, &hA->ij);
1760792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR);
176145b8d346SStefano Zampini 
176245b8d346SStefano Zampini   /* create new ParCSR object if needed */
176345b8d346SStefano Zampini   if (ishyp && copymode == PETSC_COPY_VALUES) {
176445b8d346SStefano Zampini     hypre_ParCSRMatrix *new_parcsr;
17656ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0)
176645b8d346SStefano Zampini     hypre_CSRMatrix *hdiag, *hoffd, *ndiag, *noffd;
176745b8d346SStefano Zampini 
17680e6427aaSSatish Balay     new_parcsr = hypre_ParCSRMatrixClone(parcsr, 0);
176945b8d346SStefano Zampini     hdiag      = hypre_ParCSRMatrixDiag(parcsr);
177045b8d346SStefano Zampini     hoffd      = hypre_ParCSRMatrixOffd(parcsr);
177145b8d346SStefano Zampini     ndiag      = hypre_ParCSRMatrixDiag(new_parcsr);
177245b8d346SStefano Zampini     noffd      = hypre_ParCSRMatrixOffd(new_parcsr);
17739566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hypre_CSRMatrixData(ndiag), hypre_CSRMatrixData(hdiag), hypre_CSRMatrixNumNonzeros(hdiag)));
17749566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hypre_CSRMatrixData(noffd), hypre_CSRMatrixData(hoffd), hypre_CSRMatrixNumNonzeros(hoffd)));
17756ea7df73SStefano Zampini #else
17766ea7df73SStefano Zampini     new_parcsr = hypre_ParCSRMatrixClone(parcsr, 1);
17776ea7df73SStefano Zampini #endif
177845b8d346SStefano Zampini     parcsr   = new_parcsr;
177945b8d346SStefano Zampini     copymode = PETSC_OWN_POINTER;
178045b8d346SStefano Zampini   }
1781978814f1SStefano Zampini 
1782978814f1SStefano Zampini   /* set ParCSR object */
1783978814f1SStefano Zampini   hypre_IJMatrixObject(hA->ij) = parcsr;
17844ec6421dSstefano_zampini   T->preallocated              = PETSC_TRUE;
1785978814f1SStefano Zampini 
1786978814f1SStefano Zampini   /* set assembled flag */
1787978814f1SStefano Zampini   hypre_IJMatrixAssembleFlag(hA->ij) = 1;
17886ea7df73SStefano Zampini #if 0
1789792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize,hA->ij);
17906ea7df73SStefano Zampini #endif
1791225daaf8SStefano Zampini   if (ishyp) {
17926d2a658fSstefano_zampini     PetscMPIInt myid = 0;
17936d2a658fSstefano_zampini 
17946d2a658fSstefano_zampini     /* make sure we always have row_starts and col_starts available */
179548a46eb9SPierre Jolivet     if (HYPRE_AssumedPartitionCheck()) PetscCallMPI(MPI_Comm_rank(comm, &myid));
1796a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
17976d2a658fSstefano_zampini     if (!hypre_ParCSRMatrixOwnsColStarts(parcsr)) {
17986d2a658fSstefano_zampini       PetscLayout map;
17996d2a658fSstefano_zampini 
18009566063dSJacob Faibussowitsch       PetscCall(MatGetLayouts(T, NULL, &map));
18019566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetUp(map));
18022cf14000SStefano Zampini       hypre_ParCSRMatrixColStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid);
18036d2a658fSstefano_zampini     }
18046d2a658fSstefano_zampini     if (!hypre_ParCSRMatrixOwnsRowStarts(parcsr)) {
18056d2a658fSstefano_zampini       PetscLayout map;
18066d2a658fSstefano_zampini 
18079566063dSJacob Faibussowitsch       PetscCall(MatGetLayouts(T, &map, NULL));
18089566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetUp(map));
18092cf14000SStefano Zampini       hypre_ParCSRMatrixRowStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid);
18106d2a658fSstefano_zampini     }
1811a1d2239cSSatish Balay #endif
1812978814f1SStefano Zampini     /* prevent from freeing the pointer */
1813978814f1SStefano Zampini     if (copymode == PETSC_USE_POINTER) hA->inner_free = PETSC_FALSE;
1814225daaf8SStefano Zampini     *A = T;
18159566063dSJacob Faibussowitsch     PetscCall(MatSetOption(*A, MAT_SORTED_FULL, PETSC_TRUE));
18169566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(*A, MAT_FINAL_ASSEMBLY));
18179566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(*A, MAT_FINAL_ASSEMBLY));
1818bb4689ddSStefano Zampini   } else if (isaij) {
1819bb4689ddSStefano Zampini     if (copymode != PETSC_OWN_POINTER) {
1820225daaf8SStefano Zampini       /* prevent from freeing the pointer */
1821225daaf8SStefano Zampini       hA->inner_free = PETSC_FALSE;
18229566063dSJacob Faibussowitsch       PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INITIAL_MATRIX, A));
18239566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&T));
1824225daaf8SStefano Zampini     } else { /* AIJ return type with PETSC_OWN_POINTER */
18259566063dSJacob Faibussowitsch       PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INPLACE_MATRIX, &T));
1826225daaf8SStefano Zampini       *A = T;
1827225daaf8SStefano Zampini     }
1828bb4689ddSStefano Zampini   } else if (isis) {
18299566063dSJacob Faibussowitsch     PetscCall(MatConvert_HYPRE_IS(T, MATIS, MAT_INITIAL_MATRIX, A));
18308cfe8d00SStefano Zampini     if (copymode != PETSC_OWN_POINTER) hA->inner_free = PETSC_FALSE;
18319566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&T));
1832bb4689ddSStefano Zampini   }
18333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1834978814f1SStefano Zampini }
1835978814f1SStefano Zampini 
1836d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPREGetParCSR_HYPRE(Mat A, hypre_ParCSRMatrix **parcsr)
1837d71ae5a4SJacob Faibussowitsch {
1838dd9c0a25Sstefano_zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1839dd9c0a25Sstefano_zampini   HYPRE_Int  type;
1840dd9c0a25Sstefano_zampini 
1841dd9c0a25Sstefano_zampini   PetscFunctionBegin;
184228b400f6SJacob Faibussowitsch   PetscCheck(hA->ij, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "HYPRE_IJMatrix not present");
1843792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
184408401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "HYPRE_IJMatrix is not of type HYPRE_PARCSR");
1845792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)parcsr);
18463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1847dd9c0a25Sstefano_zampini }
1848dd9c0a25Sstefano_zampini 
184920f4b53cSBarry Smith /*@C
1850dd9c0a25Sstefano_zampini    MatHYPREGetParCSR - Gets the pointer to the ParCSR matrix
1851dd9c0a25Sstefano_zampini 
18522ef1f0ffSBarry Smith    Not Collective
1853dd9c0a25Sstefano_zampini 
185420f4b53cSBarry Smith    Input Parameter:
185520f4b53cSBarry Smith .  A  - the `MATHYPRE` object
1856dd9c0a25Sstefano_zampini 
1857dd9c0a25Sstefano_zampini    Output Parameter:
18582ef1f0ffSBarry Smith .  parcsr  - the pointer to the `hypre_ParCSRMatrix`
1859dd9c0a25Sstefano_zampini 
1860dd9c0a25Sstefano_zampini    Level: intermediate
1861dd9c0a25Sstefano_zampini 
18621cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatHYPRE`, `PetscCopyMode`
186320f4b53cSBarry Smith @*/
1864d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHYPREGetParCSR(Mat A, hypre_ParCSRMatrix **parcsr)
1865d71ae5a4SJacob Faibussowitsch {
1866dd9c0a25Sstefano_zampini   PetscFunctionBegin;
1867dd9c0a25Sstefano_zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1868dd9c0a25Sstefano_zampini   PetscValidType(A, 1);
1869cac4c232SBarry Smith   PetscUseMethod(A, "MatHYPREGetParCSR_C", (Mat, hypre_ParCSRMatrix **), (A, parcsr));
18703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1871dd9c0a25Sstefano_zampini }
1872dd9c0a25Sstefano_zampini 
1873d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_HYPRE(Mat A, PetscBool *missing, PetscInt *dd)
1874d71ae5a4SJacob Faibussowitsch {
187568ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
187668ec7858SStefano Zampini   hypre_CSRMatrix    *ha;
187768ec7858SStefano Zampini   PetscInt            rst;
187868ec7858SStefano Zampini 
187968ec7858SStefano Zampini   PetscFunctionBegin;
188008401ef6SPierre Jolivet   PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented with non-square diagonal blocks");
18819566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &rst, NULL));
18829566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
188368ec7858SStefano Zampini   if (missing) *missing = PETSC_FALSE;
188468ec7858SStefano Zampini   if (dd) *dd = -1;
188568ec7858SStefano Zampini   ha = hypre_ParCSRMatrixDiag(parcsr);
188668ec7858SStefano Zampini   if (ha) {
188768299464SStefano Zampini     PetscInt   size, i;
188868299464SStefano Zampini     HYPRE_Int *ii, *jj;
188968ec7858SStefano Zampini 
189068ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
189168ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
189268ec7858SStefano Zampini     jj   = hypre_CSRMatrixJ(ha);
189368ec7858SStefano Zampini     for (i = 0; i < size; i++) {
189468ec7858SStefano Zampini       PetscInt  j;
189568ec7858SStefano Zampini       PetscBool found = PETSC_FALSE;
189668ec7858SStefano Zampini 
18979371c9d4SSatish Balay       for (j = ii[i]; j < ii[i + 1] && !found; j++) found = (jj[j] == i) ? PETSC_TRUE : PETSC_FALSE;
189868ec7858SStefano Zampini 
189968ec7858SStefano Zampini       if (!found) {
19003ba16761SJacob Faibussowitsch         PetscCall(PetscInfo(A, "Matrix is missing local diagonal entry %" PetscInt_FMT "\n", i));
190168ec7858SStefano Zampini         if (missing) *missing = PETSC_TRUE;
190268ec7858SStefano Zampini         if (dd) *dd = i + rst;
19033ba16761SJacob Faibussowitsch         PetscFunctionReturn(PETSC_SUCCESS);
190468ec7858SStefano Zampini       }
190568ec7858SStefano Zampini     }
190668ec7858SStefano Zampini     if (!size) {
19073ba16761SJacob Faibussowitsch       PetscCall(PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n"));
190868ec7858SStefano Zampini       if (missing) *missing = PETSC_TRUE;
190968ec7858SStefano Zampini       if (dd) *dd = rst;
191068ec7858SStefano Zampini     }
191168ec7858SStefano Zampini   } else {
19123ba16761SJacob Faibussowitsch     PetscCall(PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n"));
191368ec7858SStefano Zampini     if (missing) *missing = PETSC_TRUE;
191468ec7858SStefano Zampini     if (dd) *dd = rst;
191568ec7858SStefano Zampini   }
19163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
191768ec7858SStefano Zampini }
191868ec7858SStefano Zampini 
1919d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatScale_HYPRE(Mat A, PetscScalar s)
1920d71ae5a4SJacob Faibussowitsch {
192168ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
19226ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
192368ec7858SStefano Zampini   hypre_CSRMatrix *ha;
19246ea7df73SStefano Zampini #endif
192539accc25SStefano Zampini   HYPRE_Complex hs;
192668ec7858SStefano Zampini 
192768ec7858SStefano Zampini   PetscFunctionBegin;
19289566063dSJacob Faibussowitsch   PetscCall(PetscHYPREScalarCast(s, &hs));
19299566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
19306ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 19, 0)
1931792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixScale, parcsr, hs);
19326ea7df73SStefano Zampini #else /* diagonal part */
193368ec7858SStefano Zampini   ha = hypre_ParCSRMatrixDiag(parcsr);
193468ec7858SStefano Zampini   if (ha) {
193568299464SStefano Zampini     PetscInt       size, i;
193668299464SStefano Zampini     HYPRE_Int     *ii;
193739accc25SStefano Zampini     HYPRE_Complex *a;
193868ec7858SStefano Zampini 
193968ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
194068ec7858SStefano Zampini     a    = hypre_CSRMatrixData(ha);
194168ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
194239accc25SStefano Zampini     for (i = 0; i < ii[size]; i++) a[i] *= hs;
194368ec7858SStefano Zampini   }
194468ec7858SStefano Zampini   /* offdiagonal part */
194568ec7858SStefano Zampini   ha = hypre_ParCSRMatrixOffd(parcsr);
194668ec7858SStefano Zampini   if (ha) {
194768299464SStefano Zampini     PetscInt       size, i;
194868299464SStefano Zampini     HYPRE_Int     *ii;
194939accc25SStefano Zampini     HYPRE_Complex *a;
195068ec7858SStefano Zampini 
195168ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
195268ec7858SStefano Zampini     a    = hypre_CSRMatrixData(ha);
195368ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
195439accc25SStefano Zampini     for (i = 0; i < ii[size]; i++) a[i] *= hs;
195568ec7858SStefano Zampini   }
19566ea7df73SStefano Zampini #endif
19573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
195868ec7858SStefano Zampini }
195968ec7858SStefano Zampini 
1960d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_HYPRE(Mat A, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
1961d71ae5a4SJacob Faibussowitsch {
196268ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
196368299464SStefano Zampini   HYPRE_Int          *lrows;
196468299464SStefano Zampini   PetscInt            rst, ren, i;
196568ec7858SStefano Zampini 
196668ec7858SStefano Zampini   PetscFunctionBegin;
196708401ef6SPierre Jolivet   PetscCheck(!x && !b, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "To be implemented");
19689566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
19699566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numRows, &lrows));
19709566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &rst, &ren));
197168ec7858SStefano Zampini   for (i = 0; i < numRows; i++) {
19727a46b595SBarry Smith     PetscCheck(rows[i] >= rst && rows[i] < ren, PETSC_COMM_SELF, PETSC_ERR_SUP, "Non-local rows not yet supported");
197368ec7858SStefano Zampini     lrows[i] = rows[i] - rst;
197468ec7858SStefano Zampini   }
1975792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixEliminateRowsCols, parcsr, numRows, lrows);
19769566063dSJacob Faibussowitsch   PetscCall(PetscFree(lrows));
19773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
197868ec7858SStefano Zampini }
197968ec7858SStefano Zampini 
1980d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPRE_CSRMatrix(hypre_CSRMatrix *ha)
1981d71ae5a4SJacob Faibussowitsch {
1982c69f721fSFande Kong   PetscFunctionBegin;
1983c69f721fSFande Kong   if (ha) {
1984c69f721fSFande Kong     HYPRE_Int     *ii, size;
1985c69f721fSFande Kong     HYPRE_Complex *a;
1986c69f721fSFande Kong 
1987c69f721fSFande Kong     size = hypre_CSRMatrixNumRows(ha);
1988c69f721fSFande Kong     a    = hypre_CSRMatrixData(ha);
1989c69f721fSFande Kong     ii   = hypre_CSRMatrixI(ha);
1990c69f721fSFande Kong 
19919566063dSJacob Faibussowitsch     if (a) PetscCall(PetscArrayzero(a, ii[size]));
1992c69f721fSFande Kong   }
19933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1994c69f721fSFande Kong }
1995c69f721fSFande Kong 
1996d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroEntries_HYPRE(Mat A)
1997d71ae5a4SJacob Faibussowitsch {
19986ea7df73SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
19996ea7df73SStefano Zampini 
20006ea7df73SStefano Zampini   PetscFunctionBegin;
20016ea7df73SStefano Zampini   if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(hA->ij)) {
2002792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetConstantValues, hA->ij, 0.0);
20036ea7df73SStefano Zampini   } else {
2004c69f721fSFande Kong     hypre_ParCSRMatrix *parcsr;
2005c69f721fSFande Kong 
20069566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
20079566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr)));
20089566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr)));
20096ea7df73SStefano Zampini   }
20103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2011c69f721fSFande Kong }
2012c69f721fSFande Kong 
2013d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_HYPRE_CSRMatrix(hypre_CSRMatrix *hA, PetscInt N, const PetscInt rows[], HYPRE_Complex diag)
2014d71ae5a4SJacob Faibussowitsch {
201539accc25SStefano Zampini   PetscInt       ii;
201639accc25SStefano Zampini   HYPRE_Int     *i, *j;
201739accc25SStefano Zampini   HYPRE_Complex *a;
2018c69f721fSFande Kong 
2019c69f721fSFande Kong   PetscFunctionBegin;
20203ba16761SJacob Faibussowitsch   if (!hA) PetscFunctionReturn(PETSC_SUCCESS);
2021c69f721fSFande Kong 
202239accc25SStefano Zampini   i = hypre_CSRMatrixI(hA);
202339accc25SStefano Zampini   j = hypre_CSRMatrixJ(hA);
2024c69f721fSFande Kong   a = hypre_CSRMatrixData(hA);
2025c69f721fSFande Kong 
2026c69f721fSFande Kong   for (ii = 0; ii < N; ii++) {
202739accc25SStefano Zampini     HYPRE_Int jj, ibeg, iend, irow;
202839accc25SStefano Zampini 
2029c69f721fSFande Kong     irow = rows[ii];
2030c69f721fSFande Kong     ibeg = i[irow];
2031c69f721fSFande Kong     iend = i[irow + 1];
2032c69f721fSFande Kong     for (jj = ibeg; jj < iend; jj++)
2033c69f721fSFande Kong       if (j[jj] == irow) a[jj] = diag;
2034c69f721fSFande Kong       else a[jj] = 0.0;
2035c69f721fSFande Kong   }
20363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2037c69f721fSFande Kong }
2038c69f721fSFande Kong 
2039d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_HYPRE(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
2040d71ae5a4SJacob Faibussowitsch {
2041c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
2042c69f721fSFande Kong   PetscInt           *lrows, len;
204339accc25SStefano Zampini   HYPRE_Complex       hdiag;
2044c69f721fSFande Kong 
2045c69f721fSFande Kong   PetscFunctionBegin;
204608401ef6SPierre Jolivet   PetscCheck(!x && !b, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Does not support to modify the solution and the right hand size");
20479566063dSJacob Faibussowitsch   PetscCall(PetscHYPREScalarCast(diag, &hdiag));
2048c69f721fSFande Kong   /* retrieve the internal matrix */
20499566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
2050c69f721fSFande Kong   /* get locally owned rows */
20519566063dSJacob Faibussowitsch   PetscCall(MatZeroRowsMapLocal_Private(A, N, rows, &len, &lrows));
2052c69f721fSFande Kong   /* zero diagonal part */
20539566063dSJacob Faibussowitsch   PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr), len, lrows, hdiag));
2054c69f721fSFande Kong   /* zero off-diagonal part */
20559566063dSJacob Faibussowitsch   PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr), len, lrows, 0.0));
2056c69f721fSFande Kong 
20579566063dSJacob Faibussowitsch   PetscCall(PetscFree(lrows));
20583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2059c69f721fSFande Kong }
2060c69f721fSFande Kong 
2061d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_HYPRE(Mat mat, MatAssemblyType mode)
2062d71ae5a4SJacob Faibussowitsch {
2063c69f721fSFande Kong   PetscFunctionBegin;
20643ba16761SJacob Faibussowitsch   if (mat->nooffprocentries) PetscFunctionReturn(PETSC_SUCCESS);
2065c69f721fSFande Kong 
20669566063dSJacob Faibussowitsch   PetscCall(MatStashScatterBegin_Private(mat, &mat->stash, mat->rmap->range));
20673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2068c69f721fSFande Kong }
2069c69f721fSFande Kong 
2070d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
2071d71ae5a4SJacob Faibussowitsch {
2072c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
20732cf14000SStefano Zampini   HYPRE_Int           hnz;
2074c69f721fSFande Kong 
2075c69f721fSFande Kong   PetscFunctionBegin;
2076c69f721fSFande Kong   /* retrieve the internal matrix */
20779566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
2078c69f721fSFande Kong   /* call HYPRE API */
2079792fecdfSBarry Smith   PetscCallExternal(HYPRE_ParCSRMatrixGetRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v);
20802cf14000SStefano Zampini   if (nz) *nz = (PetscInt)hnz;
20813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2082c69f721fSFande Kong }
2083c69f721fSFande Kong 
2084d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
2085d71ae5a4SJacob Faibussowitsch {
2086c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
20872cf14000SStefano Zampini   HYPRE_Int           hnz;
2088c69f721fSFande Kong 
2089c69f721fSFande Kong   PetscFunctionBegin;
2090c69f721fSFande Kong   /* retrieve the internal matrix */
20919566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
2092c69f721fSFande Kong   /* call HYPRE API */
20932cf14000SStefano Zampini   hnz = nz ? (HYPRE_Int)(*nz) : 0;
2094792fecdfSBarry Smith   PetscCallExternal(HYPRE_ParCSRMatrixRestoreRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v);
20953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2096c69f721fSFande Kong }
2097c69f721fSFande Kong 
2098d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetValues_HYPRE(Mat A, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2099d71ae5a4SJacob Faibussowitsch {
210045b8d346SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
2101c69f721fSFande Kong   PetscInt   i;
21021d4906efSStefano Zampini 
2103c69f721fSFande Kong   PetscFunctionBegin;
21043ba16761SJacob Faibussowitsch   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2105c69f721fSFande Kong   /* Ignore negative row indices
2106c69f721fSFande Kong    * And negative column indices should be automatically ignored in hypre
2107c69f721fSFande Kong    * */
21082cf14000SStefano Zampini   for (i = 0; i < m; i++) {
21092cf14000SStefano Zampini     if (idxm[i] >= 0) {
21102cf14000SStefano Zampini       HYPRE_Int hn = (HYPRE_Int)n;
2111792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetValues, hA->ij, 1, &hn, (HYPRE_BigInt *)&idxm[i], (HYPRE_BigInt *)idxn, (HYPRE_Complex *)(v + i * n));
21122cf14000SStefano Zampini     }
21132cf14000SStefano Zampini   }
21143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2115c69f721fSFande Kong }
2116c69f721fSFande Kong 
2117d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_HYPRE(Mat A, MatOption op, PetscBool flg)
2118d71ae5a4SJacob Faibussowitsch {
2119ddbeb582SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
2120ddbeb582SStefano Zampini 
2121ddbeb582SStefano Zampini   PetscFunctionBegin;
2122c6698e78SStefano Zampini   switch (op) {
2123ddbeb582SStefano Zampini   case MAT_NO_OFF_PROC_ENTRIES:
212448a46eb9SPierre Jolivet     if (flg) PetscCallExternal(HYPRE_IJMatrixSetMaxOffProcElmts, hA->ij, 0);
2125ddbeb582SStefano Zampini     break;
2126651b1cf9SStefano Zampini   case MAT_IGNORE_OFF_PROC_ENTRIES:
2127651b1cf9SStefano Zampini     hA->donotstash = flg;
2128d71ae5a4SJacob Faibussowitsch     break;
2129d71ae5a4SJacob Faibussowitsch   default:
2130d71ae5a4SJacob Faibussowitsch     break;
2131ddbeb582SStefano Zampini   }
21323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2133ddbeb582SStefano Zampini }
2134c69f721fSFande Kong 
2135d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_HYPRE(Mat A, PetscViewer view)
2136d71ae5a4SJacob Faibussowitsch {
213745b8d346SStefano Zampini   PetscViewerFormat format;
213845b8d346SStefano Zampini 
213945b8d346SStefano Zampini   PetscFunctionBegin;
21409566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(view, &format));
21413ba16761SJacob Faibussowitsch   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(PETSC_SUCCESS);
214245b8d346SStefano Zampini   if (format != PETSC_VIEWER_NATIVE) {
21436ea7df73SStefano Zampini     Mat                 B;
21446ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
21456ea7df73SStefano Zampini     PetscErrorCode (*mview)(Mat, PetscViewer) = NULL;
21466ea7df73SStefano Zampini 
21479566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
21489566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(parcsr, MATAIJ, PETSC_USE_POINTER, &B));
21499566063dSJacob Faibussowitsch     PetscCall(MatGetOperation(B, MATOP_VIEW, (void (**)(void)) & mview));
215028b400f6SJacob Faibussowitsch     PetscCheck(mview, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Missing view operation");
21519566063dSJacob Faibussowitsch     PetscCall((*mview)(B, view));
21529566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
215345b8d346SStefano Zampini   } else {
215445b8d346SStefano Zampini     Mat_HYPRE  *hA = (Mat_HYPRE *)A->data;
215545b8d346SStefano Zampini     PetscMPIInt size;
215645b8d346SStefano Zampini     PetscBool   isascii;
215745b8d346SStefano Zampini     const char *filename;
215845b8d346SStefano Zampini 
215945b8d346SStefano Zampini     /* HYPRE uses only text files */
21609566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERASCII, &isascii));
216128b400f6SJacob Faibussowitsch     PetscCheck(isascii, PetscObjectComm((PetscObject)view), PETSC_ERR_SUP, "PetscViewerType %s: native HYPRE format needs PETSCVIEWERASCII", ((PetscObject)view)->type_name);
21629566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileGetName(view, &filename));
2163792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixPrint, hA->ij, filename);
21649566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(hA->comm, &size));
216545b8d346SStefano Zampini     if (size > 1) {
21669566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(view, "Matrix files: %s.%05d ... %s.%05d\n", filename, 0, filename, size - 1));
216745b8d346SStefano Zampini     } else {
21689566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(view, "Matrix file: %s.%05d\n", filename, 0));
216945b8d346SStefano Zampini     }
217045b8d346SStefano Zampini   }
21713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
217245b8d346SStefano Zampini }
217345b8d346SStefano Zampini 
2174d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCopy_HYPRE(Mat A, Mat B, MatStructure str)
2175d71ae5a4SJacob Faibussowitsch {
2176465edc17SStefano Zampini   hypre_ParCSRMatrix *acsr, *bcsr;
2177465edc17SStefano Zampini 
2178465edc17SStefano Zampini   PetscFunctionBegin;
2179465edc17SStefano Zampini   if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) {
21809566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &acsr));
21819566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(B, &bcsr));
2182792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixCopy, acsr, bcsr, 1);
21839566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_SORTED_FULL, PETSC_TRUE)); /* "perfect" preallocation, so no need for hypre_AuxParCSRMatrixNeedAux */
21849566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
21859566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
2186465edc17SStefano Zampini   } else {
21879566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
2188465edc17SStefano Zampini   }
21893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2190465edc17SStefano Zampini }
2191465edc17SStefano Zampini 
2192d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_HYPRE(Mat A, Vec d)
2193d71ae5a4SJacob Faibussowitsch {
21946305df00SStefano Zampini   hypre_ParCSRMatrix *parcsr;
21956305df00SStefano Zampini   hypre_CSRMatrix    *dmat;
219639accc25SStefano Zampini   HYPRE_Complex      *a;
21976305df00SStefano Zampini   PetscBool           cong;
21986305df00SStefano Zampini 
21996305df00SStefano Zampini   PetscFunctionBegin;
22009566063dSJacob Faibussowitsch   PetscCall(MatHasCongruentLayouts(A, &cong));
220128b400f6SJacob Faibussowitsch   PetscCheck(cong, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only for square matrices with same local distributions of rows and columns");
22029566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
22036305df00SStefano Zampini   dmat = hypre_ParCSRMatrixDiag(parcsr);
22046305df00SStefano Zampini   if (dmat) {
2205*06977982Sstefanozampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
2206*06977982Sstefanozampini     HYPRE_MemoryLocation mem = hypre_CSRMatrixMemoryLocation(dmat);
2207*06977982Sstefanozampini #else
2208*06977982Sstefanozampini     HYPRE_MemoryLocation mem = HYPRE_MEMORY_HOST;
2209*06977982Sstefanozampini #endif
2210*06977982Sstefanozampini 
2211*06977982Sstefanozampini     if (mem != HYPRE_MEMORY_HOST) PetscCall(VecGetArrayWriteAndMemType(d, (PetscScalar **)&a, NULL));
2212*06977982Sstefanozampini     else PetscCall(VecGetArrayWrite(d, (PetscScalar **)&a));
2213*06977982Sstefanozampini     hypre_CSRMatrixExtractDiagonal(dmat, a, 0);
2214*06977982Sstefanozampini     if (mem != HYPRE_MEMORY_HOST) PetscCall(VecRestoreArrayWriteAndMemType(d, (PetscScalar **)&a));
2215*06977982Sstefanozampini     else PetscCall(VecRestoreArrayWrite(d, (PetscScalar **)&a));
22166305df00SStefano Zampini   }
22173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22186305df00SStefano Zampini }
22196305df00SStefano Zampini 
2220363d496dSStefano Zampini #include <petscblaslapack.h>
2221363d496dSStefano Zampini 
2222d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAXPY_HYPRE(Mat Y, PetscScalar a, Mat X, MatStructure str)
2223d71ae5a4SJacob Faibussowitsch {
2224363d496dSStefano Zampini   PetscFunctionBegin;
22256ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
22266ea7df73SStefano Zampini   {
22276ea7df73SStefano Zampini     Mat                 B;
22286ea7df73SStefano Zampini     hypre_ParCSRMatrix *x, *y, *z;
22296ea7df73SStefano Zampini 
22309566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(Y, &y));
22319566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(X, &x));
2232792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixAdd, 1.0, y, 1.0, x, &z);
22339566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(z, MATHYPRE, PETSC_OWN_POINTER, &B));
22349566063dSJacob Faibussowitsch     PetscCall(MatHeaderMerge(Y, &B));
22356ea7df73SStefano Zampini   }
22366ea7df73SStefano Zampini #else
2237363d496dSStefano Zampini   if (str == SAME_NONZERO_PATTERN) {
2238363d496dSStefano Zampini     hypre_ParCSRMatrix *x, *y;
2239363d496dSStefano Zampini     hypre_CSRMatrix    *xloc, *yloc;
2240363d496dSStefano Zampini     PetscInt            xnnz, ynnz;
224139accc25SStefano Zampini     HYPRE_Complex      *xarr, *yarr;
2242363d496dSStefano Zampini     PetscBLASInt        one = 1, bnz;
2243363d496dSStefano Zampini 
22449566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(Y, &y));
22459566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(X, &x));
2246363d496dSStefano Zampini 
2247363d496dSStefano Zampini     /* diagonal block */
2248363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixDiag(x);
2249363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixDiag(y);
2250363d496dSStefano Zampini     xnnz = 0;
2251363d496dSStefano Zampini     ynnz = 0;
2252363d496dSStefano Zampini     xarr = NULL;
2253363d496dSStefano Zampini     yarr = NULL;
2254363d496dSStefano Zampini     if (xloc) {
225539accc25SStefano Zampini       xarr = hypre_CSRMatrixData(xloc);
2256363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
2257363d496dSStefano Zampini     }
2258363d496dSStefano Zampini     if (yloc) {
225939accc25SStefano Zampini       yarr = hypre_CSRMatrixData(yloc);
2260363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
2261363d496dSStefano Zampini     }
226208401ef6SPierre Jolivet     PetscCheck(xnnz == ynnz, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Different number of nonzeros in diagonal block %" PetscInt_FMT " != %" PetscInt_FMT, xnnz, ynnz);
22639566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(xnnz, &bnz));
2264792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one));
2265363d496dSStefano Zampini 
2266363d496dSStefano Zampini     /* off-diagonal block */
2267363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixOffd(x);
2268363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixOffd(y);
2269363d496dSStefano Zampini     xnnz = 0;
2270363d496dSStefano Zampini     ynnz = 0;
2271363d496dSStefano Zampini     xarr = NULL;
2272363d496dSStefano Zampini     yarr = NULL;
2273363d496dSStefano Zampini     if (xloc) {
227439accc25SStefano Zampini       xarr = hypre_CSRMatrixData(xloc);
2275363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
2276363d496dSStefano Zampini     }
2277363d496dSStefano Zampini     if (yloc) {
227839accc25SStefano Zampini       yarr = hypre_CSRMatrixData(yloc);
2279363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
2280363d496dSStefano Zampini     }
228108401ef6SPierre 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);
22829566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(xnnz, &bnz));
2283792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one));
2284363d496dSStefano Zampini   } else if (str == SUBSET_NONZERO_PATTERN) {
22859566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic(Y, a, X, str));
2286363d496dSStefano Zampini   } else {
2287363d496dSStefano Zampini     Mat B;
2288363d496dSStefano Zampini 
22899566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic_Preallocate(Y, X, &B));
22909566063dSJacob Faibussowitsch     PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str));
22919566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(Y, &B));
2292363d496dSStefano Zampini   }
22936ea7df73SStefano Zampini #endif
22943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2295363d496dSStefano Zampini }
2296363d496dSStefano Zampini 
22972c4ab24aSJunchao Zhang static PetscErrorCode MatDuplicate_HYPRE(Mat A, MatDuplicateOption op, Mat *B)
22982c4ab24aSJunchao Zhang {
22992c4ab24aSJunchao Zhang   hypre_ParCSRMatrix *parcsr = NULL;
23002c4ab24aSJunchao Zhang   PetscCopyMode       cpmode;
23012c4ab24aSJunchao Zhang   Mat_HYPRE          *hA;
23022c4ab24aSJunchao Zhang 
23032c4ab24aSJunchao Zhang   PetscFunctionBegin;
23042c4ab24aSJunchao Zhang   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
23052c4ab24aSJunchao Zhang   if (op == MAT_DO_NOT_COPY_VALUES || op == MAT_SHARE_NONZERO_PATTERN) {
23062c4ab24aSJunchao Zhang     parcsr = hypre_ParCSRMatrixClone(parcsr, 0);
23072c4ab24aSJunchao Zhang     cpmode = PETSC_OWN_POINTER;
23082c4ab24aSJunchao Zhang   } else {
23092c4ab24aSJunchao Zhang     cpmode = PETSC_COPY_VALUES;
23102c4ab24aSJunchao Zhang   }
23112c4ab24aSJunchao Zhang   PetscCall(MatCreateFromParCSR(parcsr, MATHYPRE, cpmode, B));
23122c4ab24aSJunchao Zhang   hA = (Mat_HYPRE *)A->data;
23132c4ab24aSJunchao Zhang   if (hA->cooMat) {
2314*06977982Sstefanozampini     Mat_HYPRE *hB = (Mat_HYPRE *)((*B)->data);
2315b73e3080SStefano Zampini     op            = (op == MAT_DO_NOT_COPY_VALUES) ? op : MAT_COPY_VALUES;
2316b73e3080SStefano Zampini     /* Cannot simply increase the reference count of hA->cooMat, since B needs to share cooMat's data array */
2317*06977982Sstefanozampini     PetscCall(MatDuplicate(hA->cooMat, op, &hB->cooMat));
2318*06977982Sstefanozampini     PetscCall(MatHYPRE_AttachCOOMat(*B));
23192c4ab24aSJunchao Zhang   }
23202c4ab24aSJunchao Zhang   PetscFunctionReturn(PETSC_SUCCESS);
23212c4ab24aSJunchao Zhang }
23222c4ab24aSJunchao Zhang 
2323d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetPreallocationCOO_HYPRE(Mat mat, PetscCount coo_n, PetscInt coo_i[], PetscInt coo_j[])
2324d71ae5a4SJacob Faibussowitsch {
2325*06977982Sstefanozampini   Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data;
23265fbaff96SJunchao Zhang 
23275fbaff96SJunchao Zhang   PetscFunctionBegin;
2328651b1cf9SStefano Zampini   /* Build an agent matrix cooMat with AIJ format
23295fbaff96SJunchao 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.
23305fbaff96SJunchao Zhang    */
2331*06977982Sstefanozampini   PetscCall(MatHYPRE_CreateCOOMat(mat));
2332*06977982Sstefanozampini   PetscCall(MatSetOption(hmat->cooMat, MAT_IGNORE_OFF_PROC_ENTRIES, hmat->donotstash));
2333*06977982Sstefanozampini   PetscCall(MatSetOption(hmat->cooMat, MAT_NO_OFF_PROC_ENTRIES, mat->nooffprocentries));
2334651b1cf9SStefano Zampini 
2335651b1cf9SStefano Zampini   /* MatSetPreallocationCOO_SeqAIJ and MatSetPreallocationCOO_MPIAIJ uses this specific
2336651b1cf9SStefano Zampini      name to automatically put the diagonal entries first */
2337*06977982Sstefanozampini   PetscCall(PetscObjectSetName((PetscObject)hmat->cooMat, "_internal_COO_mat_for_hypre"));
2338*06977982Sstefanozampini   PetscCall(MatSetPreallocationCOO(hmat->cooMat, coo_n, coo_i, coo_j));
2339*06977982Sstefanozampini   hmat->cooMat->assembled = PETSC_TRUE;
23405fbaff96SJunchao Zhang 
23415fbaff96SJunchao Zhang   /* Copy the sparsity pattern from cooMat to hypre IJMatrix hmat->ij */
23425fbaff96SJunchao Zhang   PetscCall(MatSetOption(mat, MAT_SORTED_FULL, PETSC_TRUE));
2343*06977982Sstefanozampini   PetscCall(MatHYPRE_CreateFromMat(hmat->cooMat, hmat));      /* Create hmat->ij and preallocate it */
2344*06977982Sstefanozampini   PetscCall(MatHYPRE_IJMatrixCopyIJ(hmat->cooMat, hmat->ij)); /* Copy A's (i,j) to hmat->ij */
23455fbaff96SJunchao Zhang 
23465fbaff96SJunchao Zhang   mat->preallocated = PETSC_TRUE;
23475fbaff96SJunchao Zhang   PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
23485fbaff96SJunchao Zhang   PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); /* Migrate mat to device if it is bound to. Hypre builds its own SpMV context here */
23495fbaff96SJunchao Zhang 
23502c4ab24aSJunchao Zhang   /* Attach cooMat to mat */
2351*06977982Sstefanozampini   PetscCall(MatHYPRE_AttachCOOMat(mat));
23523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23535fbaff96SJunchao Zhang }
23545fbaff96SJunchao Zhang 
2355d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesCOO_HYPRE(Mat mat, const PetscScalar v[], InsertMode imode)
2356d71ae5a4SJacob Faibussowitsch {
23575fbaff96SJunchao Zhang   Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data;
23585fbaff96SJunchao Zhang 
23595fbaff96SJunchao Zhang   PetscFunctionBegin;
2360b73e3080SStefano Zampini   PetscCheck(hmat->cooMat, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet");
23615fbaff96SJunchao Zhang   PetscCall(MatSetValuesCOO(hmat->cooMat, v, imode));
2362651b1cf9SStefano Zampini   PetscCall(MatViewFromOptions(hmat->cooMat, (PetscObject)mat, "-cooMat_view"));
23633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23645fbaff96SJunchao Zhang }
23655fbaff96SJunchao Zhang 
2366a055b5aaSBarry Smith /*MC
23672ef1f0ffSBarry Smith    MATHYPRE - "hypre" - A matrix type to be used for sequential and parallel sparse matrices
2368a055b5aaSBarry Smith           based on the hypre IJ interface.
2369a055b5aaSBarry Smith 
2370a055b5aaSBarry Smith    Level: intermediate
2371a055b5aaSBarry Smith 
23721cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatHYPRESetPreallocation`
2373a055b5aaSBarry Smith M*/
2374a055b5aaSBarry Smith 
2375d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_HYPRE(Mat B)
2376d71ae5a4SJacob Faibussowitsch {
237763c07aadSStefano Zampini   Mat_HYPRE *hB;
237863c07aadSStefano Zampini 
237963c07aadSStefano Zampini   PetscFunctionBegin;
23804dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&hB));
23816ea7df73SStefano Zampini 
2382978814f1SStefano Zampini   hB->inner_free      = PETSC_TRUE;
2383651b1cf9SStefano Zampini   hB->array_available = PETSC_TRUE;
2384978814f1SStefano Zampini 
238563c07aadSStefano Zampini   B->data = (void *)hB;
238663c07aadSStefano Zampini 
23879566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(B->ops, sizeof(struct _MatOps)));
238863c07aadSStefano Zampini   B->ops->mult                  = MatMult_HYPRE;
238963c07aadSStefano Zampini   B->ops->multtranspose         = MatMultTranspose_HYPRE;
2390414bd5c3SStefano Zampini   B->ops->multadd               = MatMultAdd_HYPRE;
2391414bd5c3SStefano Zampini   B->ops->multtransposeadd      = MatMultTransposeAdd_HYPRE;
239263c07aadSStefano Zampini   B->ops->setup                 = MatSetUp_HYPRE;
239363c07aadSStefano Zampini   B->ops->destroy               = MatDestroy_HYPRE;
239463c07aadSStefano Zampini   B->ops->assemblyend           = MatAssemblyEnd_HYPRE;
2395c69f721fSFande Kong   B->ops->assemblybegin         = MatAssemblyBegin_HYPRE;
2396d975228cSstefano_zampini   B->ops->setvalues             = MatSetValues_HYPRE;
239768ec7858SStefano Zampini   B->ops->missingdiagonal       = MatMissingDiagonal_HYPRE;
239868ec7858SStefano Zampini   B->ops->scale                 = MatScale_HYPRE;
239968ec7858SStefano Zampini   B->ops->zerorowscolumns       = MatZeroRowsColumns_HYPRE;
2400c69f721fSFande Kong   B->ops->zeroentries           = MatZeroEntries_HYPRE;
2401c69f721fSFande Kong   B->ops->zerorows              = MatZeroRows_HYPRE;
2402c69f721fSFande Kong   B->ops->getrow                = MatGetRow_HYPRE;
2403c69f721fSFande Kong   B->ops->restorerow            = MatRestoreRow_HYPRE;
2404c69f721fSFande Kong   B->ops->getvalues             = MatGetValues_HYPRE;
2405ddbeb582SStefano Zampini   B->ops->setoption             = MatSetOption_HYPRE;
240645b8d346SStefano Zampini   B->ops->duplicate             = MatDuplicate_HYPRE;
2407465edc17SStefano Zampini   B->ops->copy                  = MatCopy_HYPRE;
240845b8d346SStefano Zampini   B->ops->view                  = MatView_HYPRE;
24096305df00SStefano Zampini   B->ops->getdiagonal           = MatGetDiagonal_HYPRE;
2410363d496dSStefano Zampini   B->ops->axpy                  = MatAXPY_HYPRE;
24114222ddf1SHong Zhang   B->ops->productsetfromoptions = MatProductSetFromOptions_HYPRE;
24126ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
24136ea7df73SStefano Zampini   B->ops->bindtocpu = MatBindToCPU_HYPRE;
24146ea7df73SStefano Zampini   B->boundtocpu     = PETSC_FALSE;
24156ea7df73SStefano Zampini #endif
241645b8d346SStefano Zampini 
241745b8d346SStefano Zampini   /* build cache for off array entries formed */
24189566063dSJacob Faibussowitsch   PetscCall(MatStashCreate_Private(PetscObjectComm((PetscObject)B), 1, &B->stash));
241963c07aadSStefano Zampini 
24209566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)B), &hB->comm));
24219566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRE));
24229566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_aij_C", MatConvert_HYPRE_AIJ));
24239566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_is_C", MatConvert_HYPRE_IS));
24249566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_hypre_C", MatProductSetFromOptions_HYPRE));
24259566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaij_hypre_C", MatProductSetFromOptions_HYPRE));
24269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPRESetPreallocation_C", MatHYPRESetPreallocation_HYPRE));
24279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPREGetParCSR_C", MatHYPREGetParCSR_HYPRE));
24285fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_HYPRE));
24295fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetValuesCOO_C", MatSetValuesCOO_HYPRE));
24306ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
24316ea7df73SStefano Zampini   #if defined(HYPRE_USING_HIP)
2432*06977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijhipsparse_hypre_C", MatProductSetFromOptions_HYPRE));
2433*06977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaijhipsparse_hypre_C", MatProductSetFromOptions_HYPRE));
24349566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP));
24359566063dSJacob Faibussowitsch   PetscCall(MatSetVecType(B, VECHIP));
24366ea7df73SStefano Zampini   #endif
24376ea7df73SStefano Zampini   #if defined(HYPRE_USING_CUDA)
2438*06977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaijcusparse_hypre_C", MatProductSetFromOptions_HYPRE));
2439*06977982Sstefanozampini   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaijcusparse_hypre_C", MatProductSetFromOptions_HYPRE));
24409566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
24419566063dSJacob Faibussowitsch   PetscCall(MatSetVecType(B, VECCUDA));
24426ea7df73SStefano Zampini   #endif
24436ea7df73SStefano Zampini #endif
2444ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
24453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
244663c07aadSStefano Zampini }
2447