xref: /petsc/src/mat/impls/hypre/mhypre.c (revision 651b1cf95e744fa8e8eb4540e0fb634cee609368)
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);
28225daaf8SStefano Zampini static PetscErrorCode hypre_array_destroy(void *);
296ea7df73SStefano Zampini static PetscErrorCode MatSetValues_HYPRE(Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[], const PetscScalar[], InsertMode ins);
3063c07aadSStefano Zampini 
31d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat A_d, Mat A_o, HYPRE_IJMatrix ij)
32d71ae5a4SJacob Faibussowitsch {
3363c07aadSStefano Zampini   PetscInt        i, n_d, n_o;
3463c07aadSStefano Zampini   const PetscInt *ia_d, *ia_o;
3563c07aadSStefano Zampini   PetscBool       done_d = PETSC_FALSE, done_o = PETSC_FALSE;
362cf14000SStefano Zampini   HYPRE_Int      *nnz_d = NULL, *nnz_o = NULL;
3763c07aadSStefano Zampini 
3863c07aadSStefano Zampini   PetscFunctionBegin;
3963c07aadSStefano Zampini   if (A_d) { /* determine number of nonzero entries in local diagonal part */
409566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(A_d, 0, PETSC_FALSE, PETSC_FALSE, &n_d, &ia_d, NULL, &done_d));
4163c07aadSStefano Zampini     if (done_d) {
429566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(n_d, &nnz_d));
43ad540459SPierre Jolivet       for (i = 0; i < n_d; i++) nnz_d[i] = ia_d[i + 1] - ia_d[i];
4463c07aadSStefano Zampini     }
459566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowIJ(A_d, 0, PETSC_FALSE, PETSC_FALSE, NULL, &ia_d, NULL, &done_d));
4663c07aadSStefano Zampini   }
4763c07aadSStefano Zampini   if (A_o) { /* determine number of nonzero entries in local off-diagonal part */
489566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(A_o, 0, PETSC_FALSE, PETSC_FALSE, &n_o, &ia_o, NULL, &done_o));
4963c07aadSStefano Zampini     if (done_o) {
509566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(n_o, &nnz_o));
51ad540459SPierre Jolivet       for (i = 0; i < n_o; i++) nnz_o[i] = ia_o[i + 1] - ia_o[i];
5263c07aadSStefano Zampini     }
539566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowIJ(A_o, 0, PETSC_FALSE, PETSC_FALSE, &n_o, &ia_o, NULL, &done_o));
5463c07aadSStefano Zampini   }
5563c07aadSStefano Zampini   if (done_d) {    /* set number of nonzeros in HYPRE IJ matrix */
5663c07aadSStefano Zampini     if (!done_o) { /* only diagonal part */
579566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(n_d, &nnz_o));
5863c07aadSStefano Zampini     }
59c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0)
60c6698e78SStefano Zampini     { /* If we don't do this, the columns of the matrix will be all zeros! */
61c6698e78SStefano Zampini       hypre_AuxParCSRMatrix *aux_matrix;
62c6698e78SStefano Zampini       aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij);
63c6698e78SStefano Zampini       hypre_AuxParCSRMatrixDestroy(aux_matrix);
64c6698e78SStefano Zampini       hypre_IJMatrixTranslator(ij) = NULL;
65792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, ij, nnz_d, nnz_o);
6622235d61SPierre Jolivet       /* it seems they partially fixed it in 2.19.0 */
6722235d61SPierre Jolivet   #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
68c6698e78SStefano Zampini       aux_matrix                               = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij);
69c6698e78SStefano Zampini       hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1;
7022235d61SPierre Jolivet   #endif
71c6698e78SStefano Zampini     }
72c6698e78SStefano Zampini #else
73792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, ij, nnz_d, nnz_o);
74c6698e78SStefano Zampini #endif
759566063dSJacob Faibussowitsch     PetscCall(PetscFree(nnz_d));
769566063dSJacob Faibussowitsch     PetscCall(PetscFree(nnz_o));
7763c07aadSStefano Zampini   }
783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7963c07aadSStefano Zampini }
8063c07aadSStefano Zampini 
81d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_CreateFromMat(Mat A, Mat_HYPRE *hA)
82d71ae5a4SJacob Faibussowitsch {
8363c07aadSStefano Zampini   PetscInt rstart, rend, cstart, cend;
8463c07aadSStefano Zampini 
8563c07aadSStefano Zampini   PetscFunctionBegin;
869566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
879566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
8863c07aadSStefano Zampini   rstart = A->rmap->rstart;
8963c07aadSStefano Zampini   rend   = A->rmap->rend;
9063c07aadSStefano Zampini   cstart = A->cmap->rstart;
9163c07aadSStefano Zampini   cend   = A->cmap->rend;
92ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
93*651b1cf9SStefano Zampini   if (hA->ij) {
94*651b1cf9SStefano Zampini     if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL;
95*651b1cf9SStefano Zampini     PetscCallExternal(HYPRE_IJMatrixDestroy, hA->ij);
96*651b1cf9SStefano Zampini   }
97792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rstart, rend - 1, cstart, cend - 1, &hA->ij);
98792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR);
9963c07aadSStefano Zampini   {
10063c07aadSStefano Zampini     PetscBool       same;
10163c07aadSStefano Zampini     Mat             A_d, A_o;
10263c07aadSStefano Zampini     const PetscInt *colmap;
1039566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &same));
10463c07aadSStefano Zampini     if (same) {
1059566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJGetSeqAIJ(A, &A_d, &A_o, &colmap));
1069566063dSJacob Faibussowitsch       PetscCall(MatHYPRE_IJMatrixPreallocate(A_d, A_o, hA->ij));
1073ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
10863c07aadSStefano Zampini     }
1099566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIBAIJ, &same));
11063c07aadSStefano Zampini     if (same) {
1119566063dSJacob Faibussowitsch       PetscCall(MatMPIBAIJGetSeqBAIJ(A, &A_d, &A_o, &colmap));
1129566063dSJacob Faibussowitsch       PetscCall(MatHYPRE_IJMatrixPreallocate(A_d, A_o, hA->ij));
1133ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
11463c07aadSStefano Zampini     }
1159566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &same));
11663c07aadSStefano Zampini     if (same) {
1179566063dSJacob Faibussowitsch       PetscCall(MatHYPRE_IJMatrixPreallocate(A, NULL, hA->ij));
1183ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
11963c07aadSStefano Zampini     }
1209566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQBAIJ, &same));
12163c07aadSStefano Zampini     if (same) {
1229566063dSJacob Faibussowitsch       PetscCall(MatHYPRE_IJMatrixPreallocate(A, NULL, hA->ij));
1233ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
12463c07aadSStefano Zampini     }
12563c07aadSStefano Zampini   }
1263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12763c07aadSStefano Zampini }
12863c07aadSStefano Zampini 
129b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ(Mat A, HYPRE_IJMatrix ij)
130d71ae5a4SJacob Faibussowitsch {
13163c07aadSStefano Zampini   PetscBool flg;
13263c07aadSStefano Zampini 
13363c07aadSStefano Zampini   PetscFunctionBegin;
1346ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
135792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize, ij);
1366ea7df73SStefano Zampini #else
137792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize_v2, ij, HYPRE_MEMORY_HOST);
1386ea7df73SStefano Zampini #endif
1399566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &flg));
140b73e3080SStefano Zampini   if (flg) {
141b73e3080SStefano Zampini     PetscCall(MatHYPRE_IJMatrixCopyIJ_MPIAIJ(A, ij));
1423ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
14363c07aadSStefano Zampini   }
1449566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &flg));
14563c07aadSStefano Zampini   if (flg) {
146b73e3080SStefano Zampini     PetscCall(MatHYPRE_IJMatrixCopyIJ_SeqAIJ(A, ij));
1473ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
14863c07aadSStefano Zampini   }
149b73e3080SStefano Zampini   PetscCheck(PETSC_FALSE, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "No support for matrix type %s", ((PetscObject)A)->type_name);
15063c07aadSStefano Zampini }
15163c07aadSStefano Zampini 
152b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_SeqAIJ(Mat A, HYPRE_IJMatrix ij)
153d71ae5a4SJacob Faibussowitsch {
15463c07aadSStefano Zampini   Mat_SeqAIJ            *pdiag = (Mat_SeqAIJ *)A->data;
15558968eb6SStefano Zampini   HYPRE_Int              type;
15663c07aadSStefano Zampini   hypre_ParCSRMatrix    *par_matrix;
15763c07aadSStefano Zampini   hypre_AuxParCSRMatrix *aux_matrix;
15863c07aadSStefano Zampini   hypre_CSRMatrix       *hdiag;
1592cf14000SStefano Zampini   PetscBool              sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
16063c07aadSStefano Zampini 
16163c07aadSStefano Zampini   PetscFunctionBegin;
162792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type);
16308401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
164792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix);
16563c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(par_matrix);
16663c07aadSStefano Zampini   /*
16763c07aadSStefano Zampini        this is the Hack part where we monkey directly with the hypre datastructures
16863c07aadSStefano Zampini   */
1692cf14000SStefano Zampini   if (sameint) {
1709566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hdiag->i, pdiag->i, A->rmap->n + 1));
1719566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hdiag->j, pdiag->j, pdiag->nz));
1722cf14000SStefano Zampini   } else {
1732cf14000SStefano Zampini     PetscInt i;
1742cf14000SStefano Zampini 
1752cf14000SStefano Zampini     for (i = 0; i < A->rmap->n + 1; i++) hdiag->i[i] = (HYPRE_Int)pdiag->i[i];
1762cf14000SStefano Zampini     for (i = 0; i < pdiag->nz; i++) hdiag->j[i] = (HYPRE_Int)pdiag->j[i];
1772cf14000SStefano Zampini   }
1786ea7df73SStefano Zampini 
179ea9daf28SStefano Zampini   aux_matrix                               = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij);
18063c07aadSStefano Zampini   hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
1813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18263c07aadSStefano Zampini }
18363c07aadSStefano Zampini 
184b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_MPIAIJ(Mat A, HYPRE_IJMatrix ij)
185d71ae5a4SJacob Faibussowitsch {
18663c07aadSStefano Zampini   Mat_MPIAIJ            *pA = (Mat_MPIAIJ *)A->data;
18763c07aadSStefano Zampini   Mat_SeqAIJ            *pdiag, *poffd;
18863c07aadSStefano Zampini   PetscInt               i, *garray = pA->garray, *jj, cstart, *pjj;
1892cf14000SStefano Zampini   HYPRE_Int             *hjj, type;
19063c07aadSStefano Zampini   hypre_ParCSRMatrix    *par_matrix;
19163c07aadSStefano Zampini   hypre_AuxParCSRMatrix *aux_matrix;
19263c07aadSStefano Zampini   hypre_CSRMatrix       *hdiag, *hoffd;
1932cf14000SStefano Zampini   PetscBool              sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
19463c07aadSStefano Zampini 
19563c07aadSStefano Zampini   PetscFunctionBegin;
19663c07aadSStefano Zampini   pdiag = (Mat_SeqAIJ *)pA->A->data;
19763c07aadSStefano Zampini   poffd = (Mat_SeqAIJ *)pA->B->data;
198da81f932SPierre Jolivet   /* cstart is only valid for square MPIAIJ laid out in the usual way */
1999566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &cstart, NULL));
20063c07aadSStefano Zampini 
201792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type);
20208401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
203792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix);
20463c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(par_matrix);
20563c07aadSStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(par_matrix);
20663c07aadSStefano Zampini 
2072cf14000SStefano Zampini   if (sameint) {
2089566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hdiag->i, pdiag->i, pA->A->rmap->n + 1));
2092cf14000SStefano Zampini   } else {
2102cf14000SStefano Zampini     for (i = 0; i < pA->A->rmap->n + 1; i++) hdiag->i[i] = (HYPRE_Int)(pdiag->i[i]);
2112cf14000SStefano Zampini   }
212b73e3080SStefano Zampini 
2132cf14000SStefano Zampini   hjj = hdiag->j;
2142cf14000SStefano Zampini   pjj = pdiag->j;
215c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0)
2162cf14000SStefano Zampini   for (i = 0; i < pdiag->nz; i++) hjj[i] = pjj[i];
217c6698e78SStefano Zampini #else
2182cf14000SStefano Zampini   for (i = 0; i < pdiag->nz; i++) hjj[i] = cstart + pjj[i];
219c6698e78SStefano Zampini #endif
2202cf14000SStefano Zampini   if (sameint) {
2219566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hoffd->i, poffd->i, pA->A->rmap->n + 1));
2222cf14000SStefano Zampini   } else {
2232cf14000SStefano Zampini     for (i = 0; i < pA->A->rmap->n + 1; i++) hoffd->i[i] = (HYPRE_Int)(poffd->i[i]);
2242cf14000SStefano Zampini   }
2252cf14000SStefano Zampini 
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 #else
23063c07aadSStefano Zampini   jj = (PetscInt *)hoffd->j;
231c6698e78SStefano Zampini #endif
2322cf14000SStefano Zampini   pjj = poffd->j;
23363c07aadSStefano Zampini   for (i = 0; i < poffd->nz; i++) jj[i] = garray[pjj[i]];
234c6698e78SStefano Zampini 
235ea9daf28SStefano Zampini   aux_matrix                               = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij);
23663c07aadSStefano Zampini   hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
2373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23863c07aadSStefano Zampini }
23963c07aadSStefano Zampini 
240d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_HYPRE_IS(Mat A, MatType mtype, MatReuse reuse, Mat *B)
241d71ae5a4SJacob Faibussowitsch {
2422df22349SStefano Zampini   Mat_HYPRE             *mhA = (Mat_HYPRE *)(A->data);
2432df22349SStefano Zampini   Mat                    lA;
2442df22349SStefano Zampini   ISLocalToGlobalMapping rl2g, cl2g;
2452df22349SStefano Zampini   IS                     is;
2462df22349SStefano Zampini   hypre_ParCSRMatrix    *hA;
2472df22349SStefano Zampini   hypre_CSRMatrix       *hdiag, *hoffd;
2482df22349SStefano Zampini   MPI_Comm               comm;
24939accc25SStefano Zampini   HYPRE_Complex         *hdd, *hod, *aa;
25039accc25SStefano Zampini   PetscScalar           *data;
2512cf14000SStefano Zampini   HYPRE_BigInt          *col_map_offd;
2522cf14000SStefano Zampini   HYPRE_Int             *hdi, *hdj, *hoi, *hoj;
2532df22349SStefano Zampini   PetscInt              *ii, *jj, *iptr, *jptr;
2542df22349SStefano Zampini   PetscInt               cum, dr, dc, oc, str, stc, nnz, i, jd, jo, M, N;
25558968eb6SStefano Zampini   HYPRE_Int              type;
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);
2622df22349SStefano Zampini   M     = hypre_ParCSRMatrixGlobalNumRows(hA);
2632df22349SStefano Zampini   N     = hypre_ParCSRMatrixGlobalNumCols(hA);
2642df22349SStefano Zampini   str   = hypre_ParCSRMatrixFirstRowIndex(hA);
2652df22349SStefano Zampini   stc   = hypre_ParCSRMatrixFirstColDiag(hA);
2662df22349SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(hA);
2672df22349SStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(hA);
2682df22349SStefano Zampini   dr    = hypre_CSRMatrixNumRows(hdiag);
2692df22349SStefano Zampini   dc    = hypre_CSRMatrixNumCols(hdiag);
2702df22349SStefano Zampini   nnz   = hypre_CSRMatrixNumNonzeros(hdiag);
2712df22349SStefano Zampini   hdi   = hypre_CSRMatrixI(hdiag);
2722df22349SStefano Zampini   hdj   = hypre_CSRMatrixJ(hdiag);
2732df22349SStefano Zampini   hdd   = hypre_CSRMatrixData(hdiag);
2742df22349SStefano Zampini   oc    = hypre_CSRMatrixNumCols(hoffd);
2752df22349SStefano Zampini   nnz += hypre_CSRMatrixNumNonzeros(hoffd);
2762df22349SStefano Zampini   hoi = hypre_CSRMatrixI(hoffd);
2772df22349SStefano Zampini   hoj = hypre_CSRMatrixJ(hoffd);
2782df22349SStefano Zampini   hod = hypre_CSRMatrixData(hoffd);
2792df22349SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
2802df22349SStefano Zampini     PetscInt *aux;
2812df22349SStefano Zampini 
2822df22349SStefano Zampini     /* generate l2g maps for rows and cols */
2839566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(comm, dr, str, 1, &is));
2849566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g));
2859566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
2862df22349SStefano Zampini     col_map_offd = hypre_ParCSRMatrixColMapOffd(hA);
2879566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dc + oc, &aux));
2882df22349SStefano Zampini     for (i = 0; i < dc; i++) aux[i] = i + stc;
2892df22349SStefano Zampini     for (i = 0; i < oc; i++) aux[i + dc] = col_map_offd[i];
2909566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, dc + oc, aux, PETSC_OWN_POINTER, &is));
2919566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g));
2929566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
2932df22349SStefano Zampini     /* create MATIS object */
2949566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm, B));
2959566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(*B, dr, dc, M, N));
2969566063dSJacob Faibussowitsch     PetscCall(MatSetType(*B, MATIS));
2979566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(*B, rl2g, cl2g));
2989566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
2999566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
3002df22349SStefano Zampini 
3012df22349SStefano Zampini     /* allocate CSR for local matrix */
3029566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dr + 1, &iptr));
3039566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &jptr));
3049566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &data));
3052df22349SStefano Zampini   } else {
3062df22349SStefano Zampini     PetscInt  nr;
3072df22349SStefano Zampini     PetscBool done;
3089566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(*B, &lA));
3099566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(lA, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&iptr, (const PetscInt **)&jptr, &done));
31008401ef6SPierre 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);
31108401ef6SPierre 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);
3129566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArray(lA, &data));
3132df22349SStefano Zampini   }
3142df22349SStefano Zampini   /* merge local matrices */
3152df22349SStefano Zampini   ii  = iptr;
3162df22349SStefano Zampini   jj  = jptr;
31739accc25SStefano 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++ */
3182df22349SStefano Zampini   *ii = *(hdi++) + *(hoi++);
3192df22349SStefano Zampini   for (jd = 0, jo = 0, cum = 0; *ii < nnz; cum++) {
32039accc25SStefano Zampini     PetscScalar *aold = (PetscScalar *)aa;
3212df22349SStefano Zampini     PetscInt    *jold = jj, nc = jd + jo;
3229371c9d4SSatish Balay     for (; jd < *hdi; jd++) {
3239371c9d4SSatish Balay       *jj++ = *hdj++;
3249371c9d4SSatish Balay       *aa++ = *hdd++;
3259371c9d4SSatish Balay     }
3269371c9d4SSatish Balay     for (; jo < *hoi; jo++) {
3279371c9d4SSatish Balay       *jj++ = *hoj++ + dc;
3289371c9d4SSatish Balay       *aa++ = *hod++;
3299371c9d4SSatish Balay     }
3302df22349SStefano Zampini     *(++ii) = *(hdi++) + *(hoi++);
3319566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithScalarArray(jd + jo - nc, jold, aold));
3322df22349SStefano Zampini   }
3332df22349SStefano Zampini   for (; cum < dr; cum++) *(++ii) = nnz;
3342df22349SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
335a033916dSStefano Zampini     Mat_SeqAIJ *a;
336a033916dSStefano Zampini 
3379566063dSJacob Faibussowitsch     PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, dr, dc + oc, iptr, jptr, data, &lA));
3389566063dSJacob Faibussowitsch     PetscCall(MatISSetLocalMat(*B, lA));
339a033916dSStefano Zampini     /* hack SeqAIJ */
340a033916dSStefano Zampini     a          = (Mat_SeqAIJ *)(lA->data);
341a033916dSStefano Zampini     a->free_a  = PETSC_TRUE;
342a033916dSStefano Zampini     a->free_ij = PETSC_TRUE;
3439566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&lA));
3442df22349SStefano Zampini   }
3459566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY));
3469566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY));
34748a46eb9SPierre Jolivet   if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, B));
3483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3492df22349SStefano Zampini }
3502df22349SStefano Zampini 
351b73e3080SStefano Zampini /* Move diagonal elements of the diagonal block to the front of their row, as needed by ParCSRMatrix. So damn hacky */
352b73e3080SStefano Zampini static PetscErrorCode EnsureHypreCSR_SeqAIJ(Mat A, hypre_CSRMatrix *hA)
353d71ae5a4SJacob Faibussowitsch {
354b73e3080SStefano Zampini   Mat_SeqAIJ   *aij = (Mat_SeqAIJ *)A->data;
355b73e3080SStefano Zampini   PetscBool     isseqaij;
356b73e3080SStefano Zampini   HYPRE_Int     tmpj, *hj;
357b73e3080SStefano Zampini   HYPRE_Complex tmpv, *ha;
35863c07aadSStefano Zampini 
35963c07aadSStefano Zampini   PetscFunctionBegin;
360b73e3080SStefano Zampini   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isseqaij));
361b73e3080SStefano Zampini   PetscCheck(isseqaij, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Not for type %s\n", ((PetscObject)A)->type_name);
362b73e3080SStefano Zampini   hj = hypre_CSRMatrixJ(hA);
363b73e3080SStefano Zampini   ha = hypre_CSRMatrixData(hA);
364b73e3080SStefano Zampini #define swap_with_tmp(a, b, t) \
365b73e3080SStefano Zampini   { \
366b73e3080SStefano Zampini     t = a; \
367b73e3080SStefano Zampini     a = b; \
368b73e3080SStefano Zampini     b = t; \
369b73e3080SStefano Zampini   }
370b73e3080SStefano Zampini   for (PetscInt i = 0; i < A->rmap->n; i++) {
371b73e3080SStefano Zampini     if (aij->diag[i] >= aij->i[i] && aij->diag[i] < aij->i[i + 1]) { /* Diagonal element of this row exists in a[] and j[] */
372b73e3080SStefano Zampini       swap_with_tmp(ha[aij->i[i]], ha[aij->diag[i]], tmpv);
373b73e3080SStefano Zampini       if (hj[aij->i[i]] != i) swap_with_tmp(hj[aij->i[i]], hj[aij->diag[i]], tmpj);
374b73e3080SStefano Zampini     }
375b73e3080SStefano Zampini   }
376b73e3080SStefano Zampini #undef swap_with_tmp
377b73e3080SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
378b73e3080SStefano Zampini }
379b73e3080SStefano Zampini 
380b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyValues(Mat A, HYPRE_IJMatrix ij)
381b73e3080SStefano Zampini {
382b73e3080SStefano Zampini   HYPRE_Int           type;
383b73e3080SStefano Zampini   hypre_ParCSRMatrix *par_matrix;
384b73e3080SStefano Zampini   hypre_CSRMatrix    *hdiag, *hoffd;
385b73e3080SStefano Zampini   PetscBool           ismpiaij;
386b73e3080SStefano Zampini   Mat                 dA = A, oA = NULL;
387b73e3080SStefano Zampini   PetscInt            nnz;
388b73e3080SStefano Zampini   const PetscScalar  *pa;
389b73e3080SStefano Zampini 
390b73e3080SStefano Zampini   PetscFunctionBegin;
391b73e3080SStefano Zampini   PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type);
392b73e3080SStefano Zampini   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
393b73e3080SStefano Zampini   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
394b73e3080SStefano Zampini   if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(A, &dA, &oA, NULL));
395b73e3080SStefano Zampini   PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix);
396b73e3080SStefano Zampini 
397b73e3080SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(par_matrix);
398b73e3080SStefano Zampini   nnz   = hypre_CSRMatrixNumNonzeros(hdiag);
399b73e3080SStefano Zampini   PetscCall(MatSeqAIJGetArrayRead(dA, &pa));
400b73e3080SStefano Zampini   PetscCall(PetscArraycpy(hdiag->data, pa, nnz));
401b73e3080SStefano Zampini   PetscCall(MatSeqAIJRestoreArrayRead(dA, &pa));
402b73e3080SStefano Zampini   if (oA) {
403b73e3080SStefano Zampini     hoffd = hypre_ParCSRMatrixOffd(par_matrix);
404b73e3080SStefano Zampini     nnz   = hypre_CSRMatrixNumNonzeros(hoffd);
405b73e3080SStefano Zampini     PetscCall(MatSeqAIJGetArrayRead(oA, &pa));
406b73e3080SStefano Zampini     PetscCall(PetscArraycpy(hoffd->data, pa, nnz));
407b73e3080SStefano Zampini     PetscCall(MatSeqAIJRestoreArrayRead(dA, &pa));
408b73e3080SStefano Zampini   }
409b73e3080SStefano Zampini   PetscCall(EnsureHypreCSR_SeqAIJ(dA, hdiag));
410b73e3080SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
411b73e3080SStefano Zampini }
412b73e3080SStefano Zampini 
413b73e3080SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType type, MatReuse reuse, Mat *B)
414b73e3080SStefano Zampini {
415b73e3080SStefano Zampini   MPI_Comm   comm = PetscObjectComm((PetscObject)A);
416b73e3080SStefano Zampini   Mat        M    = NULL;
417b73e3080SStefano Zampini   Mat        dA = A, oA = NULL;
418b73e3080SStefano Zampini   PetscBool  ismpiaij, issbaij, isbaij;
419b73e3080SStefano Zampini   Mat_HYPRE *hA;
420b73e3080SStefano Zampini 
421b73e3080SStefano Zampini   PetscFunctionBegin;
422b73e3080SStefano Zampini   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &issbaij, MATSEQSBAIJ, MATMPIBAIJ, ""));
423b73e3080SStefano Zampini   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &isbaij, MATSEQBAIJ, MATMPIBAIJ, ""));
424b73e3080SStefano Zampini   if (isbaij || issbaij) { /* handle BAIJ and SBAIJ */
425b73e3080SStefano Zampini     PetscBool ismpi;
426b73e3080SStefano Zampini     MatType   newtype;
427b73e3080SStefano Zampini 
428b73e3080SStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &ismpi, MATMPISBAIJ, MATMPIBAIJ, ""));
429b73e3080SStefano Zampini     newtype = ismpi ? MATMPIAIJ : MATSEQAIJ;
43063c07aadSStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
431b73e3080SStefano Zampini       PetscCall(MatConvert(*B, newtype, MAT_INPLACE_MATRIX, B));
432b73e3080SStefano Zampini       PetscCall(MatConvert(A, newtype, MAT_REUSE_MATRIX, B));
433b73e3080SStefano Zampini       PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B));
434b73e3080SStefano Zampini     } else if (reuse == MAT_INITIAL_MATRIX) {
435b73e3080SStefano Zampini       PetscCall(MatConvert(A, newtype, MAT_INITIAL_MATRIX, B));
436b73e3080SStefano Zampini       PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B));
43763c07aadSStefano Zampini     } else {
438b73e3080SStefano Zampini       PetscCall(MatConvert(A, newtype, MAT_INPLACE_MATRIX, &A));
439b73e3080SStefano Zampini       PetscCall(MatConvert(A, MATHYPRE, MAT_INPLACE_MATRIX, &A));
440b73e3080SStefano Zampini     }
441b73e3080SStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
442b73e3080SStefano Zampini   }
443b73e3080SStefano Zampini   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
444b73e3080SStefano Zampini   if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(A, &dA, &oA, NULL));
445b73e3080SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
4469566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm, &M));
4479566063dSJacob Faibussowitsch     PetscCall(MatSetType(M, MATHYPRE));
4489566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(M, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
449b73e3080SStefano Zampini     PetscCall(MatSetOption(M, MAT_SORTED_FULL, PETSC_TRUE));
450b73e3080SStefano Zampini     PetscCall(MatSetOption(M, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE));
451b73e3080SStefano Zampini     PetscCall(PetscLayoutSetUp(M->rmap));
452b73e3080SStefano Zampini     PetscCall(PetscLayoutSetUp(M->cmap));
453b73e3080SStefano Zampini 
454b73e3080SStefano Zampini     hA = (Mat_HYPRE *)M->data;
455b73e3080SStefano Zampini     PetscCall(MatHYPRE_CreateFromMat(A, hA));      /* Create hmat->ij and preallocate it */
456b73e3080SStefano Zampini     PetscCall(MatHYPRE_IJMatrixCopyIJ(A, hA->ij)); /* Copy A's (a,i,j) to hmat->ij */
457b73e3080SStefano Zampini     M->preallocated = PETSC_TRUE;
45884d4e069SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) *B = M;
459b73e3080SStefano Zampini   } else M = *B;
460b73e3080SStefano Zampini 
461b73e3080SStefano Zampini   hA = (Mat_HYPRE *)M->data;
462b73e3080SStefano Zampini   PetscCall(MatHYPRE_IJMatrixCopyValues(A, hA->ij));
463b73e3080SStefano Zampini   PetscCall(MatAssemblyBegin(M, MAT_FINAL_ASSEMBLY));
464b73e3080SStefano Zampini   PetscCall(MatAssemblyEnd(M, MAT_FINAL_ASSEMBLY)); /* Migrate mat to device if it is bound to. Hypre builds its own SpMV context here */
465b73e3080SStefano Zampini 
46648a46eb9SPierre Jolivet   if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &M));
4673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46863c07aadSStefano Zampini }
46963c07aadSStefano Zampini 
470d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_HYPRE_AIJ(Mat A, MatType mtype, MatReuse reuse, Mat *B)
471d71ae5a4SJacob Faibussowitsch {
47263c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE *)A->data;
47363c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
47463c07aadSStefano Zampini   hypre_CSRMatrix    *hdiag, *hoffd;
47563c07aadSStefano Zampini   MPI_Comm            comm;
47663c07aadSStefano Zampini   PetscScalar        *da, *oa, *aptr;
47763c07aadSStefano Zampini   PetscInt           *dii, *djj, *oii, *ojj, *iptr;
47863c07aadSStefano Zampini   PetscInt            i, dnnz, onnz, m, n;
47958968eb6SStefano Zampini   HYPRE_Int           type;
48063c07aadSStefano Zampini   PetscMPIInt         size;
4812cf14000SStefano Zampini   PetscBool           sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
482b73e3080SStefano Zampini   PetscBool           downs = PETSC_TRUE, oowns = PETSC_TRUE;
48363c07aadSStefano Zampini 
48463c07aadSStefano Zampini   PetscFunctionBegin;
48563c07aadSStefano Zampini   comm = PetscObjectComm((PetscObject)A);
486792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
48708401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
48863c07aadSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
48963c07aadSStefano Zampini     PetscBool ismpiaij, isseqaij;
4909566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATMPIAIJ, &ismpiaij));
4919566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATSEQAIJ, &isseqaij));
49208401ef6SPierre Jolivet     PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Only MATMPIAIJ or MATSEQAIJ are supported");
49363c07aadSStefano Zampini   }
4946ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
49508401ef6SPierre Jolivet   PetscCheck(HYPRE_MEMORY_DEVICE != hypre_IJMatrixMemoryLocation(hA->ij), comm, PETSC_ERR_SUP, "Not yet implemented");
4966ea7df73SStefano Zampini #endif
4979566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
49863c07aadSStefano Zampini 
499792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
50063c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(parcsr);
50163c07aadSStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(parcsr);
50263c07aadSStefano Zampini   m     = hypre_CSRMatrixNumRows(hdiag);
50363c07aadSStefano Zampini   n     = hypre_CSRMatrixNumCols(hdiag);
50463c07aadSStefano Zampini   dnnz  = hypre_CSRMatrixNumNonzeros(hdiag);
50563c07aadSStefano Zampini   onnz  = hypre_CSRMatrixNumNonzeros(hoffd);
506225daaf8SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
5079566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m + 1, &dii));
5089566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dnnz, &djj));
5099566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dnnz, &da));
510225daaf8SStefano Zampini   } else if (reuse == MAT_REUSE_MATRIX) {
51163c07aadSStefano Zampini     PetscInt  nr;
51263c07aadSStefano Zampini     PetscBool done;
51363c07aadSStefano Zampini     if (size > 1) {
51463c07aadSStefano Zampini       Mat_MPIAIJ *b = (Mat_MPIAIJ *)((*B)->data);
51563c07aadSStefano Zampini 
5169566063dSJacob Faibussowitsch       PetscCall(MatGetRowIJ(b->A, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&dii, (const PetscInt **)&djj, &done));
51708401ef6SPierre Jolivet       PetscCheck(nr == m, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of local rows in diag part! %" PetscInt_FMT " != %" PetscInt_FMT, nr, m);
51808401ef6SPierre Jolivet       PetscCheck(dii[nr] >= dnnz, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of nonzeros in diag part! reuse %" PetscInt_FMT " hypre %" PetscInt_FMT, dii[nr], dnnz);
5199566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJGetArray(b->A, &da));
52063c07aadSStefano Zampini     } else {
5219566063dSJacob Faibussowitsch       PetscCall(MatGetRowIJ(*B, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&dii, (const PetscInt **)&djj, &done));
52208401ef6SPierre Jolivet       PetscCheck(nr == m, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of local rows! %" PetscInt_FMT " != %" PetscInt_FMT, nr, m);
52308401ef6SPierre Jolivet       PetscCheck(dii[nr] >= dnnz, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of nonzeros! reuse %" PetscInt_FMT " hypre %" PetscInt_FMT, dii[nr], dnnz);
5249566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJGetArray(*B, &da));
52563c07aadSStefano Zampini     }
526225daaf8SStefano Zampini   } else { /* MAT_INPLACE_MATRIX */
527b73e3080SStefano Zampini     downs = (PetscBool)(hypre_CSRMatrixOwnsData(hdiag));
528b73e3080SStefano Zampini     if (!sameint || !downs) {
5299566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(m + 1, &dii));
5309566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(dnnz, &djj));
5312cf14000SStefano Zampini     } else {
5327d968826Sstefano_zampini       dii = (PetscInt *)hypre_CSRMatrixI(hdiag);
5337d968826Sstefano_zampini       djj = (PetscInt *)hypre_CSRMatrixJ(hdiag);
53463c07aadSStefano Zampini     }
535b73e3080SStefano Zampini     if (!downs) {
536b73e3080SStefano Zampini       PetscCall(PetscMalloc1(dnnz, &da));
537b73e3080SStefano Zampini     } else da = (PetscScalar *)hypre_CSRMatrixData(hdiag);
53863c07aadSStefano Zampini   }
5392cf14000SStefano Zampini 
5402cf14000SStefano Zampini   if (!sameint) {
5419371c9d4SSatish Balay     if (reuse != MAT_REUSE_MATRIX) {
5429371c9d4SSatish Balay       for (i = 0; i < m + 1; i++) dii[i] = (PetscInt)(hypre_CSRMatrixI(hdiag)[i]);
5439371c9d4SSatish Balay     }
5442cf14000SStefano Zampini     for (i = 0; i < dnnz; i++) djj[i] = (PetscInt)(hypre_CSRMatrixJ(hdiag)[i]);
5452cf14000SStefano Zampini   } else {
5469566063dSJacob Faibussowitsch     if (reuse != MAT_REUSE_MATRIX) PetscCall(PetscArraycpy(dii, hypre_CSRMatrixI(hdiag), m + 1));
5479566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(djj, hypre_CSRMatrixJ(hdiag), dnnz));
5482cf14000SStefano Zampini   }
5499566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(da, hypre_CSRMatrixData(hdiag), dnnz));
55063c07aadSStefano Zampini   iptr = djj;
55163c07aadSStefano Zampini   aptr = da;
55263c07aadSStefano Zampini   for (i = 0; i < m; i++) {
55363c07aadSStefano Zampini     PetscInt nc = dii[i + 1] - dii[i];
5549566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithScalarArray(nc, iptr, aptr));
55563c07aadSStefano Zampini     iptr += nc;
55663c07aadSStefano Zampini     aptr += nc;
55763c07aadSStefano Zampini   }
55863c07aadSStefano Zampini   if (size > 1) {
5592cf14000SStefano Zampini     HYPRE_BigInt *coffd;
5602cf14000SStefano Zampini     HYPRE_Int    *offdj;
56163c07aadSStefano Zampini 
562225daaf8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
5639566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(m + 1, &oii));
5649566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(onnz, &ojj));
5659566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(onnz, &oa));
566225daaf8SStefano Zampini     } else if (reuse == MAT_REUSE_MATRIX) {
56763c07aadSStefano Zampini       Mat_MPIAIJ *b = (Mat_MPIAIJ *)((*B)->data);
56863c07aadSStefano Zampini       PetscInt    nr, hr = hypre_CSRMatrixNumRows(hoffd);
56963c07aadSStefano Zampini       PetscBool   done;
57063c07aadSStefano Zampini 
5719566063dSJacob Faibussowitsch       PetscCall(MatGetRowIJ(b->B, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&oii, (const PetscInt **)&ojj, &done));
57208401ef6SPierre Jolivet       PetscCheck(nr == hr, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of local rows in offdiag part! %" PetscInt_FMT " != %" PetscInt_FMT, nr, hr);
573b73e3080SStefano Zampini       PetscCheck(oii[nr] >= onnz, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse matrix: different number of nonzeros in off-diagonal part of matrix! reuse %" PetscInt_FMT " hypre %" PetscInt_FMT, oii[nr], onnz);
5749566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJGetArray(b->B, &oa));
575225daaf8SStefano Zampini     } else { /* MAT_INPLACE_MATRIX */
576b73e3080SStefano Zampini       oowns = (PetscBool)(hypre_CSRMatrixOwnsData(hoffd));
577b73e3080SStefano Zampini       if (!sameint || !oowns) {
5789566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(m + 1, &oii));
5799566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(onnz, &ojj));
5802cf14000SStefano Zampini       } else {
5817d968826Sstefano_zampini         oii = (PetscInt *)hypre_CSRMatrixI(hoffd);
5827d968826Sstefano_zampini         ojj = (PetscInt *)hypre_CSRMatrixJ(hoffd);
58363c07aadSStefano Zampini       }
584b73e3080SStefano Zampini       if (!oowns) {
585b73e3080SStefano Zampini         PetscCall(PetscMalloc1(onnz, &oa));
586b73e3080SStefano Zampini       } else oa = (PetscScalar *)hypre_CSRMatrixData(hoffd);
58763c07aadSStefano Zampini     }
588a16187a7SStefano Zampini     if (reuse != MAT_REUSE_MATRIX) {
5892cf14000SStefano Zampini       if (!sameint) {
5902cf14000SStefano Zampini         for (i = 0; i < m + 1; i++) oii[i] = (PetscInt)(hypre_CSRMatrixI(hoffd)[i]);
5912cf14000SStefano Zampini       } else {
5929566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(oii, hypre_CSRMatrixI(hoffd), m + 1));
5932cf14000SStefano Zampini       }
594a16187a7SStefano Zampini     }
5959566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(oa, hypre_CSRMatrixData(hoffd), onnz));
596a16187a7SStefano Zampini 
59763c07aadSStefano Zampini     offdj = hypre_CSRMatrixJ(hoffd);
59863c07aadSStefano Zampini     coffd = hypre_ParCSRMatrixColMapOffd(parcsr);
599a16187a7SStefano Zampini     /* we only need the permutation to be computed properly, I don't know if HYPRE
600a16187a7SStefano Zampini        messes up with the ordering. Just in case, allocate some memory and free it
601a16187a7SStefano Zampini        later */
602a16187a7SStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
603a16187a7SStefano Zampini       Mat_MPIAIJ *b = (Mat_MPIAIJ *)((*B)->data);
604a16187a7SStefano Zampini       PetscInt    mnz;
605a16187a7SStefano Zampini 
6069566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJGetMaxRowNonzeros(b->B, &mnz));
6079566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mnz, &ojj));
6089371c9d4SSatish Balay     } else
6099371c9d4SSatish Balay       for (i = 0; i < onnz; i++) ojj[i] = coffd[offdj[i]];
61063c07aadSStefano Zampini     iptr = ojj;
61163c07aadSStefano Zampini     aptr = oa;
61263c07aadSStefano Zampini     for (i = 0; i < m; i++) {
61363c07aadSStefano Zampini       PetscInt nc = oii[i + 1] - oii[i];
614a16187a7SStefano Zampini       if (reuse == MAT_REUSE_MATRIX) {
615a16187a7SStefano Zampini         PetscInt j;
616a16187a7SStefano Zampini 
617a16187a7SStefano Zampini         iptr = ojj;
618a16187a7SStefano Zampini         for (j = 0; j < nc; j++) iptr[j] = coffd[offdj[oii[i] + j]];
619a16187a7SStefano Zampini       }
6209566063dSJacob Faibussowitsch       PetscCall(PetscSortIntWithScalarArray(nc, iptr, aptr));
62163c07aadSStefano Zampini       iptr += nc;
62263c07aadSStefano Zampini       aptr += nc;
62363c07aadSStefano Zampini     }
6249566063dSJacob Faibussowitsch     if (reuse == MAT_REUSE_MATRIX) PetscCall(PetscFree(ojj));
625225daaf8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
62663c07aadSStefano Zampini       Mat_MPIAIJ *b;
62763c07aadSStefano Zampini       Mat_SeqAIJ *d, *o;
628225daaf8SStefano Zampini 
6299566063dSJacob Faibussowitsch       PetscCall(MatCreateMPIAIJWithSplitArrays(comm, m, n, PETSC_DECIDE, PETSC_DECIDE, dii, djj, da, oii, ojj, oa, B));
63063c07aadSStefano Zampini       /* hack MPIAIJ */
63163c07aadSStefano Zampini       b          = (Mat_MPIAIJ *)((*B)->data);
63263c07aadSStefano Zampini       d          = (Mat_SeqAIJ *)b->A->data;
63363c07aadSStefano Zampini       o          = (Mat_SeqAIJ *)b->B->data;
63463c07aadSStefano Zampini       d->free_a  = PETSC_TRUE;
63563c07aadSStefano Zampini       d->free_ij = PETSC_TRUE;
63663c07aadSStefano Zampini       o->free_a  = PETSC_TRUE;
63763c07aadSStefano Zampini       o->free_ij = PETSC_TRUE;
638225daaf8SStefano Zampini     } else if (reuse == MAT_INPLACE_MATRIX) {
639225daaf8SStefano Zampini       Mat T;
6402cf14000SStefano Zampini 
6419566063dSJacob Faibussowitsch       PetscCall(MatCreateMPIAIJWithSplitArrays(comm, m, n, PETSC_DECIDE, PETSC_DECIDE, dii, djj, da, oii, ojj, oa, &T));
642b73e3080SStefano Zampini       if (sameint && downs) { /* ownership of CSR pointers is transferred to PETSc */
643225daaf8SStefano Zampini         hypre_CSRMatrixI(hdiag) = NULL;
644225daaf8SStefano Zampini         hypre_CSRMatrixJ(hdiag) = NULL;
645b73e3080SStefano Zampini       } else { /* Hack MPIAIJ -> free ij but maybe not a */
6462cf14000SStefano Zampini         Mat_MPIAIJ *b = (Mat_MPIAIJ *)(T->data);
6472cf14000SStefano Zampini         Mat_SeqAIJ *d = (Mat_SeqAIJ *)(b->A->data);
6482cf14000SStefano Zampini 
6492cf14000SStefano Zampini         d->free_ij = PETSC_TRUE;
650b73e3080SStefano Zampini         d->free_a  = downs ? PETSC_FALSE : PETSC_TRUE;
651b73e3080SStefano Zampini       }
652b73e3080SStefano Zampini       if (sameint && oowns) { /* ownership of CSR pointers is transferred to PETSc */
653b73e3080SStefano Zampini         hypre_CSRMatrixI(hoffd) = NULL;
654b73e3080SStefano Zampini         hypre_CSRMatrixJ(hoffd) = NULL;
655b73e3080SStefano Zampini       } else { /* Hack MPIAIJ -> free ij but maybe not a */
656b73e3080SStefano Zampini         Mat_MPIAIJ *b = (Mat_MPIAIJ *)(T->data);
657b73e3080SStefano Zampini         Mat_SeqAIJ *o = (Mat_SeqAIJ *)(b->B->data);
658b73e3080SStefano Zampini 
6592cf14000SStefano Zampini         o->free_ij = PETSC_TRUE;
660b73e3080SStefano Zampini         o->free_a  = oowns ? PETSC_FALSE : PETSC_TRUE;
6612cf14000SStefano Zampini       }
6622cf14000SStefano Zampini       hypre_CSRMatrixData(hdiag) = NULL;
663225daaf8SStefano Zampini       hypre_CSRMatrixData(hoffd) = NULL;
6649566063dSJacob Faibussowitsch       PetscCall(MatHeaderReplace(A, &T));
66563c07aadSStefano Zampini     }
666225daaf8SStefano Zampini   } else {
667225daaf8SStefano Zampini     oii = NULL;
668225daaf8SStefano Zampini     ojj = NULL;
669225daaf8SStefano Zampini     oa  = NULL;
670225daaf8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
67163c07aadSStefano Zampini       Mat_SeqAIJ *b;
6722cf14000SStefano Zampini 
6739566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqAIJWithArrays(comm, m, n, dii, djj, da, B));
67463c07aadSStefano Zampini       /* hack SeqAIJ */
67563c07aadSStefano Zampini       b          = (Mat_SeqAIJ *)((*B)->data);
67663c07aadSStefano Zampini       b->free_a  = PETSC_TRUE;
67763c07aadSStefano Zampini       b->free_ij = PETSC_TRUE;
678225daaf8SStefano Zampini     } else if (reuse == MAT_INPLACE_MATRIX) {
679225daaf8SStefano Zampini       Mat T;
6802cf14000SStefano Zampini 
6819566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqAIJWithArrays(comm, m, n, dii, djj, da, &T));
682b73e3080SStefano Zampini       if (sameint && downs) { /* ownership of CSR pointers is transferred to PETSc */
683225daaf8SStefano Zampini         hypre_CSRMatrixI(hdiag) = NULL;
684225daaf8SStefano Zampini         hypre_CSRMatrixJ(hdiag) = NULL;
685b73e3080SStefano Zampini       } else { /* free ij but maybe not a */
6862cf14000SStefano Zampini         Mat_SeqAIJ *b = (Mat_SeqAIJ *)(T->data);
6872cf14000SStefano Zampini 
6882cf14000SStefano Zampini         b->free_ij = PETSC_TRUE;
689b73e3080SStefano Zampini         b->free_a  = downs ? PETSC_FALSE : PETSC_TRUE;
6902cf14000SStefano Zampini       }
691225daaf8SStefano Zampini       hypre_CSRMatrixData(hdiag) = NULL;
6929566063dSJacob Faibussowitsch       PetscCall(MatHeaderReplace(A, &T));
69363c07aadSStefano Zampini     }
694225daaf8SStefano Zampini   }
695225daaf8SStefano Zampini 
6962cf14000SStefano Zampini   /* we have to use hypre_Tfree to free the HYPRE arrays
697da81f932SPierre Jolivet      that PETSc now owns */
69863c07aadSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
6999371c9d4SSatish Balay     const char *names[6] = {"_hypre_csr_da", "_hypre_csr_oa", "_hypre_csr_dii", "_hypre_csr_djj", "_hypre_csr_oii", "_hypre_csr_ojj"};
700b73e3080SStefano Zampini     // clang-format off
701b73e3080SStefano Zampini     void *ptrs[6] = {downs ? da : NULL,
702b73e3080SStefano Zampini                      oowns ? oa : NULL,
703b73e3080SStefano Zampini                      downs && sameint ? dii : NULL,
704b73e3080SStefano Zampini                      downs && sameint ? djj : NULL,
705b73e3080SStefano Zampini                      oowns && sameint ? oii : NULL,
706b73e3080SStefano Zampini                      oowns && sameint ? ojj : NULL};
707b73e3080SStefano Zampini     // clang-format on
708b73e3080SStefano Zampini     for (i = 0; i < 6; i++) {
709225daaf8SStefano Zampini       PetscContainer c;
710225daaf8SStefano Zampini 
7119566063dSJacob Faibussowitsch       PetscCall(PetscContainerCreate(comm, &c));
7129566063dSJacob Faibussowitsch       PetscCall(PetscContainerSetPointer(c, ptrs[i]));
7139566063dSJacob Faibussowitsch       PetscCall(PetscContainerSetUserDestroy(c, hypre_array_destroy));
7149566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)(*B), names[i], (PetscObject)c));
7159566063dSJacob Faibussowitsch       PetscCall(PetscContainerDestroy(&c));
716225daaf8SStefano Zampini     }
71763c07aadSStefano Zampini   }
7183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71963c07aadSStefano Zampini }
72063c07aadSStefano Zampini 
721d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJGetParCSR_Private(Mat A, hypre_ParCSRMatrix **hA)
722d71ae5a4SJacob Faibussowitsch {
723613e5ff0Sstefano_zampini   hypre_ParCSRMatrix *tA;
724c1a070e6SStefano Zampini   hypre_CSRMatrix    *hdiag, *hoffd;
725c1a070e6SStefano Zampini   Mat_SeqAIJ         *diag, *offd;
7262cf14000SStefano Zampini   PetscInt           *garray, i, noffd, dnnz, onnz, *row_starts, *col_starts;
727c1a070e6SStefano Zampini   MPI_Comm            comm = PetscObjectComm((PetscObject)A);
728613e5ff0Sstefano_zampini   PetscBool           ismpiaij, isseqaij;
7292cf14000SStefano Zampini   PetscBool           sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
7306ea7df73SStefano Zampini   HYPRE_Int          *hdi = NULL, *hdj = NULL, *hoi = NULL, *hoj = NULL;
7315c97c10fSStefano Zampini   PetscInt           *pdi = NULL, *pdj = NULL, *poi = NULL, *poj = NULL;
7326ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
7336ea7df73SStefano Zampini   PetscBool iscuda = PETSC_FALSE;
7346ea7df73SStefano Zampini #endif
735c1a070e6SStefano Zampini 
736c1a070e6SStefano Zampini   PetscFunctionBegin;
7379566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
7389566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isseqaij));
73908401ef6SPierre Jolivet   PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Unsupported type %s", ((PetscObject)A)->type_name);
740ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
741c1a070e6SStefano Zampini   if (ismpiaij) {
742c1a070e6SStefano Zampini     Mat_MPIAIJ *a = (Mat_MPIAIJ *)(A->data);
743c1a070e6SStefano Zampini 
744c1a070e6SStefano Zampini     diag = (Mat_SeqAIJ *)a->A->data;
745c1a070e6SStefano Zampini     offd = (Mat_SeqAIJ *)a->B->data;
7466ea7df73SStefano Zampini #if defined(PETSC_HAVE_CUDA) && defined(PETSC_HAVE_HYPRE_DEVICE) && defined(HYPRE_USING_CUDA)
7479566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMPIAIJCUSPARSE, &iscuda));
7486ea7df73SStefano Zampini     if (iscuda && !A->boundtocpu) {
7496ea7df73SStefano Zampini       sameint = PETSC_TRUE;
7509566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJCUSPARSEGetIJ(a->A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
7519566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJCUSPARSEGetIJ(a->B, PETSC_FALSE, (const HYPRE_Int **)&hoi, (const HYPRE_Int **)&hoj));
7526ea7df73SStefano Zampini     } else {
7536ea7df73SStefano Zampini #else
7546ea7df73SStefano Zampini     {
7556ea7df73SStefano Zampini #endif
7566ea7df73SStefano Zampini       pdi = diag->i;
7576ea7df73SStefano Zampini       pdj = diag->j;
7586ea7df73SStefano Zampini       poi = offd->i;
7596ea7df73SStefano Zampini       poj = offd->j;
7606ea7df73SStefano Zampini       if (sameint) {
7616ea7df73SStefano Zampini         hdi = (HYPRE_Int *)pdi;
7626ea7df73SStefano Zampini         hdj = (HYPRE_Int *)pdj;
7636ea7df73SStefano Zampini         hoi = (HYPRE_Int *)poi;
7646ea7df73SStefano Zampini         hoj = (HYPRE_Int *)poj;
7656ea7df73SStefano Zampini       }
7666ea7df73SStefano Zampini     }
767c1a070e6SStefano Zampini     garray = a->garray;
768c1a070e6SStefano Zampini     noffd  = a->B->cmap->N;
769c1a070e6SStefano Zampini     dnnz   = diag->nz;
770c1a070e6SStefano Zampini     onnz   = offd->nz;
771c1a070e6SStefano Zampini   } else {
772c1a070e6SStefano Zampini     diag = (Mat_SeqAIJ *)A->data;
773c1a070e6SStefano Zampini     offd = NULL;
7746ea7df73SStefano Zampini #if defined(PETSC_HAVE_CUDA) && defined(PETSC_HAVE_HYPRE_DEVICE)
7759566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATSEQAIJCUSPARSE, &iscuda));
7766ea7df73SStefano Zampini     if (iscuda && !A->boundtocpu) {
7776ea7df73SStefano Zampini       sameint = PETSC_TRUE;
7789566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJCUSPARSEGetIJ(A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
7796ea7df73SStefano Zampini     } else {
7806ea7df73SStefano Zampini #else
7816ea7df73SStefano Zampini     {
7826ea7df73SStefano Zampini #endif
7836ea7df73SStefano Zampini       pdi = diag->i;
7846ea7df73SStefano Zampini       pdj = diag->j;
7856ea7df73SStefano Zampini       if (sameint) {
7866ea7df73SStefano Zampini         hdi = (HYPRE_Int *)pdi;
7876ea7df73SStefano Zampini         hdj = (HYPRE_Int *)pdj;
7886ea7df73SStefano Zampini       }
7896ea7df73SStefano Zampini     }
790c1a070e6SStefano Zampini     garray = NULL;
791c1a070e6SStefano Zampini     noffd  = 0;
792c1a070e6SStefano Zampini     dnnz   = diag->nz;
793c1a070e6SStefano Zampini     onnz   = 0;
794c1a070e6SStefano Zampini   }
795225daaf8SStefano Zampini 
796c1a070e6SStefano Zampini   /* create a temporary ParCSR */
797c1a070e6SStefano Zampini   if (HYPRE_AssumedPartitionCheck()) {
798c1a070e6SStefano Zampini     PetscMPIInt myid;
799c1a070e6SStefano Zampini 
8009566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &myid));
801c1a070e6SStefano Zampini     row_starts = A->rmap->range + myid;
802c1a070e6SStefano Zampini     col_starts = A->cmap->range + myid;
803c1a070e6SStefano Zampini   } else {
804c1a070e6SStefano Zampini     row_starts = A->rmap->range;
805c1a070e6SStefano Zampini     col_starts = A->cmap->range;
806c1a070e6SStefano Zampini   }
8072cf14000SStefano Zampini   tA = hypre_ParCSRMatrixCreate(comm, A->rmap->N, A->cmap->N, (HYPRE_BigInt *)row_starts, (HYPRE_BigInt *)col_starts, noffd, dnnz, onnz);
808a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
809c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetRowStartsOwner(tA, 0);
810c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetColStartsOwner(tA, 0);
811a1d2239cSSatish Balay #endif
812c1a070e6SStefano Zampini 
813225daaf8SStefano Zampini   /* set diagonal part */
814c1a070e6SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(tA);
8156ea7df73SStefano Zampini   if (!sameint) { /* malloc CSR pointers */
8169566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(A->rmap->n + 1, &hdi, dnnz, &hdj));
8176ea7df73SStefano Zampini     for (i = 0; i < A->rmap->n + 1; i++) hdi[i] = (HYPRE_Int)(pdi[i]);
8186ea7df73SStefano Zampini     for (i = 0; i < dnnz; i++) hdj[i] = (HYPRE_Int)(pdj[i]);
8192cf14000SStefano Zampini   }
8206ea7df73SStefano Zampini   hypre_CSRMatrixI(hdiag)           = hdi;
8216ea7df73SStefano Zampini   hypre_CSRMatrixJ(hdiag)           = hdj;
82239accc25SStefano Zampini   hypre_CSRMatrixData(hdiag)        = (HYPRE_Complex *)diag->a;
823c1a070e6SStefano Zampini   hypre_CSRMatrixNumNonzeros(hdiag) = diag->nz;
824c1a070e6SStefano Zampini   hypre_CSRMatrixSetRownnz(hdiag);
825c1a070e6SStefano Zampini   hypre_CSRMatrixSetDataOwner(hdiag, 0);
826c1a070e6SStefano Zampini 
827225daaf8SStefano Zampini   /* set offdiagonal part */
828c1a070e6SStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(tA);
829c1a070e6SStefano Zampini   if (offd) {
8306ea7df73SStefano Zampini     if (!sameint) { /* malloc CSR pointers */
8319566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(A->rmap->n + 1, &hoi, onnz, &hoj));
8326ea7df73SStefano Zampini       for (i = 0; i < A->rmap->n + 1; i++) hoi[i] = (HYPRE_Int)(poi[i]);
8336ea7df73SStefano Zampini       for (i = 0; i < onnz; i++) hoj[i] = (HYPRE_Int)(poj[i]);
8342cf14000SStefano Zampini     }
8356ea7df73SStefano Zampini     hypre_CSRMatrixI(hoffd)           = hoi;
8366ea7df73SStefano Zampini     hypre_CSRMatrixJ(hoffd)           = hoj;
83739accc25SStefano Zampini     hypre_CSRMatrixData(hoffd)        = (HYPRE_Complex *)offd->a;
838c1a070e6SStefano Zampini     hypre_CSRMatrixNumNonzeros(hoffd) = offd->nz;
839c1a070e6SStefano Zampini     hypre_CSRMatrixSetRownnz(hoffd);
840c1a070e6SStefano Zampini     hypre_CSRMatrixSetDataOwner(hoffd, 0);
8416ea7df73SStefano Zampini   }
8426ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
843792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, iscuda ? HYPRE_MEMORY_DEVICE : HYPRE_MEMORY_HOST);
8446ea7df73SStefano Zampini #else
8456ea7df73SStefano Zampini   #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0)
846792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixInitialize, tA);
8476ea7df73SStefano Zampini   #else
848792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, HYPRE_MEMORY_HOST);
8496ea7df73SStefano Zampini   #endif
8506ea7df73SStefano Zampini #endif
8516ea7df73SStefano Zampini   hypre_TFree(hypre_ParCSRMatrixColMapOffd(tA), HYPRE_MEMORY_HOST);
852c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetNumNonzeros(tA);
8532cf14000SStefano Zampini   hypre_ParCSRMatrixColMapOffd(tA) = (HYPRE_BigInt *)garray;
854792fecdfSBarry Smith   if (!hypre_ParCSRMatrixCommPkg(tA)) PetscCallExternal(hypre_MatvecCommPkgCreate, tA);
855613e5ff0Sstefano_zampini   *hA = tA;
8563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
857613e5ff0Sstefano_zampini }
858c1a070e6SStefano Zampini 
859d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJRestoreParCSR_Private(Mat A, hypre_ParCSRMatrix **hA)
860d71ae5a4SJacob Faibussowitsch {
861613e5ff0Sstefano_zampini   hypre_CSRMatrix *hdiag, *hoffd;
8626ea7df73SStefano Zampini   PetscBool        ismpiaij, sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
8636ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
8646ea7df73SStefano Zampini   PetscBool iscuda = PETSC_FALSE;
8656ea7df73SStefano Zampini #endif
866c1a070e6SStefano Zampini 
867613e5ff0Sstefano_zampini   PetscFunctionBegin;
8689566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
8696ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
8709566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, ""));
8716ea7df73SStefano Zampini   if (iscuda) sameint = PETSC_TRUE;
8726ea7df73SStefano Zampini #endif
873613e5ff0Sstefano_zampini   hdiag = hypre_ParCSRMatrixDiag(*hA);
874613e5ff0Sstefano_zampini   hoffd = hypre_ParCSRMatrixOffd(*hA);
8756ea7df73SStefano Zampini   /* free temporary memory allocated by PETSc
8766ea7df73SStefano Zampini      set pointers to NULL before destroying tA */
8772cf14000SStefano Zampini   if (!sameint) {
8782cf14000SStefano Zampini     HYPRE_Int *hi, *hj;
8792cf14000SStefano Zampini 
8802cf14000SStefano Zampini     hi = hypre_CSRMatrixI(hdiag);
8812cf14000SStefano Zampini     hj = hypre_CSRMatrixJ(hdiag);
8829566063dSJacob Faibussowitsch     PetscCall(PetscFree2(hi, hj));
8836ea7df73SStefano Zampini     if (ismpiaij) {
8842cf14000SStefano Zampini       hi = hypre_CSRMatrixI(hoffd);
8852cf14000SStefano Zampini       hj = hypre_CSRMatrixJ(hoffd);
8869566063dSJacob Faibussowitsch       PetscCall(PetscFree2(hi, hj));
8872cf14000SStefano Zampini     }
8882cf14000SStefano Zampini   }
889c1a070e6SStefano Zampini   hypre_CSRMatrixI(hdiag)    = NULL;
890c1a070e6SStefano Zampini   hypre_CSRMatrixJ(hdiag)    = NULL;
891c1a070e6SStefano Zampini   hypre_CSRMatrixData(hdiag) = NULL;
8926ea7df73SStefano Zampini   if (ismpiaij) {
893c1a070e6SStefano Zampini     hypre_CSRMatrixI(hoffd)    = NULL;
894c1a070e6SStefano Zampini     hypre_CSRMatrixJ(hoffd)    = NULL;
895c1a070e6SStefano Zampini     hypre_CSRMatrixData(hoffd) = NULL;
8966ea7df73SStefano Zampini   }
897613e5ff0Sstefano_zampini   hypre_ParCSRMatrixColMapOffd(*hA) = NULL;
898613e5ff0Sstefano_zampini   hypre_ParCSRMatrixDestroy(*hA);
899613e5ff0Sstefano_zampini   *hA = NULL;
9003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
901613e5ff0Sstefano_zampini }
902613e5ff0Sstefano_zampini 
903613e5ff0Sstefano_zampini /* calls RAP from BoomerAMG:
9043dad0653Sstefano_zampini    the resulting ParCSR will not own the column and row starts
9056ea7df73SStefano Zampini    It looks like we don't need to have the diagonal entries ordered first */
906d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_RAP(hypre_ParCSRMatrix *hR, hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hP, hypre_ParCSRMatrix **hRAP)
907d71ae5a4SJacob Faibussowitsch {
908a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
909613e5ff0Sstefano_zampini   HYPRE_Int P_owns_col_starts, R_owns_row_starts;
910a1d2239cSSatish Balay #endif
911613e5ff0Sstefano_zampini 
912613e5ff0Sstefano_zampini   PetscFunctionBegin;
913a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
914613e5ff0Sstefano_zampini   P_owns_col_starts = hypre_ParCSRMatrixOwnsColStarts(hP);
915613e5ff0Sstefano_zampini   R_owns_row_starts = hypre_ParCSRMatrixOwnsRowStarts(hR);
916a1d2239cSSatish Balay #endif
9176ea7df73SStefano Zampini   /* can be replaced by version test later */
9186ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
919792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParCSRMatrixRAP");
9206ea7df73SStefano Zampini   *hRAP = hypre_ParCSRMatrixRAP(hR, hA, hP);
9216ea7df73SStefano Zampini   PetscStackPop;
9226ea7df73SStefano Zampini #else
923792fecdfSBarry Smith   PetscCallExternal(hypre_BoomerAMGBuildCoarseOperator, hR, hA, hP, hRAP);
924792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixSetNumNonzeros, *hRAP);
9256ea7df73SStefano Zampini #endif
926613e5ff0Sstefano_zampini   /* hypre_BoomerAMGBuildCoarseOperator steals the col_starts from P and the row_starts from R */
927a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
928613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetRowStartsOwner(*hRAP, 0);
929613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetColStartsOwner(*hRAP, 0);
930613e5ff0Sstefano_zampini   if (P_owns_col_starts) hypre_ParCSRMatrixSetColStartsOwner(hP, 1);
931613e5ff0Sstefano_zampini   if (R_owns_row_starts) hypre_ParCSRMatrixSetRowStartsOwner(hR, 1);
932a1d2239cSSatish Balay #endif
9333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
934613e5ff0Sstefano_zampini }
935613e5ff0Sstefano_zampini 
936d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat P, Mat C)
937d71ae5a4SJacob Faibussowitsch {
9386f231fbdSstefano_zampini   Mat                 B;
9396abb4441SStefano Zampini   hypre_ParCSRMatrix *hA, *hP, *hPtAP = NULL;
9404222ddf1SHong Zhang   Mat_Product        *product = C->product;
941613e5ff0Sstefano_zampini 
942613e5ff0Sstefano_zampini   PetscFunctionBegin;
9439566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
9449566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(P, &hP));
9459566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(hP, hA, hP, &hPtAP));
9469566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hPtAP, MATAIJ, PETSC_OWN_POINTER, &B));
9474222ddf1SHong Zhang 
9489566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
9494222ddf1SHong Zhang   C->product = product;
9504222ddf1SHong Zhang 
9519566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
9529566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(P, &hP));
9533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9546f231fbdSstefano_zampini }
9556f231fbdSstefano_zampini 
956d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatPtAPSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat P, PetscReal fill, Mat C)
957d71ae5a4SJacob Faibussowitsch {
9586f231fbdSstefano_zampini   PetscFunctionBegin;
9599566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATAIJ));
9604222ddf1SHong Zhang   C->ops->ptapnumeric    = MatPtAPNumeric_AIJ_AIJ_wHYPRE;
9614222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
9623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
963613e5ff0Sstefano_zampini }
964613e5ff0Sstefano_zampini 
965d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_HYPRE(Mat A, Mat P, Mat C)
966d71ae5a4SJacob Faibussowitsch {
9674cc28894Sstefano_zampini   Mat                 B;
9684cc28894Sstefano_zampini   Mat_HYPRE          *hP;
9696abb4441SStefano Zampini   hypre_ParCSRMatrix *hA = NULL, *Pparcsr, *ptapparcsr = NULL;
970613e5ff0Sstefano_zampini   HYPRE_Int           type;
971613e5ff0Sstefano_zampini   MPI_Comm            comm = PetscObjectComm((PetscObject)A);
9724cc28894Sstefano_zampini   PetscBool           ishypre;
973613e5ff0Sstefano_zampini 
974613e5ff0Sstefano_zampini   PetscFunctionBegin;
9759566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre));
97628b400f6SJacob Faibussowitsch   PetscCheck(ishypre, comm, PETSC_ERR_USER, "P should be of type %s", MATHYPRE);
9774cc28894Sstefano_zampini   hP = (Mat_HYPRE *)P->data;
978792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type);
97908401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
980792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr);
981613e5ff0Sstefano_zampini 
9829566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
9839566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, hA, Pparcsr, &ptapparcsr));
9849566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
985225daaf8SStefano Zampini 
9864cc28894Sstefano_zampini   /* create temporary matrix and merge to C */
9879566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ptapparcsr, ((PetscObject)C)->type_name, PETSC_OWN_POINTER, &B));
9889566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
9893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9904cc28894Sstefano_zampini }
9914cc28894Sstefano_zampini 
992d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_HYPRE_HYPRE(Mat A, Mat P, Mat C)
993d71ae5a4SJacob Faibussowitsch {
9944cc28894Sstefano_zampini   Mat                 B;
9956abb4441SStefano Zampini   hypre_ParCSRMatrix *Aparcsr, *Pparcsr, *ptapparcsr = NULL;
9964cc28894Sstefano_zampini   Mat_HYPRE          *hA, *hP;
9974cc28894Sstefano_zampini   PetscBool           ishypre;
9984cc28894Sstefano_zampini   HYPRE_Int           type;
9994cc28894Sstefano_zampini 
10004cc28894Sstefano_zampini   PetscFunctionBegin;
10019566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre));
100228b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)P), PETSC_ERR_USER, "P should be of type %s", MATHYPRE);
10039566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
100428b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE);
10054cc28894Sstefano_zampini   hA = (Mat_HYPRE *)A->data;
10064cc28894Sstefano_zampini   hP = (Mat_HYPRE *)P->data;
1007792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
100808401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1009792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type);
101008401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)P), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1011792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr);
1012792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr);
10139566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, Aparcsr, Pparcsr, &ptapparcsr));
10149566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ptapparcsr, MATHYPRE, PETSC_OWN_POINTER, &B));
10159566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
10163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10174cc28894Sstefano_zampini }
10184cc28894Sstefano_zampini 
1019d501dc42Sstefano_zampini /* calls hypre_ParMatmul
1020d501dc42Sstefano_zampini    hypre_ParMatMul uses hypre_ParMatrixCreate with the communicator of hA
10213dad0653Sstefano_zampini    hypre_ParMatrixCreate does not duplicate the communicator
10226ea7df73SStefano Zampini    It looks like we don't need to have the diagonal entries ordered first */
1023d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_MatMatMult(hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hB, hypre_ParCSRMatrix **hAB)
1024d71ae5a4SJacob Faibussowitsch {
1025d501dc42Sstefano_zampini   PetscFunctionBegin;
10266ea7df73SStefano Zampini   /* can be replaced by version test later */
10276ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
1028792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParCSRMatMat");
10296ea7df73SStefano Zampini   *hAB = hypre_ParCSRMatMat(hA, hB);
10306ea7df73SStefano Zampini #else
1031792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParMatmul");
1032d501dc42Sstefano_zampini   *hAB = hypre_ParMatmul(hA, hB);
10336ea7df73SStefano Zampini #endif
1034d501dc42Sstefano_zampini   PetscStackPop;
10353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1036d501dc42Sstefano_zampini }
1037d501dc42Sstefano_zampini 
1038d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C)
1039d71ae5a4SJacob Faibussowitsch {
10405e5acdf2Sstefano_zampini   Mat                 D;
1041d501dc42Sstefano_zampini   hypre_ParCSRMatrix *hA, *hB, *hAB = NULL;
10424222ddf1SHong Zhang   Mat_Product        *product = C->product;
10435e5acdf2Sstefano_zampini 
10445e5acdf2Sstefano_zampini   PetscFunctionBegin;
10459566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
10469566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(B, &hB));
10479566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_MatMatMult(hA, hB, &hAB));
10489566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hAB, MATAIJ, PETSC_OWN_POINTER, &D));
10494222ddf1SHong Zhang 
10509566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &D));
10514222ddf1SHong Zhang   C->product = product;
10524222ddf1SHong Zhang 
10539566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
10549566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(B, &hB));
10553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10565e5acdf2Sstefano_zampini }
10575e5acdf2Sstefano_zampini 
1058d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatMatMultSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat B, PetscReal fill, Mat C)
1059d71ae5a4SJacob Faibussowitsch {
10605e5acdf2Sstefano_zampini   PetscFunctionBegin;
10619566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATAIJ));
10624222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_AIJ_AIJ_wHYPRE;
10634222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
10643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10655e5acdf2Sstefano_zampini }
10665e5acdf2Sstefano_zampini 
1067d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_HYPRE_HYPRE(Mat A, Mat B, Mat C)
1068d71ae5a4SJacob Faibussowitsch {
1069d501dc42Sstefano_zampini   Mat                 D;
1070d501dc42Sstefano_zampini   hypre_ParCSRMatrix *Aparcsr, *Bparcsr, *ABparcsr = NULL;
1071d501dc42Sstefano_zampini   Mat_HYPRE          *hA, *hB;
1072d501dc42Sstefano_zampini   PetscBool           ishypre;
1073d501dc42Sstefano_zampini   HYPRE_Int           type;
10744222ddf1SHong Zhang   Mat_Product        *product;
1075d501dc42Sstefano_zampini 
1076d501dc42Sstefano_zampini   PetscFunctionBegin;
10779566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)B, MATHYPRE, &ishypre));
107828b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)B), PETSC_ERR_USER, "B should be of type %s", MATHYPRE);
10799566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
108028b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE);
1081d501dc42Sstefano_zampini   hA = (Mat_HYPRE *)A->data;
1082d501dc42Sstefano_zampini   hB = (Mat_HYPRE *)B->data;
1083792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
108408401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1085792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hB->ij, &type);
108608401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1087792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr);
1088792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hB->ij, (void **)&Bparcsr);
10899566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_MatMatMult(Aparcsr, Bparcsr, &ABparcsr));
10909566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ABparcsr, MATHYPRE, PETSC_OWN_POINTER, &D));
10914222ddf1SHong Zhang 
1092d501dc42Sstefano_zampini   /* need to use HeaderReplace because HeaderMerge messes up with the communicator */
10934222ddf1SHong Zhang   product    = C->product; /* save it from MatHeaderReplace() */
10944222ddf1SHong Zhang   C->product = NULL;
10959566063dSJacob Faibussowitsch   PetscCall(MatHeaderReplace(C, &D));
10964222ddf1SHong Zhang   C->product             = product;
1097d501dc42Sstefano_zampini   C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE;
10984222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
10993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1100d501dc42Sstefano_zampini }
1101d501dc42Sstefano_zampini 
1102d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultNumeric_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, Mat D)
1103d71ae5a4SJacob Faibussowitsch {
110420e1dc0dSstefano_zampini   Mat                 E;
11056abb4441SStefano Zampini   hypre_ParCSRMatrix *hA, *hB, *hC, *hABC = NULL;
110620e1dc0dSstefano_zampini 
110720e1dc0dSstefano_zampini   PetscFunctionBegin;
11089566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
11099566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(B, &hB));
11109566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(C, &hC));
11119566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(hA, hB, hC, &hABC));
11129566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hABC, MATAIJ, PETSC_OWN_POINTER, &E));
11139566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(D, &E));
11149566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
11159566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(B, &hB));
11169566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(C, &hC));
11173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
111820e1dc0dSstefano_zampini }
111920e1dc0dSstefano_zampini 
1120d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultSymbolic_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, PetscReal fill, Mat D)
1121d71ae5a4SJacob Faibussowitsch {
112220e1dc0dSstefano_zampini   PetscFunctionBegin;
11239566063dSJacob Faibussowitsch   PetscCall(MatSetType(D, MATAIJ));
11243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
112520e1dc0dSstefano_zampini }
112620e1dc0dSstefano_zampini 
1127d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_AB_HYPRE(Mat C)
1128d71ae5a4SJacob Faibussowitsch {
11294222ddf1SHong Zhang   PetscFunctionBegin;
11304222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
11313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11324222ddf1SHong Zhang }
11334222ddf1SHong Zhang 
1134d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_AB(Mat C)
1135d71ae5a4SJacob Faibussowitsch {
11364222ddf1SHong Zhang   Mat_Product *product = C->product;
11374222ddf1SHong Zhang   PetscBool    Ahypre;
11384222ddf1SHong Zhang 
11394222ddf1SHong Zhang   PetscFunctionBegin;
11409566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)product->A, MATHYPRE, &Ahypre));
11414222ddf1SHong Zhang   if (Ahypre) { /* A is a Hypre matrix */
11429566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
11434222ddf1SHong Zhang     C->ops->productsymbolic = MatProductSymbolic_AB_HYPRE;
11444222ddf1SHong Zhang     C->ops->matmultnumeric  = MatMatMultNumeric_HYPRE_HYPRE;
11453ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
11466718818eSStefano Zampini   }
11473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11484222ddf1SHong Zhang }
11494222ddf1SHong Zhang 
1150d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_PtAP_HYPRE(Mat C)
1151d71ae5a4SJacob Faibussowitsch {
11524222ddf1SHong Zhang   PetscFunctionBegin;
11534222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
11543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11554222ddf1SHong Zhang }
11564222ddf1SHong Zhang 
1157d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_PtAP(Mat C)
1158d71ae5a4SJacob Faibussowitsch {
11594222ddf1SHong Zhang   Mat_Product *product = C->product;
11604222ddf1SHong Zhang   PetscBool    flg;
11614222ddf1SHong Zhang   PetscInt     type        = 0;
11624222ddf1SHong Zhang   const char  *outTypes[4] = {"aij", "seqaij", "mpiaij", "hypre"};
11634222ddf1SHong Zhang   PetscInt     ntype       = 4;
11644222ddf1SHong Zhang   Mat          A           = product->A;
11654222ddf1SHong Zhang   PetscBool    Ahypre;
11664222ddf1SHong Zhang 
11674222ddf1SHong Zhang   PetscFunctionBegin;
11689566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &Ahypre));
11694222ddf1SHong Zhang   if (Ahypre) { /* A is a Hypre matrix */
11709566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
11714222ddf1SHong Zhang     C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE;
11724222ddf1SHong Zhang     C->ops->ptapnumeric     = MatPtAPNumeric_HYPRE_HYPRE;
11733ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
11744222ddf1SHong Zhang   }
11754222ddf1SHong Zhang 
11764222ddf1SHong Zhang   /* A is AIJ, P is Hypre, C = PtAP can be either AIJ or Hypre format */
11774222ddf1SHong Zhang   /* Get runtime option */
11784222ddf1SHong Zhang   if (product->api_user) {
1179d0609cedSBarry Smith     PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatPtAP_HYPRE", "Mat");
11809566063dSJacob Faibussowitsch     PetscCall(PetscOptionsEList("-matptap_hypre_outtype", "MatPtAP outtype", "MatPtAP outtype", outTypes, ntype, outTypes[type], &type, &flg));
1181d0609cedSBarry Smith     PetscOptionsEnd();
11824222ddf1SHong Zhang   } else {
1183d0609cedSBarry Smith     PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatProduct_PtAP_HYPRE", "Mat");
11849566063dSJacob Faibussowitsch     PetscCall(PetscOptionsEList("-mat_product_algorithm_hypre_outtype", "MatProduct_PtAP outtype", "MatProduct_PtAP", outTypes, ntype, outTypes[type], &type, &flg));
1185d0609cedSBarry Smith     PetscOptionsEnd();
11864222ddf1SHong Zhang   }
11874222ddf1SHong Zhang 
11884222ddf1SHong Zhang   if (type == 0 || type == 1 || type == 2) {
11899566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATAIJ));
11904222ddf1SHong Zhang   } else if (type == 3) {
11919566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
11924222ddf1SHong Zhang   } else SETERRQ(PetscObjectComm((PetscObject)C), PETSC_ERR_SUP, "MatPtAP outtype is not supported");
11934222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE;
11944222ddf1SHong Zhang   C->ops->ptapnumeric     = MatPtAPNumeric_AIJ_HYPRE;
11953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11964222ddf1SHong Zhang }
11974222ddf1SHong Zhang 
1198d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE(Mat C)
1199d71ae5a4SJacob Faibussowitsch {
12004222ddf1SHong Zhang   Mat_Product *product = C->product;
12014222ddf1SHong Zhang 
12024222ddf1SHong Zhang   PetscFunctionBegin;
12034222ddf1SHong Zhang   switch (product->type) {
1204d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AB:
1205d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_HYPRE_AB(C));
1206d71ae5a4SJacob Faibussowitsch     break;
1207d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_PtAP:
1208d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_HYPRE_PtAP(C));
1209d71ae5a4SJacob Faibussowitsch     break;
1210d71ae5a4SJacob Faibussowitsch   default:
1211d71ae5a4SJacob Faibussowitsch     break;
12124222ddf1SHong Zhang   }
12133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12144222ddf1SHong Zhang }
12154222ddf1SHong Zhang 
1216d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTranspose_HYPRE(Mat A, Vec x, Vec y)
1217d71ae5a4SJacob Faibussowitsch {
121863c07aadSStefano Zampini   PetscFunctionBegin;
12199566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_TRUE));
12203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
122163c07aadSStefano Zampini }
122263c07aadSStefano Zampini 
1223d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_HYPRE(Mat A, Vec x, Vec y)
1224d71ae5a4SJacob Faibussowitsch {
122563c07aadSStefano Zampini   PetscFunctionBegin;
12269566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_FALSE));
12273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
122863c07aadSStefano Zampini }
122963c07aadSStefano Zampini 
1230d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultAdd_HYPRE(Mat A, Vec x, Vec y, Vec z)
1231d71ae5a4SJacob Faibussowitsch {
1232414bd5c3SStefano Zampini   PetscFunctionBegin;
123348a46eb9SPierre Jolivet   if (y != z) PetscCall(VecCopy(y, z));
12349566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_FALSE));
12353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1236414bd5c3SStefano Zampini }
1237414bd5c3SStefano Zampini 
1238d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTransposeAdd_HYPRE(Mat A, Vec x, Vec y, Vec z)
1239d71ae5a4SJacob Faibussowitsch {
1240414bd5c3SStefano Zampini   PetscFunctionBegin;
124148a46eb9SPierre Jolivet   if (y != z) PetscCall(VecCopy(y, z));
12429566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_TRUE));
12433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1244414bd5c3SStefano Zampini }
1245414bd5c3SStefano Zampini 
1246414bd5c3SStefano Zampini /* y = a * A * x + b * y or y = a * A^t * x + b * y depending on trans */
1247d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_MultKernel_Private(Mat A, HYPRE_Complex a, Vec x, HYPRE_Complex b, Vec y, PetscBool trans)
1248d71ae5a4SJacob Faibussowitsch {
124963c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE *)A->data;
125063c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
125163c07aadSStefano Zampini   hypre_ParVector    *hx, *hy;
125263c07aadSStefano Zampini 
125363c07aadSStefano Zampini   PetscFunctionBegin;
125463c07aadSStefano Zampini   if (trans) {
12559566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorPushVecRead(hA->b, x));
12569566063dSJacob Faibussowitsch     if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->x, y));
12579566063dSJacob Faibussowitsch     else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->x, y));
1258792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hx);
1259792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hy);
126063c07aadSStefano Zampini   } else {
12619566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorPushVecRead(hA->x, x));
12629566063dSJacob Faibussowitsch     if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->b, y));
12639566063dSJacob Faibussowitsch     else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->b, y));
1264792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hx);
1265792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hy);
126663c07aadSStefano Zampini   }
1267792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
12686ea7df73SStefano Zampini   if (trans) {
1269792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMatvecT, a, parcsr, hx, b, hy);
12706ea7df73SStefano Zampini   } else {
1271792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMatvec, a, parcsr, hx, b, hy);
12726ea7df73SStefano Zampini   }
12739566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hA->x));
12749566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hA->b));
12753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
127663c07aadSStefano Zampini }
127763c07aadSStefano Zampini 
1278d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_HYPRE(Mat A)
1279d71ae5a4SJacob Faibussowitsch {
128063c07aadSStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
128163c07aadSStefano Zampini 
128263c07aadSStefano Zampini   PetscFunctionBegin;
12839566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&hA->x));
12849566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&hA->b));
1285978814f1SStefano Zampini   if (hA->ij) {
1286978814f1SStefano Zampini     if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL;
1287792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixDestroy, hA->ij);
1288978814f1SStefano Zampini   }
12899566063dSJacob Faibussowitsch   if (hA->comm) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)A), &hA->comm));
1290c69f721fSFande Kong 
12919566063dSJacob Faibussowitsch   PetscCall(MatStashDestroy_Private(&A->stash));
12929566063dSJacob Faibussowitsch   PetscCall(PetscFree(hA->array));
1293c69f721fSFande Kong 
12945fbaff96SJunchao Zhang   if (hA->cooMat) {
12955fbaff96SJunchao Zhang     PetscCall(MatDestroy(&hA->cooMat));
1296e77caa6dSBarry Smith     PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hA->diagJ, hA->memType));
1297e77caa6dSBarry Smith     PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hA->offdJ, hA->memType));
1298e77caa6dSBarry Smith     PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hA->diag, hA->memType));
12995fbaff96SJunchao Zhang   }
13005fbaff96SJunchao Zhang 
13019566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_aij_C", NULL));
13029566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_is_C", NULL));
13039566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_hypre_C", NULL));
13049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaij_hypre_C", NULL));
13059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPRESetPreallocation_C", NULL));
13069566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPREGetParCSR_C", NULL));
13075fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL));
13085fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL));
13099566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->data));
13103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
131163c07aadSStefano Zampini }
131263c07aadSStefano Zampini 
1313d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetUp_HYPRE(Mat A)
1314d71ae5a4SJacob Faibussowitsch {
13154ec6421dSstefano_zampini   PetscFunctionBegin;
13169566063dSJacob Faibussowitsch   PetscCall(MatHYPRESetPreallocation(A, PETSC_DEFAULT, NULL, PETSC_DEFAULT, NULL));
13173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13184ec6421dSstefano_zampini }
13194ec6421dSstefano_zampini 
13206ea7df73SStefano Zampini //TODO FIX hypre_CSRMatrixMatvecOutOfPlace
13216ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
1322d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatBindToCPU_HYPRE(Mat A, PetscBool bind)
1323d71ae5a4SJacob Faibussowitsch {
13246ea7df73SStefano Zampini   Mat_HYPRE           *hA   = (Mat_HYPRE *)A->data;
13256ea7df73SStefano Zampini   HYPRE_MemoryLocation hmem = bind ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE;
13266ea7df73SStefano Zampini 
13276ea7df73SStefano Zampini   PetscFunctionBegin;
13286ea7df73SStefano Zampini   A->boundtocpu = bind;
13295fbaff96SJunchao Zhang   if (hA->ij && hypre_IJMatrixAssembleFlag(hA->ij) && hmem != hypre_IJMatrixMemoryLocation(hA->ij)) {
13306ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
1331792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
1332792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMigrate, parcsr, hmem);
13336ea7df73SStefano Zampini   }
13349566063dSJacob Faibussowitsch   if (hA->x) PetscCall(VecHYPRE_IJBindToCPU(hA->x, bind));
13359566063dSJacob Faibussowitsch   if (hA->b) PetscCall(VecHYPRE_IJBindToCPU(hA->b, bind));
13363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13376ea7df73SStefano Zampini }
13386ea7df73SStefano Zampini #endif
13396ea7df73SStefano Zampini 
1340d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_HYPRE(Mat A, MatAssemblyType mode)
1341d71ae5a4SJacob Faibussowitsch {
134263c07aadSStefano Zampini   Mat_HYPRE   *hA = (Mat_HYPRE *)A->data;
1343c69f721fSFande Kong   PetscMPIInt  n;
1344c69f721fSFande Kong   PetscInt     i, j, rstart, ncols, flg;
1345c69f721fSFande Kong   PetscInt    *row, *col;
1346c69f721fSFande Kong   PetscScalar *val;
134763c07aadSStefano Zampini 
134863c07aadSStefano Zampini   PetscFunctionBegin;
134908401ef6SPierre Jolivet   PetscCheck(mode != MAT_FLUSH_ASSEMBLY, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_FLUSH_ASSEMBLY currently not supported with MATHYPRE");
1350c69f721fSFande Kong 
1351c69f721fSFande Kong   if (!A->nooffprocentries) {
1352c69f721fSFande Kong     while (1) {
13539566063dSJacob Faibussowitsch       PetscCall(MatStashScatterGetMesg_Private(&A->stash, &n, &row, &col, &val, &flg));
1354c69f721fSFande Kong       if (!flg) break;
1355c69f721fSFande Kong 
1356c69f721fSFande Kong       for (i = 0; i < n;) {
1357c69f721fSFande Kong         /* Now identify the consecutive vals belonging to the same row */
1358c69f721fSFande Kong         for (j = i, rstart = row[j]; j < n; j++) {
1359c69f721fSFande Kong           if (row[j] != rstart) break;
1360c69f721fSFande Kong         }
1361c69f721fSFande Kong         if (j < n) ncols = j - i;
1362c69f721fSFande Kong         else ncols = n - i;
1363c69f721fSFande Kong         /* Now assemble all these values with a single function call */
13649566063dSJacob Faibussowitsch         PetscCall(MatSetValues_HYPRE(A, 1, row + i, ncols, col + i, val + i, A->insertmode));
1365c69f721fSFande Kong 
1366c69f721fSFande Kong         i = j;
1367c69f721fSFande Kong       }
1368c69f721fSFande Kong     }
13699566063dSJacob Faibussowitsch     PetscCall(MatStashScatterEnd_Private(&A->stash));
1370c69f721fSFande Kong   }
1371c69f721fSFande Kong 
1372792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixAssemble, hA->ij);
1373336664bdSPierre Jolivet   /* The assembly routine destroys the aux_matrix, we recreate it here by calling HYPRE_IJMatrixInitialize */
1374336664bdSPierre 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 */
1375*651b1cf9SStefano Zampini   if (!A->sortedfull) {
1376af1cf968SStefano Zampini     hypre_AuxParCSRMatrix *aux_matrix;
1377af1cf968SStefano Zampini 
1378af1cf968SStefano Zampini     /* call destroy just to make sure we do not leak anything */
1379af1cf968SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
1380792fecdfSBarry Smith     PetscCallExternal(hypre_AuxParCSRMatrixDestroy, aux_matrix);
1381af1cf968SStefano Zampini     hypre_IJMatrixTranslator(hA->ij) = NULL;
1382af1cf968SStefano Zampini 
1383af1cf968SStefano Zampini     /* Initialize with assembled flag -> it only recreates the aux_par_matrix */
1384792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij);
1385af1cf968SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
13866ea7df73SStefano Zampini     if (aux_matrix) {
1387af1cf968SStefano Zampini       hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1; /* see comment in MatHYPRESetPreallocation_HYPRE */
138822235d61SPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
1389792fecdfSBarry Smith       PetscCallExternal(hypre_AuxParCSRMatrixInitialize, aux_matrix);
139022235d61SPierre Jolivet #else
1391792fecdfSBarry Smith       PetscCallExternal(hypre_AuxParCSRMatrixInitialize_v2, aux_matrix, HYPRE_MEMORY_HOST);
139222235d61SPierre Jolivet #endif
1393af1cf968SStefano Zampini     }
13946ea7df73SStefano Zampini   }
13956ea7df73SStefano Zampini   {
13966ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
13976ea7df73SStefano Zampini 
1398792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
1399792fecdfSBarry Smith     if (!hypre_ParCSRMatrixCommPkg(parcsr)) PetscCallExternal(hypre_MatvecCommPkgCreate, parcsr);
14006ea7df73SStefano Zampini   }
14019566063dSJacob Faibussowitsch   if (!hA->x) PetscCall(VecHYPRE_IJVectorCreate(A->cmap, &hA->x));
14029566063dSJacob Faibussowitsch   if (!hA->b) PetscCall(VecHYPRE_IJVectorCreate(A->rmap, &hA->b));
14036ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
14049566063dSJacob Faibussowitsch   PetscCall(MatBindToCPU_HYPRE(A, A->boundtocpu));
14056ea7df73SStefano Zampini #endif
14063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
140763c07aadSStefano Zampini }
140863c07aadSStefano Zampini 
1409d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetArray_HYPRE(Mat A, PetscInt size, void **array)
1410d71ae5a4SJacob Faibussowitsch {
1411c69f721fSFande Kong   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1412c69f721fSFande Kong 
1413c69f721fSFande Kong   PetscFunctionBegin;
1414*651b1cf9SStefano Zampini   PetscCheck(hA->array_available, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Temporary space is in use");
1415c69f721fSFande Kong 
1416*651b1cf9SStefano Zampini   if (hA->array_size >= size) {
141739accc25SStefano Zampini     *array = hA->array;
141839accc25SStefano Zampini   } else {
14199566063dSJacob Faibussowitsch     PetscCall(PetscFree(hA->array));
1420*651b1cf9SStefano Zampini     hA->array_size = size;
1421*651b1cf9SStefano Zampini     PetscCall(PetscMalloc(hA->array_size, &hA->array));
1422c69f721fSFande Kong     *array = hA->array;
1423c69f721fSFande Kong   }
1424c69f721fSFande Kong 
1425*651b1cf9SStefano Zampini   hA->array_available = PETSC_FALSE;
14263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1427c69f721fSFande Kong }
1428c69f721fSFande Kong 
1429d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreArray_HYPRE(Mat A, void **array)
1430d71ae5a4SJacob Faibussowitsch {
1431c69f721fSFande Kong   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1432c69f721fSFande Kong 
1433c69f721fSFande Kong   PetscFunctionBegin;
1434c69f721fSFande Kong   *array              = NULL;
1435*651b1cf9SStefano Zampini   hA->array_available = PETSC_TRUE;
14363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1437c69f721fSFande Kong }
1438c69f721fSFande Kong 
1439d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_HYPRE(Mat A, PetscInt nr, const PetscInt rows[], PetscInt nc, const PetscInt cols[], const PetscScalar v[], InsertMode ins)
1440d71ae5a4SJacob Faibussowitsch {
1441d975228cSstefano_zampini   Mat_HYPRE     *hA   = (Mat_HYPRE *)A->data;
1442d975228cSstefano_zampini   PetscScalar   *vals = (PetscScalar *)v;
144339accc25SStefano Zampini   HYPRE_Complex *sscr;
1444c69f721fSFande Kong   PetscInt      *cscr[2];
1445c69f721fSFande Kong   PetscInt       i, nzc;
1446*651b1cf9SStefano Zampini   PetscInt       rst = A->rmap->rstart, ren = A->rmap->rend;
144708defe43SFande Kong   void          *array = NULL;
1448d975228cSstefano_zampini 
1449d975228cSstefano_zampini   PetscFunctionBegin;
14509566063dSJacob Faibussowitsch   PetscCall(MatGetArray_HYPRE(A, sizeof(PetscInt) * (2 * nc) + sizeof(HYPRE_Complex) * nc * nr, &array));
1451c69f721fSFande Kong   cscr[0] = (PetscInt *)array;
1452c69f721fSFande Kong   cscr[1] = ((PetscInt *)array) + nc;
145339accc25SStefano Zampini   sscr    = (HYPRE_Complex *)(((PetscInt *)array) + nc * 2);
1454d975228cSstefano_zampini   for (i = 0, nzc = 0; i < nc; i++) {
1455d975228cSstefano_zampini     if (cols[i] >= 0) {
1456d975228cSstefano_zampini       cscr[0][nzc]   = cols[i];
1457d975228cSstefano_zampini       cscr[1][nzc++] = i;
1458d975228cSstefano_zampini     }
1459d975228cSstefano_zampini   }
1460c69f721fSFande Kong   if (!nzc) {
14619566063dSJacob Faibussowitsch     PetscCall(MatRestoreArray_HYPRE(A, &array));
14623ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1463c69f721fSFande Kong   }
1464d975228cSstefano_zampini 
14656ea7df73SStefano Zampini #if 0 //defined(PETSC_HAVE_HYPRE_DEVICE)
14666ea7df73SStefano Zampini   if (HYPRE_MEMORY_HOST != hypre_IJMatrixMemoryLocation(hA->ij)) {
14676ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
14686ea7df73SStefano Zampini 
1469792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject,hA->ij,(void**)&parcsr);
1470792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMigrate,parcsr, HYPRE_MEMORY_HOST);
14716ea7df73SStefano Zampini   }
14726ea7df73SStefano Zampini #endif
14736ea7df73SStefano Zampini 
1474d975228cSstefano_zampini   if (ins == ADD_VALUES) {
1475d975228cSstefano_zampini     for (i = 0; i < nr; i++) {
14766ea7df73SStefano Zampini       if (rows[i] >= 0) {
1477d975228cSstefano_zampini         PetscInt  j;
14782cf14000SStefano Zampini         HYPRE_Int hnc = (HYPRE_Int)nzc;
14792cf14000SStefano Zampini 
1480*651b1cf9SStefano Zampini         if (!nzc) continue;
1481*651b1cf9SStefano Zampini         /* nonlocal values */
1482*651b1cf9SStefano Zampini         if (rows[i] < rst || rows[i] >= ren) {
1483*651b1cf9SStefano 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]);
1484*651b1cf9SStefano Zampini           if (hA->donotstash) continue;
1485*651b1cf9SStefano Zampini         }
1486aed4548fSBarry 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]);
14879566063dSJacob Faibussowitsch         for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j]));
1488792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixAddToValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr);
1489d975228cSstefano_zampini       }
1490d975228cSstefano_zampini       vals += nc;
1491d975228cSstefano_zampini     }
1492d975228cSstefano_zampini   } else { /* INSERT_VALUES */
1493d975228cSstefano_zampini     for (i = 0; i < nr; i++) {
14946ea7df73SStefano Zampini       if (rows[i] >= 0) {
1495d975228cSstefano_zampini         PetscInt  j;
14962cf14000SStefano Zampini         HYPRE_Int hnc = (HYPRE_Int)nzc;
14972cf14000SStefano Zampini 
1498*651b1cf9SStefano Zampini         if (!nzc) continue;
1499aed4548fSBarry 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]);
15009566063dSJacob Faibussowitsch         for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j]));
1501c69f721fSFande Kong         /* nonlocal values */
1502*651b1cf9SStefano Zampini         if (rows[i] < rst || rows[i] >= ren) {
1503*651b1cf9SStefano 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]);
1504*651b1cf9SStefano Zampini           if (!hA->donotstash) PetscCall(MatStashValuesRow_Private(&A->stash, rows[i], nzc, cscr[0], (PetscScalar *)sscr, PETSC_FALSE));
1505*651b1cf9SStefano Zampini         }
1506c69f721fSFande Kong         /* local values */
1507*651b1cf9SStefano Zampini         else
1508*651b1cf9SStefano Zampini           PetscCallExternal(HYPRE_IJMatrixSetValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr);
1509d975228cSstefano_zampini       }
1510d975228cSstefano_zampini       vals += nc;
1511d975228cSstefano_zampini     }
1512d975228cSstefano_zampini   }
1513c69f721fSFande Kong 
15149566063dSJacob Faibussowitsch   PetscCall(MatRestoreArray_HYPRE(A, &array));
15153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1516d975228cSstefano_zampini }
1517d975228cSstefano_zampini 
1518d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRESetPreallocation_HYPRE(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[])
1519d71ae5a4SJacob Faibussowitsch {
1520d975228cSstefano_zampini   Mat_HYPRE  *hA = (Mat_HYPRE *)A->data;
15217d968826Sstefano_zampini   HYPRE_Int  *hdnnz, *honnz;
152206a29025Sstefano_zampini   PetscInt    i, rs, re, cs, ce, bs;
1523d975228cSstefano_zampini   PetscMPIInt size;
1524d975228cSstefano_zampini 
1525d975228cSstefano_zampini   PetscFunctionBegin;
15269566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
15279566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
1528d975228cSstefano_zampini   rs = A->rmap->rstart;
1529d975228cSstefano_zampini   re = A->rmap->rend;
1530d975228cSstefano_zampini   cs = A->cmap->rstart;
1531d975228cSstefano_zampini   ce = A->cmap->rend;
1532d975228cSstefano_zampini   if (!hA->ij) {
1533792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rs, re - 1, cs, ce - 1, &hA->ij);
1534792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR);
1535d975228cSstefano_zampini   } else {
15362cf14000SStefano Zampini     HYPRE_BigInt hrs, hre, hcs, hce;
1537792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetLocalRange, hA->ij, &hrs, &hre, &hcs, &hce);
1538aed4548fSBarry 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);
1539aed4548fSBarry 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);
1540d975228cSstefano_zampini   }
15419566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(A, &bs));
154206a29025Sstefano_zampini   if (dnz == PETSC_DEFAULT || dnz == PETSC_DECIDE) dnz = 10 * bs;
154306a29025Sstefano_zampini   if (onz == PETSC_DEFAULT || onz == PETSC_DECIDE) onz = 10 * bs;
154406a29025Sstefano_zampini 
1545d975228cSstefano_zampini   if (!dnnz) {
15469566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->rmap->n, &hdnnz));
1547d975228cSstefano_zampini     for (i = 0; i < A->rmap->n; i++) hdnnz[i] = dnz;
1548d975228cSstefano_zampini   } else {
15497d968826Sstefano_zampini     hdnnz = (HYPRE_Int *)dnnz;
1550d975228cSstefano_zampini   }
15519566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
1552d975228cSstefano_zampini   if (size > 1) {
1553ddbeb582SStefano Zampini     hypre_AuxParCSRMatrix *aux_matrix;
1554d975228cSstefano_zampini     if (!onnz) {
15559566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(A->rmap->n, &honnz));
1556d975228cSstefano_zampini       for (i = 0; i < A->rmap->n; i++) honnz[i] = onz;
155722235d61SPierre Jolivet     } else honnz = (HYPRE_Int *)onnz;
1558ddbeb582SStefano Zampini     /* SetDiagOffdSizes sets hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0, since it seems
1559ddbeb582SStefano Zampini        they assume the user will input the entire row values, properly sorted
1560336664bdSPierre Jolivet        In PETSc, we don't make such an assumption and set this flag to 1,
1561336664bdSPierre Jolivet        unless the option MAT_SORTED_FULL is set to true.
1562ddbeb582SStefano Zampini        Also, to avoid possible memory leaks, we destroy and recreate the translator
1563ddbeb582SStefano Zampini        This has to be done here, as HYPRE_IJMatrixInitialize will properly initialize
1564ddbeb582SStefano Zampini        the IJ matrix for us */
1565ddbeb582SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
1566ddbeb582SStefano Zampini     hypre_AuxParCSRMatrixDestroy(aux_matrix);
1567ddbeb582SStefano Zampini     hypre_IJMatrixTranslator(hA->ij) = NULL;
1568792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, hA->ij, hdnnz, honnz);
1569ddbeb582SStefano Zampini     aux_matrix                               = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
1570*651b1cf9SStefano Zampini     hypre_AuxParCSRMatrixNeedAux(aux_matrix) = !A->sortedfull;
1571d975228cSstefano_zampini   } else {
1572d975228cSstefano_zampini     honnz = NULL;
1573792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetRowSizes, hA->ij, hdnnz);
1574d975228cSstefano_zampini   }
1575ddbeb582SStefano Zampini 
1576af1cf968SStefano Zampini   /* reset assembled flag and call the initialize method */
1577af1cf968SStefano Zampini   hypre_IJMatrixAssembleFlag(hA->ij) = 0;
15786ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
1579792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij);
15806ea7df73SStefano Zampini #else
1581792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize_v2, hA->ij, HYPRE_MEMORY_HOST);
15826ea7df73SStefano Zampini #endif
158348a46eb9SPierre Jolivet   if (!dnnz) PetscCall(PetscFree(hdnnz));
158448a46eb9SPierre Jolivet   if (!onnz && honnz) PetscCall(PetscFree(honnz));
1585af1cf968SStefano Zampini   /* Match AIJ logic */
158606a29025Sstefano_zampini   A->preallocated = PETSC_TRUE;
1587af1cf968SStefano Zampini   A->assembled    = PETSC_FALSE;
15883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1589d975228cSstefano_zampini }
1590d975228cSstefano_zampini 
1591d975228cSstefano_zampini /*@C
1592d975228cSstefano_zampini    MatHYPRESetPreallocation - Preallocates memory for a sparse parallel matrix in HYPRE IJ format
1593d975228cSstefano_zampini 
1594c3339decSBarry Smith    Collective
1595d975228cSstefano_zampini 
1596d975228cSstefano_zampini    Input Parameters:
1597d975228cSstefano_zampini +  A - the matrix
1598d975228cSstefano_zampini .  dnz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1599d975228cSstefano_zampini           (same value is used for all local rows)
1600d975228cSstefano_zampini .  dnnz - array containing the number of nonzeros in the various rows of the
1601d975228cSstefano_zampini           DIAGONAL portion of the local submatrix (possibly different for each row)
16022ef1f0ffSBarry Smith           or `NULL` (`PETSC_NULL_INTEGER` in Fortran), if `d_nz` is used to specify the nonzero structure.
16032ef1f0ffSBarry Smith           The size of this array is equal to the number of local rows, i.e `m`.
1604d975228cSstefano_zampini           For matrices that will be factored, you must leave room for (and set)
1605d975228cSstefano_zampini           the diagonal entry even if it is zero.
1606d975228cSstefano_zampini .  onz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1607d975228cSstefano_zampini           submatrix (same value is used for all local rows).
1608d975228cSstefano_zampini -  onnz - array containing the number of nonzeros in the various rows of the
1609d975228cSstefano_zampini           OFF-DIAGONAL portion of the local submatrix (possibly different for
16102ef1f0ffSBarry Smith           each row) or `NULL` (`PETSC_NULL_INTEGER` in Fortran), if `o_nz` is used to specify the nonzero
1611d975228cSstefano_zampini           structure. The size of this array is equal to the number
16122ef1f0ffSBarry Smith           of local rows, i.e `m`.
1613d975228cSstefano_zampini 
16142fe279fdSBarry Smith    Level: intermediate
16152fe279fdSBarry Smith 
161611a5261eSBarry Smith    Note:
16172ef1f0ffSBarry Smith     If the *nnz parameter is given then the *nz parameter is ignored; for sequential matrices, `onz` and `onnz` are ignored.
1618d975228cSstefano_zampini 
16191cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatMPIAIJSetPreallocation()`, `MATHYPRE`, `MATAIJ`
1620d975228cSstefano_zampini @*/
1621d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHYPRESetPreallocation(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[])
1622d71ae5a4SJacob Faibussowitsch {
1623d975228cSstefano_zampini   PetscFunctionBegin;
1624d975228cSstefano_zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1625d975228cSstefano_zampini   PetscValidType(A, 1);
1626cac4c232SBarry Smith   PetscTryMethod(A, "MatHYPRESetPreallocation_C", (Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]), (A, dnz, dnnz, onz, onnz));
16273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1628d975228cSstefano_zampini }
1629d975228cSstefano_zampini 
163020f4b53cSBarry Smith /*@C
16312ef1f0ffSBarry Smith    MatCreateFromParCSR - Creates a `Mat` from a `hypre_ParCSRMatrix`
1632225daaf8SStefano Zampini 
1633225daaf8SStefano Zampini    Collective
1634225daaf8SStefano Zampini 
1635225daaf8SStefano Zampini    Input Parameters:
16362ef1f0ffSBarry Smith +  parcsr   - the pointer to the `hypre_ParCSRMatrix`
16372ef1f0ffSBarry Smith .  mtype    - matrix type to be created. Currently `MATAIJ`, `MATIS` and `MATHYPRE` are supported.
163820f4b53cSBarry Smith -  copymode - PETSc copying options, see  `PetscCopyMode`
1639225daaf8SStefano Zampini 
1640225daaf8SStefano Zampini    Output Parameter:
1641225daaf8SStefano Zampini .  A  - the matrix
1642225daaf8SStefano Zampini 
1643225daaf8SStefano Zampini    Level: intermediate
1644225daaf8SStefano Zampini 
16451cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatHYPRE`, `PetscCopyMode`
164620f4b53cSBarry Smith @*/
1647d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreateFromParCSR(hypre_ParCSRMatrix *parcsr, MatType mtype, PetscCopyMode copymode, Mat *A)
1648d71ae5a4SJacob Faibussowitsch {
1649225daaf8SStefano Zampini   Mat        T;
1650978814f1SStefano Zampini   Mat_HYPRE *hA;
1651978814f1SStefano Zampini   MPI_Comm   comm;
1652978814f1SStefano Zampini   PetscInt   rstart, rend, cstart, cend, M, N;
1653d248a85cSRichard Tran Mills   PetscBool  isseqaij, isseqaijmkl, ismpiaij, isaij, ishyp, isis;
1654978814f1SStefano Zampini 
1655978814f1SStefano Zampini   PetscFunctionBegin;
1656978814f1SStefano Zampini   comm = hypre_ParCSRMatrixComm(parcsr);
16579566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQAIJ, &isseqaij));
16589566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQAIJMKL, &isseqaijmkl));
16599566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPIAIJ, &ismpiaij));
16609566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATAIJ, &isaij));
16619566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATHYPRE, &ishyp));
16629566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATIS, &isis));
1663d248a85cSRichard Tran Mills   isaij = (PetscBool)(isseqaij || isseqaijmkl || ismpiaij || isaij);
16646ea7df73SStefano Zampini   /* TODO */
1665aed4548fSBarry 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);
1666978814f1SStefano Zampini   /* access ParCSRMatrix */
1667978814f1SStefano Zampini   rstart = hypre_ParCSRMatrixFirstRowIndex(parcsr);
1668978814f1SStefano Zampini   rend   = hypre_ParCSRMatrixLastRowIndex(parcsr);
1669978814f1SStefano Zampini   cstart = hypre_ParCSRMatrixFirstColDiag(parcsr);
1670978814f1SStefano Zampini   cend   = hypre_ParCSRMatrixLastColDiag(parcsr);
1671978814f1SStefano Zampini   M      = hypre_ParCSRMatrixGlobalNumRows(parcsr);
1672978814f1SStefano Zampini   N      = hypre_ParCSRMatrixGlobalNumCols(parcsr);
1673978814f1SStefano Zampini 
1674fa92c42cSstefano_zampini   /* fix for empty local rows/columns */
1675fa92c42cSstefano_zampini   if (rend < rstart) rend = rstart;
1676fa92c42cSstefano_zampini   if (cend < cstart) cend = cstart;
1677fa92c42cSstefano_zampini 
1678e6471dc9SStefano Zampini   /* PETSc convention */
1679e6471dc9SStefano Zampini   rend++;
1680e6471dc9SStefano Zampini   cend++;
1681e6471dc9SStefano Zampini   rend = PetscMin(rend, M);
1682e6471dc9SStefano Zampini   cend = PetscMin(cend, N);
1683e6471dc9SStefano Zampini 
1684978814f1SStefano Zampini   /* create PETSc matrix with MatHYPRE */
16859566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, &T));
16869566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(T, rend - rstart, cend - cstart, M, N));
16879566063dSJacob Faibussowitsch   PetscCall(MatSetType(T, MATHYPRE));
1688225daaf8SStefano Zampini   hA = (Mat_HYPRE *)(T->data);
1689978814f1SStefano Zampini 
1690978814f1SStefano Zampini   /* create HYPRE_IJMatrix */
1691792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rstart, rend - 1, cstart, cend - 1, &hA->ij);
1692792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR);
169345b8d346SStefano Zampini 
16946ea7df73SStefano Zampini   // TODO DEV
169545b8d346SStefano Zampini   /* create new ParCSR object if needed */
169645b8d346SStefano Zampini   if (ishyp && copymode == PETSC_COPY_VALUES) {
169745b8d346SStefano Zampini     hypre_ParCSRMatrix *new_parcsr;
16986ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0)
169945b8d346SStefano Zampini     hypre_CSRMatrix *hdiag, *hoffd, *ndiag, *noffd;
170045b8d346SStefano Zampini 
17010e6427aaSSatish Balay     new_parcsr = hypre_ParCSRMatrixClone(parcsr, 0);
170245b8d346SStefano Zampini     hdiag      = hypre_ParCSRMatrixDiag(parcsr);
170345b8d346SStefano Zampini     hoffd      = hypre_ParCSRMatrixOffd(parcsr);
170445b8d346SStefano Zampini     ndiag      = hypre_ParCSRMatrixDiag(new_parcsr);
170545b8d346SStefano Zampini     noffd      = hypre_ParCSRMatrixOffd(new_parcsr);
17069566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hypre_CSRMatrixData(ndiag), hypre_CSRMatrixData(hdiag), hypre_CSRMatrixNumNonzeros(hdiag)));
17079566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hypre_CSRMatrixData(noffd), hypre_CSRMatrixData(hoffd), hypre_CSRMatrixNumNonzeros(hoffd)));
17086ea7df73SStefano Zampini #else
17096ea7df73SStefano Zampini     new_parcsr = hypre_ParCSRMatrixClone(parcsr, 1);
17106ea7df73SStefano Zampini #endif
171145b8d346SStefano Zampini     parcsr   = new_parcsr;
171245b8d346SStefano Zampini     copymode = PETSC_OWN_POINTER;
171345b8d346SStefano Zampini   }
1714978814f1SStefano Zampini 
1715978814f1SStefano Zampini   /* set ParCSR object */
1716978814f1SStefano Zampini   hypre_IJMatrixObject(hA->ij) = parcsr;
17174ec6421dSstefano_zampini   T->preallocated              = PETSC_TRUE;
1718978814f1SStefano Zampini 
1719978814f1SStefano Zampini   /* set assembled flag */
1720978814f1SStefano Zampini   hypre_IJMatrixAssembleFlag(hA->ij) = 1;
17216ea7df73SStefano Zampini #if 0
1722792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize,hA->ij);
17236ea7df73SStefano Zampini #endif
1724225daaf8SStefano Zampini   if (ishyp) {
17256d2a658fSstefano_zampini     PetscMPIInt myid = 0;
17266d2a658fSstefano_zampini 
17276d2a658fSstefano_zampini     /* make sure we always have row_starts and col_starts available */
172848a46eb9SPierre Jolivet     if (HYPRE_AssumedPartitionCheck()) PetscCallMPI(MPI_Comm_rank(comm, &myid));
1729a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
17306d2a658fSstefano_zampini     if (!hypre_ParCSRMatrixOwnsColStarts(parcsr)) {
17316d2a658fSstefano_zampini       PetscLayout map;
17326d2a658fSstefano_zampini 
17339566063dSJacob Faibussowitsch       PetscCall(MatGetLayouts(T, NULL, &map));
17349566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetUp(map));
17352cf14000SStefano Zampini       hypre_ParCSRMatrixColStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid);
17366d2a658fSstefano_zampini     }
17376d2a658fSstefano_zampini     if (!hypre_ParCSRMatrixOwnsRowStarts(parcsr)) {
17386d2a658fSstefano_zampini       PetscLayout map;
17396d2a658fSstefano_zampini 
17409566063dSJacob Faibussowitsch       PetscCall(MatGetLayouts(T, &map, NULL));
17419566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetUp(map));
17422cf14000SStefano Zampini       hypre_ParCSRMatrixRowStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid);
17436d2a658fSstefano_zampini     }
1744a1d2239cSSatish Balay #endif
1745978814f1SStefano Zampini     /* prevent from freeing the pointer */
1746978814f1SStefano Zampini     if (copymode == PETSC_USE_POINTER) hA->inner_free = PETSC_FALSE;
1747225daaf8SStefano Zampini     *A = T;
17489566063dSJacob Faibussowitsch     PetscCall(MatSetOption(*A, MAT_SORTED_FULL, PETSC_TRUE));
17499566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(*A, MAT_FINAL_ASSEMBLY));
17509566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(*A, MAT_FINAL_ASSEMBLY));
1751bb4689ddSStefano Zampini   } else if (isaij) {
1752bb4689ddSStefano Zampini     if (copymode != PETSC_OWN_POINTER) {
1753225daaf8SStefano Zampini       /* prevent from freeing the pointer */
1754225daaf8SStefano Zampini       hA->inner_free = PETSC_FALSE;
17559566063dSJacob Faibussowitsch       PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INITIAL_MATRIX, A));
17569566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&T));
1757225daaf8SStefano Zampini     } else { /* AIJ return type with PETSC_OWN_POINTER */
17589566063dSJacob Faibussowitsch       PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INPLACE_MATRIX, &T));
1759225daaf8SStefano Zampini       *A = T;
1760225daaf8SStefano Zampini     }
1761bb4689ddSStefano Zampini   } else if (isis) {
17629566063dSJacob Faibussowitsch     PetscCall(MatConvert_HYPRE_IS(T, MATIS, MAT_INITIAL_MATRIX, A));
17638cfe8d00SStefano Zampini     if (copymode != PETSC_OWN_POINTER) hA->inner_free = PETSC_FALSE;
17649566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&T));
1765bb4689ddSStefano Zampini   }
17663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1767978814f1SStefano Zampini }
1768978814f1SStefano Zampini 
1769d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPREGetParCSR_HYPRE(Mat A, hypre_ParCSRMatrix **parcsr)
1770d71ae5a4SJacob Faibussowitsch {
1771dd9c0a25Sstefano_zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1772dd9c0a25Sstefano_zampini   HYPRE_Int  type;
1773dd9c0a25Sstefano_zampini 
1774dd9c0a25Sstefano_zampini   PetscFunctionBegin;
177528b400f6SJacob Faibussowitsch   PetscCheck(hA->ij, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "HYPRE_IJMatrix not present");
1776792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
177708401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "HYPRE_IJMatrix is not of type HYPRE_PARCSR");
1778792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)parcsr);
17793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1780dd9c0a25Sstefano_zampini }
1781dd9c0a25Sstefano_zampini 
178220f4b53cSBarry Smith /*@C
1783dd9c0a25Sstefano_zampini    MatHYPREGetParCSR - Gets the pointer to the ParCSR matrix
1784dd9c0a25Sstefano_zampini 
17852ef1f0ffSBarry Smith    Not Collective
1786dd9c0a25Sstefano_zampini 
178720f4b53cSBarry Smith    Input Parameter:
178820f4b53cSBarry Smith .  A  - the `MATHYPRE` object
1789dd9c0a25Sstefano_zampini 
1790dd9c0a25Sstefano_zampini    Output Parameter:
17912ef1f0ffSBarry Smith .  parcsr  - the pointer to the `hypre_ParCSRMatrix`
1792dd9c0a25Sstefano_zampini 
1793dd9c0a25Sstefano_zampini    Level: intermediate
1794dd9c0a25Sstefano_zampini 
17951cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatHYPRE`, `PetscCopyMode`
179620f4b53cSBarry Smith @*/
1797d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHYPREGetParCSR(Mat A, hypre_ParCSRMatrix **parcsr)
1798d71ae5a4SJacob Faibussowitsch {
1799dd9c0a25Sstefano_zampini   PetscFunctionBegin;
1800dd9c0a25Sstefano_zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1801dd9c0a25Sstefano_zampini   PetscValidType(A, 1);
1802cac4c232SBarry Smith   PetscUseMethod(A, "MatHYPREGetParCSR_C", (Mat, hypre_ParCSRMatrix **), (A, parcsr));
18033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1804dd9c0a25Sstefano_zampini }
1805dd9c0a25Sstefano_zampini 
1806d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_HYPRE(Mat A, PetscBool *missing, PetscInt *dd)
1807d71ae5a4SJacob Faibussowitsch {
180868ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
180968ec7858SStefano Zampini   hypre_CSRMatrix    *ha;
181068ec7858SStefano Zampini   PetscInt            rst;
181168ec7858SStefano Zampini 
181268ec7858SStefano Zampini   PetscFunctionBegin;
181308401ef6SPierre Jolivet   PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented with non-square diagonal blocks");
18149566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &rst, NULL));
18159566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
181668ec7858SStefano Zampini   if (missing) *missing = PETSC_FALSE;
181768ec7858SStefano Zampini   if (dd) *dd = -1;
181868ec7858SStefano Zampini   ha = hypre_ParCSRMatrixDiag(parcsr);
181968ec7858SStefano Zampini   if (ha) {
182068299464SStefano Zampini     PetscInt   size, i;
182168299464SStefano Zampini     HYPRE_Int *ii, *jj;
182268ec7858SStefano Zampini 
182368ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
182468ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
182568ec7858SStefano Zampini     jj   = hypre_CSRMatrixJ(ha);
182668ec7858SStefano Zampini     for (i = 0; i < size; i++) {
182768ec7858SStefano Zampini       PetscInt  j;
182868ec7858SStefano Zampini       PetscBool found = PETSC_FALSE;
182968ec7858SStefano Zampini 
18309371c9d4SSatish Balay       for (j = ii[i]; j < ii[i + 1] && !found; j++) found = (jj[j] == i) ? PETSC_TRUE : PETSC_FALSE;
183168ec7858SStefano Zampini 
183268ec7858SStefano Zampini       if (!found) {
18333ba16761SJacob Faibussowitsch         PetscCall(PetscInfo(A, "Matrix is missing local diagonal entry %" PetscInt_FMT "\n", i));
183468ec7858SStefano Zampini         if (missing) *missing = PETSC_TRUE;
183568ec7858SStefano Zampini         if (dd) *dd = i + rst;
18363ba16761SJacob Faibussowitsch         PetscFunctionReturn(PETSC_SUCCESS);
183768ec7858SStefano Zampini       }
183868ec7858SStefano Zampini     }
183968ec7858SStefano Zampini     if (!size) {
18403ba16761SJacob Faibussowitsch       PetscCall(PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n"));
184168ec7858SStefano Zampini       if (missing) *missing = PETSC_TRUE;
184268ec7858SStefano Zampini       if (dd) *dd = rst;
184368ec7858SStefano Zampini     }
184468ec7858SStefano Zampini   } else {
18453ba16761SJacob Faibussowitsch     PetscCall(PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n"));
184668ec7858SStefano Zampini     if (missing) *missing = PETSC_TRUE;
184768ec7858SStefano Zampini     if (dd) *dd = rst;
184868ec7858SStefano Zampini   }
18493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
185068ec7858SStefano Zampini }
185168ec7858SStefano Zampini 
1852d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatScale_HYPRE(Mat A, PetscScalar s)
1853d71ae5a4SJacob Faibussowitsch {
185468ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
18556ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
185668ec7858SStefano Zampini   hypre_CSRMatrix *ha;
18576ea7df73SStefano Zampini #endif
185839accc25SStefano Zampini   HYPRE_Complex hs;
185968ec7858SStefano Zampini 
186068ec7858SStefano Zampini   PetscFunctionBegin;
18619566063dSJacob Faibussowitsch   PetscCall(PetscHYPREScalarCast(s, &hs));
18629566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
18636ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 19, 0)
1864792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixScale, parcsr, hs);
18656ea7df73SStefano Zampini #else /* diagonal part */
186668ec7858SStefano Zampini   ha = hypre_ParCSRMatrixDiag(parcsr);
186768ec7858SStefano Zampini   if (ha) {
186868299464SStefano Zampini     PetscInt       size, i;
186968299464SStefano Zampini     HYPRE_Int     *ii;
187039accc25SStefano Zampini     HYPRE_Complex *a;
187168ec7858SStefano Zampini 
187268ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
187368ec7858SStefano Zampini     a    = hypre_CSRMatrixData(ha);
187468ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
187539accc25SStefano Zampini     for (i = 0; i < ii[size]; i++) a[i] *= hs;
187668ec7858SStefano Zampini   }
187768ec7858SStefano Zampini   /* offdiagonal part */
187868ec7858SStefano Zampini   ha = hypre_ParCSRMatrixOffd(parcsr);
187968ec7858SStefano Zampini   if (ha) {
188068299464SStefano Zampini     PetscInt       size, i;
188168299464SStefano Zampini     HYPRE_Int     *ii;
188239accc25SStefano Zampini     HYPRE_Complex *a;
188368ec7858SStefano Zampini 
188468ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
188568ec7858SStefano Zampini     a    = hypre_CSRMatrixData(ha);
188668ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
188739accc25SStefano Zampini     for (i = 0; i < ii[size]; i++) a[i] *= hs;
188868ec7858SStefano Zampini   }
18896ea7df73SStefano Zampini #endif
18903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
189168ec7858SStefano Zampini }
189268ec7858SStefano Zampini 
1893d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_HYPRE(Mat A, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
1894d71ae5a4SJacob Faibussowitsch {
189568ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
189668299464SStefano Zampini   HYPRE_Int          *lrows;
189768299464SStefano Zampini   PetscInt            rst, ren, i;
189868ec7858SStefano Zampini 
189968ec7858SStefano Zampini   PetscFunctionBegin;
190008401ef6SPierre Jolivet   PetscCheck(!x && !b, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "To be implemented");
19019566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
19029566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numRows, &lrows));
19039566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &rst, &ren));
190468ec7858SStefano Zampini   for (i = 0; i < numRows; i++) {
19057a46b595SBarry Smith     PetscCheck(rows[i] >= rst && rows[i] < ren, PETSC_COMM_SELF, PETSC_ERR_SUP, "Non-local rows not yet supported");
190668ec7858SStefano Zampini     lrows[i] = rows[i] - rst;
190768ec7858SStefano Zampini   }
1908792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixEliminateRowsCols, parcsr, numRows, lrows);
19099566063dSJacob Faibussowitsch   PetscCall(PetscFree(lrows));
19103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
191168ec7858SStefano Zampini }
191268ec7858SStefano Zampini 
1913d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPRE_CSRMatrix(hypre_CSRMatrix *ha)
1914d71ae5a4SJacob Faibussowitsch {
1915c69f721fSFande Kong   PetscFunctionBegin;
1916c69f721fSFande Kong   if (ha) {
1917c69f721fSFande Kong     HYPRE_Int     *ii, size;
1918c69f721fSFande Kong     HYPRE_Complex *a;
1919c69f721fSFande Kong 
1920c69f721fSFande Kong     size = hypre_CSRMatrixNumRows(ha);
1921c69f721fSFande Kong     a    = hypre_CSRMatrixData(ha);
1922c69f721fSFande Kong     ii   = hypre_CSRMatrixI(ha);
1923c69f721fSFande Kong 
19249566063dSJacob Faibussowitsch     if (a) PetscCall(PetscArrayzero(a, ii[size]));
1925c69f721fSFande Kong   }
19263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1927c69f721fSFande Kong }
1928c69f721fSFande Kong 
1929d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroEntries_HYPRE(Mat A)
1930d71ae5a4SJacob Faibussowitsch {
19316ea7df73SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
19326ea7df73SStefano Zampini 
19336ea7df73SStefano Zampini   PetscFunctionBegin;
19346ea7df73SStefano Zampini   if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(hA->ij)) {
1935792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetConstantValues, hA->ij, 0.0);
19366ea7df73SStefano Zampini   } else {
1937c69f721fSFande Kong     hypre_ParCSRMatrix *parcsr;
1938c69f721fSFande Kong 
19399566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
19409566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr)));
19419566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr)));
19426ea7df73SStefano Zampini   }
19433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1944c69f721fSFande Kong }
1945c69f721fSFande Kong 
1946d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_HYPRE_CSRMatrix(hypre_CSRMatrix *hA, PetscInt N, const PetscInt rows[], HYPRE_Complex diag)
1947d71ae5a4SJacob Faibussowitsch {
194839accc25SStefano Zampini   PetscInt       ii;
194939accc25SStefano Zampini   HYPRE_Int     *i, *j;
195039accc25SStefano Zampini   HYPRE_Complex *a;
1951c69f721fSFande Kong 
1952c69f721fSFande Kong   PetscFunctionBegin;
19533ba16761SJacob Faibussowitsch   if (!hA) PetscFunctionReturn(PETSC_SUCCESS);
1954c69f721fSFande Kong 
195539accc25SStefano Zampini   i = hypre_CSRMatrixI(hA);
195639accc25SStefano Zampini   j = hypre_CSRMatrixJ(hA);
1957c69f721fSFande Kong   a = hypre_CSRMatrixData(hA);
1958c69f721fSFande Kong 
1959c69f721fSFande Kong   for (ii = 0; ii < N; ii++) {
196039accc25SStefano Zampini     HYPRE_Int jj, ibeg, iend, irow;
196139accc25SStefano Zampini 
1962c69f721fSFande Kong     irow = rows[ii];
1963c69f721fSFande Kong     ibeg = i[irow];
1964c69f721fSFande Kong     iend = i[irow + 1];
1965c69f721fSFande Kong     for (jj = ibeg; jj < iend; jj++)
1966c69f721fSFande Kong       if (j[jj] == irow) a[jj] = diag;
1967c69f721fSFande Kong       else a[jj] = 0.0;
1968c69f721fSFande Kong   }
19693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1970c69f721fSFande Kong }
1971c69f721fSFande Kong 
1972d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_HYPRE(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
1973d71ae5a4SJacob Faibussowitsch {
1974c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
1975c69f721fSFande Kong   PetscInt           *lrows, len;
197639accc25SStefano Zampini   HYPRE_Complex       hdiag;
1977c69f721fSFande Kong 
1978c69f721fSFande Kong   PetscFunctionBegin;
197908401ef6SPierre Jolivet   PetscCheck(!x && !b, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Does not support to modify the solution and the right hand size");
19809566063dSJacob Faibussowitsch   PetscCall(PetscHYPREScalarCast(diag, &hdiag));
1981c69f721fSFande Kong   /* retrieve the internal matrix */
19829566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
1983c69f721fSFande Kong   /* get locally owned rows */
19849566063dSJacob Faibussowitsch   PetscCall(MatZeroRowsMapLocal_Private(A, N, rows, &len, &lrows));
1985c69f721fSFande Kong   /* zero diagonal part */
19869566063dSJacob Faibussowitsch   PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr), len, lrows, hdiag));
1987c69f721fSFande Kong   /* zero off-diagonal part */
19889566063dSJacob Faibussowitsch   PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr), len, lrows, 0.0));
1989c69f721fSFande Kong 
19909566063dSJacob Faibussowitsch   PetscCall(PetscFree(lrows));
19913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1992c69f721fSFande Kong }
1993c69f721fSFande Kong 
1994d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_HYPRE(Mat mat, MatAssemblyType mode)
1995d71ae5a4SJacob Faibussowitsch {
1996c69f721fSFande Kong   PetscFunctionBegin;
19973ba16761SJacob Faibussowitsch   if (mat->nooffprocentries) PetscFunctionReturn(PETSC_SUCCESS);
1998c69f721fSFande Kong 
19999566063dSJacob Faibussowitsch   PetscCall(MatStashScatterBegin_Private(mat, &mat->stash, mat->rmap->range));
20003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2001c69f721fSFande Kong }
2002c69f721fSFande Kong 
2003d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
2004d71ae5a4SJacob Faibussowitsch {
2005c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
20062cf14000SStefano Zampini   HYPRE_Int           hnz;
2007c69f721fSFande Kong 
2008c69f721fSFande Kong   PetscFunctionBegin;
2009c69f721fSFande Kong   /* retrieve the internal matrix */
20109566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
2011c69f721fSFande Kong   /* call HYPRE API */
2012792fecdfSBarry Smith   PetscCallExternal(HYPRE_ParCSRMatrixGetRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v);
20132cf14000SStefano Zampini   if (nz) *nz = (PetscInt)hnz;
20143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2015c69f721fSFande Kong }
2016c69f721fSFande Kong 
2017d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
2018d71ae5a4SJacob Faibussowitsch {
2019c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
20202cf14000SStefano Zampini   HYPRE_Int           hnz;
2021c69f721fSFande Kong 
2022c69f721fSFande Kong   PetscFunctionBegin;
2023c69f721fSFande Kong   /* retrieve the internal matrix */
20249566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
2025c69f721fSFande Kong   /* call HYPRE API */
20262cf14000SStefano Zampini   hnz = nz ? (HYPRE_Int)(*nz) : 0;
2027792fecdfSBarry Smith   PetscCallExternal(HYPRE_ParCSRMatrixRestoreRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v);
20283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2029c69f721fSFande Kong }
2030c69f721fSFande Kong 
2031d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetValues_HYPRE(Mat A, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2032d71ae5a4SJacob Faibussowitsch {
203345b8d346SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
2034c69f721fSFande Kong   PetscInt   i;
20351d4906efSStefano Zampini 
2036c69f721fSFande Kong   PetscFunctionBegin;
20373ba16761SJacob Faibussowitsch   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2038c69f721fSFande Kong   /* Ignore negative row indices
2039c69f721fSFande Kong    * And negative column indices should be automatically ignored in hypre
2040c69f721fSFande Kong    * */
20412cf14000SStefano Zampini   for (i = 0; i < m; i++) {
20422cf14000SStefano Zampini     if (idxm[i] >= 0) {
20432cf14000SStefano Zampini       HYPRE_Int hn = (HYPRE_Int)n;
2044792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetValues, hA->ij, 1, &hn, (HYPRE_BigInt *)&idxm[i], (HYPRE_BigInt *)idxn, (HYPRE_Complex *)(v + i * n));
20452cf14000SStefano Zampini     }
20462cf14000SStefano Zampini   }
20473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2048c69f721fSFande Kong }
2049c69f721fSFande Kong 
2050d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_HYPRE(Mat A, MatOption op, PetscBool flg)
2051d71ae5a4SJacob Faibussowitsch {
2052ddbeb582SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
2053ddbeb582SStefano Zampini 
2054ddbeb582SStefano Zampini   PetscFunctionBegin;
2055c6698e78SStefano Zampini   switch (op) {
2056ddbeb582SStefano Zampini   case MAT_NO_OFF_PROC_ENTRIES:
205748a46eb9SPierre Jolivet     if (flg) PetscCallExternal(HYPRE_IJMatrixSetMaxOffProcElmts, hA->ij, 0);
2058ddbeb582SStefano Zampini     break;
2059*651b1cf9SStefano Zampini   case MAT_IGNORE_OFF_PROC_ENTRIES:
2060*651b1cf9SStefano Zampini     hA->donotstash = flg;
2061d71ae5a4SJacob Faibussowitsch     break;
2062d71ae5a4SJacob Faibussowitsch   default:
2063d71ae5a4SJacob Faibussowitsch     break;
2064ddbeb582SStefano Zampini   }
20653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2066ddbeb582SStefano Zampini }
2067c69f721fSFande Kong 
2068d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_HYPRE(Mat A, PetscViewer view)
2069d71ae5a4SJacob Faibussowitsch {
207045b8d346SStefano Zampini   PetscViewerFormat format;
207145b8d346SStefano Zampini 
207245b8d346SStefano Zampini   PetscFunctionBegin;
20739566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(view, &format));
20743ba16761SJacob Faibussowitsch   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(PETSC_SUCCESS);
207545b8d346SStefano Zampini   if (format != PETSC_VIEWER_NATIVE) {
20766ea7df73SStefano Zampini     Mat                 B;
20776ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
20786ea7df73SStefano Zampini     PetscErrorCode (*mview)(Mat, PetscViewer) = NULL;
20796ea7df73SStefano Zampini 
20809566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
20819566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(parcsr, MATAIJ, PETSC_USE_POINTER, &B));
20829566063dSJacob Faibussowitsch     PetscCall(MatGetOperation(B, MATOP_VIEW, (void (**)(void)) & mview));
208328b400f6SJacob Faibussowitsch     PetscCheck(mview, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Missing view operation");
20849566063dSJacob Faibussowitsch     PetscCall((*mview)(B, view));
20859566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
208645b8d346SStefano Zampini   } else {
208745b8d346SStefano Zampini     Mat_HYPRE  *hA = (Mat_HYPRE *)A->data;
208845b8d346SStefano Zampini     PetscMPIInt size;
208945b8d346SStefano Zampini     PetscBool   isascii;
209045b8d346SStefano Zampini     const char *filename;
209145b8d346SStefano Zampini 
209245b8d346SStefano Zampini     /* HYPRE uses only text files */
20939566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERASCII, &isascii));
209428b400f6SJacob Faibussowitsch     PetscCheck(isascii, PetscObjectComm((PetscObject)view), PETSC_ERR_SUP, "PetscViewerType %s: native HYPRE format needs PETSCVIEWERASCII", ((PetscObject)view)->type_name);
20959566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileGetName(view, &filename));
2096792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixPrint, hA->ij, filename);
20979566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(hA->comm, &size));
209845b8d346SStefano Zampini     if (size > 1) {
20999566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(view, "Matrix files: %s.%05d ... %s.%05d\n", filename, 0, filename, size - 1));
210045b8d346SStefano Zampini     } else {
21019566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(view, "Matrix file: %s.%05d\n", filename, 0));
210245b8d346SStefano Zampini     }
210345b8d346SStefano Zampini   }
21043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
210545b8d346SStefano Zampini }
210645b8d346SStefano Zampini 
2107d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCopy_HYPRE(Mat A, Mat B, MatStructure str)
2108d71ae5a4SJacob Faibussowitsch {
2109465edc17SStefano Zampini   hypre_ParCSRMatrix *acsr, *bcsr;
2110465edc17SStefano Zampini 
2111465edc17SStefano Zampini   PetscFunctionBegin;
2112465edc17SStefano Zampini   if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) {
21139566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &acsr));
21149566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(B, &bcsr));
2115792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixCopy, acsr, bcsr, 1);
21169566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_SORTED_FULL, PETSC_TRUE)); /* "perfect" preallocation, so no need for hypre_AuxParCSRMatrixNeedAux */
21179566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
21189566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
2119465edc17SStefano Zampini   } else {
21209566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
2121465edc17SStefano Zampini   }
21223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2123465edc17SStefano Zampini }
2124465edc17SStefano Zampini 
2125d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_HYPRE(Mat A, Vec d)
2126d71ae5a4SJacob Faibussowitsch {
21276305df00SStefano Zampini   hypre_ParCSRMatrix *parcsr;
21286305df00SStefano Zampini   hypre_CSRMatrix    *dmat;
212939accc25SStefano Zampini   HYPRE_Complex      *a;
213039accc25SStefano Zampini   HYPRE_Complex      *data = NULL;
21312cf14000SStefano Zampini   HYPRE_Int          *diag = NULL;
21322cf14000SStefano Zampini   PetscInt            i;
21336305df00SStefano Zampini   PetscBool           cong;
21346305df00SStefano Zampini 
21356305df00SStefano Zampini   PetscFunctionBegin;
21369566063dSJacob Faibussowitsch   PetscCall(MatHasCongruentLayouts(A, &cong));
213728b400f6SJacob Faibussowitsch   PetscCheck(cong, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only for square matrices with same local distributions of rows and columns");
213876bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
21396305df00SStefano Zampini     PetscBool miss;
21409566063dSJacob Faibussowitsch     PetscCall(MatMissingDiagonal(A, &miss, NULL));
214108401ef6SPierre Jolivet     PetscCheck(!miss || !A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented when diagonal entries are missing");
21426305df00SStefano Zampini   }
21439566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
21446305df00SStefano Zampini   dmat = hypre_ParCSRMatrixDiag(parcsr);
21456305df00SStefano Zampini   if (dmat) {
214639accc25SStefano Zampini     /* this cast fixes the clang error: implicit conversion from 'HYPRE_Complex' (aka '_Complex double') to 'double' is not permitted in C++ */
21479566063dSJacob Faibussowitsch     PetscCall(VecGetArray(d, (PetscScalar **)&a));
21482cf14000SStefano Zampini     diag = hypre_CSRMatrixI(dmat);
214939accc25SStefano Zampini     data = hypre_CSRMatrixData(dmat);
21506305df00SStefano Zampini     for (i = 0; i < A->rmap->n; i++) a[i] = data[diag[i]];
21519566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(d, (PetscScalar **)&a));
21526305df00SStefano Zampini   }
21533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21546305df00SStefano Zampini }
21556305df00SStefano Zampini 
2156363d496dSStefano Zampini #include <petscblaslapack.h>
2157363d496dSStefano Zampini 
2158d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAXPY_HYPRE(Mat Y, PetscScalar a, Mat X, MatStructure str)
2159d71ae5a4SJacob Faibussowitsch {
2160363d496dSStefano Zampini   PetscFunctionBegin;
21616ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
21626ea7df73SStefano Zampini   {
21636ea7df73SStefano Zampini     Mat                 B;
21646ea7df73SStefano Zampini     hypre_ParCSRMatrix *x, *y, *z;
21656ea7df73SStefano Zampini 
21669566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(Y, &y));
21679566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(X, &x));
2168792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixAdd, 1.0, y, 1.0, x, &z);
21699566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(z, MATHYPRE, PETSC_OWN_POINTER, &B));
21709566063dSJacob Faibussowitsch     PetscCall(MatHeaderMerge(Y, &B));
21716ea7df73SStefano Zampini   }
21726ea7df73SStefano Zampini #else
2173363d496dSStefano Zampini   if (str == SAME_NONZERO_PATTERN) {
2174363d496dSStefano Zampini     hypre_ParCSRMatrix *x, *y;
2175363d496dSStefano Zampini     hypre_CSRMatrix    *xloc, *yloc;
2176363d496dSStefano Zampini     PetscInt            xnnz, ynnz;
217739accc25SStefano Zampini     HYPRE_Complex      *xarr, *yarr;
2178363d496dSStefano Zampini     PetscBLASInt        one = 1, bnz;
2179363d496dSStefano Zampini 
21809566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(Y, &y));
21819566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(X, &x));
2182363d496dSStefano Zampini 
2183363d496dSStefano Zampini     /* diagonal block */
2184363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixDiag(x);
2185363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixDiag(y);
2186363d496dSStefano Zampini     xnnz = 0;
2187363d496dSStefano Zampini     ynnz = 0;
2188363d496dSStefano Zampini     xarr = NULL;
2189363d496dSStefano Zampini     yarr = NULL;
2190363d496dSStefano Zampini     if (xloc) {
219139accc25SStefano Zampini       xarr = hypre_CSRMatrixData(xloc);
2192363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
2193363d496dSStefano Zampini     }
2194363d496dSStefano Zampini     if (yloc) {
219539accc25SStefano Zampini       yarr = hypre_CSRMatrixData(yloc);
2196363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
2197363d496dSStefano Zampini     }
219808401ef6SPierre Jolivet     PetscCheck(xnnz == ynnz, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Different number of nonzeros in diagonal block %" PetscInt_FMT " != %" PetscInt_FMT, xnnz, ynnz);
21999566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(xnnz, &bnz));
2200792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one));
2201363d496dSStefano Zampini 
2202363d496dSStefano Zampini     /* off-diagonal block */
2203363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixOffd(x);
2204363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixOffd(y);
2205363d496dSStefano Zampini     xnnz = 0;
2206363d496dSStefano Zampini     ynnz = 0;
2207363d496dSStefano Zampini     xarr = NULL;
2208363d496dSStefano Zampini     yarr = NULL;
2209363d496dSStefano Zampini     if (xloc) {
221039accc25SStefano Zampini       xarr = hypre_CSRMatrixData(xloc);
2211363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
2212363d496dSStefano Zampini     }
2213363d496dSStefano Zampini     if (yloc) {
221439accc25SStefano Zampini       yarr = hypre_CSRMatrixData(yloc);
2215363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
2216363d496dSStefano Zampini     }
221708401ef6SPierre 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);
22189566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(xnnz, &bnz));
2219792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one));
2220363d496dSStefano Zampini   } else if (str == SUBSET_NONZERO_PATTERN) {
22219566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic(Y, a, X, str));
2222363d496dSStefano Zampini   } else {
2223363d496dSStefano Zampini     Mat B;
2224363d496dSStefano Zampini 
22259566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic_Preallocate(Y, X, &B));
22269566063dSJacob Faibussowitsch     PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str));
22279566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(Y, &B));
2228363d496dSStefano Zampini   }
22296ea7df73SStefano Zampini #endif
22303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2231363d496dSStefano Zampini }
2232363d496dSStefano Zampini 
22332c4ab24aSJunchao Zhang /* Attach cooMat to hypre matrix mat. The two matrices will share the same data array */
22342c4ab24aSJunchao Zhang static PetscErrorCode MatAttachCOOMat_HYPRE(Mat mat, Mat cooMat)
22352c4ab24aSJunchao Zhang {
22362c4ab24aSJunchao Zhang   Mat_HYPRE           *hmat = (Mat_HYPRE *)mat->data;
22372c4ab24aSJunchao Zhang   hypre_CSRMatrix     *diag, *offd;
22382c4ab24aSJunchao Zhang   hypre_ParCSRMatrix  *parCSR;
22392c4ab24aSJunchao Zhang   HYPRE_MemoryLocation hypreMemtype = HYPRE_MEMORY_HOST;
22402c4ab24aSJunchao Zhang   PetscMemType         petscMemtype;
22412c4ab24aSJunchao Zhang   Mat                  A, B;
22422c4ab24aSJunchao Zhang   PetscScalar         *Aa, *Ba;
22432c4ab24aSJunchao Zhang   PetscMPIInt          size;
22442c4ab24aSJunchao Zhang   MPI_Comm             comm;
22452c4ab24aSJunchao Zhang   PetscLayout          rmap;
22462c4ab24aSJunchao Zhang 
22472c4ab24aSJunchao Zhang   PetscFunctionBegin;
22482c4ab24aSJunchao Zhang   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
22492c4ab24aSJunchao Zhang   PetscCallMPI(MPI_Comm_size(comm, &size));
22502c4ab24aSJunchao Zhang   PetscCall(MatGetLayouts(mat, &rmap, NULL));
22512c4ab24aSJunchao Zhang 
22522c4ab24aSJunchao Zhang   /* Alias cooMat's data array to IJMatrix's */
22532c4ab24aSJunchao Zhang   PetscCallExternal(HYPRE_IJMatrixGetObject, hmat->ij, (void **)&parCSR);
22542c4ab24aSJunchao Zhang   diag = hypre_ParCSRMatrixDiag(parCSR);
22552c4ab24aSJunchao Zhang   offd = hypre_ParCSRMatrixOffd(parCSR);
22562c4ab24aSJunchao Zhang 
22572c4ab24aSJunchao Zhang   hypreMemtype = hypre_CSRMatrixMemoryLocation(diag);
22582c4ab24aSJunchao Zhang   A            = (size == 1) ? cooMat : ((Mat_MPIAIJ *)cooMat->data)->A;
22592c4ab24aSJunchao Zhang   PetscCall(MatSeqAIJGetCSRAndMemType(A, NULL, NULL, &Aa, &petscMemtype));
22602c4ab24aSJunchao Zhang   PetscAssert((PetscMemTypeHost(petscMemtype) && hypreMemtype == HYPRE_MEMORY_HOST) || (PetscMemTypeDevice(petscMemtype) && hypreMemtype == HYPRE_MEMORY_DEVICE), comm, PETSC_ERR_PLIB, "PETSc and hypre's memory types mismatch");
22612c4ab24aSJunchao Zhang 
22622c4ab24aSJunchao Zhang   hmat->diagJ = hypre_CSRMatrixJ(diag);
22632c4ab24aSJunchao Zhang   PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(diag), hypreMemtype));
22642c4ab24aSJunchao Zhang   hypre_CSRMatrixData(diag)     = (HYPRE_Complex *)Aa;
22652c4ab24aSJunchao Zhang   hypre_CSRMatrixOwnsData(diag) = 0; /* Take ownership of (j,a) away from hypre. As a result, we need to free them on our own */
22662c4ab24aSJunchao Zhang 
22672c4ab24aSJunchao Zhang   if (size > 1) {
22682c4ab24aSJunchao Zhang     B = ((Mat_MPIAIJ *)cooMat->data)->B;
22692c4ab24aSJunchao Zhang     PetscCall(MatSeqAIJGetCSRAndMemType(B, NULL, NULL, &Ba, &petscMemtype));
22702c4ab24aSJunchao Zhang     hmat->offdJ = hypre_CSRMatrixJ(offd);
22712c4ab24aSJunchao Zhang     PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(offd), hypreMemtype));
22722c4ab24aSJunchao Zhang     hypre_CSRMatrixData(offd)     = (HYPRE_Complex *)Ba;
22732c4ab24aSJunchao Zhang     hypre_CSRMatrixOwnsData(offd) = 0;
22742c4ab24aSJunchao Zhang   }
22752c4ab24aSJunchao Zhang 
22762c4ab24aSJunchao Zhang   /* Record cooMat for use in MatSetValuesCOO_HYPRE */
22772c4ab24aSJunchao Zhang   hmat->cooMat  = cooMat;
22782c4ab24aSJunchao Zhang   hmat->memType = hypreMemtype;
22792c4ab24aSJunchao Zhang   PetscFunctionReturn(PETSC_SUCCESS);
22802c4ab24aSJunchao Zhang }
22812c4ab24aSJunchao Zhang 
22822c4ab24aSJunchao Zhang static PetscErrorCode MatDuplicate_HYPRE(Mat A, MatDuplicateOption op, Mat *B)
22832c4ab24aSJunchao Zhang {
22842c4ab24aSJunchao Zhang   hypre_ParCSRMatrix *parcsr = NULL;
22852c4ab24aSJunchao Zhang   PetscCopyMode       cpmode;
22862c4ab24aSJunchao Zhang   Mat_HYPRE          *hA;
22872c4ab24aSJunchao Zhang   Mat                 cooMat;
22882c4ab24aSJunchao Zhang 
22892c4ab24aSJunchao Zhang   PetscFunctionBegin;
22902c4ab24aSJunchao Zhang   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
22912c4ab24aSJunchao Zhang   if (op == MAT_DO_NOT_COPY_VALUES || op == MAT_SHARE_NONZERO_PATTERN) {
22922c4ab24aSJunchao Zhang     parcsr = hypre_ParCSRMatrixClone(parcsr, 0);
22932c4ab24aSJunchao Zhang     cpmode = PETSC_OWN_POINTER;
22942c4ab24aSJunchao Zhang   } else {
22952c4ab24aSJunchao Zhang     cpmode = PETSC_COPY_VALUES;
22962c4ab24aSJunchao Zhang   }
22972c4ab24aSJunchao Zhang   PetscCall(MatCreateFromParCSR(parcsr, MATHYPRE, cpmode, B));
22982c4ab24aSJunchao Zhang   hA = (Mat_HYPRE *)A->data;
22992c4ab24aSJunchao Zhang   if (hA->cooMat) {
2300b73e3080SStefano Zampini     op = (op == MAT_DO_NOT_COPY_VALUES) ? op : MAT_COPY_VALUES;
2301b73e3080SStefano Zampini     /* Cannot simply increase the reference count of hA->cooMat, since B needs to share cooMat's data array */
2302b73e3080SStefano Zampini     PetscCall(MatDuplicate(hA->cooMat, op, &cooMat));
2303*651b1cf9SStefano Zampini     PetscCall(PetscObjectSetName((PetscObject)cooMat, "_internal_COO_mat_for_hypre"));
23042c4ab24aSJunchao Zhang     PetscCall(MatAttachCOOMat_HYPRE(*B, cooMat));
23052c4ab24aSJunchao Zhang   }
23062c4ab24aSJunchao Zhang   PetscFunctionReturn(PETSC_SUCCESS);
23072c4ab24aSJunchao Zhang }
23082c4ab24aSJunchao Zhang 
2309d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetPreallocationCOO_HYPRE(Mat mat, PetscCount coo_n, PetscInt coo_i[], PetscInt coo_j[])
2310d71ae5a4SJacob Faibussowitsch {
23115fbaff96SJunchao Zhang   MPI_Comm    comm;
23125fbaff96SJunchao Zhang   PetscMPIInt size;
23135fbaff96SJunchao Zhang   PetscLayout rmap, cmap;
23145fbaff96SJunchao Zhang   Mat_HYPRE  *hmat;
23152c4ab24aSJunchao Zhang   Mat         cooMat;
23165fbaff96SJunchao Zhang   MatType     matType = MATAIJ; /* default type of cooMat */
23175fbaff96SJunchao Zhang 
23185fbaff96SJunchao Zhang   PetscFunctionBegin;
2319*651b1cf9SStefano Zampini   /* Build an agent matrix cooMat with AIJ format
23205fbaff96SJunchao 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.
23215fbaff96SJunchao Zhang    */
23225fbaff96SJunchao Zhang   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
23235fbaff96SJunchao Zhang   PetscCallMPI(MPI_Comm_size(comm, &size));
23245fbaff96SJunchao Zhang   PetscCall(PetscLayoutSetUp(mat->rmap));
23255fbaff96SJunchao Zhang   PetscCall(PetscLayoutSetUp(mat->cmap));
23265fbaff96SJunchao Zhang   PetscCall(MatGetLayouts(mat, &rmap, &cmap));
23275fbaff96SJunchao Zhang 
2328*651b1cf9SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
23295fbaff96SJunchao Zhang   if (!mat->boundtocpu) { /* mat will be on device, so will cooMat */
2330*651b1cf9SStefano Zampini   #if defined(HYPRE_USING_HIP)
2331*651b1cf9SStefano Zampini     matType = MATAIJHIPSPARSE;
2332*651b1cf9SStefano Zampini   #elif defined(HYPRE_USING_CUDA)
2333*651b1cf9SStefano Zampini     matType = MATAIJCUSPARSE;
23345fbaff96SJunchao Zhang   #else
2335*651b1cf9SStefano Zampini     SETERRQ(comm, PETSC_ERR_SUP, "Do not know the HYPRE device");
23365fbaff96SJunchao Zhang   #endif
23375fbaff96SJunchao Zhang   }
23385fbaff96SJunchao Zhang #endif
23395fbaff96SJunchao Zhang 
23405fbaff96SJunchao Zhang   /* Do COO preallocation through cooMat */
23415fbaff96SJunchao Zhang   hmat = (Mat_HYPRE *)mat->data;
2342*651b1cf9SStefano Zampini   if (hmat->cooMat) {
23435fbaff96SJunchao Zhang     PetscCall(MatDestroy(&hmat->cooMat));
2344*651b1cf9SStefano Zampini     PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hmat->diagJ, hmat->memType));
2345*651b1cf9SStefano Zampini     PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hmat->offdJ, hmat->memType));
2346*651b1cf9SStefano Zampini     PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hmat->diag, hmat->memType));
2347*651b1cf9SStefano Zampini   }
23485fbaff96SJunchao Zhang   PetscCall(MatCreate(comm, &cooMat));
23495fbaff96SJunchao Zhang   PetscCall(MatSetType(cooMat, matType));
23505fbaff96SJunchao Zhang   PetscCall(MatSetLayouts(cooMat, rmap, cmap));
2351*651b1cf9SStefano Zampini   PetscCall(MatSetOption(cooMat, MAT_IGNORE_OFF_PROC_ENTRIES, hmat->donotstash));
2352*651b1cf9SStefano Zampini   PetscCall(MatSetOption(cooMat, MAT_NO_OFF_PROC_ENTRIES, mat->nooffprocentries));
2353*651b1cf9SStefano Zampini 
2354*651b1cf9SStefano Zampini   /* MatSetPreallocationCOO_SeqAIJ and MatSetPreallocationCOO_MPIAIJ uses this specific
2355*651b1cf9SStefano Zampini      name to automatically put the diagonal entries first */
2356*651b1cf9SStefano Zampini   PetscCall(PetscObjectSetName((PetscObject)cooMat, "_internal_COO_mat_for_hypre"));
23575fbaff96SJunchao Zhang   PetscCall(MatSetPreallocationCOO(cooMat, coo_n, coo_i, coo_j));
2358b73e3080SStefano Zampini   cooMat->assembled = PETSC_TRUE;
23595fbaff96SJunchao Zhang 
23605fbaff96SJunchao Zhang   /* Copy the sparsity pattern from cooMat to hypre IJMatrix hmat->ij */
23615fbaff96SJunchao Zhang   PetscCall(MatSetOption(mat, MAT_SORTED_FULL, PETSC_TRUE));
23625fbaff96SJunchao Zhang   PetscCall(MatHYPRE_CreateFromMat(cooMat, hmat));      /* Create hmat->ij and preallocate it */
2363b73e3080SStefano Zampini   PetscCall(MatHYPRE_IJMatrixCopyIJ(cooMat, hmat->ij)); /* Copy A's (i,j) to hmat->ij */
23645fbaff96SJunchao Zhang 
23655fbaff96SJunchao Zhang   mat->preallocated = PETSC_TRUE;
23665fbaff96SJunchao Zhang   PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
23675fbaff96SJunchao Zhang   PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); /* Migrate mat to device if it is bound to. Hypre builds its own SpMV context here */
23685fbaff96SJunchao Zhang 
23692c4ab24aSJunchao Zhang   /* Attach cooMat to mat */
23702c4ab24aSJunchao Zhang   PetscCall(MatAttachCOOMat_HYPRE(mat, cooMat));
23713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23725fbaff96SJunchao Zhang }
23735fbaff96SJunchao Zhang 
2374d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesCOO_HYPRE(Mat mat, const PetscScalar v[], InsertMode imode)
2375d71ae5a4SJacob Faibussowitsch {
23765fbaff96SJunchao Zhang   Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data;
23775fbaff96SJunchao Zhang 
23785fbaff96SJunchao Zhang   PetscFunctionBegin;
2379b73e3080SStefano Zampini   PetscCheck(hmat->cooMat, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet");
23805fbaff96SJunchao Zhang   PetscCall(MatSetValuesCOO(hmat->cooMat, v, imode));
2381*651b1cf9SStefano Zampini   PetscCall(MatViewFromOptions(hmat->cooMat, (PetscObject)mat, "-cooMat_view"));
23823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23835fbaff96SJunchao Zhang }
23845fbaff96SJunchao Zhang 
2385a055b5aaSBarry Smith /*MC
23862ef1f0ffSBarry Smith    MATHYPRE - "hypre" - A matrix type to be used for sequential and parallel sparse matrices
2387a055b5aaSBarry Smith           based on the hypre IJ interface.
2388a055b5aaSBarry Smith 
2389a055b5aaSBarry Smith    Level: intermediate
2390a055b5aaSBarry Smith 
23911cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatHYPRESetPreallocation`
2392a055b5aaSBarry Smith M*/
2393a055b5aaSBarry Smith 
2394d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_HYPRE(Mat B)
2395d71ae5a4SJacob Faibussowitsch {
239663c07aadSStefano Zampini   Mat_HYPRE *hB;
239763c07aadSStefano Zampini 
239863c07aadSStefano Zampini   PetscFunctionBegin;
23994dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&hB));
24006ea7df73SStefano Zampini 
2401978814f1SStefano Zampini   hB->inner_free      = PETSC_TRUE;
2402*651b1cf9SStefano Zampini   hB->array_available = PETSC_TRUE;
2403978814f1SStefano Zampini 
240463c07aadSStefano Zampini   B->data = (void *)hB;
240563c07aadSStefano Zampini 
24069566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(B->ops, sizeof(struct _MatOps)));
240763c07aadSStefano Zampini   B->ops->mult                  = MatMult_HYPRE;
240863c07aadSStefano Zampini   B->ops->multtranspose         = MatMultTranspose_HYPRE;
2409414bd5c3SStefano Zampini   B->ops->multadd               = MatMultAdd_HYPRE;
2410414bd5c3SStefano Zampini   B->ops->multtransposeadd      = MatMultTransposeAdd_HYPRE;
241163c07aadSStefano Zampini   B->ops->setup                 = MatSetUp_HYPRE;
241263c07aadSStefano Zampini   B->ops->destroy               = MatDestroy_HYPRE;
241363c07aadSStefano Zampini   B->ops->assemblyend           = MatAssemblyEnd_HYPRE;
2414c69f721fSFande Kong   B->ops->assemblybegin         = MatAssemblyBegin_HYPRE;
2415d975228cSstefano_zampini   B->ops->setvalues             = MatSetValues_HYPRE;
241668ec7858SStefano Zampini   B->ops->missingdiagonal       = MatMissingDiagonal_HYPRE;
241768ec7858SStefano Zampini   B->ops->scale                 = MatScale_HYPRE;
241868ec7858SStefano Zampini   B->ops->zerorowscolumns       = MatZeroRowsColumns_HYPRE;
2419c69f721fSFande Kong   B->ops->zeroentries           = MatZeroEntries_HYPRE;
2420c69f721fSFande Kong   B->ops->zerorows              = MatZeroRows_HYPRE;
2421c69f721fSFande Kong   B->ops->getrow                = MatGetRow_HYPRE;
2422c69f721fSFande Kong   B->ops->restorerow            = MatRestoreRow_HYPRE;
2423c69f721fSFande Kong   B->ops->getvalues             = MatGetValues_HYPRE;
2424ddbeb582SStefano Zampini   B->ops->setoption             = MatSetOption_HYPRE;
242545b8d346SStefano Zampini   B->ops->duplicate             = MatDuplicate_HYPRE;
2426465edc17SStefano Zampini   B->ops->copy                  = MatCopy_HYPRE;
242745b8d346SStefano Zampini   B->ops->view                  = MatView_HYPRE;
24286305df00SStefano Zampini   B->ops->getdiagonal           = MatGetDiagonal_HYPRE;
2429363d496dSStefano Zampini   B->ops->axpy                  = MatAXPY_HYPRE;
24304222ddf1SHong Zhang   B->ops->productsetfromoptions = MatProductSetFromOptions_HYPRE;
24316ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
24326ea7df73SStefano Zampini   B->ops->bindtocpu = MatBindToCPU_HYPRE;
24336ea7df73SStefano Zampini   B->boundtocpu     = PETSC_FALSE;
24346ea7df73SStefano Zampini #endif
243545b8d346SStefano Zampini 
243645b8d346SStefano Zampini   /* build cache for off array entries formed */
24379566063dSJacob Faibussowitsch   PetscCall(MatStashCreate_Private(PetscObjectComm((PetscObject)B), 1, &B->stash));
243863c07aadSStefano Zampini 
24399566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)B), &hB->comm));
24409566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRE));
24419566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_aij_C", MatConvert_HYPRE_AIJ));
24429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_is_C", MatConvert_HYPRE_IS));
24439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_hypre_C", MatProductSetFromOptions_HYPRE));
24449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaij_hypre_C", MatProductSetFromOptions_HYPRE));
24459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPRESetPreallocation_C", MatHYPRESetPreallocation_HYPRE));
24469566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPREGetParCSR_C", MatHYPREGetParCSR_HYPRE));
24475fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_HYPRE));
24485fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetValuesCOO_C", MatSetValuesCOO_HYPRE));
24496ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
24506ea7df73SStefano Zampini   #if defined(HYPRE_USING_HIP)
24519566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP));
24529566063dSJacob Faibussowitsch   PetscCall(MatSetVecType(B, VECHIP));
24536ea7df73SStefano Zampini   #endif
24546ea7df73SStefano Zampini   #if defined(HYPRE_USING_CUDA)
24559566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
24569566063dSJacob Faibussowitsch   PetscCall(MatSetVecType(B, VECCUDA));
24576ea7df73SStefano Zampini   #endif
24586ea7df73SStefano Zampini #endif
2459ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
24603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
246163c07aadSStefano Zampini }
246263c07aadSStefano Zampini 
2463d71ae5a4SJacob Faibussowitsch static PetscErrorCode hypre_array_destroy(void *ptr)
2464d71ae5a4SJacob Faibussowitsch {
2465225daaf8SStefano Zampini   PetscFunctionBegin;
2466b73e3080SStefano Zampini   if (ptr) hypre_TFree(ptr, HYPRE_MEMORY_HOST);
24673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2468225daaf8SStefano Zampini }
2469