xref: /petsc/src/mat/impls/hypre/mhypre.c (revision b73e3080d67479b9c7f89b0eb85e0227a0983617)
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);
25*b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_MPIAIJ(Mat, HYPRE_IJMatrix);
26*b73e3080SStefano 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();
93792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rstart, rend - 1, cstart, cend - 1, &hA->ij);
94792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR);
9563c07aadSStefano Zampini   {
9663c07aadSStefano Zampini     PetscBool       same;
9763c07aadSStefano Zampini     Mat             A_d, A_o;
9863c07aadSStefano Zampini     const PetscInt *colmap;
999566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &same));
10063c07aadSStefano Zampini     if (same) {
1019566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJGetSeqAIJ(A, &A_d, &A_o, &colmap));
1029566063dSJacob Faibussowitsch       PetscCall(MatHYPRE_IJMatrixPreallocate(A_d, A_o, hA->ij));
1033ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
10463c07aadSStefano Zampini     }
1059566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIBAIJ, &same));
10663c07aadSStefano Zampini     if (same) {
1079566063dSJacob Faibussowitsch       PetscCall(MatMPIBAIJGetSeqBAIJ(A, &A_d, &A_o, &colmap));
1089566063dSJacob Faibussowitsch       PetscCall(MatHYPRE_IJMatrixPreallocate(A_d, A_o, hA->ij));
1093ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
11063c07aadSStefano Zampini     }
1119566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &same));
11263c07aadSStefano Zampini     if (same) {
1139566063dSJacob Faibussowitsch       PetscCall(MatHYPRE_IJMatrixPreallocate(A, NULL, hA->ij));
1143ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
11563c07aadSStefano Zampini     }
1169566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQBAIJ, &same));
11763c07aadSStefano Zampini     if (same) {
1189566063dSJacob Faibussowitsch       PetscCall(MatHYPRE_IJMatrixPreallocate(A, NULL, hA->ij));
1193ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
12063c07aadSStefano Zampini     }
12163c07aadSStefano Zampini   }
1223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12363c07aadSStefano Zampini }
12463c07aadSStefano Zampini 
125*b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ(Mat A, HYPRE_IJMatrix ij)
126d71ae5a4SJacob Faibussowitsch {
12763c07aadSStefano Zampini   PetscBool flg;
12863c07aadSStefano Zampini 
12963c07aadSStefano Zampini   PetscFunctionBegin;
1306ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
131792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize, ij);
1326ea7df73SStefano Zampini #else
133792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize_v2, ij, HYPRE_MEMORY_HOST);
1346ea7df73SStefano Zampini #endif
1359566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &flg));
136*b73e3080SStefano Zampini   if (flg) {
137*b73e3080SStefano Zampini     PetscCall(MatHYPRE_IJMatrixCopyIJ_MPIAIJ(A, ij));
1383ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
13963c07aadSStefano Zampini   }
1409566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &flg));
14163c07aadSStefano Zampini   if (flg) {
142*b73e3080SStefano Zampini     PetscCall(MatHYPRE_IJMatrixCopyIJ_SeqAIJ(A, ij));
1433ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
14463c07aadSStefano Zampini   }
145*b73e3080SStefano Zampini   PetscCheck(PETSC_FALSE, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "No support for matrix type %s", ((PetscObject)A)->type_name);
14663c07aadSStefano Zampini }
14763c07aadSStefano Zampini 
148*b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_SeqAIJ(Mat A, HYPRE_IJMatrix ij)
149d71ae5a4SJacob Faibussowitsch {
15063c07aadSStefano Zampini   Mat_SeqAIJ            *pdiag = (Mat_SeqAIJ *)A->data;
15158968eb6SStefano Zampini   HYPRE_Int              type;
15263c07aadSStefano Zampini   hypre_ParCSRMatrix    *par_matrix;
15363c07aadSStefano Zampini   hypre_AuxParCSRMatrix *aux_matrix;
15463c07aadSStefano Zampini   hypre_CSRMatrix       *hdiag;
1552cf14000SStefano Zampini   PetscBool              sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
15663c07aadSStefano Zampini 
15763c07aadSStefano Zampini   PetscFunctionBegin;
158792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type);
15908401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
160792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix);
16163c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(par_matrix);
16263c07aadSStefano Zampini   /*
16363c07aadSStefano Zampini        this is the Hack part where we monkey directly with the hypre datastructures
16463c07aadSStefano Zampini   */
1652cf14000SStefano Zampini   if (sameint) {
1669566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hdiag->i, pdiag->i, A->rmap->n + 1));
1679566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hdiag->j, pdiag->j, pdiag->nz));
1682cf14000SStefano Zampini   } else {
1692cf14000SStefano Zampini     PetscInt i;
1702cf14000SStefano Zampini 
1712cf14000SStefano Zampini     for (i = 0; i < A->rmap->n + 1; i++) hdiag->i[i] = (HYPRE_Int)pdiag->i[i];
1722cf14000SStefano Zampini     for (i = 0; i < pdiag->nz; i++) hdiag->j[i] = (HYPRE_Int)pdiag->j[i];
1732cf14000SStefano Zampini   }
1746ea7df73SStefano Zampini 
175ea9daf28SStefano Zampini   aux_matrix                               = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij);
17663c07aadSStefano Zampini   hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
1773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17863c07aadSStefano Zampini }
17963c07aadSStefano Zampini 
180*b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyIJ_MPIAIJ(Mat A, HYPRE_IJMatrix ij)
181d71ae5a4SJacob Faibussowitsch {
18263c07aadSStefano Zampini   Mat_MPIAIJ            *pA = (Mat_MPIAIJ *)A->data;
18363c07aadSStefano Zampini   Mat_SeqAIJ            *pdiag, *poffd;
18463c07aadSStefano Zampini   PetscInt               i, *garray = pA->garray, *jj, cstart, *pjj;
1852cf14000SStefano Zampini   HYPRE_Int             *hjj, type;
18663c07aadSStefano Zampini   hypre_ParCSRMatrix    *par_matrix;
18763c07aadSStefano Zampini   hypre_AuxParCSRMatrix *aux_matrix;
18863c07aadSStefano Zampini   hypre_CSRMatrix       *hdiag, *hoffd;
1892cf14000SStefano Zampini   PetscBool              sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
19063c07aadSStefano Zampini 
19163c07aadSStefano Zampini   PetscFunctionBegin;
19263c07aadSStefano Zampini   pdiag = (Mat_SeqAIJ *)pA->A->data;
19363c07aadSStefano Zampini   poffd = (Mat_SeqAIJ *)pA->B->data;
194da81f932SPierre Jolivet   /* cstart is only valid for square MPIAIJ laid out in the usual way */
1959566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &cstart, NULL));
19663c07aadSStefano Zampini 
197792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type);
19808401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
199792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix);
20063c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(par_matrix);
20163c07aadSStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(par_matrix);
20263c07aadSStefano Zampini 
2032cf14000SStefano Zampini   if (sameint) {
2049566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hdiag->i, pdiag->i, pA->A->rmap->n + 1));
2052cf14000SStefano Zampini   } else {
2062cf14000SStefano Zampini     for (i = 0; i < pA->A->rmap->n + 1; i++) hdiag->i[i] = (HYPRE_Int)(pdiag->i[i]);
2072cf14000SStefano Zampini   }
208*b73e3080SStefano Zampini 
2092cf14000SStefano Zampini   hjj = hdiag->j;
2102cf14000SStefano Zampini   pjj = pdiag->j;
211c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0)
2122cf14000SStefano Zampini   for (i = 0; i < pdiag->nz; i++) hjj[i] = pjj[i];
213c6698e78SStefano Zampini #else
2142cf14000SStefano Zampini   for (i = 0; i < pdiag->nz; i++) hjj[i] = cstart + pjj[i];
215c6698e78SStefano Zampini #endif
2162cf14000SStefano Zampini   if (sameint) {
2179566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hoffd->i, poffd->i, pA->A->rmap->n + 1));
2182cf14000SStefano Zampini   } else {
2192cf14000SStefano Zampini     for (i = 0; i < pA->A->rmap->n + 1; i++) hoffd->i[i] = (HYPRE_Int)(poffd->i[i]);
2202cf14000SStefano Zampini   }
2212cf14000SStefano Zampini 
222c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0)
223792fecdfSBarry Smith   PetscCallExternal(hypre_CSRMatrixBigInitialize, hoffd);
224c6698e78SStefano Zampini   jj = (PetscInt *)hoffd->big_j;
225c6698e78SStefano Zampini #else
22663c07aadSStefano Zampini   jj = (PetscInt *)hoffd->j;
227c6698e78SStefano Zampini #endif
2282cf14000SStefano Zampini   pjj = poffd->j;
22963c07aadSStefano Zampini   for (i = 0; i < poffd->nz; i++) jj[i] = garray[pjj[i]];
230c6698e78SStefano Zampini 
231ea9daf28SStefano Zampini   aux_matrix                               = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij);
23263c07aadSStefano Zampini   hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
2333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23463c07aadSStefano Zampini }
23563c07aadSStefano Zampini 
236d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_HYPRE_IS(Mat A, MatType mtype, MatReuse reuse, Mat *B)
237d71ae5a4SJacob Faibussowitsch {
2382df22349SStefano Zampini   Mat_HYPRE             *mhA = (Mat_HYPRE *)(A->data);
2392df22349SStefano Zampini   Mat                    lA;
2402df22349SStefano Zampini   ISLocalToGlobalMapping rl2g, cl2g;
2412df22349SStefano Zampini   IS                     is;
2422df22349SStefano Zampini   hypre_ParCSRMatrix    *hA;
2432df22349SStefano Zampini   hypre_CSRMatrix       *hdiag, *hoffd;
2442df22349SStefano Zampini   MPI_Comm               comm;
24539accc25SStefano Zampini   HYPRE_Complex         *hdd, *hod, *aa;
24639accc25SStefano Zampini   PetscScalar           *data;
2472cf14000SStefano Zampini   HYPRE_BigInt          *col_map_offd;
2482cf14000SStefano Zampini   HYPRE_Int             *hdi, *hdj, *hoi, *hoj;
2492df22349SStefano Zampini   PetscInt              *ii, *jj, *iptr, *jptr;
2502df22349SStefano Zampini   PetscInt               cum, dr, dc, oc, str, stc, nnz, i, jd, jo, M, N;
25158968eb6SStefano Zampini   HYPRE_Int              type;
2522df22349SStefano Zampini 
2532df22349SStefano Zampini   PetscFunctionBegin;
254a1787963SStefano Zampini   comm = PetscObjectComm((PetscObject)A);
255792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, mhA->ij, &type);
25608401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
257792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, mhA->ij, (void **)&hA);
2582df22349SStefano Zampini   M     = hypre_ParCSRMatrixGlobalNumRows(hA);
2592df22349SStefano Zampini   N     = hypre_ParCSRMatrixGlobalNumCols(hA);
2602df22349SStefano Zampini   str   = hypre_ParCSRMatrixFirstRowIndex(hA);
2612df22349SStefano Zampini   stc   = hypre_ParCSRMatrixFirstColDiag(hA);
2622df22349SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(hA);
2632df22349SStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(hA);
2642df22349SStefano Zampini   dr    = hypre_CSRMatrixNumRows(hdiag);
2652df22349SStefano Zampini   dc    = hypre_CSRMatrixNumCols(hdiag);
2662df22349SStefano Zampini   nnz   = hypre_CSRMatrixNumNonzeros(hdiag);
2672df22349SStefano Zampini   hdi   = hypre_CSRMatrixI(hdiag);
2682df22349SStefano Zampini   hdj   = hypre_CSRMatrixJ(hdiag);
2692df22349SStefano Zampini   hdd   = hypre_CSRMatrixData(hdiag);
2702df22349SStefano Zampini   oc    = hypre_CSRMatrixNumCols(hoffd);
2712df22349SStefano Zampini   nnz += hypre_CSRMatrixNumNonzeros(hoffd);
2722df22349SStefano Zampini   hoi = hypre_CSRMatrixI(hoffd);
2732df22349SStefano Zampini   hoj = hypre_CSRMatrixJ(hoffd);
2742df22349SStefano Zampini   hod = hypre_CSRMatrixData(hoffd);
2752df22349SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
2762df22349SStefano Zampini     PetscInt *aux;
2772df22349SStefano Zampini 
2782df22349SStefano Zampini     /* generate l2g maps for rows and cols */
2799566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(comm, dr, str, 1, &is));
2809566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g));
2819566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
2822df22349SStefano Zampini     col_map_offd = hypre_ParCSRMatrixColMapOffd(hA);
2839566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dc + oc, &aux));
2842df22349SStefano Zampini     for (i = 0; i < dc; i++) aux[i] = i + stc;
2852df22349SStefano Zampini     for (i = 0; i < oc; i++) aux[i + dc] = col_map_offd[i];
2869566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, dc + oc, aux, PETSC_OWN_POINTER, &is));
2879566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g));
2889566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
2892df22349SStefano Zampini     /* create MATIS object */
2909566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm, B));
2919566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(*B, dr, dc, M, N));
2929566063dSJacob Faibussowitsch     PetscCall(MatSetType(*B, MATIS));
2939566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(*B, rl2g, cl2g));
2949566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
2959566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
2962df22349SStefano Zampini 
2972df22349SStefano Zampini     /* allocate CSR for local matrix */
2989566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dr + 1, &iptr));
2999566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &jptr));
3009566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &data));
3012df22349SStefano Zampini   } else {
3022df22349SStefano Zampini     PetscInt  nr;
3032df22349SStefano Zampini     PetscBool done;
3049566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(*B, &lA));
3059566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(lA, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&iptr, (const PetscInt **)&jptr, &done));
30608401ef6SPierre 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);
30708401ef6SPierre 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);
3089566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArray(lA, &data));
3092df22349SStefano Zampini   }
3102df22349SStefano Zampini   /* merge local matrices */
3112df22349SStefano Zampini   ii  = iptr;
3122df22349SStefano Zampini   jj  = jptr;
31339accc25SStefano 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++ */
3142df22349SStefano Zampini   *ii = *(hdi++) + *(hoi++);
3152df22349SStefano Zampini   for (jd = 0, jo = 0, cum = 0; *ii < nnz; cum++) {
31639accc25SStefano Zampini     PetscScalar *aold = (PetscScalar *)aa;
3172df22349SStefano Zampini     PetscInt    *jold = jj, nc = jd + jo;
3189371c9d4SSatish Balay     for (; jd < *hdi; jd++) {
3199371c9d4SSatish Balay       *jj++ = *hdj++;
3209371c9d4SSatish Balay       *aa++ = *hdd++;
3219371c9d4SSatish Balay     }
3229371c9d4SSatish Balay     for (; jo < *hoi; jo++) {
3239371c9d4SSatish Balay       *jj++ = *hoj++ + dc;
3249371c9d4SSatish Balay       *aa++ = *hod++;
3259371c9d4SSatish Balay     }
3262df22349SStefano Zampini     *(++ii) = *(hdi++) + *(hoi++);
3279566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithScalarArray(jd + jo - nc, jold, aold));
3282df22349SStefano Zampini   }
3292df22349SStefano Zampini   for (; cum < dr; cum++) *(++ii) = nnz;
3302df22349SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
331a033916dSStefano Zampini     Mat_SeqAIJ *a;
332a033916dSStefano Zampini 
3339566063dSJacob Faibussowitsch     PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, dr, dc + oc, iptr, jptr, data, &lA));
3349566063dSJacob Faibussowitsch     PetscCall(MatISSetLocalMat(*B, lA));
335a033916dSStefano Zampini     /* hack SeqAIJ */
336a033916dSStefano Zampini     a          = (Mat_SeqAIJ *)(lA->data);
337a033916dSStefano Zampini     a->free_a  = PETSC_TRUE;
338a033916dSStefano Zampini     a->free_ij = PETSC_TRUE;
3399566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&lA));
3402df22349SStefano Zampini   }
3419566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY));
3429566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY));
34348a46eb9SPierre Jolivet   if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, B));
3443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3452df22349SStefano Zampini }
3462df22349SStefano Zampini 
347*b73e3080SStefano Zampini /* Move diagonal elements of the diagonal block to the front of their row, as needed by ParCSRMatrix. So damn hacky */
348*b73e3080SStefano Zampini static PetscErrorCode EnsureHypreCSR_SeqAIJ(Mat A, hypre_CSRMatrix *hA)
349d71ae5a4SJacob Faibussowitsch {
350*b73e3080SStefano Zampini   Mat_SeqAIJ   *aij = (Mat_SeqAIJ *)A->data;
351*b73e3080SStefano Zampini   PetscBool     isseqaij;
352*b73e3080SStefano Zampini   HYPRE_Int     tmpj, *hj;
353*b73e3080SStefano Zampini   HYPRE_Complex tmpv, *ha;
35463c07aadSStefano Zampini 
35563c07aadSStefano Zampini   PetscFunctionBegin;
356*b73e3080SStefano Zampini   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isseqaij));
357*b73e3080SStefano Zampini   PetscCheck(isseqaij, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Not for type %s\n", ((PetscObject)A)->type_name);
358*b73e3080SStefano Zampini   hj = hypre_CSRMatrixJ(hA);
359*b73e3080SStefano Zampini   ha = hypre_CSRMatrixData(hA);
360*b73e3080SStefano Zampini #define swap_with_tmp(a, b, t) \
361*b73e3080SStefano Zampini   { \
362*b73e3080SStefano Zampini     t = a; \
363*b73e3080SStefano Zampini     a = b; \
364*b73e3080SStefano Zampini     b = t; \
365*b73e3080SStefano Zampini   }
366*b73e3080SStefano Zampini   for (PetscInt i = 0; i < A->rmap->n; i++) {
367*b73e3080SStefano 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[] */
368*b73e3080SStefano Zampini       swap_with_tmp(ha[aij->i[i]], ha[aij->diag[i]], tmpv);
369*b73e3080SStefano Zampini       if (hj[aij->i[i]] != i) swap_with_tmp(hj[aij->i[i]], hj[aij->diag[i]], tmpj);
370*b73e3080SStefano Zampini     }
371*b73e3080SStefano Zampini   }
372*b73e3080SStefano Zampini #undef swap_with_tmp
373*b73e3080SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
374*b73e3080SStefano Zampini }
375*b73e3080SStefano Zampini 
376*b73e3080SStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopyValues(Mat A, HYPRE_IJMatrix ij)
377*b73e3080SStefano Zampini {
378*b73e3080SStefano Zampini   HYPRE_Int           type;
379*b73e3080SStefano Zampini   hypre_ParCSRMatrix *par_matrix;
380*b73e3080SStefano Zampini   hypre_CSRMatrix    *hdiag, *hoffd;
381*b73e3080SStefano Zampini   PetscBool           ismpiaij;
382*b73e3080SStefano Zampini   Mat                 dA = A, oA = NULL;
383*b73e3080SStefano Zampini   PetscInt            nnz;
384*b73e3080SStefano Zampini   const PetscScalar  *pa;
385*b73e3080SStefano Zampini 
386*b73e3080SStefano Zampini   PetscFunctionBegin;
387*b73e3080SStefano Zampini   PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type);
388*b73e3080SStefano Zampini   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
389*b73e3080SStefano Zampini   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
390*b73e3080SStefano Zampini   if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(A, &dA, &oA, NULL));
391*b73e3080SStefano Zampini   PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix);
392*b73e3080SStefano Zampini 
393*b73e3080SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(par_matrix);
394*b73e3080SStefano Zampini   nnz   = hypre_CSRMatrixNumNonzeros(hdiag);
395*b73e3080SStefano Zampini   PetscCall(MatSeqAIJGetArrayRead(dA, &pa));
396*b73e3080SStefano Zampini   PetscCall(PetscArraycpy(hdiag->data, pa, nnz));
397*b73e3080SStefano Zampini   PetscCall(MatSeqAIJRestoreArrayRead(dA, &pa));
398*b73e3080SStefano Zampini   if (oA) {
399*b73e3080SStefano Zampini     hoffd = hypre_ParCSRMatrixOffd(par_matrix);
400*b73e3080SStefano Zampini     nnz   = hypre_CSRMatrixNumNonzeros(hoffd);
401*b73e3080SStefano Zampini     PetscCall(MatSeqAIJGetArrayRead(oA, &pa));
402*b73e3080SStefano Zampini     PetscCall(PetscArraycpy(hoffd->data, pa, nnz));
403*b73e3080SStefano Zampini     PetscCall(MatSeqAIJRestoreArrayRead(dA, &pa));
404*b73e3080SStefano Zampini   }
405*b73e3080SStefano Zampini   PetscCall(EnsureHypreCSR_SeqAIJ(dA, hdiag));
406*b73e3080SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
407*b73e3080SStefano Zampini }
408*b73e3080SStefano Zampini 
409*b73e3080SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType type, MatReuse reuse, Mat *B)
410*b73e3080SStefano Zampini {
411*b73e3080SStefano Zampini   MPI_Comm   comm = PetscObjectComm((PetscObject)A);
412*b73e3080SStefano Zampini   Mat        M    = NULL;
413*b73e3080SStefano Zampini   Mat        dA = A, oA = NULL;
414*b73e3080SStefano Zampini   PetscBool  ismpiaij, issbaij, isbaij;
415*b73e3080SStefano Zampini   Mat_HYPRE *hA;
416*b73e3080SStefano Zampini 
417*b73e3080SStefano Zampini   PetscFunctionBegin;
418*b73e3080SStefano Zampini   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &issbaij, MATSEQSBAIJ, MATMPIBAIJ, ""));
419*b73e3080SStefano Zampini   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &isbaij, MATSEQBAIJ, MATMPIBAIJ, ""));
420*b73e3080SStefano Zampini   if (isbaij || issbaij) { /* handle BAIJ and SBAIJ */
421*b73e3080SStefano Zampini     PetscBool ismpi;
422*b73e3080SStefano Zampini     MatType   newtype;
423*b73e3080SStefano Zampini 
424*b73e3080SStefano Zampini     PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &ismpi, MATMPISBAIJ, MATMPIBAIJ, ""));
425*b73e3080SStefano Zampini     newtype = ismpi ? MATMPIAIJ : MATSEQAIJ;
42663c07aadSStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
427*b73e3080SStefano Zampini       PetscCall(MatConvert(*B, newtype, MAT_INPLACE_MATRIX, B));
428*b73e3080SStefano Zampini       PetscCall(MatConvert(A, newtype, MAT_REUSE_MATRIX, B));
429*b73e3080SStefano Zampini       PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B));
430*b73e3080SStefano Zampini     } else if (reuse == MAT_INITIAL_MATRIX) {
431*b73e3080SStefano Zampini       PetscCall(MatConvert(A, newtype, MAT_INITIAL_MATRIX, B));
432*b73e3080SStefano Zampini       PetscCall(MatConvert(*B, MATHYPRE, MAT_INPLACE_MATRIX, B));
43363c07aadSStefano Zampini     } else {
434*b73e3080SStefano Zampini       PetscCall(MatConvert(A, newtype, MAT_INPLACE_MATRIX, &A));
435*b73e3080SStefano Zampini       PetscCall(MatConvert(A, MATHYPRE, MAT_INPLACE_MATRIX, &A));
436*b73e3080SStefano Zampini     }
437*b73e3080SStefano Zampini     PetscFunctionReturn(PETSC_SUCCESS);
438*b73e3080SStefano Zampini   }
439*b73e3080SStefano Zampini   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
440*b73e3080SStefano Zampini   if (ismpiaij) PetscCall(MatMPIAIJGetSeqAIJ(A, &dA, &oA, NULL));
441*b73e3080SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
4429566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm, &M));
4439566063dSJacob Faibussowitsch     PetscCall(MatSetType(M, MATHYPRE));
4449566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(M, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
445*b73e3080SStefano Zampini     PetscCall(MatSetOption(M, MAT_SORTED_FULL, PETSC_TRUE));
446*b73e3080SStefano Zampini     PetscCall(MatSetOption(M, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE));
447*b73e3080SStefano Zampini     PetscCall(PetscLayoutSetUp(M->rmap));
448*b73e3080SStefano Zampini     PetscCall(PetscLayoutSetUp(M->cmap));
449*b73e3080SStefano Zampini 
450*b73e3080SStefano Zampini     hA = (Mat_HYPRE *)M->data;
451*b73e3080SStefano Zampini     PetscCall(MatHYPRE_CreateFromMat(A, hA));      /* Create hmat->ij and preallocate it */
452*b73e3080SStefano Zampini     PetscCall(MatHYPRE_IJMatrixCopyIJ(A, hA->ij)); /* Copy A's (a,i,j) to hmat->ij */
453*b73e3080SStefano Zampini     M->preallocated = PETSC_TRUE;
45484d4e069SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) *B = M;
455*b73e3080SStefano Zampini   } else M = *B;
456*b73e3080SStefano Zampini 
457*b73e3080SStefano Zampini   hA = (Mat_HYPRE *)M->data;
458*b73e3080SStefano Zampini   PetscCall(MatHYPRE_IJMatrixCopyValues(A, hA->ij));
459*b73e3080SStefano Zampini   PetscCall(MatAssemblyBegin(M, MAT_FINAL_ASSEMBLY));
460*b73e3080SStefano Zampini   PetscCall(MatAssemblyEnd(M, MAT_FINAL_ASSEMBLY)); /* Migrate mat to device if it is bound to. Hypre builds its own SpMV context here */
461*b73e3080SStefano Zampini 
46248a46eb9SPierre Jolivet   if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &M));
4633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46463c07aadSStefano Zampini }
46563c07aadSStefano Zampini 
466d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatConvert_HYPRE_AIJ(Mat A, MatType mtype, MatReuse reuse, Mat *B)
467d71ae5a4SJacob Faibussowitsch {
46863c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE *)A->data;
46963c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
47063c07aadSStefano Zampini   hypre_CSRMatrix    *hdiag, *hoffd;
47163c07aadSStefano Zampini   MPI_Comm            comm;
47263c07aadSStefano Zampini   PetscScalar        *da, *oa, *aptr;
47363c07aadSStefano Zampini   PetscInt           *dii, *djj, *oii, *ojj, *iptr;
47463c07aadSStefano Zampini   PetscInt            i, dnnz, onnz, m, n;
47558968eb6SStefano Zampini   HYPRE_Int           type;
47663c07aadSStefano Zampini   PetscMPIInt         size;
4772cf14000SStefano Zampini   PetscBool           sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
478*b73e3080SStefano Zampini   PetscBool           downs = PETSC_TRUE, oowns = PETSC_TRUE;
47963c07aadSStefano Zampini 
48063c07aadSStefano Zampini   PetscFunctionBegin;
48163c07aadSStefano Zampini   comm = PetscObjectComm((PetscObject)A);
482792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
48308401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
48463c07aadSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
48563c07aadSStefano Zampini     PetscBool ismpiaij, isseqaij;
4869566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATMPIAIJ, &ismpiaij));
4879566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATSEQAIJ, &isseqaij));
48808401ef6SPierre Jolivet     PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Only MATMPIAIJ or MATSEQAIJ are supported");
48963c07aadSStefano Zampini   }
4906ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
49108401ef6SPierre Jolivet   PetscCheck(HYPRE_MEMORY_DEVICE != hypre_IJMatrixMemoryLocation(hA->ij), comm, PETSC_ERR_SUP, "Not yet implemented");
4926ea7df73SStefano Zampini #endif
4939566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
49463c07aadSStefano Zampini 
495792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
49663c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(parcsr);
49763c07aadSStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(parcsr);
49863c07aadSStefano Zampini   m     = hypre_CSRMatrixNumRows(hdiag);
49963c07aadSStefano Zampini   n     = hypre_CSRMatrixNumCols(hdiag);
50063c07aadSStefano Zampini   dnnz  = hypre_CSRMatrixNumNonzeros(hdiag);
50163c07aadSStefano Zampini   onnz  = hypre_CSRMatrixNumNonzeros(hoffd);
502225daaf8SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
5039566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m + 1, &dii));
5049566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dnnz, &djj));
5059566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dnnz, &da));
506225daaf8SStefano Zampini   } else if (reuse == MAT_REUSE_MATRIX) {
50763c07aadSStefano Zampini     PetscInt  nr;
50863c07aadSStefano Zampini     PetscBool done;
50963c07aadSStefano Zampini     if (size > 1) {
51063c07aadSStefano Zampini       Mat_MPIAIJ *b = (Mat_MPIAIJ *)((*B)->data);
51163c07aadSStefano Zampini 
5129566063dSJacob Faibussowitsch       PetscCall(MatGetRowIJ(b->A, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&dii, (const PetscInt **)&djj, &done));
51308401ef6SPierre 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);
51408401ef6SPierre 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);
5159566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJGetArray(b->A, &da));
51663c07aadSStefano Zampini     } else {
5179566063dSJacob Faibussowitsch       PetscCall(MatGetRowIJ(*B, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&dii, (const PetscInt **)&djj, &done));
51808401ef6SPierre Jolivet       PetscCheck(nr == m, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of local rows! %" PetscInt_FMT " != %" PetscInt_FMT, nr, m);
51908401ef6SPierre 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);
5209566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJGetArray(*B, &da));
52163c07aadSStefano Zampini     }
522225daaf8SStefano Zampini   } else { /* MAT_INPLACE_MATRIX */
523*b73e3080SStefano Zampini     downs = (PetscBool)(hypre_CSRMatrixOwnsData(hdiag));
524*b73e3080SStefano Zampini     if (!sameint || !downs) {
5259566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(m + 1, &dii));
5269566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(dnnz, &djj));
5272cf14000SStefano Zampini     } else {
5287d968826Sstefano_zampini       dii = (PetscInt *)hypre_CSRMatrixI(hdiag);
5297d968826Sstefano_zampini       djj = (PetscInt *)hypre_CSRMatrixJ(hdiag);
53063c07aadSStefano Zampini     }
531*b73e3080SStefano Zampini     if (!downs) {
532*b73e3080SStefano Zampini       PetscCall(PetscMalloc1(dnnz, &da));
533*b73e3080SStefano Zampini     } else da = (PetscScalar *)hypre_CSRMatrixData(hdiag);
53463c07aadSStefano Zampini   }
5352cf14000SStefano Zampini 
5362cf14000SStefano Zampini   if (!sameint) {
5379371c9d4SSatish Balay     if (reuse != MAT_REUSE_MATRIX) {
5389371c9d4SSatish Balay       for (i = 0; i < m + 1; i++) dii[i] = (PetscInt)(hypre_CSRMatrixI(hdiag)[i]);
5399371c9d4SSatish Balay     }
5402cf14000SStefano Zampini     for (i = 0; i < dnnz; i++) djj[i] = (PetscInt)(hypre_CSRMatrixJ(hdiag)[i]);
5412cf14000SStefano Zampini   } else {
5429566063dSJacob Faibussowitsch     if (reuse != MAT_REUSE_MATRIX) PetscCall(PetscArraycpy(dii, hypre_CSRMatrixI(hdiag), m + 1));
5439566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(djj, hypre_CSRMatrixJ(hdiag), dnnz));
5442cf14000SStefano Zampini   }
5459566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(da, hypre_CSRMatrixData(hdiag), dnnz));
54663c07aadSStefano Zampini   iptr = djj;
54763c07aadSStefano Zampini   aptr = da;
54863c07aadSStefano Zampini   for (i = 0; i < m; i++) {
54963c07aadSStefano Zampini     PetscInt nc = dii[i + 1] - dii[i];
5509566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithScalarArray(nc, iptr, aptr));
55163c07aadSStefano Zampini     iptr += nc;
55263c07aadSStefano Zampini     aptr += nc;
55363c07aadSStefano Zampini   }
55463c07aadSStefano Zampini   if (size > 1) {
5552cf14000SStefano Zampini     HYPRE_BigInt *coffd;
5562cf14000SStefano Zampini     HYPRE_Int    *offdj;
55763c07aadSStefano Zampini 
558225daaf8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
5599566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(m + 1, &oii));
5609566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(onnz, &ojj));
5619566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(onnz, &oa));
562225daaf8SStefano Zampini     } else if (reuse == MAT_REUSE_MATRIX) {
56363c07aadSStefano Zampini       Mat_MPIAIJ *b = (Mat_MPIAIJ *)((*B)->data);
56463c07aadSStefano Zampini       PetscInt    nr, hr = hypre_CSRMatrixNumRows(hoffd);
56563c07aadSStefano Zampini       PetscBool   done;
56663c07aadSStefano Zampini 
5679566063dSJacob Faibussowitsch       PetscCall(MatGetRowIJ(b->B, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&oii, (const PetscInt **)&ojj, &done));
56808401ef6SPierre 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);
569*b73e3080SStefano 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);
5709566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJGetArray(b->B, &oa));
571225daaf8SStefano Zampini     } else { /* MAT_INPLACE_MATRIX */
572*b73e3080SStefano Zampini       oowns = (PetscBool)(hypre_CSRMatrixOwnsData(hoffd));
573*b73e3080SStefano Zampini       if (!sameint || !oowns) {
5749566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(m + 1, &oii));
5759566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(onnz, &ojj));
5762cf14000SStefano Zampini       } else {
5777d968826Sstefano_zampini         oii = (PetscInt *)hypre_CSRMatrixI(hoffd);
5787d968826Sstefano_zampini         ojj = (PetscInt *)hypre_CSRMatrixJ(hoffd);
57963c07aadSStefano Zampini       }
580*b73e3080SStefano Zampini       if (!oowns) {
581*b73e3080SStefano Zampini         PetscCall(PetscMalloc1(onnz, &oa));
582*b73e3080SStefano Zampini       } else oa = (PetscScalar *)hypre_CSRMatrixData(hoffd);
58363c07aadSStefano Zampini     }
584a16187a7SStefano Zampini     if (reuse != MAT_REUSE_MATRIX) {
5852cf14000SStefano Zampini       if (!sameint) {
5862cf14000SStefano Zampini         for (i = 0; i < m + 1; i++) oii[i] = (PetscInt)(hypre_CSRMatrixI(hoffd)[i]);
5872cf14000SStefano Zampini       } else {
5889566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(oii, hypre_CSRMatrixI(hoffd), m + 1));
5892cf14000SStefano Zampini       }
590a16187a7SStefano Zampini     }
5919566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(oa, hypre_CSRMatrixData(hoffd), onnz));
592a16187a7SStefano Zampini 
59363c07aadSStefano Zampini     offdj = hypre_CSRMatrixJ(hoffd);
59463c07aadSStefano Zampini     coffd = hypre_ParCSRMatrixColMapOffd(parcsr);
595a16187a7SStefano Zampini     /* we only need the permutation to be computed properly, I don't know if HYPRE
596a16187a7SStefano Zampini        messes up with the ordering. Just in case, allocate some memory and free it
597a16187a7SStefano Zampini        later */
598a16187a7SStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
599a16187a7SStefano Zampini       Mat_MPIAIJ *b = (Mat_MPIAIJ *)((*B)->data);
600a16187a7SStefano Zampini       PetscInt    mnz;
601a16187a7SStefano Zampini 
6029566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJGetMaxRowNonzeros(b->B, &mnz));
6039566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mnz, &ojj));
6049371c9d4SSatish Balay     } else
6059371c9d4SSatish Balay       for (i = 0; i < onnz; i++) ojj[i] = coffd[offdj[i]];
60663c07aadSStefano Zampini     iptr = ojj;
60763c07aadSStefano Zampini     aptr = oa;
60863c07aadSStefano Zampini     for (i = 0; i < m; i++) {
60963c07aadSStefano Zampini       PetscInt nc = oii[i + 1] - oii[i];
610a16187a7SStefano Zampini       if (reuse == MAT_REUSE_MATRIX) {
611a16187a7SStefano Zampini         PetscInt j;
612a16187a7SStefano Zampini 
613a16187a7SStefano Zampini         iptr = ojj;
614a16187a7SStefano Zampini         for (j = 0; j < nc; j++) iptr[j] = coffd[offdj[oii[i] + j]];
615a16187a7SStefano Zampini       }
6169566063dSJacob Faibussowitsch       PetscCall(PetscSortIntWithScalarArray(nc, iptr, aptr));
61763c07aadSStefano Zampini       iptr += nc;
61863c07aadSStefano Zampini       aptr += nc;
61963c07aadSStefano Zampini     }
6209566063dSJacob Faibussowitsch     if (reuse == MAT_REUSE_MATRIX) PetscCall(PetscFree(ojj));
621225daaf8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
62263c07aadSStefano Zampini       Mat_MPIAIJ *b;
62363c07aadSStefano Zampini       Mat_SeqAIJ *d, *o;
624225daaf8SStefano Zampini 
6259566063dSJacob Faibussowitsch       PetscCall(MatCreateMPIAIJWithSplitArrays(comm, m, n, PETSC_DECIDE, PETSC_DECIDE, dii, djj, da, oii, ojj, oa, B));
62663c07aadSStefano Zampini       /* hack MPIAIJ */
62763c07aadSStefano Zampini       b          = (Mat_MPIAIJ *)((*B)->data);
62863c07aadSStefano Zampini       d          = (Mat_SeqAIJ *)b->A->data;
62963c07aadSStefano Zampini       o          = (Mat_SeqAIJ *)b->B->data;
63063c07aadSStefano Zampini       d->free_a  = PETSC_TRUE;
63163c07aadSStefano Zampini       d->free_ij = PETSC_TRUE;
63263c07aadSStefano Zampini       o->free_a  = PETSC_TRUE;
63363c07aadSStefano Zampini       o->free_ij = PETSC_TRUE;
634225daaf8SStefano Zampini     } else if (reuse == MAT_INPLACE_MATRIX) {
635225daaf8SStefano Zampini       Mat T;
6362cf14000SStefano Zampini 
6379566063dSJacob Faibussowitsch       PetscCall(MatCreateMPIAIJWithSplitArrays(comm, m, n, PETSC_DECIDE, PETSC_DECIDE, dii, djj, da, oii, ojj, oa, &T));
638*b73e3080SStefano Zampini       if (sameint && downs) { /* ownership of CSR pointers is transferred to PETSc */
639225daaf8SStefano Zampini         hypre_CSRMatrixI(hdiag) = NULL;
640225daaf8SStefano Zampini         hypre_CSRMatrixJ(hdiag) = NULL;
641*b73e3080SStefano Zampini       } else { /* Hack MPIAIJ -> free ij but maybe not a */
6422cf14000SStefano Zampini         Mat_MPIAIJ *b = (Mat_MPIAIJ *)(T->data);
6432cf14000SStefano Zampini         Mat_SeqAIJ *d = (Mat_SeqAIJ *)(b->A->data);
6442cf14000SStefano Zampini 
6452cf14000SStefano Zampini         d->free_ij = PETSC_TRUE;
646*b73e3080SStefano Zampini         d->free_a  = downs ? PETSC_FALSE : PETSC_TRUE;
647*b73e3080SStefano Zampini       }
648*b73e3080SStefano Zampini       if (sameint && oowns) { /* ownership of CSR pointers is transferred to PETSc */
649*b73e3080SStefano Zampini         hypre_CSRMatrixI(hoffd) = NULL;
650*b73e3080SStefano Zampini         hypre_CSRMatrixJ(hoffd) = NULL;
651*b73e3080SStefano Zampini       } else { /* Hack MPIAIJ -> free ij but maybe not a */
652*b73e3080SStefano Zampini         Mat_MPIAIJ *b = (Mat_MPIAIJ *)(T->data);
653*b73e3080SStefano Zampini         Mat_SeqAIJ *o = (Mat_SeqAIJ *)(b->B->data);
654*b73e3080SStefano Zampini 
6552cf14000SStefano Zampini         o->free_ij = PETSC_TRUE;
656*b73e3080SStefano Zampini         o->free_a  = oowns ? PETSC_FALSE : PETSC_TRUE;
6572cf14000SStefano Zampini       }
6582cf14000SStefano Zampini       hypre_CSRMatrixData(hdiag) = NULL;
659225daaf8SStefano Zampini       hypre_CSRMatrixData(hoffd) = NULL;
6609566063dSJacob Faibussowitsch       PetscCall(MatHeaderReplace(A, &T));
66163c07aadSStefano Zampini     }
662225daaf8SStefano Zampini   } else {
663225daaf8SStefano Zampini     oii = NULL;
664225daaf8SStefano Zampini     ojj = NULL;
665225daaf8SStefano Zampini     oa  = NULL;
666225daaf8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
66763c07aadSStefano Zampini       Mat_SeqAIJ *b;
6682cf14000SStefano Zampini 
6699566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqAIJWithArrays(comm, m, n, dii, djj, da, B));
67063c07aadSStefano Zampini       /* hack SeqAIJ */
67163c07aadSStefano Zampini       b          = (Mat_SeqAIJ *)((*B)->data);
67263c07aadSStefano Zampini       b->free_a  = PETSC_TRUE;
67363c07aadSStefano Zampini       b->free_ij = PETSC_TRUE;
674225daaf8SStefano Zampini     } else if (reuse == MAT_INPLACE_MATRIX) {
675225daaf8SStefano Zampini       Mat T;
6762cf14000SStefano Zampini 
6779566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqAIJWithArrays(comm, m, n, dii, djj, da, &T));
678*b73e3080SStefano Zampini       if (sameint && downs) { /* ownership of CSR pointers is transferred to PETSc */
679225daaf8SStefano Zampini         hypre_CSRMatrixI(hdiag) = NULL;
680225daaf8SStefano Zampini         hypre_CSRMatrixJ(hdiag) = NULL;
681*b73e3080SStefano Zampini       } else { /* free ij but maybe not a */
6822cf14000SStefano Zampini         Mat_SeqAIJ *b = (Mat_SeqAIJ *)(T->data);
6832cf14000SStefano Zampini 
6842cf14000SStefano Zampini         b->free_ij = PETSC_TRUE;
685*b73e3080SStefano Zampini         b->free_a  = downs ? PETSC_FALSE : PETSC_TRUE;
6862cf14000SStefano Zampini       }
687225daaf8SStefano Zampini       hypre_CSRMatrixData(hdiag) = NULL;
6889566063dSJacob Faibussowitsch       PetscCall(MatHeaderReplace(A, &T));
68963c07aadSStefano Zampini     }
690225daaf8SStefano Zampini   }
691225daaf8SStefano Zampini 
6922cf14000SStefano Zampini   /* we have to use hypre_Tfree to free the HYPRE arrays
693da81f932SPierre Jolivet      that PETSc now owns */
69463c07aadSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
6959371c9d4SSatish Balay     const char *names[6] = {"_hypre_csr_da", "_hypre_csr_oa", "_hypre_csr_dii", "_hypre_csr_djj", "_hypre_csr_oii", "_hypre_csr_ojj"};
696*b73e3080SStefano Zampini     // clang-format off
697*b73e3080SStefano Zampini     void *ptrs[6] = {downs ? da : NULL,
698*b73e3080SStefano Zampini                      oowns ? oa : NULL,
699*b73e3080SStefano Zampini                      downs && sameint ? dii : NULL,
700*b73e3080SStefano Zampini                      downs && sameint ? djj : NULL,
701*b73e3080SStefano Zampini                      oowns && sameint ? oii : NULL,
702*b73e3080SStefano Zampini                      oowns && sameint ? ojj : NULL};
703*b73e3080SStefano Zampini     // clang-format on
704*b73e3080SStefano Zampini     for (i = 0; i < 6; i++) {
705225daaf8SStefano Zampini       PetscContainer c;
706225daaf8SStefano Zampini 
7079566063dSJacob Faibussowitsch       PetscCall(PetscContainerCreate(comm, &c));
7089566063dSJacob Faibussowitsch       PetscCall(PetscContainerSetPointer(c, ptrs[i]));
7099566063dSJacob Faibussowitsch       PetscCall(PetscContainerSetUserDestroy(c, hypre_array_destroy));
7109566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)(*B), names[i], (PetscObject)c));
7119566063dSJacob Faibussowitsch       PetscCall(PetscContainerDestroy(&c));
712225daaf8SStefano Zampini     }
71363c07aadSStefano Zampini   }
7143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71563c07aadSStefano Zampini }
71663c07aadSStefano Zampini 
717d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJGetParCSR_Private(Mat A, hypre_ParCSRMatrix **hA)
718d71ae5a4SJacob Faibussowitsch {
719613e5ff0Sstefano_zampini   hypre_ParCSRMatrix *tA;
720c1a070e6SStefano Zampini   hypre_CSRMatrix    *hdiag, *hoffd;
721c1a070e6SStefano Zampini   Mat_SeqAIJ         *diag, *offd;
7222cf14000SStefano Zampini   PetscInt           *garray, i, noffd, dnnz, onnz, *row_starts, *col_starts;
723c1a070e6SStefano Zampini   MPI_Comm            comm = PetscObjectComm((PetscObject)A);
724613e5ff0Sstefano_zampini   PetscBool           ismpiaij, isseqaij;
7252cf14000SStefano Zampini   PetscBool           sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
7266ea7df73SStefano Zampini   HYPRE_Int          *hdi = NULL, *hdj = NULL, *hoi = NULL, *hoj = NULL;
7275c97c10fSStefano Zampini   PetscInt           *pdi = NULL, *pdj = NULL, *poi = NULL, *poj = NULL;
7286ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
7296ea7df73SStefano Zampini   PetscBool iscuda = PETSC_FALSE;
7306ea7df73SStefano Zampini #endif
731c1a070e6SStefano Zampini 
732c1a070e6SStefano Zampini   PetscFunctionBegin;
7339566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
7349566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isseqaij));
73508401ef6SPierre Jolivet   PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Unsupported type %s", ((PetscObject)A)->type_name);
736ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
737c1a070e6SStefano Zampini   if (ismpiaij) {
738c1a070e6SStefano Zampini     Mat_MPIAIJ *a = (Mat_MPIAIJ *)(A->data);
739c1a070e6SStefano Zampini 
740c1a070e6SStefano Zampini     diag = (Mat_SeqAIJ *)a->A->data;
741c1a070e6SStefano Zampini     offd = (Mat_SeqAIJ *)a->B->data;
7426ea7df73SStefano Zampini #if defined(PETSC_HAVE_CUDA) && defined(PETSC_HAVE_HYPRE_DEVICE) && defined(HYPRE_USING_CUDA)
7439566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMPIAIJCUSPARSE, &iscuda));
7446ea7df73SStefano Zampini     if (iscuda && !A->boundtocpu) {
7456ea7df73SStefano Zampini       sameint = PETSC_TRUE;
7469566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJCUSPARSEGetIJ(a->A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
7479566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJCUSPARSEGetIJ(a->B, PETSC_FALSE, (const HYPRE_Int **)&hoi, (const HYPRE_Int **)&hoj));
7486ea7df73SStefano Zampini     } else {
7496ea7df73SStefano Zampini #else
7506ea7df73SStefano Zampini     {
7516ea7df73SStefano Zampini #endif
7526ea7df73SStefano Zampini       pdi = diag->i;
7536ea7df73SStefano Zampini       pdj = diag->j;
7546ea7df73SStefano Zampini       poi = offd->i;
7556ea7df73SStefano Zampini       poj = offd->j;
7566ea7df73SStefano Zampini       if (sameint) {
7576ea7df73SStefano Zampini         hdi = (HYPRE_Int *)pdi;
7586ea7df73SStefano Zampini         hdj = (HYPRE_Int *)pdj;
7596ea7df73SStefano Zampini         hoi = (HYPRE_Int *)poi;
7606ea7df73SStefano Zampini         hoj = (HYPRE_Int *)poj;
7616ea7df73SStefano Zampini       }
7626ea7df73SStefano Zampini     }
763c1a070e6SStefano Zampini     garray = a->garray;
764c1a070e6SStefano Zampini     noffd  = a->B->cmap->N;
765c1a070e6SStefano Zampini     dnnz   = diag->nz;
766c1a070e6SStefano Zampini     onnz   = offd->nz;
767c1a070e6SStefano Zampini   } else {
768c1a070e6SStefano Zampini     diag = (Mat_SeqAIJ *)A->data;
769c1a070e6SStefano Zampini     offd = NULL;
7706ea7df73SStefano Zampini #if defined(PETSC_HAVE_CUDA) && defined(PETSC_HAVE_HYPRE_DEVICE)
7719566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATSEQAIJCUSPARSE, &iscuda));
7726ea7df73SStefano Zampini     if (iscuda && !A->boundtocpu) {
7736ea7df73SStefano Zampini       sameint = PETSC_TRUE;
7749566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJCUSPARSEGetIJ(A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
7756ea7df73SStefano Zampini     } else {
7766ea7df73SStefano Zampini #else
7776ea7df73SStefano Zampini     {
7786ea7df73SStefano Zampini #endif
7796ea7df73SStefano Zampini       pdi = diag->i;
7806ea7df73SStefano Zampini       pdj = diag->j;
7816ea7df73SStefano Zampini       if (sameint) {
7826ea7df73SStefano Zampini         hdi = (HYPRE_Int *)pdi;
7836ea7df73SStefano Zampini         hdj = (HYPRE_Int *)pdj;
7846ea7df73SStefano Zampini       }
7856ea7df73SStefano Zampini     }
786c1a070e6SStefano Zampini     garray = NULL;
787c1a070e6SStefano Zampini     noffd  = 0;
788c1a070e6SStefano Zampini     dnnz   = diag->nz;
789c1a070e6SStefano Zampini     onnz   = 0;
790c1a070e6SStefano Zampini   }
791225daaf8SStefano Zampini 
792c1a070e6SStefano Zampini   /* create a temporary ParCSR */
793c1a070e6SStefano Zampini   if (HYPRE_AssumedPartitionCheck()) {
794c1a070e6SStefano Zampini     PetscMPIInt myid;
795c1a070e6SStefano Zampini 
7969566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &myid));
797c1a070e6SStefano Zampini     row_starts = A->rmap->range + myid;
798c1a070e6SStefano Zampini     col_starts = A->cmap->range + myid;
799c1a070e6SStefano Zampini   } else {
800c1a070e6SStefano Zampini     row_starts = A->rmap->range;
801c1a070e6SStefano Zampini     col_starts = A->cmap->range;
802c1a070e6SStefano Zampini   }
8032cf14000SStefano Zampini   tA = hypre_ParCSRMatrixCreate(comm, A->rmap->N, A->cmap->N, (HYPRE_BigInt *)row_starts, (HYPRE_BigInt *)col_starts, noffd, dnnz, onnz);
804a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
805c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetRowStartsOwner(tA, 0);
806c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetColStartsOwner(tA, 0);
807a1d2239cSSatish Balay #endif
808c1a070e6SStefano Zampini 
809225daaf8SStefano Zampini   /* set diagonal part */
810c1a070e6SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(tA);
8116ea7df73SStefano Zampini   if (!sameint) { /* malloc CSR pointers */
8129566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(A->rmap->n + 1, &hdi, dnnz, &hdj));
8136ea7df73SStefano Zampini     for (i = 0; i < A->rmap->n + 1; i++) hdi[i] = (HYPRE_Int)(pdi[i]);
8146ea7df73SStefano Zampini     for (i = 0; i < dnnz; i++) hdj[i] = (HYPRE_Int)(pdj[i]);
8152cf14000SStefano Zampini   }
8166ea7df73SStefano Zampini   hypre_CSRMatrixI(hdiag)           = hdi;
8176ea7df73SStefano Zampini   hypre_CSRMatrixJ(hdiag)           = hdj;
81839accc25SStefano Zampini   hypre_CSRMatrixData(hdiag)        = (HYPRE_Complex *)diag->a;
819c1a070e6SStefano Zampini   hypre_CSRMatrixNumNonzeros(hdiag) = diag->nz;
820c1a070e6SStefano Zampini   hypre_CSRMatrixSetRownnz(hdiag);
821c1a070e6SStefano Zampini   hypre_CSRMatrixSetDataOwner(hdiag, 0);
822c1a070e6SStefano Zampini 
823225daaf8SStefano Zampini   /* set offdiagonal part */
824c1a070e6SStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(tA);
825c1a070e6SStefano Zampini   if (offd) {
8266ea7df73SStefano Zampini     if (!sameint) { /* malloc CSR pointers */
8279566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(A->rmap->n + 1, &hoi, onnz, &hoj));
8286ea7df73SStefano Zampini       for (i = 0; i < A->rmap->n + 1; i++) hoi[i] = (HYPRE_Int)(poi[i]);
8296ea7df73SStefano Zampini       for (i = 0; i < onnz; i++) hoj[i] = (HYPRE_Int)(poj[i]);
8302cf14000SStefano Zampini     }
8316ea7df73SStefano Zampini     hypre_CSRMatrixI(hoffd)           = hoi;
8326ea7df73SStefano Zampini     hypre_CSRMatrixJ(hoffd)           = hoj;
83339accc25SStefano Zampini     hypre_CSRMatrixData(hoffd)        = (HYPRE_Complex *)offd->a;
834c1a070e6SStefano Zampini     hypre_CSRMatrixNumNonzeros(hoffd) = offd->nz;
835c1a070e6SStefano Zampini     hypre_CSRMatrixSetRownnz(hoffd);
836c1a070e6SStefano Zampini     hypre_CSRMatrixSetDataOwner(hoffd, 0);
8376ea7df73SStefano Zampini   }
8386ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
839792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, iscuda ? HYPRE_MEMORY_DEVICE : HYPRE_MEMORY_HOST);
8406ea7df73SStefano Zampini #else
8416ea7df73SStefano Zampini   #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0)
842792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixInitialize, tA);
8436ea7df73SStefano Zampini   #else
844792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, HYPRE_MEMORY_HOST);
8456ea7df73SStefano Zampini   #endif
8466ea7df73SStefano Zampini #endif
8476ea7df73SStefano Zampini   hypre_TFree(hypre_ParCSRMatrixColMapOffd(tA), HYPRE_MEMORY_HOST);
848c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetNumNonzeros(tA);
8492cf14000SStefano Zampini   hypre_ParCSRMatrixColMapOffd(tA) = (HYPRE_BigInt *)garray;
850792fecdfSBarry Smith   if (!hypre_ParCSRMatrixCommPkg(tA)) PetscCallExternal(hypre_MatvecCommPkgCreate, tA);
851613e5ff0Sstefano_zampini   *hA = tA;
8523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
853613e5ff0Sstefano_zampini }
854c1a070e6SStefano Zampini 
855d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAIJRestoreParCSR_Private(Mat A, hypre_ParCSRMatrix **hA)
856d71ae5a4SJacob Faibussowitsch {
857613e5ff0Sstefano_zampini   hypre_CSRMatrix *hdiag, *hoffd;
8586ea7df73SStefano Zampini   PetscBool        ismpiaij, sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
8596ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
8606ea7df73SStefano Zampini   PetscBool iscuda = PETSC_FALSE;
8616ea7df73SStefano Zampini #endif
862c1a070e6SStefano Zampini 
863613e5ff0Sstefano_zampini   PetscFunctionBegin;
8649566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
8656ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
8669566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, ""));
8676ea7df73SStefano Zampini   if (iscuda) sameint = PETSC_TRUE;
8686ea7df73SStefano Zampini #endif
869613e5ff0Sstefano_zampini   hdiag = hypre_ParCSRMatrixDiag(*hA);
870613e5ff0Sstefano_zampini   hoffd = hypre_ParCSRMatrixOffd(*hA);
8716ea7df73SStefano Zampini   /* free temporary memory allocated by PETSc
8726ea7df73SStefano Zampini      set pointers to NULL before destroying tA */
8732cf14000SStefano Zampini   if (!sameint) {
8742cf14000SStefano Zampini     HYPRE_Int *hi, *hj;
8752cf14000SStefano Zampini 
8762cf14000SStefano Zampini     hi = hypre_CSRMatrixI(hdiag);
8772cf14000SStefano Zampini     hj = hypre_CSRMatrixJ(hdiag);
8789566063dSJacob Faibussowitsch     PetscCall(PetscFree2(hi, hj));
8796ea7df73SStefano Zampini     if (ismpiaij) {
8802cf14000SStefano Zampini       hi = hypre_CSRMatrixI(hoffd);
8812cf14000SStefano Zampini       hj = hypre_CSRMatrixJ(hoffd);
8829566063dSJacob Faibussowitsch       PetscCall(PetscFree2(hi, hj));
8832cf14000SStefano Zampini     }
8842cf14000SStefano Zampini   }
885c1a070e6SStefano Zampini   hypre_CSRMatrixI(hdiag)    = NULL;
886c1a070e6SStefano Zampini   hypre_CSRMatrixJ(hdiag)    = NULL;
887c1a070e6SStefano Zampini   hypre_CSRMatrixData(hdiag) = NULL;
8886ea7df73SStefano Zampini   if (ismpiaij) {
889c1a070e6SStefano Zampini     hypre_CSRMatrixI(hoffd)    = NULL;
890c1a070e6SStefano Zampini     hypre_CSRMatrixJ(hoffd)    = NULL;
891c1a070e6SStefano Zampini     hypre_CSRMatrixData(hoffd) = NULL;
8926ea7df73SStefano Zampini   }
893613e5ff0Sstefano_zampini   hypre_ParCSRMatrixColMapOffd(*hA) = NULL;
894613e5ff0Sstefano_zampini   hypre_ParCSRMatrixDestroy(*hA);
895613e5ff0Sstefano_zampini   *hA = NULL;
8963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
897613e5ff0Sstefano_zampini }
898613e5ff0Sstefano_zampini 
899613e5ff0Sstefano_zampini /* calls RAP from BoomerAMG:
9003dad0653Sstefano_zampini    the resulting ParCSR will not own the column and row starts
9016ea7df73SStefano Zampini    It looks like we don't need to have the diagonal entries ordered first */
902d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_RAP(hypre_ParCSRMatrix *hR, hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hP, hypre_ParCSRMatrix **hRAP)
903d71ae5a4SJacob Faibussowitsch {
904a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
905613e5ff0Sstefano_zampini   HYPRE_Int P_owns_col_starts, R_owns_row_starts;
906a1d2239cSSatish Balay #endif
907613e5ff0Sstefano_zampini 
908613e5ff0Sstefano_zampini   PetscFunctionBegin;
909a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
910613e5ff0Sstefano_zampini   P_owns_col_starts = hypre_ParCSRMatrixOwnsColStarts(hP);
911613e5ff0Sstefano_zampini   R_owns_row_starts = hypre_ParCSRMatrixOwnsRowStarts(hR);
912a1d2239cSSatish Balay #endif
9136ea7df73SStefano Zampini   /* can be replaced by version test later */
9146ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
915792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParCSRMatrixRAP");
9166ea7df73SStefano Zampini   *hRAP = hypre_ParCSRMatrixRAP(hR, hA, hP);
9176ea7df73SStefano Zampini   PetscStackPop;
9186ea7df73SStefano Zampini #else
919792fecdfSBarry Smith   PetscCallExternal(hypre_BoomerAMGBuildCoarseOperator, hR, hA, hP, hRAP);
920792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixSetNumNonzeros, *hRAP);
9216ea7df73SStefano Zampini #endif
922613e5ff0Sstefano_zampini   /* hypre_BoomerAMGBuildCoarseOperator steals the col_starts from P and the row_starts from R */
923a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
924613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetRowStartsOwner(*hRAP, 0);
925613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetColStartsOwner(*hRAP, 0);
926613e5ff0Sstefano_zampini   if (P_owns_col_starts) hypre_ParCSRMatrixSetColStartsOwner(hP, 1);
927613e5ff0Sstefano_zampini   if (R_owns_row_starts) hypre_ParCSRMatrixSetRowStartsOwner(hR, 1);
928a1d2239cSSatish Balay #endif
9293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
930613e5ff0Sstefano_zampini }
931613e5ff0Sstefano_zampini 
932d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat P, Mat C)
933d71ae5a4SJacob Faibussowitsch {
9346f231fbdSstefano_zampini   Mat                 B;
9356abb4441SStefano Zampini   hypre_ParCSRMatrix *hA, *hP, *hPtAP = NULL;
9364222ddf1SHong Zhang   Mat_Product        *product = C->product;
937613e5ff0Sstefano_zampini 
938613e5ff0Sstefano_zampini   PetscFunctionBegin;
9399566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
9409566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(P, &hP));
9419566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(hP, hA, hP, &hPtAP));
9429566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hPtAP, MATAIJ, PETSC_OWN_POINTER, &B));
9434222ddf1SHong Zhang 
9449566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
9454222ddf1SHong Zhang   C->product = product;
9464222ddf1SHong Zhang 
9479566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
9489566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(P, &hP));
9493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9506f231fbdSstefano_zampini }
9516f231fbdSstefano_zampini 
952d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatPtAPSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat P, PetscReal fill, Mat C)
953d71ae5a4SJacob Faibussowitsch {
9546f231fbdSstefano_zampini   PetscFunctionBegin;
9559566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATAIJ));
9564222ddf1SHong Zhang   C->ops->ptapnumeric    = MatPtAPNumeric_AIJ_AIJ_wHYPRE;
9574222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
9583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
959613e5ff0Sstefano_zampini }
960613e5ff0Sstefano_zampini 
961d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_AIJ_HYPRE(Mat A, Mat P, Mat C)
962d71ae5a4SJacob Faibussowitsch {
9634cc28894Sstefano_zampini   Mat                 B;
9644cc28894Sstefano_zampini   Mat_HYPRE          *hP;
9656abb4441SStefano Zampini   hypre_ParCSRMatrix *hA = NULL, *Pparcsr, *ptapparcsr = NULL;
966613e5ff0Sstefano_zampini   HYPRE_Int           type;
967613e5ff0Sstefano_zampini   MPI_Comm            comm = PetscObjectComm((PetscObject)A);
9684cc28894Sstefano_zampini   PetscBool           ishypre;
969613e5ff0Sstefano_zampini 
970613e5ff0Sstefano_zampini   PetscFunctionBegin;
9719566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre));
97228b400f6SJacob Faibussowitsch   PetscCheck(ishypre, comm, PETSC_ERR_USER, "P should be of type %s", MATHYPRE);
9734cc28894Sstefano_zampini   hP = (Mat_HYPRE *)P->data;
974792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type);
97508401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
976792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr);
977613e5ff0Sstefano_zampini 
9789566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
9799566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, hA, Pparcsr, &ptapparcsr));
9809566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
981225daaf8SStefano Zampini 
9824cc28894Sstefano_zampini   /* create temporary matrix and merge to C */
9839566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ptapparcsr, ((PetscObject)C)->type_name, PETSC_OWN_POINTER, &B));
9849566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
9853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9864cc28894Sstefano_zampini }
9874cc28894Sstefano_zampini 
988d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatPtAPNumeric_HYPRE_HYPRE(Mat A, Mat P, Mat C)
989d71ae5a4SJacob Faibussowitsch {
9904cc28894Sstefano_zampini   Mat                 B;
9916abb4441SStefano Zampini   hypre_ParCSRMatrix *Aparcsr, *Pparcsr, *ptapparcsr = NULL;
9924cc28894Sstefano_zampini   Mat_HYPRE          *hA, *hP;
9934cc28894Sstefano_zampini   PetscBool           ishypre;
9944cc28894Sstefano_zampini   HYPRE_Int           type;
9954cc28894Sstefano_zampini 
9964cc28894Sstefano_zampini   PetscFunctionBegin;
9979566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre));
99828b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)P), PETSC_ERR_USER, "P should be of type %s", MATHYPRE);
9999566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
100028b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE);
10014cc28894Sstefano_zampini   hA = (Mat_HYPRE *)A->data;
10024cc28894Sstefano_zampini   hP = (Mat_HYPRE *)P->data;
1003792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
100408401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1005792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type);
100608401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)P), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1007792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr);
1008792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr);
10099566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, Aparcsr, Pparcsr, &ptapparcsr));
10109566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ptapparcsr, MATHYPRE, PETSC_OWN_POINTER, &B));
10119566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
10123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10134cc28894Sstefano_zampini }
10144cc28894Sstefano_zampini 
1015d501dc42Sstefano_zampini /* calls hypre_ParMatmul
1016d501dc42Sstefano_zampini    hypre_ParMatMul uses hypre_ParMatrixCreate with the communicator of hA
10173dad0653Sstefano_zampini    hypre_ParMatrixCreate does not duplicate the communicator
10186ea7df73SStefano Zampini    It looks like we don't need to have the diagonal entries ordered first */
1019d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_ParCSR_MatMatMult(hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hB, hypre_ParCSRMatrix **hAB)
1020d71ae5a4SJacob Faibussowitsch {
1021d501dc42Sstefano_zampini   PetscFunctionBegin;
10226ea7df73SStefano Zampini   /* can be replaced by version test later */
10236ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
1024792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParCSRMatMat");
10256ea7df73SStefano Zampini   *hAB = hypre_ParCSRMatMat(hA, hB);
10266ea7df73SStefano Zampini #else
1027792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParMatmul");
1028d501dc42Sstefano_zampini   *hAB = hypre_ParMatmul(hA, hB);
10296ea7df73SStefano Zampini #endif
1030d501dc42Sstefano_zampini   PetscStackPop;
10313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1032d501dc42Sstefano_zampini }
1033d501dc42Sstefano_zampini 
1034d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C)
1035d71ae5a4SJacob Faibussowitsch {
10365e5acdf2Sstefano_zampini   Mat                 D;
1037d501dc42Sstefano_zampini   hypre_ParCSRMatrix *hA, *hB, *hAB = NULL;
10384222ddf1SHong Zhang   Mat_Product        *product = C->product;
10395e5acdf2Sstefano_zampini 
10405e5acdf2Sstefano_zampini   PetscFunctionBegin;
10419566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
10429566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(B, &hB));
10439566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_MatMatMult(hA, hB, &hAB));
10449566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hAB, MATAIJ, PETSC_OWN_POINTER, &D));
10454222ddf1SHong Zhang 
10469566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &D));
10474222ddf1SHong Zhang   C->product = product;
10484222ddf1SHong Zhang 
10499566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
10509566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(B, &hB));
10513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10525e5acdf2Sstefano_zampini }
10535e5acdf2Sstefano_zampini 
1054d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatMatMultSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat B, PetscReal fill, Mat C)
1055d71ae5a4SJacob Faibussowitsch {
10565e5acdf2Sstefano_zampini   PetscFunctionBegin;
10579566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATAIJ));
10584222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_AIJ_AIJ_wHYPRE;
10594222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
10603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10615e5acdf2Sstefano_zampini }
10625e5acdf2Sstefano_zampini 
1063d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMatMultNumeric_HYPRE_HYPRE(Mat A, Mat B, Mat C)
1064d71ae5a4SJacob Faibussowitsch {
1065d501dc42Sstefano_zampini   Mat                 D;
1066d501dc42Sstefano_zampini   hypre_ParCSRMatrix *Aparcsr, *Bparcsr, *ABparcsr = NULL;
1067d501dc42Sstefano_zampini   Mat_HYPRE          *hA, *hB;
1068d501dc42Sstefano_zampini   PetscBool           ishypre;
1069d501dc42Sstefano_zampini   HYPRE_Int           type;
10704222ddf1SHong Zhang   Mat_Product        *product;
1071d501dc42Sstefano_zampini 
1072d501dc42Sstefano_zampini   PetscFunctionBegin;
10739566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)B, MATHYPRE, &ishypre));
107428b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)B), PETSC_ERR_USER, "B should be of type %s", MATHYPRE);
10759566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
107628b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE);
1077d501dc42Sstefano_zampini   hA = (Mat_HYPRE *)A->data;
1078d501dc42Sstefano_zampini   hB = (Mat_HYPRE *)B->data;
1079792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
108008401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1081792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hB->ij, &type);
108208401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
1083792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr);
1084792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hB->ij, (void **)&Bparcsr);
10859566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_MatMatMult(Aparcsr, Bparcsr, &ABparcsr));
10869566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ABparcsr, MATHYPRE, PETSC_OWN_POINTER, &D));
10874222ddf1SHong Zhang 
1088d501dc42Sstefano_zampini   /* need to use HeaderReplace because HeaderMerge messes up with the communicator */
10894222ddf1SHong Zhang   product    = C->product; /* save it from MatHeaderReplace() */
10904222ddf1SHong Zhang   C->product = NULL;
10919566063dSJacob Faibussowitsch   PetscCall(MatHeaderReplace(C, &D));
10924222ddf1SHong Zhang   C->product             = product;
1093d501dc42Sstefano_zampini   C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE;
10944222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
10953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1096d501dc42Sstefano_zampini }
1097d501dc42Sstefano_zampini 
1098d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultNumeric_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, Mat D)
1099d71ae5a4SJacob Faibussowitsch {
110020e1dc0dSstefano_zampini   Mat                 E;
11016abb4441SStefano Zampini   hypre_ParCSRMatrix *hA, *hB, *hC, *hABC = NULL;
110220e1dc0dSstefano_zampini 
110320e1dc0dSstefano_zampini   PetscFunctionBegin;
11049566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
11059566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(B, &hB));
11069566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(C, &hC));
11079566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(hA, hB, hC, &hABC));
11089566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hABC, MATAIJ, PETSC_OWN_POINTER, &E));
11099566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(D, &E));
11109566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
11119566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(B, &hB));
11129566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(C, &hC));
11133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
111420e1dc0dSstefano_zampini }
111520e1dc0dSstefano_zampini 
1116d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode MatTransposeMatMatMultSymbolic_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, PetscReal fill, Mat D)
1117d71ae5a4SJacob Faibussowitsch {
111820e1dc0dSstefano_zampini   PetscFunctionBegin;
11199566063dSJacob Faibussowitsch   PetscCall(MatSetType(D, MATAIJ));
11203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
112120e1dc0dSstefano_zampini }
112220e1dc0dSstefano_zampini 
1123d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_AB_HYPRE(Mat C)
1124d71ae5a4SJacob Faibussowitsch {
11254222ddf1SHong Zhang   PetscFunctionBegin;
11264222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
11273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11284222ddf1SHong Zhang }
11294222ddf1SHong Zhang 
1130d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_AB(Mat C)
1131d71ae5a4SJacob Faibussowitsch {
11324222ddf1SHong Zhang   Mat_Product *product = C->product;
11334222ddf1SHong Zhang   PetscBool    Ahypre;
11344222ddf1SHong Zhang 
11354222ddf1SHong Zhang   PetscFunctionBegin;
11369566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)product->A, MATHYPRE, &Ahypre));
11374222ddf1SHong Zhang   if (Ahypre) { /* A is a Hypre matrix */
11389566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
11394222ddf1SHong Zhang     C->ops->productsymbolic = MatProductSymbolic_AB_HYPRE;
11404222ddf1SHong Zhang     C->ops->matmultnumeric  = MatMatMultNumeric_HYPRE_HYPRE;
11413ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
11426718818eSStefano Zampini   }
11433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11444222ddf1SHong Zhang }
11454222ddf1SHong Zhang 
1146d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSymbolic_PtAP_HYPRE(Mat C)
1147d71ae5a4SJacob Faibussowitsch {
11484222ddf1SHong Zhang   PetscFunctionBegin;
11494222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
11503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11514222ddf1SHong Zhang }
11524222ddf1SHong Zhang 
1153d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE_PtAP(Mat C)
1154d71ae5a4SJacob Faibussowitsch {
11554222ddf1SHong Zhang   Mat_Product *product = C->product;
11564222ddf1SHong Zhang   PetscBool    flg;
11574222ddf1SHong Zhang   PetscInt     type        = 0;
11584222ddf1SHong Zhang   const char  *outTypes[4] = {"aij", "seqaij", "mpiaij", "hypre"};
11594222ddf1SHong Zhang   PetscInt     ntype       = 4;
11604222ddf1SHong Zhang   Mat          A           = product->A;
11614222ddf1SHong Zhang   PetscBool    Ahypre;
11624222ddf1SHong Zhang 
11634222ddf1SHong Zhang   PetscFunctionBegin;
11649566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &Ahypre));
11654222ddf1SHong Zhang   if (Ahypre) { /* A is a Hypre matrix */
11669566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
11674222ddf1SHong Zhang     C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE;
11684222ddf1SHong Zhang     C->ops->ptapnumeric     = MatPtAPNumeric_HYPRE_HYPRE;
11693ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
11704222ddf1SHong Zhang   }
11714222ddf1SHong Zhang 
11724222ddf1SHong Zhang   /* A is AIJ, P is Hypre, C = PtAP can be either AIJ or Hypre format */
11734222ddf1SHong Zhang   /* Get runtime option */
11744222ddf1SHong Zhang   if (product->api_user) {
1175d0609cedSBarry Smith     PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatPtAP_HYPRE", "Mat");
11769566063dSJacob Faibussowitsch     PetscCall(PetscOptionsEList("-matptap_hypre_outtype", "MatPtAP outtype", "MatPtAP outtype", outTypes, ntype, outTypes[type], &type, &flg));
1177d0609cedSBarry Smith     PetscOptionsEnd();
11784222ddf1SHong Zhang   } else {
1179d0609cedSBarry Smith     PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatProduct_PtAP_HYPRE", "Mat");
11809566063dSJacob Faibussowitsch     PetscCall(PetscOptionsEList("-mat_product_algorithm_hypre_outtype", "MatProduct_PtAP outtype", "MatProduct_PtAP", outTypes, ntype, outTypes[type], &type, &flg));
1181d0609cedSBarry Smith     PetscOptionsEnd();
11824222ddf1SHong Zhang   }
11834222ddf1SHong Zhang 
11844222ddf1SHong Zhang   if (type == 0 || type == 1 || type == 2) {
11859566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATAIJ));
11864222ddf1SHong Zhang   } else if (type == 3) {
11879566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
11884222ddf1SHong Zhang   } else SETERRQ(PetscObjectComm((PetscObject)C), PETSC_ERR_SUP, "MatPtAP outtype is not supported");
11894222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE;
11904222ddf1SHong Zhang   C->ops->ptapnumeric     = MatPtAPNumeric_AIJ_HYPRE;
11913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11924222ddf1SHong Zhang }
11934222ddf1SHong Zhang 
1194d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatProductSetFromOptions_HYPRE(Mat C)
1195d71ae5a4SJacob Faibussowitsch {
11964222ddf1SHong Zhang   Mat_Product *product = C->product;
11974222ddf1SHong Zhang 
11984222ddf1SHong Zhang   PetscFunctionBegin;
11994222ddf1SHong Zhang   switch (product->type) {
1200d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_AB:
1201d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_HYPRE_AB(C));
1202d71ae5a4SJacob Faibussowitsch     break;
1203d71ae5a4SJacob Faibussowitsch   case MATPRODUCT_PtAP:
1204d71ae5a4SJacob Faibussowitsch     PetscCall(MatProductSetFromOptions_HYPRE_PtAP(C));
1205d71ae5a4SJacob Faibussowitsch     break;
1206d71ae5a4SJacob Faibussowitsch   default:
1207d71ae5a4SJacob Faibussowitsch     break;
12084222ddf1SHong Zhang   }
12093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
12104222ddf1SHong Zhang }
12114222ddf1SHong Zhang 
1212d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTranspose_HYPRE(Mat A, Vec x, Vec y)
1213d71ae5a4SJacob Faibussowitsch {
121463c07aadSStefano Zampini   PetscFunctionBegin;
12159566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_TRUE));
12163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
121763c07aadSStefano Zampini }
121863c07aadSStefano Zampini 
1219d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMult_HYPRE(Mat A, Vec x, Vec y)
1220d71ae5a4SJacob Faibussowitsch {
122163c07aadSStefano Zampini   PetscFunctionBegin;
12229566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_FALSE));
12233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
122463c07aadSStefano Zampini }
122563c07aadSStefano Zampini 
1226d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultAdd_HYPRE(Mat A, Vec x, Vec y, Vec z)
1227d71ae5a4SJacob Faibussowitsch {
1228414bd5c3SStefano Zampini   PetscFunctionBegin;
122948a46eb9SPierre Jolivet   if (y != z) PetscCall(VecCopy(y, z));
12309566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_FALSE));
12313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1232414bd5c3SStefano Zampini }
1233414bd5c3SStefano Zampini 
1234d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMultTransposeAdd_HYPRE(Mat A, Vec x, Vec y, Vec z)
1235d71ae5a4SJacob Faibussowitsch {
1236414bd5c3SStefano Zampini   PetscFunctionBegin;
123748a46eb9SPierre Jolivet   if (y != z) PetscCall(VecCopy(y, z));
12389566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_TRUE));
12393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1240414bd5c3SStefano Zampini }
1241414bd5c3SStefano Zampini 
1242414bd5c3SStefano Zampini /* y = a * A * x + b * y or y = a * A^t * x + b * y depending on trans */
1243d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRE_MultKernel_Private(Mat A, HYPRE_Complex a, Vec x, HYPRE_Complex b, Vec y, PetscBool trans)
1244d71ae5a4SJacob Faibussowitsch {
124563c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE *)A->data;
124663c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
124763c07aadSStefano Zampini   hypre_ParVector    *hx, *hy;
124863c07aadSStefano Zampini 
124963c07aadSStefano Zampini   PetscFunctionBegin;
125063c07aadSStefano Zampini   if (trans) {
12519566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorPushVecRead(hA->b, x));
12529566063dSJacob Faibussowitsch     if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->x, y));
12539566063dSJacob Faibussowitsch     else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->x, y));
1254792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hx);
1255792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hy);
125663c07aadSStefano Zampini   } else {
12579566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorPushVecRead(hA->x, x));
12589566063dSJacob Faibussowitsch     if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->b, y));
12599566063dSJacob Faibussowitsch     else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->b, y));
1260792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hx);
1261792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hy);
126263c07aadSStefano Zampini   }
1263792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
12646ea7df73SStefano Zampini   if (trans) {
1265792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMatvecT, a, parcsr, hx, b, hy);
12666ea7df73SStefano Zampini   } else {
1267792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMatvec, a, parcsr, hx, b, hy);
12686ea7df73SStefano Zampini   }
12699566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hA->x));
12709566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hA->b));
12713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
127263c07aadSStefano Zampini }
127363c07aadSStefano Zampini 
1274d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatDestroy_HYPRE(Mat A)
1275d71ae5a4SJacob Faibussowitsch {
127663c07aadSStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
127763c07aadSStefano Zampini 
127863c07aadSStefano Zampini   PetscFunctionBegin;
12799566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&hA->x));
12809566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&hA->b));
1281978814f1SStefano Zampini   if (hA->ij) {
1282978814f1SStefano Zampini     if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL;
1283792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixDestroy, hA->ij);
1284978814f1SStefano Zampini   }
12859566063dSJacob Faibussowitsch   if (hA->comm) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)A), &hA->comm));
1286c69f721fSFande Kong 
12879566063dSJacob Faibussowitsch   PetscCall(MatStashDestroy_Private(&A->stash));
12889566063dSJacob Faibussowitsch   PetscCall(PetscFree(hA->array));
1289c69f721fSFande Kong 
12905fbaff96SJunchao Zhang   if (hA->cooMat) {
12915fbaff96SJunchao Zhang     PetscCall(MatDestroy(&hA->cooMat));
1292e77caa6dSBarry Smith     PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hA->diagJ, hA->memType));
1293e77caa6dSBarry Smith     PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hA->offdJ, hA->memType));
1294e77caa6dSBarry Smith     PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hA->diag, hA->memType));
12955fbaff96SJunchao Zhang   }
12965fbaff96SJunchao Zhang 
12979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_aij_C", NULL));
12989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_is_C", NULL));
12999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_hypre_C", NULL));
13009566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaij_hypre_C", NULL));
13019566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPRESetPreallocation_C", NULL));
13029566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPREGetParCSR_C", NULL));
13035fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL));
13045fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL));
13059566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->data));
13063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
130763c07aadSStefano Zampini }
130863c07aadSStefano Zampini 
1309d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetUp_HYPRE(Mat A)
1310d71ae5a4SJacob Faibussowitsch {
13114ec6421dSstefano_zampini   PetscFunctionBegin;
13129566063dSJacob Faibussowitsch   PetscCall(MatHYPRESetPreallocation(A, PETSC_DEFAULT, NULL, PETSC_DEFAULT, NULL));
13133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13144ec6421dSstefano_zampini }
13154ec6421dSstefano_zampini 
13166ea7df73SStefano Zampini //TODO FIX hypre_CSRMatrixMatvecOutOfPlace
13176ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
1318d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatBindToCPU_HYPRE(Mat A, PetscBool bind)
1319d71ae5a4SJacob Faibussowitsch {
13206ea7df73SStefano Zampini   Mat_HYPRE           *hA   = (Mat_HYPRE *)A->data;
13216ea7df73SStefano Zampini   HYPRE_MemoryLocation hmem = bind ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE;
13226ea7df73SStefano Zampini 
13236ea7df73SStefano Zampini   PetscFunctionBegin;
13246ea7df73SStefano Zampini   A->boundtocpu = bind;
13255fbaff96SJunchao Zhang   if (hA->ij && hypre_IJMatrixAssembleFlag(hA->ij) && hmem != hypre_IJMatrixMemoryLocation(hA->ij)) {
13266ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
1327792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
1328792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMigrate, parcsr, hmem);
13296ea7df73SStefano Zampini   }
13309566063dSJacob Faibussowitsch   if (hA->x) PetscCall(VecHYPRE_IJBindToCPU(hA->x, bind));
13319566063dSJacob Faibussowitsch   if (hA->b) PetscCall(VecHYPRE_IJBindToCPU(hA->b, bind));
13323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
13336ea7df73SStefano Zampini }
13346ea7df73SStefano Zampini #endif
13356ea7df73SStefano Zampini 
1336d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_HYPRE(Mat A, MatAssemblyType mode)
1337d71ae5a4SJacob Faibussowitsch {
133863c07aadSStefano Zampini   Mat_HYPRE   *hA = (Mat_HYPRE *)A->data;
1339c69f721fSFande Kong   PetscMPIInt  n;
1340c69f721fSFande Kong   PetscInt     i, j, rstart, ncols, flg;
1341c69f721fSFande Kong   PetscInt    *row, *col;
1342c69f721fSFande Kong   PetscScalar *val;
134363c07aadSStefano Zampini 
134463c07aadSStefano Zampini   PetscFunctionBegin;
134508401ef6SPierre Jolivet   PetscCheck(mode != MAT_FLUSH_ASSEMBLY, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_FLUSH_ASSEMBLY currently not supported with MATHYPRE");
1346c69f721fSFande Kong 
1347c69f721fSFande Kong   if (!A->nooffprocentries) {
1348c69f721fSFande Kong     while (1) {
13499566063dSJacob Faibussowitsch       PetscCall(MatStashScatterGetMesg_Private(&A->stash, &n, &row, &col, &val, &flg));
1350c69f721fSFande Kong       if (!flg) break;
1351c69f721fSFande Kong 
1352c69f721fSFande Kong       for (i = 0; i < n;) {
1353c69f721fSFande Kong         /* Now identify the consecutive vals belonging to the same row */
1354c69f721fSFande Kong         for (j = i, rstart = row[j]; j < n; j++) {
1355c69f721fSFande Kong           if (row[j] != rstart) break;
1356c69f721fSFande Kong         }
1357c69f721fSFande Kong         if (j < n) ncols = j - i;
1358c69f721fSFande Kong         else ncols = n - i;
1359c69f721fSFande Kong         /* Now assemble all these values with a single function call */
13609566063dSJacob Faibussowitsch         PetscCall(MatSetValues_HYPRE(A, 1, row + i, ncols, col + i, val + i, A->insertmode));
1361c69f721fSFande Kong 
1362c69f721fSFande Kong         i = j;
1363c69f721fSFande Kong       }
1364c69f721fSFande Kong     }
13659566063dSJacob Faibussowitsch     PetscCall(MatStashScatterEnd_Private(&A->stash));
1366c69f721fSFande Kong   }
1367c69f721fSFande Kong 
1368792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixAssemble, hA->ij);
1369336664bdSPierre Jolivet   /* The assembly routine destroys the aux_matrix, we recreate it here by calling HYPRE_IJMatrixInitialize */
1370336664bdSPierre 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 */
1371336664bdSPierre Jolivet   if (!hA->sorted_full) {
1372af1cf968SStefano Zampini     hypre_AuxParCSRMatrix *aux_matrix;
1373af1cf968SStefano Zampini 
1374af1cf968SStefano Zampini     /* call destroy just to make sure we do not leak anything */
1375af1cf968SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
1376792fecdfSBarry Smith     PetscCallExternal(hypre_AuxParCSRMatrixDestroy, aux_matrix);
1377af1cf968SStefano Zampini     hypre_IJMatrixTranslator(hA->ij) = NULL;
1378af1cf968SStefano Zampini 
1379af1cf968SStefano Zampini     /* Initialize with assembled flag -> it only recreates the aux_par_matrix */
1380792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij);
1381af1cf968SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
13826ea7df73SStefano Zampini     if (aux_matrix) {
1383af1cf968SStefano Zampini       hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1; /* see comment in MatHYPRESetPreallocation_HYPRE */
138422235d61SPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
1385792fecdfSBarry Smith       PetscCallExternal(hypre_AuxParCSRMatrixInitialize, aux_matrix);
138622235d61SPierre Jolivet #else
1387792fecdfSBarry Smith       PetscCallExternal(hypre_AuxParCSRMatrixInitialize_v2, aux_matrix, HYPRE_MEMORY_HOST);
138822235d61SPierre Jolivet #endif
1389af1cf968SStefano Zampini     }
13906ea7df73SStefano Zampini   }
13916ea7df73SStefano Zampini   {
13926ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
13936ea7df73SStefano Zampini 
1394792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
1395792fecdfSBarry Smith     if (!hypre_ParCSRMatrixCommPkg(parcsr)) PetscCallExternal(hypre_MatvecCommPkgCreate, parcsr);
13966ea7df73SStefano Zampini   }
13979566063dSJacob Faibussowitsch   if (!hA->x) PetscCall(VecHYPRE_IJVectorCreate(A->cmap, &hA->x));
13989566063dSJacob Faibussowitsch   if (!hA->b) PetscCall(VecHYPRE_IJVectorCreate(A->rmap, &hA->b));
13996ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
14009566063dSJacob Faibussowitsch   PetscCall(MatBindToCPU_HYPRE(A, A->boundtocpu));
14016ea7df73SStefano Zampini #endif
14023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
140363c07aadSStefano Zampini }
140463c07aadSStefano Zampini 
1405d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetArray_HYPRE(Mat A, PetscInt size, void **array)
1406d71ae5a4SJacob Faibussowitsch {
1407c69f721fSFande Kong   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1408c69f721fSFande Kong 
1409c69f721fSFande Kong   PetscFunctionBegin;
141028b400f6SJacob Faibussowitsch   PetscCheck(hA->available, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Temporary space is in use");
1411c69f721fSFande Kong 
141239accc25SStefano Zampini   if (hA->size >= size) {
141339accc25SStefano Zampini     *array = hA->array;
141439accc25SStefano Zampini   } else {
14159566063dSJacob Faibussowitsch     PetscCall(PetscFree(hA->array));
1416c69f721fSFande Kong     hA->size = size;
14179566063dSJacob Faibussowitsch     PetscCall(PetscMalloc(hA->size, &hA->array));
1418c69f721fSFande Kong     *array = hA->array;
1419c69f721fSFande Kong   }
1420c69f721fSFande Kong 
1421c69f721fSFande Kong   hA->available = PETSC_FALSE;
14223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1423c69f721fSFande Kong }
1424c69f721fSFande Kong 
1425d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreArray_HYPRE(Mat A, void **array)
1426d71ae5a4SJacob Faibussowitsch {
1427c69f721fSFande Kong   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1428c69f721fSFande Kong 
1429c69f721fSFande Kong   PetscFunctionBegin;
1430c69f721fSFande Kong   *array        = NULL;
1431c69f721fSFande Kong   hA->available = PETSC_TRUE;
14323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1433c69f721fSFande Kong }
1434c69f721fSFande Kong 
1435d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValues_HYPRE(Mat A, PetscInt nr, const PetscInt rows[], PetscInt nc, const PetscInt cols[], const PetscScalar v[], InsertMode ins)
1436d71ae5a4SJacob Faibussowitsch {
1437d975228cSstefano_zampini   Mat_HYPRE     *hA   = (Mat_HYPRE *)A->data;
1438d975228cSstefano_zampini   PetscScalar   *vals = (PetscScalar *)v;
143939accc25SStefano Zampini   HYPRE_Complex *sscr;
1440c69f721fSFande Kong   PetscInt      *cscr[2];
1441c69f721fSFande Kong   PetscInt       i, nzc;
144208defe43SFande Kong   void          *array = NULL;
1443d975228cSstefano_zampini 
1444d975228cSstefano_zampini   PetscFunctionBegin;
14459566063dSJacob Faibussowitsch   PetscCall(MatGetArray_HYPRE(A, sizeof(PetscInt) * (2 * nc) + sizeof(HYPRE_Complex) * nc * nr, &array));
1446c69f721fSFande Kong   cscr[0] = (PetscInt *)array;
1447c69f721fSFande Kong   cscr[1] = ((PetscInt *)array) + nc;
144839accc25SStefano Zampini   sscr    = (HYPRE_Complex *)(((PetscInt *)array) + nc * 2);
1449d975228cSstefano_zampini   for (i = 0, nzc = 0; i < nc; i++) {
1450d975228cSstefano_zampini     if (cols[i] >= 0) {
1451d975228cSstefano_zampini       cscr[0][nzc]   = cols[i];
1452d975228cSstefano_zampini       cscr[1][nzc++] = i;
1453d975228cSstefano_zampini     }
1454d975228cSstefano_zampini   }
1455c69f721fSFande Kong   if (!nzc) {
14569566063dSJacob Faibussowitsch     PetscCall(MatRestoreArray_HYPRE(A, &array));
14573ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1458c69f721fSFande Kong   }
1459d975228cSstefano_zampini 
14606ea7df73SStefano Zampini #if 0 //defined(PETSC_HAVE_HYPRE_DEVICE)
14616ea7df73SStefano Zampini   if (HYPRE_MEMORY_HOST != hypre_IJMatrixMemoryLocation(hA->ij)) {
14626ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
14636ea7df73SStefano Zampini 
1464792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject,hA->ij,(void**)&parcsr);
1465792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMigrate,parcsr, HYPRE_MEMORY_HOST);
14666ea7df73SStefano Zampini   }
14676ea7df73SStefano Zampini #endif
14686ea7df73SStefano Zampini 
1469d975228cSstefano_zampini   if (ins == ADD_VALUES) {
1470d975228cSstefano_zampini     for (i = 0; i < nr; i++) {
14716ea7df73SStefano Zampini       if (rows[i] >= 0) {
1472d975228cSstefano_zampini         PetscInt  j;
14732cf14000SStefano Zampini         HYPRE_Int hnc = (HYPRE_Int)nzc;
14742cf14000SStefano Zampini 
1475aed4548fSBarry 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]);
14769566063dSJacob Faibussowitsch         for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j]));
1477792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixAddToValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr);
1478d975228cSstefano_zampini       }
1479d975228cSstefano_zampini       vals += nc;
1480d975228cSstefano_zampini     }
1481d975228cSstefano_zampini   } else { /* INSERT_VALUES */
1482d975228cSstefano_zampini     PetscInt rst, ren;
1483c69f721fSFande Kong 
14849566063dSJacob Faibussowitsch     PetscCall(MatGetOwnershipRange(A, &rst, &ren));
1485d975228cSstefano_zampini     for (i = 0; i < nr; i++) {
14866ea7df73SStefano Zampini       if (rows[i] >= 0) {
1487d975228cSstefano_zampini         PetscInt  j;
14882cf14000SStefano Zampini         HYPRE_Int hnc = (HYPRE_Int)nzc;
14892cf14000SStefano Zampini 
1490aed4548fSBarry 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]);
14919566063dSJacob Faibussowitsch         for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j]));
1492c69f721fSFande Kong         /* nonlocal values */
14939566063dSJacob Faibussowitsch         if (rows[i] < rst || rows[i] >= ren) PetscCall(MatStashValuesRow_Private(&A->stash, rows[i], nzc, cscr[0], (PetscScalar *)sscr, PETSC_FALSE));
1494c69f721fSFande Kong         /* local values */
1495792fecdfSBarry Smith         else PetscCallExternal(HYPRE_IJMatrixSetValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr);
1496d975228cSstefano_zampini       }
1497d975228cSstefano_zampini       vals += nc;
1498d975228cSstefano_zampini     }
1499d975228cSstefano_zampini   }
1500c69f721fSFande Kong 
15019566063dSJacob Faibussowitsch   PetscCall(MatRestoreArray_HYPRE(A, &array));
15023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1503d975228cSstefano_zampini }
1504d975228cSstefano_zampini 
1505d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPRESetPreallocation_HYPRE(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[])
1506d71ae5a4SJacob Faibussowitsch {
1507d975228cSstefano_zampini   Mat_HYPRE  *hA = (Mat_HYPRE *)A->data;
15087d968826Sstefano_zampini   HYPRE_Int  *hdnnz, *honnz;
150906a29025Sstefano_zampini   PetscInt    i, rs, re, cs, ce, bs;
1510d975228cSstefano_zampini   PetscMPIInt size;
1511d975228cSstefano_zampini 
1512d975228cSstefano_zampini   PetscFunctionBegin;
15139566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
15149566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
1515d975228cSstefano_zampini   rs = A->rmap->rstart;
1516d975228cSstefano_zampini   re = A->rmap->rend;
1517d975228cSstefano_zampini   cs = A->cmap->rstart;
1518d975228cSstefano_zampini   ce = A->cmap->rend;
1519d975228cSstefano_zampini   if (!hA->ij) {
1520792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rs, re - 1, cs, ce - 1, &hA->ij);
1521792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR);
1522d975228cSstefano_zampini   } else {
15232cf14000SStefano Zampini     HYPRE_BigInt hrs, hre, hcs, hce;
1524792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetLocalRange, hA->ij, &hrs, &hre, &hcs, &hce);
1525aed4548fSBarry 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);
1526aed4548fSBarry 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);
1527d975228cSstefano_zampini   }
15289566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(A, &bs));
152906a29025Sstefano_zampini   if (dnz == PETSC_DEFAULT || dnz == PETSC_DECIDE) dnz = 10 * bs;
153006a29025Sstefano_zampini   if (onz == PETSC_DEFAULT || onz == PETSC_DECIDE) onz = 10 * bs;
153106a29025Sstefano_zampini 
1532d975228cSstefano_zampini   if (!dnnz) {
15339566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->rmap->n, &hdnnz));
1534d975228cSstefano_zampini     for (i = 0; i < A->rmap->n; i++) hdnnz[i] = dnz;
1535d975228cSstefano_zampini   } else {
15367d968826Sstefano_zampini     hdnnz = (HYPRE_Int *)dnnz;
1537d975228cSstefano_zampini   }
15389566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
1539d975228cSstefano_zampini   if (size > 1) {
1540ddbeb582SStefano Zampini     hypre_AuxParCSRMatrix *aux_matrix;
1541d975228cSstefano_zampini     if (!onnz) {
15429566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(A->rmap->n, &honnz));
1543d975228cSstefano_zampini       for (i = 0; i < A->rmap->n; i++) honnz[i] = onz;
154422235d61SPierre Jolivet     } else honnz = (HYPRE_Int *)onnz;
1545ddbeb582SStefano Zampini     /* SetDiagOffdSizes sets hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0, since it seems
1546ddbeb582SStefano Zampini        they assume the user will input the entire row values, properly sorted
1547336664bdSPierre Jolivet        In PETSc, we don't make such an assumption and set this flag to 1,
1548336664bdSPierre Jolivet        unless the option MAT_SORTED_FULL is set to true.
1549ddbeb582SStefano Zampini        Also, to avoid possible memory leaks, we destroy and recreate the translator
1550ddbeb582SStefano Zampini        This has to be done here, as HYPRE_IJMatrixInitialize will properly initialize
1551ddbeb582SStefano Zampini        the IJ matrix for us */
1552ddbeb582SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
1553ddbeb582SStefano Zampini     hypre_AuxParCSRMatrixDestroy(aux_matrix);
1554ddbeb582SStefano Zampini     hypre_IJMatrixTranslator(hA->ij) = NULL;
1555792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, hA->ij, hdnnz, honnz);
1556ddbeb582SStefano Zampini     aux_matrix                               = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
1557336664bdSPierre Jolivet     hypre_AuxParCSRMatrixNeedAux(aux_matrix) = !hA->sorted_full;
1558d975228cSstefano_zampini   } else {
1559d975228cSstefano_zampini     honnz = NULL;
1560792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetRowSizes, hA->ij, hdnnz);
1561d975228cSstefano_zampini   }
1562ddbeb582SStefano Zampini 
1563af1cf968SStefano Zampini   /* reset assembled flag and call the initialize method */
1564af1cf968SStefano Zampini   hypre_IJMatrixAssembleFlag(hA->ij) = 0;
15656ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
1566792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij);
15676ea7df73SStefano Zampini #else
1568792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize_v2, hA->ij, HYPRE_MEMORY_HOST);
15696ea7df73SStefano Zampini #endif
157048a46eb9SPierre Jolivet   if (!dnnz) PetscCall(PetscFree(hdnnz));
157148a46eb9SPierre Jolivet   if (!onnz && honnz) PetscCall(PetscFree(honnz));
1572af1cf968SStefano Zampini   /* Match AIJ logic */
157306a29025Sstefano_zampini   A->preallocated = PETSC_TRUE;
1574af1cf968SStefano Zampini   A->assembled    = PETSC_FALSE;
15753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1576d975228cSstefano_zampini }
1577d975228cSstefano_zampini 
1578d975228cSstefano_zampini /*@C
1579d975228cSstefano_zampini    MatHYPRESetPreallocation - Preallocates memory for a sparse parallel matrix in HYPRE IJ format
1580d975228cSstefano_zampini 
1581c3339decSBarry Smith    Collective
1582d975228cSstefano_zampini 
1583d975228cSstefano_zampini    Input Parameters:
1584d975228cSstefano_zampini +  A - the matrix
1585d975228cSstefano_zampini .  dnz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1586d975228cSstefano_zampini           (same value is used for all local rows)
1587d975228cSstefano_zampini .  dnnz - array containing the number of nonzeros in the various rows of the
1588d975228cSstefano_zampini           DIAGONAL portion of the local submatrix (possibly different for each row)
15892ef1f0ffSBarry Smith           or `NULL` (`PETSC_NULL_INTEGER` in Fortran), if `d_nz` is used to specify the nonzero structure.
15902ef1f0ffSBarry Smith           The size of this array is equal to the number of local rows, i.e `m`.
1591d975228cSstefano_zampini           For matrices that will be factored, you must leave room for (and set)
1592d975228cSstefano_zampini           the diagonal entry even if it is zero.
1593d975228cSstefano_zampini .  onz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1594d975228cSstefano_zampini           submatrix (same value is used for all local rows).
1595d975228cSstefano_zampini -  onnz - array containing the number of nonzeros in the various rows of the
1596d975228cSstefano_zampini           OFF-DIAGONAL portion of the local submatrix (possibly different for
15972ef1f0ffSBarry Smith           each row) or `NULL` (`PETSC_NULL_INTEGER` in Fortran), if `o_nz` is used to specify the nonzero
1598d975228cSstefano_zampini           structure. The size of this array is equal to the number
15992ef1f0ffSBarry Smith           of local rows, i.e `m`.
1600d975228cSstefano_zampini 
16012fe279fdSBarry Smith    Level: intermediate
16022fe279fdSBarry Smith 
160311a5261eSBarry Smith    Note:
16042ef1f0ffSBarry Smith     If the *nnz parameter is given then the *nz parameter is ignored; for sequential matrices, `onz` and `onnz` are ignored.
1605d975228cSstefano_zampini 
16061cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatMPIAIJSetPreallocation()`, `MATHYPRE`, `MATAIJ`
1607d975228cSstefano_zampini @*/
1608d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHYPRESetPreallocation(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[])
1609d71ae5a4SJacob Faibussowitsch {
1610d975228cSstefano_zampini   PetscFunctionBegin;
1611d975228cSstefano_zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1612d975228cSstefano_zampini   PetscValidType(A, 1);
1613cac4c232SBarry Smith   PetscTryMethod(A, "MatHYPRESetPreallocation_C", (Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]), (A, dnz, dnnz, onz, onnz));
16143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1615d975228cSstefano_zampini }
1616d975228cSstefano_zampini 
161720f4b53cSBarry Smith /*@C
16182ef1f0ffSBarry Smith    MatCreateFromParCSR - Creates a `Mat` from a `hypre_ParCSRMatrix`
1619225daaf8SStefano Zampini 
1620225daaf8SStefano Zampini    Collective
1621225daaf8SStefano Zampini 
1622225daaf8SStefano Zampini    Input Parameters:
16232ef1f0ffSBarry Smith +  parcsr   - the pointer to the `hypre_ParCSRMatrix`
16242ef1f0ffSBarry Smith .  mtype    - matrix type to be created. Currently `MATAIJ`, `MATIS` and `MATHYPRE` are supported.
162520f4b53cSBarry Smith -  copymode - PETSc copying options, see  `PetscCopyMode`
1626225daaf8SStefano Zampini 
1627225daaf8SStefano Zampini    Output Parameter:
1628225daaf8SStefano Zampini .  A  - the matrix
1629225daaf8SStefano Zampini 
1630225daaf8SStefano Zampini    Level: intermediate
1631225daaf8SStefano Zampini 
16321cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatHYPRE`, `PetscCopyMode`
163320f4b53cSBarry Smith @*/
1634d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreateFromParCSR(hypre_ParCSRMatrix *parcsr, MatType mtype, PetscCopyMode copymode, Mat *A)
1635d71ae5a4SJacob Faibussowitsch {
1636225daaf8SStefano Zampini   Mat        T;
1637978814f1SStefano Zampini   Mat_HYPRE *hA;
1638978814f1SStefano Zampini   MPI_Comm   comm;
1639978814f1SStefano Zampini   PetscInt   rstart, rend, cstart, cend, M, N;
1640d248a85cSRichard Tran Mills   PetscBool  isseqaij, isseqaijmkl, ismpiaij, isaij, ishyp, isis;
1641978814f1SStefano Zampini 
1642978814f1SStefano Zampini   PetscFunctionBegin;
1643978814f1SStefano Zampini   comm = hypre_ParCSRMatrixComm(parcsr);
16449566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQAIJ, &isseqaij));
16459566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQAIJMKL, &isseqaijmkl));
16469566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPIAIJ, &ismpiaij));
16479566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATAIJ, &isaij));
16489566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATHYPRE, &ishyp));
16499566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATIS, &isis));
1650d248a85cSRichard Tran Mills   isaij = (PetscBool)(isseqaij || isseqaijmkl || ismpiaij || isaij);
16516ea7df73SStefano Zampini   /* TODO */
1652aed4548fSBarry 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);
1653978814f1SStefano Zampini   /* access ParCSRMatrix */
1654978814f1SStefano Zampini   rstart = hypre_ParCSRMatrixFirstRowIndex(parcsr);
1655978814f1SStefano Zampini   rend   = hypre_ParCSRMatrixLastRowIndex(parcsr);
1656978814f1SStefano Zampini   cstart = hypre_ParCSRMatrixFirstColDiag(parcsr);
1657978814f1SStefano Zampini   cend   = hypre_ParCSRMatrixLastColDiag(parcsr);
1658978814f1SStefano Zampini   M      = hypre_ParCSRMatrixGlobalNumRows(parcsr);
1659978814f1SStefano Zampini   N      = hypre_ParCSRMatrixGlobalNumCols(parcsr);
1660978814f1SStefano Zampini 
1661fa92c42cSstefano_zampini   /* fix for empty local rows/columns */
1662fa92c42cSstefano_zampini   if (rend < rstart) rend = rstart;
1663fa92c42cSstefano_zampini   if (cend < cstart) cend = cstart;
1664fa92c42cSstefano_zampini 
1665e6471dc9SStefano Zampini   /* PETSc convention */
1666e6471dc9SStefano Zampini   rend++;
1667e6471dc9SStefano Zampini   cend++;
1668e6471dc9SStefano Zampini   rend = PetscMin(rend, M);
1669e6471dc9SStefano Zampini   cend = PetscMin(cend, N);
1670e6471dc9SStefano Zampini 
1671978814f1SStefano Zampini   /* create PETSc matrix with MatHYPRE */
16729566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, &T));
16739566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(T, rend - rstart, cend - cstart, M, N));
16749566063dSJacob Faibussowitsch   PetscCall(MatSetType(T, MATHYPRE));
1675225daaf8SStefano Zampini   hA = (Mat_HYPRE *)(T->data);
1676978814f1SStefano Zampini 
1677978814f1SStefano Zampini   /* create HYPRE_IJMatrix */
1678792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rstart, rend - 1, cstart, cend - 1, &hA->ij);
1679792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR);
168045b8d346SStefano Zampini 
16816ea7df73SStefano Zampini   // TODO DEV
168245b8d346SStefano Zampini   /* create new ParCSR object if needed */
168345b8d346SStefano Zampini   if (ishyp && copymode == PETSC_COPY_VALUES) {
168445b8d346SStefano Zampini     hypre_ParCSRMatrix *new_parcsr;
16856ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0)
168645b8d346SStefano Zampini     hypre_CSRMatrix *hdiag, *hoffd, *ndiag, *noffd;
168745b8d346SStefano Zampini 
16880e6427aaSSatish Balay     new_parcsr = hypre_ParCSRMatrixClone(parcsr, 0);
168945b8d346SStefano Zampini     hdiag      = hypre_ParCSRMatrixDiag(parcsr);
169045b8d346SStefano Zampini     hoffd      = hypre_ParCSRMatrixOffd(parcsr);
169145b8d346SStefano Zampini     ndiag      = hypre_ParCSRMatrixDiag(new_parcsr);
169245b8d346SStefano Zampini     noffd      = hypre_ParCSRMatrixOffd(new_parcsr);
16939566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hypre_CSRMatrixData(ndiag), hypre_CSRMatrixData(hdiag), hypre_CSRMatrixNumNonzeros(hdiag)));
16949566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hypre_CSRMatrixData(noffd), hypre_CSRMatrixData(hoffd), hypre_CSRMatrixNumNonzeros(hoffd)));
16956ea7df73SStefano Zampini #else
16966ea7df73SStefano Zampini     new_parcsr = hypre_ParCSRMatrixClone(parcsr, 1);
16976ea7df73SStefano Zampini #endif
169845b8d346SStefano Zampini     parcsr   = new_parcsr;
169945b8d346SStefano Zampini     copymode = PETSC_OWN_POINTER;
170045b8d346SStefano Zampini   }
1701978814f1SStefano Zampini 
1702978814f1SStefano Zampini   /* set ParCSR object */
1703978814f1SStefano Zampini   hypre_IJMatrixObject(hA->ij) = parcsr;
17044ec6421dSstefano_zampini   T->preallocated              = PETSC_TRUE;
1705978814f1SStefano Zampini 
1706978814f1SStefano Zampini   /* set assembled flag */
1707978814f1SStefano Zampini   hypre_IJMatrixAssembleFlag(hA->ij) = 1;
17086ea7df73SStefano Zampini #if 0
1709792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize,hA->ij);
17106ea7df73SStefano Zampini #endif
1711225daaf8SStefano Zampini   if (ishyp) {
17126d2a658fSstefano_zampini     PetscMPIInt myid = 0;
17136d2a658fSstefano_zampini 
17146d2a658fSstefano_zampini     /* make sure we always have row_starts and col_starts available */
171548a46eb9SPierre Jolivet     if (HYPRE_AssumedPartitionCheck()) PetscCallMPI(MPI_Comm_rank(comm, &myid));
1716a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
17176d2a658fSstefano_zampini     if (!hypre_ParCSRMatrixOwnsColStarts(parcsr)) {
17186d2a658fSstefano_zampini       PetscLayout map;
17196d2a658fSstefano_zampini 
17209566063dSJacob Faibussowitsch       PetscCall(MatGetLayouts(T, NULL, &map));
17219566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetUp(map));
17222cf14000SStefano Zampini       hypre_ParCSRMatrixColStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid);
17236d2a658fSstefano_zampini     }
17246d2a658fSstefano_zampini     if (!hypre_ParCSRMatrixOwnsRowStarts(parcsr)) {
17256d2a658fSstefano_zampini       PetscLayout map;
17266d2a658fSstefano_zampini 
17279566063dSJacob Faibussowitsch       PetscCall(MatGetLayouts(T, &map, NULL));
17289566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetUp(map));
17292cf14000SStefano Zampini       hypre_ParCSRMatrixRowStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid);
17306d2a658fSstefano_zampini     }
1731a1d2239cSSatish Balay #endif
1732978814f1SStefano Zampini     /* prevent from freeing the pointer */
1733978814f1SStefano Zampini     if (copymode == PETSC_USE_POINTER) hA->inner_free = PETSC_FALSE;
1734225daaf8SStefano Zampini     *A = T;
17359566063dSJacob Faibussowitsch     PetscCall(MatSetOption(*A, MAT_SORTED_FULL, PETSC_TRUE));
17369566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(*A, MAT_FINAL_ASSEMBLY));
17379566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(*A, MAT_FINAL_ASSEMBLY));
1738bb4689ddSStefano Zampini   } else if (isaij) {
1739bb4689ddSStefano Zampini     if (copymode != PETSC_OWN_POINTER) {
1740225daaf8SStefano Zampini       /* prevent from freeing the pointer */
1741225daaf8SStefano Zampini       hA->inner_free = PETSC_FALSE;
17429566063dSJacob Faibussowitsch       PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INITIAL_MATRIX, A));
17439566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&T));
1744225daaf8SStefano Zampini     } else { /* AIJ return type with PETSC_OWN_POINTER */
17459566063dSJacob Faibussowitsch       PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INPLACE_MATRIX, &T));
1746225daaf8SStefano Zampini       *A = T;
1747225daaf8SStefano Zampini     }
1748bb4689ddSStefano Zampini   } else if (isis) {
17499566063dSJacob Faibussowitsch     PetscCall(MatConvert_HYPRE_IS(T, MATIS, MAT_INITIAL_MATRIX, A));
17508cfe8d00SStefano Zampini     if (copymode != PETSC_OWN_POINTER) hA->inner_free = PETSC_FALSE;
17519566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&T));
1752bb4689ddSStefano Zampini   }
17533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1754978814f1SStefano Zampini }
1755978814f1SStefano Zampini 
1756d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatHYPREGetParCSR_HYPRE(Mat A, hypre_ParCSRMatrix **parcsr)
1757d71ae5a4SJacob Faibussowitsch {
1758dd9c0a25Sstefano_zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1759dd9c0a25Sstefano_zampini   HYPRE_Int  type;
1760dd9c0a25Sstefano_zampini 
1761dd9c0a25Sstefano_zampini   PetscFunctionBegin;
176228b400f6SJacob Faibussowitsch   PetscCheck(hA->ij, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "HYPRE_IJMatrix not present");
1763792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
176408401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "HYPRE_IJMatrix is not of type HYPRE_PARCSR");
1765792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)parcsr);
17663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1767dd9c0a25Sstefano_zampini }
1768dd9c0a25Sstefano_zampini 
176920f4b53cSBarry Smith /*@C
1770dd9c0a25Sstefano_zampini    MatHYPREGetParCSR - Gets the pointer to the ParCSR matrix
1771dd9c0a25Sstefano_zampini 
17722ef1f0ffSBarry Smith    Not Collective
1773dd9c0a25Sstefano_zampini 
177420f4b53cSBarry Smith    Input Parameter:
177520f4b53cSBarry Smith .  A  - the `MATHYPRE` object
1776dd9c0a25Sstefano_zampini 
1777dd9c0a25Sstefano_zampini    Output Parameter:
17782ef1f0ffSBarry Smith .  parcsr  - the pointer to the `hypre_ParCSRMatrix`
1779dd9c0a25Sstefano_zampini 
1780dd9c0a25Sstefano_zampini    Level: intermediate
1781dd9c0a25Sstefano_zampini 
17821cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatHYPRE`, `PetscCopyMode`
178320f4b53cSBarry Smith @*/
1784d71ae5a4SJacob Faibussowitsch PetscErrorCode MatHYPREGetParCSR(Mat A, hypre_ParCSRMatrix **parcsr)
1785d71ae5a4SJacob Faibussowitsch {
1786dd9c0a25Sstefano_zampini   PetscFunctionBegin;
1787dd9c0a25Sstefano_zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1788dd9c0a25Sstefano_zampini   PetscValidType(A, 1);
1789cac4c232SBarry Smith   PetscUseMethod(A, "MatHYPREGetParCSR_C", (Mat, hypre_ParCSRMatrix **), (A, parcsr));
17903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1791dd9c0a25Sstefano_zampini }
1792dd9c0a25Sstefano_zampini 
1793d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatMissingDiagonal_HYPRE(Mat A, PetscBool *missing, PetscInt *dd)
1794d71ae5a4SJacob Faibussowitsch {
179568ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
179668ec7858SStefano Zampini   hypre_CSRMatrix    *ha;
179768ec7858SStefano Zampini   PetscInt            rst;
179868ec7858SStefano Zampini 
179968ec7858SStefano Zampini   PetscFunctionBegin;
180008401ef6SPierre Jolivet   PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented with non-square diagonal blocks");
18019566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &rst, NULL));
18029566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
180368ec7858SStefano Zampini   if (missing) *missing = PETSC_FALSE;
180468ec7858SStefano Zampini   if (dd) *dd = -1;
180568ec7858SStefano Zampini   ha = hypre_ParCSRMatrixDiag(parcsr);
180668ec7858SStefano Zampini   if (ha) {
180768299464SStefano Zampini     PetscInt   size, i;
180868299464SStefano Zampini     HYPRE_Int *ii, *jj;
180968ec7858SStefano Zampini 
181068ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
181168ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
181268ec7858SStefano Zampini     jj   = hypre_CSRMatrixJ(ha);
181368ec7858SStefano Zampini     for (i = 0; i < size; i++) {
181468ec7858SStefano Zampini       PetscInt  j;
181568ec7858SStefano Zampini       PetscBool found = PETSC_FALSE;
181668ec7858SStefano Zampini 
18179371c9d4SSatish Balay       for (j = ii[i]; j < ii[i + 1] && !found; j++) found = (jj[j] == i) ? PETSC_TRUE : PETSC_FALSE;
181868ec7858SStefano Zampini 
181968ec7858SStefano Zampini       if (!found) {
18203ba16761SJacob Faibussowitsch         PetscCall(PetscInfo(A, "Matrix is missing local diagonal entry %" PetscInt_FMT "\n", i));
182168ec7858SStefano Zampini         if (missing) *missing = PETSC_TRUE;
182268ec7858SStefano Zampini         if (dd) *dd = i + rst;
18233ba16761SJacob Faibussowitsch         PetscFunctionReturn(PETSC_SUCCESS);
182468ec7858SStefano Zampini       }
182568ec7858SStefano Zampini     }
182668ec7858SStefano Zampini     if (!size) {
18273ba16761SJacob Faibussowitsch       PetscCall(PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n"));
182868ec7858SStefano Zampini       if (missing) *missing = PETSC_TRUE;
182968ec7858SStefano Zampini       if (dd) *dd = rst;
183068ec7858SStefano Zampini     }
183168ec7858SStefano Zampini   } else {
18323ba16761SJacob Faibussowitsch     PetscCall(PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n"));
183368ec7858SStefano Zampini     if (missing) *missing = PETSC_TRUE;
183468ec7858SStefano Zampini     if (dd) *dd = rst;
183568ec7858SStefano Zampini   }
18363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
183768ec7858SStefano Zampini }
183868ec7858SStefano Zampini 
1839d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatScale_HYPRE(Mat A, PetscScalar s)
1840d71ae5a4SJacob Faibussowitsch {
184168ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
18426ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
184368ec7858SStefano Zampini   hypre_CSRMatrix *ha;
18446ea7df73SStefano Zampini #endif
184539accc25SStefano Zampini   HYPRE_Complex hs;
184668ec7858SStefano Zampini 
184768ec7858SStefano Zampini   PetscFunctionBegin;
18489566063dSJacob Faibussowitsch   PetscCall(PetscHYPREScalarCast(s, &hs));
18499566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
18506ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 19, 0)
1851792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixScale, parcsr, hs);
18526ea7df73SStefano Zampini #else /* diagonal part */
185368ec7858SStefano Zampini   ha = hypre_ParCSRMatrixDiag(parcsr);
185468ec7858SStefano Zampini   if (ha) {
185568299464SStefano Zampini     PetscInt       size, i;
185668299464SStefano Zampini     HYPRE_Int     *ii;
185739accc25SStefano Zampini     HYPRE_Complex *a;
185868ec7858SStefano Zampini 
185968ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
186068ec7858SStefano Zampini     a    = hypre_CSRMatrixData(ha);
186168ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
186239accc25SStefano Zampini     for (i = 0; i < ii[size]; i++) a[i] *= hs;
186368ec7858SStefano Zampini   }
186468ec7858SStefano Zampini   /* offdiagonal part */
186568ec7858SStefano Zampini   ha = hypre_ParCSRMatrixOffd(parcsr);
186668ec7858SStefano Zampini   if (ha) {
186768299464SStefano Zampini     PetscInt       size, i;
186868299464SStefano Zampini     HYPRE_Int     *ii;
186939accc25SStefano Zampini     HYPRE_Complex *a;
187068ec7858SStefano Zampini 
187168ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
187268ec7858SStefano Zampini     a    = hypre_CSRMatrixData(ha);
187368ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
187439accc25SStefano Zampini     for (i = 0; i < ii[size]; i++) a[i] *= hs;
187568ec7858SStefano Zampini   }
18766ea7df73SStefano Zampini #endif
18773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
187868ec7858SStefano Zampini }
187968ec7858SStefano Zampini 
1880d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRowsColumns_HYPRE(Mat A, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
1881d71ae5a4SJacob Faibussowitsch {
188268ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
188368299464SStefano Zampini   HYPRE_Int          *lrows;
188468299464SStefano Zampini   PetscInt            rst, ren, i;
188568ec7858SStefano Zampini 
188668ec7858SStefano Zampini   PetscFunctionBegin;
188708401ef6SPierre Jolivet   PetscCheck(!x && !b, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "To be implemented");
18889566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
18899566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numRows, &lrows));
18909566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &rst, &ren));
189168ec7858SStefano Zampini   for (i = 0; i < numRows; i++) {
18927a46b595SBarry Smith     PetscCheck(rows[i] >= rst && rows[i] < ren, PETSC_COMM_SELF, PETSC_ERR_SUP, "Non-local rows not yet supported");
189368ec7858SStefano Zampini     lrows[i] = rows[i] - rst;
189468ec7858SStefano Zampini   }
1895792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixEliminateRowsCols, parcsr, numRows, lrows);
18969566063dSJacob Faibussowitsch   PetscCall(PetscFree(lrows));
18973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
189868ec7858SStefano Zampini }
189968ec7858SStefano Zampini 
1900d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPRE_CSRMatrix(hypre_CSRMatrix *ha)
1901d71ae5a4SJacob Faibussowitsch {
1902c69f721fSFande Kong   PetscFunctionBegin;
1903c69f721fSFande Kong   if (ha) {
1904c69f721fSFande Kong     HYPRE_Int     *ii, size;
1905c69f721fSFande Kong     HYPRE_Complex *a;
1906c69f721fSFande Kong 
1907c69f721fSFande Kong     size = hypre_CSRMatrixNumRows(ha);
1908c69f721fSFande Kong     a    = hypre_CSRMatrixData(ha);
1909c69f721fSFande Kong     ii   = hypre_CSRMatrixI(ha);
1910c69f721fSFande Kong 
19119566063dSJacob Faibussowitsch     if (a) PetscCall(PetscArrayzero(a, ii[size]));
1912c69f721fSFande Kong   }
19133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1914c69f721fSFande Kong }
1915c69f721fSFande Kong 
1916d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroEntries_HYPRE(Mat A)
1917d71ae5a4SJacob Faibussowitsch {
19186ea7df73SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
19196ea7df73SStefano Zampini 
19206ea7df73SStefano Zampini   PetscFunctionBegin;
19216ea7df73SStefano Zampini   if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(hA->ij)) {
1922792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetConstantValues, hA->ij, 0.0);
19236ea7df73SStefano Zampini   } else {
1924c69f721fSFande Kong     hypre_ParCSRMatrix *parcsr;
1925c69f721fSFande Kong 
19269566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
19279566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr)));
19289566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr)));
19296ea7df73SStefano Zampini   }
19303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1931c69f721fSFande Kong }
1932c69f721fSFande Kong 
1933d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_HYPRE_CSRMatrix(hypre_CSRMatrix *hA, PetscInt N, const PetscInt rows[], HYPRE_Complex diag)
1934d71ae5a4SJacob Faibussowitsch {
193539accc25SStefano Zampini   PetscInt       ii;
193639accc25SStefano Zampini   HYPRE_Int     *i, *j;
193739accc25SStefano Zampini   HYPRE_Complex *a;
1938c69f721fSFande Kong 
1939c69f721fSFande Kong   PetscFunctionBegin;
19403ba16761SJacob Faibussowitsch   if (!hA) PetscFunctionReturn(PETSC_SUCCESS);
1941c69f721fSFande Kong 
194239accc25SStefano Zampini   i = hypre_CSRMatrixI(hA);
194339accc25SStefano Zampini   j = hypre_CSRMatrixJ(hA);
1944c69f721fSFande Kong   a = hypre_CSRMatrixData(hA);
1945c69f721fSFande Kong 
1946c69f721fSFande Kong   for (ii = 0; ii < N; ii++) {
194739accc25SStefano Zampini     HYPRE_Int jj, ibeg, iend, irow;
194839accc25SStefano Zampini 
1949c69f721fSFande Kong     irow = rows[ii];
1950c69f721fSFande Kong     ibeg = i[irow];
1951c69f721fSFande Kong     iend = i[irow + 1];
1952c69f721fSFande Kong     for (jj = ibeg; jj < iend; jj++)
1953c69f721fSFande Kong       if (j[jj] == irow) a[jj] = diag;
1954c69f721fSFande Kong       else a[jj] = 0.0;
1955c69f721fSFande Kong   }
19563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1957c69f721fSFande Kong }
1958c69f721fSFande Kong 
1959d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatZeroRows_HYPRE(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
1960d71ae5a4SJacob Faibussowitsch {
1961c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
1962c69f721fSFande Kong   PetscInt           *lrows, len;
196339accc25SStefano Zampini   HYPRE_Complex       hdiag;
1964c69f721fSFande Kong 
1965c69f721fSFande Kong   PetscFunctionBegin;
196608401ef6SPierre Jolivet   PetscCheck(!x && !b, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Does not support to modify the solution and the right hand size");
19679566063dSJacob Faibussowitsch   PetscCall(PetscHYPREScalarCast(diag, &hdiag));
1968c69f721fSFande Kong   /* retrieve the internal matrix */
19699566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
1970c69f721fSFande Kong   /* get locally owned rows */
19719566063dSJacob Faibussowitsch   PetscCall(MatZeroRowsMapLocal_Private(A, N, rows, &len, &lrows));
1972c69f721fSFande Kong   /* zero diagonal part */
19739566063dSJacob Faibussowitsch   PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr), len, lrows, hdiag));
1974c69f721fSFande Kong   /* zero off-diagonal part */
19759566063dSJacob Faibussowitsch   PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr), len, lrows, 0.0));
1976c69f721fSFande Kong 
19779566063dSJacob Faibussowitsch   PetscCall(PetscFree(lrows));
19783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1979c69f721fSFande Kong }
1980c69f721fSFande Kong 
1981d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAssemblyBegin_HYPRE(Mat mat, MatAssemblyType mode)
1982d71ae5a4SJacob Faibussowitsch {
1983c69f721fSFande Kong   PetscFunctionBegin;
19843ba16761SJacob Faibussowitsch   if (mat->nooffprocentries) PetscFunctionReturn(PETSC_SUCCESS);
1985c69f721fSFande Kong 
19869566063dSJacob Faibussowitsch   PetscCall(MatStashScatterBegin_Private(mat, &mat->stash, mat->rmap->range));
19873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1988c69f721fSFande Kong }
1989c69f721fSFande Kong 
1990d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
1991d71ae5a4SJacob Faibussowitsch {
1992c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
19932cf14000SStefano Zampini   HYPRE_Int           hnz;
1994c69f721fSFande Kong 
1995c69f721fSFande Kong   PetscFunctionBegin;
1996c69f721fSFande Kong   /* retrieve the internal matrix */
19979566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
1998c69f721fSFande Kong   /* call HYPRE API */
1999792fecdfSBarry Smith   PetscCallExternal(HYPRE_ParCSRMatrixGetRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v);
20002cf14000SStefano Zampini   if (nz) *nz = (PetscInt)hnz;
20013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2002c69f721fSFande Kong }
2003c69f721fSFande Kong 
2004d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatRestoreRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v)
2005d71ae5a4SJacob Faibussowitsch {
2006c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
20072cf14000SStefano Zampini   HYPRE_Int           hnz;
2008c69f721fSFande Kong 
2009c69f721fSFande Kong   PetscFunctionBegin;
2010c69f721fSFande Kong   /* retrieve the internal matrix */
20119566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
2012c69f721fSFande Kong   /* call HYPRE API */
20132cf14000SStefano Zampini   hnz = nz ? (HYPRE_Int)(*nz) : 0;
2014792fecdfSBarry Smith   PetscCallExternal(HYPRE_ParCSRMatrixRestoreRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v);
20153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2016c69f721fSFande Kong }
2017c69f721fSFande Kong 
2018d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetValues_HYPRE(Mat A, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2019d71ae5a4SJacob Faibussowitsch {
202045b8d346SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
2021c69f721fSFande Kong   PetscInt   i;
20221d4906efSStefano Zampini 
2023c69f721fSFande Kong   PetscFunctionBegin;
20243ba16761SJacob Faibussowitsch   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2025c69f721fSFande Kong   /* Ignore negative row indices
2026c69f721fSFande Kong    * And negative column indices should be automatically ignored in hypre
2027c69f721fSFande Kong    * */
20282cf14000SStefano Zampini   for (i = 0; i < m; i++) {
20292cf14000SStefano Zampini     if (idxm[i] >= 0) {
20302cf14000SStefano Zampini       HYPRE_Int hn = (HYPRE_Int)n;
2031792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetValues, hA->ij, 1, &hn, (HYPRE_BigInt *)&idxm[i], (HYPRE_BigInt *)idxn, (HYPRE_Complex *)(v + i * n));
20322cf14000SStefano Zampini     }
20332cf14000SStefano Zampini   }
20343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2035c69f721fSFande Kong }
2036c69f721fSFande Kong 
2037d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetOption_HYPRE(Mat A, MatOption op, PetscBool flg)
2038d71ae5a4SJacob Faibussowitsch {
2039ddbeb582SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
2040ddbeb582SStefano Zampini 
2041ddbeb582SStefano Zampini   PetscFunctionBegin;
2042c6698e78SStefano Zampini   switch (op) {
2043ddbeb582SStefano Zampini   case MAT_NO_OFF_PROC_ENTRIES:
204448a46eb9SPierre Jolivet     if (flg) PetscCallExternal(HYPRE_IJMatrixSetMaxOffProcElmts, hA->ij, 0);
2045ddbeb582SStefano Zampini     break;
2046d71ae5a4SJacob Faibussowitsch   case MAT_SORTED_FULL:
2047d71ae5a4SJacob Faibussowitsch     hA->sorted_full = flg;
2048d71ae5a4SJacob Faibussowitsch     break;
2049d71ae5a4SJacob Faibussowitsch   default:
2050d71ae5a4SJacob Faibussowitsch     break;
2051ddbeb582SStefano Zampini   }
20523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2053ddbeb582SStefano Zampini }
2054c69f721fSFande Kong 
2055d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatView_HYPRE(Mat A, PetscViewer view)
2056d71ae5a4SJacob Faibussowitsch {
205745b8d346SStefano Zampini   PetscViewerFormat format;
205845b8d346SStefano Zampini 
205945b8d346SStefano Zampini   PetscFunctionBegin;
20609566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(view, &format));
20613ba16761SJacob Faibussowitsch   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(PETSC_SUCCESS);
206245b8d346SStefano Zampini   if (format != PETSC_VIEWER_NATIVE) {
20636ea7df73SStefano Zampini     Mat                 B;
20646ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
20656ea7df73SStefano Zampini     PetscErrorCode (*mview)(Mat, PetscViewer) = NULL;
20666ea7df73SStefano Zampini 
20679566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
20689566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(parcsr, MATAIJ, PETSC_USE_POINTER, &B));
20699566063dSJacob Faibussowitsch     PetscCall(MatGetOperation(B, MATOP_VIEW, (void (**)(void)) & mview));
207028b400f6SJacob Faibussowitsch     PetscCheck(mview, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Missing view operation");
20719566063dSJacob Faibussowitsch     PetscCall((*mview)(B, view));
20729566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
207345b8d346SStefano Zampini   } else {
207445b8d346SStefano Zampini     Mat_HYPRE  *hA = (Mat_HYPRE *)A->data;
207545b8d346SStefano Zampini     PetscMPIInt size;
207645b8d346SStefano Zampini     PetscBool   isascii;
207745b8d346SStefano Zampini     const char *filename;
207845b8d346SStefano Zampini 
207945b8d346SStefano Zampini     /* HYPRE uses only text files */
20809566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERASCII, &isascii));
208128b400f6SJacob Faibussowitsch     PetscCheck(isascii, PetscObjectComm((PetscObject)view), PETSC_ERR_SUP, "PetscViewerType %s: native HYPRE format needs PETSCVIEWERASCII", ((PetscObject)view)->type_name);
20829566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileGetName(view, &filename));
2083792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixPrint, hA->ij, filename);
20849566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(hA->comm, &size));
208545b8d346SStefano Zampini     if (size > 1) {
20869566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(view, "Matrix files: %s.%05d ... %s.%05d\n", filename, 0, filename, size - 1));
208745b8d346SStefano Zampini     } else {
20889566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(view, "Matrix file: %s.%05d\n", filename, 0));
208945b8d346SStefano Zampini     }
209045b8d346SStefano Zampini   }
20913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
209245b8d346SStefano Zampini }
209345b8d346SStefano Zampini 
2094d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatCopy_HYPRE(Mat A, Mat B, MatStructure str)
2095d71ae5a4SJacob Faibussowitsch {
2096465edc17SStefano Zampini   hypre_ParCSRMatrix *acsr, *bcsr;
2097465edc17SStefano Zampini 
2098465edc17SStefano Zampini   PetscFunctionBegin;
2099465edc17SStefano Zampini   if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) {
21009566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &acsr));
21019566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(B, &bcsr));
2102792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixCopy, acsr, bcsr, 1);
21039566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_SORTED_FULL, PETSC_TRUE)); /* "perfect" preallocation, so no need for hypre_AuxParCSRMatrixNeedAux */
21049566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
21059566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
2106465edc17SStefano Zampini   } else {
21079566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
2108465edc17SStefano Zampini   }
21093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2110465edc17SStefano Zampini }
2111465edc17SStefano Zampini 
2112d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatGetDiagonal_HYPRE(Mat A, Vec d)
2113d71ae5a4SJacob Faibussowitsch {
21146305df00SStefano Zampini   hypre_ParCSRMatrix *parcsr;
21156305df00SStefano Zampini   hypre_CSRMatrix    *dmat;
211639accc25SStefano Zampini   HYPRE_Complex      *a;
211739accc25SStefano Zampini   HYPRE_Complex      *data = NULL;
21182cf14000SStefano Zampini   HYPRE_Int          *diag = NULL;
21192cf14000SStefano Zampini   PetscInt            i;
21206305df00SStefano Zampini   PetscBool           cong;
21216305df00SStefano Zampini 
21226305df00SStefano Zampini   PetscFunctionBegin;
21239566063dSJacob Faibussowitsch   PetscCall(MatHasCongruentLayouts(A, &cong));
212428b400f6SJacob Faibussowitsch   PetscCheck(cong, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only for square matrices with same local distributions of rows and columns");
212576bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
21266305df00SStefano Zampini     PetscBool miss;
21279566063dSJacob Faibussowitsch     PetscCall(MatMissingDiagonal(A, &miss, NULL));
212808401ef6SPierre Jolivet     PetscCheck(!miss || !A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented when diagonal entries are missing");
21296305df00SStefano Zampini   }
21309566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
21316305df00SStefano Zampini   dmat = hypre_ParCSRMatrixDiag(parcsr);
21326305df00SStefano Zampini   if (dmat) {
213339accc25SStefano Zampini     /* this cast fixes the clang error: implicit conversion from 'HYPRE_Complex' (aka '_Complex double') to 'double' is not permitted in C++ */
21349566063dSJacob Faibussowitsch     PetscCall(VecGetArray(d, (PetscScalar **)&a));
21352cf14000SStefano Zampini     diag = hypre_CSRMatrixI(dmat);
213639accc25SStefano Zampini     data = hypre_CSRMatrixData(dmat);
21376305df00SStefano Zampini     for (i = 0; i < A->rmap->n; i++) a[i] = data[diag[i]];
21389566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(d, (PetscScalar **)&a));
21396305df00SStefano Zampini   }
21403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21416305df00SStefano Zampini }
21426305df00SStefano Zampini 
2143363d496dSStefano Zampini #include <petscblaslapack.h>
2144363d496dSStefano Zampini 
2145d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatAXPY_HYPRE(Mat Y, PetscScalar a, Mat X, MatStructure str)
2146d71ae5a4SJacob Faibussowitsch {
2147363d496dSStefano Zampini   PetscFunctionBegin;
21486ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
21496ea7df73SStefano Zampini   {
21506ea7df73SStefano Zampini     Mat                 B;
21516ea7df73SStefano Zampini     hypre_ParCSRMatrix *x, *y, *z;
21526ea7df73SStefano Zampini 
21539566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(Y, &y));
21549566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(X, &x));
2155792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixAdd, 1.0, y, 1.0, x, &z);
21569566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(z, MATHYPRE, PETSC_OWN_POINTER, &B));
21579566063dSJacob Faibussowitsch     PetscCall(MatHeaderMerge(Y, &B));
21586ea7df73SStefano Zampini   }
21596ea7df73SStefano Zampini #else
2160363d496dSStefano Zampini   if (str == SAME_NONZERO_PATTERN) {
2161363d496dSStefano Zampini     hypre_ParCSRMatrix *x, *y;
2162363d496dSStefano Zampini     hypre_CSRMatrix    *xloc, *yloc;
2163363d496dSStefano Zampini     PetscInt            xnnz, ynnz;
216439accc25SStefano Zampini     HYPRE_Complex      *xarr, *yarr;
2165363d496dSStefano Zampini     PetscBLASInt        one = 1, bnz;
2166363d496dSStefano Zampini 
21679566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(Y, &y));
21689566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(X, &x));
2169363d496dSStefano Zampini 
2170363d496dSStefano Zampini     /* diagonal block */
2171363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixDiag(x);
2172363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixDiag(y);
2173363d496dSStefano Zampini     xnnz = 0;
2174363d496dSStefano Zampini     ynnz = 0;
2175363d496dSStefano Zampini     xarr = NULL;
2176363d496dSStefano Zampini     yarr = NULL;
2177363d496dSStefano Zampini     if (xloc) {
217839accc25SStefano Zampini       xarr = hypre_CSRMatrixData(xloc);
2179363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
2180363d496dSStefano Zampini     }
2181363d496dSStefano Zampini     if (yloc) {
218239accc25SStefano Zampini       yarr = hypre_CSRMatrixData(yloc);
2183363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
2184363d496dSStefano Zampini     }
218508401ef6SPierre Jolivet     PetscCheck(xnnz == ynnz, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Different number of nonzeros in diagonal block %" PetscInt_FMT " != %" PetscInt_FMT, xnnz, ynnz);
21869566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(xnnz, &bnz));
2187792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one));
2188363d496dSStefano Zampini 
2189363d496dSStefano Zampini     /* off-diagonal block */
2190363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixOffd(x);
2191363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixOffd(y);
2192363d496dSStefano Zampini     xnnz = 0;
2193363d496dSStefano Zampini     ynnz = 0;
2194363d496dSStefano Zampini     xarr = NULL;
2195363d496dSStefano Zampini     yarr = NULL;
2196363d496dSStefano Zampini     if (xloc) {
219739accc25SStefano Zampini       xarr = hypre_CSRMatrixData(xloc);
2198363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
2199363d496dSStefano Zampini     }
2200363d496dSStefano Zampini     if (yloc) {
220139accc25SStefano Zampini       yarr = hypre_CSRMatrixData(yloc);
2202363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
2203363d496dSStefano Zampini     }
220408401ef6SPierre 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);
22059566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(xnnz, &bnz));
2206792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one));
2207363d496dSStefano Zampini   } else if (str == SUBSET_NONZERO_PATTERN) {
22089566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic(Y, a, X, str));
2209363d496dSStefano Zampini   } else {
2210363d496dSStefano Zampini     Mat B;
2211363d496dSStefano Zampini 
22129566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic_Preallocate(Y, X, &B));
22139566063dSJacob Faibussowitsch     PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str));
22149566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(Y, &B));
2215363d496dSStefano Zampini   }
22166ea7df73SStefano Zampini #endif
22173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2218363d496dSStefano Zampini }
2219363d496dSStefano Zampini 
22202c4ab24aSJunchao Zhang /* Attach cooMat to hypre matrix mat. The two matrices will share the same data array */
22212c4ab24aSJunchao Zhang static PetscErrorCode MatAttachCOOMat_HYPRE(Mat mat, Mat cooMat)
22222c4ab24aSJunchao Zhang {
22232c4ab24aSJunchao Zhang   Mat_HYPRE           *hmat = (Mat_HYPRE *)mat->data;
22242c4ab24aSJunchao Zhang   hypre_CSRMatrix     *diag, *offd;
22252c4ab24aSJunchao Zhang   hypre_ParCSRMatrix  *parCSR;
22262c4ab24aSJunchao Zhang   HYPRE_MemoryLocation hypreMemtype = HYPRE_MEMORY_HOST;
22272c4ab24aSJunchao Zhang   PetscMemType         petscMemtype;
22282c4ab24aSJunchao Zhang   Mat                  A, B;
22292c4ab24aSJunchao Zhang   PetscScalar         *Aa, *Ba;
22302c4ab24aSJunchao Zhang   PetscMPIInt          size;
22312c4ab24aSJunchao Zhang   MPI_Comm             comm;
22322c4ab24aSJunchao Zhang   PetscLayout          rmap;
22332c4ab24aSJunchao Zhang 
22342c4ab24aSJunchao Zhang   PetscFunctionBegin;
22352c4ab24aSJunchao Zhang   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
22362c4ab24aSJunchao Zhang   PetscCallMPI(MPI_Comm_size(comm, &size));
22372c4ab24aSJunchao Zhang   PetscCall(MatGetLayouts(mat, &rmap, NULL));
22382c4ab24aSJunchao Zhang 
22392c4ab24aSJunchao Zhang   /* Alias cooMat's data array to IJMatrix's */
22402c4ab24aSJunchao Zhang   PetscCallExternal(HYPRE_IJMatrixGetObject, hmat->ij, (void **)&parCSR);
22412c4ab24aSJunchao Zhang   diag = hypre_ParCSRMatrixDiag(parCSR);
22422c4ab24aSJunchao Zhang   offd = hypre_ParCSRMatrixOffd(parCSR);
22432c4ab24aSJunchao Zhang 
22442c4ab24aSJunchao Zhang   hypreMemtype = hypre_CSRMatrixMemoryLocation(diag);
22452c4ab24aSJunchao Zhang   A            = (size == 1) ? cooMat : ((Mat_MPIAIJ *)cooMat->data)->A;
22462c4ab24aSJunchao Zhang   PetscCall(MatSeqAIJGetCSRAndMemType(A, NULL, NULL, &Aa, &petscMemtype));
22472c4ab24aSJunchao 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");
22482c4ab24aSJunchao Zhang 
22492c4ab24aSJunchao Zhang   hmat->diagJ = hypre_CSRMatrixJ(diag);
22502c4ab24aSJunchao Zhang   PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(diag), hypreMemtype));
22512c4ab24aSJunchao Zhang   hypre_CSRMatrixData(diag)     = (HYPRE_Complex *)Aa;
22522c4ab24aSJunchao Zhang   hypre_CSRMatrixOwnsData(diag) = 0; /* Take ownership of (j,a) away from hypre. As a result, we need to free them on our own */
22532c4ab24aSJunchao Zhang 
22542c4ab24aSJunchao Zhang   /* Copy diagonal pointers of A to device to facilitate MatSeqAIJMoveDiagonalValuesFront_SeqAIJKokkos */
22552c4ab24aSJunchao Zhang   if (hypreMemtype == HYPRE_MEMORY_DEVICE) {
22562c4ab24aSJunchao Zhang     PetscStackCallExternalVoid("hypre_TAlloc", hmat->diag = hypre_TAlloc(PetscInt, rmap->n, hypreMemtype));
22572c4ab24aSJunchao Zhang     PetscCall(MatMarkDiagonal_SeqAIJ(A)); /* We need updated diagonal positions */
22582c4ab24aSJunchao Zhang     PetscStackCallExternalVoid("hypre_TMemcpy", hypre_TMemcpy(hmat->diag, ((Mat_SeqAIJ *)A->data)->diag, PetscInt, rmap->n, hypreMemtype, HYPRE_MEMORY_HOST));
22592c4ab24aSJunchao Zhang   }
22602c4ab24aSJunchao Zhang 
22612c4ab24aSJunchao Zhang   if (size > 1) {
22622c4ab24aSJunchao Zhang     B = ((Mat_MPIAIJ *)cooMat->data)->B;
22632c4ab24aSJunchao Zhang     PetscCall(MatSeqAIJGetCSRAndMemType(B, NULL, NULL, &Ba, &petscMemtype));
22642c4ab24aSJunchao Zhang     hmat->offdJ = hypre_CSRMatrixJ(offd);
22652c4ab24aSJunchao Zhang     PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(offd), hypreMemtype));
22662c4ab24aSJunchao Zhang     hypre_CSRMatrixData(offd)     = (HYPRE_Complex *)Ba;
22672c4ab24aSJunchao Zhang     hypre_CSRMatrixOwnsData(offd) = 0;
22682c4ab24aSJunchao Zhang   }
22692c4ab24aSJunchao Zhang 
22702c4ab24aSJunchao Zhang   /* Record cooMat for use in MatSetValuesCOO_HYPRE */
22712c4ab24aSJunchao Zhang   hmat->cooMat  = cooMat;
22722c4ab24aSJunchao Zhang   hmat->memType = hypreMemtype;
22732c4ab24aSJunchao Zhang   PetscFunctionReturn(PETSC_SUCCESS);
22742c4ab24aSJunchao Zhang }
22752c4ab24aSJunchao Zhang 
22762c4ab24aSJunchao Zhang static PetscErrorCode MatDuplicate_HYPRE(Mat A, MatDuplicateOption op, Mat *B)
22772c4ab24aSJunchao Zhang {
22782c4ab24aSJunchao Zhang   hypre_ParCSRMatrix *parcsr = NULL;
22792c4ab24aSJunchao Zhang   PetscCopyMode       cpmode;
22802c4ab24aSJunchao Zhang   Mat_HYPRE          *hA;
22812c4ab24aSJunchao Zhang   Mat                 cooMat;
22822c4ab24aSJunchao Zhang 
22832c4ab24aSJunchao Zhang   PetscFunctionBegin;
22842c4ab24aSJunchao Zhang   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
22852c4ab24aSJunchao Zhang   if (op == MAT_DO_NOT_COPY_VALUES || op == MAT_SHARE_NONZERO_PATTERN) {
22862c4ab24aSJunchao Zhang     parcsr = hypre_ParCSRMatrixClone(parcsr, 0);
22872c4ab24aSJunchao Zhang     cpmode = PETSC_OWN_POINTER;
22882c4ab24aSJunchao Zhang   } else {
22892c4ab24aSJunchao Zhang     cpmode = PETSC_COPY_VALUES;
22902c4ab24aSJunchao Zhang   }
22912c4ab24aSJunchao Zhang   PetscCall(MatCreateFromParCSR(parcsr, MATHYPRE, cpmode, B));
22922c4ab24aSJunchao Zhang   hA = (Mat_HYPRE *)A->data;
22932c4ab24aSJunchao Zhang   if (hA->cooMat) {
2294*b73e3080SStefano Zampini     op = (op == MAT_DO_NOT_COPY_VALUES) ? op : MAT_COPY_VALUES;
2295*b73e3080SStefano Zampini     /* Cannot simply increase the reference count of hA->cooMat, since B needs to share cooMat's data array */
2296*b73e3080SStefano Zampini     PetscCall(MatDuplicate(hA->cooMat, op, &cooMat));
22972c4ab24aSJunchao Zhang     PetscCall(MatAttachCOOMat_HYPRE(*B, cooMat));
22982c4ab24aSJunchao Zhang   }
22992c4ab24aSJunchao Zhang   PetscFunctionReturn(PETSC_SUCCESS);
23002c4ab24aSJunchao Zhang }
23012c4ab24aSJunchao Zhang 
2302d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetPreallocationCOO_HYPRE(Mat mat, PetscCount coo_n, PetscInt coo_i[], PetscInt coo_j[])
2303d71ae5a4SJacob Faibussowitsch {
23045fbaff96SJunchao Zhang   MPI_Comm    comm;
23055fbaff96SJunchao Zhang   PetscMPIInt size;
23065fbaff96SJunchao Zhang   PetscLayout rmap, cmap;
23075fbaff96SJunchao Zhang   Mat_HYPRE  *hmat;
23082c4ab24aSJunchao Zhang   Mat         cooMat;
23095fbaff96SJunchao Zhang   MatType     matType = MATAIJ; /* default type of cooMat */
23105fbaff96SJunchao Zhang 
23115fbaff96SJunchao Zhang   PetscFunctionBegin;
23125fbaff96SJunchao Zhang   /* Build an agent matrix cooMat whose type is either MATAIJ or MATAIJKOKKOS.
23135fbaff96SJunchao 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.
23145fbaff96SJunchao Zhang    */
23155fbaff96SJunchao Zhang   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
23165fbaff96SJunchao Zhang   PetscCallMPI(MPI_Comm_size(comm, &size));
23175fbaff96SJunchao Zhang   PetscCall(PetscLayoutSetUp(mat->rmap));
23185fbaff96SJunchao Zhang   PetscCall(PetscLayoutSetUp(mat->cmap));
23195fbaff96SJunchao Zhang   PetscCall(MatGetLayouts(mat, &rmap, &cmap));
23205fbaff96SJunchao Zhang 
23215fbaff96SJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
23225fbaff96SJunchao Zhang   if (!mat->boundtocpu) { /* mat will be on device, so will cooMat */
23235fbaff96SJunchao Zhang   #if defined(PETSC_HAVE_KOKKOS)
23245fbaff96SJunchao Zhang     matType = MATAIJKOKKOS;
23255fbaff96SJunchao Zhang   #else
23265fbaff96SJunchao Zhang     SETERRQ(comm, PETSC_ERR_SUP, "To support MATHYPRE COO assembly on device, we need Kokkos, e.g., --download-kokkos --download-kokkos-kernels");
23275fbaff96SJunchao Zhang   #endif
23285fbaff96SJunchao Zhang   }
23295fbaff96SJunchao Zhang #endif
23305fbaff96SJunchao Zhang 
23315fbaff96SJunchao Zhang   /* Do COO preallocation through cooMat */
23325fbaff96SJunchao Zhang   hmat = (Mat_HYPRE *)mat->data;
23335fbaff96SJunchao Zhang   PetscCall(MatDestroy(&hmat->cooMat));
23345fbaff96SJunchao Zhang   PetscCall(MatCreate(comm, &cooMat));
23355fbaff96SJunchao Zhang   PetscCall(MatSetType(cooMat, matType));
23365fbaff96SJunchao Zhang   PetscCall(MatSetLayouts(cooMat, rmap, cmap));
23375fbaff96SJunchao Zhang   PetscCall(MatSetPreallocationCOO(cooMat, coo_n, coo_i, coo_j));
2338*b73e3080SStefano Zampini   cooMat->assembled = PETSC_TRUE;
23395fbaff96SJunchao Zhang 
23405fbaff96SJunchao Zhang   /* Copy the sparsity pattern from cooMat to hypre IJMatrix hmat->ij */
23415fbaff96SJunchao Zhang   PetscCall(MatSetOption(mat, MAT_SORTED_FULL, PETSC_TRUE));
23425fbaff96SJunchao Zhang   PetscCall(MatSetOption(mat, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE));
23435fbaff96SJunchao Zhang   PetscCall(MatHYPRE_CreateFromMat(cooMat, hmat));      /* Create hmat->ij and preallocate it */
2344*b73e3080SStefano Zampini   PetscCall(MatHYPRE_IJMatrixCopyIJ(cooMat, hmat->ij)); /* Copy A's (i,j) to hmat->ij */
23455fbaff96SJunchao Zhang 
23465fbaff96SJunchao Zhang   mat->preallocated = PETSC_TRUE;
23475fbaff96SJunchao Zhang   PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
23485fbaff96SJunchao Zhang   PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); /* Migrate mat to device if it is bound to. Hypre builds its own SpMV context here */
23495fbaff96SJunchao Zhang 
23502c4ab24aSJunchao Zhang   /* Attach cooMat to mat */
23512c4ab24aSJunchao Zhang   PetscCall(MatAttachCOOMat_HYPRE(mat, cooMat));
23523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23535fbaff96SJunchao Zhang }
23545fbaff96SJunchao Zhang 
2355d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetValuesCOO_HYPRE(Mat mat, const PetscScalar v[], InsertMode imode)
2356d71ae5a4SJacob Faibussowitsch {
23575fbaff96SJunchao Zhang   Mat_HYPRE *hmat = (Mat_HYPRE *)mat->data;
2358*b73e3080SStefano Zampini   PetscBool  ismpiaij;
23595fbaff96SJunchao Zhang   Mat        A;
23605fbaff96SJunchao Zhang 
23615fbaff96SJunchao Zhang   PetscFunctionBegin;
2362*b73e3080SStefano Zampini   PetscCheck(hmat->cooMat, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet");
23635fbaff96SJunchao Zhang   PetscCall(MatSetValuesCOO(hmat->cooMat, v, imode));
23645fbaff96SJunchao Zhang 
2365*b73e3080SStefano Zampini   PetscCall(PetscObjectBaseTypeCompare((PetscObject)hmat->cooMat, MATMPIAIJ, &ismpiaij));
2366*b73e3080SStefano Zampini 
23675fbaff96SJunchao Zhang   /* Move diagonal elements of the diagonal block to the front of their row, as needed by ParCSRMatrix. So damn hacky */
2368*b73e3080SStefano Zampini   A = ismpiaij ? ((Mat_MPIAIJ *)hmat->cooMat->data)->A : hmat->cooMat;
23695fbaff96SJunchao Zhang   if (hmat->memType == HYPRE_MEMORY_HOST) {
23705fbaff96SJunchao Zhang     Mat_SeqAIJ  *aij = (Mat_SeqAIJ *)A->data;
23715fbaff96SJunchao Zhang     PetscInt     i, m, *Ai = aij->i, *Adiag = aij->diag;
23725fbaff96SJunchao Zhang     PetscScalar *Aa = aij->a, tmp;
23735fbaff96SJunchao Zhang 
23745fbaff96SJunchao Zhang     PetscCall(MatGetSize(A, &m, NULL));
23755fbaff96SJunchao Zhang     for (i = 0; i < m; i++) {
2376*b73e3080SStefano Zampini       if (Adiag[i] >= Ai[i] && Adiag[i] < Ai[i + 1]) { /* Diagonal element of this row exists in a[] and j[] */
23775fbaff96SJunchao Zhang         tmp          = Aa[Ai[i]];
23785fbaff96SJunchao Zhang         Aa[Ai[i]]    = Aa[Adiag[i]];
23795fbaff96SJunchao Zhang         Aa[Adiag[i]] = tmp;
23805fbaff96SJunchao Zhang       }
23815fbaff96SJunchao Zhang     }
23825fbaff96SJunchao Zhang   } else {
23835fbaff96SJunchao Zhang #if defined(PETSC_HAVE_KOKKOS_KERNELS)
23845fbaff96SJunchao Zhang     PetscCall(MatSeqAIJMoveDiagonalValuesFront_SeqAIJKokkos(A, hmat->diag));
23855fbaff96SJunchao Zhang #endif
23865fbaff96SJunchao Zhang   }
23873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23885fbaff96SJunchao Zhang }
23895fbaff96SJunchao Zhang 
2390a055b5aaSBarry Smith /*MC
23912ef1f0ffSBarry Smith    MATHYPRE - "hypre" - A matrix type to be used for sequential and parallel sparse matrices
2392a055b5aaSBarry Smith           based on the hypre IJ interface.
2393a055b5aaSBarry Smith 
2394a055b5aaSBarry Smith    Level: intermediate
2395a055b5aaSBarry Smith 
23961cc06b55SBarry Smith .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatHYPRESetPreallocation`
2397a055b5aaSBarry Smith M*/
2398a055b5aaSBarry Smith 
2399d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_HYPRE(Mat B)
2400d71ae5a4SJacob Faibussowitsch {
240163c07aadSStefano Zampini   Mat_HYPRE *hB;
240263c07aadSStefano Zampini 
240363c07aadSStefano Zampini   PetscFunctionBegin;
24044dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&hB));
24056ea7df73SStefano Zampini 
2406978814f1SStefano Zampini   hB->inner_free  = PETSC_TRUE;
2407c69f721fSFande Kong   hB->available   = PETSC_TRUE;
2408336664bdSPierre Jolivet   hB->sorted_full = PETSC_FALSE; /* no assumption whether column indices are sorted or not */
2409c69f721fSFande Kong   hB->size        = 0;
2410c69f721fSFande Kong   hB->array       = NULL;
2411978814f1SStefano Zampini 
241263c07aadSStefano Zampini   B->data      = (void *)hB;
241363c07aadSStefano Zampini   B->assembled = PETSC_FALSE;
241463c07aadSStefano Zampini 
24159566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(B->ops, sizeof(struct _MatOps)));
241663c07aadSStefano Zampini   B->ops->mult                  = MatMult_HYPRE;
241763c07aadSStefano Zampini   B->ops->multtranspose         = MatMultTranspose_HYPRE;
2418414bd5c3SStefano Zampini   B->ops->multadd               = MatMultAdd_HYPRE;
2419414bd5c3SStefano Zampini   B->ops->multtransposeadd      = MatMultTransposeAdd_HYPRE;
242063c07aadSStefano Zampini   B->ops->setup                 = MatSetUp_HYPRE;
242163c07aadSStefano Zampini   B->ops->destroy               = MatDestroy_HYPRE;
242263c07aadSStefano Zampini   B->ops->assemblyend           = MatAssemblyEnd_HYPRE;
2423c69f721fSFande Kong   B->ops->assemblybegin         = MatAssemblyBegin_HYPRE;
2424d975228cSstefano_zampini   B->ops->setvalues             = MatSetValues_HYPRE;
242568ec7858SStefano Zampini   B->ops->missingdiagonal       = MatMissingDiagonal_HYPRE;
242668ec7858SStefano Zampini   B->ops->scale                 = MatScale_HYPRE;
242768ec7858SStefano Zampini   B->ops->zerorowscolumns       = MatZeroRowsColumns_HYPRE;
2428c69f721fSFande Kong   B->ops->zeroentries           = MatZeroEntries_HYPRE;
2429c69f721fSFande Kong   B->ops->zerorows              = MatZeroRows_HYPRE;
2430c69f721fSFande Kong   B->ops->getrow                = MatGetRow_HYPRE;
2431c69f721fSFande Kong   B->ops->restorerow            = MatRestoreRow_HYPRE;
2432c69f721fSFande Kong   B->ops->getvalues             = MatGetValues_HYPRE;
2433ddbeb582SStefano Zampini   B->ops->setoption             = MatSetOption_HYPRE;
243445b8d346SStefano Zampini   B->ops->duplicate             = MatDuplicate_HYPRE;
2435465edc17SStefano Zampini   B->ops->copy                  = MatCopy_HYPRE;
243645b8d346SStefano Zampini   B->ops->view                  = MatView_HYPRE;
24376305df00SStefano Zampini   B->ops->getdiagonal           = MatGetDiagonal_HYPRE;
2438363d496dSStefano Zampini   B->ops->axpy                  = MatAXPY_HYPRE;
24394222ddf1SHong Zhang   B->ops->productsetfromoptions = MatProductSetFromOptions_HYPRE;
24406ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
24416ea7df73SStefano Zampini   B->ops->bindtocpu = MatBindToCPU_HYPRE;
24426ea7df73SStefano Zampini   B->boundtocpu     = PETSC_FALSE;
24436ea7df73SStefano Zampini #endif
244445b8d346SStefano Zampini 
244545b8d346SStefano Zampini   /* build cache for off array entries formed */
24469566063dSJacob Faibussowitsch   PetscCall(MatStashCreate_Private(PetscObjectComm((PetscObject)B), 1, &B->stash));
244763c07aadSStefano Zampini 
24489566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)B), &hB->comm));
24499566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRE));
24509566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_aij_C", MatConvert_HYPRE_AIJ));
24519566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_is_C", MatConvert_HYPRE_IS));
24529566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_hypre_C", MatProductSetFromOptions_HYPRE));
24539566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaij_hypre_C", MatProductSetFromOptions_HYPRE));
24549566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPRESetPreallocation_C", MatHYPRESetPreallocation_HYPRE));
24559566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPREGetParCSR_C", MatHYPREGetParCSR_HYPRE));
24565fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_HYPRE));
24575fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetValuesCOO_C", MatSetValuesCOO_HYPRE));
24586ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
24596ea7df73SStefano Zampini   #if defined(HYPRE_USING_HIP)
24609566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP));
24619566063dSJacob Faibussowitsch   PetscCall(MatSetVecType(B, VECHIP));
24626ea7df73SStefano Zampini   #endif
24636ea7df73SStefano Zampini   #if defined(HYPRE_USING_CUDA)
24649566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
24659566063dSJacob Faibussowitsch   PetscCall(MatSetVecType(B, VECCUDA));
24666ea7df73SStefano Zampini   #endif
24676ea7df73SStefano Zampini #endif
2468ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
24693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
247063c07aadSStefano Zampini }
247163c07aadSStefano Zampini 
2472d71ae5a4SJacob Faibussowitsch static PetscErrorCode hypre_array_destroy(void *ptr)
2473d71ae5a4SJacob Faibussowitsch {
2474225daaf8SStefano Zampini   PetscFunctionBegin;
2475*b73e3080SStefano Zampini   if (ptr) hypre_TFree(ptr, HYPRE_MEMORY_HOST);
24763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2477225daaf8SStefano Zampini }
2478