xref: /petsc/src/mat/impls/hypre/mhypre.c (revision 4dfa11a44d5adf2389f1d3acbc8f3c1116dc6c3a)
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);
2563c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixFastCopy_MPIAIJ(Mat, HYPRE_IJMatrix);
2663c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixFastCopy_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 
319371c9d4SSatish Balay static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat A_d, Mat A_o, HYPRE_IJMatrix ij) {
3263c07aadSStefano Zampini   PetscInt        i, n_d, n_o;
3363c07aadSStefano Zampini   const PetscInt *ia_d, *ia_o;
3463c07aadSStefano Zampini   PetscBool       done_d = PETSC_FALSE, done_o = PETSC_FALSE;
352cf14000SStefano Zampini   HYPRE_Int      *nnz_d = NULL, *nnz_o = NULL;
3663c07aadSStefano Zampini 
3763c07aadSStefano Zampini   PetscFunctionBegin;
3863c07aadSStefano Zampini   if (A_d) { /* determine number of nonzero entries in local diagonal part */
399566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(A_d, 0, PETSC_FALSE, PETSC_FALSE, &n_d, &ia_d, NULL, &done_d));
4063c07aadSStefano Zampini     if (done_d) {
419566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(n_d, &nnz_d));
42ad540459SPierre Jolivet       for (i = 0; i < n_d; i++) nnz_d[i] = ia_d[i + 1] - ia_d[i];
4363c07aadSStefano Zampini     }
449566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowIJ(A_d, 0, PETSC_FALSE, PETSC_FALSE, NULL, &ia_d, NULL, &done_d));
4563c07aadSStefano Zampini   }
4663c07aadSStefano Zampini   if (A_o) { /* determine number of nonzero entries in local off-diagonal part */
479566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(A_o, 0, PETSC_FALSE, PETSC_FALSE, &n_o, &ia_o, NULL, &done_o));
4863c07aadSStefano Zampini     if (done_o) {
499566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(n_o, &nnz_o));
50ad540459SPierre Jolivet       for (i = 0; i < n_o; i++) nnz_o[i] = ia_o[i + 1] - ia_o[i];
5163c07aadSStefano Zampini     }
529566063dSJacob Faibussowitsch     PetscCall(MatRestoreRowIJ(A_o, 0, PETSC_FALSE, PETSC_FALSE, &n_o, &ia_o, NULL, &done_o));
5363c07aadSStefano Zampini   }
5463c07aadSStefano Zampini   if (done_d) {    /* set number of nonzeros in HYPRE IJ matrix */
5563c07aadSStefano Zampini     if (!done_o) { /* only diagonal part */
569566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(n_d, &nnz_o));
5763c07aadSStefano Zampini     }
58c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0)
59c6698e78SStefano Zampini     { /* If we don't do this, the columns of the matrix will be all zeros! */
60c6698e78SStefano Zampini       hypre_AuxParCSRMatrix *aux_matrix;
61c6698e78SStefano Zampini       aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij);
62c6698e78SStefano Zampini       hypre_AuxParCSRMatrixDestroy(aux_matrix);
63c6698e78SStefano Zampini       hypre_IJMatrixTranslator(ij) = NULL;
64792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, ij, nnz_d, nnz_o);
6522235d61SPierre Jolivet       /* it seems they partially fixed it in 2.19.0 */
6622235d61SPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
67c6698e78SStefano Zampini       aux_matrix                               = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij);
68c6698e78SStefano Zampini       hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1;
6922235d61SPierre Jolivet #endif
70c6698e78SStefano Zampini     }
71c6698e78SStefano Zampini #else
72792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, ij, nnz_d, nnz_o);
73c6698e78SStefano Zampini #endif
749566063dSJacob Faibussowitsch     PetscCall(PetscFree(nnz_d));
759566063dSJacob Faibussowitsch     PetscCall(PetscFree(nnz_o));
7663c07aadSStefano Zampini   }
7763c07aadSStefano Zampini   PetscFunctionReturn(0);
7863c07aadSStefano Zampini }
7963c07aadSStefano Zampini 
809371c9d4SSatish Balay static PetscErrorCode MatHYPRE_CreateFromMat(Mat A, Mat_HYPRE *hA) {
8163c07aadSStefano Zampini   PetscInt rstart, rend, cstart, cend;
8263c07aadSStefano Zampini 
8363c07aadSStefano Zampini   PetscFunctionBegin;
849566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
859566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
8663c07aadSStefano Zampini   rstart = A->rmap->rstart;
8763c07aadSStefano Zampini   rend   = A->rmap->rend;
8863c07aadSStefano Zampini   cstart = A->cmap->rstart;
8963c07aadSStefano Zampini   cend   = A->cmap->rend;
90792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rstart, rend - 1, cstart, cend - 1, &hA->ij);
91792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR);
9263c07aadSStefano Zampini   {
9363c07aadSStefano Zampini     PetscBool       same;
9463c07aadSStefano Zampini     Mat             A_d, A_o;
9563c07aadSStefano Zampini     const PetscInt *colmap;
969566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &same));
9763c07aadSStefano Zampini     if (same) {
989566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJGetSeqAIJ(A, &A_d, &A_o, &colmap));
999566063dSJacob Faibussowitsch       PetscCall(MatHYPRE_IJMatrixPreallocate(A_d, A_o, hA->ij));
10063c07aadSStefano Zampini       PetscFunctionReturn(0);
10163c07aadSStefano Zampini     }
1029566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIBAIJ, &same));
10363c07aadSStefano Zampini     if (same) {
1049566063dSJacob Faibussowitsch       PetscCall(MatMPIBAIJGetSeqBAIJ(A, &A_d, &A_o, &colmap));
1059566063dSJacob Faibussowitsch       PetscCall(MatHYPRE_IJMatrixPreallocate(A_d, A_o, hA->ij));
10663c07aadSStefano Zampini       PetscFunctionReturn(0);
10763c07aadSStefano Zampini     }
1089566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &same));
10963c07aadSStefano Zampini     if (same) {
1109566063dSJacob Faibussowitsch       PetscCall(MatHYPRE_IJMatrixPreallocate(A, NULL, hA->ij));
11163c07aadSStefano Zampini       PetscFunctionReturn(0);
11263c07aadSStefano Zampini     }
1139566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQBAIJ, &same));
11463c07aadSStefano Zampini     if (same) {
1159566063dSJacob Faibussowitsch       PetscCall(MatHYPRE_IJMatrixPreallocate(A, NULL, hA->ij));
11663c07aadSStefano Zampini       PetscFunctionReturn(0);
11763c07aadSStefano Zampini     }
11863c07aadSStefano Zampini   }
11963c07aadSStefano Zampini   PetscFunctionReturn(0);
12063c07aadSStefano Zampini }
12163c07aadSStefano Zampini 
1229371c9d4SSatish Balay static PetscErrorCode MatHYPRE_IJMatrixCopy(Mat A, HYPRE_IJMatrix ij) {
12363c07aadSStefano Zampini   PetscInt           i, rstart, rend, ncols, nr, nc;
12463c07aadSStefano Zampini   const PetscScalar *values;
12563c07aadSStefano Zampini   const PetscInt    *cols;
12663c07aadSStefano Zampini   PetscBool          flg;
12763c07aadSStefano Zampini 
12863c07aadSStefano Zampini   PetscFunctionBegin;
1296ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
130792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize, ij);
1316ea7df73SStefano Zampini #else
132792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize_v2, ij, HYPRE_MEMORY_HOST);
1336ea7df73SStefano Zampini #endif
1349566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &flg));
1359566063dSJacob Faibussowitsch   PetscCall(MatGetSize(A, &nr, &nc));
13663c07aadSStefano Zampini   if (flg && nr == nc) {
1379566063dSJacob Faibussowitsch     PetscCall(MatHYPRE_IJMatrixFastCopy_MPIAIJ(A, ij));
13863c07aadSStefano Zampini     PetscFunctionReturn(0);
13963c07aadSStefano Zampini   }
1409566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &flg));
14163c07aadSStefano Zampini   if (flg) {
1429566063dSJacob Faibussowitsch     PetscCall(MatHYPRE_IJMatrixFastCopy_SeqAIJ(A, ij));
14363c07aadSStefano Zampini     PetscFunctionReturn(0);
14463c07aadSStefano Zampini   }
14563c07aadSStefano Zampini 
1465fbaff96SJunchao Zhang   /* Do not need Aux since we have done precise i[],j[] allocation in MatHYPRE_CreateFromMat() */
1475fbaff96SJunchao Zhang   hypre_AuxParCSRMatrixNeedAux((hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij)) = 0;
1485fbaff96SJunchao Zhang 
1499566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
15063c07aadSStefano Zampini   for (i = rstart; i < rend; i++) {
1519566063dSJacob Faibussowitsch     PetscCall(MatGetRow(A, i, &ncols, &cols, &values));
152e3977e59Sstefano_zampini     if (ncols) {
1532cf14000SStefano Zampini       HYPRE_Int nc = (HYPRE_Int)ncols;
1542cf14000SStefano Zampini 
155aed4548fSBarry Smith       PetscCheck((PetscInt)nc == ncols, PETSC_COMM_SELF, PETSC_ERR_SUP, "Hypre overflow! number of columns %" PetscInt_FMT " for row %" PetscInt_FMT, ncols, i);
156792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixSetValues, ij, 1, &nc, (HYPRE_BigInt *)&i, (HYPRE_BigInt *)cols, (HYPRE_Complex *)values);
157e3977e59Sstefano_zampini     }
1589566063dSJacob Faibussowitsch     PetscCall(MatRestoreRow(A, i, &ncols, &cols, &values));
15963c07aadSStefano Zampini   }
16063c07aadSStefano Zampini   PetscFunctionReturn(0);
16163c07aadSStefano Zampini }
16263c07aadSStefano Zampini 
1639371c9d4SSatish Balay static PetscErrorCode MatHYPRE_IJMatrixFastCopy_SeqAIJ(Mat A, HYPRE_IJMatrix ij) {
16463c07aadSStefano Zampini   Mat_SeqAIJ            *pdiag = (Mat_SeqAIJ *)A->data;
16558968eb6SStefano Zampini   HYPRE_Int              type;
16663c07aadSStefano Zampini   hypre_ParCSRMatrix    *par_matrix;
16763c07aadSStefano Zampini   hypre_AuxParCSRMatrix *aux_matrix;
16863c07aadSStefano Zampini   hypre_CSRMatrix       *hdiag;
1692cf14000SStefano Zampini   PetscBool              sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
1706ea7df73SStefano Zampini   const PetscScalar     *pa;
17163c07aadSStefano Zampini 
17263c07aadSStefano Zampini   PetscFunctionBegin;
173792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type);
17408401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
175792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix);
17663c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(par_matrix);
17763c07aadSStefano Zampini   /*
17863c07aadSStefano Zampini        this is the Hack part where we monkey directly with the hypre datastructures
17963c07aadSStefano Zampini   */
1802cf14000SStefano Zampini   if (sameint) {
1819566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hdiag->i, pdiag->i, A->rmap->n + 1));
1829566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hdiag->j, pdiag->j, pdiag->nz));
1832cf14000SStefano Zampini   } else {
1842cf14000SStefano Zampini     PetscInt i;
1852cf14000SStefano Zampini 
1862cf14000SStefano Zampini     for (i = 0; i < A->rmap->n + 1; i++) hdiag->i[i] = (HYPRE_Int)pdiag->i[i];
1872cf14000SStefano Zampini     for (i = 0; i < pdiag->nz; i++) hdiag->j[i] = (HYPRE_Int)pdiag->j[i];
1882cf14000SStefano Zampini   }
1896ea7df73SStefano Zampini 
1909566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(A, &pa));
1919566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(hdiag->data, pa, pdiag->nz));
1929566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(A, &pa));
193ea9daf28SStefano Zampini 
194ea9daf28SStefano Zampini   aux_matrix                               = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij);
19563c07aadSStefano Zampini   hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
19663c07aadSStefano Zampini   PetscFunctionReturn(0);
19763c07aadSStefano Zampini }
19863c07aadSStefano Zampini 
1999371c9d4SSatish Balay static PetscErrorCode MatHYPRE_IJMatrixFastCopy_MPIAIJ(Mat A, HYPRE_IJMatrix ij) {
20063c07aadSStefano Zampini   Mat_MPIAIJ            *pA = (Mat_MPIAIJ *)A->data;
20163c07aadSStefano Zampini   Mat_SeqAIJ            *pdiag, *poffd;
20263c07aadSStefano Zampini   PetscInt               i, *garray = pA->garray, *jj, cstart, *pjj;
2032cf14000SStefano Zampini   HYPRE_Int             *hjj, type;
20463c07aadSStefano Zampini   hypre_ParCSRMatrix    *par_matrix;
20563c07aadSStefano Zampini   hypre_AuxParCSRMatrix *aux_matrix;
20663c07aadSStefano Zampini   hypre_CSRMatrix       *hdiag, *hoffd;
2072cf14000SStefano Zampini   PetscBool              sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
2086ea7df73SStefano Zampini   const PetscScalar     *pa;
20963c07aadSStefano Zampini 
21063c07aadSStefano Zampini   PetscFunctionBegin;
21163c07aadSStefano Zampini   pdiag = (Mat_SeqAIJ *)pA->A->data;
21263c07aadSStefano Zampini   poffd = (Mat_SeqAIJ *)pA->B->data;
21363c07aadSStefano Zampini   /* cstart is only valid for square MPIAIJ layed out in the usual way */
2149566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &cstart, NULL));
21563c07aadSStefano Zampini 
216792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, ij, &type);
21708401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
218792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, ij, (void **)&par_matrix);
21963c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(par_matrix);
22063c07aadSStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(par_matrix);
22163c07aadSStefano Zampini 
22263c07aadSStefano Zampini   /*
22363c07aadSStefano Zampini        this is the Hack part where we monkey directly with the hypre datastructures
22463c07aadSStefano Zampini   */
2252cf14000SStefano Zampini   if (sameint) {
2269566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hdiag->i, pdiag->i, pA->A->rmap->n + 1));
2272cf14000SStefano Zampini   } else {
2282cf14000SStefano Zampini     for (i = 0; i < pA->A->rmap->n + 1; i++) hdiag->i[i] = (HYPRE_Int)(pdiag->i[i]);
2292cf14000SStefano Zampini   }
23063c07aadSStefano Zampini   /* need to shift the diag column indices (hdiag->j) back to global numbering since hypre is expecting this */
2312cf14000SStefano Zampini   hjj = hdiag->j;
2322cf14000SStefano Zampini   pjj = pdiag->j;
233c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0)
2342cf14000SStefano Zampini   for (i = 0; i < pdiag->nz; i++) hjj[i] = pjj[i];
235c6698e78SStefano Zampini #else
2362cf14000SStefano Zampini   for (i = 0; i < pdiag->nz; i++) hjj[i] = cstart + pjj[i];
237c6698e78SStefano Zampini #endif
2389566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(pA->A, &pa));
2399566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(hdiag->data, pa, pdiag->nz));
2409566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(pA->A, &pa));
2412cf14000SStefano Zampini   if (sameint) {
2429566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hoffd->i, poffd->i, pA->A->rmap->n + 1));
2432cf14000SStefano Zampini   } else {
2442cf14000SStefano Zampini     for (i = 0; i < pA->A->rmap->n + 1; i++) hoffd->i[i] = (HYPRE_Int)(poffd->i[i]);
2452cf14000SStefano Zampini   }
2462cf14000SStefano Zampini 
24763c07aadSStefano Zampini   /* need to move the offd column indices (hoffd->j) back to global numbering since hypre is expecting this
24863c07aadSStefano Zampini      If we hacked a hypre a bit more we might be able to avoid this step */
249c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 16, 0)
250792fecdfSBarry Smith   PetscCallExternal(hypre_CSRMatrixBigInitialize, hoffd);
251c6698e78SStefano Zampini   jj = (PetscInt *)hoffd->big_j;
252c6698e78SStefano Zampini #else
25363c07aadSStefano Zampini   jj = (PetscInt *)hoffd->j;
254c6698e78SStefano Zampini #endif
2552cf14000SStefano Zampini   pjj = poffd->j;
25663c07aadSStefano Zampini   for (i = 0; i < poffd->nz; i++) jj[i] = garray[pjj[i]];
257c6698e78SStefano Zampini 
2589566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJGetArrayRead(pA->B, &pa));
2599566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(hoffd->data, pa, poffd->nz));
2609566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJRestoreArrayRead(pA->B, &pa));
26163c07aadSStefano Zampini 
262ea9daf28SStefano Zampini   aux_matrix                               = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(ij);
26363c07aadSStefano Zampini   hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
26463c07aadSStefano Zampini   PetscFunctionReturn(0);
26563c07aadSStefano Zampini }
26663c07aadSStefano Zampini 
2679371c9d4SSatish Balay static PetscErrorCode MatConvert_HYPRE_IS(Mat A, MatType mtype, MatReuse reuse, Mat *B) {
2682df22349SStefano Zampini   Mat_HYPRE             *mhA = (Mat_HYPRE *)(A->data);
2692df22349SStefano Zampini   Mat                    lA;
2702df22349SStefano Zampini   ISLocalToGlobalMapping rl2g, cl2g;
2712df22349SStefano Zampini   IS                     is;
2722df22349SStefano Zampini   hypre_ParCSRMatrix    *hA;
2732df22349SStefano Zampini   hypre_CSRMatrix       *hdiag, *hoffd;
2742df22349SStefano Zampini   MPI_Comm               comm;
27539accc25SStefano Zampini   HYPRE_Complex         *hdd, *hod, *aa;
27639accc25SStefano Zampini   PetscScalar           *data;
2772cf14000SStefano Zampini   HYPRE_BigInt          *col_map_offd;
2782cf14000SStefano Zampini   HYPRE_Int             *hdi, *hdj, *hoi, *hoj;
2792df22349SStefano Zampini   PetscInt              *ii, *jj, *iptr, *jptr;
2802df22349SStefano Zampini   PetscInt               cum, dr, dc, oc, str, stc, nnz, i, jd, jo, M, N;
28158968eb6SStefano Zampini   HYPRE_Int              type;
2822df22349SStefano Zampini 
2832df22349SStefano Zampini   PetscFunctionBegin;
284a1787963SStefano Zampini   comm = PetscObjectComm((PetscObject)A);
285792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, mhA->ij, &type);
28608401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
287792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, mhA->ij, (void **)&hA);
2882df22349SStefano Zampini   M     = hypre_ParCSRMatrixGlobalNumRows(hA);
2892df22349SStefano Zampini   N     = hypre_ParCSRMatrixGlobalNumCols(hA);
2902df22349SStefano Zampini   str   = hypre_ParCSRMatrixFirstRowIndex(hA);
2912df22349SStefano Zampini   stc   = hypre_ParCSRMatrixFirstColDiag(hA);
2922df22349SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(hA);
2932df22349SStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(hA);
2942df22349SStefano Zampini   dr    = hypre_CSRMatrixNumRows(hdiag);
2952df22349SStefano Zampini   dc    = hypre_CSRMatrixNumCols(hdiag);
2962df22349SStefano Zampini   nnz   = hypre_CSRMatrixNumNonzeros(hdiag);
2972df22349SStefano Zampini   hdi   = hypre_CSRMatrixI(hdiag);
2982df22349SStefano Zampini   hdj   = hypre_CSRMatrixJ(hdiag);
2992df22349SStefano Zampini   hdd   = hypre_CSRMatrixData(hdiag);
3002df22349SStefano Zampini   oc    = hypre_CSRMatrixNumCols(hoffd);
3012df22349SStefano Zampini   nnz += hypre_CSRMatrixNumNonzeros(hoffd);
3022df22349SStefano Zampini   hoi = hypre_CSRMatrixI(hoffd);
3032df22349SStefano Zampini   hoj = hypre_CSRMatrixJ(hoffd);
3042df22349SStefano Zampini   hod = hypre_CSRMatrixData(hoffd);
3052df22349SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
3062df22349SStefano Zampini     PetscInt *aux;
3072df22349SStefano Zampini 
3082df22349SStefano Zampini     /* generate l2g maps for rows and cols */
3099566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(comm, dr, str, 1, &is));
3109566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is, &rl2g));
3119566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
3122df22349SStefano Zampini     col_map_offd = hypre_ParCSRMatrixColMapOffd(hA);
3139566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dc + oc, &aux));
3142df22349SStefano Zampini     for (i = 0; i < dc; i++) aux[i] = i + stc;
3152df22349SStefano Zampini     for (i = 0; i < oc; i++) aux[i + dc] = col_map_offd[i];
3169566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, dc + oc, aux, PETSC_OWN_POINTER, &is));
3179566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(is, &cl2g));
3189566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is));
3192df22349SStefano Zampini     /* create MATIS object */
3209566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm, B));
3219566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(*B, dr, dc, M, N));
3229566063dSJacob Faibussowitsch     PetscCall(MatSetType(*B, MATIS));
3239566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(*B, rl2g, cl2g));
3249566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&rl2g));
3259566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&cl2g));
3262df22349SStefano Zampini 
3272df22349SStefano Zampini     /* allocate CSR for local matrix */
3289566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dr + 1, &iptr));
3299566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &jptr));
3309566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nnz, &data));
3312df22349SStefano Zampini   } else {
3322df22349SStefano Zampini     PetscInt  nr;
3332df22349SStefano Zampini     PetscBool done;
3349566063dSJacob Faibussowitsch     PetscCall(MatISGetLocalMat(*B, &lA));
3359566063dSJacob Faibussowitsch     PetscCall(MatGetRowIJ(lA, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&iptr, (const PetscInt **)&jptr, &done));
33608401ef6SPierre 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);
33708401ef6SPierre 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);
3389566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJGetArray(lA, &data));
3392df22349SStefano Zampini   }
3402df22349SStefano Zampini   /* merge local matrices */
3412df22349SStefano Zampini   ii  = iptr;
3422df22349SStefano Zampini   jj  = jptr;
34339accc25SStefano 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++ */
3442df22349SStefano Zampini   *ii = *(hdi++) + *(hoi++);
3452df22349SStefano Zampini   for (jd = 0, jo = 0, cum = 0; *ii < nnz; cum++) {
34639accc25SStefano Zampini     PetscScalar *aold = (PetscScalar *)aa;
3472df22349SStefano Zampini     PetscInt    *jold = jj, nc = jd + jo;
3489371c9d4SSatish Balay     for (; jd < *hdi; jd++) {
3499371c9d4SSatish Balay       *jj++ = *hdj++;
3509371c9d4SSatish Balay       *aa++ = *hdd++;
3519371c9d4SSatish Balay     }
3529371c9d4SSatish Balay     for (; jo < *hoi; jo++) {
3539371c9d4SSatish Balay       *jj++ = *hoj++ + dc;
3549371c9d4SSatish Balay       *aa++ = *hod++;
3559371c9d4SSatish Balay     }
3562df22349SStefano Zampini     *(++ii) = *(hdi++) + *(hoi++);
3579566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithScalarArray(jd + jo - nc, jold, aold));
3582df22349SStefano Zampini   }
3592df22349SStefano Zampini   for (; cum < dr; cum++) *(++ii) = nnz;
3602df22349SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
361a033916dSStefano Zampini     Mat_SeqAIJ *a;
362a033916dSStefano Zampini 
3639566063dSJacob Faibussowitsch     PetscCall(MatCreateSeqAIJWithArrays(PETSC_COMM_SELF, dr, dc + oc, iptr, jptr, data, &lA));
3649566063dSJacob Faibussowitsch     PetscCall(MatISSetLocalMat(*B, lA));
365a033916dSStefano Zampini     /* hack SeqAIJ */
366a033916dSStefano Zampini     a          = (Mat_SeqAIJ *)(lA->data);
367a033916dSStefano Zampini     a->free_a  = PETSC_TRUE;
368a033916dSStefano Zampini     a->free_ij = PETSC_TRUE;
3699566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&lA));
3702df22349SStefano Zampini   }
3719566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY));
3729566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY));
37348a46eb9SPierre Jolivet   if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, B));
3742df22349SStefano Zampini   PetscFunctionReturn(0);
3752df22349SStefano Zampini }
3762df22349SStefano Zampini 
3779371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType type, MatReuse reuse, Mat *B) {
37884d4e069SStefano Zampini   Mat        M = NULL;
37963c07aadSStefano Zampini   Mat_HYPRE *hB;
38063c07aadSStefano Zampini   MPI_Comm   comm = PetscObjectComm((PetscObject)A);
38163c07aadSStefano Zampini 
38263c07aadSStefano Zampini   PetscFunctionBegin;
38363c07aadSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
38463c07aadSStefano Zampini     /* always destroy the old matrix and create a new memory;
38563c07aadSStefano Zampini        hope this does not churn the memory too much. The problem
38663c07aadSStefano Zampini        is I do not know if it is possible to put the matrix back to
38763c07aadSStefano Zampini        its initial state so that we can directly copy the values
38863c07aadSStefano Zampini        the second time through. */
38963c07aadSStefano Zampini     hB = (Mat_HYPRE *)((*B)->data);
390792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixDestroy, hB->ij);
39163c07aadSStefano Zampini   } else {
3929566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm, &M));
3939566063dSJacob Faibussowitsch     PetscCall(MatSetType(M, MATHYPRE));
3949566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(M, A->rmap->n, A->cmap->n, A->rmap->N, A->cmap->N));
39584d4e069SStefano Zampini     hB = (Mat_HYPRE *)(M->data);
39684d4e069SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) *B = M;
39763c07aadSStefano Zampini   }
3989566063dSJacob Faibussowitsch   PetscCall(MatSetOption(*B, MAT_SORTED_FULL, PETSC_TRUE)); /* "perfect" preallocation, so no need for hypre_AuxParCSRMatrixNeedAux */
3999566063dSJacob Faibussowitsch   PetscCall(MatSetOption(*B, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE));
4009566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_CreateFromMat(A, hB));
4019566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_IJMatrixCopy(A, hB->ij));
40248a46eb9SPierre Jolivet   if (reuse == MAT_INPLACE_MATRIX) PetscCall(MatHeaderReplace(A, &M));
4034ec6421dSstefano_zampini   (*B)->preallocated = PETSC_TRUE;
4049566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*B, MAT_FINAL_ASSEMBLY));
4059566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*B, MAT_FINAL_ASSEMBLY));
40663c07aadSStefano Zampini   PetscFunctionReturn(0);
40763c07aadSStefano Zampini }
40863c07aadSStefano Zampini 
4099371c9d4SSatish Balay static PetscErrorCode MatConvert_HYPRE_AIJ(Mat A, MatType mtype, MatReuse reuse, Mat *B) {
41063c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE *)A->data;
41163c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
41263c07aadSStefano Zampini   hypre_CSRMatrix    *hdiag, *hoffd;
41363c07aadSStefano Zampini   MPI_Comm            comm;
41463c07aadSStefano Zampini   PetscScalar        *da, *oa, *aptr;
41563c07aadSStefano Zampini   PetscInt           *dii, *djj, *oii, *ojj, *iptr;
41663c07aadSStefano Zampini   PetscInt            i, dnnz, onnz, m, n;
41758968eb6SStefano Zampini   HYPRE_Int           type;
41863c07aadSStefano Zampini   PetscMPIInt         size;
4192cf14000SStefano Zampini   PetscBool           sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
42063c07aadSStefano Zampini 
42163c07aadSStefano Zampini   PetscFunctionBegin;
42263c07aadSStefano Zampini   comm = PetscObjectComm((PetscObject)A);
423792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
42408401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
42563c07aadSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
42663c07aadSStefano Zampini     PetscBool ismpiaij, isseqaij;
4279566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATMPIAIJ, &ismpiaij));
4289566063dSJacob Faibussowitsch     PetscCall(PetscObjectBaseTypeCompare((PetscObject)*B, MATSEQAIJ, &isseqaij));
42908401ef6SPierre Jolivet     PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Only MATMPIAIJ or MATSEQAIJ are supported");
43063c07aadSStefano Zampini   }
4316ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
43208401ef6SPierre Jolivet   PetscCheck(HYPRE_MEMORY_DEVICE != hypre_IJMatrixMemoryLocation(hA->ij), comm, PETSC_ERR_SUP, "Not yet implemented");
4336ea7df73SStefano Zampini #endif
4349566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
43563c07aadSStefano Zampini 
436792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
43763c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(parcsr);
43863c07aadSStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(parcsr);
43963c07aadSStefano Zampini   m     = hypre_CSRMatrixNumRows(hdiag);
44063c07aadSStefano Zampini   n     = hypre_CSRMatrixNumCols(hdiag);
44163c07aadSStefano Zampini   dnnz  = hypre_CSRMatrixNumNonzeros(hdiag);
44263c07aadSStefano Zampini   onnz  = hypre_CSRMatrixNumNonzeros(hoffd);
443225daaf8SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
4449566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(m + 1, &dii));
4459566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dnnz, &djj));
4469566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(dnnz, &da));
447225daaf8SStefano Zampini   } else if (reuse == MAT_REUSE_MATRIX) {
44863c07aadSStefano Zampini     PetscInt  nr;
44963c07aadSStefano Zampini     PetscBool done;
45063c07aadSStefano Zampini     if (size > 1) {
45163c07aadSStefano Zampini       Mat_MPIAIJ *b = (Mat_MPIAIJ *)((*B)->data);
45263c07aadSStefano Zampini 
4539566063dSJacob Faibussowitsch       PetscCall(MatGetRowIJ(b->A, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&dii, (const PetscInt **)&djj, &done));
45408401ef6SPierre 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);
45508401ef6SPierre 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);
4569566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJGetArray(b->A, &da));
45763c07aadSStefano Zampini     } else {
4589566063dSJacob Faibussowitsch       PetscCall(MatGetRowIJ(*B, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&dii, (const PetscInt **)&djj, &done));
45908401ef6SPierre Jolivet       PetscCheck(nr == m, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of local rows! %" PetscInt_FMT " != %" PetscInt_FMT, nr, m);
46008401ef6SPierre 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);
4619566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJGetArray(*B, &da));
46263c07aadSStefano Zampini     }
463225daaf8SStefano Zampini   } else { /* MAT_INPLACE_MATRIX */
4642cf14000SStefano Zampini     if (!sameint) {
4659566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(m + 1, &dii));
4669566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(dnnz, &djj));
4672cf14000SStefano Zampini     } else {
4687d968826Sstefano_zampini       dii = (PetscInt *)hypre_CSRMatrixI(hdiag);
4697d968826Sstefano_zampini       djj = (PetscInt *)hypre_CSRMatrixJ(hdiag);
47063c07aadSStefano Zampini     }
47139accc25SStefano Zampini     da = (PetscScalar *)hypre_CSRMatrixData(hdiag);
47263c07aadSStefano Zampini   }
4732cf14000SStefano Zampini 
4742cf14000SStefano Zampini   if (!sameint) {
4759371c9d4SSatish Balay     if (reuse != MAT_REUSE_MATRIX) {
4769371c9d4SSatish Balay       for (i = 0; i < m + 1; i++) dii[i] = (PetscInt)(hypre_CSRMatrixI(hdiag)[i]);
4779371c9d4SSatish Balay     }
4782cf14000SStefano Zampini     for (i = 0; i < dnnz; i++) djj[i] = (PetscInt)(hypre_CSRMatrixJ(hdiag)[i]);
4792cf14000SStefano Zampini   } else {
4809566063dSJacob Faibussowitsch     if (reuse != MAT_REUSE_MATRIX) PetscCall(PetscArraycpy(dii, hypre_CSRMatrixI(hdiag), m + 1));
4819566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(djj, hypre_CSRMatrixJ(hdiag), dnnz));
4822cf14000SStefano Zampini   }
4839566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(da, hypre_CSRMatrixData(hdiag), dnnz));
48463c07aadSStefano Zampini   iptr = djj;
48563c07aadSStefano Zampini   aptr = da;
48663c07aadSStefano Zampini   for (i = 0; i < m; i++) {
48763c07aadSStefano Zampini     PetscInt nc = dii[i + 1] - dii[i];
4889566063dSJacob Faibussowitsch     PetscCall(PetscSortIntWithScalarArray(nc, iptr, aptr));
48963c07aadSStefano Zampini     iptr += nc;
49063c07aadSStefano Zampini     aptr += nc;
49163c07aadSStefano Zampini   }
49263c07aadSStefano Zampini   if (size > 1) {
4932cf14000SStefano Zampini     HYPRE_BigInt *coffd;
4942cf14000SStefano Zampini     HYPRE_Int    *offdj;
49563c07aadSStefano Zampini 
496225daaf8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
4979566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(m + 1, &oii));
4989566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(onnz, &ojj));
4999566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(onnz, &oa));
500225daaf8SStefano Zampini     } else if (reuse == MAT_REUSE_MATRIX) {
50163c07aadSStefano Zampini       Mat_MPIAIJ *b = (Mat_MPIAIJ *)((*B)->data);
50263c07aadSStefano Zampini       PetscInt    nr, hr = hypre_CSRMatrixNumRows(hoffd);
50363c07aadSStefano Zampini       PetscBool   done;
50463c07aadSStefano Zampini 
5059566063dSJacob Faibussowitsch       PetscCall(MatGetRowIJ(b->B, 0, PETSC_FALSE, PETSC_FALSE, &nr, (const PetscInt **)&oii, (const PetscInt **)&ojj, &done));
50608401ef6SPierre 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);
50708401ef6SPierre Jolivet       PetscCheck(oii[nr] >= onnz, PETSC_COMM_SELF, PETSC_ERR_USER, "Cannot reuse mat: invalid number of nonzeros in offdiag part! reuse %" PetscInt_FMT " hypre %" PetscInt_FMT, oii[nr], onnz);
5089566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJGetArray(b->B, &oa));
509225daaf8SStefano Zampini     } else { /* MAT_INPLACE_MATRIX */
5102cf14000SStefano Zampini       if (!sameint) {
5119566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(m + 1, &oii));
5129566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(onnz, &ojj));
5132cf14000SStefano Zampini       } else {
5147d968826Sstefano_zampini         oii = (PetscInt *)hypre_CSRMatrixI(hoffd);
5157d968826Sstefano_zampini         ojj = (PetscInt *)hypre_CSRMatrixJ(hoffd);
51663c07aadSStefano Zampini       }
51739accc25SStefano Zampini       oa = (PetscScalar *)hypre_CSRMatrixData(hoffd);
51863c07aadSStefano Zampini     }
519a16187a7SStefano Zampini     if (reuse != MAT_REUSE_MATRIX) {
5202cf14000SStefano Zampini       if (!sameint) {
5212cf14000SStefano Zampini         for (i = 0; i < m + 1; i++) oii[i] = (PetscInt)(hypre_CSRMatrixI(hoffd)[i]);
5222cf14000SStefano Zampini       } else {
5239566063dSJacob Faibussowitsch         PetscCall(PetscArraycpy(oii, hypre_CSRMatrixI(hoffd), m + 1));
5242cf14000SStefano Zampini       }
525a16187a7SStefano Zampini     }
5269566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(oa, hypre_CSRMatrixData(hoffd), onnz));
527a16187a7SStefano Zampini 
52863c07aadSStefano Zampini     offdj = hypre_CSRMatrixJ(hoffd);
52963c07aadSStefano Zampini     coffd = hypre_ParCSRMatrixColMapOffd(parcsr);
530a16187a7SStefano Zampini     /* we only need the permutation to be computed properly, I don't know if HYPRE
531a16187a7SStefano Zampini        messes up with the ordering. Just in case, allocate some memory and free it
532a16187a7SStefano Zampini        later */
533a16187a7SStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
534a16187a7SStefano Zampini       Mat_MPIAIJ *b = (Mat_MPIAIJ *)((*B)->data);
535a16187a7SStefano Zampini       PetscInt    mnz;
536a16187a7SStefano Zampini 
5379566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJGetMaxRowNonzeros(b->B, &mnz));
5389566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(mnz, &ojj));
5399371c9d4SSatish Balay     } else
5409371c9d4SSatish Balay       for (i = 0; i < onnz; i++) ojj[i] = coffd[offdj[i]];
54163c07aadSStefano Zampini     iptr = ojj;
54263c07aadSStefano Zampini     aptr = oa;
54363c07aadSStefano Zampini     for (i = 0; i < m; i++) {
54463c07aadSStefano Zampini       PetscInt nc = oii[i + 1] - oii[i];
545a16187a7SStefano Zampini       if (reuse == MAT_REUSE_MATRIX) {
546a16187a7SStefano Zampini         PetscInt j;
547a16187a7SStefano Zampini 
548a16187a7SStefano Zampini         iptr = ojj;
549a16187a7SStefano Zampini         for (j = 0; j < nc; j++) iptr[j] = coffd[offdj[oii[i] + j]];
550a16187a7SStefano Zampini       }
5519566063dSJacob Faibussowitsch       PetscCall(PetscSortIntWithScalarArray(nc, iptr, aptr));
55263c07aadSStefano Zampini       iptr += nc;
55363c07aadSStefano Zampini       aptr += nc;
55463c07aadSStefano Zampini     }
5559566063dSJacob Faibussowitsch     if (reuse == MAT_REUSE_MATRIX) PetscCall(PetscFree(ojj));
556225daaf8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
55763c07aadSStefano Zampini       Mat_MPIAIJ *b;
55863c07aadSStefano Zampini       Mat_SeqAIJ *d, *o;
559225daaf8SStefano Zampini 
5609566063dSJacob Faibussowitsch       PetscCall(MatCreateMPIAIJWithSplitArrays(comm, m, n, PETSC_DECIDE, PETSC_DECIDE, dii, djj, da, oii, ojj, oa, B));
56163c07aadSStefano Zampini       /* hack MPIAIJ */
56263c07aadSStefano Zampini       b          = (Mat_MPIAIJ *)((*B)->data);
56363c07aadSStefano Zampini       d          = (Mat_SeqAIJ *)b->A->data;
56463c07aadSStefano Zampini       o          = (Mat_SeqAIJ *)b->B->data;
56563c07aadSStefano Zampini       d->free_a  = PETSC_TRUE;
56663c07aadSStefano Zampini       d->free_ij = PETSC_TRUE;
56763c07aadSStefano Zampini       o->free_a  = PETSC_TRUE;
56863c07aadSStefano Zampini       o->free_ij = PETSC_TRUE;
569225daaf8SStefano Zampini     } else if (reuse == MAT_INPLACE_MATRIX) {
570225daaf8SStefano Zampini       Mat T;
5712cf14000SStefano Zampini 
5729566063dSJacob Faibussowitsch       PetscCall(MatCreateMPIAIJWithSplitArrays(comm, m, n, PETSC_DECIDE, PETSC_DECIDE, dii, djj, da, oii, ojj, oa, &T));
5732cf14000SStefano Zampini       if (sameint) { /* ownership of CSR pointers is transferred to PETSc */
574225daaf8SStefano Zampini         hypre_CSRMatrixI(hdiag) = NULL;
575225daaf8SStefano Zampini         hypre_CSRMatrixJ(hdiag) = NULL;
576225daaf8SStefano Zampini         hypre_CSRMatrixI(hoffd) = NULL;
577225daaf8SStefano Zampini         hypre_CSRMatrixJ(hoffd) = NULL;
5782cf14000SStefano Zampini       } else { /* Hack MPIAIJ -> free ij but not a */
5792cf14000SStefano Zampini         Mat_MPIAIJ *b = (Mat_MPIAIJ *)(T->data);
5802cf14000SStefano Zampini         Mat_SeqAIJ *d = (Mat_SeqAIJ *)(b->A->data);
5812cf14000SStefano Zampini         Mat_SeqAIJ *o = (Mat_SeqAIJ *)(b->B->data);
5822cf14000SStefano Zampini 
5832cf14000SStefano Zampini         d->free_ij = PETSC_TRUE;
5842cf14000SStefano Zampini         o->free_ij = PETSC_TRUE;
5852cf14000SStefano Zampini       }
5862cf14000SStefano Zampini       hypre_CSRMatrixData(hdiag) = NULL;
587225daaf8SStefano Zampini       hypre_CSRMatrixData(hoffd) = NULL;
5889566063dSJacob Faibussowitsch       PetscCall(MatHeaderReplace(A, &T));
58963c07aadSStefano Zampini     }
590225daaf8SStefano Zampini   } else {
591225daaf8SStefano Zampini     oii = NULL;
592225daaf8SStefano Zampini     ojj = NULL;
593225daaf8SStefano Zampini     oa  = NULL;
594225daaf8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
59563c07aadSStefano Zampini       Mat_SeqAIJ *b;
5962cf14000SStefano Zampini 
5979566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqAIJWithArrays(comm, m, n, dii, djj, da, B));
59863c07aadSStefano Zampini       /* hack SeqAIJ */
59963c07aadSStefano Zampini       b          = (Mat_SeqAIJ *)((*B)->data);
60063c07aadSStefano Zampini       b->free_a  = PETSC_TRUE;
60163c07aadSStefano Zampini       b->free_ij = PETSC_TRUE;
602225daaf8SStefano Zampini     } else if (reuse == MAT_INPLACE_MATRIX) {
603225daaf8SStefano Zampini       Mat T;
6042cf14000SStefano Zampini 
6059566063dSJacob Faibussowitsch       PetscCall(MatCreateSeqAIJWithArrays(comm, m, n, dii, djj, da, &T));
6062cf14000SStefano Zampini       if (sameint) { /* ownership of CSR pointers is transferred to PETSc */
607225daaf8SStefano Zampini         hypre_CSRMatrixI(hdiag) = NULL;
608225daaf8SStefano Zampini         hypre_CSRMatrixJ(hdiag) = NULL;
6092cf14000SStefano Zampini       } else { /* free ij but not a */
6102cf14000SStefano Zampini         Mat_SeqAIJ *b = (Mat_SeqAIJ *)(T->data);
6112cf14000SStefano Zampini 
6122cf14000SStefano Zampini         b->free_ij = PETSC_TRUE;
6132cf14000SStefano Zampini       }
614225daaf8SStefano Zampini       hypre_CSRMatrixData(hdiag) = NULL;
6159566063dSJacob Faibussowitsch       PetscCall(MatHeaderReplace(A, &T));
61663c07aadSStefano Zampini     }
617225daaf8SStefano Zampini   }
618225daaf8SStefano Zampini 
6192cf14000SStefano Zampini   /* we have to use hypre_Tfree to free the HYPRE arrays
6202cf14000SStefano Zampini      that PETSc now onws */
62163c07aadSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
6222cf14000SStefano Zampini     PetscInt    nh;
6232cf14000SStefano Zampini     void       *ptrs[6]  = {da, oa, dii, djj, oii, ojj};
6249371c9d4SSatish Balay     const char *names[6] = {"_hypre_csr_da", "_hypre_csr_oa", "_hypre_csr_dii", "_hypre_csr_djj", "_hypre_csr_oii", "_hypre_csr_ojj"};
6252cf14000SStefano Zampini     nh                   = sameint ? 6 : 2;
6262cf14000SStefano Zampini     for (i = 0; i < nh; i++) {
627225daaf8SStefano Zampini       PetscContainer c;
628225daaf8SStefano Zampini 
6299566063dSJacob Faibussowitsch       PetscCall(PetscContainerCreate(comm, &c));
6309566063dSJacob Faibussowitsch       PetscCall(PetscContainerSetPointer(c, ptrs[i]));
6319566063dSJacob Faibussowitsch       PetscCall(PetscContainerSetUserDestroy(c, hypre_array_destroy));
6329566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)(*B), names[i], (PetscObject)c));
6339566063dSJacob Faibussowitsch       PetscCall(PetscContainerDestroy(&c));
634225daaf8SStefano Zampini     }
63563c07aadSStefano Zampini   }
63663c07aadSStefano Zampini   PetscFunctionReturn(0);
63763c07aadSStefano Zampini }
63863c07aadSStefano Zampini 
6399371c9d4SSatish Balay static PetscErrorCode MatAIJGetParCSR_Private(Mat A, hypre_ParCSRMatrix **hA) {
640613e5ff0Sstefano_zampini   hypre_ParCSRMatrix *tA;
641c1a070e6SStefano Zampini   hypre_CSRMatrix    *hdiag, *hoffd;
642c1a070e6SStefano Zampini   Mat_SeqAIJ         *diag, *offd;
6432cf14000SStefano Zampini   PetscInt           *garray, i, noffd, dnnz, onnz, *row_starts, *col_starts;
644c1a070e6SStefano Zampini   MPI_Comm            comm = PetscObjectComm((PetscObject)A);
645613e5ff0Sstefano_zampini   PetscBool           ismpiaij, isseqaij;
6462cf14000SStefano Zampini   PetscBool           sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
6476ea7df73SStefano Zampini   HYPRE_Int          *hdi = NULL, *hdj = NULL, *hoi = NULL, *hoj = NULL;
6485c97c10fSStefano Zampini   PetscInt           *pdi = NULL, *pdj = NULL, *poi = NULL, *poj = NULL;
6496ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
6506ea7df73SStefano Zampini   PetscBool iscuda = PETSC_FALSE;
6516ea7df73SStefano Zampini #endif
652c1a070e6SStefano Zampini 
653c1a070e6SStefano Zampini   PetscFunctionBegin;
6549566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
6559566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATSEQAIJ, &isseqaij));
65608401ef6SPierre Jolivet   PetscCheck(ismpiaij || isseqaij, comm, PETSC_ERR_SUP, "Unsupported type %s", ((PetscObject)A)->type_name);
657c1a070e6SStefano Zampini   if (ismpiaij) {
658c1a070e6SStefano Zampini     Mat_MPIAIJ *a = (Mat_MPIAIJ *)(A->data);
659c1a070e6SStefano Zampini 
660c1a070e6SStefano Zampini     diag = (Mat_SeqAIJ *)a->A->data;
661c1a070e6SStefano Zampini     offd = (Mat_SeqAIJ *)a->B->data;
6626ea7df73SStefano Zampini #if defined(PETSC_HAVE_CUDA) && defined(PETSC_HAVE_HYPRE_DEVICE) && defined(HYPRE_USING_CUDA)
6639566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATMPIAIJCUSPARSE, &iscuda));
6646ea7df73SStefano Zampini     if (iscuda && !A->boundtocpu) {
6656ea7df73SStefano Zampini       sameint = PETSC_TRUE;
6669566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJCUSPARSEGetIJ(a->A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
6679566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJCUSPARSEGetIJ(a->B, PETSC_FALSE, (const HYPRE_Int **)&hoi, (const HYPRE_Int **)&hoj));
6686ea7df73SStefano Zampini     } else {
6696ea7df73SStefano Zampini #else
6706ea7df73SStefano Zampini     {
6716ea7df73SStefano Zampini #endif
6726ea7df73SStefano Zampini       pdi = diag->i;
6736ea7df73SStefano Zampini       pdj = diag->j;
6746ea7df73SStefano Zampini       poi = offd->i;
6756ea7df73SStefano Zampini       poj = offd->j;
6766ea7df73SStefano Zampini       if (sameint) {
6776ea7df73SStefano Zampini         hdi = (HYPRE_Int *)pdi;
6786ea7df73SStefano Zampini         hdj = (HYPRE_Int *)pdj;
6796ea7df73SStefano Zampini         hoi = (HYPRE_Int *)poi;
6806ea7df73SStefano Zampini         hoj = (HYPRE_Int *)poj;
6816ea7df73SStefano Zampini       }
6826ea7df73SStefano Zampini     }
683c1a070e6SStefano Zampini     garray = a->garray;
684c1a070e6SStefano Zampini     noffd  = a->B->cmap->N;
685c1a070e6SStefano Zampini     dnnz   = diag->nz;
686c1a070e6SStefano Zampini     onnz   = offd->nz;
687c1a070e6SStefano Zampini   } else {
688c1a070e6SStefano Zampini     diag = (Mat_SeqAIJ *)A->data;
689c1a070e6SStefano Zampini     offd = NULL;
6906ea7df73SStefano Zampini #if defined(PETSC_HAVE_CUDA) && defined(PETSC_HAVE_HYPRE_DEVICE)
6919566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)A, MATSEQAIJCUSPARSE, &iscuda));
6926ea7df73SStefano Zampini     if (iscuda && !A->boundtocpu) {
6936ea7df73SStefano Zampini       sameint = PETSC_TRUE;
6949566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJCUSPARSEGetIJ(A, PETSC_FALSE, (const HYPRE_Int **)&hdi, (const HYPRE_Int **)&hdj));
6956ea7df73SStefano Zampini     } else {
6966ea7df73SStefano Zampini #else
6976ea7df73SStefano Zampini     {
6986ea7df73SStefano Zampini #endif
6996ea7df73SStefano Zampini       pdi = diag->i;
7006ea7df73SStefano Zampini       pdj = diag->j;
7016ea7df73SStefano Zampini       if (sameint) {
7026ea7df73SStefano Zampini         hdi = (HYPRE_Int *)pdi;
7036ea7df73SStefano Zampini         hdj = (HYPRE_Int *)pdj;
7046ea7df73SStefano Zampini       }
7056ea7df73SStefano Zampini     }
706c1a070e6SStefano Zampini     garray = NULL;
707c1a070e6SStefano Zampini     noffd  = 0;
708c1a070e6SStefano Zampini     dnnz   = diag->nz;
709c1a070e6SStefano Zampini     onnz   = 0;
710c1a070e6SStefano Zampini   }
711225daaf8SStefano Zampini 
712c1a070e6SStefano Zampini   /* create a temporary ParCSR */
713c1a070e6SStefano Zampini   if (HYPRE_AssumedPartitionCheck()) {
714c1a070e6SStefano Zampini     PetscMPIInt myid;
715c1a070e6SStefano Zampini 
7169566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &myid));
717c1a070e6SStefano Zampini     row_starts = A->rmap->range + myid;
718c1a070e6SStefano Zampini     col_starts = A->cmap->range + myid;
719c1a070e6SStefano Zampini   } else {
720c1a070e6SStefano Zampini     row_starts = A->rmap->range;
721c1a070e6SStefano Zampini     col_starts = A->cmap->range;
722c1a070e6SStefano Zampini   }
7232cf14000SStefano Zampini   tA = hypre_ParCSRMatrixCreate(comm, A->rmap->N, A->cmap->N, (HYPRE_BigInt *)row_starts, (HYPRE_BigInt *)col_starts, noffd, dnnz, onnz);
724a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
725c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetRowStartsOwner(tA, 0);
726c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetColStartsOwner(tA, 0);
727a1d2239cSSatish Balay #endif
728c1a070e6SStefano Zampini 
729225daaf8SStefano Zampini   /* set diagonal part */
730c1a070e6SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(tA);
7316ea7df73SStefano Zampini   if (!sameint) { /* malloc CSR pointers */
7329566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(A->rmap->n + 1, &hdi, dnnz, &hdj));
7336ea7df73SStefano Zampini     for (i = 0; i < A->rmap->n + 1; i++) hdi[i] = (HYPRE_Int)(pdi[i]);
7346ea7df73SStefano Zampini     for (i = 0; i < dnnz; i++) hdj[i] = (HYPRE_Int)(pdj[i]);
7352cf14000SStefano Zampini   }
7366ea7df73SStefano Zampini   hypre_CSRMatrixI(hdiag)           = hdi;
7376ea7df73SStefano Zampini   hypre_CSRMatrixJ(hdiag)           = hdj;
73839accc25SStefano Zampini   hypre_CSRMatrixData(hdiag)        = (HYPRE_Complex *)diag->a;
739c1a070e6SStefano Zampini   hypre_CSRMatrixNumNonzeros(hdiag) = diag->nz;
740c1a070e6SStefano Zampini   hypre_CSRMatrixSetRownnz(hdiag);
741c1a070e6SStefano Zampini   hypre_CSRMatrixSetDataOwner(hdiag, 0);
742c1a070e6SStefano Zampini 
743225daaf8SStefano Zampini   /* set offdiagonal part */
744c1a070e6SStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(tA);
745c1a070e6SStefano Zampini   if (offd) {
7466ea7df73SStefano Zampini     if (!sameint) { /* malloc CSR pointers */
7479566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(A->rmap->n + 1, &hoi, onnz, &hoj));
7486ea7df73SStefano Zampini       for (i = 0; i < A->rmap->n + 1; i++) hoi[i] = (HYPRE_Int)(poi[i]);
7496ea7df73SStefano Zampini       for (i = 0; i < onnz; i++) hoj[i] = (HYPRE_Int)(poj[i]);
7502cf14000SStefano Zampini     }
7516ea7df73SStefano Zampini     hypre_CSRMatrixI(hoffd)           = hoi;
7526ea7df73SStefano Zampini     hypre_CSRMatrixJ(hoffd)           = hoj;
75339accc25SStefano Zampini     hypre_CSRMatrixData(hoffd)        = (HYPRE_Complex *)offd->a;
754c1a070e6SStefano Zampini     hypre_CSRMatrixNumNonzeros(hoffd) = offd->nz;
755c1a070e6SStefano Zampini     hypre_CSRMatrixSetRownnz(hoffd);
756c1a070e6SStefano Zampini     hypre_CSRMatrixSetDataOwner(hoffd, 0);
7576ea7df73SStefano Zampini   }
7586ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
759792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, iscuda ? HYPRE_MEMORY_DEVICE : HYPRE_MEMORY_HOST);
7606ea7df73SStefano Zampini #else
7616ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0)
762792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixInitialize, tA);
7636ea7df73SStefano Zampini #else
764792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixInitialize_v2, tA, HYPRE_MEMORY_HOST);
7656ea7df73SStefano Zampini #endif
7666ea7df73SStefano Zampini #endif
7676ea7df73SStefano Zampini   hypre_TFree(hypre_ParCSRMatrixColMapOffd(tA), HYPRE_MEMORY_HOST);
768c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetNumNonzeros(tA);
7692cf14000SStefano Zampini   hypre_ParCSRMatrixColMapOffd(tA) = (HYPRE_BigInt *)garray;
770792fecdfSBarry Smith   if (!hypre_ParCSRMatrixCommPkg(tA)) PetscCallExternal(hypre_MatvecCommPkgCreate, tA);
771613e5ff0Sstefano_zampini   *hA = tA;
772613e5ff0Sstefano_zampini   PetscFunctionReturn(0);
773613e5ff0Sstefano_zampini }
774c1a070e6SStefano Zampini 
7759371c9d4SSatish Balay static PetscErrorCode MatAIJRestoreParCSR_Private(Mat A, hypre_ParCSRMatrix **hA) {
776613e5ff0Sstefano_zampini   hypre_CSRMatrix *hdiag, *hoffd;
7776ea7df73SStefano Zampini   PetscBool        ismpiaij, sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
7786ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
7796ea7df73SStefano Zampini   PetscBool iscuda = PETSC_FALSE;
7806ea7df73SStefano Zampini #endif
781c1a070e6SStefano Zampini 
782613e5ff0Sstefano_zampini   PetscFunctionBegin;
7839566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)A, MATMPIAIJ, &ismpiaij));
7846ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
7859566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)A, &iscuda, MATSEQAIJCUSPARSE, MATMPIAIJCUSPARSE, ""));
7866ea7df73SStefano Zampini   if (iscuda) sameint = PETSC_TRUE;
7876ea7df73SStefano Zampini #endif
788613e5ff0Sstefano_zampini   hdiag = hypre_ParCSRMatrixDiag(*hA);
789613e5ff0Sstefano_zampini   hoffd = hypre_ParCSRMatrixOffd(*hA);
7906ea7df73SStefano Zampini   /* free temporary memory allocated by PETSc
7916ea7df73SStefano Zampini      set pointers to NULL before destroying tA */
7922cf14000SStefano Zampini   if (!sameint) {
7932cf14000SStefano Zampini     HYPRE_Int *hi, *hj;
7942cf14000SStefano Zampini 
7952cf14000SStefano Zampini     hi = hypre_CSRMatrixI(hdiag);
7962cf14000SStefano Zampini     hj = hypre_CSRMatrixJ(hdiag);
7979566063dSJacob Faibussowitsch     PetscCall(PetscFree2(hi, hj));
7986ea7df73SStefano Zampini     if (ismpiaij) {
7992cf14000SStefano Zampini       hi = hypre_CSRMatrixI(hoffd);
8002cf14000SStefano Zampini       hj = hypre_CSRMatrixJ(hoffd);
8019566063dSJacob Faibussowitsch       PetscCall(PetscFree2(hi, hj));
8022cf14000SStefano Zampini     }
8032cf14000SStefano Zampini   }
804c1a070e6SStefano Zampini   hypre_CSRMatrixI(hdiag)    = NULL;
805c1a070e6SStefano Zampini   hypre_CSRMatrixJ(hdiag)    = NULL;
806c1a070e6SStefano Zampini   hypre_CSRMatrixData(hdiag) = NULL;
8076ea7df73SStefano Zampini   if (ismpiaij) {
808c1a070e6SStefano Zampini     hypre_CSRMatrixI(hoffd)    = NULL;
809c1a070e6SStefano Zampini     hypre_CSRMatrixJ(hoffd)    = NULL;
810c1a070e6SStefano Zampini     hypre_CSRMatrixData(hoffd) = NULL;
8116ea7df73SStefano Zampini   }
812613e5ff0Sstefano_zampini   hypre_ParCSRMatrixColMapOffd(*hA) = NULL;
813613e5ff0Sstefano_zampini   hypre_ParCSRMatrixDestroy(*hA);
814613e5ff0Sstefano_zampini   *hA = NULL;
815613e5ff0Sstefano_zampini   PetscFunctionReturn(0);
816613e5ff0Sstefano_zampini }
817613e5ff0Sstefano_zampini 
818613e5ff0Sstefano_zampini /* calls RAP from BoomerAMG:
8193dad0653Sstefano_zampini    the resulting ParCSR will not own the column and row starts
8206ea7df73SStefano Zampini    It looks like we don't need to have the diagonal entries ordered first */
8219371c9d4SSatish Balay static PetscErrorCode MatHYPRE_ParCSR_RAP(hypre_ParCSRMatrix *hR, hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hP, hypre_ParCSRMatrix **hRAP) {
822a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
823613e5ff0Sstefano_zampini   HYPRE_Int P_owns_col_starts, R_owns_row_starts;
824a1d2239cSSatish Balay #endif
825613e5ff0Sstefano_zampini 
826613e5ff0Sstefano_zampini   PetscFunctionBegin;
827a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
828613e5ff0Sstefano_zampini   P_owns_col_starts = hypre_ParCSRMatrixOwnsColStarts(hP);
829613e5ff0Sstefano_zampini   R_owns_row_starts = hypre_ParCSRMatrixOwnsRowStarts(hR);
830a1d2239cSSatish Balay #endif
8316ea7df73SStefano Zampini   /* can be replaced by version test later */
8326ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
833792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParCSRMatrixRAP");
8346ea7df73SStefano Zampini   *hRAP = hypre_ParCSRMatrixRAP(hR, hA, hP);
8356ea7df73SStefano Zampini   PetscStackPop;
8366ea7df73SStefano Zampini #else
837792fecdfSBarry Smith   PetscCallExternal(hypre_BoomerAMGBuildCoarseOperator, hR, hA, hP, hRAP);
838792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixSetNumNonzeros, *hRAP);
8396ea7df73SStefano Zampini #endif
840613e5ff0Sstefano_zampini   /* hypre_BoomerAMGBuildCoarseOperator steals the col_starts from P and the row_starts from R */
841a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
842613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetRowStartsOwner(*hRAP, 0);
843613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetColStartsOwner(*hRAP, 0);
844613e5ff0Sstefano_zampini   if (P_owns_col_starts) hypre_ParCSRMatrixSetColStartsOwner(hP, 1);
845613e5ff0Sstefano_zampini   if (R_owns_row_starts) hypre_ParCSRMatrixSetRowStartsOwner(hR, 1);
846a1d2239cSSatish Balay #endif
847613e5ff0Sstefano_zampini   PetscFunctionReturn(0);
848613e5ff0Sstefano_zampini }
849613e5ff0Sstefano_zampini 
8509371c9d4SSatish Balay static PetscErrorCode MatPtAPNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat P, Mat C) {
8516f231fbdSstefano_zampini   Mat                 B;
8526abb4441SStefano Zampini   hypre_ParCSRMatrix *hA, *hP, *hPtAP = NULL;
8534222ddf1SHong Zhang   Mat_Product        *product = C->product;
854613e5ff0Sstefano_zampini 
855613e5ff0Sstefano_zampini   PetscFunctionBegin;
8569566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
8579566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(P, &hP));
8589566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(hP, hA, hP, &hPtAP));
8599566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hPtAP, MATAIJ, PETSC_OWN_POINTER, &B));
8604222ddf1SHong Zhang 
8619566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
8624222ddf1SHong Zhang   C->product = product;
8634222ddf1SHong Zhang 
8649566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
8659566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(P, &hP));
8666f231fbdSstefano_zampini   PetscFunctionReturn(0);
8676f231fbdSstefano_zampini }
8686f231fbdSstefano_zampini 
8699371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatPtAPSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat P, PetscReal fill, Mat C) {
8706f231fbdSstefano_zampini   PetscFunctionBegin;
8719566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATAIJ));
8724222ddf1SHong Zhang   C->ops->ptapnumeric    = MatPtAPNumeric_AIJ_AIJ_wHYPRE;
8734222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
874613e5ff0Sstefano_zampini   PetscFunctionReturn(0);
875613e5ff0Sstefano_zampini }
876613e5ff0Sstefano_zampini 
8779371c9d4SSatish Balay static PetscErrorCode MatPtAPNumeric_AIJ_HYPRE(Mat A, Mat P, Mat C) {
8784cc28894Sstefano_zampini   Mat                 B;
8794cc28894Sstefano_zampini   Mat_HYPRE          *hP;
8806abb4441SStefano Zampini   hypre_ParCSRMatrix *hA = NULL, *Pparcsr, *ptapparcsr = NULL;
881613e5ff0Sstefano_zampini   HYPRE_Int           type;
882613e5ff0Sstefano_zampini   MPI_Comm            comm = PetscObjectComm((PetscObject)A);
8834cc28894Sstefano_zampini   PetscBool           ishypre;
884613e5ff0Sstefano_zampini 
885613e5ff0Sstefano_zampini   PetscFunctionBegin;
8869566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre));
88728b400f6SJacob Faibussowitsch   PetscCheck(ishypre, comm, PETSC_ERR_USER, "P should be of type %s", MATHYPRE);
8884cc28894Sstefano_zampini   hP = (Mat_HYPRE *)P->data;
889792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type);
89008401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, comm, PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
891792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr);
892613e5ff0Sstefano_zampini 
8939566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
8949566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, hA, Pparcsr, &ptapparcsr));
8959566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
896225daaf8SStefano Zampini 
8974cc28894Sstefano_zampini   /* create temporary matrix and merge to C */
8989566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ptapparcsr, ((PetscObject)C)->type_name, PETSC_OWN_POINTER, &B));
8999566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
9004cc28894Sstefano_zampini   PetscFunctionReturn(0);
9014cc28894Sstefano_zampini }
9024cc28894Sstefano_zampini 
9039371c9d4SSatish Balay static PetscErrorCode MatPtAPNumeric_HYPRE_HYPRE(Mat A, Mat P, Mat C) {
9044cc28894Sstefano_zampini   Mat                 B;
9056abb4441SStefano Zampini   hypre_ParCSRMatrix *Aparcsr, *Pparcsr, *ptapparcsr = NULL;
9064cc28894Sstefano_zampini   Mat_HYPRE          *hA, *hP;
9074cc28894Sstefano_zampini   PetscBool           ishypre;
9084cc28894Sstefano_zampini   HYPRE_Int           type;
9094cc28894Sstefano_zampini 
9104cc28894Sstefano_zampini   PetscFunctionBegin;
9119566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)P, MATHYPRE, &ishypre));
91228b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)P), PETSC_ERR_USER, "P should be of type %s", MATHYPRE);
9139566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
91428b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE);
9154cc28894Sstefano_zampini   hA = (Mat_HYPRE *)A->data;
9164cc28894Sstefano_zampini   hP = (Mat_HYPRE *)P->data;
917792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
91808401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
919792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hP->ij, &type);
92008401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)P), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
921792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr);
922792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hP->ij, (void **)&Pparcsr);
9239566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(Pparcsr, Aparcsr, Pparcsr, &ptapparcsr));
9249566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ptapparcsr, MATHYPRE, PETSC_OWN_POINTER, &B));
9259566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &B));
9264cc28894Sstefano_zampini   PetscFunctionReturn(0);
9274cc28894Sstefano_zampini }
9284cc28894Sstefano_zampini 
929d501dc42Sstefano_zampini /* calls hypre_ParMatmul
930d501dc42Sstefano_zampini    hypre_ParMatMul uses hypre_ParMatrixCreate with the communicator of hA
9313dad0653Sstefano_zampini    hypre_ParMatrixCreate does not duplicate the communicator
9326ea7df73SStefano Zampini    It looks like we don't need to have the diagonal entries ordered first */
9339371c9d4SSatish Balay static PetscErrorCode MatHYPRE_ParCSR_MatMatMult(hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hB, hypre_ParCSRMatrix **hAB) {
934d501dc42Sstefano_zampini   PetscFunctionBegin;
9356ea7df73SStefano Zampini   /* can be replaced by version test later */
9366ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
937792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParCSRMatMat");
9386ea7df73SStefano Zampini   *hAB = hypre_ParCSRMatMat(hA, hB);
9396ea7df73SStefano Zampini #else
940792fecdfSBarry Smith   PetscStackPushExternal("hypre_ParMatmul");
941d501dc42Sstefano_zampini   *hAB = hypre_ParMatmul(hA, hB);
9426ea7df73SStefano Zampini #endif
943d501dc42Sstefano_zampini   PetscStackPop;
944d501dc42Sstefano_zampini   PetscFunctionReturn(0);
945d501dc42Sstefano_zampini }
946d501dc42Sstefano_zampini 
9479371c9d4SSatish Balay static PetscErrorCode MatMatMultNumeric_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C) {
9485e5acdf2Sstefano_zampini   Mat                 D;
949d501dc42Sstefano_zampini   hypre_ParCSRMatrix *hA, *hB, *hAB = NULL;
9504222ddf1SHong Zhang   Mat_Product        *product = C->product;
9515e5acdf2Sstefano_zampini 
9525e5acdf2Sstefano_zampini   PetscFunctionBegin;
9539566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
9549566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(B, &hB));
9559566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_MatMatMult(hA, hB, &hAB));
9569566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hAB, MATAIJ, PETSC_OWN_POINTER, &D));
9574222ddf1SHong Zhang 
9589566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(C, &D));
9594222ddf1SHong Zhang   C->product = product;
9604222ddf1SHong Zhang 
9619566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
9629566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(B, &hB));
9635e5acdf2Sstefano_zampini   PetscFunctionReturn(0);
9645e5acdf2Sstefano_zampini }
9655e5acdf2Sstefano_zampini 
9669371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatMatMultSymbolic_AIJ_AIJ_wHYPRE(Mat A, Mat B, PetscReal fill, Mat C) {
9675e5acdf2Sstefano_zampini   PetscFunctionBegin;
9689566063dSJacob Faibussowitsch   PetscCall(MatSetType(C, MATAIJ));
9694222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_AIJ_AIJ_wHYPRE;
9704222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
9715e5acdf2Sstefano_zampini   PetscFunctionReturn(0);
9725e5acdf2Sstefano_zampini }
9735e5acdf2Sstefano_zampini 
9749371c9d4SSatish Balay static PetscErrorCode MatMatMultNumeric_HYPRE_HYPRE(Mat A, Mat B, Mat C) {
975d501dc42Sstefano_zampini   Mat                 D;
976d501dc42Sstefano_zampini   hypre_ParCSRMatrix *Aparcsr, *Bparcsr, *ABparcsr = NULL;
977d501dc42Sstefano_zampini   Mat_HYPRE          *hA, *hB;
978d501dc42Sstefano_zampini   PetscBool           ishypre;
979d501dc42Sstefano_zampini   HYPRE_Int           type;
9804222ddf1SHong Zhang   Mat_Product        *product;
981d501dc42Sstefano_zampini 
982d501dc42Sstefano_zampini   PetscFunctionBegin;
9839566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)B, MATHYPRE, &ishypre));
98428b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)B), PETSC_ERR_USER, "B should be of type %s", MATHYPRE);
9859566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &ishypre));
98628b400f6SJacob Faibussowitsch   PetscCheck(ishypre, PetscObjectComm((PetscObject)A), PETSC_ERR_USER, "A should be of type %s", MATHYPRE);
987d501dc42Sstefano_zampini   hA = (Mat_HYPRE *)A->data;
988d501dc42Sstefano_zampini   hB = (Mat_HYPRE *)B->data;
989792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
99008401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
991792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hB->ij, &type);
99208401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)B), PETSC_ERR_SUP, "Only HYPRE_PARCSR is supported");
993792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&Aparcsr);
994792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hB->ij, (void **)&Bparcsr);
9959566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_MatMatMult(Aparcsr, Bparcsr, &ABparcsr));
9969566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(ABparcsr, MATHYPRE, PETSC_OWN_POINTER, &D));
9974222ddf1SHong Zhang 
998d501dc42Sstefano_zampini   /* need to use HeaderReplace because HeaderMerge messes up with the communicator */
9994222ddf1SHong Zhang   product    = C->product; /* save it from MatHeaderReplace() */
10004222ddf1SHong Zhang   C->product = NULL;
10019566063dSJacob Faibussowitsch   PetscCall(MatHeaderReplace(C, &D));
10024222ddf1SHong Zhang   C->product             = product;
1003d501dc42Sstefano_zampini   C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE;
10044222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
1005d501dc42Sstefano_zampini   PetscFunctionReturn(0);
1006d501dc42Sstefano_zampini }
1007d501dc42Sstefano_zampini 
10089371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatTransposeMatMatMultNumeric_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, Mat D) {
100920e1dc0dSstefano_zampini   Mat                 E;
10106abb4441SStefano Zampini   hypre_ParCSRMatrix *hA, *hB, *hC, *hABC = NULL;
101120e1dc0dSstefano_zampini 
101220e1dc0dSstefano_zampini   PetscFunctionBegin;
10139566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(A, &hA));
10149566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(B, &hB));
10159566063dSJacob Faibussowitsch   PetscCall(MatAIJGetParCSR_Private(C, &hC));
10169566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_ParCSR_RAP(hA, hB, hC, &hABC));
10179566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(hABC, MATAIJ, PETSC_OWN_POINTER, &E));
10189566063dSJacob Faibussowitsch   PetscCall(MatHeaderMerge(D, &E));
10199566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(A, &hA));
10209566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(B, &hB));
10219566063dSJacob Faibussowitsch   PetscCall(MatAIJRestoreParCSR_Private(C, &hC));
102220e1dc0dSstefano_zampini   PetscFunctionReturn(0);
102320e1dc0dSstefano_zampini }
102420e1dc0dSstefano_zampini 
10259371c9d4SSatish Balay PETSC_INTERN PetscErrorCode MatTransposeMatMatMultSymbolic_AIJ_AIJ_AIJ_wHYPRE(Mat A, Mat B, Mat C, PetscReal fill, Mat D) {
102620e1dc0dSstefano_zampini   PetscFunctionBegin;
10279566063dSJacob Faibussowitsch   PetscCall(MatSetType(D, MATAIJ));
102820e1dc0dSstefano_zampini   PetscFunctionReturn(0);
102920e1dc0dSstefano_zampini }
103020e1dc0dSstefano_zampini 
10314222ddf1SHong Zhang /* ---------------------------------------------------- */
10329371c9d4SSatish Balay static PetscErrorCode MatProductSymbolic_AB_HYPRE(Mat C) {
10334222ddf1SHong Zhang   PetscFunctionBegin;
10344222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
10354222ddf1SHong Zhang   PetscFunctionReturn(0);
10364222ddf1SHong Zhang }
10374222ddf1SHong Zhang 
10389371c9d4SSatish Balay static PetscErrorCode MatProductSetFromOptions_HYPRE_AB(Mat C) {
10394222ddf1SHong Zhang   Mat_Product *product = C->product;
10404222ddf1SHong Zhang   PetscBool    Ahypre;
10414222ddf1SHong Zhang 
10424222ddf1SHong Zhang   PetscFunctionBegin;
10439566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)product->A, MATHYPRE, &Ahypre));
10444222ddf1SHong Zhang   if (Ahypre) { /* A is a Hypre matrix */
10459566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
10464222ddf1SHong Zhang     C->ops->productsymbolic = MatProductSymbolic_AB_HYPRE;
10474222ddf1SHong Zhang     C->ops->matmultnumeric  = MatMatMultNumeric_HYPRE_HYPRE;
10484222ddf1SHong Zhang     PetscFunctionReturn(0);
10496718818eSStefano Zampini   }
10504222ddf1SHong Zhang   PetscFunctionReturn(0);
10514222ddf1SHong Zhang }
10524222ddf1SHong Zhang 
10539371c9d4SSatish Balay static PetscErrorCode MatProductSymbolic_PtAP_HYPRE(Mat C) {
10544222ddf1SHong Zhang   PetscFunctionBegin;
10554222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
10564222ddf1SHong Zhang   PetscFunctionReturn(0);
10574222ddf1SHong Zhang }
10584222ddf1SHong Zhang 
10599371c9d4SSatish Balay static PetscErrorCode MatProductSetFromOptions_HYPRE_PtAP(Mat C) {
10604222ddf1SHong Zhang   Mat_Product *product = C->product;
10614222ddf1SHong Zhang   PetscBool    flg;
10624222ddf1SHong Zhang   PetscInt     type        = 0;
10634222ddf1SHong Zhang   const char  *outTypes[4] = {"aij", "seqaij", "mpiaij", "hypre"};
10644222ddf1SHong Zhang   PetscInt     ntype       = 4;
10654222ddf1SHong Zhang   Mat          A           = product->A;
10664222ddf1SHong Zhang   PetscBool    Ahypre;
10674222ddf1SHong Zhang 
10684222ddf1SHong Zhang   PetscFunctionBegin;
10699566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)A, MATHYPRE, &Ahypre));
10704222ddf1SHong Zhang   if (Ahypre) { /* A is a Hypre matrix */
10719566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
10724222ddf1SHong Zhang     C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE;
10734222ddf1SHong Zhang     C->ops->ptapnumeric     = MatPtAPNumeric_HYPRE_HYPRE;
10744222ddf1SHong Zhang     PetscFunctionReturn(0);
10754222ddf1SHong Zhang   }
10764222ddf1SHong Zhang 
10774222ddf1SHong Zhang   /* A is AIJ, P is Hypre, C = PtAP can be either AIJ or Hypre format */
10784222ddf1SHong Zhang   /* Get runtime option */
10794222ddf1SHong Zhang   if (product->api_user) {
1080d0609cedSBarry Smith     PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatPtAP_HYPRE", "Mat");
10819566063dSJacob Faibussowitsch     PetscCall(PetscOptionsEList("-matptap_hypre_outtype", "MatPtAP outtype", "MatPtAP outtype", outTypes, ntype, outTypes[type], &type, &flg));
1082d0609cedSBarry Smith     PetscOptionsEnd();
10834222ddf1SHong Zhang   } else {
1084d0609cedSBarry Smith     PetscOptionsBegin(PetscObjectComm((PetscObject)C), ((PetscObject)C)->prefix, "MatProduct_PtAP_HYPRE", "Mat");
10859566063dSJacob Faibussowitsch     PetscCall(PetscOptionsEList("-mat_product_algorithm_hypre_outtype", "MatProduct_PtAP outtype", "MatProduct_PtAP", outTypes, ntype, outTypes[type], &type, &flg));
1086d0609cedSBarry Smith     PetscOptionsEnd();
10874222ddf1SHong Zhang   }
10884222ddf1SHong Zhang 
10894222ddf1SHong Zhang   if (type == 0 || type == 1 || type == 2) {
10909566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATAIJ));
10914222ddf1SHong Zhang   } else if (type == 3) {
10929566063dSJacob Faibussowitsch     PetscCall(MatSetType(C, MATHYPRE));
10934222ddf1SHong Zhang   } else SETERRQ(PetscObjectComm((PetscObject)C), PETSC_ERR_SUP, "MatPtAP outtype is not supported");
10944222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE;
10954222ddf1SHong Zhang   C->ops->ptapnumeric     = MatPtAPNumeric_AIJ_HYPRE;
10964222ddf1SHong Zhang   PetscFunctionReturn(0);
10974222ddf1SHong Zhang }
10984222ddf1SHong Zhang 
10999371c9d4SSatish Balay static PetscErrorCode MatProductSetFromOptions_HYPRE(Mat C) {
11004222ddf1SHong Zhang   Mat_Product *product = C->product;
11014222ddf1SHong Zhang 
11024222ddf1SHong Zhang   PetscFunctionBegin;
11034222ddf1SHong Zhang   switch (product->type) {
11049371c9d4SSatish Balay   case MATPRODUCT_AB: PetscCall(MatProductSetFromOptions_HYPRE_AB(C)); break;
11059371c9d4SSatish Balay   case MATPRODUCT_PtAP: PetscCall(MatProductSetFromOptions_HYPRE_PtAP(C)); break;
11069371c9d4SSatish Balay   default: break;
11074222ddf1SHong Zhang   }
11084222ddf1SHong Zhang   PetscFunctionReturn(0);
11094222ddf1SHong Zhang }
11104222ddf1SHong Zhang 
11114222ddf1SHong Zhang /* -------------------------------------------------------- */
11124222ddf1SHong Zhang 
11139371c9d4SSatish Balay static PetscErrorCode MatMultTranspose_HYPRE(Mat A, Vec x, Vec y) {
111463c07aadSStefano Zampini   PetscFunctionBegin;
11159566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_TRUE));
111663c07aadSStefano Zampini   PetscFunctionReturn(0);
111763c07aadSStefano Zampini }
111863c07aadSStefano Zampini 
11199371c9d4SSatish Balay static PetscErrorCode MatMult_HYPRE(Mat A, Vec x, Vec y) {
112063c07aadSStefano Zampini   PetscFunctionBegin;
11219566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 0.0, y, PETSC_FALSE));
112263c07aadSStefano Zampini   PetscFunctionReturn(0);
112363c07aadSStefano Zampini }
112463c07aadSStefano Zampini 
11259371c9d4SSatish Balay static PetscErrorCode MatMultAdd_HYPRE(Mat A, Vec x, Vec y, Vec z) {
1126414bd5c3SStefano Zampini   PetscFunctionBegin;
112748a46eb9SPierre Jolivet   if (y != z) PetscCall(VecCopy(y, z));
11289566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_FALSE));
1129414bd5c3SStefano Zampini   PetscFunctionReturn(0);
1130414bd5c3SStefano Zampini }
1131414bd5c3SStefano Zampini 
11329371c9d4SSatish Balay static PetscErrorCode MatMultTransposeAdd_HYPRE(Mat A, Vec x, Vec y, Vec z) {
1133414bd5c3SStefano Zampini   PetscFunctionBegin;
113448a46eb9SPierre Jolivet   if (y != z) PetscCall(VecCopy(y, z));
11359566063dSJacob Faibussowitsch   PetscCall(MatHYPRE_MultKernel_Private(A, 1.0, x, 1.0, z, PETSC_TRUE));
1136414bd5c3SStefano Zampini   PetscFunctionReturn(0);
1137414bd5c3SStefano Zampini }
1138414bd5c3SStefano Zampini 
1139414bd5c3SStefano Zampini /* y = a * A * x + b * y or y = a * A^t * x + b * y depending on trans */
11409371c9d4SSatish Balay static PetscErrorCode MatHYPRE_MultKernel_Private(Mat A, HYPRE_Complex a, Vec x, HYPRE_Complex b, Vec y, PetscBool trans) {
114163c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE *)A->data;
114263c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
114363c07aadSStefano Zampini   hypre_ParVector    *hx, *hy;
114463c07aadSStefano Zampini 
114563c07aadSStefano Zampini   PetscFunctionBegin;
114663c07aadSStefano Zampini   if (trans) {
11479566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorPushVecRead(hA->b, x));
11489566063dSJacob Faibussowitsch     if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->x, y));
11499566063dSJacob Faibussowitsch     else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->x, y));
1150792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hx);
1151792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hy);
115263c07aadSStefano Zampini   } else {
11539566063dSJacob Faibussowitsch     PetscCall(VecHYPRE_IJVectorPushVecRead(hA->x, x));
11549566063dSJacob Faibussowitsch     if (b != 0.0) PetscCall(VecHYPRE_IJVectorPushVec(hA->b, y));
11559566063dSJacob Faibussowitsch     else PetscCall(VecHYPRE_IJVectorPushVecWrite(hA->b, y));
1156792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->x->ij, (void **)&hx);
1157792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJVectorGetObject, hA->b->ij, (void **)&hy);
115863c07aadSStefano Zampini   }
1159792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
11606ea7df73SStefano Zampini   if (trans) {
1161792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMatvecT, a, parcsr, hx, b, hy);
11626ea7df73SStefano Zampini   } else {
1163792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMatvec, a, parcsr, hx, b, hy);
11646ea7df73SStefano Zampini   }
11659566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hA->x));
11669566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorPopVec(hA->b));
116763c07aadSStefano Zampini   PetscFunctionReturn(0);
116863c07aadSStefano Zampini }
116963c07aadSStefano Zampini 
11709371c9d4SSatish Balay static PetscErrorCode MatDestroy_HYPRE(Mat A) {
117163c07aadSStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
117263c07aadSStefano Zampini 
117363c07aadSStefano Zampini   PetscFunctionBegin;
11749566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&hA->x));
11759566063dSJacob Faibussowitsch   PetscCall(VecHYPRE_IJVectorDestroy(&hA->b));
1176978814f1SStefano Zampini   if (hA->ij) {
1177978814f1SStefano Zampini     if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL;
1178792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixDestroy, hA->ij);
1179978814f1SStefano Zampini   }
11809566063dSJacob Faibussowitsch   if (hA->comm) PetscCall(PetscCommRestoreComm(PetscObjectComm((PetscObject)A), &hA->comm));
1181c69f721fSFande Kong 
11829566063dSJacob Faibussowitsch   PetscCall(MatStashDestroy_Private(&A->stash));
11839566063dSJacob Faibussowitsch   PetscCall(PetscFree(hA->array));
1184c69f721fSFande Kong 
11855fbaff96SJunchao Zhang   if (hA->cooMat) {
11865fbaff96SJunchao Zhang     PetscCall(MatDestroy(&hA->cooMat));
1187e77caa6dSBarry Smith     PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hA->diagJ, hA->memType));
1188e77caa6dSBarry Smith     PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hA->offdJ, hA->memType));
1189e77caa6dSBarry Smith     PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hA->diag, hA->memType));
11905fbaff96SJunchao Zhang   }
11915fbaff96SJunchao Zhang 
11929566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_aij_C", NULL));
11939566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatConvert_hypre_is_C", NULL));
11949566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_seqaij_hypre_C", NULL));
11959566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatProductSetFromOptions_mpiaij_hypre_C", NULL));
11969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPRESetPreallocation_C", NULL));
11979566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatHYPREGetParCSR_C", NULL));
11985fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetPreallocationCOO_C", NULL));
11995fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)A, "MatSetValuesCOO_C", NULL));
12009566063dSJacob Faibussowitsch   PetscCall(PetscFree(A->data));
120163c07aadSStefano Zampini   PetscFunctionReturn(0);
120263c07aadSStefano Zampini }
120363c07aadSStefano Zampini 
12049371c9d4SSatish Balay static PetscErrorCode MatSetUp_HYPRE(Mat A) {
12054ec6421dSstefano_zampini   PetscFunctionBegin;
12069566063dSJacob Faibussowitsch   PetscCall(MatHYPRESetPreallocation(A, PETSC_DEFAULT, NULL, PETSC_DEFAULT, NULL));
12074ec6421dSstefano_zampini   PetscFunctionReturn(0);
12084ec6421dSstefano_zampini }
12094ec6421dSstefano_zampini 
12106ea7df73SStefano Zampini //TODO FIX hypre_CSRMatrixMatvecOutOfPlace
12116ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
12129371c9d4SSatish Balay static PetscErrorCode MatBindToCPU_HYPRE(Mat A, PetscBool bind) {
12136ea7df73SStefano Zampini   Mat_HYPRE           *hA   = (Mat_HYPRE *)A->data;
12146ea7df73SStefano Zampini   HYPRE_MemoryLocation hmem = bind ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE;
12156ea7df73SStefano Zampini 
12166ea7df73SStefano Zampini   PetscFunctionBegin;
12176ea7df73SStefano Zampini   A->boundtocpu = bind;
12185fbaff96SJunchao Zhang   if (hA->ij && hypre_IJMatrixAssembleFlag(hA->ij) && hmem != hypre_IJMatrixMemoryLocation(hA->ij)) {
12196ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
1220792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
1221792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMigrate, parcsr, hmem);
12226ea7df73SStefano Zampini   }
12239566063dSJacob Faibussowitsch   if (hA->x) PetscCall(VecHYPRE_IJBindToCPU(hA->x, bind));
12249566063dSJacob Faibussowitsch   if (hA->b) PetscCall(VecHYPRE_IJBindToCPU(hA->b, bind));
12256ea7df73SStefano Zampini   PetscFunctionReturn(0);
12266ea7df73SStefano Zampini }
12276ea7df73SStefano Zampini #endif
12286ea7df73SStefano Zampini 
12299371c9d4SSatish Balay static PetscErrorCode MatAssemblyEnd_HYPRE(Mat A, MatAssemblyType mode) {
123063c07aadSStefano Zampini   Mat_HYPRE   *hA = (Mat_HYPRE *)A->data;
1231c69f721fSFande Kong   PetscMPIInt  n;
1232c69f721fSFande Kong   PetscInt     i, j, rstart, ncols, flg;
1233c69f721fSFande Kong   PetscInt    *row, *col;
1234c69f721fSFande Kong   PetscScalar *val;
123563c07aadSStefano Zampini 
123663c07aadSStefano Zampini   PetscFunctionBegin;
123708401ef6SPierre Jolivet   PetscCheck(mode != MAT_FLUSH_ASSEMBLY, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_FLUSH_ASSEMBLY currently not supported with MATHYPRE");
1238c69f721fSFande Kong 
1239c69f721fSFande Kong   if (!A->nooffprocentries) {
1240c69f721fSFande Kong     while (1) {
12419566063dSJacob Faibussowitsch       PetscCall(MatStashScatterGetMesg_Private(&A->stash, &n, &row, &col, &val, &flg));
1242c69f721fSFande Kong       if (!flg) break;
1243c69f721fSFande Kong 
1244c69f721fSFande Kong       for (i = 0; i < n;) {
1245c69f721fSFande Kong         /* Now identify the consecutive vals belonging to the same row */
1246c69f721fSFande Kong         for (j = i, rstart = row[j]; j < n; j++) {
1247c69f721fSFande Kong           if (row[j] != rstart) break;
1248c69f721fSFande Kong         }
1249c69f721fSFande Kong         if (j < n) ncols = j - i;
1250c69f721fSFande Kong         else ncols = n - i;
1251c69f721fSFande Kong         /* Now assemble all these values with a single function call */
12529566063dSJacob Faibussowitsch         PetscCall(MatSetValues_HYPRE(A, 1, row + i, ncols, col + i, val + i, A->insertmode));
1253c69f721fSFande Kong 
1254c69f721fSFande Kong         i = j;
1255c69f721fSFande Kong       }
1256c69f721fSFande Kong     }
12579566063dSJacob Faibussowitsch     PetscCall(MatStashScatterEnd_Private(&A->stash));
1258c69f721fSFande Kong   }
1259c69f721fSFande Kong 
1260792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixAssemble, hA->ij);
1261336664bdSPierre Jolivet   /* The assembly routine destroys the aux_matrix, we recreate it here by calling HYPRE_IJMatrixInitialize */
1262336664bdSPierre 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 */
1263336664bdSPierre Jolivet   if (!hA->sorted_full) {
1264af1cf968SStefano Zampini     hypre_AuxParCSRMatrix *aux_matrix;
1265af1cf968SStefano Zampini 
1266af1cf968SStefano Zampini     /* call destroy just to make sure we do not leak anything */
1267af1cf968SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
1268792fecdfSBarry Smith     PetscCallExternal(hypre_AuxParCSRMatrixDestroy, aux_matrix);
1269af1cf968SStefano Zampini     hypre_IJMatrixTranslator(hA->ij) = NULL;
1270af1cf968SStefano Zampini 
1271af1cf968SStefano Zampini     /* Initialize with assembled flag -> it only recreates the aux_par_matrix */
1272792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij);
1273af1cf968SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
12746ea7df73SStefano Zampini     if (aux_matrix) {
1275af1cf968SStefano Zampini       hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1; /* see comment in MatHYPRESetPreallocation_HYPRE */
127622235d61SPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
1277792fecdfSBarry Smith       PetscCallExternal(hypre_AuxParCSRMatrixInitialize, aux_matrix);
127822235d61SPierre Jolivet #else
1279792fecdfSBarry Smith       PetscCallExternal(hypre_AuxParCSRMatrixInitialize_v2, aux_matrix, HYPRE_MEMORY_HOST);
128022235d61SPierre Jolivet #endif
1281af1cf968SStefano Zampini     }
12826ea7df73SStefano Zampini   }
12836ea7df73SStefano Zampini   {
12846ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
12856ea7df73SStefano Zampini 
1286792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)&parcsr);
1287792fecdfSBarry Smith     if (!hypre_ParCSRMatrixCommPkg(parcsr)) PetscCallExternal(hypre_MatvecCommPkgCreate, parcsr);
12886ea7df73SStefano Zampini   }
12899566063dSJacob Faibussowitsch   if (!hA->x) PetscCall(VecHYPRE_IJVectorCreate(A->cmap, &hA->x));
12909566063dSJacob Faibussowitsch   if (!hA->b) PetscCall(VecHYPRE_IJVectorCreate(A->rmap, &hA->b));
12916ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
12929566063dSJacob Faibussowitsch   PetscCall(MatBindToCPU_HYPRE(A, A->boundtocpu));
12936ea7df73SStefano Zampini #endif
129463c07aadSStefano Zampini   PetscFunctionReturn(0);
129563c07aadSStefano Zampini }
129663c07aadSStefano Zampini 
12979371c9d4SSatish Balay static PetscErrorCode MatGetArray_HYPRE(Mat A, PetscInt size, void **array) {
1298c69f721fSFande Kong   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1299c69f721fSFande Kong 
1300c69f721fSFande Kong   PetscFunctionBegin;
130128b400f6SJacob Faibussowitsch   PetscCheck(hA->available, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Temporary space is in use");
1302c69f721fSFande Kong 
130339accc25SStefano Zampini   if (hA->size >= size) {
130439accc25SStefano Zampini     *array = hA->array;
130539accc25SStefano Zampini   } else {
13069566063dSJacob Faibussowitsch     PetscCall(PetscFree(hA->array));
1307c69f721fSFande Kong     hA->size = size;
13089566063dSJacob Faibussowitsch     PetscCall(PetscMalloc(hA->size, &hA->array));
1309c69f721fSFande Kong     *array = hA->array;
1310c69f721fSFande Kong   }
1311c69f721fSFande Kong 
1312c69f721fSFande Kong   hA->available = PETSC_FALSE;
1313c69f721fSFande Kong   PetscFunctionReturn(0);
1314c69f721fSFande Kong }
1315c69f721fSFande Kong 
13169371c9d4SSatish Balay static PetscErrorCode MatRestoreArray_HYPRE(Mat A, void **array) {
1317c69f721fSFande Kong   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1318c69f721fSFande Kong 
1319c69f721fSFande Kong   PetscFunctionBegin;
1320c69f721fSFande Kong   *array        = NULL;
1321c69f721fSFande Kong   hA->available = PETSC_TRUE;
1322c69f721fSFande Kong   PetscFunctionReturn(0);
1323c69f721fSFande Kong }
1324c69f721fSFande Kong 
13259371c9d4SSatish Balay static PetscErrorCode MatSetValues_HYPRE(Mat A, PetscInt nr, const PetscInt rows[], PetscInt nc, const PetscInt cols[], const PetscScalar v[], InsertMode ins) {
1326d975228cSstefano_zampini   Mat_HYPRE     *hA   = (Mat_HYPRE *)A->data;
1327d975228cSstefano_zampini   PetscScalar   *vals = (PetscScalar *)v;
132839accc25SStefano Zampini   HYPRE_Complex *sscr;
1329c69f721fSFande Kong   PetscInt      *cscr[2];
1330c69f721fSFande Kong   PetscInt       i, nzc;
133108defe43SFande Kong   void          *array = NULL;
1332d975228cSstefano_zampini 
1333d975228cSstefano_zampini   PetscFunctionBegin;
13349566063dSJacob Faibussowitsch   PetscCall(MatGetArray_HYPRE(A, sizeof(PetscInt) * (2 * nc) + sizeof(HYPRE_Complex) * nc * nr, &array));
1335c69f721fSFande Kong   cscr[0] = (PetscInt *)array;
1336c69f721fSFande Kong   cscr[1] = ((PetscInt *)array) + nc;
133739accc25SStefano Zampini   sscr    = (HYPRE_Complex *)(((PetscInt *)array) + nc * 2);
1338d975228cSstefano_zampini   for (i = 0, nzc = 0; i < nc; i++) {
1339d975228cSstefano_zampini     if (cols[i] >= 0) {
1340d975228cSstefano_zampini       cscr[0][nzc]   = cols[i];
1341d975228cSstefano_zampini       cscr[1][nzc++] = i;
1342d975228cSstefano_zampini     }
1343d975228cSstefano_zampini   }
1344c69f721fSFande Kong   if (!nzc) {
13459566063dSJacob Faibussowitsch     PetscCall(MatRestoreArray_HYPRE(A, &array));
1346c69f721fSFande Kong     PetscFunctionReturn(0);
1347c69f721fSFande Kong   }
1348d975228cSstefano_zampini 
13496ea7df73SStefano Zampini #if 0 //defined(PETSC_HAVE_HYPRE_DEVICE)
13506ea7df73SStefano Zampini   if (HYPRE_MEMORY_HOST != hypre_IJMatrixMemoryLocation(hA->ij)) {
13516ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
13526ea7df73SStefano Zampini 
1353792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetObject,hA->ij,(void**)&parcsr);
1354792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixMigrate,parcsr, HYPRE_MEMORY_HOST);
13556ea7df73SStefano Zampini   }
13566ea7df73SStefano Zampini #endif
13576ea7df73SStefano Zampini 
1358d975228cSstefano_zampini   if (ins == ADD_VALUES) {
1359d975228cSstefano_zampini     for (i = 0; i < nr; i++) {
13606ea7df73SStefano Zampini       if (rows[i] >= 0) {
1361d975228cSstefano_zampini         PetscInt  j;
13622cf14000SStefano Zampini         HYPRE_Int hnc = (HYPRE_Int)nzc;
13632cf14000SStefano Zampini 
1364aed4548fSBarry 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]);
13659566063dSJacob Faibussowitsch         for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j]));
1366792fecdfSBarry Smith         PetscCallExternal(HYPRE_IJMatrixAddToValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr);
1367d975228cSstefano_zampini       }
1368d975228cSstefano_zampini       vals += nc;
1369d975228cSstefano_zampini     }
1370d975228cSstefano_zampini   } else { /* INSERT_VALUES */
1371d975228cSstefano_zampini     PetscInt rst, ren;
1372c69f721fSFande Kong 
13739566063dSJacob Faibussowitsch     PetscCall(MatGetOwnershipRange(A, &rst, &ren));
1374d975228cSstefano_zampini     for (i = 0; i < nr; i++) {
13756ea7df73SStefano Zampini       if (rows[i] >= 0) {
1376d975228cSstefano_zampini         PetscInt  j;
13772cf14000SStefano Zampini         HYPRE_Int hnc = (HYPRE_Int)nzc;
13782cf14000SStefano Zampini 
1379aed4548fSBarry 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]);
13809566063dSJacob Faibussowitsch         for (j = 0; j < nzc; j++) PetscCall(PetscHYPREScalarCast(vals[cscr[1][j]], &sscr[j]));
1381c69f721fSFande Kong         /* nonlocal values */
13829566063dSJacob Faibussowitsch         if (rows[i] < rst || rows[i] >= ren) PetscCall(MatStashValuesRow_Private(&A->stash, rows[i], nzc, cscr[0], (PetscScalar *)sscr, PETSC_FALSE));
1383c69f721fSFande Kong         /* local values */
1384792fecdfSBarry Smith         else PetscCallExternal(HYPRE_IJMatrixSetValues, hA->ij, 1, &hnc, (HYPRE_BigInt *)(rows + i), (HYPRE_BigInt *)cscr[0], sscr);
1385d975228cSstefano_zampini       }
1386d975228cSstefano_zampini       vals += nc;
1387d975228cSstefano_zampini     }
1388d975228cSstefano_zampini   }
1389c69f721fSFande Kong 
13909566063dSJacob Faibussowitsch   PetscCall(MatRestoreArray_HYPRE(A, &array));
1391d975228cSstefano_zampini   PetscFunctionReturn(0);
1392d975228cSstefano_zampini }
1393d975228cSstefano_zampini 
13949371c9d4SSatish Balay static PetscErrorCode MatHYPRESetPreallocation_HYPRE(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[]) {
1395d975228cSstefano_zampini   Mat_HYPRE  *hA = (Mat_HYPRE *)A->data;
13967d968826Sstefano_zampini   HYPRE_Int  *hdnnz, *honnz;
139706a29025Sstefano_zampini   PetscInt    i, rs, re, cs, ce, bs;
1398d975228cSstefano_zampini   PetscMPIInt size;
1399d975228cSstefano_zampini 
1400d975228cSstefano_zampini   PetscFunctionBegin;
14019566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->rmap));
14029566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(A->cmap));
1403d975228cSstefano_zampini   rs = A->rmap->rstart;
1404d975228cSstefano_zampini   re = A->rmap->rend;
1405d975228cSstefano_zampini   cs = A->cmap->rstart;
1406d975228cSstefano_zampini   ce = A->cmap->rend;
1407d975228cSstefano_zampini   if (!hA->ij) {
1408792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rs, re - 1, cs, ce - 1, &hA->ij);
1409792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR);
1410d975228cSstefano_zampini   } else {
14112cf14000SStefano Zampini     HYPRE_BigInt hrs, hre, hcs, hce;
1412792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixGetLocalRange, hA->ij, &hrs, &hre, &hcs, &hce);
1413aed4548fSBarry 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);
1414aed4548fSBarry 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);
1415d975228cSstefano_zampini   }
14169566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(A, &bs));
141706a29025Sstefano_zampini   if (dnz == PETSC_DEFAULT || dnz == PETSC_DECIDE) dnz = 10 * bs;
141806a29025Sstefano_zampini   if (onz == PETSC_DEFAULT || onz == PETSC_DECIDE) onz = 10 * bs;
141906a29025Sstefano_zampini 
1420d975228cSstefano_zampini   if (!dnnz) {
14219566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(A->rmap->n, &hdnnz));
1422d975228cSstefano_zampini     for (i = 0; i < A->rmap->n; i++) hdnnz[i] = dnz;
1423d975228cSstefano_zampini   } else {
14247d968826Sstefano_zampini     hdnnz = (HYPRE_Int *)dnnz;
1425d975228cSstefano_zampini   }
14269566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
1427d975228cSstefano_zampini   if (size > 1) {
1428ddbeb582SStefano Zampini     hypre_AuxParCSRMatrix *aux_matrix;
1429d975228cSstefano_zampini     if (!onnz) {
14309566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(A->rmap->n, &honnz));
1431d975228cSstefano_zampini       for (i = 0; i < A->rmap->n; i++) honnz[i] = onz;
143222235d61SPierre Jolivet     } else honnz = (HYPRE_Int *)onnz;
1433ddbeb582SStefano Zampini     /* SetDiagOffdSizes sets hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0, since it seems
1434ddbeb582SStefano Zampini        they assume the user will input the entire row values, properly sorted
1435336664bdSPierre Jolivet        In PETSc, we don't make such an assumption and set this flag to 1,
1436336664bdSPierre Jolivet        unless the option MAT_SORTED_FULL is set to true.
1437ddbeb582SStefano Zampini        Also, to avoid possible memory leaks, we destroy and recreate the translator
1438ddbeb582SStefano Zampini        This has to be done here, as HYPRE_IJMatrixInitialize will properly initialize
1439ddbeb582SStefano Zampini        the IJ matrix for us */
1440ddbeb582SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
1441ddbeb582SStefano Zampini     hypre_AuxParCSRMatrixDestroy(aux_matrix);
1442ddbeb582SStefano Zampini     hypre_IJMatrixTranslator(hA->ij) = NULL;
1443792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetDiagOffdSizes, hA->ij, hdnnz, honnz);
1444ddbeb582SStefano Zampini     aux_matrix                               = (hypre_AuxParCSRMatrix *)hypre_IJMatrixTranslator(hA->ij);
1445336664bdSPierre Jolivet     hypre_AuxParCSRMatrixNeedAux(aux_matrix) = !hA->sorted_full;
1446d975228cSstefano_zampini   } else {
1447d975228cSstefano_zampini     honnz = NULL;
1448792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetRowSizes, hA->ij, hdnnz);
1449d975228cSstefano_zampini   }
1450ddbeb582SStefano Zampini 
1451af1cf968SStefano Zampini   /* reset assembled flag and call the initialize method */
1452af1cf968SStefano Zampini   hypre_IJMatrixAssembleFlag(hA->ij) = 0;
14536ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
1454792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize, hA->ij);
14556ea7df73SStefano Zampini #else
1456792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize_v2, hA->ij, HYPRE_MEMORY_HOST);
14576ea7df73SStefano Zampini #endif
145848a46eb9SPierre Jolivet   if (!dnnz) PetscCall(PetscFree(hdnnz));
145948a46eb9SPierre Jolivet   if (!onnz && honnz) PetscCall(PetscFree(honnz));
1460af1cf968SStefano Zampini   /* Match AIJ logic */
146106a29025Sstefano_zampini   A->preallocated = PETSC_TRUE;
1462af1cf968SStefano Zampini   A->assembled    = PETSC_FALSE;
1463d975228cSstefano_zampini   PetscFunctionReturn(0);
1464d975228cSstefano_zampini }
1465d975228cSstefano_zampini 
1466d975228cSstefano_zampini /*@C
1467d975228cSstefano_zampini    MatHYPRESetPreallocation - Preallocates memory for a sparse parallel matrix in HYPRE IJ format
1468d975228cSstefano_zampini 
146911a5261eSBarry Smith    Collective on A
1470d975228cSstefano_zampini 
1471d975228cSstefano_zampini    Input Parameters:
1472d975228cSstefano_zampini +  A - the matrix
1473d975228cSstefano_zampini .  dnz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1474d975228cSstefano_zampini           (same value is used for all local rows)
1475d975228cSstefano_zampini .  dnnz - array containing the number of nonzeros in the various rows of the
1476d975228cSstefano_zampini           DIAGONAL portion of the local submatrix (possibly different for each row)
147711a5261eSBarry Smith           or NULL (`PETSC_NULL_INTEGER` in Fortran), if d_nz is used to specify the nonzero structure.
1478d975228cSstefano_zampini           The size of this array is equal to the number of local rows, i.e 'm'.
1479d975228cSstefano_zampini           For matrices that will be factored, you must leave room for (and set)
1480d975228cSstefano_zampini           the diagonal entry even if it is zero.
1481d975228cSstefano_zampini .  onz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1482d975228cSstefano_zampini           submatrix (same value is used for all local rows).
1483d975228cSstefano_zampini -  onnz - array containing the number of nonzeros in the various rows of the
1484d975228cSstefano_zampini           OFF-DIAGONAL portion of the local submatrix (possibly different for
148511a5261eSBarry Smith           each row) or NULL (`PETSC_NULL_INTEGER` in Fortran), if o_nz is used to specify the nonzero
1486d975228cSstefano_zampini           structure. The size of this array is equal to the number
1487d975228cSstefano_zampini           of local rows, i.e 'm'.
1488d975228cSstefano_zampini 
148911a5261eSBarry Smith    Note:
149095452b02SPatrick Sanan     If the *nnz parameter is given then the *nz parameter is ignored; for sequential matrices, onz and onnz are ignored.
1491d975228cSstefano_zampini 
1492d975228cSstefano_zampini    Level: intermediate
1493d975228cSstefano_zampini 
1494db781477SPatrick Sanan .seealso: `MatCreate()`, `MatMPIAIJSetPreallocation()`, `MATHYPRE`
1495d975228cSstefano_zampini @*/
14969371c9d4SSatish Balay PetscErrorCode MatHYPRESetPreallocation(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[]) {
1497d975228cSstefano_zampini   PetscFunctionBegin;
1498d975228cSstefano_zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1499d975228cSstefano_zampini   PetscValidType(A, 1);
1500cac4c232SBarry Smith   PetscTryMethod(A, "MatHYPRESetPreallocation_C", (Mat, PetscInt, const PetscInt[], PetscInt, const PetscInt[]), (A, dnz, dnnz, onz, onnz));
1501d975228cSstefano_zampini   PetscFunctionReturn(0);
1502d975228cSstefano_zampini }
1503d975228cSstefano_zampini 
1504225daaf8SStefano Zampini /*
1505225daaf8SStefano Zampini    MatCreateFromParCSR - Creates a matrix from a hypre_ParCSRMatrix
1506225daaf8SStefano Zampini 
1507225daaf8SStefano Zampini    Collective
1508225daaf8SStefano Zampini 
1509225daaf8SStefano Zampini    Input Parameters:
151045b8d346SStefano Zampini +  parcsr   - the pointer to the hypre_ParCSRMatrix
1511bb4689ddSStefano Zampini .  mtype    - matrix type to be created. Currently MATAIJ, MATIS and MATHYPRE are supported.
1512225daaf8SStefano Zampini -  copymode - PETSc copying options
1513225daaf8SStefano Zampini 
1514225daaf8SStefano Zampini    Output Parameter:
1515225daaf8SStefano Zampini .  A  - the matrix
1516225daaf8SStefano Zampini 
1517225daaf8SStefano Zampini    Level: intermediate
1518225daaf8SStefano Zampini 
1519db781477SPatrick Sanan .seealso: `MatHYPRE`, `PetscCopyMode`
1520225daaf8SStefano Zampini */
15219371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatCreateFromParCSR(hypre_ParCSRMatrix *parcsr, MatType mtype, PetscCopyMode copymode, Mat *A) {
1522225daaf8SStefano Zampini   Mat        T;
1523978814f1SStefano Zampini   Mat_HYPRE *hA;
1524978814f1SStefano Zampini   MPI_Comm   comm;
1525978814f1SStefano Zampini   PetscInt   rstart, rend, cstart, cend, M, N;
1526d248a85cSRichard Tran Mills   PetscBool  isseqaij, isseqaijmkl, ismpiaij, isaij, ishyp, isis;
1527978814f1SStefano Zampini 
1528978814f1SStefano Zampini   PetscFunctionBegin;
1529978814f1SStefano Zampini   comm = hypre_ParCSRMatrixComm(parcsr);
15309566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQAIJ, &isseqaij));
15319566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQAIJMKL, &isseqaijmkl));
15329566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPIAIJ, &ismpiaij));
15339566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATAIJ, &isaij));
15349566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATHYPRE, &ishyp));
15359566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATIS, &isis));
1536d248a85cSRichard Tran Mills   isaij = (PetscBool)(isseqaij || isseqaijmkl || ismpiaij || isaij);
15376ea7df73SStefano Zampini   /* TODO */
1538aed4548fSBarry 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);
1539978814f1SStefano Zampini   /* access ParCSRMatrix */
1540978814f1SStefano Zampini   rstart = hypre_ParCSRMatrixFirstRowIndex(parcsr);
1541978814f1SStefano Zampini   rend   = hypre_ParCSRMatrixLastRowIndex(parcsr);
1542978814f1SStefano Zampini   cstart = hypre_ParCSRMatrixFirstColDiag(parcsr);
1543978814f1SStefano Zampini   cend   = hypre_ParCSRMatrixLastColDiag(parcsr);
1544978814f1SStefano Zampini   M      = hypre_ParCSRMatrixGlobalNumRows(parcsr);
1545978814f1SStefano Zampini   N      = hypre_ParCSRMatrixGlobalNumCols(parcsr);
1546978814f1SStefano Zampini 
1547fa92c42cSstefano_zampini   /* fix for empty local rows/columns */
1548fa92c42cSstefano_zampini   if (rend < rstart) rend = rstart;
1549fa92c42cSstefano_zampini   if (cend < cstart) cend = cstart;
1550fa92c42cSstefano_zampini 
1551e6471dc9SStefano Zampini   /* PETSc convention */
1552e6471dc9SStefano Zampini   rend++;
1553e6471dc9SStefano Zampini   cend++;
1554e6471dc9SStefano Zampini   rend = PetscMin(rend, M);
1555e6471dc9SStefano Zampini   cend = PetscMin(cend, N);
1556e6471dc9SStefano Zampini 
1557978814f1SStefano Zampini   /* create PETSc matrix with MatHYPRE */
15589566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, &T));
15599566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(T, rend - rstart, cend - cstart, M, N));
15609566063dSJacob Faibussowitsch   PetscCall(MatSetType(T, MATHYPRE));
1561225daaf8SStefano Zampini   hA = (Mat_HYPRE *)(T->data);
1562978814f1SStefano Zampini 
1563978814f1SStefano Zampini   /* create HYPRE_IJMatrix */
1564792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixCreate, hA->comm, rstart, rend - 1, cstart, cend - 1, &hA->ij);
1565792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixSetObjectType, hA->ij, HYPRE_PARCSR);
156645b8d346SStefano Zampini 
15676ea7df73SStefano Zampini   // TODO DEV
156845b8d346SStefano Zampini   /* create new ParCSR object if needed */
156945b8d346SStefano Zampini   if (ishyp && copymode == PETSC_COPY_VALUES) {
157045b8d346SStefano Zampini     hypre_ParCSRMatrix *new_parcsr;
15716ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 18, 0)
157245b8d346SStefano Zampini     hypre_CSRMatrix *hdiag, *hoffd, *ndiag, *noffd;
157345b8d346SStefano Zampini 
15740e6427aaSSatish Balay     new_parcsr = hypre_ParCSRMatrixClone(parcsr, 0);
157545b8d346SStefano Zampini     hdiag      = hypre_ParCSRMatrixDiag(parcsr);
157645b8d346SStefano Zampini     hoffd      = hypre_ParCSRMatrixOffd(parcsr);
157745b8d346SStefano Zampini     ndiag      = hypre_ParCSRMatrixDiag(new_parcsr);
157845b8d346SStefano Zampini     noffd      = hypre_ParCSRMatrixOffd(new_parcsr);
15799566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hypre_CSRMatrixData(ndiag), hypre_CSRMatrixData(hdiag), hypre_CSRMatrixNumNonzeros(hdiag)));
15809566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(hypre_CSRMatrixData(noffd), hypre_CSRMatrixData(hoffd), hypre_CSRMatrixNumNonzeros(hoffd)));
15816ea7df73SStefano Zampini #else
15826ea7df73SStefano Zampini     new_parcsr = hypre_ParCSRMatrixClone(parcsr, 1);
15836ea7df73SStefano Zampini #endif
158445b8d346SStefano Zampini     parcsr   = new_parcsr;
158545b8d346SStefano Zampini     copymode = PETSC_OWN_POINTER;
158645b8d346SStefano Zampini   }
1587978814f1SStefano Zampini 
1588978814f1SStefano Zampini   /* set ParCSR object */
1589978814f1SStefano Zampini   hypre_IJMatrixObject(hA->ij) = parcsr;
15904ec6421dSstefano_zampini   T->preallocated              = PETSC_TRUE;
1591978814f1SStefano Zampini 
1592978814f1SStefano Zampini   /* set assembled flag */
1593978814f1SStefano Zampini   hypre_IJMatrixAssembleFlag(hA->ij) = 1;
15946ea7df73SStefano Zampini #if 0
1595792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixInitialize,hA->ij);
15966ea7df73SStefano Zampini #endif
1597225daaf8SStefano Zampini   if (ishyp) {
15986d2a658fSstefano_zampini     PetscMPIInt myid = 0;
15996d2a658fSstefano_zampini 
16006d2a658fSstefano_zampini     /* make sure we always have row_starts and col_starts available */
160148a46eb9SPierre Jolivet     if (HYPRE_AssumedPartitionCheck()) PetscCallMPI(MPI_Comm_rank(comm, &myid));
1602a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
16036d2a658fSstefano_zampini     if (!hypre_ParCSRMatrixOwnsColStarts(parcsr)) {
16046d2a658fSstefano_zampini       PetscLayout map;
16056d2a658fSstefano_zampini 
16069566063dSJacob Faibussowitsch       PetscCall(MatGetLayouts(T, NULL, &map));
16079566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetUp(map));
16082cf14000SStefano Zampini       hypre_ParCSRMatrixColStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid);
16096d2a658fSstefano_zampini     }
16106d2a658fSstefano_zampini     if (!hypre_ParCSRMatrixOwnsRowStarts(parcsr)) {
16116d2a658fSstefano_zampini       PetscLayout map;
16126d2a658fSstefano_zampini 
16139566063dSJacob Faibussowitsch       PetscCall(MatGetLayouts(T, &map, NULL));
16149566063dSJacob Faibussowitsch       PetscCall(PetscLayoutSetUp(map));
16152cf14000SStefano Zampini       hypre_ParCSRMatrixRowStarts(parcsr) = (HYPRE_BigInt *)(map->range + myid);
16166d2a658fSstefano_zampini     }
1617a1d2239cSSatish Balay #endif
1618978814f1SStefano Zampini     /* prevent from freeing the pointer */
1619978814f1SStefano Zampini     if (copymode == PETSC_USE_POINTER) hA->inner_free = PETSC_FALSE;
1620225daaf8SStefano Zampini     *A = T;
16219566063dSJacob Faibussowitsch     PetscCall(MatSetOption(*A, MAT_SORTED_FULL, PETSC_TRUE));
16229566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(*A, MAT_FINAL_ASSEMBLY));
16239566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(*A, MAT_FINAL_ASSEMBLY));
1624bb4689ddSStefano Zampini   } else if (isaij) {
1625bb4689ddSStefano Zampini     if (copymode != PETSC_OWN_POINTER) {
1626225daaf8SStefano Zampini       /* prevent from freeing the pointer */
1627225daaf8SStefano Zampini       hA->inner_free = PETSC_FALSE;
16289566063dSJacob Faibussowitsch       PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INITIAL_MATRIX, A));
16299566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&T));
1630225daaf8SStefano Zampini     } else { /* AIJ return type with PETSC_OWN_POINTER */
16319566063dSJacob Faibussowitsch       PetscCall(MatConvert_HYPRE_AIJ(T, MATAIJ, MAT_INPLACE_MATRIX, &T));
1632225daaf8SStefano Zampini       *A = T;
1633225daaf8SStefano Zampini     }
1634bb4689ddSStefano Zampini   } else if (isis) {
16359566063dSJacob Faibussowitsch     PetscCall(MatConvert_HYPRE_IS(T, MATIS, MAT_INITIAL_MATRIX, A));
16368cfe8d00SStefano Zampini     if (copymode != PETSC_OWN_POINTER) hA->inner_free = PETSC_FALSE;
16379566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&T));
1638bb4689ddSStefano Zampini   }
1639978814f1SStefano Zampini   PetscFunctionReturn(0);
1640978814f1SStefano Zampini }
1641978814f1SStefano Zampini 
16429371c9d4SSatish Balay static PetscErrorCode MatHYPREGetParCSR_HYPRE(Mat A, hypre_ParCSRMatrix **parcsr) {
1643dd9c0a25Sstefano_zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1644dd9c0a25Sstefano_zampini   HYPRE_Int  type;
1645dd9c0a25Sstefano_zampini 
1646dd9c0a25Sstefano_zampini   PetscFunctionBegin;
164728b400f6SJacob Faibussowitsch   PetscCheck(hA->ij, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "HYPRE_IJMatrix not present");
1648792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObjectType, hA->ij, &type);
164908401ef6SPierre Jolivet   PetscCheck(type == HYPRE_PARCSR, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "HYPRE_IJMatrix is not of type HYPRE_PARCSR");
1650792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hA->ij, (void **)parcsr);
1651dd9c0a25Sstefano_zampini   PetscFunctionReturn(0);
1652dd9c0a25Sstefano_zampini }
1653dd9c0a25Sstefano_zampini 
1654dd9c0a25Sstefano_zampini /*
1655dd9c0a25Sstefano_zampini    MatHYPREGetParCSR - Gets the pointer to the ParCSR matrix
1656dd9c0a25Sstefano_zampini 
1657dd9c0a25Sstefano_zampini    Not collective
1658dd9c0a25Sstefano_zampini 
1659dd9c0a25Sstefano_zampini    Input Parameters:
1660dd9c0a25Sstefano_zampini +  A  - the MATHYPRE object
1661dd9c0a25Sstefano_zampini 
1662dd9c0a25Sstefano_zampini    Output Parameter:
1663dd9c0a25Sstefano_zampini .  parcsr  - the pointer to the hypre_ParCSRMatrix
1664dd9c0a25Sstefano_zampini 
1665dd9c0a25Sstefano_zampini    Level: intermediate
1666dd9c0a25Sstefano_zampini 
1667db781477SPatrick Sanan .seealso: `MatHYPRE`, `PetscCopyMode`
1668dd9c0a25Sstefano_zampini */
16699371c9d4SSatish Balay PetscErrorCode MatHYPREGetParCSR(Mat A, hypre_ParCSRMatrix **parcsr) {
1670dd9c0a25Sstefano_zampini   PetscFunctionBegin;
1671dd9c0a25Sstefano_zampini   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1672dd9c0a25Sstefano_zampini   PetscValidType(A, 1);
1673cac4c232SBarry Smith   PetscUseMethod(A, "MatHYPREGetParCSR_C", (Mat, hypre_ParCSRMatrix **), (A, parcsr));
1674dd9c0a25Sstefano_zampini   PetscFunctionReturn(0);
1675dd9c0a25Sstefano_zampini }
1676dd9c0a25Sstefano_zampini 
16779371c9d4SSatish Balay static PetscErrorCode MatMissingDiagonal_HYPRE(Mat A, PetscBool *missing, PetscInt *dd) {
167868ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
167968ec7858SStefano Zampini   hypre_CSRMatrix    *ha;
168068ec7858SStefano Zampini   PetscInt            rst;
168168ec7858SStefano Zampini 
168268ec7858SStefano Zampini   PetscFunctionBegin;
168308401ef6SPierre Jolivet   PetscCheck(A->rmap->n == A->cmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented with non-square diagonal blocks");
16849566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &rst, NULL));
16859566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
168668ec7858SStefano Zampini   if (missing) *missing = PETSC_FALSE;
168768ec7858SStefano Zampini   if (dd) *dd = -1;
168868ec7858SStefano Zampini   ha = hypre_ParCSRMatrixDiag(parcsr);
168968ec7858SStefano Zampini   if (ha) {
169068299464SStefano Zampini     PetscInt   size, i;
169168299464SStefano Zampini     HYPRE_Int *ii, *jj;
169268ec7858SStefano Zampini 
169368ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
169468ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
169568ec7858SStefano Zampini     jj   = hypre_CSRMatrixJ(ha);
169668ec7858SStefano Zampini     for (i = 0; i < size; i++) {
169768ec7858SStefano Zampini       PetscInt  j;
169868ec7858SStefano Zampini       PetscBool found = PETSC_FALSE;
169968ec7858SStefano Zampini 
17009371c9d4SSatish Balay       for (j = ii[i]; j < ii[i + 1] && !found; j++) found = (jj[j] == i) ? PETSC_TRUE : PETSC_FALSE;
170168ec7858SStefano Zampini 
170268ec7858SStefano Zampini       if (!found) {
17037d3de750SJacob Faibussowitsch         PetscInfo(A, "Matrix is missing local diagonal entry %" PetscInt_FMT "\n", i);
170468ec7858SStefano Zampini         if (missing) *missing = PETSC_TRUE;
170568ec7858SStefano Zampini         if (dd) *dd = i + rst;
170668ec7858SStefano Zampini         PetscFunctionReturn(0);
170768ec7858SStefano Zampini       }
170868ec7858SStefano Zampini     }
170968ec7858SStefano Zampini     if (!size) {
171068ec7858SStefano Zampini       PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n");
171168ec7858SStefano Zampini       if (missing) *missing = PETSC_TRUE;
171268ec7858SStefano Zampini       if (dd) *dd = rst;
171368ec7858SStefano Zampini     }
171468ec7858SStefano Zampini   } else {
171568ec7858SStefano Zampini     PetscInfo(A, "Matrix has no diagonal entries therefore is missing diagonal\n");
171668ec7858SStefano Zampini     if (missing) *missing = PETSC_TRUE;
171768ec7858SStefano Zampini     if (dd) *dd = rst;
171868ec7858SStefano Zampini   }
171968ec7858SStefano Zampini   PetscFunctionReturn(0);
172068ec7858SStefano Zampini }
172168ec7858SStefano Zampini 
17229371c9d4SSatish Balay static PetscErrorCode MatScale_HYPRE(Mat A, PetscScalar s) {
172368ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
17246ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2, 19, 0)
172568ec7858SStefano Zampini   hypre_CSRMatrix *ha;
17266ea7df73SStefano Zampini #endif
172739accc25SStefano Zampini   HYPRE_Complex hs;
172868ec7858SStefano Zampini 
172968ec7858SStefano Zampini   PetscFunctionBegin;
17309566063dSJacob Faibussowitsch   PetscCall(PetscHYPREScalarCast(s, &hs));
17319566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
17326ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2, 19, 0)
1733792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixScale, parcsr, hs);
17346ea7df73SStefano Zampini #else /* diagonal part */
173568ec7858SStefano Zampini   ha = hypre_ParCSRMatrixDiag(parcsr);
173668ec7858SStefano Zampini   if (ha) {
173768299464SStefano Zampini     PetscInt size, i;
173868299464SStefano Zampini     HYPRE_Int *ii;
173939accc25SStefano Zampini     HYPRE_Complex *a;
174068ec7858SStefano Zampini 
174168ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
174268ec7858SStefano Zampini     a = hypre_CSRMatrixData(ha);
174368ec7858SStefano Zampini     ii = hypre_CSRMatrixI(ha);
174439accc25SStefano Zampini     for (i = 0; i < ii[size]; i++) a[i] *= hs;
174568ec7858SStefano Zampini   }
174668ec7858SStefano Zampini   /* offdiagonal part */
174768ec7858SStefano Zampini   ha = hypre_ParCSRMatrixOffd(parcsr);
174868ec7858SStefano Zampini   if (ha) {
174968299464SStefano Zampini     PetscInt size, i;
175068299464SStefano Zampini     HYPRE_Int *ii;
175139accc25SStefano Zampini     HYPRE_Complex *a;
175268ec7858SStefano Zampini 
175368ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
175468ec7858SStefano Zampini     a = hypre_CSRMatrixData(ha);
175568ec7858SStefano Zampini     ii = hypre_CSRMatrixI(ha);
175639accc25SStefano Zampini     for (i = 0; i < ii[size]; i++) a[i] *= hs;
175768ec7858SStefano Zampini   }
17586ea7df73SStefano Zampini #endif
175968ec7858SStefano Zampini   PetscFunctionReturn(0);
176068ec7858SStefano Zampini }
176168ec7858SStefano Zampini 
17629371c9d4SSatish Balay static PetscErrorCode MatZeroRowsColumns_HYPRE(Mat A, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) {
176368ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
176468299464SStefano Zampini   HYPRE_Int          *lrows;
176568299464SStefano Zampini   PetscInt            rst, ren, i;
176668ec7858SStefano Zampini 
176768ec7858SStefano Zampini   PetscFunctionBegin;
176808401ef6SPierre Jolivet   PetscCheck(!x && !b, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "To be implemented");
17699566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
17709566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numRows, &lrows));
17719566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &rst, &ren));
177268ec7858SStefano Zampini   for (i = 0; i < numRows; i++) {
17737a46b595SBarry Smith     PetscCheck(rows[i] >= rst && rows[i] < ren, PETSC_COMM_SELF, PETSC_ERR_SUP, "Non-local rows not yet supported");
177468ec7858SStefano Zampini     lrows[i] = rows[i] - rst;
177568ec7858SStefano Zampini   }
1776792fecdfSBarry Smith   PetscCallExternal(hypre_ParCSRMatrixEliminateRowsCols, parcsr, numRows, lrows);
17779566063dSJacob Faibussowitsch   PetscCall(PetscFree(lrows));
177868ec7858SStefano Zampini   PetscFunctionReturn(0);
177968ec7858SStefano Zampini }
178068ec7858SStefano Zampini 
17819371c9d4SSatish Balay static PetscErrorCode MatZeroEntries_HYPRE_CSRMatrix(hypre_CSRMatrix *ha) {
1782c69f721fSFande Kong   PetscFunctionBegin;
1783c69f721fSFande Kong   if (ha) {
1784c69f721fSFande Kong     HYPRE_Int     *ii, size;
1785c69f721fSFande Kong     HYPRE_Complex *a;
1786c69f721fSFande Kong 
1787c69f721fSFande Kong     size = hypre_CSRMatrixNumRows(ha);
1788c69f721fSFande Kong     a    = hypre_CSRMatrixData(ha);
1789c69f721fSFande Kong     ii   = hypre_CSRMatrixI(ha);
1790c69f721fSFande Kong 
17919566063dSJacob Faibussowitsch     if (a) PetscCall(PetscArrayzero(a, ii[size]));
1792c69f721fSFande Kong   }
1793c69f721fSFande Kong   PetscFunctionReturn(0);
1794c69f721fSFande Kong }
1795c69f721fSFande Kong 
17969371c9d4SSatish Balay PetscErrorCode MatZeroEntries_HYPRE(Mat A) {
17976ea7df73SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
17986ea7df73SStefano Zampini 
17996ea7df73SStefano Zampini   PetscFunctionBegin;
18006ea7df73SStefano Zampini   if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(hA->ij)) {
1801792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixSetConstantValues, hA->ij, 0.0);
18026ea7df73SStefano Zampini   } else {
1803c69f721fSFande Kong     hypre_ParCSRMatrix *parcsr;
1804c69f721fSFande Kong 
18059566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
18069566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr)));
18079566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr)));
18086ea7df73SStefano Zampini   }
1809c69f721fSFande Kong   PetscFunctionReturn(0);
1810c69f721fSFande Kong }
1811c69f721fSFande Kong 
18129371c9d4SSatish Balay static PetscErrorCode MatZeroRows_HYPRE_CSRMatrix(hypre_CSRMatrix *hA, PetscInt N, const PetscInt rows[], HYPRE_Complex diag) {
181339accc25SStefano Zampini   PetscInt       ii;
181439accc25SStefano Zampini   HYPRE_Int     *i, *j;
181539accc25SStefano Zampini   HYPRE_Complex *a;
1816c69f721fSFande Kong 
1817c69f721fSFande Kong   PetscFunctionBegin;
1818c69f721fSFande Kong   if (!hA) PetscFunctionReturn(0);
1819c69f721fSFande Kong 
182039accc25SStefano Zampini   i = hypre_CSRMatrixI(hA);
182139accc25SStefano Zampini   j = hypre_CSRMatrixJ(hA);
1822c69f721fSFande Kong   a = hypre_CSRMatrixData(hA);
1823c69f721fSFande Kong 
1824c69f721fSFande Kong   for (ii = 0; ii < N; ii++) {
182539accc25SStefano Zampini     HYPRE_Int jj, ibeg, iend, irow;
182639accc25SStefano Zampini 
1827c69f721fSFande Kong     irow = rows[ii];
1828c69f721fSFande Kong     ibeg = i[irow];
1829c69f721fSFande Kong     iend = i[irow + 1];
1830c69f721fSFande Kong     for (jj = ibeg; jj < iend; jj++)
1831c69f721fSFande Kong       if (j[jj] == irow) a[jj] = diag;
1832c69f721fSFande Kong       else a[jj] = 0.0;
1833c69f721fSFande Kong   }
1834c69f721fSFande Kong   PetscFunctionReturn(0);
1835c69f721fSFande Kong }
1836c69f721fSFande Kong 
18379371c9d4SSatish Balay static PetscErrorCode MatZeroRows_HYPRE(Mat A, PetscInt N, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) {
1838c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
1839c69f721fSFande Kong   PetscInt           *lrows, len;
184039accc25SStefano Zampini   HYPRE_Complex       hdiag;
1841c69f721fSFande Kong 
1842c69f721fSFande Kong   PetscFunctionBegin;
184308401ef6SPierre Jolivet   PetscCheck(!x && !b, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Does not support to modify the solution and the right hand size");
18449566063dSJacob Faibussowitsch   PetscCall(PetscHYPREScalarCast(diag, &hdiag));
1845c69f721fSFande Kong   /* retrieve the internal matrix */
18469566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
1847c69f721fSFande Kong   /* get locally owned rows */
18489566063dSJacob Faibussowitsch   PetscCall(MatZeroRowsMapLocal_Private(A, N, rows, &len, &lrows));
1849c69f721fSFande Kong   /* zero diagonal part */
18509566063dSJacob Faibussowitsch   PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr), len, lrows, hdiag));
1851c69f721fSFande Kong   /* zero off-diagonal part */
18529566063dSJacob Faibussowitsch   PetscCall(MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr), len, lrows, 0.0));
1853c69f721fSFande Kong 
18549566063dSJacob Faibussowitsch   PetscCall(PetscFree(lrows));
1855c69f721fSFande Kong   PetscFunctionReturn(0);
1856c69f721fSFande Kong }
1857c69f721fSFande Kong 
18589371c9d4SSatish Balay static PetscErrorCode MatAssemblyBegin_HYPRE(Mat mat, MatAssemblyType mode) {
1859c69f721fSFande Kong   PetscFunctionBegin;
1860c69f721fSFande Kong   if (mat->nooffprocentries) PetscFunctionReturn(0);
1861c69f721fSFande Kong 
18629566063dSJacob Faibussowitsch   PetscCall(MatStashScatterBegin_Private(mat, &mat->stash, mat->rmap->range));
1863c69f721fSFande Kong   PetscFunctionReturn(0);
1864c69f721fSFande Kong }
1865c69f721fSFande Kong 
18669371c9d4SSatish Balay static PetscErrorCode MatGetRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) {
1867c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
18682cf14000SStefano Zampini   HYPRE_Int           hnz;
1869c69f721fSFande Kong 
1870c69f721fSFande Kong   PetscFunctionBegin;
1871c69f721fSFande Kong   /* retrieve the internal matrix */
18729566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
1873c69f721fSFande Kong   /* call HYPRE API */
1874792fecdfSBarry Smith   PetscCallExternal(HYPRE_ParCSRMatrixGetRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v);
18752cf14000SStefano Zampini   if (nz) *nz = (PetscInt)hnz;
1876c69f721fSFande Kong   PetscFunctionReturn(0);
1877c69f721fSFande Kong }
1878c69f721fSFande Kong 
18799371c9d4SSatish Balay static PetscErrorCode MatRestoreRow_HYPRE(Mat A, PetscInt row, PetscInt *nz, PetscInt **idx, PetscScalar **v) {
1880c69f721fSFande Kong   hypre_ParCSRMatrix *parcsr;
18812cf14000SStefano Zampini   HYPRE_Int           hnz;
1882c69f721fSFande Kong 
1883c69f721fSFande Kong   PetscFunctionBegin;
1884c69f721fSFande Kong   /* retrieve the internal matrix */
18859566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
1886c69f721fSFande Kong   /* call HYPRE API */
18872cf14000SStefano Zampini   hnz = nz ? (HYPRE_Int)(*nz) : 0;
1888792fecdfSBarry Smith   PetscCallExternal(HYPRE_ParCSRMatrixRestoreRow, parcsr, row, &hnz, (HYPRE_BigInt **)idx, (HYPRE_Complex **)v);
1889c69f721fSFande Kong   PetscFunctionReturn(0);
1890c69f721fSFande Kong }
1891c69f721fSFande Kong 
18929371c9d4SSatish Balay static PetscErrorCode MatGetValues_HYPRE(Mat A, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) {
189345b8d346SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1894c69f721fSFande Kong   PetscInt   i;
18951d4906efSStefano Zampini 
1896c69f721fSFande Kong   PetscFunctionBegin;
1897c69f721fSFande Kong   if (!m || !n) PetscFunctionReturn(0);
1898c69f721fSFande Kong   /* Ignore negative row indices
1899c69f721fSFande Kong    * And negative column indices should be automatically ignored in hypre
1900c69f721fSFande Kong    * */
19012cf14000SStefano Zampini   for (i = 0; i < m; i++) {
19022cf14000SStefano Zampini     if (idxm[i] >= 0) {
19032cf14000SStefano Zampini       HYPRE_Int hn = (HYPRE_Int)n;
1904792fecdfSBarry Smith       PetscCallExternal(HYPRE_IJMatrixGetValues, hA->ij, 1, &hn, (HYPRE_BigInt *)&idxm[i], (HYPRE_BigInt *)idxn, (HYPRE_Complex *)(v + i * n));
19052cf14000SStefano Zampini     }
19062cf14000SStefano Zampini   }
1907c69f721fSFande Kong   PetscFunctionReturn(0);
1908c69f721fSFande Kong }
1909c69f721fSFande Kong 
19109371c9d4SSatish Balay static PetscErrorCode MatSetOption_HYPRE(Mat A, MatOption op, PetscBool flg) {
1911ddbeb582SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE *)A->data;
1912ddbeb582SStefano Zampini 
1913ddbeb582SStefano Zampini   PetscFunctionBegin;
1914c6698e78SStefano Zampini   switch (op) {
1915ddbeb582SStefano Zampini   case MAT_NO_OFF_PROC_ENTRIES:
191648a46eb9SPierre Jolivet     if (flg) PetscCallExternal(HYPRE_IJMatrixSetMaxOffProcElmts, hA->ij, 0);
1917ddbeb582SStefano Zampini     break;
19189371c9d4SSatish Balay   case MAT_SORTED_FULL: hA->sorted_full = flg; break;
19199371c9d4SSatish Balay   default: break;
1920ddbeb582SStefano Zampini   }
1921ddbeb582SStefano Zampini   PetscFunctionReturn(0);
1922ddbeb582SStefano Zampini }
1923c69f721fSFande Kong 
19249371c9d4SSatish Balay static PetscErrorCode MatView_HYPRE(Mat A, PetscViewer view) {
192545b8d346SStefano Zampini   PetscViewerFormat format;
192645b8d346SStefano Zampini 
192745b8d346SStefano Zampini   PetscFunctionBegin;
19289566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(view, &format));
19296ea7df73SStefano Zampini   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(0);
193045b8d346SStefano Zampini   if (format != PETSC_VIEWER_NATIVE) {
19316ea7df73SStefano Zampini     Mat                 B;
19326ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
19336ea7df73SStefano Zampini     PetscErrorCode (*mview)(Mat, PetscViewer) = NULL;
19346ea7df73SStefano Zampini 
19359566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
19369566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(parcsr, MATAIJ, PETSC_USE_POINTER, &B));
19379566063dSJacob Faibussowitsch     PetscCall(MatGetOperation(B, MATOP_VIEW, (void (**)(void)) & mview));
193828b400f6SJacob Faibussowitsch     PetscCheck(mview, PetscObjectComm((PetscObject)A), PETSC_ERR_PLIB, "Missing view operation");
19399566063dSJacob Faibussowitsch     PetscCall((*mview)(B, view));
19409566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&B));
194145b8d346SStefano Zampini   } else {
194245b8d346SStefano Zampini     Mat_HYPRE  *hA = (Mat_HYPRE *)A->data;
194345b8d346SStefano Zampini     PetscMPIInt size;
194445b8d346SStefano Zampini     PetscBool   isascii;
194545b8d346SStefano Zampini     const char *filename;
194645b8d346SStefano Zampini 
194745b8d346SStefano Zampini     /* HYPRE uses only text files */
19489566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERASCII, &isascii));
194928b400f6SJacob Faibussowitsch     PetscCheck(isascii, PetscObjectComm((PetscObject)view), PETSC_ERR_SUP, "PetscViewerType %s: native HYPRE format needs PETSCVIEWERASCII", ((PetscObject)view)->type_name);
19509566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileGetName(view, &filename));
1951792fecdfSBarry Smith     PetscCallExternal(HYPRE_IJMatrixPrint, hA->ij, filename);
19529566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(hA->comm, &size));
195345b8d346SStefano Zampini     if (size > 1) {
19549566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(view, "Matrix files: %s.%05d ... %s.%05d\n", filename, 0, filename, size - 1));
195545b8d346SStefano Zampini     } else {
19569566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(view, "Matrix file: %s.%05d\n", filename, 0));
195745b8d346SStefano Zampini     }
195845b8d346SStefano Zampini   }
195945b8d346SStefano Zampini   PetscFunctionReturn(0);
196045b8d346SStefano Zampini }
196145b8d346SStefano Zampini 
19629371c9d4SSatish Balay static PetscErrorCode MatDuplicate_HYPRE(Mat A, MatDuplicateOption op, Mat *B) {
19636abb4441SStefano Zampini   hypre_ParCSRMatrix *parcsr = NULL;
196445b8d346SStefano Zampini   PetscCopyMode       cpmode;
196545b8d346SStefano Zampini 
196645b8d346SStefano Zampini   PetscFunctionBegin;
19679566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
196845b8d346SStefano Zampini   if (op == MAT_DO_NOT_COPY_VALUES || op == MAT_SHARE_NONZERO_PATTERN) {
19690e6427aaSSatish Balay     parcsr = hypre_ParCSRMatrixClone(parcsr, 0);
197045b8d346SStefano Zampini     cpmode = PETSC_OWN_POINTER;
197145b8d346SStefano Zampini   } else {
197245b8d346SStefano Zampini     cpmode = PETSC_COPY_VALUES;
197345b8d346SStefano Zampini   }
19749566063dSJacob Faibussowitsch   PetscCall(MatCreateFromParCSR(parcsr, MATHYPRE, cpmode, B));
197545b8d346SStefano Zampini   PetscFunctionReturn(0);
197645b8d346SStefano Zampini }
197745b8d346SStefano Zampini 
19789371c9d4SSatish Balay static PetscErrorCode MatCopy_HYPRE(Mat A, Mat B, MatStructure str) {
1979465edc17SStefano Zampini   hypre_ParCSRMatrix *acsr, *bcsr;
1980465edc17SStefano Zampini 
1981465edc17SStefano Zampini   PetscFunctionBegin;
1982465edc17SStefano Zampini   if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) {
19839566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(A, &acsr));
19849566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR_HYPRE(B, &bcsr));
1985792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixCopy, acsr, bcsr, 1);
19869566063dSJacob Faibussowitsch     PetscCall(MatSetOption(B, MAT_SORTED_FULL, PETSC_TRUE)); /* "perfect" preallocation, so no need for hypre_AuxParCSRMatrixNeedAux */
19879566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
19889566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
1989465edc17SStefano Zampini   } else {
19909566063dSJacob Faibussowitsch     PetscCall(MatCopy_Basic(A, B, str));
1991465edc17SStefano Zampini   }
1992465edc17SStefano Zampini   PetscFunctionReturn(0);
1993465edc17SStefano Zampini }
1994465edc17SStefano Zampini 
19959371c9d4SSatish Balay static PetscErrorCode MatGetDiagonal_HYPRE(Mat A, Vec d) {
19966305df00SStefano Zampini   hypre_ParCSRMatrix *parcsr;
19976305df00SStefano Zampini   hypre_CSRMatrix    *dmat;
199839accc25SStefano Zampini   HYPRE_Complex      *a;
199939accc25SStefano Zampini   HYPRE_Complex      *data = NULL;
20002cf14000SStefano Zampini   HYPRE_Int          *diag = NULL;
20012cf14000SStefano Zampini   PetscInt            i;
20026305df00SStefano Zampini   PetscBool           cong;
20036305df00SStefano Zampini 
20046305df00SStefano Zampini   PetscFunctionBegin;
20059566063dSJacob Faibussowitsch   PetscCall(MatHasCongruentLayouts(A, &cong));
200628b400f6SJacob Faibussowitsch   PetscCheck(cong, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Only for square matrices with same local distributions of rows and columns");
200776bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
20086305df00SStefano Zampini     PetscBool miss;
20099566063dSJacob Faibussowitsch     PetscCall(MatMissingDiagonal(A, &miss, NULL));
201008401ef6SPierre Jolivet     PetscCheck(!miss || !A->rmap->n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented when diagonal entries are missing");
20116305df00SStefano Zampini   }
20129566063dSJacob Faibussowitsch   PetscCall(MatHYPREGetParCSR_HYPRE(A, &parcsr));
20136305df00SStefano Zampini   dmat = hypre_ParCSRMatrixDiag(parcsr);
20146305df00SStefano Zampini   if (dmat) {
201539accc25SStefano Zampini     /* this cast fixes the clang error: implicit conversion from 'HYPRE_Complex' (aka '_Complex double') to 'double' is not permitted in C++ */
20169566063dSJacob Faibussowitsch     PetscCall(VecGetArray(d, (PetscScalar **)&a));
20172cf14000SStefano Zampini     diag = hypre_CSRMatrixI(dmat);
201839accc25SStefano Zampini     data = hypre_CSRMatrixData(dmat);
20196305df00SStefano Zampini     for (i = 0; i < A->rmap->n; i++) a[i] = data[diag[i]];
20209566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(d, (PetscScalar **)&a));
20216305df00SStefano Zampini   }
20226305df00SStefano Zampini   PetscFunctionReturn(0);
20236305df00SStefano Zampini }
20246305df00SStefano Zampini 
2025363d496dSStefano Zampini #include <petscblaslapack.h>
2026363d496dSStefano Zampini 
20279371c9d4SSatish Balay static PetscErrorCode MatAXPY_HYPRE(Mat Y, PetscScalar a, Mat X, MatStructure str) {
2028363d496dSStefano Zampini   PetscFunctionBegin;
20296ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
20306ea7df73SStefano Zampini   {
20316ea7df73SStefano Zampini     Mat                 B;
20326ea7df73SStefano Zampini     hypre_ParCSRMatrix *x, *y, *z;
20336ea7df73SStefano Zampini 
20349566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(Y, &y));
20359566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(X, &x));
2036792fecdfSBarry Smith     PetscCallExternal(hypre_ParCSRMatrixAdd, 1.0, y, 1.0, x, &z);
20379566063dSJacob Faibussowitsch     PetscCall(MatCreateFromParCSR(z, MATHYPRE, PETSC_OWN_POINTER, &B));
20389566063dSJacob Faibussowitsch     PetscCall(MatHeaderMerge(Y, &B));
20396ea7df73SStefano Zampini   }
20406ea7df73SStefano Zampini #else
2041363d496dSStefano Zampini   if (str == SAME_NONZERO_PATTERN) {
2042363d496dSStefano Zampini     hypre_ParCSRMatrix *x, *y;
2043363d496dSStefano Zampini     hypre_CSRMatrix *xloc, *yloc;
2044363d496dSStefano Zampini     PetscInt xnnz, ynnz;
204539accc25SStefano Zampini     HYPRE_Complex *xarr, *yarr;
2046363d496dSStefano Zampini     PetscBLASInt one = 1, bnz;
2047363d496dSStefano Zampini 
20489566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(Y, &y));
20499566063dSJacob Faibussowitsch     PetscCall(MatHYPREGetParCSR(X, &x));
2050363d496dSStefano Zampini 
2051363d496dSStefano Zampini     /* diagonal block */
2052363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixDiag(x);
2053363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixDiag(y);
2054363d496dSStefano Zampini     xnnz = 0;
2055363d496dSStefano Zampini     ynnz = 0;
2056363d496dSStefano Zampini     xarr = NULL;
2057363d496dSStefano Zampini     yarr = NULL;
2058363d496dSStefano Zampini     if (xloc) {
205939accc25SStefano Zampini       xarr = hypre_CSRMatrixData(xloc);
2060363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
2061363d496dSStefano Zampini     }
2062363d496dSStefano Zampini     if (yloc) {
206339accc25SStefano Zampini       yarr = hypre_CSRMatrixData(yloc);
2064363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
2065363d496dSStefano Zampini     }
206608401ef6SPierre Jolivet     PetscCheck(xnnz == ynnz, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Different number of nonzeros in diagonal block %" PetscInt_FMT " != %" PetscInt_FMT, xnnz, ynnz);
20679566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(xnnz, &bnz));
2068792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one));
2069363d496dSStefano Zampini 
2070363d496dSStefano Zampini     /* off-diagonal block */
2071363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixOffd(x);
2072363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixOffd(y);
2073363d496dSStefano Zampini     xnnz = 0;
2074363d496dSStefano Zampini     ynnz = 0;
2075363d496dSStefano Zampini     xarr = NULL;
2076363d496dSStefano Zampini     yarr = NULL;
2077363d496dSStefano Zampini     if (xloc) {
207839accc25SStefano Zampini       xarr = hypre_CSRMatrixData(xloc);
2079363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
2080363d496dSStefano Zampini     }
2081363d496dSStefano Zampini     if (yloc) {
208239accc25SStefano Zampini       yarr = hypre_CSRMatrixData(yloc);
2083363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
2084363d496dSStefano Zampini     }
208508401ef6SPierre 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);
20869566063dSJacob Faibussowitsch     PetscCall(PetscBLASIntCast(xnnz, &bnz));
2087792fecdfSBarry Smith     PetscCallBLAS("BLASaxpy", BLASaxpy_(&bnz, &a, (PetscScalar *)xarr, &one, (PetscScalar *)yarr, &one));
2088363d496dSStefano Zampini   } else if (str == SUBSET_NONZERO_PATTERN) {
20899566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic(Y, a, X, str));
2090363d496dSStefano Zampini   } else {
2091363d496dSStefano Zampini     Mat B;
2092363d496dSStefano Zampini 
20939566063dSJacob Faibussowitsch     PetscCall(MatAXPY_Basic_Preallocate(Y, X, &B));
20949566063dSJacob Faibussowitsch     PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str));
20959566063dSJacob Faibussowitsch     PetscCall(MatHeaderReplace(Y, &B));
2096363d496dSStefano Zampini   }
20976ea7df73SStefano Zampini #endif
2098363d496dSStefano Zampini   PetscFunctionReturn(0);
2099363d496dSStefano Zampini }
2100363d496dSStefano Zampini 
21019371c9d4SSatish Balay static PetscErrorCode MatSetPreallocationCOO_HYPRE(Mat mat, PetscCount coo_n, PetscInt coo_i[], PetscInt coo_j[]) {
21025fbaff96SJunchao Zhang   MPI_Comm             comm;
21035fbaff96SJunchao Zhang   PetscMPIInt          size;
21045fbaff96SJunchao Zhang   PetscLayout          rmap, cmap;
21055fbaff96SJunchao Zhang   Mat_HYPRE           *hmat;
21065fbaff96SJunchao Zhang   hypre_ParCSRMatrix  *parCSR;
21075fbaff96SJunchao Zhang   hypre_CSRMatrix     *diag, *offd;
21085fbaff96SJunchao Zhang   Mat                  A, B, cooMat;
21095fbaff96SJunchao Zhang   PetscScalar         *Aa, *Ba;
21105fbaff96SJunchao Zhang   HYPRE_MemoryLocation hypreMemtype = HYPRE_MEMORY_HOST;
21115fbaff96SJunchao Zhang   PetscMemType         petscMemtype;
21125fbaff96SJunchao Zhang   MatType              matType = MATAIJ; /* default type of cooMat */
21135fbaff96SJunchao Zhang 
21145fbaff96SJunchao Zhang   PetscFunctionBegin;
21155fbaff96SJunchao Zhang   /* Build an agent matrix cooMat whose type is either MATAIJ or MATAIJKOKKOS.
21165fbaff96SJunchao 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.
21175fbaff96SJunchao Zhang    */
21185fbaff96SJunchao Zhang   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
21195fbaff96SJunchao Zhang   PetscCallMPI(MPI_Comm_size(comm, &size));
21205fbaff96SJunchao Zhang   PetscCall(PetscLayoutSetUp(mat->rmap));
21215fbaff96SJunchao Zhang   PetscCall(PetscLayoutSetUp(mat->cmap));
21225fbaff96SJunchao Zhang   PetscCall(MatGetLayouts(mat, &rmap, &cmap));
21235fbaff96SJunchao Zhang 
21245fbaff96SJunchao Zhang   /* I do not know how hypre_ParCSRMatrix stores diagonal elements for non-square matrices, so I just give up now */
21255fbaff96SJunchao Zhang   PetscCheck(rmap->N == cmap->N, comm, PETSC_ERR_SUP, "MATHYPRE COO cannot handle non-square matrices");
21265fbaff96SJunchao Zhang 
21275fbaff96SJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
21285fbaff96SJunchao Zhang   if (!mat->boundtocpu) { /* mat will be on device, so will cooMat */
21295fbaff96SJunchao Zhang #if defined(PETSC_HAVE_KOKKOS)
21305fbaff96SJunchao Zhang     matType = MATAIJKOKKOS;
21315fbaff96SJunchao Zhang #else
21325fbaff96SJunchao Zhang     SETERRQ(comm, PETSC_ERR_SUP, "To support MATHYPRE COO assembly on device, we need Kokkos, e.g., --download-kokkos --download-kokkos-kernels");
21335fbaff96SJunchao Zhang #endif
21345fbaff96SJunchao Zhang   }
21355fbaff96SJunchao Zhang #endif
21365fbaff96SJunchao Zhang 
21375fbaff96SJunchao Zhang   /* Do COO preallocation through cooMat */
21385fbaff96SJunchao Zhang   hmat = (Mat_HYPRE *)mat->data;
21395fbaff96SJunchao Zhang   PetscCall(MatDestroy(&hmat->cooMat));
21405fbaff96SJunchao Zhang   PetscCall(MatCreate(comm, &cooMat));
21415fbaff96SJunchao Zhang   PetscCall(MatSetType(cooMat, matType));
21425fbaff96SJunchao Zhang   PetscCall(MatSetLayouts(cooMat, rmap, cmap));
21435fbaff96SJunchao Zhang   PetscCall(MatSetPreallocationCOO(cooMat, coo_n, coo_i, coo_j));
21445fbaff96SJunchao Zhang 
21455fbaff96SJunchao Zhang   /* Copy the sparsity pattern from cooMat to hypre IJMatrix hmat->ij */
21465fbaff96SJunchao Zhang   PetscCall(MatSetOption(mat, MAT_SORTED_FULL, PETSC_TRUE));
21475fbaff96SJunchao Zhang   PetscCall(MatSetOption(mat, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE));
21485fbaff96SJunchao Zhang   PetscCall(MatHYPRE_CreateFromMat(cooMat, hmat));    /* Create hmat->ij and preallocate it */
21495fbaff96SJunchao Zhang   PetscCall(MatHYPRE_IJMatrixCopy(cooMat, hmat->ij)); /* Copy A's (a,i,j) to hmat->ij. To reuse code. Copying 'a' is not really needed */
21505fbaff96SJunchao Zhang 
21515fbaff96SJunchao Zhang   mat->preallocated = PETSC_TRUE;
21525fbaff96SJunchao Zhang   PetscCall(MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY));
21535fbaff96SJunchao Zhang   PetscCall(MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY)); /* Migrate mat to device if it is bound to. Hypre builds its own SpMV context here */
21545fbaff96SJunchao Zhang 
21555fbaff96SJunchao Zhang   /* Alias cooMat's data array to IJMatrix's */
2156792fecdfSBarry Smith   PetscCallExternal(HYPRE_IJMatrixGetObject, hmat->ij, (void **)&parCSR);
21575fbaff96SJunchao Zhang   diag = hypre_ParCSRMatrixDiag(parCSR);
21585fbaff96SJunchao Zhang   offd = hypre_ParCSRMatrixOffd(parCSR);
21595fbaff96SJunchao Zhang 
21605fbaff96SJunchao Zhang   hypreMemtype = hypre_CSRMatrixMemoryLocation(diag);
21615fbaff96SJunchao Zhang   A            = (size == 1) ? cooMat : ((Mat_MPIAIJ *)cooMat->data)->A;
21625fbaff96SJunchao Zhang   PetscCall(MatSeqAIJGetCSRAndMemType(A, NULL, NULL, &Aa, &petscMemtype));
21639371c9d4SSatish Balay   PetscAssert((PetscMemTypeHost(petscMemtype) && hypreMemtype == HYPRE_MEMORY_HOST) || (PetscMemTypeDevice(petscMemtype) && hypreMemtype == HYPRE_MEMORY_DEVICE), comm, PETSC_ERR_PLIB, "PETSc and hypre's memory types mismatch");
21645fbaff96SJunchao Zhang 
21655fbaff96SJunchao Zhang   hmat->diagJ = hypre_CSRMatrixJ(diag);
2166e77caa6dSBarry Smith   PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(diag), hypreMemtype));
21675fbaff96SJunchao Zhang   hypre_CSRMatrixData(diag)     = (HYPRE_Complex *)Aa;
21685fbaff96SJunchao Zhang   hypre_CSRMatrixOwnsData(diag) = 0; /* Take ownership of (j,a) away from hypre. As a result, we need to free them on our own */
21695fbaff96SJunchao Zhang 
21705fbaff96SJunchao Zhang   /* Copy diagonal pointers of A to device to facilitate MatSeqAIJMoveDiagonalValuesFront_SeqAIJKokkos */
21715fbaff96SJunchao Zhang   if (hypreMemtype == HYPRE_MEMORY_DEVICE) {
2172e77caa6dSBarry Smith     PetscStackCallExternalVoid("hypre_TAlloc", hmat->diag = hypre_TAlloc(PetscInt, rmap->n, hypreMemtype));
21735fbaff96SJunchao Zhang     PetscCall(MatMarkDiagonal_SeqAIJ(A)); /* We need updated diagonal positions */
2174e77caa6dSBarry Smith     PetscStackCallExternalVoid("hypre_TMemcpy", hypre_TMemcpy(hmat->diag, ((Mat_SeqAIJ *)A->data)->diag, PetscInt, rmap->n, hypreMemtype, HYPRE_MEMORY_HOST));
21755fbaff96SJunchao Zhang   }
21765fbaff96SJunchao Zhang 
21775fbaff96SJunchao Zhang   if (size > 1) {
21785fbaff96SJunchao Zhang     B = ((Mat_MPIAIJ *)cooMat->data)->B;
21795fbaff96SJunchao Zhang     PetscCall(MatSeqAIJGetCSRAndMemType(B, NULL, NULL, &Ba, &petscMemtype));
21805fbaff96SJunchao Zhang     hmat->offdJ = hypre_CSRMatrixJ(offd);
2181e77caa6dSBarry Smith     PetscStackCallExternalVoid("hypre_TFree", hypre_TFree(hypre_CSRMatrixData(offd), hypreMemtype));
21825fbaff96SJunchao Zhang     hypre_CSRMatrixData(offd)     = (HYPRE_Complex *)Ba;
21835fbaff96SJunchao Zhang     hypre_CSRMatrixOwnsData(offd) = 0;
21845fbaff96SJunchao Zhang   }
21855fbaff96SJunchao Zhang 
21865fbaff96SJunchao Zhang   /* Record cooMat for use in MatSetValuesCOO_HYPRE */
21875fbaff96SJunchao Zhang   hmat->cooMat  = cooMat;
21885fbaff96SJunchao Zhang   hmat->memType = hypreMemtype;
21895fbaff96SJunchao Zhang   PetscFunctionReturn(0);
21905fbaff96SJunchao Zhang }
21915fbaff96SJunchao Zhang 
21929371c9d4SSatish Balay static PetscErrorCode MatSetValuesCOO_HYPRE(Mat mat, const PetscScalar v[], InsertMode imode) {
21935fbaff96SJunchao Zhang   Mat_HYPRE  *hmat = (Mat_HYPRE *)mat->data;
21945fbaff96SJunchao Zhang   PetscMPIInt size;
21955fbaff96SJunchao Zhang   Mat         A;
21965fbaff96SJunchao Zhang 
21975fbaff96SJunchao Zhang   PetscFunctionBegin;
21985fbaff96SJunchao Zhang   PetscCheck(hmat->cooMat, hmat->comm, PETSC_ERR_PLIB, "HYPRE COO delegate matrix has not been created yet");
21995fbaff96SJunchao Zhang   PetscCallMPI(MPI_Comm_size(hmat->comm, &size));
22005fbaff96SJunchao Zhang   PetscCall(MatSetValuesCOO(hmat->cooMat, v, imode));
22015fbaff96SJunchao Zhang 
22025fbaff96SJunchao Zhang   /* Move diagonal elements of the diagonal block to the front of their row, as needed by ParCSRMatrix. So damn hacky */
22035fbaff96SJunchao Zhang   A = (size == 1) ? hmat->cooMat : ((Mat_MPIAIJ *)hmat->cooMat->data)->A;
22045fbaff96SJunchao Zhang   if (hmat->memType == HYPRE_MEMORY_HOST) {
22055fbaff96SJunchao Zhang     Mat_SeqAIJ  *aij = (Mat_SeqAIJ *)A->data;
22065fbaff96SJunchao Zhang     PetscInt     i, m, *Ai = aij->i, *Adiag = aij->diag;
22075fbaff96SJunchao Zhang     PetscScalar *Aa = aij->a, tmp;
22085fbaff96SJunchao Zhang 
22095fbaff96SJunchao Zhang     PetscCall(MatGetSize(A, &m, NULL));
22105fbaff96SJunchao Zhang     for (i = 0; i < m; i++) {
22115fbaff96SJunchao Zhang       if (Adiag[i] >= Ai[i] && Adiag[i] < Ai[i + 1]) { /* Digonal element of this row exists in a[] and j[] */
22125fbaff96SJunchao Zhang         tmp          = Aa[Ai[i]];
22135fbaff96SJunchao Zhang         Aa[Ai[i]]    = Aa[Adiag[i]];
22145fbaff96SJunchao Zhang         Aa[Adiag[i]] = tmp;
22155fbaff96SJunchao Zhang       }
22165fbaff96SJunchao Zhang     }
22175fbaff96SJunchao Zhang   } else {
22185fbaff96SJunchao Zhang #if defined(PETSC_HAVE_KOKKOS_KERNELS)
22195fbaff96SJunchao Zhang     PetscCall(MatSeqAIJMoveDiagonalValuesFront_SeqAIJKokkos(A, hmat->diag));
22205fbaff96SJunchao Zhang #endif
22215fbaff96SJunchao Zhang   }
22225fbaff96SJunchao Zhang   PetscFunctionReturn(0);
22235fbaff96SJunchao Zhang }
22245fbaff96SJunchao Zhang 
2225a055b5aaSBarry Smith /*MC
2226a055b5aaSBarry Smith    MATHYPRE - MATHYPRE = "hypre" - A matrix type to be used for sequential and parallel sparse matrices
2227a055b5aaSBarry Smith           based on the hypre IJ interface.
2228a055b5aaSBarry Smith 
2229a055b5aaSBarry Smith    Level: intermediate
2230a055b5aaSBarry Smith 
223111a5261eSBarry Smith .seealso: `MatCreate()`, `MatHYPRESetPreallocation`
2232a055b5aaSBarry Smith M*/
2233a055b5aaSBarry Smith 
22349371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatCreate_HYPRE(Mat B) {
223563c07aadSStefano Zampini   Mat_HYPRE *hB;
223663c07aadSStefano Zampini 
223763c07aadSStefano Zampini   PetscFunctionBegin;
2238*4dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&hB));
22396ea7df73SStefano Zampini 
2240978814f1SStefano Zampini   hB->inner_free  = PETSC_TRUE;
2241c69f721fSFande Kong   hB->available   = PETSC_TRUE;
2242336664bdSPierre Jolivet   hB->sorted_full = PETSC_FALSE; /* no assumption whether column indices are sorted or not */
2243c69f721fSFande Kong   hB->size        = 0;
2244c69f721fSFande Kong   hB->array       = NULL;
2245978814f1SStefano Zampini 
224663c07aadSStefano Zampini   B->data      = (void *)hB;
224763c07aadSStefano Zampini   B->assembled = PETSC_FALSE;
224863c07aadSStefano Zampini 
22499566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(B->ops, sizeof(struct _MatOps)));
225063c07aadSStefano Zampini   B->ops->mult                  = MatMult_HYPRE;
225163c07aadSStefano Zampini   B->ops->multtranspose         = MatMultTranspose_HYPRE;
2252414bd5c3SStefano Zampini   B->ops->multadd               = MatMultAdd_HYPRE;
2253414bd5c3SStefano Zampini   B->ops->multtransposeadd      = MatMultTransposeAdd_HYPRE;
225463c07aadSStefano Zampini   B->ops->setup                 = MatSetUp_HYPRE;
225563c07aadSStefano Zampini   B->ops->destroy               = MatDestroy_HYPRE;
225663c07aadSStefano Zampini   B->ops->assemblyend           = MatAssemblyEnd_HYPRE;
2257c69f721fSFande Kong   B->ops->assemblybegin         = MatAssemblyBegin_HYPRE;
2258d975228cSstefano_zampini   B->ops->setvalues             = MatSetValues_HYPRE;
225968ec7858SStefano Zampini   B->ops->missingdiagonal       = MatMissingDiagonal_HYPRE;
226068ec7858SStefano Zampini   B->ops->scale                 = MatScale_HYPRE;
226168ec7858SStefano Zampini   B->ops->zerorowscolumns       = MatZeroRowsColumns_HYPRE;
2262c69f721fSFande Kong   B->ops->zeroentries           = MatZeroEntries_HYPRE;
2263c69f721fSFande Kong   B->ops->zerorows              = MatZeroRows_HYPRE;
2264c69f721fSFande Kong   B->ops->getrow                = MatGetRow_HYPRE;
2265c69f721fSFande Kong   B->ops->restorerow            = MatRestoreRow_HYPRE;
2266c69f721fSFande Kong   B->ops->getvalues             = MatGetValues_HYPRE;
2267ddbeb582SStefano Zampini   B->ops->setoption             = MatSetOption_HYPRE;
226845b8d346SStefano Zampini   B->ops->duplicate             = MatDuplicate_HYPRE;
2269465edc17SStefano Zampini   B->ops->copy                  = MatCopy_HYPRE;
227045b8d346SStefano Zampini   B->ops->view                  = MatView_HYPRE;
22716305df00SStefano Zampini   B->ops->getdiagonal           = MatGetDiagonal_HYPRE;
2272363d496dSStefano Zampini   B->ops->axpy                  = MatAXPY_HYPRE;
22734222ddf1SHong Zhang   B->ops->productsetfromoptions = MatProductSetFromOptions_HYPRE;
22746ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
22756ea7df73SStefano Zampini   B->ops->bindtocpu = MatBindToCPU_HYPRE;
22766ea7df73SStefano Zampini   B->boundtocpu     = PETSC_FALSE;
22776ea7df73SStefano Zampini #endif
227845b8d346SStefano Zampini 
227945b8d346SStefano Zampini   /* build cache for off array entries formed */
22809566063dSJacob Faibussowitsch   PetscCall(MatStashCreate_Private(PetscObjectComm((PetscObject)B), 1, &B->stash));
228163c07aadSStefano Zampini 
22829566063dSJacob Faibussowitsch   PetscCall(PetscCommGetComm(PetscObjectComm((PetscObject)B), &hB->comm));
22839566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRE));
22849566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_aij_C", MatConvert_HYPRE_AIJ));
22859566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatConvert_hypre_is_C", MatConvert_HYPRE_IS));
22869566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_seqaij_hypre_C", MatProductSetFromOptions_HYPRE));
22879566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatProductSetFromOptions_mpiaij_hypre_C", MatProductSetFromOptions_HYPRE));
22889566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPRESetPreallocation_C", MatHYPRESetPreallocation_HYPRE));
22899566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatHYPREGetParCSR_C", MatHYPREGetParCSR_HYPRE));
22905fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetPreallocationCOO_C", MatSetPreallocationCOO_HYPRE));
22915fbaff96SJunchao Zhang   PetscCall(PetscObjectComposeFunction((PetscObject)B, "MatSetValuesCOO_C", MatSetValuesCOO_HYPRE));
22926ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
22936ea7df73SStefano Zampini #if defined(HYPRE_USING_HIP)
22949566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_HIP));
22959566063dSJacob Faibussowitsch   PetscCall(MatSetVecType(B, VECHIP));
22966ea7df73SStefano Zampini #endif
22976ea7df73SStefano Zampini #if defined(HYPRE_USING_CUDA)
22989566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
22999566063dSJacob Faibussowitsch   PetscCall(MatSetVecType(B, VECCUDA));
23006ea7df73SStefano Zampini #endif
23016ea7df73SStefano Zampini #endif
230263c07aadSStefano Zampini   PetscFunctionReturn(0);
230363c07aadSStefano Zampini }
230463c07aadSStefano Zampini 
23059371c9d4SSatish Balay static PetscErrorCode hypre_array_destroy(void *ptr) {
2306225daaf8SStefano Zampini   PetscFunctionBegin;
2307e6de0934SSatish Balay   hypre_TFree(ptr, HYPRE_MEMORY_HOST);
2308225daaf8SStefano Zampini   PetscFunctionReturn(0);
2309225daaf8SStefano Zampini }
2310