xref: /petsc/src/mat/impls/hypre/mhypre.c (revision a16187a7a8dfded3244d3cb78a79d8775d871bcb)
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>
1063c07aadSStefano Zampini #include <../src/mat/impls/hypre/mhypre.h>
1163c07aadSStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
1258968eb6SStefano Zampini #include <../src/vec/vec/impls/hypre/vhyp.h>
1358968eb6SStefano Zampini #include <HYPRE.h>
14c1a070e6SStefano Zampini #include <HYPRE_utilities.h>
15cd8bc7baSStefano Zampini #include <_hypre_parcsr_ls.h>
1668ec7858SStefano Zampini #include <_hypre_sstruct_ls.h>
1763c07aadSStefano Zampini 
180e6427aaSSatish Balay #if PETSC_PKG_HYPRE_VERSION_LT(2,18,0)
190e6427aaSSatish Balay #define  hypre_ParCSRMatrixClone(A,B) hypre_ParCSRMatrixCompleteClone(A)
200e6427aaSSatish Balay #endif
210e6427aaSSatish Balay 
2263c07aadSStefano Zampini static PetscErrorCode MatHYPRE_CreateFromMat(Mat,Mat_HYPRE*);
2363c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat,Mat,HYPRE_IJMatrix);
2463c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixFastCopy_MPIAIJ(Mat,HYPRE_IJMatrix);
2563c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixFastCopy_SeqAIJ(Mat,HYPRE_IJMatrix);
2639accc25SStefano Zampini static PetscErrorCode MatHYPRE_MultKernel_Private(Mat,HYPRE_Complex,Vec,HYPRE_Complex,Vec,PetscBool);
27225daaf8SStefano Zampini static PetscErrorCode hypre_array_destroy(void*);
286ea7df73SStefano Zampini static PetscErrorCode MatSetValues_HYPRE(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[],const PetscScalar[],InsertMode ins);
2963c07aadSStefano Zampini 
3063c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat A_d, Mat A_o, HYPRE_IJMatrix ij)
3163c07aadSStefano Zampini {
3263c07aadSStefano Zampini   PetscErrorCode ierr;
3363c07aadSStefano Zampini   PetscInt       i,n_d,n_o;
3463c07aadSStefano Zampini   const PetscInt *ia_d,*ia_o;
3563c07aadSStefano Zampini   PetscBool      done_d=PETSC_FALSE,done_o=PETSC_FALSE;
362cf14000SStefano Zampini   HYPRE_Int      *nnz_d=NULL,*nnz_o=NULL;
3763c07aadSStefano Zampini 
3863c07aadSStefano Zampini   PetscFunctionBegin;
3963c07aadSStefano Zampini   if (A_d) { /* determine number of nonzero entries in local diagonal part */
4063c07aadSStefano Zampini     ierr = MatGetRowIJ(A_d,0,PETSC_FALSE,PETSC_FALSE,&n_d,&ia_d,NULL,&done_d);CHKERRQ(ierr);
4163c07aadSStefano Zampini     if (done_d) {
4263c07aadSStefano Zampini       ierr = PetscMalloc1(n_d,&nnz_d);CHKERRQ(ierr);
4363c07aadSStefano Zampini       for (i=0; i<n_d; i++) {
4463c07aadSStefano Zampini         nnz_d[i] = ia_d[i+1] - ia_d[i];
4563c07aadSStefano Zampini       }
4663c07aadSStefano Zampini     }
4763c07aadSStefano Zampini     ierr = MatRestoreRowIJ(A_d,0,PETSC_FALSE,PETSC_FALSE,NULL,&ia_d,NULL,&done_d);CHKERRQ(ierr);
4863c07aadSStefano Zampini   }
4963c07aadSStefano Zampini   if (A_o) { /* determine number of nonzero entries in local off-diagonal part */
5063c07aadSStefano Zampini     ierr = MatGetRowIJ(A_o,0,PETSC_FALSE,PETSC_FALSE,&n_o,&ia_o,NULL,&done_o);CHKERRQ(ierr);
5163c07aadSStefano Zampini     if (done_o) {
5263c07aadSStefano Zampini       ierr = PetscMalloc1(n_o,&nnz_o);CHKERRQ(ierr);
5363c07aadSStefano Zampini       for (i=0; i<n_o; i++) {
5463c07aadSStefano Zampini         nnz_o[i] = ia_o[i+1] - ia_o[i];
5563c07aadSStefano Zampini       }
5663c07aadSStefano Zampini     }
5763c07aadSStefano Zampini     ierr = MatRestoreRowIJ(A_o,0,PETSC_FALSE,PETSC_FALSE,&n_o,&ia_o,NULL,&done_o);CHKERRQ(ierr);
5863c07aadSStefano Zampini   }
5963c07aadSStefano Zampini   if (done_d) {    /* set number of nonzeros in HYPRE IJ matrix */
6063c07aadSStefano Zampini     if (!done_o) { /* only diagonal part */
6122235d61SPierre Jolivet       ierr = PetscCalloc1(n_d,&nnz_o);CHKERRQ(ierr);
6263c07aadSStefano Zampini     }
63c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2,16,0)
64c6698e78SStefano Zampini     { /* If we don't do this, the columns of the matrix will be all zeros! */
65c6698e78SStefano Zampini       hypre_AuxParCSRMatrix *aux_matrix;
66c6698e78SStefano Zampini       aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(ij);
67c6698e78SStefano Zampini       hypre_AuxParCSRMatrixDestroy(aux_matrix);
68c6698e78SStefano Zampini       hypre_IJMatrixTranslator(ij) = NULL;
692cf14000SStefano Zampini       PetscStackCallStandard(HYPRE_IJMatrixSetDiagOffdSizes,(ij,nnz_d,nnz_o));
7022235d61SPierre Jolivet       /* it seems they partially fixed it in 2.19.0 */
7122235d61SPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LT(2,19,0)
72c6698e78SStefano Zampini       aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(ij);
73c6698e78SStefano Zampini       hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1;
7422235d61SPierre Jolivet #endif
75c6698e78SStefano Zampini     }
76c6698e78SStefano Zampini #else
772cf14000SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixSetDiagOffdSizes,(ij,nnz_d,nnz_o));
78c6698e78SStefano Zampini #endif
7963c07aadSStefano Zampini     ierr = PetscFree(nnz_d);CHKERRQ(ierr);
8063c07aadSStefano Zampini     ierr = PetscFree(nnz_o);CHKERRQ(ierr);
8163c07aadSStefano Zampini   }
8263c07aadSStefano Zampini   PetscFunctionReturn(0);
8363c07aadSStefano Zampini }
8463c07aadSStefano Zampini 
8563c07aadSStefano Zampini static PetscErrorCode MatHYPRE_CreateFromMat(Mat A, Mat_HYPRE *hA)
8663c07aadSStefano Zampini {
8763c07aadSStefano Zampini   PetscErrorCode ierr;
8863c07aadSStefano Zampini   PetscInt       rstart,rend,cstart,cend;
8963c07aadSStefano Zampini 
9063c07aadSStefano Zampini   PetscFunctionBegin;
91d975228cSstefano_zampini   ierr   = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
92d975228cSstefano_zampini   ierr   = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
9363c07aadSStefano Zampini   rstart = A->rmap->rstart;
9463c07aadSStefano Zampini   rend   = A->rmap->rend;
9563c07aadSStefano Zampini   cstart = A->cmap->rstart;
9663c07aadSStefano Zampini   cend   = A->cmap->rend;
9763c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixCreate,(hA->comm,rstart,rend-1,cstart,cend-1,&hA->ij));
9863c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(hA->ij,HYPRE_PARCSR));
9963c07aadSStefano Zampini   {
10063c07aadSStefano Zampini     PetscBool      same;
10163c07aadSStefano Zampini     Mat            A_d,A_o;
10263c07aadSStefano Zampini     const PetscInt *colmap;
103b9e7e5c1SBarry Smith     ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATMPIAIJ,&same);CHKERRQ(ierr);
10463c07aadSStefano Zampini     if (same) {
10563c07aadSStefano Zampini       ierr = MatMPIAIJGetSeqAIJ(A,&A_d,&A_o,&colmap);CHKERRQ(ierr);
10663c07aadSStefano Zampini       ierr = MatHYPRE_IJMatrixPreallocate(A_d,A_o,hA->ij);CHKERRQ(ierr);
10763c07aadSStefano Zampini       PetscFunctionReturn(0);
10863c07aadSStefano Zampini     }
109b9e7e5c1SBarry Smith     ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATMPIBAIJ,&same);CHKERRQ(ierr);
11063c07aadSStefano Zampini     if (same) {
11163c07aadSStefano Zampini       ierr = MatMPIBAIJGetSeqBAIJ(A,&A_d,&A_o,&colmap);CHKERRQ(ierr);
11263c07aadSStefano Zampini       ierr = MatHYPRE_IJMatrixPreallocate(A_d,A_o,hA->ij);CHKERRQ(ierr);
11363c07aadSStefano Zampini       PetscFunctionReturn(0);
11463c07aadSStefano Zampini     }
115b9e7e5c1SBarry Smith     ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATSEQAIJ,&same);CHKERRQ(ierr);
11663c07aadSStefano Zampini     if (same) {
11763c07aadSStefano Zampini       ierr = MatHYPRE_IJMatrixPreallocate(A,NULL,hA->ij);CHKERRQ(ierr);
11863c07aadSStefano Zampini       PetscFunctionReturn(0);
11963c07aadSStefano Zampini     }
120b9e7e5c1SBarry Smith     ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATSEQBAIJ,&same);CHKERRQ(ierr);
12163c07aadSStefano Zampini     if (same) {
12263c07aadSStefano Zampini       ierr = MatHYPRE_IJMatrixPreallocate(A,NULL,hA->ij);CHKERRQ(ierr);
12363c07aadSStefano Zampini       PetscFunctionReturn(0);
12463c07aadSStefano Zampini     }
12563c07aadSStefano Zampini   }
12663c07aadSStefano Zampini   PetscFunctionReturn(0);
12763c07aadSStefano Zampini }
12863c07aadSStefano Zampini 
12963c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopy(Mat A, HYPRE_IJMatrix ij)
13063c07aadSStefano Zampini {
13163c07aadSStefano Zampini   PetscErrorCode    ierr;
13263c07aadSStefano Zampini   PetscInt          i,rstart,rend,ncols,nr,nc;
13363c07aadSStefano Zampini   const PetscScalar *values;
13463c07aadSStefano Zampini   const PetscInt    *cols;
13563c07aadSStefano Zampini   PetscBool         flg;
13663c07aadSStefano Zampini 
13763c07aadSStefano Zampini   PetscFunctionBegin;
1386ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2,19,0)
1396ea7df73SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixInitialize,(ij));
1406ea7df73SStefano Zampini #else
1416ea7df73SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixInitialize_v2,(ij,HYPRE_MEMORY_HOST));
1426ea7df73SStefano Zampini #endif
143b9e7e5c1SBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATMPIAIJ,&flg);CHKERRQ(ierr);
14463c07aadSStefano Zampini   ierr = MatGetSize(A,&nr,&nc);CHKERRQ(ierr);
14563c07aadSStefano Zampini   if (flg && nr == nc) {
14663c07aadSStefano Zampini     ierr = MatHYPRE_IJMatrixFastCopy_MPIAIJ(A,ij);CHKERRQ(ierr);
14763c07aadSStefano Zampini     PetscFunctionReturn(0);
14863c07aadSStefano Zampini   }
149b9e7e5c1SBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATSEQAIJ,&flg);CHKERRQ(ierr);
15063c07aadSStefano Zampini   if (flg) {
15163c07aadSStefano Zampini     ierr = MatHYPRE_IJMatrixFastCopy_SeqAIJ(A,ij);CHKERRQ(ierr);
15263c07aadSStefano Zampini     PetscFunctionReturn(0);
15363c07aadSStefano Zampini   }
15463c07aadSStefano Zampini 
15563c07aadSStefano Zampini   ierr = MatGetOwnershipRange(A,&rstart,&rend);CHKERRQ(ierr);
15663c07aadSStefano Zampini   for (i=rstart; i<rend; i++) {
15763c07aadSStefano Zampini     ierr = MatGetRow(A,i,&ncols,&cols,&values);CHKERRQ(ierr);
158e3977e59Sstefano_zampini     if (ncols) {
1592cf14000SStefano Zampini       HYPRE_Int nc = (HYPRE_Int)ncols;
1602cf14000SStefano Zampini 
1612cf14000SStefano Zampini       if ((PetscInt)nc != ncols) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Hypre overflow! number of columns %D for row %D",ncols,i);
16239accc25SStefano Zampini       PetscStackCallStandard(HYPRE_IJMatrixSetValues,(ij,1,&nc,(HYPRE_BigInt *)&i,(HYPRE_BigInt *)cols,(HYPRE_Complex *)values));
163e3977e59Sstefano_zampini     }
16463c07aadSStefano Zampini     ierr = MatRestoreRow(A,i,&ncols,&cols,&values);CHKERRQ(ierr);
16563c07aadSStefano Zampini   }
16663c07aadSStefano Zampini   PetscFunctionReturn(0);
16763c07aadSStefano Zampini }
16863c07aadSStefano Zampini 
16963c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixFastCopy_SeqAIJ(Mat A, HYPRE_IJMatrix ij)
17063c07aadSStefano Zampini {
17163c07aadSStefano Zampini   PetscErrorCode        ierr;
17263c07aadSStefano Zampini   Mat_SeqAIJ            *pdiag = (Mat_SeqAIJ*)A->data;
17358968eb6SStefano Zampini   HYPRE_Int             type;
17463c07aadSStefano Zampini   hypre_ParCSRMatrix    *par_matrix;
17563c07aadSStefano Zampini   hypre_AuxParCSRMatrix *aux_matrix;
17663c07aadSStefano Zampini   hypre_CSRMatrix       *hdiag;
1772cf14000SStefano Zampini   PetscBool             sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
1786ea7df73SStefano Zampini   const PetscScalar     *pa;
17963c07aadSStefano Zampini 
18063c07aadSStefano Zampini   PetscFunctionBegin;
181ea9daf28SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(ij,&type));
182ea9daf28SStefano Zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
183ea9daf28SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(ij,(void**)&par_matrix));
18463c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(par_matrix);
18563c07aadSStefano Zampini   /*
18663c07aadSStefano Zampini        this is the Hack part where we monkey directly with the hypre datastructures
18763c07aadSStefano Zampini   */
1882cf14000SStefano Zampini   if (sameint) {
189580bdb30SBarry Smith     ierr = PetscArraycpy(hdiag->i,pdiag->i,A->rmap->n + 1);CHKERRQ(ierr);
190580bdb30SBarry Smith     ierr = PetscArraycpy(hdiag->j,pdiag->j,pdiag->nz);CHKERRQ(ierr);
1912cf14000SStefano Zampini   } else {
1922cf14000SStefano Zampini     PetscInt i;
1932cf14000SStefano Zampini 
1942cf14000SStefano Zampini     for (i=0;i<A->rmap->n + 1;i++) hdiag->i[i] = (HYPRE_Int)pdiag->i[i];
1952cf14000SStefano Zampini     for (i=0;i<pdiag->nz;i++)      hdiag->j[i] = (HYPRE_Int)pdiag->j[i];
1962cf14000SStefano Zampini   }
1976ea7df73SStefano Zampini 
1986ea7df73SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&pa);CHKERRQ(ierr);
1996ea7df73SStefano Zampini   ierr = PetscArraycpy(hdiag->data,pa,pdiag->nz);CHKERRQ(ierr);
2006ea7df73SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&pa);CHKERRQ(ierr);
201ea9daf28SStefano Zampini 
202ea9daf28SStefano Zampini   aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(ij);
20363c07aadSStefano Zampini   hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
20463c07aadSStefano Zampini   PetscFunctionReturn(0);
20563c07aadSStefano Zampini }
20663c07aadSStefano Zampini 
20763c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixFastCopy_MPIAIJ(Mat A, HYPRE_IJMatrix ij)
20863c07aadSStefano Zampini {
20963c07aadSStefano Zampini   PetscErrorCode        ierr;
21063c07aadSStefano Zampini   Mat_MPIAIJ            *pA = (Mat_MPIAIJ*)A->data;
21163c07aadSStefano Zampini   Mat_SeqAIJ            *pdiag,*poffd;
21263c07aadSStefano Zampini   PetscInt              i,*garray = pA->garray,*jj,cstart,*pjj;
2132cf14000SStefano Zampini   HYPRE_Int             *hjj,type;
21463c07aadSStefano Zampini   hypre_ParCSRMatrix    *par_matrix;
21563c07aadSStefano Zampini   hypre_AuxParCSRMatrix *aux_matrix;
21663c07aadSStefano Zampini   hypre_CSRMatrix       *hdiag,*hoffd;
2172cf14000SStefano Zampini   PetscBool             sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
2186ea7df73SStefano Zampini   const PetscScalar     *pa;
21963c07aadSStefano Zampini 
22063c07aadSStefano Zampini   PetscFunctionBegin;
22163c07aadSStefano Zampini   pdiag = (Mat_SeqAIJ*) pA->A->data;
22263c07aadSStefano Zampini   poffd = (Mat_SeqAIJ*) pA->B->data;
22363c07aadSStefano Zampini   /* cstart is only valid for square MPIAIJ layed out in the usual way */
22463c07aadSStefano Zampini   ierr = MatGetOwnershipRange(A,&cstart,NULL);CHKERRQ(ierr);
22563c07aadSStefano Zampini 
226ea9daf28SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(ij,&type));
227ea9daf28SStefano Zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
228ea9daf28SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(ij,(void**)&par_matrix));
22963c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(par_matrix);
23063c07aadSStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(par_matrix);
23163c07aadSStefano Zampini 
23263c07aadSStefano Zampini   /*
23363c07aadSStefano Zampini        this is the Hack part where we monkey directly with the hypre datastructures
23463c07aadSStefano Zampini   */
2352cf14000SStefano Zampini   if (sameint) {
236580bdb30SBarry Smith     ierr = PetscArraycpy(hdiag->i,pdiag->i,pA->A->rmap->n + 1);CHKERRQ(ierr);
2372cf14000SStefano Zampini   } else {
2382cf14000SStefano Zampini     for (i=0; i<pA->A->rmap->n + 1; i++) hdiag->i[i] = (HYPRE_Int)(pdiag->i[i]);
2392cf14000SStefano Zampini   }
24063c07aadSStefano Zampini   /* need to shift the diag column indices (hdiag->j) back to global numbering since hypre is expecting this */
2412cf14000SStefano Zampini   hjj = hdiag->j;
2422cf14000SStefano Zampini   pjj = pdiag->j;
243c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2,16,0)
2442cf14000SStefano Zampini   for (i=0; i<pdiag->nz; i++) hjj[i] = pjj[i];
245c6698e78SStefano Zampini #else
2462cf14000SStefano Zampini   for (i=0; i<pdiag->nz; i++) hjj[i] = cstart + pjj[i];
247c6698e78SStefano Zampini #endif
2486ea7df73SStefano Zampini   ierr = MatSeqAIJGetArrayRead(pA->A,&pa);CHKERRQ(ierr);
2496ea7df73SStefano Zampini   ierr = PetscArraycpy(hdiag->data,pa,pdiag->nz);CHKERRQ(ierr);
2506ea7df73SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(pA->A,&pa);CHKERRQ(ierr);
2512cf14000SStefano Zampini   if (sameint) {
252580bdb30SBarry Smith     ierr = PetscArraycpy(hoffd->i,poffd->i,pA->A->rmap->n + 1);CHKERRQ(ierr);
2532cf14000SStefano Zampini   } else {
2542cf14000SStefano Zampini     for (i=0; i<pA->A->rmap->n + 1; i++) hoffd->i[i] = (HYPRE_Int)(poffd->i[i]);
2552cf14000SStefano Zampini   }
2562cf14000SStefano Zampini 
25763c07aadSStefano Zampini   /* need to move the offd column indices (hoffd->j) back to global numbering since hypre is expecting this
25863c07aadSStefano Zampini      If we hacked a hypre a bit more we might be able to avoid this step */
259c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2,16,0)
260c6698e78SStefano Zampini   PetscStackCallStandard(hypre_CSRMatrixBigInitialize,(hoffd));
261c6698e78SStefano Zampini   jj  = (PetscInt*) hoffd->big_j;
262c6698e78SStefano Zampini #else
26363c07aadSStefano Zampini   jj  = (PetscInt*) hoffd->j;
264c6698e78SStefano Zampini #endif
2652cf14000SStefano Zampini   pjj = poffd->j;
26663c07aadSStefano Zampini   for (i=0; i<poffd->nz; i++) jj[i] = garray[pjj[i]];
267c6698e78SStefano Zampini 
2686ea7df73SStefano Zampini   ierr = MatSeqAIJGetArrayRead(pA->B,&pa);CHKERRQ(ierr);
2696ea7df73SStefano Zampini   ierr = PetscArraycpy(hoffd->data,pa,poffd->nz);CHKERRQ(ierr);
2706ea7df73SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(pA->B,&pa);CHKERRQ(ierr);
27163c07aadSStefano Zampini 
272ea9daf28SStefano Zampini   aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(ij);
27363c07aadSStefano Zampini   hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
27463c07aadSStefano Zampini   PetscFunctionReturn(0);
27563c07aadSStefano Zampini }
27663c07aadSStefano Zampini 
2772df22349SStefano Zampini static PetscErrorCode MatConvert_HYPRE_IS(Mat A, MatType mtype, MatReuse reuse, Mat* B)
2782df22349SStefano Zampini {
2792df22349SStefano Zampini   Mat_HYPRE*             mhA = (Mat_HYPRE*)(A->data);
2802df22349SStefano Zampini   Mat                    lA;
2812df22349SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
2822df22349SStefano Zampini   IS                     is;
2832df22349SStefano Zampini   hypre_ParCSRMatrix     *hA;
2842df22349SStefano Zampini   hypre_CSRMatrix        *hdiag,*hoffd;
2852df22349SStefano Zampini   MPI_Comm               comm;
28639accc25SStefano Zampini   HYPRE_Complex          *hdd,*hod,*aa;
28739accc25SStefano Zampini   PetscScalar            *data;
2882cf14000SStefano Zampini   HYPRE_BigInt           *col_map_offd;
2892cf14000SStefano Zampini   HYPRE_Int              *hdi,*hdj,*hoi,*hoj;
2902df22349SStefano Zampini   PetscInt               *ii,*jj,*iptr,*jptr;
2912df22349SStefano Zampini   PetscInt               cum,dr,dc,oc,str,stc,nnz,i,jd,jo,M,N;
29258968eb6SStefano Zampini   HYPRE_Int              type;
2932df22349SStefano Zampini   PetscErrorCode         ierr;
2942df22349SStefano Zampini 
2952df22349SStefano Zampini   PetscFunctionBegin;
296a1787963SStefano Zampini   comm = PetscObjectComm((PetscObject)A);
2972df22349SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(mhA->ij,&type));
2982df22349SStefano Zampini   if (type != HYPRE_PARCSR) SETERRQ(comm,PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
2992df22349SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(mhA->ij,(void**)&hA));
3002df22349SStefano Zampini   M     = hypre_ParCSRMatrixGlobalNumRows(hA);
3012df22349SStefano Zampini   N     = hypre_ParCSRMatrixGlobalNumCols(hA);
3022df22349SStefano Zampini   str   = hypre_ParCSRMatrixFirstRowIndex(hA);
3032df22349SStefano Zampini   stc   = hypre_ParCSRMatrixFirstColDiag(hA);
3042df22349SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(hA);
3052df22349SStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(hA);
3062df22349SStefano Zampini   dr    = hypre_CSRMatrixNumRows(hdiag);
3072df22349SStefano Zampini   dc    = hypre_CSRMatrixNumCols(hdiag);
3082df22349SStefano Zampini   nnz   = hypre_CSRMatrixNumNonzeros(hdiag);
3092df22349SStefano Zampini   hdi   = hypre_CSRMatrixI(hdiag);
3102df22349SStefano Zampini   hdj   = hypre_CSRMatrixJ(hdiag);
3112df22349SStefano Zampini   hdd   = hypre_CSRMatrixData(hdiag);
3122df22349SStefano Zampini   oc    = hypre_CSRMatrixNumCols(hoffd);
3132df22349SStefano Zampini   nnz  += hypre_CSRMatrixNumNonzeros(hoffd);
3142df22349SStefano Zampini   hoi   = hypre_CSRMatrixI(hoffd);
3152df22349SStefano Zampini   hoj   = hypre_CSRMatrixJ(hoffd);
3162df22349SStefano Zampini   hod   = hypre_CSRMatrixData(hoffd);
3172df22349SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
3182df22349SStefano Zampini     PetscInt *aux;
3192df22349SStefano Zampini 
3202df22349SStefano Zampini     /* generate l2g maps for rows and cols */
3212df22349SStefano Zampini     ierr = ISCreateStride(comm,dr,str,1,&is);CHKERRQ(ierr);
3222df22349SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
3232df22349SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
3242df22349SStefano Zampini     col_map_offd = hypre_ParCSRMatrixColMapOffd(hA);
3252df22349SStefano Zampini     ierr = PetscMalloc1(dc+oc,&aux);CHKERRQ(ierr);
3262df22349SStefano Zampini     for (i=0; i<dc; i++) aux[i] = i+stc;
3272df22349SStefano Zampini     for (i=0; i<oc; i++) aux[i+dc] = col_map_offd[i];
3282df22349SStefano Zampini     ierr = ISCreateGeneral(comm,dc+oc,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
3292df22349SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
3302df22349SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
3312df22349SStefano Zampini     /* create MATIS object */
3322df22349SStefano Zampini     ierr = MatCreate(comm,B);CHKERRQ(ierr);
3332df22349SStefano Zampini     ierr = MatSetSizes(*B,dr,dc,M,N);CHKERRQ(ierr);
3342df22349SStefano Zampini     ierr = MatSetType(*B,MATIS);CHKERRQ(ierr);
3352df22349SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*B,rl2g,cl2g);CHKERRQ(ierr);
3362df22349SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
3372df22349SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
3382df22349SStefano Zampini 
3392df22349SStefano Zampini     /* allocate CSR for local matrix */
3402df22349SStefano Zampini     ierr = PetscMalloc1(dr+1,&iptr);CHKERRQ(ierr);
3412df22349SStefano Zampini     ierr = PetscMalloc1(nnz,&jptr);CHKERRQ(ierr);
3422df22349SStefano Zampini     ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr);
3432df22349SStefano Zampini   } else {
3442df22349SStefano Zampini     PetscInt  nr;
3452df22349SStefano Zampini     PetscBool done;
3462df22349SStefano Zampini     ierr = MatISGetLocalMat(*B,&lA);CHKERRQ(ierr);
3472df22349SStefano Zampini     ierr = MatGetRowIJ(lA,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&iptr,(const PetscInt**)&jptr,&done);CHKERRQ(ierr);
3482df22349SStefano Zampini     if (nr != dr) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot reuse mat: invalid number of rows in local mat! %D != %D",nr,dr);
3492df22349SStefano Zampini     if (iptr[nr] < nnz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot reuse mat: invalid number of nonzeros in local mat! reuse %D requested %D",iptr[nr],nnz);
3502df22349SStefano Zampini     ierr = MatSeqAIJGetArray(lA,&data);CHKERRQ(ierr);
3512df22349SStefano Zampini   }
3522df22349SStefano Zampini   /* merge local matrices */
3532df22349SStefano Zampini   ii  = iptr;
3542df22349SStefano Zampini   jj  = jptr;
35539accc25SStefano 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++ */
3562df22349SStefano Zampini   *ii = *(hdi++) + *(hoi++);
3572df22349SStefano Zampini   for (jd=0,jo=0,cum=0; *ii<nnz; cum++) {
35839accc25SStefano Zampini     PetscScalar *aold = (PetscScalar*)aa;
3592df22349SStefano Zampini     PetscInt    *jold = jj,nc = jd+jo;
3602df22349SStefano Zampini     for (; jd<*hdi; jd++) { *jj++ = *hdj++;      *aa++ = *hdd++; }
3612df22349SStefano Zampini     for (; jo<*hoi; jo++) { *jj++ = *hoj++ + dc; *aa++ = *hod++; }
3622df22349SStefano Zampini     *(++ii) = *(hdi++) + *(hoi++);
3632df22349SStefano Zampini     ierr = PetscSortIntWithScalarArray(jd+jo-nc,jold,aold);CHKERRQ(ierr);
3642df22349SStefano Zampini   }
3652df22349SStefano Zampini   for (; cum<dr; cum++) *(++ii) = nnz;
3662df22349SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
367a033916dSStefano Zampini     Mat_SeqAIJ* a;
368a033916dSStefano Zampini 
3692df22349SStefano Zampini     ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,dc+oc,iptr,jptr,data,&lA);CHKERRQ(ierr);
3702df22349SStefano Zampini     ierr = MatISSetLocalMat(*B,lA);CHKERRQ(ierr);
371a033916dSStefano Zampini     /* hack SeqAIJ */
372a033916dSStefano Zampini     a          = (Mat_SeqAIJ*)(lA->data);
373a033916dSStefano Zampini     a->free_a  = PETSC_TRUE;
374a033916dSStefano Zampini     a->free_ij = PETSC_TRUE;
3752df22349SStefano Zampini     ierr = MatDestroy(&lA);CHKERRQ(ierr);
3762df22349SStefano Zampini   }
3772df22349SStefano Zampini   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3782df22349SStefano Zampini   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3792df22349SStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
3802df22349SStefano Zampini     ierr = MatHeaderReplace(A,B);CHKERRQ(ierr);
3812df22349SStefano Zampini   }
3822df22349SStefano Zampini   PetscFunctionReturn(0);
3832df22349SStefano Zampini }
3842df22349SStefano Zampini 
38563c07aadSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType type, MatReuse reuse, Mat *B)
38663c07aadSStefano Zampini {
38784d4e069SStefano Zampini   Mat            M = NULL;
38863c07aadSStefano Zampini   Mat_HYPRE      *hB;
38963c07aadSStefano Zampini   MPI_Comm       comm = PetscObjectComm((PetscObject)A);
39063c07aadSStefano Zampini   PetscErrorCode ierr;
39163c07aadSStefano Zampini 
39263c07aadSStefano Zampini   PetscFunctionBegin;
39363c07aadSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
39463c07aadSStefano Zampini     /* always destroy the old matrix and create a new memory;
39563c07aadSStefano Zampini        hope this does not churn the memory too much. The problem
39663c07aadSStefano Zampini        is I do not know if it is possible to put the matrix back to
39763c07aadSStefano Zampini        its initial state so that we can directly copy the values
39863c07aadSStefano Zampini        the second time through. */
39963c07aadSStefano Zampini     hB = (Mat_HYPRE*)((*B)->data);
40063c07aadSStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixDestroy,(hB->ij));
40163c07aadSStefano Zampini   } else {
40284d4e069SStefano Zampini     ierr = MatCreate(comm,&M);CHKERRQ(ierr);
40384d4e069SStefano Zampini     ierr = MatSetType(M,MATHYPRE);CHKERRQ(ierr);
40484d4e069SStefano Zampini     ierr = MatSetSizes(M,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
40584d4e069SStefano Zampini     hB   = (Mat_HYPRE*)(M->data);
40684d4e069SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) *B = M;
40763c07aadSStefano Zampini   }
408d04e6649SStefano Zampini   ierr = MatSetOption(*B,MAT_SORTED_FULL,PETSC_TRUE);CHKERRQ(ierr); /* "perfect" preallocation, so no need for hypre_AuxParCSRMatrixNeedAux */
409d04e6649SStefano Zampini   ierr = MatSetOption(*B,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
41063c07aadSStefano Zampini   ierr = MatHYPRE_CreateFromMat(A,hB);CHKERRQ(ierr);
41163c07aadSStefano Zampini   ierr = MatHYPRE_IJMatrixCopy(A,hB->ij);CHKERRQ(ierr);
41284d4e069SStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
41384d4e069SStefano Zampini     ierr = MatHeaderReplace(A,&M);CHKERRQ(ierr);
41484d4e069SStefano Zampini   }
4154ec6421dSstefano_zampini   (*B)->preallocated = PETSC_TRUE;
41663c07aadSStefano Zampini   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
41763c07aadSStefano Zampini   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
41863c07aadSStefano Zampini   PetscFunctionReturn(0);
41963c07aadSStefano Zampini }
42063c07aadSStefano Zampini 
421ea9daf28SStefano Zampini static PetscErrorCode MatConvert_HYPRE_AIJ(Mat A, MatType mtype, MatReuse reuse, Mat *B)
42263c07aadSStefano Zampini {
42363c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE*)A->data;
42463c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
42563c07aadSStefano Zampini   hypre_CSRMatrix    *hdiag,*hoffd;
42663c07aadSStefano Zampini   MPI_Comm           comm;
42763c07aadSStefano Zampini   PetscScalar        *da,*oa,*aptr;
42863c07aadSStefano Zampini   PetscInt           *dii,*djj,*oii,*ojj,*iptr;
42963c07aadSStefano Zampini   PetscInt           i,dnnz,onnz,m,n;
43058968eb6SStefano Zampini   HYPRE_Int          type;
43163c07aadSStefano Zampini   PetscMPIInt        size;
4322cf14000SStefano Zampini   PetscBool          sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
43363c07aadSStefano Zampini   PetscErrorCode     ierr;
43463c07aadSStefano Zampini 
43563c07aadSStefano Zampini   PetscFunctionBegin;
43663c07aadSStefano Zampini   comm = PetscObjectComm((PetscObject)A);
43763c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type));
43863c07aadSStefano Zampini   if (type != HYPRE_PARCSR) SETERRQ(comm,PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
43963c07aadSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
44063c07aadSStefano Zampini     PetscBool ismpiaij,isseqaij;
441b9e7e5c1SBarry Smith     ierr = PetscObjectBaseTypeCompare((PetscObject)*B,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
4424099cc6bSBarry Smith     ierr = PetscObjectBaseTypeCompare((PetscObject)*B,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
44363c07aadSStefano Zampini     if (!ismpiaij && !isseqaij) SETERRQ(comm,PETSC_ERR_SUP,"Only MATMPIAIJ or MATSEQAIJ are supported");
44463c07aadSStefano Zampini   }
4456ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
4466ea7df73SStefano Zampini   if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(hA->ij)) SETERRQ(comm,PETSC_ERR_SUP,"Not yet implemented");
4476ea7df73SStefano Zampini #endif
448ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
44963c07aadSStefano Zampini 
45063c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&parcsr));
45163c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(parcsr);
45263c07aadSStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(parcsr);
45363c07aadSStefano Zampini   m     = hypre_CSRMatrixNumRows(hdiag);
45463c07aadSStefano Zampini   n     = hypre_CSRMatrixNumCols(hdiag);
45563c07aadSStefano Zampini   dnnz  = hypre_CSRMatrixNumNonzeros(hdiag);
45663c07aadSStefano Zampini   onnz  = hypre_CSRMatrixNumNonzeros(hoffd);
457225daaf8SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
45863c07aadSStefano Zampini     ierr = PetscMalloc1(m+1,&dii);CHKERRQ(ierr);
45963c07aadSStefano Zampini     ierr = PetscMalloc1(dnnz,&djj);CHKERRQ(ierr);
46063c07aadSStefano Zampini     ierr = PetscMalloc1(dnnz,&da);CHKERRQ(ierr);
461225daaf8SStefano Zampini   } else if (reuse == MAT_REUSE_MATRIX) {
46263c07aadSStefano Zampini     PetscInt  nr;
46363c07aadSStefano Zampini     PetscBool done;
46463c07aadSStefano Zampini     if (size > 1) {
46563c07aadSStefano Zampini       Mat_MPIAIJ *b = (Mat_MPIAIJ*)((*B)->data);
46663c07aadSStefano Zampini 
46763c07aadSStefano Zampini       ierr = MatGetRowIJ(b->A,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&dii,(const PetscInt**)&djj,&done);CHKERRQ(ierr);
46863c07aadSStefano Zampini       if (nr != m) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot reuse mat: invalid number of local rows in diag part! %D != %D",nr,m);
46963c07aadSStefano Zampini       if (dii[nr] < dnnz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot reuse mat: invalid number of nonzeros in diag part! reuse %D hypre %D",dii[nr],dnnz);
47063c07aadSStefano Zampini       ierr = MatSeqAIJGetArray(b->A,&da);CHKERRQ(ierr);
47163c07aadSStefano Zampini     } else {
47263c07aadSStefano Zampini       ierr = MatGetRowIJ(*B,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&dii,(const PetscInt**)&djj,&done);CHKERRQ(ierr);
47363c07aadSStefano Zampini       if (nr != m) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot reuse mat: invalid number of local rows! %D != %D",nr,m);
47463c07aadSStefano Zampini       if (dii[nr] < dnnz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot reuse mat: invalid number of nonzeros! reuse %D hypre %D",dii[nr],dnnz);
47563c07aadSStefano Zampini       ierr = MatSeqAIJGetArray(*B,&da);CHKERRQ(ierr);
47663c07aadSStefano Zampini     }
477225daaf8SStefano Zampini   } else { /* MAT_INPLACE_MATRIX */
4782cf14000SStefano Zampini     if (!sameint) {
4792cf14000SStefano Zampini       ierr = PetscMalloc1(m+1,&dii);CHKERRQ(ierr);
4802cf14000SStefano Zampini       ierr = PetscMalloc1(dnnz,&djj);CHKERRQ(ierr);
4812cf14000SStefano Zampini     } else {
4827d968826Sstefano_zampini       dii = (PetscInt*)hypre_CSRMatrixI(hdiag);
4837d968826Sstefano_zampini       djj = (PetscInt*)hypre_CSRMatrixJ(hdiag);
48463c07aadSStefano Zampini     }
48539accc25SStefano Zampini     da = (PetscScalar*)hypre_CSRMatrixData(hdiag);
48663c07aadSStefano Zampini   }
4872cf14000SStefano Zampini 
4882cf14000SStefano Zampini   if (!sameint) {
489*a16187a7SStefano Zampini     if (reuse != MAT_REUSE_MATRIX) { for (i=0;i<m+1;i++)  dii[i] = (PetscInt)(hypre_CSRMatrixI(hdiag)[i]); }
4902cf14000SStefano Zampini     for (i=0;i<dnnz;i++) djj[i] = (PetscInt)(hypre_CSRMatrixJ(hdiag)[i]);
4912cf14000SStefano Zampini   } else {
492*a16187a7SStefano Zampini     if (reuse != MAT_REUSE_MATRIX) { ierr = PetscArraycpy(dii,hypre_CSRMatrixI(hdiag),m+1);CHKERRQ(ierr); }
493580bdb30SBarry Smith     ierr = PetscArraycpy(djj,hypre_CSRMatrixJ(hdiag),dnnz);CHKERRQ(ierr);
4942cf14000SStefano Zampini   }
495580bdb30SBarry Smith   ierr = PetscArraycpy(da,hypre_CSRMatrixData(hdiag),dnnz);CHKERRQ(ierr);
49663c07aadSStefano Zampini   iptr = djj;
49763c07aadSStefano Zampini   aptr = da;
49863c07aadSStefano Zampini   for (i=0; i<m; i++) {
49963c07aadSStefano Zampini     PetscInt nc = dii[i+1]-dii[i];
50063c07aadSStefano Zampini     ierr = PetscSortIntWithScalarArray(nc,iptr,aptr);CHKERRQ(ierr);
50163c07aadSStefano Zampini     iptr += nc;
50263c07aadSStefano Zampini     aptr += nc;
50363c07aadSStefano Zampini   }
50463c07aadSStefano Zampini   if (size > 1) {
5052cf14000SStefano Zampini     HYPRE_BigInt *coffd;
5062cf14000SStefano Zampini     HYPRE_Int    *offdj;
50763c07aadSStefano Zampini 
508225daaf8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
50963c07aadSStefano Zampini       ierr = PetscMalloc1(m+1,&oii);CHKERRQ(ierr);
51063c07aadSStefano Zampini       ierr = PetscMalloc1(onnz,&ojj);CHKERRQ(ierr);
51163c07aadSStefano Zampini       ierr = PetscMalloc1(onnz,&oa);CHKERRQ(ierr);
512225daaf8SStefano Zampini     } else if (reuse == MAT_REUSE_MATRIX) {
51363c07aadSStefano Zampini       Mat_MPIAIJ *b = (Mat_MPIAIJ*)((*B)->data);
51463c07aadSStefano Zampini       PetscInt   nr,hr = hypre_CSRMatrixNumRows(hoffd);
51563c07aadSStefano Zampini       PetscBool  done;
51663c07aadSStefano Zampini 
51763c07aadSStefano Zampini       ierr = MatGetRowIJ(b->B,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&oii,(const PetscInt**)&ojj,&done);CHKERRQ(ierr);
51863c07aadSStefano Zampini       if (nr != hr) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot reuse mat: invalid number of local rows in offdiag part! %D != %D",nr,hr);
51963c07aadSStefano Zampini       if (oii[nr] < onnz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot reuse mat: invalid number of nonzeros in offdiag part! reuse %D hypre %D",oii[nr],onnz);
52063c07aadSStefano Zampini       ierr = MatSeqAIJGetArray(b->B,&oa);CHKERRQ(ierr);
521225daaf8SStefano Zampini     } else { /* MAT_INPLACE_MATRIX */
5222cf14000SStefano Zampini       if (!sameint) {
5232cf14000SStefano Zampini         ierr = PetscMalloc1(m+1,&oii);CHKERRQ(ierr);
5242cf14000SStefano Zampini         ierr = PetscMalloc1(onnz,&ojj);CHKERRQ(ierr);
5252cf14000SStefano Zampini       } else {
5267d968826Sstefano_zampini         oii = (PetscInt*)hypre_CSRMatrixI(hoffd);
5277d968826Sstefano_zampini         ojj = (PetscInt*)hypre_CSRMatrixJ(hoffd);
52863c07aadSStefano Zampini       }
52939accc25SStefano Zampini       oa = (PetscScalar*)hypre_CSRMatrixData(hoffd);
53063c07aadSStefano Zampini     }
531*a16187a7SStefano Zampini     if (reuse != MAT_REUSE_MATRIX) {
5322cf14000SStefano Zampini       if (!sameint) {
5332cf14000SStefano Zampini         for (i=0;i<m+1;i++) oii[i] = (PetscInt)(hypre_CSRMatrixI(hoffd)[i]);
5342cf14000SStefano Zampini       } else {
535580bdb30SBarry Smith         ierr = PetscArraycpy(oii,hypre_CSRMatrixI(hoffd),m+1);CHKERRQ(ierr);
5362cf14000SStefano Zampini       }
537*a16187a7SStefano Zampini     }
538*a16187a7SStefano Zampini     ierr = PetscArraycpy(oa,hypre_CSRMatrixData(hoffd),onnz);CHKERRQ(ierr);
539*a16187a7SStefano Zampini 
54063c07aadSStefano Zampini     offdj = hypre_CSRMatrixJ(hoffd);
54163c07aadSStefano Zampini     coffd = hypre_ParCSRMatrixColMapOffd(parcsr);
542*a16187a7SStefano Zampini     /* we only need the permutation to be computed properly, I don't know if HYPRE
543*a16187a7SStefano Zampini        messes up with the ordering. Just in case, allocate some memory and free it
544*a16187a7SStefano Zampini        later */
545*a16187a7SStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
546*a16187a7SStefano Zampini       Mat_MPIAIJ *b = (Mat_MPIAIJ*)((*B)->data);
547*a16187a7SStefano Zampini       PetscInt   mnz;
548*a16187a7SStefano Zampini 
549*a16187a7SStefano Zampini       ierr = MatSeqAIJGetMaxRowNonzeros(b->B,&mnz);CHKERRQ(ierr);
550*a16187a7SStefano Zampini       ierr = PetscMalloc1(mnz,&ojj);CHKERRQ(ierr);
551*a16187a7SStefano Zampini     } else for (i=0; i<onnz; i++) ojj[i] = coffd[offdj[i]];
55263c07aadSStefano Zampini     iptr = ojj;
55363c07aadSStefano Zampini     aptr = oa;
55463c07aadSStefano Zampini     for (i=0; i<m; i++) {
55563c07aadSStefano Zampini        PetscInt nc = oii[i+1]-oii[i];
556*a16187a7SStefano Zampini        if (reuse == MAT_REUSE_MATRIX) {
557*a16187a7SStefano Zampini          PetscInt j;
558*a16187a7SStefano Zampini 
559*a16187a7SStefano Zampini          iptr = ojj;
560*a16187a7SStefano Zampini          for (j=0; j<nc; j++) iptr[j] = coffd[offdj[oii[i] + j]];
561*a16187a7SStefano Zampini        }
56263c07aadSStefano Zampini        ierr = PetscSortIntWithScalarArray(nc,iptr,aptr);CHKERRQ(ierr);
56363c07aadSStefano Zampini        iptr += nc;
56463c07aadSStefano Zampini        aptr += nc;
56563c07aadSStefano Zampini     }
566*a16187a7SStefano Zampini     if (reuse == MAT_REUSE_MATRIX) { ierr = PetscFree(ojj);CHKERRQ(ierr); }
567225daaf8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
56863c07aadSStefano Zampini       Mat_MPIAIJ *b;
56963c07aadSStefano Zampini       Mat_SeqAIJ *d,*o;
570225daaf8SStefano Zampini 
57141073d71Sstefano_zampini       ierr = MatCreateMPIAIJWithSplitArrays(comm,m,n,PETSC_DECIDE,PETSC_DECIDE,dii,djj,da,oii,ojj,oa,B);CHKERRQ(ierr);
57263c07aadSStefano Zampini       /* hack MPIAIJ */
57363c07aadSStefano Zampini       b          = (Mat_MPIAIJ*)((*B)->data);
57463c07aadSStefano Zampini       d          = (Mat_SeqAIJ*)b->A->data;
57563c07aadSStefano Zampini       o          = (Mat_SeqAIJ*)b->B->data;
57663c07aadSStefano Zampini       d->free_a  = PETSC_TRUE;
57763c07aadSStefano Zampini       d->free_ij = PETSC_TRUE;
57863c07aadSStefano Zampini       o->free_a  = PETSC_TRUE;
57963c07aadSStefano Zampini       o->free_ij = PETSC_TRUE;
580225daaf8SStefano Zampini     } else if (reuse == MAT_INPLACE_MATRIX) {
581225daaf8SStefano Zampini       Mat T;
5822cf14000SStefano Zampini 
58341073d71Sstefano_zampini       ierr = MatCreateMPIAIJWithSplitArrays(comm,m,n,PETSC_DECIDE,PETSC_DECIDE,dii,djj,da,oii,ojj,oa,&T);CHKERRQ(ierr);
5842cf14000SStefano Zampini       if (sameint) { /* ownership of CSR pointers is transferred to PETSc */
585225daaf8SStefano Zampini         hypre_CSRMatrixI(hdiag) = NULL;
586225daaf8SStefano Zampini         hypre_CSRMatrixJ(hdiag) = NULL;
587225daaf8SStefano Zampini         hypre_CSRMatrixI(hoffd) = NULL;
588225daaf8SStefano Zampini         hypre_CSRMatrixJ(hoffd) = NULL;
5892cf14000SStefano Zampini       } else { /* Hack MPIAIJ -> free ij but not a */
5902cf14000SStefano Zampini         Mat_MPIAIJ *b = (Mat_MPIAIJ*)(T->data);
5912cf14000SStefano Zampini         Mat_SeqAIJ *d = (Mat_SeqAIJ*)(b->A->data);
5922cf14000SStefano Zampini         Mat_SeqAIJ *o = (Mat_SeqAIJ*)(b->B->data);
5932cf14000SStefano Zampini 
5942cf14000SStefano Zampini         d->free_ij = PETSC_TRUE;
5952cf14000SStefano Zampini         o->free_ij = PETSC_TRUE;
5962cf14000SStefano Zampini       }
5972cf14000SStefano Zampini       hypre_CSRMatrixData(hdiag) = NULL;
598225daaf8SStefano Zampini       hypre_CSRMatrixData(hoffd) = NULL;
599225daaf8SStefano Zampini       ierr = MatHeaderReplace(A,&T);CHKERRQ(ierr);
60063c07aadSStefano Zampini     }
601225daaf8SStefano Zampini   } else {
602225daaf8SStefano Zampini     oii  = NULL;
603225daaf8SStefano Zampini     ojj  = NULL;
604225daaf8SStefano Zampini     oa   = NULL;
605225daaf8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
60663c07aadSStefano Zampini       Mat_SeqAIJ* b;
6072cf14000SStefano Zampini 
60863c07aadSStefano Zampini       ierr = MatCreateSeqAIJWithArrays(comm,m,n,dii,djj,da,B);CHKERRQ(ierr);
60963c07aadSStefano Zampini       /* hack SeqAIJ */
61063c07aadSStefano Zampini       b          = (Mat_SeqAIJ*)((*B)->data);
61163c07aadSStefano Zampini       b->free_a  = PETSC_TRUE;
61263c07aadSStefano Zampini       b->free_ij = PETSC_TRUE;
613225daaf8SStefano Zampini     } else if (reuse == MAT_INPLACE_MATRIX) {
614225daaf8SStefano Zampini       Mat T;
6152cf14000SStefano Zampini 
616225daaf8SStefano Zampini       ierr = MatCreateSeqAIJWithArrays(comm,m,n,dii,djj,da,&T);CHKERRQ(ierr);
6172cf14000SStefano Zampini       if (sameint) { /* ownership of CSR pointers is transferred to PETSc */
618225daaf8SStefano Zampini         hypre_CSRMatrixI(hdiag) = NULL;
619225daaf8SStefano Zampini         hypre_CSRMatrixJ(hdiag) = NULL;
6202cf14000SStefano Zampini       } else { /* free ij but not a */
6212cf14000SStefano Zampini         Mat_SeqAIJ* b = (Mat_SeqAIJ*)(T->data);
6222cf14000SStefano Zampini 
6232cf14000SStefano Zampini         b->free_ij = PETSC_TRUE;
6242cf14000SStefano Zampini       }
625225daaf8SStefano Zampini       hypre_CSRMatrixData(hdiag) = NULL;
626225daaf8SStefano Zampini       ierr = MatHeaderReplace(A,&T);CHKERRQ(ierr);
62763c07aadSStefano Zampini     }
628225daaf8SStefano Zampini   }
629225daaf8SStefano Zampini 
6302cf14000SStefano Zampini   /* we have to use hypre_Tfree to free the HYPRE arrays
6312cf14000SStefano Zampini      that PETSc now onws */
63263c07aadSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
6332cf14000SStefano Zampini     PetscInt nh;
6342cf14000SStefano Zampini     void *ptrs[6] = {da,oa,dii,djj,oii,ojj};
6352cf14000SStefano Zampini     const char *names[6] = {"_hypre_csr_da",
6362cf14000SStefano Zampini                             "_hypre_csr_oa",
6372cf14000SStefano Zampini                             "_hypre_csr_dii",
638225daaf8SStefano Zampini                             "_hypre_csr_djj",
639225daaf8SStefano Zampini                             "_hypre_csr_oii",
6402cf14000SStefano Zampini                             "_hypre_csr_ojj"};
6412cf14000SStefano Zampini     nh = sameint ? 6 : 2;
6422cf14000SStefano Zampini     for (i=0; i<nh; i++) {
643225daaf8SStefano Zampini       PetscContainer c;
644225daaf8SStefano Zampini 
645225daaf8SStefano Zampini       ierr = PetscContainerCreate(comm,&c);CHKERRQ(ierr);
646225daaf8SStefano Zampini       ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr);
647225daaf8SStefano Zampini       ierr = PetscContainerSetUserDestroy(c,hypre_array_destroy);CHKERRQ(ierr);
648225daaf8SStefano Zampini       ierr = PetscObjectCompose((PetscObject)(*B),names[i],(PetscObject)c);CHKERRQ(ierr);
649225daaf8SStefano Zampini       ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
650225daaf8SStefano Zampini     }
65163c07aadSStefano Zampini   }
65263c07aadSStefano Zampini   PetscFunctionReturn(0);
65363c07aadSStefano Zampini }
65463c07aadSStefano Zampini 
655613e5ff0Sstefano_zampini static PetscErrorCode MatAIJGetParCSR_Private(Mat A, hypre_ParCSRMatrix **hA)
656c1a070e6SStefano Zampini {
657613e5ff0Sstefano_zampini   hypre_ParCSRMatrix *tA;
658c1a070e6SStefano Zampini   hypre_CSRMatrix    *hdiag,*hoffd;
659c1a070e6SStefano Zampini   Mat_SeqAIJ         *diag,*offd;
6602cf14000SStefano Zampini   PetscInt           *garray,i,noffd,dnnz,onnz,*row_starts,*col_starts;
661c1a070e6SStefano Zampini   MPI_Comm           comm = PetscObjectComm((PetscObject)A);
662613e5ff0Sstefano_zampini   PetscBool          ismpiaij,isseqaij;
6632cf14000SStefano Zampini   PetscBool          sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
664c1a070e6SStefano Zampini   PetscErrorCode     ierr;
6656ea7df73SStefano Zampini   HYPRE_Int          *hdi = NULL,*hdj = NULL,*hoi = NULL,*hoj = NULL;
6666ea7df73SStefano Zampini   PetscInt           *pdi,*pdj,*poi,*poj;
6676ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
6686ea7df73SStefano Zampini   PetscBool          iscuda = PETSC_FALSE;
6696ea7df73SStefano Zampini #endif
670c1a070e6SStefano Zampini 
671c1a070e6SStefano Zampini   PetscFunctionBegin;
6723937f725SBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
6734099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
674a32993e3SJed Brown   if (!ismpiaij && !isseqaij) SETERRQ1(comm,PETSC_ERR_SUP,"Unsupported type %s",((PetscObject)A)->type_name);
675c1a070e6SStefano Zampini   if (ismpiaij) {
676c1a070e6SStefano Zampini     Mat_MPIAIJ *a = (Mat_MPIAIJ*)(A->data);
677c1a070e6SStefano Zampini 
678c1a070e6SStefano Zampini     diag = (Mat_SeqAIJ*)a->A->data;
679c1a070e6SStefano Zampini     offd = (Mat_SeqAIJ*)a->B->data;
6806ea7df73SStefano Zampini #if defined(PETSC_HAVE_CUDA) && defined(PETSC_HAVE_HYPRE_DEVICE) && defined(HYPRE_USING_CUDA)
6816ea7df73SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJCUSPARSE,&iscuda);CHKERRQ(ierr);
6826ea7df73SStefano Zampini     if (iscuda && !A->boundtocpu) {
6836ea7df73SStefano Zampini       sameint = PETSC_TRUE;
6846ea7df73SStefano Zampini       ierr = MatSeqAIJCUSPARSEGetIJ(a->A,PETSC_FALSE,(const HYPRE_Int**)&hdi,(const HYPRE_Int**)&hdj);CHKERRQ(ierr);
6856ea7df73SStefano Zampini       ierr = MatSeqAIJCUSPARSEGetIJ(a->B,PETSC_FALSE,(const HYPRE_Int**)&hoi,(const HYPRE_Int**)&hoj);CHKERRQ(ierr);
6866ea7df73SStefano Zampini     } else {
6876ea7df73SStefano Zampini #else
6886ea7df73SStefano Zampini     {
6896ea7df73SStefano Zampini #endif
6906ea7df73SStefano Zampini       pdi = diag->i;
6916ea7df73SStefano Zampini       pdj = diag->j;
6926ea7df73SStefano Zampini       poi = offd->i;
6936ea7df73SStefano Zampini       poj = offd->j;
6946ea7df73SStefano Zampini       if (sameint) {
6956ea7df73SStefano Zampini         hdi = (HYPRE_Int*)pdi;
6966ea7df73SStefano Zampini         hdj = (HYPRE_Int*)pdj;
6976ea7df73SStefano Zampini         hoi = (HYPRE_Int*)poi;
6986ea7df73SStefano Zampini         hoj = (HYPRE_Int*)poj;
6996ea7df73SStefano Zampini       }
7006ea7df73SStefano Zampini     }
701c1a070e6SStefano Zampini     garray = a->garray;
702c1a070e6SStefano Zampini     noffd  = a->B->cmap->N;
703c1a070e6SStefano Zampini     dnnz   = diag->nz;
704c1a070e6SStefano Zampini     onnz   = offd->nz;
705c1a070e6SStefano Zampini   } else {
706c1a070e6SStefano Zampini     diag = (Mat_SeqAIJ*)A->data;
707c1a070e6SStefano Zampini     offd = NULL;
7086ea7df73SStefano Zampini #if defined(PETSC_HAVE_CUDA) && defined(PETSC_HAVE_HYPRE_DEVICE)
7096ea7df73SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJCUSPARSE,&iscuda);CHKERRQ(ierr);
7106ea7df73SStefano Zampini     if (iscuda && !A->boundtocpu) {
7116ea7df73SStefano Zampini       sameint = PETSC_TRUE;
7126ea7df73SStefano Zampini       ierr = MatSeqAIJCUSPARSEGetIJ(A,PETSC_FALSE,(const HYPRE_Int**)&hdi,(const HYPRE_Int**)&hdj);CHKERRQ(ierr);
7136ea7df73SStefano Zampini     } else {
7146ea7df73SStefano Zampini #else
7156ea7df73SStefano Zampini     {
7166ea7df73SStefano Zampini #endif
7176ea7df73SStefano Zampini       pdi = diag->i;
7186ea7df73SStefano Zampini       pdj = diag->j;
7196ea7df73SStefano Zampini       if (sameint) {
7206ea7df73SStefano Zampini         hdi = (HYPRE_Int*)pdi;
7216ea7df73SStefano Zampini         hdj = (HYPRE_Int*)pdj;
7226ea7df73SStefano Zampini       }
7236ea7df73SStefano Zampini     }
724c1a070e6SStefano Zampini     garray = NULL;
725c1a070e6SStefano Zampini     noffd  = 0;
726c1a070e6SStefano Zampini     dnnz   = diag->nz;
727c1a070e6SStefano Zampini     onnz   = 0;
728c1a070e6SStefano Zampini   }
729225daaf8SStefano Zampini 
730c1a070e6SStefano Zampini   /* create a temporary ParCSR */
731c1a070e6SStefano Zampini   if (HYPRE_AssumedPartitionCheck()) {
732c1a070e6SStefano Zampini     PetscMPIInt myid;
733c1a070e6SStefano Zampini 
73455b25c41SPierre Jolivet     ierr       = MPI_Comm_rank(comm,&myid);CHKERRMPI(ierr);
735c1a070e6SStefano Zampini     row_starts = A->rmap->range + myid;
736c1a070e6SStefano Zampini     col_starts = A->cmap->range + myid;
737c1a070e6SStefano Zampini   } else {
738c1a070e6SStefano Zampini     row_starts = A->rmap->range;
739c1a070e6SStefano Zampini     col_starts = A->cmap->range;
740c1a070e6SStefano Zampini   }
7412cf14000SStefano Zampini   tA = hypre_ParCSRMatrixCreate(comm,A->rmap->N,A->cmap->N,(HYPRE_BigInt*)row_starts,(HYPRE_BigInt*)col_starts,noffd,dnnz,onnz);
742a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
743c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetRowStartsOwner(tA,0);
744c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetColStartsOwner(tA,0);
745a1d2239cSSatish Balay #endif
746c1a070e6SStefano Zampini 
747225daaf8SStefano Zampini   /* set diagonal part */
748c1a070e6SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(tA);
7496ea7df73SStefano Zampini   if (!sameint) { /* malloc CSR pointers */
7506ea7df73SStefano Zampini     ierr = PetscMalloc2(A->rmap->n+1,&hdi,dnnz,&hdj);CHKERRQ(ierr);
7516ea7df73SStefano Zampini     for (i = 0; i < A->rmap->n+1; i++) hdi[i] = (HYPRE_Int)(pdi[i]);
7526ea7df73SStefano Zampini     for (i = 0; i < dnnz; i++)         hdj[i] = (HYPRE_Int)(pdj[i]);
7532cf14000SStefano Zampini   }
7546ea7df73SStefano Zampini   hypre_CSRMatrixI(hdiag)           = hdi;
7556ea7df73SStefano Zampini   hypre_CSRMatrixJ(hdiag)           = hdj;
75639accc25SStefano Zampini   hypre_CSRMatrixData(hdiag)        = (HYPRE_Complex*)diag->a;
757c1a070e6SStefano Zampini   hypre_CSRMatrixNumNonzeros(hdiag) = diag->nz;
758c1a070e6SStefano Zampini   hypre_CSRMatrixSetRownnz(hdiag);
759c1a070e6SStefano Zampini   hypre_CSRMatrixSetDataOwner(hdiag,0);
760c1a070e6SStefano Zampini 
761225daaf8SStefano Zampini   /* set offdiagonal part */
762c1a070e6SStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(tA);
763c1a070e6SStefano Zampini   if (offd) {
7646ea7df73SStefano Zampini     if (!sameint) { /* malloc CSR pointers */
7656ea7df73SStefano Zampini       ierr = PetscMalloc2(A->rmap->n+1,&hoi,onnz,&hoj);CHKERRQ(ierr);
7666ea7df73SStefano Zampini       for (i = 0; i < A->rmap->n+1; i++) hoi[i] = (HYPRE_Int)(poi[i]);
7676ea7df73SStefano Zampini       for (i = 0; i < onnz; i++)         hoj[i] = (HYPRE_Int)(poj[i]);
7682cf14000SStefano Zampini     }
7696ea7df73SStefano Zampini     hypre_CSRMatrixI(hoffd)           = hoi;
7706ea7df73SStefano Zampini     hypre_CSRMatrixJ(hoffd)           = hoj;
77139accc25SStefano Zampini     hypre_CSRMatrixData(hoffd)        = (HYPRE_Complex*)offd->a;
772c1a070e6SStefano Zampini     hypre_CSRMatrixNumNonzeros(hoffd) = offd->nz;
773c1a070e6SStefano Zampini     hypre_CSRMatrixSetRownnz(hoffd);
774c1a070e6SStefano Zampini     hypre_CSRMatrixSetDataOwner(hoffd,0);
7756ea7df73SStefano Zampini   }
7766ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
7776ea7df73SStefano Zampini   PetscStackCallStandard(hypre_ParCSRMatrixInitialize_v2,(tA,iscuda ? HYPRE_MEMORY_DEVICE : HYPRE_MEMORY_HOST));
7786ea7df73SStefano Zampini #else
7796ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2,18,0)
7806ea7df73SStefano Zampini   PetscStackCallStandard(hypre_ParCSRMatrixInitialize,(tA));
7816ea7df73SStefano Zampini #else
7826ea7df73SStefano Zampini   PetscStackCallStandard(hypre_ParCSRMatrixInitialize_v2,(tA,HYPRE_MEMORY_HOST));
7836ea7df73SStefano Zampini #endif
7846ea7df73SStefano Zampini #endif
7856ea7df73SStefano Zampini   hypre_TFree(hypre_ParCSRMatrixColMapOffd(tA),HYPRE_MEMORY_HOST);
786c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetNumNonzeros(tA);
7872cf14000SStefano Zampini   hypre_ParCSRMatrixColMapOffd(tA) = (HYPRE_BigInt*)garray;
7886ea7df73SStefano Zampini   if (!hypre_ParCSRMatrixCommPkg(tA)) PetscStackCallStandard(hypre_MatvecCommPkgCreate,(tA));
789613e5ff0Sstefano_zampini   *hA = tA;
790613e5ff0Sstefano_zampini   PetscFunctionReturn(0);
791613e5ff0Sstefano_zampini }
792c1a070e6SStefano Zampini 
793613e5ff0Sstefano_zampini static PetscErrorCode MatAIJRestoreParCSR_Private(Mat A, hypre_ParCSRMatrix **hA)
794613e5ff0Sstefano_zampini {
795613e5ff0Sstefano_zampini   hypre_CSRMatrix *hdiag,*hoffd;
7966ea7df73SStefano Zampini   PetscBool       ismpiaij,sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
7972cf14000SStefano Zampini   PetscErrorCode  ierr;
7986ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
7996ea7df73SStefano Zampini   PetscBool       iscuda = PETSC_FALSE;
8006ea7df73SStefano Zampini #endif
801c1a070e6SStefano Zampini 
802613e5ff0Sstefano_zampini   PetscFunctionBegin;
8036ea7df73SStefano Zampini   ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
8046ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
8056ea7df73SStefano Zampini   ierr = PetscObjectTypeCompareAny((PetscObject)A,&iscuda,MATSEQAIJCUSPARSE,MATMPIAIJCUSPARSE,"");CHKERRQ(ierr);
8066ea7df73SStefano Zampini   if (iscuda) sameint = PETSC_TRUE;
8076ea7df73SStefano Zampini #endif
808613e5ff0Sstefano_zampini   hdiag = hypre_ParCSRMatrixDiag(*hA);
809613e5ff0Sstefano_zampini   hoffd = hypre_ParCSRMatrixOffd(*hA);
8106ea7df73SStefano Zampini   /* free temporary memory allocated by PETSc
8116ea7df73SStefano Zampini      set pointers to NULL before destroying tA */
8122cf14000SStefano Zampini   if (!sameint) {
8132cf14000SStefano Zampini     HYPRE_Int *hi,*hj;
8142cf14000SStefano Zampini 
8152cf14000SStefano Zampini     hi = hypre_CSRMatrixI(hdiag);
8162cf14000SStefano Zampini     hj = hypre_CSRMatrixJ(hdiag);
8172cf14000SStefano Zampini     ierr = PetscFree2(hi,hj);CHKERRQ(ierr);
8186ea7df73SStefano Zampini     if (ismpiaij) {
8192cf14000SStefano Zampini       hi = hypre_CSRMatrixI(hoffd);
8202cf14000SStefano Zampini       hj = hypre_CSRMatrixJ(hoffd);
8212cf14000SStefano Zampini       ierr = PetscFree2(hi,hj);CHKERRQ(ierr);
8222cf14000SStefano Zampini     }
8232cf14000SStefano Zampini   }
824c1a070e6SStefano Zampini   hypre_CSRMatrixI(hdiag)    = NULL;
825c1a070e6SStefano Zampini   hypre_CSRMatrixJ(hdiag)    = NULL;
826c1a070e6SStefano Zampini   hypre_CSRMatrixData(hdiag) = NULL;
8276ea7df73SStefano Zampini   if (ismpiaij) {
828c1a070e6SStefano Zampini     hypre_CSRMatrixI(hoffd)    = NULL;
829c1a070e6SStefano Zampini     hypre_CSRMatrixJ(hoffd)    = NULL;
830c1a070e6SStefano Zampini     hypre_CSRMatrixData(hoffd) = NULL;
8316ea7df73SStefano Zampini   }
832613e5ff0Sstefano_zampini   hypre_ParCSRMatrixColMapOffd(*hA) = NULL;
833613e5ff0Sstefano_zampini   hypre_ParCSRMatrixDestroy(*hA);
834613e5ff0Sstefano_zampini   *hA = NULL;
835613e5ff0Sstefano_zampini   PetscFunctionReturn(0);
836613e5ff0Sstefano_zampini }
837613e5ff0Sstefano_zampini 
838613e5ff0Sstefano_zampini /* calls RAP from BoomerAMG:
8393dad0653Sstefano_zampini    the resulting ParCSR will not own the column and row starts
8406ea7df73SStefano Zampini    It looks like we don't need to have the diagonal entries ordered first */
841a055b5aaSBarry Smith static PetscErrorCode MatHYPRE_ParCSR_RAP(hypre_ParCSRMatrix *hR, hypre_ParCSRMatrix *hA,hypre_ParCSRMatrix *hP, hypre_ParCSRMatrix **hRAP)
842613e5ff0Sstefano_zampini {
843a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
844613e5ff0Sstefano_zampini   HYPRE_Int P_owns_col_starts,R_owns_row_starts;
845a1d2239cSSatish Balay #endif
846613e5ff0Sstefano_zampini 
847613e5ff0Sstefano_zampini   PetscFunctionBegin;
848a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
849613e5ff0Sstefano_zampini   P_owns_col_starts = hypre_ParCSRMatrixOwnsColStarts(hP);
850613e5ff0Sstefano_zampini   R_owns_row_starts = hypre_ParCSRMatrixOwnsRowStarts(hR);
851a1d2239cSSatish Balay #endif
8526ea7df73SStefano Zampini   /* can be replaced by version test later */
8536ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
8546ea7df73SStefano Zampini   PetscStackPush("hypre_ParCSRMatrixRAP");
8556ea7df73SStefano Zampini   *hRAP = hypre_ParCSRMatrixRAP(hR,hA,hP);
8566ea7df73SStefano Zampini   PetscStackPop;
8576ea7df73SStefano Zampini #else
858613e5ff0Sstefano_zampini   PetscStackCallStandard(hypre_BoomerAMGBuildCoarseOperator,(hR,hA,hP,hRAP));
859613e5ff0Sstefano_zampini   PetscStackCallStandard(hypre_ParCSRMatrixSetNumNonzeros,(*hRAP));
8606ea7df73SStefano Zampini #endif
861613e5ff0Sstefano_zampini   /* hypre_BoomerAMGBuildCoarseOperator steals the col_starts from P and the row_starts from R */
862a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
863613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetRowStartsOwner(*hRAP,0);
864613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetColStartsOwner(*hRAP,0);
865613e5ff0Sstefano_zampini   if (P_owns_col_starts) hypre_ParCSRMatrixSetColStartsOwner(hP,1);
866613e5ff0Sstefano_zampini   if (R_owns_row_starts) hypre_ParCSRMatrixSetRowStartsOwner(hR,1);
867a1d2239cSSatish Balay #endif
868613e5ff0Sstefano_zampini   PetscFunctionReturn(0);
869613e5ff0Sstefano_zampini }
870613e5ff0Sstefano_zampini 
8716f231fbdSstefano_zampini static PetscErrorCode MatPtAPNumeric_AIJ_AIJ_wHYPRE(Mat A,Mat P,Mat C)
872613e5ff0Sstefano_zampini {
8736f231fbdSstefano_zampini   Mat                B;
8746abb4441SStefano Zampini   hypre_ParCSRMatrix *hA,*hP,*hPtAP = NULL;
875613e5ff0Sstefano_zampini   PetscErrorCode     ierr;
8764222ddf1SHong Zhang   Mat_Product        *product=C->product;
877613e5ff0Sstefano_zampini 
878613e5ff0Sstefano_zampini   PetscFunctionBegin;
879613e5ff0Sstefano_zampini   ierr = MatAIJGetParCSR_Private(A,&hA);CHKERRQ(ierr);
880613e5ff0Sstefano_zampini   ierr = MatAIJGetParCSR_Private(P,&hP);CHKERRQ(ierr);
881613e5ff0Sstefano_zampini   ierr = MatHYPRE_ParCSR_RAP(hP,hA,hP,&hPtAP);CHKERRQ(ierr);
8826f231fbdSstefano_zampini   ierr = MatCreateFromParCSR(hPtAP,MATAIJ,PETSC_OWN_POINTER,&B);CHKERRQ(ierr);
8834222ddf1SHong Zhang 
8846f231fbdSstefano_zampini   ierr = MatHeaderMerge(C,&B);CHKERRQ(ierr);
8854222ddf1SHong Zhang   C->product = product;
8864222ddf1SHong Zhang 
887613e5ff0Sstefano_zampini   ierr = MatAIJRestoreParCSR_Private(A,&hA);CHKERRQ(ierr);
888613e5ff0Sstefano_zampini   ierr = MatAIJRestoreParCSR_Private(P,&hP);CHKERRQ(ierr);
8896f231fbdSstefano_zampini   PetscFunctionReturn(0);
8906f231fbdSstefano_zampini }
8916f231fbdSstefano_zampini 
8924222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatPtAPSymbolic_AIJ_AIJ_wHYPRE(Mat A,Mat P,PetscReal fill,Mat C)
8936f231fbdSstefano_zampini {
8946f231fbdSstefano_zampini   PetscErrorCode ierr;
895ab4d48faSStefano Zampini 
8966f231fbdSstefano_zampini   PetscFunctionBegin;
8974222ddf1SHong Zhang   ierr                   = MatSetType(C,MATAIJ);CHKERRQ(ierr);
8984222ddf1SHong Zhang   C->ops->ptapnumeric    = MatPtAPNumeric_AIJ_AIJ_wHYPRE;
8994222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
900613e5ff0Sstefano_zampini   PetscFunctionReturn(0);
901613e5ff0Sstefano_zampini }
902613e5ff0Sstefano_zampini 
9034cc28894Sstefano_zampini static PetscErrorCode MatPtAPNumeric_AIJ_HYPRE(Mat A,Mat P,Mat C)
904613e5ff0Sstefano_zampini {
9054cc28894Sstefano_zampini   Mat                B;
9064cc28894Sstefano_zampini   Mat_HYPRE          *hP;
9076abb4441SStefano Zampini   hypre_ParCSRMatrix *hA = NULL,*Pparcsr,*ptapparcsr = NULL;
908613e5ff0Sstefano_zampini   HYPRE_Int          type;
909613e5ff0Sstefano_zampini   MPI_Comm           comm = PetscObjectComm((PetscObject)A);
9104cc28894Sstefano_zampini   PetscBool          ishypre;
911613e5ff0Sstefano_zampini   PetscErrorCode     ierr;
912613e5ff0Sstefano_zampini 
913613e5ff0Sstefano_zampini   PetscFunctionBegin;
9144cc28894Sstefano_zampini   ierr = PetscObjectTypeCompare((PetscObject)P,MATHYPRE,&ishypre);CHKERRQ(ierr);
9154cc28894Sstefano_zampini   if (!ishypre) SETERRQ1(comm,PETSC_ERR_USER,"P should be of type %s",MATHYPRE);
9164cc28894Sstefano_zampini   hP = (Mat_HYPRE*)P->data;
917613e5ff0Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hP->ij,&type));
918613e5ff0Sstefano_zampini   if (type != HYPRE_PARCSR) SETERRQ(comm,PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
919613e5ff0Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hP->ij,(void**)&Pparcsr));
920613e5ff0Sstefano_zampini 
921613e5ff0Sstefano_zampini   ierr = MatAIJGetParCSR_Private(A,&hA);CHKERRQ(ierr);
922613e5ff0Sstefano_zampini   ierr = MatHYPRE_ParCSR_RAP(Pparcsr,hA,Pparcsr,&ptapparcsr);CHKERRQ(ierr);
923613e5ff0Sstefano_zampini   ierr = MatAIJRestoreParCSR_Private(A,&hA);CHKERRQ(ierr);
924225daaf8SStefano Zampini 
9254cc28894Sstefano_zampini   /* create temporary matrix and merge to C */
9264cc28894Sstefano_zampini   ierr = MatCreateFromParCSR(ptapparcsr,((PetscObject)C)->type_name,PETSC_OWN_POINTER,&B);CHKERRQ(ierr);
9274cc28894Sstefano_zampini   ierr = MatHeaderMerge(C,&B);CHKERRQ(ierr);
9284cc28894Sstefano_zampini   PetscFunctionReturn(0);
9294cc28894Sstefano_zampini }
9304cc28894Sstefano_zampini 
9314cc28894Sstefano_zampini static PetscErrorCode MatPtAPNumeric_HYPRE_HYPRE(Mat A,Mat P,Mat C)
9324cc28894Sstefano_zampini {
9334cc28894Sstefano_zampini   Mat                B;
9346abb4441SStefano Zampini   hypre_ParCSRMatrix *Aparcsr,*Pparcsr,*ptapparcsr = NULL;
9354cc28894Sstefano_zampini   Mat_HYPRE          *hA,*hP;
9364cc28894Sstefano_zampini   PetscBool          ishypre;
9374cc28894Sstefano_zampini   HYPRE_Int          type;
9384cc28894Sstefano_zampini   PetscErrorCode     ierr;
9394cc28894Sstefano_zampini 
9404cc28894Sstefano_zampini   PetscFunctionBegin;
9414cc28894Sstefano_zampini   ierr = PetscObjectTypeCompare((PetscObject)P,MATHYPRE,&ishypre);CHKERRQ(ierr);
9424cc28894Sstefano_zampini   if (!ishypre) SETERRQ1(PetscObjectComm((PetscObject)P),PETSC_ERR_USER,"P should be of type %s",MATHYPRE);
9434cc28894Sstefano_zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATHYPRE,&ishypre);CHKERRQ(ierr);
9444cc28894Sstefano_zampini   if (!ishypre) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_USER,"A should be of type %s",MATHYPRE);
9454cc28894Sstefano_zampini   hA = (Mat_HYPRE*)A->data;
9464cc28894Sstefano_zampini   hP = (Mat_HYPRE*)P->data;
9474cc28894Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type));
9484cc28894Sstefano_zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
9494cc28894Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hP->ij,&type));
9504cc28894Sstefano_zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)P),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
9514cc28894Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&Aparcsr));
9524cc28894Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hP->ij,(void**)&Pparcsr));
9534cc28894Sstefano_zampini   ierr = MatHYPRE_ParCSR_RAP(Pparcsr,Aparcsr,Pparcsr,&ptapparcsr);CHKERRQ(ierr);
9544cc28894Sstefano_zampini   ierr = MatCreateFromParCSR(ptapparcsr,MATHYPRE,PETSC_OWN_POINTER,&B);CHKERRQ(ierr);
9554cc28894Sstefano_zampini   ierr = MatHeaderMerge(C,&B);CHKERRQ(ierr);
9564cc28894Sstefano_zampini   PetscFunctionReturn(0);
9574cc28894Sstefano_zampini }
9584cc28894Sstefano_zampini 
959d501dc42Sstefano_zampini /* calls hypre_ParMatmul
960d501dc42Sstefano_zampini    hypre_ParMatMul uses hypre_ParMatrixCreate with the communicator of hA
9613dad0653Sstefano_zampini    hypre_ParMatrixCreate does not duplicate the communicator
9626ea7df73SStefano Zampini    It looks like we don't need to have the diagonal entries ordered first */
963d501dc42Sstefano_zampini static PetscErrorCode MatHYPRE_ParCSR_MatMatMult(hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hB, hypre_ParCSRMatrix **hAB)
964d501dc42Sstefano_zampini {
965d501dc42Sstefano_zampini   PetscFunctionBegin;
9666ea7df73SStefano Zampini   /* can be replaced by version test later */
9676ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
9686ea7df73SStefano Zampini   PetscStackPush("hypre_ParCSRMatMat");
9696ea7df73SStefano Zampini   *hAB = hypre_ParCSRMatMat(hA,hB);
9706ea7df73SStefano Zampini #else
971d501dc42Sstefano_zampini   PetscStackPush("hypre_ParMatmul");
972d501dc42Sstefano_zampini   *hAB = hypre_ParMatmul(hA,hB);
9736ea7df73SStefano Zampini #endif
974d501dc42Sstefano_zampini   PetscStackPop;
975d501dc42Sstefano_zampini   PetscFunctionReturn(0);
976d501dc42Sstefano_zampini }
977d501dc42Sstefano_zampini 
9785e5acdf2Sstefano_zampini static PetscErrorCode MatMatMultNumeric_AIJ_AIJ_wHYPRE(Mat A,Mat B,Mat C)
9795e5acdf2Sstefano_zampini {
9805e5acdf2Sstefano_zampini   Mat                D;
981d501dc42Sstefano_zampini   hypre_ParCSRMatrix *hA,*hB,*hAB = NULL;
9825e5acdf2Sstefano_zampini   PetscErrorCode     ierr;
9834222ddf1SHong Zhang   Mat_Product        *product=C->product;
9845e5acdf2Sstefano_zampini 
9855e5acdf2Sstefano_zampini   PetscFunctionBegin;
9865e5acdf2Sstefano_zampini   ierr = MatAIJGetParCSR_Private(A,&hA);CHKERRQ(ierr);
9875e5acdf2Sstefano_zampini   ierr = MatAIJGetParCSR_Private(B,&hB);CHKERRQ(ierr);
988d501dc42Sstefano_zampini   ierr = MatHYPRE_ParCSR_MatMatMult(hA,hB,&hAB);CHKERRQ(ierr);
9895e5acdf2Sstefano_zampini   ierr = MatCreateFromParCSR(hAB,MATAIJ,PETSC_OWN_POINTER,&D);CHKERRQ(ierr);
9904222ddf1SHong Zhang 
9915e5acdf2Sstefano_zampini   ierr = MatHeaderMerge(C,&D);CHKERRQ(ierr);
9924222ddf1SHong Zhang   C->product = product;
9934222ddf1SHong Zhang 
9945e5acdf2Sstefano_zampini   ierr = MatAIJRestoreParCSR_Private(A,&hA);CHKERRQ(ierr);
9955e5acdf2Sstefano_zampini   ierr = MatAIJRestoreParCSR_Private(B,&hB);CHKERRQ(ierr);
9965e5acdf2Sstefano_zampini   PetscFunctionReturn(0);
9975e5acdf2Sstefano_zampini }
9985e5acdf2Sstefano_zampini 
9994222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatMatMultSymbolic_AIJ_AIJ_wHYPRE(Mat A,Mat B,PetscReal fill,Mat C)
10005e5acdf2Sstefano_zampini {
10015e5acdf2Sstefano_zampini   PetscErrorCode ierr;
100220e1dc0dSstefano_zampini 
10035e5acdf2Sstefano_zampini   PetscFunctionBegin;
10044222ddf1SHong Zhang   ierr = MatSetType(C,MATAIJ);CHKERRQ(ierr);
10054222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_AIJ_AIJ_wHYPRE;
10064222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
10075e5acdf2Sstefano_zampini   PetscFunctionReturn(0);
10085e5acdf2Sstefano_zampini }
10095e5acdf2Sstefano_zampini 
1010d501dc42Sstefano_zampini static PetscErrorCode MatMatMultNumeric_HYPRE_HYPRE(Mat A,Mat B,Mat C)
1011d501dc42Sstefano_zampini {
1012d501dc42Sstefano_zampini   Mat                D;
1013d501dc42Sstefano_zampini   hypre_ParCSRMatrix *Aparcsr,*Bparcsr,*ABparcsr = NULL;
1014d501dc42Sstefano_zampini   Mat_HYPRE          *hA,*hB;
1015d501dc42Sstefano_zampini   PetscBool          ishypre;
1016d501dc42Sstefano_zampini   HYPRE_Int          type;
1017d501dc42Sstefano_zampini   PetscErrorCode     ierr;
10184222ddf1SHong Zhang   Mat_Product        *product;
1019d501dc42Sstefano_zampini 
1020d501dc42Sstefano_zampini   PetscFunctionBegin;
1021d501dc42Sstefano_zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATHYPRE,&ishypre);CHKERRQ(ierr);
1022d501dc42Sstefano_zampini   if (!ishypre) SETERRQ1(PetscObjectComm((PetscObject)B),PETSC_ERR_USER,"B should be of type %s",MATHYPRE);
1023d501dc42Sstefano_zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATHYPRE,&ishypre);CHKERRQ(ierr);
1024d501dc42Sstefano_zampini   if (!ishypre) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_USER,"A should be of type %s",MATHYPRE);
1025d501dc42Sstefano_zampini   hA = (Mat_HYPRE*)A->data;
1026d501dc42Sstefano_zampini   hB = (Mat_HYPRE*)B->data;
1027d501dc42Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type));
1028d501dc42Sstefano_zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
1029d501dc42Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hB->ij,&type));
1030d501dc42Sstefano_zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
1031d501dc42Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&Aparcsr));
1032d501dc42Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hB->ij,(void**)&Bparcsr));
1033d501dc42Sstefano_zampini   ierr = MatHYPRE_ParCSR_MatMatMult(Aparcsr,Bparcsr,&ABparcsr);CHKERRQ(ierr);
1034d501dc42Sstefano_zampini   ierr = MatCreateFromParCSR(ABparcsr,MATHYPRE,PETSC_OWN_POINTER,&D);CHKERRQ(ierr);
10354222ddf1SHong Zhang 
1036d501dc42Sstefano_zampini   /* need to use HeaderReplace because HeaderMerge messes up with the communicator */
10374222ddf1SHong Zhang   product    = C->product;  /* save it from MatHeaderReplace() */
10384222ddf1SHong Zhang   C->product = NULL;
1039d501dc42Sstefano_zampini   ierr = MatHeaderReplace(C,&D);CHKERRQ(ierr);
10404222ddf1SHong Zhang   C->product = product;
1041d501dc42Sstefano_zampini   C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE;
10424222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
1043d501dc42Sstefano_zampini   PetscFunctionReturn(0);
1044d501dc42Sstefano_zampini }
1045d501dc42Sstefano_zampini 
10463dad0653Sstefano_zampini PETSC_INTERN PetscErrorCode MatTransposeMatMatMultNumeric_AIJ_AIJ_AIJ_wHYPRE(Mat A,Mat B,Mat C,Mat D)
104720e1dc0dSstefano_zampini {
104820e1dc0dSstefano_zampini   Mat                E;
10496abb4441SStefano Zampini   hypre_ParCSRMatrix *hA,*hB,*hC,*hABC = NULL;
105020e1dc0dSstefano_zampini   PetscErrorCode     ierr;
105120e1dc0dSstefano_zampini 
105220e1dc0dSstefano_zampini   PetscFunctionBegin;
105320e1dc0dSstefano_zampini   ierr = MatAIJGetParCSR_Private(A,&hA);CHKERRQ(ierr);
105420e1dc0dSstefano_zampini   ierr = MatAIJGetParCSR_Private(B,&hB);CHKERRQ(ierr);
105520e1dc0dSstefano_zampini   ierr = MatAIJGetParCSR_Private(C,&hC);CHKERRQ(ierr);
105620e1dc0dSstefano_zampini   ierr = MatHYPRE_ParCSR_RAP(hA,hB,hC,&hABC);CHKERRQ(ierr);
105720e1dc0dSstefano_zampini   ierr = MatCreateFromParCSR(hABC,MATAIJ,PETSC_OWN_POINTER,&E);CHKERRQ(ierr);
105820e1dc0dSstefano_zampini   ierr = MatHeaderMerge(D,&E);CHKERRQ(ierr);
105920e1dc0dSstefano_zampini   ierr = MatAIJRestoreParCSR_Private(A,&hA);CHKERRQ(ierr);
106020e1dc0dSstefano_zampini   ierr = MatAIJRestoreParCSR_Private(B,&hB);CHKERRQ(ierr);
106120e1dc0dSstefano_zampini   ierr = MatAIJRestoreParCSR_Private(C,&hC);CHKERRQ(ierr);
106220e1dc0dSstefano_zampini   PetscFunctionReturn(0);
106320e1dc0dSstefano_zampini }
106420e1dc0dSstefano_zampini 
10654222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatTransposeMatMatMultSymbolic_AIJ_AIJ_AIJ_wHYPRE(Mat A,Mat B,Mat C,PetscReal fill,Mat D)
106620e1dc0dSstefano_zampini {
106720e1dc0dSstefano_zampini   PetscErrorCode ierr;
106820e1dc0dSstefano_zampini 
106920e1dc0dSstefano_zampini   PetscFunctionBegin;
10704222ddf1SHong Zhang   ierr = MatSetType(D,MATAIJ);CHKERRQ(ierr);
107120e1dc0dSstefano_zampini   PetscFunctionReturn(0);
107220e1dc0dSstefano_zampini }
107320e1dc0dSstefano_zampini 
10744222ddf1SHong Zhang /* ---------------------------------------------------- */
10754222ddf1SHong Zhang static PetscErrorCode MatProductSymbolic_AB_HYPRE(Mat C)
10764222ddf1SHong Zhang {
10774222ddf1SHong Zhang   PetscFunctionBegin;
10784222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
10794222ddf1SHong Zhang   PetscFunctionReturn(0);
10804222ddf1SHong Zhang }
10814222ddf1SHong Zhang 
10824222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_HYPRE_AB(Mat C)
10834222ddf1SHong Zhang {
10844222ddf1SHong Zhang   PetscErrorCode ierr;
10854222ddf1SHong Zhang   Mat_Product    *product = C->product;
10864222ddf1SHong Zhang   PetscBool      Ahypre;
10874222ddf1SHong Zhang 
10884222ddf1SHong Zhang   PetscFunctionBegin;
10894222ddf1SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)product->A,MATHYPRE,&Ahypre);CHKERRQ(ierr);
10904222ddf1SHong Zhang   if (Ahypre) { /* A is a Hypre matrix */
10914222ddf1SHong Zhang     ierr = MatSetType(C,MATHYPRE);CHKERRQ(ierr);
10924222ddf1SHong Zhang     C->ops->productsymbolic = MatProductSymbolic_AB_HYPRE;
10934222ddf1SHong Zhang     C->ops->matmultnumeric  = MatMatMultNumeric_HYPRE_HYPRE;
10944222ddf1SHong Zhang     PetscFunctionReturn(0);
10956718818eSStefano Zampini   }
10964222ddf1SHong Zhang   PetscFunctionReturn(0);
10974222ddf1SHong Zhang }
10984222ddf1SHong Zhang 
10994222ddf1SHong Zhang static PetscErrorCode MatProductSymbolic_PtAP_HYPRE(Mat C)
11004222ddf1SHong Zhang {
11014222ddf1SHong Zhang   PetscFunctionBegin;
11024222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
11034222ddf1SHong Zhang   PetscFunctionReturn(0);
11044222ddf1SHong Zhang }
11054222ddf1SHong Zhang 
11064222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_HYPRE_PtAP(Mat C)
11074222ddf1SHong Zhang {
11084222ddf1SHong Zhang   PetscErrorCode ierr;
11094222ddf1SHong Zhang   Mat_Product    *product = C->product;
11104222ddf1SHong Zhang   PetscBool      flg;
11114222ddf1SHong Zhang   PetscInt       type = 0;
11124222ddf1SHong Zhang   const char     *outTypes[4] = {"aij","seqaij","mpiaij","hypre"};
11134222ddf1SHong Zhang   PetscInt       ntype = 4;
11144222ddf1SHong Zhang   Mat            A = product->A;
11154222ddf1SHong Zhang   PetscBool      Ahypre;
11164222ddf1SHong Zhang 
11174222ddf1SHong Zhang   PetscFunctionBegin;
11184222ddf1SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)A,MATHYPRE,&Ahypre);CHKERRQ(ierr);
11194222ddf1SHong Zhang   if (Ahypre) { /* A is a Hypre matrix */
11204222ddf1SHong Zhang     ierr = MatSetType(C,MATHYPRE);CHKERRQ(ierr);
11214222ddf1SHong Zhang     C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE;
11224222ddf1SHong Zhang     C->ops->ptapnumeric     = MatPtAPNumeric_HYPRE_HYPRE;
11234222ddf1SHong Zhang     PetscFunctionReturn(0);
11244222ddf1SHong Zhang   }
11254222ddf1SHong Zhang 
11264222ddf1SHong Zhang   /* A is AIJ, P is Hypre, C = PtAP can be either AIJ or Hypre format */
11274222ddf1SHong Zhang   /* Get runtime option */
11284222ddf1SHong Zhang   if (product->api_user) {
11294222ddf1SHong Zhang     ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)C),((PetscObject)C)->prefix,"MatPtAP_HYPRE","Mat");CHKERRQ(ierr);
11304222ddf1SHong Zhang     ierr = PetscOptionsEList("-matptap_hypre_outtype","MatPtAP outtype","MatPtAP outtype",outTypes,ntype,outTypes[type],&type,&flg);CHKERRQ(ierr);
11314222ddf1SHong Zhang     ierr = PetscOptionsEnd();CHKERRQ(ierr);
11324222ddf1SHong Zhang   } else {
11334222ddf1SHong Zhang     ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)C),((PetscObject)C)->prefix,"MatProduct_PtAP_HYPRE","Mat");CHKERRQ(ierr);
11344222ddf1SHong Zhang     ierr = PetscOptionsEList("-matproduct_ptap_hypre_outtype","MatProduct_PtAP outtype","MatProduct_PtAP",outTypes,ntype,outTypes[type],&type,&flg);CHKERRQ(ierr);
11354222ddf1SHong Zhang     ierr = PetscOptionsEnd();CHKERRQ(ierr);
11364222ddf1SHong Zhang   }
11374222ddf1SHong Zhang 
11384222ddf1SHong Zhang   if (type == 0 || type == 1 || type == 2) {
11394222ddf1SHong Zhang     ierr = MatSetType(C,MATAIJ);CHKERRQ(ierr);
11404222ddf1SHong Zhang   } else if (type == 3) {
11414222ddf1SHong Zhang     ierr = MatSetType(C,MATHYPRE);CHKERRQ(ierr);
11424222ddf1SHong Zhang   } else SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_SUP,"MatPtAP outtype is not supported");
11434222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE;
11444222ddf1SHong Zhang   C->ops->ptapnumeric     = MatPtAPNumeric_AIJ_HYPRE;
11454222ddf1SHong Zhang   PetscFunctionReturn(0);
11464222ddf1SHong Zhang }
11474222ddf1SHong Zhang 
11484222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_HYPRE(Mat C)
11494222ddf1SHong Zhang {
11504222ddf1SHong Zhang   PetscErrorCode ierr;
11514222ddf1SHong Zhang   Mat_Product    *product = C->product;
11524222ddf1SHong Zhang 
11534222ddf1SHong Zhang   PetscFunctionBegin;
11544222ddf1SHong Zhang   switch (product->type) {
11554222ddf1SHong Zhang   case MATPRODUCT_AB:
11564222ddf1SHong Zhang     ierr = MatProductSetFromOptions_HYPRE_AB(C);CHKERRQ(ierr);
11574222ddf1SHong Zhang     break;
11584222ddf1SHong Zhang   case MATPRODUCT_PtAP:
11594222ddf1SHong Zhang     ierr = MatProductSetFromOptions_HYPRE_PtAP(C);CHKERRQ(ierr);
11604222ddf1SHong Zhang     break;
11616718818eSStefano Zampini   default:
11626718818eSStefano Zampini     break;
11634222ddf1SHong Zhang   }
11644222ddf1SHong Zhang   PetscFunctionReturn(0);
11654222ddf1SHong Zhang }
11664222ddf1SHong Zhang 
11674222ddf1SHong Zhang /* -------------------------------------------------------- */
11684222ddf1SHong Zhang 
1169ea9daf28SStefano Zampini static PetscErrorCode MatMultTranspose_HYPRE(Mat A, Vec x, Vec y)
117063c07aadSStefano Zampini {
117163c07aadSStefano Zampini   PetscErrorCode ierr;
117263c07aadSStefano Zampini 
117363c07aadSStefano Zampini   PetscFunctionBegin;
1174414bd5c3SStefano Zampini   ierr = MatHYPRE_MultKernel_Private(A,1.0,x,0.0,y,PETSC_TRUE);CHKERRQ(ierr);
117563c07aadSStefano Zampini   PetscFunctionReturn(0);
117663c07aadSStefano Zampini }
117763c07aadSStefano Zampini 
1178ea9daf28SStefano Zampini static PetscErrorCode MatMult_HYPRE(Mat A, Vec x, Vec y)
117963c07aadSStefano Zampini {
118063c07aadSStefano Zampini   PetscErrorCode ierr;
118163c07aadSStefano Zampini 
118263c07aadSStefano Zampini   PetscFunctionBegin;
1183414bd5c3SStefano Zampini   ierr = MatHYPRE_MultKernel_Private(A,1.0,x,0.0,y,PETSC_FALSE);CHKERRQ(ierr);
118463c07aadSStefano Zampini   PetscFunctionReturn(0);
118563c07aadSStefano Zampini }
118663c07aadSStefano Zampini 
1187414bd5c3SStefano Zampini static PetscErrorCode MatMultAdd_HYPRE(Mat A, Vec x, Vec y, Vec z)
1188414bd5c3SStefano Zampini {
1189414bd5c3SStefano Zampini   PetscErrorCode ierr;
1190414bd5c3SStefano Zampini 
1191414bd5c3SStefano Zampini   PetscFunctionBegin;
1192414bd5c3SStefano Zampini   if (y != z) {
1193414bd5c3SStefano Zampini     ierr = VecCopy(y,z);CHKERRQ(ierr);
1194414bd5c3SStefano Zampini   }
1195414bd5c3SStefano Zampini   ierr = MatHYPRE_MultKernel_Private(A,1.0,x,1.0,z,PETSC_FALSE);CHKERRQ(ierr);
1196414bd5c3SStefano Zampini   PetscFunctionReturn(0);
1197414bd5c3SStefano Zampini }
1198414bd5c3SStefano Zampini 
1199414bd5c3SStefano Zampini static PetscErrorCode MatMultTransposeAdd_HYPRE(Mat A, Vec x, Vec y, Vec z)
1200414bd5c3SStefano Zampini {
1201414bd5c3SStefano Zampini   PetscErrorCode ierr;
1202414bd5c3SStefano Zampini 
1203414bd5c3SStefano Zampini   PetscFunctionBegin;
1204414bd5c3SStefano Zampini   if (y != z) {
1205414bd5c3SStefano Zampini     ierr = VecCopy(y,z);CHKERRQ(ierr);
1206414bd5c3SStefano Zampini   }
1207414bd5c3SStefano Zampini   ierr = MatHYPRE_MultKernel_Private(A,1.0,x,1.0,z,PETSC_TRUE);CHKERRQ(ierr);
1208414bd5c3SStefano Zampini   PetscFunctionReturn(0);
1209414bd5c3SStefano Zampini }
1210414bd5c3SStefano Zampini 
1211414bd5c3SStefano Zampini /* y = a * A * x + b * y or y = a * A^t * x + b * y depending on trans */
121239accc25SStefano Zampini static PetscErrorCode MatHYPRE_MultKernel_Private(Mat A, HYPRE_Complex a, Vec x, HYPRE_Complex b, Vec y, PetscBool trans)
121363c07aadSStefano Zampini {
121463c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE*)A->data;
121563c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
121663c07aadSStefano Zampini   hypre_ParVector    *hx,*hy;
121763c07aadSStefano Zampini   PetscErrorCode     ierr;
121863c07aadSStefano Zampini 
121963c07aadSStefano Zampini   PetscFunctionBegin;
122063c07aadSStefano Zampini   if (trans) {
12216ea7df73SStefano Zampini     ierr = VecHYPRE_IJVectorPushVecRead(hA->b,x);CHKERRQ(ierr);
12226ea7df73SStefano Zampini     if (b != 0.0) { ierr = VecHYPRE_IJVectorPushVec(hA->x,y);CHKERRQ(ierr); }
12236ea7df73SStefano Zampini     else { ierr = VecHYPRE_IJVectorPushVecWrite(hA->x,y);CHKERRQ(ierr); }
12246ea7df73SStefano Zampini     PetscStackCallStandard(HYPRE_IJVectorGetObject,(hA->b->ij,(void**)&hx));
12256ea7df73SStefano Zampini     PetscStackCallStandard(HYPRE_IJVectorGetObject,(hA->x->ij,(void**)&hy));
122663c07aadSStefano Zampini   } else {
12276ea7df73SStefano Zampini     ierr = VecHYPRE_IJVectorPushVecRead(hA->x,x);CHKERRQ(ierr);
12286ea7df73SStefano Zampini     if (b != 0.0) { ierr = VecHYPRE_IJVectorPushVec(hA->b,y);CHKERRQ(ierr); }
12296ea7df73SStefano Zampini     else { ierr = VecHYPRE_IJVectorPushVecWrite(hA->b,y);CHKERRQ(ierr); }
12306ea7df73SStefano Zampini     PetscStackCallStandard(HYPRE_IJVectorGetObject,(hA->x->ij,(void**)&hx));
12316ea7df73SStefano Zampini     PetscStackCallStandard(HYPRE_IJVectorGetObject,(hA->b->ij,(void**)&hy));
123263c07aadSStefano Zampini   }
12336ea7df73SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&parcsr));
12346ea7df73SStefano Zampini   if (trans) {
12356ea7df73SStefano Zampini     PetscStackCallStandard(hypre_ParCSRMatrixMatvecT,(a,parcsr,hx,b,hy));
12366ea7df73SStefano Zampini   } else {
12376ea7df73SStefano Zampini     PetscStackCallStandard(hypre_ParCSRMatrixMatvec,(a,parcsr,hx,b,hy));
12386ea7df73SStefano Zampini   }
12396ea7df73SStefano Zampini   ierr = VecHYPRE_IJVectorPopVec(hA->x);CHKERRQ(ierr);
12406ea7df73SStefano Zampini   ierr = VecHYPRE_IJVectorPopVec(hA->b);CHKERRQ(ierr);
124163c07aadSStefano Zampini   PetscFunctionReturn(0);
124263c07aadSStefano Zampini }
124363c07aadSStefano Zampini 
1244ea9daf28SStefano Zampini static PetscErrorCode MatDestroy_HYPRE(Mat A)
124563c07aadSStefano Zampini {
124663c07aadSStefano Zampini   Mat_HYPRE      *hA = (Mat_HYPRE*)A->data;
124763c07aadSStefano Zampini   PetscErrorCode ierr;
124863c07aadSStefano Zampini 
124963c07aadSStefano Zampini   PetscFunctionBegin;
12506ea7df73SStefano Zampini   ierr = VecHYPRE_IJVectorDestroy(&hA->x);CHKERRQ(ierr);
12516ea7df73SStefano Zampini   ierr = VecHYPRE_IJVectorDestroy(&hA->b);CHKERRQ(ierr);
1252978814f1SStefano Zampini   if (hA->ij) {
1253978814f1SStefano Zampini     if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL;
1254978814f1SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixDestroy,(hA->ij));
1255978814f1SStefano Zampini   }
1256ffc4695bSBarry Smith   if (hA->comm) {ierr = MPI_Comm_free(&hA->comm);CHKERRMPI(ierr);}
1257c69f721fSFande Kong 
1258c69f721fSFande Kong   ierr = MatStashDestroy_Private(&A->stash);CHKERRQ(ierr);
1259c69f721fSFande Kong 
1260c69f721fSFande Kong   ierr = PetscFree(hA->array);CHKERRQ(ierr);
1261c69f721fSFande Kong 
126263c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_hypre_aij_C",NULL);CHKERRQ(ierr);
12632df22349SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_hypre_is_C",NULL);CHKERRQ(ierr);
12644222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_hypre_C",NULL);CHKERRQ(ierr);
12654222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_mpiaij_hypre_C",NULL);CHKERRQ(ierr);
1266d975228cSstefano_zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatHYPRESetPreallocation_C",NULL);CHKERRQ(ierr);
1267dd9c0a25Sstefano_zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatHYPREGetParCSR_C",NULL);CHKERRQ(ierr);
126863c07aadSStefano Zampini   ierr = PetscFree(A->data);CHKERRQ(ierr);
126963c07aadSStefano Zampini   PetscFunctionReturn(0);
127063c07aadSStefano Zampini }
127163c07aadSStefano Zampini 
1272ea9daf28SStefano Zampini static PetscErrorCode MatSetUp_HYPRE(Mat A)
127363c07aadSStefano Zampini {
12744ec6421dSstefano_zampini   PetscErrorCode ierr;
12754ec6421dSstefano_zampini 
12764ec6421dSstefano_zampini   PetscFunctionBegin;
12774ec6421dSstefano_zampini   ierr = MatHYPRESetPreallocation(A,PETSC_DEFAULT,NULL,PETSC_DEFAULT,NULL);CHKERRQ(ierr);
12784ec6421dSstefano_zampini   PetscFunctionReturn(0);
12794ec6421dSstefano_zampini }
12804ec6421dSstefano_zampini 
12816ea7df73SStefano Zampini //TODO FIX hypre_CSRMatrixMatvecOutOfPlace
12826ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
12836ea7df73SStefano Zampini static PetscErrorCode MatBindToCPU_HYPRE(Mat A, PetscBool bind)
12846ea7df73SStefano Zampini {
12856ea7df73SStefano Zampini   Mat_HYPRE            *hA = (Mat_HYPRE*)A->data;
12866ea7df73SStefano Zampini   HYPRE_MemoryLocation hmem = bind ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE;
12876ea7df73SStefano Zampini   PetscErrorCode       ierr;
12886ea7df73SStefano Zampini 
12896ea7df73SStefano Zampini   PetscFunctionBegin;
12906ea7df73SStefano Zampini   A->boundtocpu = bind;
12916ea7df73SStefano Zampini   if (hypre_IJMatrixAssembleFlag(hA->ij) && hmem != hypre_IJMatrixMemoryLocation(hA->ij)) {
12926ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
12936ea7df73SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&parcsr));
12946ea7df73SStefano Zampini     PetscStackCallStandard(hypre_ParCSRMatrixMigrate,(parcsr, hmem));
12956ea7df73SStefano Zampini   }
12966ea7df73SStefano Zampini   if (hA->x) { ierr  = VecHYPRE_IJBindToCPU(hA->x,bind);CHKERRQ(ierr); }
12976ea7df73SStefano Zampini   if (hA->b) { ierr  = VecHYPRE_IJBindToCPU(hA->b,bind);CHKERRQ(ierr); }
12986ea7df73SStefano Zampini   PetscFunctionReturn(0);
12996ea7df73SStefano Zampini }
13006ea7df73SStefano Zampini #endif
13016ea7df73SStefano Zampini 
13024ec6421dSstefano_zampini static PetscErrorCode MatAssemblyEnd_HYPRE(Mat A, MatAssemblyType mode)
13034ec6421dSstefano_zampini {
130463c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE*)A->data;
1305c69f721fSFande Kong   PetscMPIInt        n;
1306c69f721fSFande Kong   PetscInt           i,j,rstart,ncols,flg;
1307c69f721fSFande Kong   PetscInt           *row,*col;
1308c69f721fSFande Kong   PetscScalar        *val;
130963c07aadSStefano Zampini   PetscErrorCode     ierr;
131063c07aadSStefano Zampini 
131163c07aadSStefano Zampini   PetscFunctionBegin;
13124ec6421dSstefano_zampini   if (mode == MAT_FLUSH_ASSEMBLY) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MAT_FLUSH_ASSEMBLY currently not supported with MATHYPRE");
1313c69f721fSFande Kong 
1314c69f721fSFande Kong   if (!A->nooffprocentries) {
1315c69f721fSFande Kong     while (1) {
1316c69f721fSFande Kong       ierr = MatStashScatterGetMesg_Private(&A->stash,&n,&row,&col,&val,&flg);CHKERRQ(ierr);
1317c69f721fSFande Kong       if (!flg) break;
1318c69f721fSFande Kong 
1319c69f721fSFande Kong       for (i=0; i<n;) {
1320c69f721fSFande Kong         /* Now identify the consecutive vals belonging to the same row */
1321c69f721fSFande Kong         for (j=i,rstart=row[j]; j<n; j++) {
1322c69f721fSFande Kong           if (row[j] != rstart) break;
1323c69f721fSFande Kong         }
1324c69f721fSFande Kong         if (j < n) ncols = j-i;
1325c69f721fSFande Kong         else       ncols = n-i;
1326c69f721fSFande Kong         /* Now assemble all these values with a single function call */
1327c69f721fSFande Kong         ierr = MatSetValues_HYPRE(A,1,row+i,ncols,col+i,val+i,A->insertmode);CHKERRQ(ierr);
1328c69f721fSFande Kong 
1329c69f721fSFande Kong         i = j;
1330c69f721fSFande Kong       }
1331c69f721fSFande Kong     }
1332c69f721fSFande Kong     ierr = MatStashScatterEnd_Private(&A->stash);CHKERRQ(ierr);
1333c69f721fSFande Kong   }
1334c69f721fSFande Kong 
13354ec6421dSstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixAssemble,(hA->ij));
1336336664bdSPierre Jolivet   /* The assembly routine destroys the aux_matrix, we recreate it here by calling HYPRE_IJMatrixInitialize */
1337336664bdSPierre 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 */
1338336664bdSPierre Jolivet   if (!hA->sorted_full) {
1339af1cf968SStefano Zampini     hypre_AuxParCSRMatrix *aux_matrix;
1340af1cf968SStefano Zampini 
1341af1cf968SStefano Zampini     /* call destroy just to make sure we do not leak anything */
1342af1cf968SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(hA->ij);
1343af1cf968SStefano Zampini     PetscStackCallStandard(hypre_AuxParCSRMatrixDestroy,(aux_matrix));
1344af1cf968SStefano Zampini     hypre_IJMatrixTranslator(hA->ij) = NULL;
1345af1cf968SStefano Zampini 
1346af1cf968SStefano Zampini     /* Initialize with assembled flag -> it only recreates the aux_par_matrix */
1347af1cf968SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixInitialize,(hA->ij));
1348af1cf968SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(hA->ij);
13496ea7df73SStefano Zampini     if (aux_matrix) {
1350af1cf968SStefano Zampini       hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1; /* see comment in MatHYPRESetPreallocation_HYPRE */
135122235d61SPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LT(2,19,0)
1352af1cf968SStefano Zampini       PetscStackCallStandard(hypre_AuxParCSRMatrixInitialize,(aux_matrix));
135322235d61SPierre Jolivet #else
135422235d61SPierre Jolivet       PetscStackCallStandard(hypre_AuxParCSRMatrixInitialize_v2,(aux_matrix,HYPRE_MEMORY_HOST));
135522235d61SPierre Jolivet #endif
1356af1cf968SStefano Zampini     }
13576ea7df73SStefano Zampini   }
13586ea7df73SStefano Zampini   {
13596ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
13606ea7df73SStefano Zampini 
13616ea7df73SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&parcsr));
13626ea7df73SStefano Zampini     if (!hypre_ParCSRMatrixCommPkg(parcsr)) PetscStackCallStandard(hypre_MatvecCommPkgCreate,(parcsr));
13636ea7df73SStefano Zampini   }
13646ea7df73SStefano Zampini   if (!hA->x) { ierr = VecHYPRE_IJVectorCreate(A->cmap,&hA->x);CHKERRQ(ierr); }
13656ea7df73SStefano Zampini   if (!hA->b) { ierr = VecHYPRE_IJVectorCreate(A->rmap,&hA->b);CHKERRQ(ierr); }
13666ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
13676ea7df73SStefano Zampini   ierr = MatBindToCPU_HYPRE(A,A->boundtocpu);CHKERRQ(ierr);
13686ea7df73SStefano Zampini #endif
136963c07aadSStefano Zampini   PetscFunctionReturn(0);
137063c07aadSStefano Zampini }
137163c07aadSStefano Zampini 
1372c69f721fSFande Kong static PetscErrorCode MatGetArray_HYPRE(Mat A, PetscInt size, void **array)
1373c69f721fSFande Kong {
1374c69f721fSFande Kong   Mat_HYPRE          *hA = (Mat_HYPRE*)A->data;
1375c69f721fSFande Kong   PetscErrorCode     ierr;
1376c69f721fSFande Kong 
1377c69f721fSFande Kong   PetscFunctionBegin;
1378c69f721fSFande Kong   if (!hA->available) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Temporary space is in use");
1379c69f721fSFande Kong 
138039accc25SStefano Zampini   if (hA->size >= size) {
138139accc25SStefano Zampini     *array = hA->array;
138239accc25SStefano Zampini   } else {
1383c69f721fSFande Kong     ierr = PetscFree(hA->array);CHKERRQ(ierr);
1384c69f721fSFande Kong     hA->size = size;
1385c69f721fSFande Kong     ierr = PetscMalloc(hA->size,&hA->array);CHKERRQ(ierr);
1386c69f721fSFande Kong     *array = hA->array;
1387c69f721fSFande Kong   }
1388c69f721fSFande Kong 
1389c69f721fSFande Kong   hA->available = PETSC_FALSE;
1390c69f721fSFande Kong   PetscFunctionReturn(0);
1391c69f721fSFande Kong }
1392c69f721fSFande Kong 
1393708542d2SFande Kong static PetscErrorCode MatRestoreArray_HYPRE(Mat A, void **array)
1394c69f721fSFande Kong {
1395c69f721fSFande Kong   Mat_HYPRE          *hA = (Mat_HYPRE*)A->data;
1396c69f721fSFande Kong 
1397c69f721fSFande Kong   PetscFunctionBegin;
1398c69f721fSFande Kong   *array = NULL;
1399c69f721fSFande Kong   hA->available = PETSC_TRUE;
1400c69f721fSFande Kong   PetscFunctionReturn(0);
1401c69f721fSFande Kong }
1402c69f721fSFande Kong 
14036ea7df73SStefano Zampini static PetscErrorCode MatSetValues_HYPRE(Mat A, PetscInt nr, const PetscInt rows[], PetscInt nc, const PetscInt cols[], const PetscScalar v[], InsertMode ins)
1404d975228cSstefano_zampini {
1405d975228cSstefano_zampini   Mat_HYPRE      *hA = (Mat_HYPRE*)A->data;
1406d975228cSstefano_zampini   PetscScalar    *vals = (PetscScalar *)v;
140739accc25SStefano Zampini   HYPRE_Complex  *sscr;
1408c69f721fSFande Kong   PetscInt       *cscr[2];
1409c69f721fSFande Kong   PetscInt       i,nzc;
141008defe43SFande Kong   void           *array = NULL;
1411d975228cSstefano_zampini   PetscErrorCode ierr;
1412d975228cSstefano_zampini 
1413d975228cSstefano_zampini   PetscFunctionBegin;
141439accc25SStefano Zampini   ierr = MatGetArray_HYPRE(A,sizeof(PetscInt)*(2*nc)+sizeof(HYPRE_Complex)*nc*nr,&array);CHKERRQ(ierr);
1415c69f721fSFande Kong   cscr[0] = (PetscInt*)array;
1416c69f721fSFande Kong   cscr[1] = ((PetscInt*)array)+nc;
141739accc25SStefano Zampini   sscr = (HYPRE_Complex*)(((PetscInt*)array)+nc*2);
1418d975228cSstefano_zampini   for (i=0,nzc=0;i<nc;i++) {
1419d975228cSstefano_zampini     if (cols[i] >= 0) {
1420d975228cSstefano_zampini       cscr[0][nzc  ] = cols[i];
1421d975228cSstefano_zampini       cscr[1][nzc++] = i;
1422d975228cSstefano_zampini     }
1423d975228cSstefano_zampini   }
1424c69f721fSFande Kong   if (!nzc) {
1425708542d2SFande Kong     ierr = MatRestoreArray_HYPRE(A,&array);CHKERRQ(ierr);
1426c69f721fSFande Kong     PetscFunctionReturn(0);
1427c69f721fSFande Kong   }
1428d975228cSstefano_zampini 
14296ea7df73SStefano Zampini #if 0 //defined(PETSC_HAVE_HYPRE_DEVICE)
14306ea7df73SStefano Zampini   if (HYPRE_MEMORY_HOST != hypre_IJMatrixMemoryLocation(hA->ij)) {
14316ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
14326ea7df73SStefano Zampini 
14336ea7df73SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&parcsr));
14346ea7df73SStefano Zampini     PetscStackCallStandard(hypre_ParCSRMatrixMigrate,(parcsr, HYPRE_MEMORY_HOST));
14356ea7df73SStefano Zampini   }
14366ea7df73SStefano Zampini #endif
14376ea7df73SStefano Zampini 
1438d975228cSstefano_zampini   if (ins == ADD_VALUES) {
1439d975228cSstefano_zampini     for (i=0;i<nr;i++) {
14406ea7df73SStefano Zampini       if (rows[i] >= 0) {
1441d975228cSstefano_zampini         PetscInt  j;
14422cf14000SStefano Zampini         HYPRE_Int hnc = (HYPRE_Int)nzc;
14432cf14000SStefano Zampini 
14442cf14000SStefano Zampini         if ((PetscInt)hnc != nzc) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Hypre overflow! number of columns %D for row %D",nzc,rows[i]);
14451e1ea65dSPierre Jolivet         for (j=0;j<nzc;j++) { ierr = PetscHYPREScalarCast(vals[cscr[1][j]],&sscr[j]);CHKERRQ(ierr); }
14462cf14000SStefano Zampini         PetscStackCallStandard(HYPRE_IJMatrixAddToValues,(hA->ij,1,&hnc,(HYPRE_BigInt*)(rows+i),(HYPRE_BigInt*)cscr[0],sscr));
1447d975228cSstefano_zampini       }
1448d975228cSstefano_zampini       vals += nc;
1449d975228cSstefano_zampini     }
1450d975228cSstefano_zampini   } else { /* INSERT_VALUES */
1451d975228cSstefano_zampini     PetscInt rst,ren;
1452c69f721fSFande Kong 
1453c6698e78SStefano Zampini     ierr = MatGetOwnershipRange(A,&rst,&ren);CHKERRQ(ierr);
1454d975228cSstefano_zampini     for (i=0;i<nr;i++) {
14556ea7df73SStefano Zampini       if (rows[i] >= 0) {
1456d975228cSstefano_zampini         PetscInt  j;
14572cf14000SStefano Zampini         HYPRE_Int hnc = (HYPRE_Int)nzc;
14582cf14000SStefano Zampini 
14592cf14000SStefano Zampini         if ((PetscInt)hnc != nzc) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Hypre overflow! number of columns %D for row %D",nzc,rows[i]);
14601e1ea65dSPierre Jolivet         for (j=0;j<nzc;j++) { ierr = PetscHYPREScalarCast(vals[cscr[1][j]],&sscr[j]);CHKERRQ(ierr); }
1461c69f721fSFande Kong         /* nonlocal values */
146239accc25SStefano Zampini         if (rows[i] < rst || rows[i] >= ren) { ierr = MatStashValuesRow_Private(&A->stash,rows[i],nzc,cscr[0],(PetscScalar*)sscr,PETSC_FALSE);CHKERRQ(ierr); }
1463c69f721fSFande Kong         /* local values */
14642cf14000SStefano Zampini         else PetscStackCallStandard(HYPRE_IJMatrixSetValues,(hA->ij,1,&hnc,(HYPRE_BigInt*)(rows+i),(HYPRE_BigInt*)cscr[0],sscr));
1465d975228cSstefano_zampini       }
1466d975228cSstefano_zampini       vals += nc;
1467d975228cSstefano_zampini     }
1468d975228cSstefano_zampini   }
1469c69f721fSFande Kong 
1470708542d2SFande Kong   ierr = MatRestoreArray_HYPRE(A,&array);CHKERRQ(ierr);
1471d975228cSstefano_zampini   PetscFunctionReturn(0);
1472d975228cSstefano_zampini }
1473d975228cSstefano_zampini 
1474d975228cSstefano_zampini static PetscErrorCode MatHYPRESetPreallocation_HYPRE(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[])
1475d975228cSstefano_zampini {
1476d975228cSstefano_zampini   Mat_HYPRE      *hA = (Mat_HYPRE*)A->data;
14777d968826Sstefano_zampini   HYPRE_Int      *hdnnz,*honnz;
147806a29025Sstefano_zampini   PetscInt       i,rs,re,cs,ce,bs;
1479d975228cSstefano_zampini   PetscMPIInt    size;
1480d975228cSstefano_zampini   PetscErrorCode ierr;
1481d975228cSstefano_zampini 
1482d975228cSstefano_zampini   PetscFunctionBegin;
148306a29025Sstefano_zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
1484d975228cSstefano_zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1485d975228cSstefano_zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1486d975228cSstefano_zampini   rs   = A->rmap->rstart;
1487d975228cSstefano_zampini   re   = A->rmap->rend;
1488d975228cSstefano_zampini   cs   = A->cmap->rstart;
1489d975228cSstefano_zampini   ce   = A->cmap->rend;
1490d975228cSstefano_zampini   if (!hA->ij) {
1491d975228cSstefano_zampini     PetscStackCallStandard(HYPRE_IJMatrixCreate,(hA->comm,rs,re-1,cs,ce-1,&hA->ij));
1492d975228cSstefano_zampini     PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(hA->ij,HYPRE_PARCSR));
1493d975228cSstefano_zampini   } else {
14942cf14000SStefano Zampini     HYPRE_BigInt hrs,hre,hcs,hce;
1495d975228cSstefano_zampini     PetscStackCallStandard(HYPRE_IJMatrixGetLocalRange,(hA->ij,&hrs,&hre,&hcs,&hce));
14962cf14000SStefano Zampini     if (hre-hrs+1 != re -rs) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Inconsistent local rows: IJMatrix [%D,%D), PETSc [%D,%D)",hrs,hre+1,rs,re);
14972cf14000SStefano Zampini     if (hce-hcs+1 != ce -cs) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Inconsistent local cols: IJMatrix [%D,%D), PETSc [%D,%D)",hcs,hce+1,cs,ce);
1498d975228cSstefano_zampini   }
149906a29025Sstefano_zampini   if (dnz == PETSC_DEFAULT || dnz == PETSC_DECIDE) dnz = 10*bs;
150006a29025Sstefano_zampini   if (onz == PETSC_DEFAULT || onz == PETSC_DECIDE) onz = 10*bs;
150106a29025Sstefano_zampini 
1502d975228cSstefano_zampini   if (!dnnz) {
1503d975228cSstefano_zampini     ierr = PetscMalloc1(A->rmap->n,&hdnnz);CHKERRQ(ierr);
1504d975228cSstefano_zampini     for (i=0;i<A->rmap->n;i++) hdnnz[i] = dnz;
1505d975228cSstefano_zampini   } else {
15067d968826Sstefano_zampini     hdnnz = (HYPRE_Int*)dnnz;
1507d975228cSstefano_zampini   }
1508ffc4695bSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRMPI(ierr);
1509d975228cSstefano_zampini   if (size > 1) {
1510ddbeb582SStefano Zampini     hypre_AuxParCSRMatrix *aux_matrix;
1511d975228cSstefano_zampini     if (!onnz) {
1512d975228cSstefano_zampini       ierr = PetscMalloc1(A->rmap->n,&honnz);CHKERRQ(ierr);
1513d975228cSstefano_zampini       for (i=0;i<A->rmap->n;i++) honnz[i] = onz;
151422235d61SPierre Jolivet     } else honnz = (HYPRE_Int*)onnz;
1515ddbeb582SStefano Zampini     /* SetDiagOffdSizes sets hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0, since it seems
1516ddbeb582SStefano Zampini        they assume the user will input the entire row values, properly sorted
1517336664bdSPierre Jolivet        In PETSc, we don't make such an assumption and set this flag to 1,
1518336664bdSPierre Jolivet        unless the option MAT_SORTED_FULL is set to true.
1519ddbeb582SStefano Zampini        Also, to avoid possible memory leaks, we destroy and recreate the translator
1520ddbeb582SStefano Zampini        This has to be done here, as HYPRE_IJMatrixInitialize will properly initialize
1521ddbeb582SStefano Zampini        the IJ matrix for us */
1522ddbeb582SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(hA->ij);
1523ddbeb582SStefano Zampini     hypre_AuxParCSRMatrixDestroy(aux_matrix);
1524ddbeb582SStefano Zampini     hypre_IJMatrixTranslator(hA->ij) = NULL;
1525d975228cSstefano_zampini     PetscStackCallStandard(HYPRE_IJMatrixSetDiagOffdSizes,(hA->ij,hdnnz,honnz));
1526ddbeb582SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(hA->ij);
1527336664bdSPierre Jolivet     hypre_AuxParCSRMatrixNeedAux(aux_matrix) = !hA->sorted_full;
1528d975228cSstefano_zampini   } else {
1529d975228cSstefano_zampini     honnz = NULL;
1530d975228cSstefano_zampini     PetscStackCallStandard(HYPRE_IJMatrixSetRowSizes,(hA->ij,hdnnz));
1531d975228cSstefano_zampini   }
1532ddbeb582SStefano Zampini 
1533af1cf968SStefano Zampini   /* reset assembled flag and call the initialize method */
1534af1cf968SStefano Zampini   hypre_IJMatrixAssembleFlag(hA->ij) = 0;
15356ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2,19,0)
1536ddbeb582SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixInitialize,(hA->ij));
15376ea7df73SStefano Zampini #else
15386ea7df73SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixInitialize_v2,(hA->ij,HYPRE_MEMORY_HOST));
15396ea7df73SStefano Zampini #endif
1540d975228cSstefano_zampini   if (!dnnz) {
1541d975228cSstefano_zampini     ierr = PetscFree(hdnnz);CHKERRQ(ierr);
1542d975228cSstefano_zampini   }
1543d975228cSstefano_zampini   if (!onnz && honnz) {
1544d975228cSstefano_zampini     ierr = PetscFree(honnz);CHKERRQ(ierr);
1545d975228cSstefano_zampini   }
1546af1cf968SStefano Zampini   /* Match AIJ logic */
154706a29025Sstefano_zampini   A->preallocated = PETSC_TRUE;
1548af1cf968SStefano Zampini   A->assembled    = PETSC_FALSE;
1549d975228cSstefano_zampini   PetscFunctionReturn(0);
1550d975228cSstefano_zampini }
1551d975228cSstefano_zampini 
1552d975228cSstefano_zampini /*@C
1553d975228cSstefano_zampini    MatHYPRESetPreallocation - Preallocates memory for a sparse parallel matrix in HYPRE IJ format
1554d975228cSstefano_zampini 
1555d975228cSstefano_zampini    Collective on Mat
1556d975228cSstefano_zampini 
1557d975228cSstefano_zampini    Input Parameters:
1558d975228cSstefano_zampini +  A - the matrix
1559d975228cSstefano_zampini .  dnz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1560d975228cSstefano_zampini           (same value is used for all local rows)
1561d975228cSstefano_zampini .  dnnz - array containing the number of nonzeros in the various rows of the
1562d975228cSstefano_zampini           DIAGONAL portion of the local submatrix (possibly different for each row)
1563d975228cSstefano_zampini           or NULL (PETSC_NULL_INTEGER in Fortran), if d_nz is used to specify the nonzero structure.
1564d975228cSstefano_zampini           The size of this array is equal to the number of local rows, i.e 'm'.
1565d975228cSstefano_zampini           For matrices that will be factored, you must leave room for (and set)
1566d975228cSstefano_zampini           the diagonal entry even if it is zero.
1567d975228cSstefano_zampini .  onz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1568d975228cSstefano_zampini           submatrix (same value is used for all local rows).
1569d975228cSstefano_zampini -  onnz - array containing the number of nonzeros in the various rows of the
1570d975228cSstefano_zampini           OFF-DIAGONAL portion of the local submatrix (possibly different for
1571d975228cSstefano_zampini           each row) or NULL (PETSC_NULL_INTEGER in Fortran), if o_nz is used to specify the nonzero
1572d975228cSstefano_zampini           structure. The size of this array is equal to the number
1573d975228cSstefano_zampini           of local rows, i.e 'm'.
1574d975228cSstefano_zampini 
157595452b02SPatrick Sanan    Notes:
157695452b02SPatrick Sanan     If the *nnz parameter is given then the *nz parameter is ignored; for sequential matrices, onz and onnz are ignored.
1577d975228cSstefano_zampini 
1578d975228cSstefano_zampini    Level: intermediate
1579d975228cSstefano_zampini 
1580af1cf968SStefano Zampini .seealso: MatCreate(), MatMPIAIJSetPreallocation(), MATHYPRE
1581d975228cSstefano_zampini @*/
1582d975228cSstefano_zampini PetscErrorCode MatHYPRESetPreallocation(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[])
1583d975228cSstefano_zampini {
1584d975228cSstefano_zampini   PetscErrorCode ierr;
1585d975228cSstefano_zampini 
1586d975228cSstefano_zampini   PetscFunctionBegin;
1587d975228cSstefano_zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
1588d975228cSstefano_zampini   PetscValidType(A,1);
1589d975228cSstefano_zampini   ierr = PetscTryMethod(A,"MatHYPRESetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(A,dnz,dnnz,onz,onnz));CHKERRQ(ierr);
1590d975228cSstefano_zampini   PetscFunctionReturn(0);
1591d975228cSstefano_zampini }
1592d975228cSstefano_zampini 
1593225daaf8SStefano Zampini /*
1594225daaf8SStefano Zampini    MatCreateFromParCSR - Creates a matrix from a hypre_ParCSRMatrix
1595225daaf8SStefano Zampini 
1596225daaf8SStefano Zampini    Collective
1597225daaf8SStefano Zampini 
1598225daaf8SStefano Zampini    Input Parameters:
159945b8d346SStefano Zampini +  parcsr   - the pointer to the hypre_ParCSRMatrix
1600bb4689ddSStefano Zampini .  mtype    - matrix type to be created. Currently MATAIJ, MATIS and MATHYPRE are supported.
1601225daaf8SStefano Zampini -  copymode - PETSc copying options
1602225daaf8SStefano Zampini 
1603225daaf8SStefano Zampini    Output Parameter:
1604225daaf8SStefano Zampini .  A  - the matrix
1605225daaf8SStefano Zampini 
1606225daaf8SStefano Zampini    Level: intermediate
1607225daaf8SStefano Zampini 
1608225daaf8SStefano Zampini .seealso: MatHYPRE, PetscCopyMode
1609225daaf8SStefano Zampini */
161045b8d346SStefano Zampini PETSC_EXTERN PetscErrorCode MatCreateFromParCSR(hypre_ParCSRMatrix *parcsr, MatType mtype, PetscCopyMode copymode, Mat* A)
1611978814f1SStefano Zampini {
1612225daaf8SStefano Zampini   Mat            T;
1613978814f1SStefano Zampini   Mat_HYPRE      *hA;
1614978814f1SStefano Zampini   MPI_Comm       comm;
1615978814f1SStefano Zampini   PetscInt       rstart,rend,cstart,cend,M,N;
1616d248a85cSRichard Tran Mills   PetscBool      isseqaij,isseqaijmkl,ismpiaij,isaij,ishyp,isis;
1617978814f1SStefano Zampini   PetscErrorCode ierr;
1618978814f1SStefano Zampini 
1619978814f1SStefano Zampini   PetscFunctionBegin;
1620978814f1SStefano Zampini   comm  = hypre_ParCSRMatrixComm(parcsr);
1621225daaf8SStefano Zampini   ierr  = PetscStrcmp(mtype,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
1622d248a85cSRichard Tran Mills   ierr  = PetscStrcmp(mtype,MATSEQAIJMKL,&isseqaijmkl);CHKERRQ(ierr);
1623225daaf8SStefano Zampini   ierr  = PetscStrcmp(mtype,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
1624225daaf8SStefano Zampini   ierr  = PetscStrcmp(mtype,MATAIJ,&isaij);CHKERRQ(ierr);
1625225daaf8SStefano Zampini   ierr  = PetscStrcmp(mtype,MATHYPRE,&ishyp);CHKERRQ(ierr);
16268cfe8d00SStefano Zampini   ierr  = PetscStrcmp(mtype,MATIS,&isis);CHKERRQ(ierr);
1627d248a85cSRichard Tran Mills   isaij = (PetscBool)(isseqaij || isseqaijmkl || ismpiaij || isaij);
16286ea7df73SStefano Zampini   /* TODO */
1629d248a85cSRichard Tran Mills   if (!isaij && !ishyp && !isis) SETERRQ7(comm,PETSC_ERR_SUP,"Unsupported MatType %s! Supported types are %s, %s, %s, %s, %s, and %s",mtype,MATAIJ,MATSEQAIJ,MATSEQAIJMKL,MATMPIAIJ,MATIS,MATHYPRE);
1630978814f1SStefano Zampini   /* access ParCSRMatrix */
1631978814f1SStefano Zampini   rstart = hypre_ParCSRMatrixFirstRowIndex(parcsr);
1632978814f1SStefano Zampini   rend   = hypre_ParCSRMatrixLastRowIndex(parcsr);
1633978814f1SStefano Zampini   cstart = hypre_ParCSRMatrixFirstColDiag(parcsr);
1634978814f1SStefano Zampini   cend   = hypre_ParCSRMatrixLastColDiag(parcsr);
1635978814f1SStefano Zampini   M      = hypre_ParCSRMatrixGlobalNumRows(parcsr);
1636978814f1SStefano Zampini   N      = hypre_ParCSRMatrixGlobalNumCols(parcsr);
1637978814f1SStefano Zampini 
1638fa92c42cSstefano_zampini   /* fix for empty local rows/columns */
1639fa92c42cSstefano_zampini   if (rend < rstart) rend = rstart;
1640fa92c42cSstefano_zampini   if (cend < cstart) cend = cstart;
1641fa92c42cSstefano_zampini 
1642e6471dc9SStefano Zampini   /* PETSc convention */
1643e6471dc9SStefano Zampini   rend++;
1644e6471dc9SStefano Zampini   cend++;
1645e6471dc9SStefano Zampini   rend = PetscMin(rend,M);
1646e6471dc9SStefano Zampini   cend = PetscMin(cend,N);
1647e6471dc9SStefano Zampini 
1648978814f1SStefano Zampini   /* create PETSc matrix with MatHYPRE */
1649225daaf8SStefano Zampini   ierr = MatCreate(comm,&T);CHKERRQ(ierr);
1650e6471dc9SStefano Zampini   ierr = MatSetSizes(T,rend-rstart,cend-cstart,M,N);CHKERRQ(ierr);
1651225daaf8SStefano Zampini   ierr = MatSetType(T,MATHYPRE);CHKERRQ(ierr);
1652225daaf8SStefano Zampini   hA   = (Mat_HYPRE*)(T->data);
1653978814f1SStefano Zampini 
1654978814f1SStefano Zampini   /* create HYPRE_IJMatrix */
1655978814f1SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixCreate,(hA->comm,rstart,rend-1,cstart,cend-1,&hA->ij));
165645b8d346SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(hA->ij,HYPRE_PARCSR));
165745b8d346SStefano Zampini 
16586ea7df73SStefano Zampini // TODO DEV
165945b8d346SStefano Zampini   /* create new ParCSR object if needed */
166045b8d346SStefano Zampini   if (ishyp && copymode == PETSC_COPY_VALUES) {
166145b8d346SStefano Zampini     hypre_ParCSRMatrix *new_parcsr;
16626ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2,18,0)
166345b8d346SStefano Zampini     hypre_CSRMatrix    *hdiag,*hoffd,*ndiag,*noffd;
166445b8d346SStefano Zampini 
16650e6427aaSSatish Balay     new_parcsr = hypre_ParCSRMatrixClone(parcsr,0);
166645b8d346SStefano Zampini     hdiag      = hypre_ParCSRMatrixDiag(parcsr);
166745b8d346SStefano Zampini     hoffd      = hypre_ParCSRMatrixOffd(parcsr);
166845b8d346SStefano Zampini     ndiag      = hypre_ParCSRMatrixDiag(new_parcsr);
166945b8d346SStefano Zampini     noffd      = hypre_ParCSRMatrixOffd(new_parcsr);
1670580bdb30SBarry Smith     ierr       = PetscArraycpy(hypre_CSRMatrixData(ndiag),hypre_CSRMatrixData(hdiag),hypre_CSRMatrixNumNonzeros(hdiag));CHKERRQ(ierr);
1671580bdb30SBarry Smith     ierr       = PetscArraycpy(hypre_CSRMatrixData(noffd),hypre_CSRMatrixData(hoffd),hypre_CSRMatrixNumNonzeros(hoffd));CHKERRQ(ierr);
16726ea7df73SStefano Zampini #else
16736ea7df73SStefano Zampini     new_parcsr = hypre_ParCSRMatrixClone(parcsr,1);
16746ea7df73SStefano Zampini #endif
167545b8d346SStefano Zampini     parcsr     = new_parcsr;
167645b8d346SStefano Zampini     copymode   = PETSC_OWN_POINTER;
167745b8d346SStefano Zampini   }
1678978814f1SStefano Zampini 
1679978814f1SStefano Zampini   /* set ParCSR object */
1680978814f1SStefano Zampini   hypre_IJMatrixObject(hA->ij) = parcsr;
16814ec6421dSstefano_zampini   T->preallocated = PETSC_TRUE;
1682978814f1SStefano Zampini 
1683978814f1SStefano Zampini   /* set assembled flag */
1684978814f1SStefano Zampini   hypre_IJMatrixAssembleFlag(hA->ij) = 1;
16856ea7df73SStefano Zampini #if 0
1686978814f1SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixInitialize,(hA->ij));
16876ea7df73SStefano Zampini #endif
1688225daaf8SStefano Zampini   if (ishyp) {
16896d2a658fSstefano_zampini     PetscMPIInt myid = 0;
16906d2a658fSstefano_zampini 
16916d2a658fSstefano_zampini     /* make sure we always have row_starts and col_starts available */
16926d2a658fSstefano_zampini     if (HYPRE_AssumedPartitionCheck()) {
1693ffc4695bSBarry Smith       ierr = MPI_Comm_rank(comm,&myid);CHKERRMPI(ierr);
16946d2a658fSstefano_zampini     }
1695a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
16966d2a658fSstefano_zampini     if (!hypre_ParCSRMatrixOwnsColStarts(parcsr)) {
16976d2a658fSstefano_zampini       PetscLayout map;
16986d2a658fSstefano_zampini 
16996d2a658fSstefano_zampini       ierr = MatGetLayouts(T,NULL,&map);CHKERRQ(ierr);
17006d2a658fSstefano_zampini       ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
17012cf14000SStefano Zampini       hypre_ParCSRMatrixColStarts(parcsr) = (HYPRE_BigInt*)(map->range + myid);
17026d2a658fSstefano_zampini     }
17036d2a658fSstefano_zampini     if (!hypre_ParCSRMatrixOwnsRowStarts(parcsr)) {
17046d2a658fSstefano_zampini       PetscLayout map;
17056d2a658fSstefano_zampini 
17066d2a658fSstefano_zampini       ierr = MatGetLayouts(T,&map,NULL);CHKERRQ(ierr);
17076d2a658fSstefano_zampini       ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
17082cf14000SStefano Zampini       hypre_ParCSRMatrixRowStarts(parcsr) = (HYPRE_BigInt*)(map->range + myid);
17096d2a658fSstefano_zampini     }
1710a1d2239cSSatish Balay #endif
1711978814f1SStefano Zampini     /* prevent from freeing the pointer */
1712978814f1SStefano Zampini     if (copymode == PETSC_USE_POINTER) hA->inner_free = PETSC_FALSE;
1713225daaf8SStefano Zampini     *A   = T;
17146ea7df73SStefano Zampini     ierr = MatSetOption(*A,MAT_SORTED_FULL,PETSC_TRUE);CHKERRQ(ierr);
1715978814f1SStefano Zampini     ierr = MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1716978814f1SStefano Zampini     ierr = MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1717bb4689ddSStefano Zampini   } else if (isaij) {
1718bb4689ddSStefano Zampini     if (copymode != PETSC_OWN_POINTER) {
1719225daaf8SStefano Zampini       /* prevent from freeing the pointer */
1720225daaf8SStefano Zampini       hA->inner_free = PETSC_FALSE;
1721225daaf8SStefano Zampini       ierr = MatConvert_HYPRE_AIJ(T,MATAIJ,MAT_INITIAL_MATRIX,A);CHKERRQ(ierr);
1722225daaf8SStefano Zampini       ierr = MatDestroy(&T);CHKERRQ(ierr);
1723225daaf8SStefano Zampini     } else { /* AIJ return type with PETSC_OWN_POINTER */
1724225daaf8SStefano Zampini       ierr = MatConvert_HYPRE_AIJ(T,MATAIJ,MAT_INPLACE_MATRIX,&T);CHKERRQ(ierr);
1725225daaf8SStefano Zampini       *A   = T;
1726225daaf8SStefano Zampini     }
1727bb4689ddSStefano Zampini   } else if (isis) {
17288cfe8d00SStefano Zampini     ierr = MatConvert_HYPRE_IS(T,MATIS,MAT_INITIAL_MATRIX,A);CHKERRQ(ierr);
17298cfe8d00SStefano Zampini     if (copymode != PETSC_OWN_POINTER) hA->inner_free = PETSC_FALSE;
1730bb4689ddSStefano Zampini     ierr = MatDestroy(&T);CHKERRQ(ierr);
1731bb4689ddSStefano Zampini   }
1732978814f1SStefano Zampini   PetscFunctionReturn(0);
1733978814f1SStefano Zampini }
1734978814f1SStefano Zampini 
173568ec7858SStefano Zampini static PetscErrorCode MatHYPREGetParCSR_HYPRE(Mat A, hypre_ParCSRMatrix **parcsr)
1736dd9c0a25Sstefano_zampini {
1737dd9c0a25Sstefano_zampini   Mat_HYPRE *hA = (Mat_HYPRE*)A->data;
1738dd9c0a25Sstefano_zampini   HYPRE_Int type;
1739dd9c0a25Sstefano_zampini 
1740dd9c0a25Sstefano_zampini   PetscFunctionBegin;
1741dd9c0a25Sstefano_zampini   if (!hA->ij) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"HYPRE_IJMatrix not present");
1742dd9c0a25Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type));
1743dd9c0a25Sstefano_zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"HYPRE_IJMatrix is not of type HYPRE_PARCSR");
1744dd9c0a25Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)parcsr));
1745dd9c0a25Sstefano_zampini   PetscFunctionReturn(0);
1746dd9c0a25Sstefano_zampini }
1747dd9c0a25Sstefano_zampini 
1748dd9c0a25Sstefano_zampini /*
1749dd9c0a25Sstefano_zampini    MatHYPREGetParCSR - Gets the pointer to the ParCSR matrix
1750dd9c0a25Sstefano_zampini 
1751dd9c0a25Sstefano_zampini    Not collective
1752dd9c0a25Sstefano_zampini 
1753dd9c0a25Sstefano_zampini    Input Parameters:
1754dd9c0a25Sstefano_zampini +  A  - the MATHYPRE object
1755dd9c0a25Sstefano_zampini 
1756dd9c0a25Sstefano_zampini    Output Parameter:
1757dd9c0a25Sstefano_zampini .  parcsr  - the pointer to the hypre_ParCSRMatrix
1758dd9c0a25Sstefano_zampini 
1759dd9c0a25Sstefano_zampini    Level: intermediate
1760dd9c0a25Sstefano_zampini 
1761dd9c0a25Sstefano_zampini .seealso: MatHYPRE, PetscCopyMode
1762dd9c0a25Sstefano_zampini */
1763dd9c0a25Sstefano_zampini PetscErrorCode MatHYPREGetParCSR(Mat A, hypre_ParCSRMatrix **parcsr)
1764dd9c0a25Sstefano_zampini {
1765dd9c0a25Sstefano_zampini   PetscErrorCode ierr;
1766dd9c0a25Sstefano_zampini 
1767dd9c0a25Sstefano_zampini   PetscFunctionBegin;
1768dd9c0a25Sstefano_zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
1769dd9c0a25Sstefano_zampini   PetscValidType(A,1);
1770dd9c0a25Sstefano_zampini   ierr = PetscUseMethod(A,"MatHYPREGetParCSR_C",(Mat,hypre_ParCSRMatrix**),(A,parcsr));CHKERRQ(ierr);
1771dd9c0a25Sstefano_zampini   PetscFunctionReturn(0);
1772dd9c0a25Sstefano_zampini }
1773dd9c0a25Sstefano_zampini 
177468ec7858SStefano Zampini static PetscErrorCode MatMissingDiagonal_HYPRE(Mat A, PetscBool *missing, PetscInt *dd)
177568ec7858SStefano Zampini {
177668ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
177768ec7858SStefano Zampini   hypre_CSRMatrix    *ha;
177868ec7858SStefano Zampini   PetscInt           rst;
177968ec7858SStefano Zampini   PetscErrorCode     ierr;
178068ec7858SStefano Zampini 
178168ec7858SStefano Zampini   PetscFunctionBegin;
178268ec7858SStefano Zampini   if (A->rmap->n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented with non-square diagonal blocks");
178368ec7858SStefano Zampini   ierr = MatGetOwnershipRange(A,&rst,NULL);CHKERRQ(ierr);
178468ec7858SStefano Zampini   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
178568ec7858SStefano Zampini   if (missing) *missing = PETSC_FALSE;
178668ec7858SStefano Zampini   if (dd) *dd = -1;
178768ec7858SStefano Zampini   ha = hypre_ParCSRMatrixDiag(parcsr);
178868ec7858SStefano Zampini   if (ha) {
178968299464SStefano Zampini     PetscInt  size,i;
179068299464SStefano Zampini     HYPRE_Int *ii,*jj;
179168ec7858SStefano Zampini 
179268ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
179368ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
179468ec7858SStefano Zampini     jj   = hypre_CSRMatrixJ(ha);
179568ec7858SStefano Zampini     for (i = 0; i < size; i++) {
179668ec7858SStefano Zampini       PetscInt  j;
179768ec7858SStefano Zampini       PetscBool found = PETSC_FALSE;
179868ec7858SStefano Zampini 
179968ec7858SStefano Zampini       for (j = ii[i]; j < ii[i+1] && !found; j++)
180068ec7858SStefano Zampini         found = (jj[j] == i) ? PETSC_TRUE : PETSC_FALSE;
180168ec7858SStefano Zampini 
180268ec7858SStefano Zampini       if (!found) {
180368ec7858SStefano Zampini         PetscInfo1(A,"Matrix is missing local diagonal entry %D\n",i);
180468ec7858SStefano Zampini         if (missing) *missing = PETSC_TRUE;
180568ec7858SStefano Zampini         if (dd) *dd = i+rst;
180668ec7858SStefano Zampini         PetscFunctionReturn(0);
180768ec7858SStefano Zampini       }
180868ec7858SStefano Zampini     }
180968ec7858SStefano Zampini     if (!size) {
181068ec7858SStefano Zampini       PetscInfo(A,"Matrix has no diagonal entries therefore is missing diagonal\n");
181168ec7858SStefano Zampini       if (missing) *missing = PETSC_TRUE;
181268ec7858SStefano Zampini       if (dd) *dd = rst;
181368ec7858SStefano Zampini     }
181468ec7858SStefano Zampini   } else {
181568ec7858SStefano Zampini     PetscInfo(A,"Matrix has no diagonal entries therefore is missing diagonal\n");
181668ec7858SStefano Zampini     if (missing) *missing = PETSC_TRUE;
181768ec7858SStefano Zampini     if (dd) *dd = rst;
181868ec7858SStefano Zampini   }
181968ec7858SStefano Zampini   PetscFunctionReturn(0);
182068ec7858SStefano Zampini }
182168ec7858SStefano Zampini 
182268ec7858SStefano Zampini static PetscErrorCode MatScale_HYPRE(Mat A, PetscScalar s)
182368ec7858SStefano Zampini {
182468ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
18256ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2,19,0)
182668ec7858SStefano Zampini   hypre_CSRMatrix    *ha;
18276ea7df73SStefano Zampini #endif
182868ec7858SStefano Zampini   PetscErrorCode     ierr;
182939accc25SStefano Zampini   HYPRE_Complex      hs;
183068ec7858SStefano Zampini 
183168ec7858SStefano Zampini   PetscFunctionBegin;
183239accc25SStefano Zampini   ierr = PetscHYPREScalarCast(s,&hs);CHKERRQ(ierr);
183368ec7858SStefano Zampini   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
18346ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2,19,0)
18356ea7df73SStefano Zampini   PetscStackCallStandard(hypre_ParCSRMatrixScale,(parcsr,hs));
18366ea7df73SStefano Zampini #else  /* diagonal part */
183768ec7858SStefano Zampini   ha = hypre_ParCSRMatrixDiag(parcsr);
183868ec7858SStefano Zampini   if (ha) {
183968299464SStefano Zampini     PetscInt      size,i;
184068299464SStefano Zampini     HYPRE_Int     *ii;
184139accc25SStefano Zampini     HYPRE_Complex *a;
184268ec7858SStefano Zampini 
184368ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
184468ec7858SStefano Zampini     a    = hypre_CSRMatrixData(ha);
184568ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
184639accc25SStefano Zampini     for (i = 0; i < ii[size]; i++) a[i] *= hs;
184768ec7858SStefano Zampini   }
184868ec7858SStefano Zampini   /* offdiagonal part */
184968ec7858SStefano Zampini   ha = hypre_ParCSRMatrixOffd(parcsr);
185068ec7858SStefano Zampini   if (ha) {
185168299464SStefano Zampini     PetscInt      size,i;
185268299464SStefano Zampini     HYPRE_Int     *ii;
185339accc25SStefano Zampini     HYPRE_Complex *a;
185468ec7858SStefano Zampini 
185568ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
185668ec7858SStefano Zampini     a    = hypre_CSRMatrixData(ha);
185768ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
185839accc25SStefano Zampini     for (i = 0; i < ii[size]; i++) a[i] *= hs;
185968ec7858SStefano Zampini   }
18606ea7df73SStefano Zampini #endif
186168ec7858SStefano Zampini   PetscFunctionReturn(0);
186268ec7858SStefano Zampini }
186368ec7858SStefano Zampini 
186468ec7858SStefano Zampini static PetscErrorCode MatZeroRowsColumns_HYPRE(Mat A, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
186568ec7858SStefano Zampini {
186668ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
186768299464SStefano Zampini   HYPRE_Int          *lrows;
186868299464SStefano Zampini   PetscInt           rst,ren,i;
186968ec7858SStefano Zampini   PetscErrorCode     ierr;
187068ec7858SStefano Zampini 
187168ec7858SStefano Zampini   PetscFunctionBegin;
187268ec7858SStefano Zampini   if (x || b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"To be implemented");
187368ec7858SStefano Zampini   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
187468ec7858SStefano Zampini   ierr = PetscMalloc1(numRows,&lrows);CHKERRQ(ierr);
187568ec7858SStefano Zampini   ierr = MatGetOwnershipRange(A,&rst,&ren);CHKERRQ(ierr);
187668ec7858SStefano Zampini   for (i=0;i<numRows;i++) {
187768ec7858SStefano Zampini     if (rows[i] < rst || rows[i] >= ren)
187868ec7858SStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Non-local rows not yet supported");
187968ec7858SStefano Zampini     lrows[i] = rows[i] - rst;
188068ec7858SStefano Zampini   }
188168ec7858SStefano Zampini   PetscStackCallStandard(hypre_ParCSRMatrixEliminateRowsCols,(parcsr,numRows,lrows));
188268ec7858SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
188368ec7858SStefano Zampini   PetscFunctionReturn(0);
188468ec7858SStefano Zampini }
188568ec7858SStefano Zampini 
1886c69f721fSFande Kong static PetscErrorCode MatZeroEntries_HYPRE_CSRMatrix(hypre_CSRMatrix *ha)
1887c69f721fSFande Kong {
1888c69f721fSFande Kong   PetscErrorCode      ierr;
1889c69f721fSFande Kong 
1890c69f721fSFande Kong   PetscFunctionBegin;
1891c69f721fSFande Kong   if (ha) {
1892c69f721fSFande Kong     HYPRE_Int     *ii, size;
1893c69f721fSFande Kong     HYPRE_Complex *a;
1894c69f721fSFande Kong 
1895c69f721fSFande Kong     size = hypre_CSRMatrixNumRows(ha);
1896c69f721fSFande Kong     a    = hypre_CSRMatrixData(ha);
1897c69f721fSFande Kong     ii   = hypre_CSRMatrixI(ha);
1898c69f721fSFande Kong 
1899580bdb30SBarry Smith     if (a) {ierr = PetscArrayzero(a,ii[size]);CHKERRQ(ierr);}
1900c69f721fSFande Kong   }
1901c69f721fSFande Kong   PetscFunctionReturn(0);
1902c69f721fSFande Kong }
1903c69f721fSFande Kong 
1904c69f721fSFande Kong PetscErrorCode MatZeroEntries_HYPRE(Mat A)
1905c69f721fSFande Kong {
19066ea7df73SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE*)A->data;
19076ea7df73SStefano Zampini 
19086ea7df73SStefano Zampini   PetscFunctionBegin;
19096ea7df73SStefano Zampini   if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(hA->ij)) {
19106ea7df73SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixSetConstantValues,(hA->ij,0.0));
19116ea7df73SStefano Zampini   } else {
1912c69f721fSFande Kong     hypre_ParCSRMatrix *parcsr;
1913c69f721fSFande Kong     PetscErrorCode     ierr;
1914c69f721fSFande Kong 
1915c69f721fSFande Kong     ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
1916c69f721fSFande Kong     ierr = MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr));CHKERRQ(ierr);
1917c69f721fSFande Kong     ierr = MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr));CHKERRQ(ierr);
19186ea7df73SStefano Zampini   }
1919c69f721fSFande Kong   PetscFunctionReturn(0);
1920c69f721fSFande Kong }
1921c69f721fSFande Kong 
192239accc25SStefano Zampini static PetscErrorCode MatZeroRows_HYPRE_CSRMatrix(hypre_CSRMatrix *hA,PetscInt N,const PetscInt rows[],HYPRE_Complex diag)
1923c69f721fSFande Kong {
192439accc25SStefano Zampini   PetscInt        ii;
192539accc25SStefano Zampini   HYPRE_Int       *i, *j;
192639accc25SStefano Zampini   HYPRE_Complex   *a;
1927c69f721fSFande Kong 
1928c69f721fSFande Kong   PetscFunctionBegin;
1929c69f721fSFande Kong   if (!hA) PetscFunctionReturn(0);
1930c69f721fSFande Kong 
193139accc25SStefano Zampini   i = hypre_CSRMatrixI(hA);
193239accc25SStefano Zampini   j = hypre_CSRMatrixJ(hA);
1933c69f721fSFande Kong   a = hypre_CSRMatrixData(hA);
1934c69f721fSFande Kong 
1935c69f721fSFande Kong   for (ii = 0; ii < N; ii++) {
193639accc25SStefano Zampini     HYPRE_Int jj, ibeg, iend, irow;
193739accc25SStefano Zampini 
1938c69f721fSFande Kong     irow = rows[ii];
1939c69f721fSFande Kong     ibeg = i[irow];
1940c69f721fSFande Kong     iend = i[irow+1];
1941c69f721fSFande Kong     for (jj = ibeg; jj < iend; jj++)
1942c69f721fSFande Kong       if (j[jj] == irow) a[jj] = diag;
1943c69f721fSFande Kong       else a[jj] = 0.0;
1944c69f721fSFande Kong    }
1945c69f721fSFande Kong    PetscFunctionReturn(0);
1946c69f721fSFande Kong }
1947c69f721fSFande Kong 
1948ddbeb582SStefano Zampini static PetscErrorCode MatZeroRows_HYPRE(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1949c69f721fSFande Kong {
1950c69f721fSFande Kong   hypre_ParCSRMatrix  *parcsr;
1951c69f721fSFande Kong   PetscInt            *lrows,len;
195239accc25SStefano Zampini   HYPRE_Complex       hdiag;
1953c69f721fSFande Kong   PetscErrorCode      ierr;
1954c69f721fSFande Kong 
1955c69f721fSFande Kong   PetscFunctionBegin;
1956c6698e78SStefano Zampini   if (x || b) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Does not support to modify the solution and the right hand size");
195739accc25SStefano Zampini   ierr = PetscHYPREScalarCast(diag,&hdiag);CHKERRQ(ierr);
1958c69f721fSFande Kong   /* retrieve the internal matrix */
1959c69f721fSFande Kong   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
1960c69f721fSFande Kong   /* get locally owned rows */
1961c69f721fSFande Kong   ierr = MatZeroRowsMapLocal_Private(A,N,rows,&len,&lrows);CHKERRQ(ierr);
1962c69f721fSFande Kong   /* zero diagonal part */
196339accc25SStefano Zampini   ierr = MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr),len,lrows,hdiag);CHKERRQ(ierr);
1964c69f721fSFande Kong   /* zero off-diagonal part */
1965c69f721fSFande Kong   ierr = MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr),len,lrows,0.0);CHKERRQ(ierr);
1966c69f721fSFande Kong 
1967c69f721fSFande Kong   ierr = PetscFree(lrows);CHKERRQ(ierr);
1968c69f721fSFande Kong   PetscFunctionReturn(0);
1969c69f721fSFande Kong }
1970c69f721fSFande Kong 
1971ddbeb582SStefano Zampini static PetscErrorCode MatAssemblyBegin_HYPRE(Mat mat,MatAssemblyType mode)
1972c69f721fSFande Kong {
1973c69f721fSFande Kong   PetscErrorCode ierr;
1974c69f721fSFande Kong 
1975c69f721fSFande Kong   PetscFunctionBegin;
1976c69f721fSFande Kong   if (mat->nooffprocentries) PetscFunctionReturn(0);
1977c69f721fSFande Kong 
1978c69f721fSFande Kong   ierr = MatStashScatterBegin_Private(mat,&mat->stash,mat->rmap->range);CHKERRQ(ierr);
1979c69f721fSFande Kong   PetscFunctionReturn(0);
1980c69f721fSFande Kong }
1981c69f721fSFande Kong 
1982ddbeb582SStefano Zampini static PetscErrorCode MatGetRow_HYPRE(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
1983c69f721fSFande Kong {
1984c69f721fSFande Kong   hypre_ParCSRMatrix  *parcsr;
19852cf14000SStefano Zampini   HYPRE_Int           hnz;
1986c69f721fSFande Kong   PetscErrorCode      ierr;
1987c69f721fSFande Kong 
1988c69f721fSFande Kong   PetscFunctionBegin;
1989c69f721fSFande Kong   /* retrieve the internal matrix */
1990c69f721fSFande Kong   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
1991c69f721fSFande Kong   /* call HYPRE API */
199239accc25SStefano Zampini   PetscStackCallStandard(HYPRE_ParCSRMatrixGetRow,(parcsr,row,&hnz,(HYPRE_BigInt**)idx,(HYPRE_Complex**)v));
19932cf14000SStefano Zampini   if (nz) *nz = (PetscInt)hnz;
1994c69f721fSFande Kong   PetscFunctionReturn(0);
1995c69f721fSFande Kong }
1996c69f721fSFande Kong 
1997ddbeb582SStefano Zampini static PetscErrorCode MatRestoreRow_HYPRE(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
1998c69f721fSFande Kong {
1999c69f721fSFande Kong   hypre_ParCSRMatrix  *parcsr;
20002cf14000SStefano Zampini   HYPRE_Int           hnz;
2001c69f721fSFande Kong   PetscErrorCode      ierr;
2002c69f721fSFande Kong 
2003c69f721fSFande Kong   PetscFunctionBegin;
2004c69f721fSFande Kong   /* retrieve the internal matrix */
2005c69f721fSFande Kong   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
2006c69f721fSFande Kong   /* call HYPRE API */
20072cf14000SStefano Zampini   hnz = nz ? (HYPRE_Int)(*nz) : 0;
200839accc25SStefano Zampini   PetscStackCallStandard(HYPRE_ParCSRMatrixRestoreRow,(parcsr,row,&hnz,(HYPRE_BigInt**)idx,(HYPRE_Complex**)v));
2009c69f721fSFande Kong   PetscFunctionReturn(0);
2010c69f721fSFande Kong }
2011c69f721fSFande Kong 
2012ddbeb582SStefano Zampini static PetscErrorCode MatGetValues_HYPRE(Mat A,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],PetscScalar v[])
2013c69f721fSFande Kong {
201445b8d346SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE*)A->data;
2015c69f721fSFande Kong   PetscInt  i;
20161d4906efSStefano Zampini 
2017c69f721fSFande Kong   PetscFunctionBegin;
2018c69f721fSFande Kong   if (!m || !n) PetscFunctionReturn(0);
2019c69f721fSFande Kong   /* Ignore negative row indices
2020c69f721fSFande Kong    * And negative column indices should be automatically ignored in hypre
2021c69f721fSFande Kong    * */
20222cf14000SStefano Zampini   for (i=0; i<m; i++) {
20232cf14000SStefano Zampini     if (idxm[i] >= 0) {
20242cf14000SStefano Zampini       HYPRE_Int hn = (HYPRE_Int)n;
202539accc25SStefano Zampini       PetscStackCallStandard(HYPRE_IJMatrixGetValues,(hA->ij,1,&hn,(HYPRE_BigInt*)&idxm[i],(HYPRE_BigInt*)idxn,(HYPRE_Complex*)(v + i*n)));
20262cf14000SStefano Zampini     }
20272cf14000SStefano Zampini   }
2028c69f721fSFande Kong   PetscFunctionReturn(0);
2029c69f721fSFande Kong }
2030c69f721fSFande Kong 
2031ddbeb582SStefano Zampini static PetscErrorCode MatSetOption_HYPRE(Mat A,MatOption op,PetscBool flg)
2032ddbeb582SStefano Zampini {
2033ddbeb582SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE*)A->data;
2034ddbeb582SStefano Zampini 
2035ddbeb582SStefano Zampini   PetscFunctionBegin;
2036c6698e78SStefano Zampini   switch (op) {
2037ddbeb582SStefano Zampini   case MAT_NO_OFF_PROC_ENTRIES:
2038ddbeb582SStefano Zampini     if (flg) {
2039ddbeb582SStefano Zampini       PetscStackCallStandard(HYPRE_IJMatrixSetMaxOffProcElmts,(hA->ij,0));
2040ddbeb582SStefano Zampini     }
2041ddbeb582SStefano Zampini     break;
2042336664bdSPierre Jolivet   case MAT_SORTED_FULL:
2043336664bdSPierre Jolivet     hA->sorted_full = flg;
2044336664bdSPierre Jolivet     break;
2045ddbeb582SStefano Zampini   default:
2046ddbeb582SStefano Zampini     break;
2047ddbeb582SStefano Zampini   }
2048ddbeb582SStefano Zampini   PetscFunctionReturn(0);
2049ddbeb582SStefano Zampini }
2050c69f721fSFande Kong 
205145b8d346SStefano Zampini static PetscErrorCode MatView_HYPRE(Mat A, PetscViewer view)
205245b8d346SStefano Zampini {
205345b8d346SStefano Zampini   PetscErrorCode     ierr;
205445b8d346SStefano Zampini   PetscViewerFormat  format;
205545b8d346SStefano Zampini 
205645b8d346SStefano Zampini   PetscFunctionBegin;
205745b8d346SStefano Zampini   ierr = PetscViewerGetFormat(view,&format);CHKERRQ(ierr);
20586ea7df73SStefano Zampini   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(0);
205945b8d346SStefano Zampini   if (format != PETSC_VIEWER_NATIVE) {
20606ea7df73SStefano Zampini     Mat                B;
20616ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
20626ea7df73SStefano Zampini     PetscErrorCode     (*mview)(Mat,PetscViewer) = NULL;
20636ea7df73SStefano Zampini 
206445b8d346SStefano Zampini     ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
206545b8d346SStefano Zampini     ierr = MatCreateFromParCSR(parcsr,MATAIJ,PETSC_USE_POINTER,&B);CHKERRQ(ierr);
206645b8d346SStefano Zampini     ierr = MatGetOperation(B,MATOP_VIEW,(void(**)(void))&mview);CHKERRQ(ierr);
20672758c9b9SBarry Smith     if (!mview) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Missing view operation");
206845b8d346SStefano Zampini     ierr = (*mview)(B,view);CHKERRQ(ierr);
206945b8d346SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
207045b8d346SStefano Zampini   } else {
207145b8d346SStefano Zampini     Mat_HYPRE  *hA = (Mat_HYPRE*)A->data;
207245b8d346SStefano Zampini     PetscMPIInt size;
207345b8d346SStefano Zampini     PetscBool   isascii;
207445b8d346SStefano Zampini     const char *filename;
207545b8d346SStefano Zampini 
207645b8d346SStefano Zampini     /* HYPRE uses only text files */
207745b8d346SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)view,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
207845b8d346SStefano Zampini     if (!isascii) SETERRQ1(PetscObjectComm((PetscObject)view),PETSC_ERR_SUP,"PetscViewerType %s: native HYPRE format needs PETSCVIEWERASCII",((PetscObject)view)->type_name);
207945b8d346SStefano Zampini     ierr = PetscViewerFileGetName(view,&filename);CHKERRQ(ierr);
208045b8d346SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixPrint,(hA->ij,filename));
2081ffc4695bSBarry Smith     ierr = MPI_Comm_size(hA->comm,&size);CHKERRMPI(ierr);
208245b8d346SStefano Zampini     if (size > 1) {
208345b8d346SStefano Zampini       ierr = PetscViewerASCIIPrintf(view,"Matrix files: %s.%05d ... %s.%05d\n",filename,0,filename,size-1);CHKERRQ(ierr);
208445b8d346SStefano Zampini     } else {
208545b8d346SStefano Zampini       ierr = PetscViewerASCIIPrintf(view,"Matrix file: %s.%05d\n",filename,0);CHKERRQ(ierr);
208645b8d346SStefano Zampini     }
208745b8d346SStefano Zampini   }
208845b8d346SStefano Zampini   PetscFunctionReturn(0);
208945b8d346SStefano Zampini }
209045b8d346SStefano Zampini 
209145b8d346SStefano Zampini static PetscErrorCode MatDuplicate_HYPRE(Mat A,MatDuplicateOption op, Mat *B)
209245b8d346SStefano Zampini {
20936abb4441SStefano Zampini   hypre_ParCSRMatrix *parcsr = NULL;
209445b8d346SStefano Zampini   PetscErrorCode     ierr;
209545b8d346SStefano Zampini   PetscCopyMode      cpmode;
209645b8d346SStefano Zampini 
209745b8d346SStefano Zampini   PetscFunctionBegin;
209845b8d346SStefano Zampini   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
209945b8d346SStefano Zampini   if (op == MAT_DO_NOT_COPY_VALUES || op == MAT_SHARE_NONZERO_PATTERN) {
21000e6427aaSSatish Balay     parcsr = hypre_ParCSRMatrixClone(parcsr,0);
210145b8d346SStefano Zampini     cpmode = PETSC_OWN_POINTER;
210245b8d346SStefano Zampini   } else {
210345b8d346SStefano Zampini     cpmode = PETSC_COPY_VALUES;
210445b8d346SStefano Zampini   }
210545b8d346SStefano Zampini   ierr = MatCreateFromParCSR(parcsr,MATHYPRE,cpmode,B);CHKERRQ(ierr);
210645b8d346SStefano Zampini   PetscFunctionReturn(0);
210745b8d346SStefano Zampini }
210845b8d346SStefano Zampini 
2109465edc17SStefano Zampini static PetscErrorCode MatCopy_HYPRE(Mat A, Mat B, MatStructure str)
2110465edc17SStefano Zampini {
2111465edc17SStefano Zampini   hypre_ParCSRMatrix *acsr,*bcsr;
2112465edc17SStefano Zampini   PetscErrorCode     ierr;
2113465edc17SStefano Zampini 
2114465edc17SStefano Zampini   PetscFunctionBegin;
2115465edc17SStefano Zampini   if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) {
2116465edc17SStefano Zampini     ierr = MatHYPREGetParCSR_HYPRE(A,&acsr);CHKERRQ(ierr);
2117465edc17SStefano Zampini     ierr = MatHYPREGetParCSR_HYPRE(B,&bcsr);CHKERRQ(ierr);
2118465edc17SStefano Zampini     PetscStackCallStandard(hypre_ParCSRMatrixCopy,(acsr,bcsr,1));
21191e1ea65dSPierre Jolivet     ierr = MatSetOption(B,MAT_SORTED_FULL,PETSC_TRUE);CHKERRQ(ierr); /* "perfect" preallocation, so no need for hypre_AuxParCSRMatrixNeedAux */
2120465edc17SStefano Zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2121465edc17SStefano Zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2122465edc17SStefano Zampini   } else {
2123465edc17SStefano Zampini     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
2124465edc17SStefano Zampini   }
2125465edc17SStefano Zampini   PetscFunctionReturn(0);
2126465edc17SStefano Zampini }
2127465edc17SStefano Zampini 
21286305df00SStefano Zampini static PetscErrorCode MatGetDiagonal_HYPRE(Mat A, Vec d)
21296305df00SStefano Zampini {
21306305df00SStefano Zampini   hypre_ParCSRMatrix *parcsr;
21316305df00SStefano Zampini   hypre_CSRMatrix    *dmat;
213239accc25SStefano Zampini   HYPRE_Complex      *a;
213339accc25SStefano Zampini   HYPRE_Complex      *data = NULL;
21342cf14000SStefano Zampini   HYPRE_Int          *diag = NULL;
21352cf14000SStefano Zampini   PetscInt           i;
21366305df00SStefano Zampini   PetscBool          cong;
21376305df00SStefano Zampini   PetscErrorCode     ierr;
21386305df00SStefano Zampini 
21396305df00SStefano Zampini   PetscFunctionBegin;
21406305df00SStefano Zampini   ierr = MatHasCongruentLayouts(A,&cong);CHKERRQ(ierr);
21416305df00SStefano Zampini   if (!cong) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only for square matrices with same local distributions of rows and columns");
214276bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
21436305df00SStefano Zampini     PetscBool miss;
21446305df00SStefano Zampini     ierr = MatMissingDiagonal(A,&miss,NULL);CHKERRQ(ierr);
21456305df00SStefano Zampini     if (miss && A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented when diagonal entries are missing");
21466305df00SStefano Zampini   }
21476305df00SStefano Zampini   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
21486305df00SStefano Zampini   dmat = hypre_ParCSRMatrixDiag(parcsr);
21496305df00SStefano Zampini   if (dmat) {
215039accc25SStefano Zampini     /* this cast fixes the clang error: implicit conversion from 'HYPRE_Complex' (aka '_Complex double') to 'double' is not permitted in C++ */
215139accc25SStefano Zampini     ierr = VecGetArray(d,(PetscScalar**)&a);CHKERRQ(ierr);
21522cf14000SStefano Zampini     diag = hypre_CSRMatrixI(dmat);
215339accc25SStefano Zampini     data = hypre_CSRMatrixData(dmat);
21546305df00SStefano Zampini     for (i=0;i<A->rmap->n;i++) a[i] = data[diag[i]];
215539accc25SStefano Zampini     ierr = VecRestoreArray(d,(PetscScalar**)&a);CHKERRQ(ierr);
21566305df00SStefano Zampini   }
21576305df00SStefano Zampini   PetscFunctionReturn(0);
21586305df00SStefano Zampini }
21596305df00SStefano Zampini 
2160363d496dSStefano Zampini #include <petscblaslapack.h>
2161363d496dSStefano Zampini 
2162363d496dSStefano Zampini static PetscErrorCode MatAXPY_HYPRE(Mat Y,PetscScalar a,Mat X,MatStructure str)
2163363d496dSStefano Zampini {
2164363d496dSStefano Zampini   PetscErrorCode ierr;
2165363d496dSStefano Zampini 
2166363d496dSStefano Zampini   PetscFunctionBegin;
21676ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
21686ea7df73SStefano Zampini   {
21696ea7df73SStefano Zampini     Mat                B;
21706ea7df73SStefano Zampini     hypre_ParCSRMatrix *x,*y,*z;
21716ea7df73SStefano Zampini 
21726ea7df73SStefano Zampini     ierr = MatHYPREGetParCSR(Y,&y);CHKERRQ(ierr);
21736ea7df73SStefano Zampini     ierr = MatHYPREGetParCSR(X,&x);CHKERRQ(ierr);
21746ea7df73SStefano Zampini     PetscStackCallStandard(hypre_ParCSRMatrixAdd,(1.0,y,1.0,x,&z));
21756ea7df73SStefano Zampini     ierr = MatCreateFromParCSR(z,MATHYPRE,PETSC_OWN_POINTER,&B);CHKERRQ(ierr);
21766ea7df73SStefano Zampini     ierr = MatHeaderMerge(Y,&B);CHKERRQ(ierr);
21776ea7df73SStefano Zampini   }
21786ea7df73SStefano Zampini #else
2179363d496dSStefano Zampini   if (str == SAME_NONZERO_PATTERN) {
2180363d496dSStefano Zampini     hypre_ParCSRMatrix *x,*y;
2181363d496dSStefano Zampini     hypre_CSRMatrix    *xloc,*yloc;
2182363d496dSStefano Zampini     PetscInt           xnnz,ynnz;
218339accc25SStefano Zampini     HYPRE_Complex      *xarr,*yarr;
2184363d496dSStefano Zampini     PetscBLASInt       one=1,bnz;
2185363d496dSStefano Zampini 
2186363d496dSStefano Zampini     ierr = MatHYPREGetParCSR(Y,&y);CHKERRQ(ierr);
2187363d496dSStefano Zampini     ierr = MatHYPREGetParCSR(X,&x);CHKERRQ(ierr);
2188363d496dSStefano Zampini 
2189363d496dSStefano Zampini     /* diagonal block */
2190363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixDiag(x);
2191363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixDiag(y);
2192363d496dSStefano Zampini     xnnz = 0;
2193363d496dSStefano Zampini     ynnz = 0;
2194363d496dSStefano Zampini     xarr = NULL;
2195363d496dSStefano Zampini     yarr = NULL;
2196363d496dSStefano Zampini     if (xloc) {
219739accc25SStefano Zampini       xarr = hypre_CSRMatrixData(xloc);
2198363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
2199363d496dSStefano Zampini     }
2200363d496dSStefano Zampini     if (yloc) {
220139accc25SStefano Zampini       yarr = hypre_CSRMatrixData(yloc);
2202363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
2203363d496dSStefano Zampini     }
2204363d496dSStefano Zampini     if (xnnz != ynnz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Different number of nonzeros in diagonal block %D != %D",xnnz,ynnz);
2205363d496dSStefano Zampini     ierr = PetscBLASIntCast(xnnz,&bnz);CHKERRQ(ierr);
220639accc25SStefano Zampini     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&a,(PetscScalar*)xarr,&one,(PetscScalar*)yarr,&one));
2207363d496dSStefano Zampini 
2208363d496dSStefano Zampini     /* off-diagonal block */
2209363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixOffd(x);
2210363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixOffd(y);
2211363d496dSStefano Zampini     xnnz = 0;
2212363d496dSStefano Zampini     ynnz = 0;
2213363d496dSStefano Zampini     xarr = NULL;
2214363d496dSStefano Zampini     yarr = NULL;
2215363d496dSStefano Zampini     if (xloc) {
221639accc25SStefano Zampini       xarr = hypre_CSRMatrixData(xloc);
2217363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
2218363d496dSStefano Zampini     }
2219363d496dSStefano Zampini     if (yloc) {
222039accc25SStefano Zampini       yarr = hypre_CSRMatrixData(yloc);
2221363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
2222363d496dSStefano Zampini     }
2223363d496dSStefano Zampini     if (xnnz != ynnz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Different number of nonzeros in off-diagonal block %D != %D",xnnz,ynnz);
2224363d496dSStefano Zampini     ierr = PetscBLASIntCast(xnnz,&bnz);CHKERRQ(ierr);
222539accc25SStefano Zampini     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&a,(PetscScalar*)xarr,&one,(PetscScalar*)yarr,&one));
2226363d496dSStefano Zampini   } else if (str == SUBSET_NONZERO_PATTERN) {
2227363d496dSStefano Zampini     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
2228363d496dSStefano Zampini   } else {
2229363d496dSStefano Zampini     Mat B;
2230363d496dSStefano Zampini 
2231363d496dSStefano Zampini     ierr = MatAXPY_Basic_Preallocate(Y,X,&B);CHKERRQ(ierr);
2232363d496dSStefano Zampini     ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr);
2233363d496dSStefano Zampini     ierr = MatHeaderReplace(Y,&B);CHKERRQ(ierr);
2234363d496dSStefano Zampini   }
22356ea7df73SStefano Zampini #endif
2236363d496dSStefano Zampini   PetscFunctionReturn(0);
2237363d496dSStefano Zampini }
2238363d496dSStefano Zampini 
2239a055b5aaSBarry Smith /*MC
2240a055b5aaSBarry Smith    MATHYPRE - MATHYPRE = "hypre" - A matrix type to be used for sequential and parallel sparse matrices
2241a055b5aaSBarry Smith           based on the hypre IJ interface.
2242a055b5aaSBarry Smith 
2243a055b5aaSBarry Smith    Level: intermediate
2244a055b5aaSBarry Smith 
2245a055b5aaSBarry Smith .seealso: MatCreate()
2246a055b5aaSBarry Smith M*/
2247a055b5aaSBarry Smith 
224863c07aadSStefano Zampini PETSC_EXTERN PetscErrorCode MatCreate_HYPRE(Mat B)
224963c07aadSStefano Zampini {
225063c07aadSStefano Zampini   Mat_HYPRE      *hB;
225163c07aadSStefano Zampini   PetscErrorCode ierr;
225263c07aadSStefano Zampini 
225363c07aadSStefano Zampini   PetscFunctionBegin;
225463c07aadSStefano Zampini   ierr = PetscNewLog(B,&hB);CHKERRQ(ierr);
22556ea7df73SStefano Zampini 
2256978814f1SStefano Zampini   hB->inner_free  = PETSC_TRUE;
2257c69f721fSFande Kong   hB->available   = PETSC_TRUE;
2258336664bdSPierre Jolivet   hB->sorted_full = PETSC_FALSE; /* no assumption whether column indices are sorted or not */
2259c69f721fSFande Kong   hB->size        = 0;
2260c69f721fSFande Kong   hB->array       = NULL;
2261978814f1SStefano Zampini 
226263c07aadSStefano Zampini   B->data       = (void*)hB;
226363c07aadSStefano Zampini   B->rmap->bs   = 1;
226463c07aadSStefano Zampini   B->assembled  = PETSC_FALSE;
226563c07aadSStefano Zampini 
2266de393100SStefano Zampini   ierr = PetscMemzero(B->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
226763c07aadSStefano Zampini   B->ops->mult                  = MatMult_HYPRE;
226863c07aadSStefano Zampini   B->ops->multtranspose         = MatMultTranspose_HYPRE;
2269414bd5c3SStefano Zampini   B->ops->multadd               = MatMultAdd_HYPRE;
2270414bd5c3SStefano Zampini   B->ops->multtransposeadd      = MatMultTransposeAdd_HYPRE;
227163c07aadSStefano Zampini   B->ops->setup                 = MatSetUp_HYPRE;
227263c07aadSStefano Zampini   B->ops->destroy               = MatDestroy_HYPRE;
227363c07aadSStefano Zampini   B->ops->assemblyend           = MatAssemblyEnd_HYPRE;
2274c69f721fSFande Kong   B->ops->assemblybegin         = MatAssemblyBegin_HYPRE;
2275d975228cSstefano_zampini   B->ops->setvalues             = MatSetValues_HYPRE;
227668ec7858SStefano Zampini   B->ops->missingdiagonal       = MatMissingDiagonal_HYPRE;
227768ec7858SStefano Zampini   B->ops->scale                 = MatScale_HYPRE;
227868ec7858SStefano Zampini   B->ops->zerorowscolumns       = MatZeroRowsColumns_HYPRE;
2279c69f721fSFande Kong   B->ops->zeroentries           = MatZeroEntries_HYPRE;
2280c69f721fSFande Kong   B->ops->zerorows              = MatZeroRows_HYPRE;
2281c69f721fSFande Kong   B->ops->getrow                = MatGetRow_HYPRE;
2282c69f721fSFande Kong   B->ops->restorerow            = MatRestoreRow_HYPRE;
2283c69f721fSFande Kong   B->ops->getvalues             = MatGetValues_HYPRE;
2284ddbeb582SStefano Zampini   B->ops->setoption             = MatSetOption_HYPRE;
228545b8d346SStefano Zampini   B->ops->duplicate             = MatDuplicate_HYPRE;
2286465edc17SStefano Zampini   B->ops->copy                  = MatCopy_HYPRE;
228745b8d346SStefano Zampini   B->ops->view                  = MatView_HYPRE;
22886305df00SStefano Zampini   B->ops->getdiagonal           = MatGetDiagonal_HYPRE;
2289363d496dSStefano Zampini   B->ops->axpy                  = MatAXPY_HYPRE;
22904222ddf1SHong Zhang   B->ops->productsetfromoptions = MatProductSetFromOptions_HYPRE;
22916ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
22926ea7df73SStefano Zampini   B->ops->bindtocpu             = MatBindToCPU_HYPRE;
22936ea7df73SStefano Zampini   B->boundtocpu                 = PETSC_FALSE;
22946ea7df73SStefano Zampini #endif
229545b8d346SStefano Zampini 
229645b8d346SStefano Zampini   /* build cache for off array entries formed */
229745b8d346SStefano Zampini   ierr = MatStashCreate_Private(PetscObjectComm((PetscObject)B),1,&B->stash);CHKERRQ(ierr);
229863c07aadSStefano Zampini 
2299ffc4695bSBarry Smith   ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)B),&hB->comm);CHKERRMPI(ierr);
230063c07aadSStefano Zampini   ierr = PetscObjectChangeTypeName((PetscObject)B,MATHYPRE);CHKERRQ(ierr);
230163c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_hypre_aij_C",MatConvert_HYPRE_AIJ);CHKERRQ(ierr);
23022df22349SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_hypre_is_C",MatConvert_HYPRE_IS);CHKERRQ(ierr);
23034222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_hypre_C",MatProductSetFromOptions_HYPRE);CHKERRQ(ierr);
23044222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_mpiaij_hypre_C",MatProductSetFromOptions_HYPRE);CHKERRQ(ierr);
2305d975228cSstefano_zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatHYPRESetPreallocation_C",MatHYPRESetPreallocation_HYPRE);CHKERRQ(ierr);
2306dd9c0a25Sstefano_zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatHYPREGetParCSR_C",MatHYPREGetParCSR_HYPRE);CHKERRQ(ierr);
23076ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
23086ea7df73SStefano Zampini #if defined(HYPRE_USING_HIP)
23096ea7df73SStefano Zampini   ierr = PetscHIPInitializeCheck();CHKERRQ(ierr);
23106ea7df73SStefano Zampini   ierr = MatSetVecType(B,VECHIP);CHKERRQ(ierr);
23116ea7df73SStefano Zampini #endif
23126ea7df73SStefano Zampini #if defined(HYPRE_USING_CUDA)
23136ea7df73SStefano Zampini   ierr = PetscCUDAInitializeCheck();CHKERRQ(ierr);
23146ea7df73SStefano Zampini   ierr = MatSetVecType(B,VECCUDA);CHKERRQ(ierr);
23156ea7df73SStefano Zampini #endif
23166ea7df73SStefano Zampini #endif
231763c07aadSStefano Zampini   PetscFunctionReturn(0);
231863c07aadSStefano Zampini }
231963c07aadSStefano Zampini 
2320225daaf8SStefano Zampini static PetscErrorCode hypre_array_destroy(void *ptr)
2321225daaf8SStefano Zampini {
2322225daaf8SStefano Zampini    PetscFunctionBegin;
2323e6de0934SSatish Balay    hypre_TFree(ptr,HYPRE_MEMORY_HOST);
2324225daaf8SStefano Zampini    PetscFunctionReturn(0);
2325225daaf8SStefano Zampini }
2326