xref: /petsc/src/mat/impls/hypre/mhypre.c (revision 6ea7df73cca75adecc2aef0b2f4d0c18ef6de222)
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*);
28*6ea7df73SStefano 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;
138*6ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2,19,0)
139*6ea7df73SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixInitialize,(ij));
140*6ea7df73SStefano Zampini #else
141*6ea7df73SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixInitialize_v2,(ij,HYPRE_MEMORY_HOST));
142*6ea7df73SStefano 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));
178*6ea7df73SStefano 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   }
197*6ea7df73SStefano Zampini 
198*6ea7df73SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&pa);CHKERRQ(ierr);
199*6ea7df73SStefano Zampini   ierr = PetscArraycpy(hdiag->data,pa,pdiag->nz);CHKERRQ(ierr);
200*6ea7df73SStefano 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));
218*6ea7df73SStefano 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
248*6ea7df73SStefano Zampini   ierr = MatSeqAIJGetArrayRead(pA->A,&pa);CHKERRQ(ierr);
249*6ea7df73SStefano Zampini   ierr = PetscArraycpy(hdiag->data,pa,pdiag->nz);CHKERRQ(ierr);
250*6ea7df73SStefano 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 
268*6ea7df73SStefano Zampini   ierr = MatSeqAIJGetArrayRead(pA->B,&pa);CHKERRQ(ierr);
269*6ea7df73SStefano Zampini   ierr = PetscArraycpy(hoffd->data,pa,poffd->nz);CHKERRQ(ierr);
270*6ea7df73SStefano 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   }
445*6ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
446*6ea7df73SStefano Zampini   if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(hA->ij)) SETERRQ(comm,PETSC_ERR_SUP,"Not yet implemented");
447*6ea7df73SStefano 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) {
4892cf14000SStefano Zampini     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 {
492580bdb30SBarry Smith     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     }
5312cf14000SStefano Zampini     if (!sameint) {
5322cf14000SStefano Zampini       for (i=0;i<m+1;i++) oii[i] = (PetscInt)(hypre_CSRMatrixI(hoffd)[i]);
5332cf14000SStefano Zampini     } else {
534580bdb30SBarry Smith       ierr = PetscArraycpy(oii,hypre_CSRMatrixI(hoffd),m+1);CHKERRQ(ierr);
5352cf14000SStefano Zampini     }
53663c07aadSStefano Zampini     offdj = hypre_CSRMatrixJ(hoffd);
53763c07aadSStefano Zampini     coffd = hypre_ParCSRMatrixColMapOffd(parcsr);
53863c07aadSStefano Zampini     for (i=0; i<onnz; i++) ojj[i] = coffd[offdj[i]];
539580bdb30SBarry Smith     ierr = PetscArraycpy(oa,hypre_CSRMatrixData(hoffd),onnz);CHKERRQ(ierr);
54063c07aadSStefano Zampini     iptr = ojj;
54163c07aadSStefano Zampini     aptr = oa;
54263c07aadSStefano Zampini     for (i=0; i<m; i++) {
54363c07aadSStefano Zampini        PetscInt nc = oii[i+1]-oii[i];
54463c07aadSStefano Zampini        ierr = PetscSortIntWithScalarArray(nc,iptr,aptr);CHKERRQ(ierr);
54563c07aadSStefano Zampini        iptr += nc;
54663c07aadSStefano Zampini        aptr += nc;
54763c07aadSStefano Zampini     }
548225daaf8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
54963c07aadSStefano Zampini       Mat_MPIAIJ *b;
55063c07aadSStefano Zampini       Mat_SeqAIJ *d,*o;
551225daaf8SStefano Zampini 
55241073d71Sstefano_zampini       ierr = MatCreateMPIAIJWithSplitArrays(comm,m,n,PETSC_DECIDE,PETSC_DECIDE,dii,djj,da,oii,ojj,oa,B);CHKERRQ(ierr);
55363c07aadSStefano Zampini       /* hack MPIAIJ */
55463c07aadSStefano Zampini       b          = (Mat_MPIAIJ*)((*B)->data);
55563c07aadSStefano Zampini       d          = (Mat_SeqAIJ*)b->A->data;
55663c07aadSStefano Zampini       o          = (Mat_SeqAIJ*)b->B->data;
55763c07aadSStefano Zampini       d->free_a  = PETSC_TRUE;
55863c07aadSStefano Zampini       d->free_ij = PETSC_TRUE;
55963c07aadSStefano Zampini       o->free_a  = PETSC_TRUE;
56063c07aadSStefano Zampini       o->free_ij = PETSC_TRUE;
561225daaf8SStefano Zampini     } else if (reuse == MAT_INPLACE_MATRIX) {
562225daaf8SStefano Zampini       Mat T;
5632cf14000SStefano Zampini 
56441073d71Sstefano_zampini       ierr = MatCreateMPIAIJWithSplitArrays(comm,m,n,PETSC_DECIDE,PETSC_DECIDE,dii,djj,da,oii,ojj,oa,&T);CHKERRQ(ierr);
5652cf14000SStefano Zampini       if (sameint) { /* ownership of CSR pointers is transferred to PETSc */
566225daaf8SStefano Zampini         hypre_CSRMatrixI(hdiag) = NULL;
567225daaf8SStefano Zampini         hypre_CSRMatrixJ(hdiag) = NULL;
568225daaf8SStefano Zampini         hypre_CSRMatrixI(hoffd) = NULL;
569225daaf8SStefano Zampini         hypre_CSRMatrixJ(hoffd) = NULL;
5702cf14000SStefano Zampini       } else { /* Hack MPIAIJ -> free ij but not a */
5712cf14000SStefano Zampini         Mat_MPIAIJ *b = (Mat_MPIAIJ*)(T->data);
5722cf14000SStefano Zampini         Mat_SeqAIJ *d = (Mat_SeqAIJ*)(b->A->data);
5732cf14000SStefano Zampini         Mat_SeqAIJ *o = (Mat_SeqAIJ*)(b->B->data);
5742cf14000SStefano Zampini 
5752cf14000SStefano Zampini         d->free_ij = PETSC_TRUE;
5762cf14000SStefano Zampini         o->free_ij = PETSC_TRUE;
5772cf14000SStefano Zampini       }
5782cf14000SStefano Zampini       hypre_CSRMatrixData(hdiag) = NULL;
579225daaf8SStefano Zampini       hypre_CSRMatrixData(hoffd) = NULL;
580225daaf8SStefano Zampini       ierr = MatHeaderReplace(A,&T);CHKERRQ(ierr);
58163c07aadSStefano Zampini     }
582225daaf8SStefano Zampini   } else {
583225daaf8SStefano Zampini     oii  = NULL;
584225daaf8SStefano Zampini     ojj  = NULL;
585225daaf8SStefano Zampini     oa   = NULL;
586225daaf8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
58763c07aadSStefano Zampini       Mat_SeqAIJ* b;
5882cf14000SStefano Zampini 
58963c07aadSStefano Zampini       ierr = MatCreateSeqAIJWithArrays(comm,m,n,dii,djj,da,B);CHKERRQ(ierr);
59063c07aadSStefano Zampini       /* hack SeqAIJ */
59163c07aadSStefano Zampini       b          = (Mat_SeqAIJ*)((*B)->data);
59263c07aadSStefano Zampini       b->free_a  = PETSC_TRUE;
59363c07aadSStefano Zampini       b->free_ij = PETSC_TRUE;
594225daaf8SStefano Zampini     } else if (reuse == MAT_INPLACE_MATRIX) {
595225daaf8SStefano Zampini       Mat T;
5962cf14000SStefano Zampini 
597225daaf8SStefano Zampini       ierr = MatCreateSeqAIJWithArrays(comm,m,n,dii,djj,da,&T);CHKERRQ(ierr);
5982cf14000SStefano Zampini       if (sameint) { /* ownership of CSR pointers is transferred to PETSc */
599225daaf8SStefano Zampini         hypre_CSRMatrixI(hdiag) = NULL;
600225daaf8SStefano Zampini         hypre_CSRMatrixJ(hdiag) = NULL;
6012cf14000SStefano Zampini       } else { /* free ij but not a */
6022cf14000SStefano Zampini         Mat_SeqAIJ* b = (Mat_SeqAIJ*)(T->data);
6032cf14000SStefano Zampini 
6042cf14000SStefano Zampini         b->free_ij = PETSC_TRUE;
6052cf14000SStefano Zampini       }
606225daaf8SStefano Zampini       hypre_CSRMatrixData(hdiag) = NULL;
607225daaf8SStefano Zampini       ierr = MatHeaderReplace(A,&T);CHKERRQ(ierr);
60863c07aadSStefano Zampini     }
609225daaf8SStefano Zampini   }
610225daaf8SStefano Zampini 
6112cf14000SStefano Zampini   /* we have to use hypre_Tfree to free the HYPRE arrays
6122cf14000SStefano Zampini      that PETSc now onws */
61363c07aadSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
6142cf14000SStefano Zampini     PetscInt nh;
6152cf14000SStefano Zampini     void *ptrs[6] = {da,oa,dii,djj,oii,ojj};
6162cf14000SStefano Zampini     const char *names[6] = {"_hypre_csr_da",
6172cf14000SStefano Zampini                             "_hypre_csr_oa",
6182cf14000SStefano Zampini                             "_hypre_csr_dii",
619225daaf8SStefano Zampini                             "_hypre_csr_djj",
620225daaf8SStefano Zampini                             "_hypre_csr_oii",
6212cf14000SStefano Zampini                             "_hypre_csr_ojj"};
6222cf14000SStefano Zampini     nh = sameint ? 6 : 2;
6232cf14000SStefano Zampini     for (i=0; i<nh; i++) {
624225daaf8SStefano Zampini       PetscContainer c;
625225daaf8SStefano Zampini 
626225daaf8SStefano Zampini       ierr = PetscContainerCreate(comm,&c);CHKERRQ(ierr);
627225daaf8SStefano Zampini       ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr);
628225daaf8SStefano Zampini       ierr = PetscContainerSetUserDestroy(c,hypre_array_destroy);CHKERRQ(ierr);
629225daaf8SStefano Zampini       ierr = PetscObjectCompose((PetscObject)(*B),names[i],(PetscObject)c);CHKERRQ(ierr);
630225daaf8SStefano Zampini       ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
631225daaf8SStefano Zampini     }
63263c07aadSStefano Zampini   }
63363c07aadSStefano Zampini   PetscFunctionReturn(0);
63463c07aadSStefano Zampini }
63563c07aadSStefano Zampini 
636613e5ff0Sstefano_zampini static PetscErrorCode MatAIJGetParCSR_Private(Mat A, hypre_ParCSRMatrix **hA)
637c1a070e6SStefano Zampini {
638613e5ff0Sstefano_zampini   hypre_ParCSRMatrix *tA;
639c1a070e6SStefano Zampini   hypre_CSRMatrix    *hdiag,*hoffd;
640c1a070e6SStefano Zampini   Mat_SeqAIJ         *diag,*offd;
6412cf14000SStefano Zampini   PetscInt           *garray,i,noffd,dnnz,onnz,*row_starts,*col_starts;
642c1a070e6SStefano Zampini   MPI_Comm           comm = PetscObjectComm((PetscObject)A);
643613e5ff0Sstefano_zampini   PetscBool          ismpiaij,isseqaij;
6442cf14000SStefano Zampini   PetscBool          sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
645c1a070e6SStefano Zampini   PetscErrorCode     ierr;
646*6ea7df73SStefano Zampini   HYPRE_Int          *hdi = NULL,*hdj = NULL,*hoi = NULL,*hoj = NULL;
647*6ea7df73SStefano Zampini   PetscInt           *pdi,*pdj,*poi,*poj;
648*6ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
649*6ea7df73SStefano Zampini   PetscBool          iscuda = PETSC_FALSE;
650*6ea7df73SStefano Zampini #endif
651c1a070e6SStefano Zampini 
652c1a070e6SStefano Zampini   PetscFunctionBegin;
6533937f725SBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
6544099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
655a32993e3SJed Brown   if (!ismpiaij && !isseqaij) SETERRQ1(comm,PETSC_ERR_SUP,"Unsupported type %s",((PetscObject)A)->type_name);
656c1a070e6SStefano Zampini   if (ismpiaij) {
657c1a070e6SStefano Zampini     Mat_MPIAIJ *a = (Mat_MPIAIJ*)(A->data);
658c1a070e6SStefano Zampini 
659c1a070e6SStefano Zampini     diag = (Mat_SeqAIJ*)a->A->data;
660c1a070e6SStefano Zampini     offd = (Mat_SeqAIJ*)a->B->data;
661*6ea7df73SStefano Zampini #if defined(PETSC_HAVE_CUDA) && defined(PETSC_HAVE_HYPRE_DEVICE) && defined(HYPRE_USING_CUDA)
662*6ea7df73SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJCUSPARSE,&iscuda);CHKERRQ(ierr);
663*6ea7df73SStefano Zampini     if (iscuda && !A->boundtocpu) {
664*6ea7df73SStefano Zampini       sameint = PETSC_TRUE;
665*6ea7df73SStefano Zampini       ierr = MatSeqAIJCUSPARSEGetIJ(a->A,PETSC_FALSE,(const HYPRE_Int**)&hdi,(const HYPRE_Int**)&hdj);CHKERRQ(ierr);
666*6ea7df73SStefano Zampini       ierr = MatSeqAIJCUSPARSEGetIJ(a->B,PETSC_FALSE,(const HYPRE_Int**)&hoi,(const HYPRE_Int**)&hoj);CHKERRQ(ierr);
667*6ea7df73SStefano Zampini     } else {
668*6ea7df73SStefano Zampini #else
669*6ea7df73SStefano Zampini     {
670*6ea7df73SStefano Zampini #endif
671*6ea7df73SStefano Zampini       pdi = diag->i;
672*6ea7df73SStefano Zampini       pdj = diag->j;
673*6ea7df73SStefano Zampini       poi = offd->i;
674*6ea7df73SStefano Zampini       poj = offd->j;
675*6ea7df73SStefano Zampini       if (sameint) {
676*6ea7df73SStefano Zampini         hdi = (HYPRE_Int*)pdi;
677*6ea7df73SStefano Zampini         hdj = (HYPRE_Int*)pdj;
678*6ea7df73SStefano Zampini         hoi = (HYPRE_Int*)poi;
679*6ea7df73SStefano Zampini         hoj = (HYPRE_Int*)poj;
680*6ea7df73SStefano Zampini       }
681*6ea7df73SStefano Zampini     }
682c1a070e6SStefano Zampini     garray = a->garray;
683c1a070e6SStefano Zampini     noffd  = a->B->cmap->N;
684c1a070e6SStefano Zampini     dnnz   = diag->nz;
685c1a070e6SStefano Zampini     onnz   = offd->nz;
686c1a070e6SStefano Zampini   } else {
687c1a070e6SStefano Zampini     diag = (Mat_SeqAIJ*)A->data;
688c1a070e6SStefano Zampini     offd = NULL;
689*6ea7df73SStefano Zampini #if defined(PETSC_HAVE_CUDA) && defined(PETSC_HAVE_HYPRE_DEVICE)
690*6ea7df73SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJCUSPARSE,&iscuda);CHKERRQ(ierr);
691*6ea7df73SStefano Zampini     if (iscuda && !A->boundtocpu) {
692*6ea7df73SStefano Zampini       sameint = PETSC_TRUE;
693*6ea7df73SStefano Zampini       ierr = MatSeqAIJCUSPARSEGetIJ(A,PETSC_FALSE,(const HYPRE_Int**)&hdi,(const HYPRE_Int**)&hdj);CHKERRQ(ierr);
694*6ea7df73SStefano Zampini     } else {
695*6ea7df73SStefano Zampini #else
696*6ea7df73SStefano Zampini     {
697*6ea7df73SStefano Zampini #endif
698*6ea7df73SStefano Zampini       pdi = diag->i;
699*6ea7df73SStefano Zampini       pdj = diag->j;
700*6ea7df73SStefano Zampini       if (sameint) {
701*6ea7df73SStefano Zampini         hdi = (HYPRE_Int*)pdi;
702*6ea7df73SStefano Zampini         hdj = (HYPRE_Int*)pdj;
703*6ea7df73SStefano Zampini       }
704*6ea7df73SStefano Zampini     }
705c1a070e6SStefano Zampini     garray = NULL;
706c1a070e6SStefano Zampini     noffd  = 0;
707c1a070e6SStefano Zampini     dnnz   = diag->nz;
708c1a070e6SStefano Zampini     onnz   = 0;
709c1a070e6SStefano Zampini   }
710225daaf8SStefano Zampini 
711c1a070e6SStefano Zampini   /* create a temporary ParCSR */
712c1a070e6SStefano Zampini   if (HYPRE_AssumedPartitionCheck()) {
713c1a070e6SStefano Zampini     PetscMPIInt myid;
714c1a070e6SStefano Zampini 
71555b25c41SPierre Jolivet     ierr       = MPI_Comm_rank(comm,&myid);CHKERRMPI(ierr);
716c1a070e6SStefano Zampini     row_starts = A->rmap->range + myid;
717c1a070e6SStefano Zampini     col_starts = A->cmap->range + myid;
718c1a070e6SStefano Zampini   } else {
719c1a070e6SStefano Zampini     row_starts = A->rmap->range;
720c1a070e6SStefano Zampini     col_starts = A->cmap->range;
721c1a070e6SStefano Zampini   }
7222cf14000SStefano Zampini   tA = hypre_ParCSRMatrixCreate(comm,A->rmap->N,A->cmap->N,(HYPRE_BigInt*)row_starts,(HYPRE_BigInt*)col_starts,noffd,dnnz,onnz);
723a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
724c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetRowStartsOwner(tA,0);
725c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetColStartsOwner(tA,0);
726a1d2239cSSatish Balay #endif
727c1a070e6SStefano Zampini 
728225daaf8SStefano Zampini   /* set diagonal part */
729c1a070e6SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(tA);
730*6ea7df73SStefano Zampini   if (!sameint) { /* malloc CSR pointers */
731*6ea7df73SStefano Zampini     ierr = PetscMalloc2(A->rmap->n+1,&hdi,dnnz,&hdj);CHKERRQ(ierr);
732*6ea7df73SStefano Zampini     for (i = 0; i < A->rmap->n+1; i++) hdi[i] = (HYPRE_Int)(pdi[i]);
733*6ea7df73SStefano Zampini     for (i = 0; i < dnnz; i++)         hdj[i] = (HYPRE_Int)(pdj[i]);
7342cf14000SStefano Zampini   }
735*6ea7df73SStefano Zampini   hypre_CSRMatrixI(hdiag)           = hdi;
736*6ea7df73SStefano Zampini   hypre_CSRMatrixJ(hdiag)           = hdj;
73739accc25SStefano Zampini   hypre_CSRMatrixData(hdiag)        = (HYPRE_Complex*)diag->a;
738c1a070e6SStefano Zampini   hypre_CSRMatrixNumNonzeros(hdiag) = diag->nz;
739c1a070e6SStefano Zampini   hypre_CSRMatrixSetRownnz(hdiag);
740c1a070e6SStefano Zampini   hypre_CSRMatrixSetDataOwner(hdiag,0);
741c1a070e6SStefano Zampini 
742225daaf8SStefano Zampini   /* set offdiagonal part */
743c1a070e6SStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(tA);
744c1a070e6SStefano Zampini   if (offd) {
745*6ea7df73SStefano Zampini     if (!sameint) { /* malloc CSR pointers */
746*6ea7df73SStefano Zampini       ierr = PetscMalloc2(A->rmap->n+1,&hoi,onnz,&hoj);CHKERRQ(ierr);
747*6ea7df73SStefano Zampini       for (i = 0; i < A->rmap->n+1; i++) hoi[i] = (HYPRE_Int)(poi[i]);
748*6ea7df73SStefano Zampini       for (i = 0; i < onnz; i++)         hoj[i] = (HYPRE_Int)(poj[i]);
7492cf14000SStefano Zampini     }
750*6ea7df73SStefano Zampini     hypre_CSRMatrixI(hoffd)           = hoi;
751*6ea7df73SStefano Zampini     hypre_CSRMatrixJ(hoffd)           = hoj;
75239accc25SStefano Zampini     hypre_CSRMatrixData(hoffd)        = (HYPRE_Complex*)offd->a;
753c1a070e6SStefano Zampini     hypre_CSRMatrixNumNonzeros(hoffd) = offd->nz;
754c1a070e6SStefano Zampini     hypre_CSRMatrixSetRownnz(hoffd);
755c1a070e6SStefano Zampini     hypre_CSRMatrixSetDataOwner(hoffd,0);
756*6ea7df73SStefano Zampini   }
757*6ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
758*6ea7df73SStefano Zampini   PetscStackCallStandard(hypre_ParCSRMatrixInitialize_v2,(tA,iscuda ? HYPRE_MEMORY_DEVICE : HYPRE_MEMORY_HOST));
759*6ea7df73SStefano Zampini #else
760*6ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2,18,0)
761*6ea7df73SStefano Zampini   PetscStackCallStandard(hypre_ParCSRMatrixInitialize,(tA));
762*6ea7df73SStefano Zampini #else
763*6ea7df73SStefano Zampini   PetscStackCallStandard(hypre_ParCSRMatrixInitialize_v2,(tA,HYPRE_MEMORY_HOST));
764*6ea7df73SStefano Zampini #endif
765*6ea7df73SStefano Zampini #endif
766*6ea7df73SStefano Zampini   hypre_TFree(hypre_ParCSRMatrixColMapOffd(tA),HYPRE_MEMORY_HOST);
767c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetNumNonzeros(tA);
7682cf14000SStefano Zampini   hypre_ParCSRMatrixColMapOffd(tA) = (HYPRE_BigInt*)garray;
769*6ea7df73SStefano Zampini   if (!hypre_ParCSRMatrixCommPkg(tA)) PetscStackCallStandard(hypre_MatvecCommPkgCreate,(tA));
770613e5ff0Sstefano_zampini   *hA = tA;
771613e5ff0Sstefano_zampini   PetscFunctionReturn(0);
772613e5ff0Sstefano_zampini }
773c1a070e6SStefano Zampini 
774613e5ff0Sstefano_zampini static PetscErrorCode MatAIJRestoreParCSR_Private(Mat A, hypre_ParCSRMatrix **hA)
775613e5ff0Sstefano_zampini {
776613e5ff0Sstefano_zampini   hypre_CSRMatrix *hdiag,*hoffd;
777*6ea7df73SStefano Zampini   PetscBool       ismpiaij,sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
7782cf14000SStefano Zampini   PetscErrorCode  ierr;
779*6ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
780*6ea7df73SStefano Zampini   PetscBool       iscuda = PETSC_FALSE;
781*6ea7df73SStefano Zampini #endif
782c1a070e6SStefano Zampini 
783613e5ff0Sstefano_zampini   PetscFunctionBegin;
784*6ea7df73SStefano Zampini   ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
785*6ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
786*6ea7df73SStefano Zampini   ierr = PetscObjectTypeCompareAny((PetscObject)A,&iscuda,MATSEQAIJCUSPARSE,MATMPIAIJCUSPARSE,"");CHKERRQ(ierr);
787*6ea7df73SStefano Zampini   if (iscuda) sameint = PETSC_TRUE;
788*6ea7df73SStefano Zampini #endif
789613e5ff0Sstefano_zampini   hdiag = hypre_ParCSRMatrixDiag(*hA);
790613e5ff0Sstefano_zampini   hoffd = hypre_ParCSRMatrixOffd(*hA);
791*6ea7df73SStefano Zampini   /* free temporary memory allocated by PETSc
792*6ea7df73SStefano Zampini      set pointers to NULL before destroying tA */
7932cf14000SStefano Zampini   if (!sameint) {
7942cf14000SStefano Zampini     HYPRE_Int *hi,*hj;
7952cf14000SStefano Zampini 
7962cf14000SStefano Zampini     hi = hypre_CSRMatrixI(hdiag);
7972cf14000SStefano Zampini     hj = hypre_CSRMatrixJ(hdiag);
7982cf14000SStefano Zampini     ierr = PetscFree2(hi,hj);CHKERRQ(ierr);
799*6ea7df73SStefano Zampini     if (ismpiaij) {
8002cf14000SStefano Zampini       hi = hypre_CSRMatrixI(hoffd);
8012cf14000SStefano Zampini       hj = hypre_CSRMatrixJ(hoffd);
8022cf14000SStefano Zampini       ierr = PetscFree2(hi,hj);CHKERRQ(ierr);
8032cf14000SStefano Zampini     }
8042cf14000SStefano Zampini   }
805c1a070e6SStefano Zampini   hypre_CSRMatrixI(hdiag)    = NULL;
806c1a070e6SStefano Zampini   hypre_CSRMatrixJ(hdiag)    = NULL;
807c1a070e6SStefano Zampini   hypre_CSRMatrixData(hdiag) = NULL;
808*6ea7df73SStefano Zampini   if (ismpiaij) {
809c1a070e6SStefano Zampini     hypre_CSRMatrixI(hoffd)    = NULL;
810c1a070e6SStefano Zampini     hypre_CSRMatrixJ(hoffd)    = NULL;
811c1a070e6SStefano Zampini     hypre_CSRMatrixData(hoffd) = NULL;
812*6ea7df73SStefano Zampini   }
813613e5ff0Sstefano_zampini   hypre_ParCSRMatrixColMapOffd(*hA) = NULL;
814613e5ff0Sstefano_zampini   hypre_ParCSRMatrixDestroy(*hA);
815613e5ff0Sstefano_zampini   *hA = NULL;
816613e5ff0Sstefano_zampini   PetscFunctionReturn(0);
817613e5ff0Sstefano_zampini }
818613e5ff0Sstefano_zampini 
819613e5ff0Sstefano_zampini /* calls RAP from BoomerAMG:
8203dad0653Sstefano_zampini    the resulting ParCSR will not own the column and row starts
821*6ea7df73SStefano Zampini    It looks like we don't need to have the diagonal entries ordered first */
822a055b5aaSBarry Smith static PetscErrorCode MatHYPRE_ParCSR_RAP(hypre_ParCSRMatrix *hR, hypre_ParCSRMatrix *hA,hypre_ParCSRMatrix *hP, hypre_ParCSRMatrix **hRAP)
823613e5ff0Sstefano_zampini {
824a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
825613e5ff0Sstefano_zampini   HYPRE_Int P_owns_col_starts,R_owns_row_starts;
826a1d2239cSSatish Balay #endif
827613e5ff0Sstefano_zampini 
828613e5ff0Sstefano_zampini   PetscFunctionBegin;
829a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
830613e5ff0Sstefano_zampini   P_owns_col_starts = hypre_ParCSRMatrixOwnsColStarts(hP);
831613e5ff0Sstefano_zampini   R_owns_row_starts = hypre_ParCSRMatrixOwnsRowStarts(hR);
832a1d2239cSSatish Balay #endif
833*6ea7df73SStefano Zampini   /* can be replaced by version test later */
834*6ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
835*6ea7df73SStefano Zampini   PetscStackPush("hypre_ParCSRMatrixRAP");
836*6ea7df73SStefano Zampini   *hRAP = hypre_ParCSRMatrixRAP(hR,hA,hP);
837*6ea7df73SStefano Zampini   PetscStackPop;
838*6ea7df73SStefano Zampini #else
839613e5ff0Sstefano_zampini   PetscStackCallStandard(hypre_BoomerAMGBuildCoarseOperator,(hR,hA,hP,hRAP));
840613e5ff0Sstefano_zampini   PetscStackCallStandard(hypre_ParCSRMatrixSetNumNonzeros,(*hRAP));
841*6ea7df73SStefano Zampini #endif
842613e5ff0Sstefano_zampini   /* hypre_BoomerAMGBuildCoarseOperator steals the col_starts from P and the row_starts from R */
843a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
844613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetRowStartsOwner(*hRAP,0);
845613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetColStartsOwner(*hRAP,0);
846613e5ff0Sstefano_zampini   if (P_owns_col_starts) hypre_ParCSRMatrixSetColStartsOwner(hP,1);
847613e5ff0Sstefano_zampini   if (R_owns_row_starts) hypre_ParCSRMatrixSetRowStartsOwner(hR,1);
848a1d2239cSSatish Balay #endif
849613e5ff0Sstefano_zampini   PetscFunctionReturn(0);
850613e5ff0Sstefano_zampini }
851613e5ff0Sstefano_zampini 
8526f231fbdSstefano_zampini static PetscErrorCode MatPtAPNumeric_AIJ_AIJ_wHYPRE(Mat A,Mat P,Mat C)
853613e5ff0Sstefano_zampini {
8546f231fbdSstefano_zampini   Mat                B;
855613e5ff0Sstefano_zampini   hypre_ParCSRMatrix *hA,*hP,*hPtAP;
856613e5ff0Sstefano_zampini   PetscErrorCode     ierr;
8574222ddf1SHong Zhang   Mat_Product        *product=C->product;
858613e5ff0Sstefano_zampini 
859613e5ff0Sstefano_zampini   PetscFunctionBegin;
860613e5ff0Sstefano_zampini   ierr = MatAIJGetParCSR_Private(A,&hA);CHKERRQ(ierr);
861613e5ff0Sstefano_zampini   ierr = MatAIJGetParCSR_Private(P,&hP);CHKERRQ(ierr);
862613e5ff0Sstefano_zampini   ierr = MatHYPRE_ParCSR_RAP(hP,hA,hP,&hPtAP);CHKERRQ(ierr);
8636f231fbdSstefano_zampini   ierr = MatCreateFromParCSR(hPtAP,MATAIJ,PETSC_OWN_POINTER,&B);CHKERRQ(ierr);
8644222ddf1SHong Zhang 
8656f231fbdSstefano_zampini   ierr = MatHeaderMerge(C,&B);CHKERRQ(ierr);
8664222ddf1SHong Zhang   C->product = product;
8674222ddf1SHong Zhang 
868613e5ff0Sstefano_zampini   ierr = MatAIJRestoreParCSR_Private(A,&hA);CHKERRQ(ierr);
869613e5ff0Sstefano_zampini   ierr = MatAIJRestoreParCSR_Private(P,&hP);CHKERRQ(ierr);
8706f231fbdSstefano_zampini   PetscFunctionReturn(0);
8716f231fbdSstefano_zampini }
8726f231fbdSstefano_zampini 
8734222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatPtAPSymbolic_AIJ_AIJ_wHYPRE(Mat A,Mat P,PetscReal fill,Mat C)
8746f231fbdSstefano_zampini {
8756f231fbdSstefano_zampini   PetscErrorCode ierr;
876ab4d48faSStefano Zampini 
8776f231fbdSstefano_zampini   PetscFunctionBegin;
8784222ddf1SHong Zhang   ierr                   = MatSetType(C,MATAIJ);CHKERRQ(ierr);
8794222ddf1SHong Zhang   C->ops->ptapnumeric    = MatPtAPNumeric_AIJ_AIJ_wHYPRE;
8804222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
881613e5ff0Sstefano_zampini   PetscFunctionReturn(0);
882613e5ff0Sstefano_zampini }
883613e5ff0Sstefano_zampini 
8844cc28894Sstefano_zampini static PetscErrorCode MatPtAPNumeric_AIJ_HYPRE(Mat A,Mat P,Mat C)
885613e5ff0Sstefano_zampini {
8864cc28894Sstefano_zampini   Mat                B;
8874cc28894Sstefano_zampini   Mat_HYPRE          *hP;
888613e5ff0Sstefano_zampini   hypre_ParCSRMatrix *hA = NULL,*Pparcsr,*ptapparcsr;
889613e5ff0Sstefano_zampini   HYPRE_Int          type;
890613e5ff0Sstefano_zampini   MPI_Comm           comm = PetscObjectComm((PetscObject)A);
8914cc28894Sstefano_zampini   PetscBool          ishypre;
892613e5ff0Sstefano_zampini   PetscErrorCode     ierr;
893613e5ff0Sstefano_zampini 
894613e5ff0Sstefano_zampini   PetscFunctionBegin;
8954cc28894Sstefano_zampini   ierr = PetscObjectTypeCompare((PetscObject)P,MATHYPRE,&ishypre);CHKERRQ(ierr);
8964cc28894Sstefano_zampini   if (!ishypre) SETERRQ1(comm,PETSC_ERR_USER,"P should be of type %s",MATHYPRE);
8974cc28894Sstefano_zampini   hP = (Mat_HYPRE*)P->data;
898613e5ff0Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hP->ij,&type));
899613e5ff0Sstefano_zampini   if (type != HYPRE_PARCSR) SETERRQ(comm,PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
900613e5ff0Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hP->ij,(void**)&Pparcsr));
901613e5ff0Sstefano_zampini 
902613e5ff0Sstefano_zampini   ierr = MatAIJGetParCSR_Private(A,&hA);CHKERRQ(ierr);
903613e5ff0Sstefano_zampini   ierr = MatHYPRE_ParCSR_RAP(Pparcsr,hA,Pparcsr,&ptapparcsr);CHKERRQ(ierr);
904613e5ff0Sstefano_zampini   ierr = MatAIJRestoreParCSR_Private(A,&hA);CHKERRQ(ierr);
905225daaf8SStefano Zampini 
9064cc28894Sstefano_zampini   /* create temporary matrix and merge to C */
9074cc28894Sstefano_zampini   ierr = MatCreateFromParCSR(ptapparcsr,((PetscObject)C)->type_name,PETSC_OWN_POINTER,&B);CHKERRQ(ierr);
9084cc28894Sstefano_zampini   ierr = MatHeaderMerge(C,&B);CHKERRQ(ierr);
9094cc28894Sstefano_zampini   PetscFunctionReturn(0);
9104cc28894Sstefano_zampini }
9114cc28894Sstefano_zampini 
9124cc28894Sstefano_zampini static PetscErrorCode MatPtAPNumeric_HYPRE_HYPRE(Mat A,Mat P,Mat C)
9134cc28894Sstefano_zampini {
9144cc28894Sstefano_zampini   Mat                B;
9154cc28894Sstefano_zampini   hypre_ParCSRMatrix *Aparcsr,*Pparcsr,*ptapparcsr;
9164cc28894Sstefano_zampini   Mat_HYPRE          *hA,*hP;
9174cc28894Sstefano_zampini   PetscBool          ishypre;
9184cc28894Sstefano_zampini   HYPRE_Int          type;
9194cc28894Sstefano_zampini   PetscErrorCode     ierr;
9204cc28894Sstefano_zampini 
9214cc28894Sstefano_zampini   PetscFunctionBegin;
9224cc28894Sstefano_zampini   ierr = PetscObjectTypeCompare((PetscObject)P,MATHYPRE,&ishypre);CHKERRQ(ierr);
9234cc28894Sstefano_zampini   if (!ishypre) SETERRQ1(PetscObjectComm((PetscObject)P),PETSC_ERR_USER,"P should be of type %s",MATHYPRE);
9244cc28894Sstefano_zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATHYPRE,&ishypre);CHKERRQ(ierr);
9254cc28894Sstefano_zampini   if (!ishypre) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_USER,"A should be of type %s",MATHYPRE);
9264cc28894Sstefano_zampini   hA = (Mat_HYPRE*)A->data;
9274cc28894Sstefano_zampini   hP = (Mat_HYPRE*)P->data;
9284cc28894Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type));
9294cc28894Sstefano_zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
9304cc28894Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hP->ij,&type));
9314cc28894Sstefano_zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)P),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
9324cc28894Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&Aparcsr));
9334cc28894Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hP->ij,(void**)&Pparcsr));
9344cc28894Sstefano_zampini   ierr = MatHYPRE_ParCSR_RAP(Pparcsr,Aparcsr,Pparcsr,&ptapparcsr);CHKERRQ(ierr);
9354cc28894Sstefano_zampini   ierr = MatCreateFromParCSR(ptapparcsr,MATHYPRE,PETSC_OWN_POINTER,&B);CHKERRQ(ierr);
9364cc28894Sstefano_zampini   ierr = MatHeaderMerge(C,&B);CHKERRQ(ierr);
9374cc28894Sstefano_zampini   PetscFunctionReturn(0);
9384cc28894Sstefano_zampini }
9394cc28894Sstefano_zampini 
940d501dc42Sstefano_zampini /* calls hypre_ParMatmul
941d501dc42Sstefano_zampini    hypre_ParMatMul uses hypre_ParMatrixCreate with the communicator of hA
9423dad0653Sstefano_zampini    hypre_ParMatrixCreate does not duplicate the communicator
943*6ea7df73SStefano Zampini    It looks like we don't need to have the diagonal entries ordered first */
944d501dc42Sstefano_zampini static PetscErrorCode MatHYPRE_ParCSR_MatMatMult(hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hB, hypre_ParCSRMatrix **hAB)
945d501dc42Sstefano_zampini {
946d501dc42Sstefano_zampini   PetscFunctionBegin;
947*6ea7df73SStefano Zampini   /* can be replaced by version test later */
948*6ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
949*6ea7df73SStefano Zampini   PetscStackPush("hypre_ParCSRMatMat");
950*6ea7df73SStefano Zampini   *hAB = hypre_ParCSRMatMat(hA,hB);
951*6ea7df73SStefano Zampini #else
952d501dc42Sstefano_zampini   PetscStackPush("hypre_ParMatmul");
953d501dc42Sstefano_zampini   *hAB = hypre_ParMatmul(hA,hB);
954*6ea7df73SStefano Zampini #endif
955d501dc42Sstefano_zampini   PetscStackPop;
956d501dc42Sstefano_zampini   PetscFunctionReturn(0);
957d501dc42Sstefano_zampini }
958d501dc42Sstefano_zampini 
9595e5acdf2Sstefano_zampini static PetscErrorCode MatMatMultNumeric_AIJ_AIJ_wHYPRE(Mat A,Mat B,Mat C)
9605e5acdf2Sstefano_zampini {
9615e5acdf2Sstefano_zampini   Mat                D;
962d501dc42Sstefano_zampini   hypre_ParCSRMatrix *hA,*hB,*hAB = NULL;
9635e5acdf2Sstefano_zampini   PetscErrorCode     ierr;
9644222ddf1SHong Zhang   Mat_Product        *product=C->product;
9655e5acdf2Sstefano_zampini 
9665e5acdf2Sstefano_zampini   PetscFunctionBegin;
9675e5acdf2Sstefano_zampini   ierr = MatAIJGetParCSR_Private(A,&hA);CHKERRQ(ierr);
9685e5acdf2Sstefano_zampini   ierr = MatAIJGetParCSR_Private(B,&hB);CHKERRQ(ierr);
969d501dc42Sstefano_zampini   ierr = MatHYPRE_ParCSR_MatMatMult(hA,hB,&hAB);CHKERRQ(ierr);
9705e5acdf2Sstefano_zampini   ierr = MatCreateFromParCSR(hAB,MATAIJ,PETSC_OWN_POINTER,&D);CHKERRQ(ierr);
9714222ddf1SHong Zhang 
9725e5acdf2Sstefano_zampini   ierr = MatHeaderMerge(C,&D);CHKERRQ(ierr);
9734222ddf1SHong Zhang   C->product = product;
9744222ddf1SHong Zhang 
9755e5acdf2Sstefano_zampini   ierr = MatAIJRestoreParCSR_Private(A,&hA);CHKERRQ(ierr);
9765e5acdf2Sstefano_zampini   ierr = MatAIJRestoreParCSR_Private(B,&hB);CHKERRQ(ierr);
9775e5acdf2Sstefano_zampini   PetscFunctionReturn(0);
9785e5acdf2Sstefano_zampini }
9795e5acdf2Sstefano_zampini 
9804222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatMatMultSymbolic_AIJ_AIJ_wHYPRE(Mat A,Mat B,PetscReal fill,Mat C)
9815e5acdf2Sstefano_zampini {
9825e5acdf2Sstefano_zampini   PetscErrorCode ierr;
98320e1dc0dSstefano_zampini 
9845e5acdf2Sstefano_zampini   PetscFunctionBegin;
9854222ddf1SHong Zhang   ierr = MatSetType(C,MATAIJ);CHKERRQ(ierr);
9864222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_AIJ_AIJ_wHYPRE;
9874222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
9885e5acdf2Sstefano_zampini   PetscFunctionReturn(0);
9895e5acdf2Sstefano_zampini }
9905e5acdf2Sstefano_zampini 
991d501dc42Sstefano_zampini static PetscErrorCode MatMatMultNumeric_HYPRE_HYPRE(Mat A,Mat B,Mat C)
992d501dc42Sstefano_zampini {
993d501dc42Sstefano_zampini   Mat                D;
994d501dc42Sstefano_zampini   hypre_ParCSRMatrix *Aparcsr,*Bparcsr,*ABparcsr = NULL;
995d501dc42Sstefano_zampini   Mat_HYPRE          *hA,*hB;
996d501dc42Sstefano_zampini   PetscBool          ishypre;
997d501dc42Sstefano_zampini   HYPRE_Int          type;
998d501dc42Sstefano_zampini   PetscErrorCode     ierr;
9994222ddf1SHong Zhang   Mat_Product        *product;
1000d501dc42Sstefano_zampini 
1001d501dc42Sstefano_zampini   PetscFunctionBegin;
1002d501dc42Sstefano_zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATHYPRE,&ishypre);CHKERRQ(ierr);
1003d501dc42Sstefano_zampini   if (!ishypre) SETERRQ1(PetscObjectComm((PetscObject)B),PETSC_ERR_USER,"B should be of type %s",MATHYPRE);
1004d501dc42Sstefano_zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATHYPRE,&ishypre);CHKERRQ(ierr);
1005d501dc42Sstefano_zampini   if (!ishypre) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_USER,"A should be of type %s",MATHYPRE);
1006d501dc42Sstefano_zampini   hA = (Mat_HYPRE*)A->data;
1007d501dc42Sstefano_zampini   hB = (Mat_HYPRE*)B->data;
1008d501dc42Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type));
1009d501dc42Sstefano_zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
1010d501dc42Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hB->ij,&type));
1011d501dc42Sstefano_zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
1012d501dc42Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&Aparcsr));
1013d501dc42Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hB->ij,(void**)&Bparcsr));
1014d501dc42Sstefano_zampini   ierr = MatHYPRE_ParCSR_MatMatMult(Aparcsr,Bparcsr,&ABparcsr);CHKERRQ(ierr);
1015d501dc42Sstefano_zampini   ierr = MatCreateFromParCSR(ABparcsr,MATHYPRE,PETSC_OWN_POINTER,&D);CHKERRQ(ierr);
10164222ddf1SHong Zhang 
1017d501dc42Sstefano_zampini   /* need to use HeaderReplace because HeaderMerge messes up with the communicator */
10184222ddf1SHong Zhang   product    = C->product;  /* save it from MatHeaderReplace() */
10194222ddf1SHong Zhang   C->product = NULL;
1020d501dc42Sstefano_zampini   ierr = MatHeaderReplace(C,&D);CHKERRQ(ierr);
10214222ddf1SHong Zhang   C->product = product;
1022d501dc42Sstefano_zampini   C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE;
10234222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
1024d501dc42Sstefano_zampini   PetscFunctionReturn(0);
1025d501dc42Sstefano_zampini }
1026d501dc42Sstefano_zampini 
10273dad0653Sstefano_zampini PETSC_INTERN PetscErrorCode MatTransposeMatMatMultNumeric_AIJ_AIJ_AIJ_wHYPRE(Mat A,Mat B,Mat C,Mat D)
102820e1dc0dSstefano_zampini {
102920e1dc0dSstefano_zampini   Mat                E;
103020e1dc0dSstefano_zampini   hypre_ParCSRMatrix *hA,*hB,*hC,*hABC;
103120e1dc0dSstefano_zampini   PetscErrorCode     ierr;
103220e1dc0dSstefano_zampini 
103320e1dc0dSstefano_zampini   PetscFunctionBegin;
103420e1dc0dSstefano_zampini   ierr = MatAIJGetParCSR_Private(A,&hA);CHKERRQ(ierr);
103520e1dc0dSstefano_zampini   ierr = MatAIJGetParCSR_Private(B,&hB);CHKERRQ(ierr);
103620e1dc0dSstefano_zampini   ierr = MatAIJGetParCSR_Private(C,&hC);CHKERRQ(ierr);
103720e1dc0dSstefano_zampini   ierr = MatHYPRE_ParCSR_RAP(hA,hB,hC,&hABC);CHKERRQ(ierr);
103820e1dc0dSstefano_zampini   ierr = MatCreateFromParCSR(hABC,MATAIJ,PETSC_OWN_POINTER,&E);CHKERRQ(ierr);
103920e1dc0dSstefano_zampini   ierr = MatHeaderMerge(D,&E);CHKERRQ(ierr);
104020e1dc0dSstefano_zampini   ierr = MatAIJRestoreParCSR_Private(A,&hA);CHKERRQ(ierr);
104120e1dc0dSstefano_zampini   ierr = MatAIJRestoreParCSR_Private(B,&hB);CHKERRQ(ierr);
104220e1dc0dSstefano_zampini   ierr = MatAIJRestoreParCSR_Private(C,&hC);CHKERRQ(ierr);
104320e1dc0dSstefano_zampini   PetscFunctionReturn(0);
104420e1dc0dSstefano_zampini }
104520e1dc0dSstefano_zampini 
10464222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatTransposeMatMatMultSymbolic_AIJ_AIJ_AIJ_wHYPRE(Mat A,Mat B,Mat C,PetscReal fill,Mat D)
104720e1dc0dSstefano_zampini {
104820e1dc0dSstefano_zampini   PetscErrorCode ierr;
104920e1dc0dSstefano_zampini 
105020e1dc0dSstefano_zampini   PetscFunctionBegin;
10514222ddf1SHong Zhang   ierr = MatSetType(D,MATAIJ);CHKERRQ(ierr);
105220e1dc0dSstefano_zampini   PetscFunctionReturn(0);
105320e1dc0dSstefano_zampini }
105420e1dc0dSstefano_zampini 
10554222ddf1SHong Zhang /* ---------------------------------------------------- */
10564222ddf1SHong Zhang static PetscErrorCode MatProductSymbolic_AB_HYPRE(Mat C)
10574222ddf1SHong Zhang {
10584222ddf1SHong Zhang   PetscFunctionBegin;
10594222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
10604222ddf1SHong Zhang   PetscFunctionReturn(0);
10614222ddf1SHong Zhang }
10624222ddf1SHong Zhang 
10634222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_HYPRE_AB(Mat C)
10644222ddf1SHong Zhang {
10654222ddf1SHong Zhang   PetscErrorCode ierr;
10664222ddf1SHong Zhang   Mat_Product    *product = C->product;
10674222ddf1SHong Zhang   PetscBool      Ahypre;
10684222ddf1SHong Zhang 
10694222ddf1SHong Zhang   PetscFunctionBegin;
10704222ddf1SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)product->A,MATHYPRE,&Ahypre);CHKERRQ(ierr);
10714222ddf1SHong Zhang   if (Ahypre) { /* A is a Hypre matrix */
10724222ddf1SHong Zhang     ierr = MatSetType(C,MATHYPRE);CHKERRQ(ierr);
10734222ddf1SHong Zhang     C->ops->productsymbolic = MatProductSymbolic_AB_HYPRE;
10744222ddf1SHong Zhang     C->ops->matmultnumeric  = MatMatMultNumeric_HYPRE_HYPRE;
10754222ddf1SHong Zhang     PetscFunctionReturn(0);
10766718818eSStefano Zampini   }
10774222ddf1SHong Zhang   PetscFunctionReturn(0);
10784222ddf1SHong Zhang }
10794222ddf1SHong Zhang 
10804222ddf1SHong Zhang static PetscErrorCode MatProductSymbolic_PtAP_HYPRE(Mat C)
10814222ddf1SHong Zhang {
10824222ddf1SHong Zhang   PetscFunctionBegin;
10834222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
10844222ddf1SHong Zhang   PetscFunctionReturn(0);
10854222ddf1SHong Zhang }
10864222ddf1SHong Zhang 
10874222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_HYPRE_PtAP(Mat C)
10884222ddf1SHong Zhang {
10894222ddf1SHong Zhang   PetscErrorCode ierr;
10904222ddf1SHong Zhang   Mat_Product    *product = C->product;
10914222ddf1SHong Zhang   PetscBool      flg;
10924222ddf1SHong Zhang   PetscInt       type = 0;
10934222ddf1SHong Zhang   const char     *outTypes[4] = {"aij","seqaij","mpiaij","hypre"};
10944222ddf1SHong Zhang   PetscInt       ntype = 4;
10954222ddf1SHong Zhang   Mat            A = product->A;
10964222ddf1SHong Zhang   PetscBool      Ahypre;
10974222ddf1SHong Zhang 
10984222ddf1SHong Zhang   PetscFunctionBegin;
10994222ddf1SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)A,MATHYPRE,&Ahypre);CHKERRQ(ierr);
11004222ddf1SHong Zhang   if (Ahypre) { /* A is a Hypre matrix */
11014222ddf1SHong Zhang     ierr = MatSetType(C,MATHYPRE);CHKERRQ(ierr);
11024222ddf1SHong Zhang     C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE;
11034222ddf1SHong Zhang     C->ops->ptapnumeric     = MatPtAPNumeric_HYPRE_HYPRE;
11044222ddf1SHong Zhang     PetscFunctionReturn(0);
11054222ddf1SHong Zhang   }
11064222ddf1SHong Zhang 
11074222ddf1SHong Zhang   /* A is AIJ, P is Hypre, C = PtAP can be either AIJ or Hypre format */
11084222ddf1SHong Zhang   /* Get runtime option */
11094222ddf1SHong Zhang   if (product->api_user) {
11104222ddf1SHong Zhang     ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)C),((PetscObject)C)->prefix,"MatPtAP_HYPRE","Mat");CHKERRQ(ierr);
11114222ddf1SHong Zhang     ierr = PetscOptionsEList("-matptap_hypre_outtype","MatPtAP outtype","MatPtAP outtype",outTypes,ntype,outTypes[type],&type,&flg);CHKERRQ(ierr);
11124222ddf1SHong Zhang     ierr = PetscOptionsEnd();CHKERRQ(ierr);
11134222ddf1SHong Zhang   } else {
11144222ddf1SHong Zhang     ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)C),((PetscObject)C)->prefix,"MatProduct_PtAP_HYPRE","Mat");CHKERRQ(ierr);
11154222ddf1SHong Zhang     ierr = PetscOptionsEList("-matproduct_ptap_hypre_outtype","MatProduct_PtAP outtype","MatProduct_PtAP",outTypes,ntype,outTypes[type],&type,&flg);CHKERRQ(ierr);
11164222ddf1SHong Zhang     ierr = PetscOptionsEnd();CHKERRQ(ierr);
11174222ddf1SHong Zhang   }
11184222ddf1SHong Zhang 
11194222ddf1SHong Zhang   if (type == 0 || type == 1 || type == 2) {
11204222ddf1SHong Zhang     ierr = MatSetType(C,MATAIJ);CHKERRQ(ierr);
11214222ddf1SHong Zhang   } else if (type == 3) {
11224222ddf1SHong Zhang     ierr = MatSetType(C,MATHYPRE);CHKERRQ(ierr);
11234222ddf1SHong Zhang   } else SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_SUP,"MatPtAP outtype is not supported");
11244222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE;
11254222ddf1SHong Zhang   C->ops->ptapnumeric     = MatPtAPNumeric_AIJ_HYPRE;
11264222ddf1SHong Zhang   PetscFunctionReturn(0);
11274222ddf1SHong Zhang }
11284222ddf1SHong Zhang 
11294222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_HYPRE(Mat C)
11304222ddf1SHong Zhang {
11314222ddf1SHong Zhang   PetscErrorCode ierr;
11324222ddf1SHong Zhang   Mat_Product    *product = C->product;
11334222ddf1SHong Zhang 
11344222ddf1SHong Zhang   PetscFunctionBegin;
11354222ddf1SHong Zhang   switch (product->type) {
11364222ddf1SHong Zhang   case MATPRODUCT_AB:
11374222ddf1SHong Zhang     ierr = MatProductSetFromOptions_HYPRE_AB(C);CHKERRQ(ierr);
11384222ddf1SHong Zhang     break;
11394222ddf1SHong Zhang   case MATPRODUCT_PtAP:
11404222ddf1SHong Zhang     ierr = MatProductSetFromOptions_HYPRE_PtAP(C);CHKERRQ(ierr);
11414222ddf1SHong Zhang     break;
11426718818eSStefano Zampini   default:
11436718818eSStefano Zampini     break;
11444222ddf1SHong Zhang   }
11454222ddf1SHong Zhang   PetscFunctionReturn(0);
11464222ddf1SHong Zhang }
11474222ddf1SHong Zhang 
11484222ddf1SHong Zhang /* -------------------------------------------------------- */
11494222ddf1SHong Zhang 
1150ea9daf28SStefano Zampini static PetscErrorCode MatMultTranspose_HYPRE(Mat A, Vec x, Vec y)
115163c07aadSStefano Zampini {
115263c07aadSStefano Zampini   PetscErrorCode ierr;
115363c07aadSStefano Zampini 
115463c07aadSStefano Zampini   PetscFunctionBegin;
1155414bd5c3SStefano Zampini   ierr = MatHYPRE_MultKernel_Private(A,1.0,x,0.0,y,PETSC_TRUE);CHKERRQ(ierr);
115663c07aadSStefano Zampini   PetscFunctionReturn(0);
115763c07aadSStefano Zampini }
115863c07aadSStefano Zampini 
1159ea9daf28SStefano Zampini static PetscErrorCode MatMult_HYPRE(Mat A, Vec x, Vec y)
116063c07aadSStefano Zampini {
116163c07aadSStefano Zampini   PetscErrorCode ierr;
116263c07aadSStefano Zampini 
116363c07aadSStefano Zampini   PetscFunctionBegin;
1164414bd5c3SStefano Zampini   ierr = MatHYPRE_MultKernel_Private(A,1.0,x,0.0,y,PETSC_FALSE);CHKERRQ(ierr);
116563c07aadSStefano Zampini   PetscFunctionReturn(0);
116663c07aadSStefano Zampini }
116763c07aadSStefano Zampini 
1168414bd5c3SStefano Zampini static PetscErrorCode MatMultAdd_HYPRE(Mat A, Vec x, Vec y, Vec z)
1169414bd5c3SStefano Zampini {
1170414bd5c3SStefano Zampini   PetscErrorCode ierr;
1171414bd5c3SStefano Zampini 
1172414bd5c3SStefano Zampini   PetscFunctionBegin;
1173414bd5c3SStefano Zampini   if (y != z) {
1174414bd5c3SStefano Zampini     ierr = VecCopy(y,z);CHKERRQ(ierr);
1175414bd5c3SStefano Zampini   }
1176414bd5c3SStefano Zampini   ierr = MatHYPRE_MultKernel_Private(A,1.0,x,1.0,z,PETSC_FALSE);CHKERRQ(ierr);
1177414bd5c3SStefano Zampini   PetscFunctionReturn(0);
1178414bd5c3SStefano Zampini }
1179414bd5c3SStefano Zampini 
1180414bd5c3SStefano Zampini static PetscErrorCode MatMultTransposeAdd_HYPRE(Mat A, Vec x, Vec y, Vec z)
1181414bd5c3SStefano Zampini {
1182414bd5c3SStefano Zampini   PetscErrorCode ierr;
1183414bd5c3SStefano Zampini 
1184414bd5c3SStefano Zampini   PetscFunctionBegin;
1185414bd5c3SStefano Zampini   if (y != z) {
1186414bd5c3SStefano Zampini     ierr = VecCopy(y,z);CHKERRQ(ierr);
1187414bd5c3SStefano Zampini   }
1188414bd5c3SStefano Zampini   ierr = MatHYPRE_MultKernel_Private(A,1.0,x,1.0,z,PETSC_TRUE);CHKERRQ(ierr);
1189414bd5c3SStefano Zampini   PetscFunctionReturn(0);
1190414bd5c3SStefano Zampini }
1191414bd5c3SStefano Zampini 
1192414bd5c3SStefano Zampini /* y = a * A * x + b * y or y = a * A^t * x + b * y depending on trans */
119339accc25SStefano Zampini static PetscErrorCode MatHYPRE_MultKernel_Private(Mat A, HYPRE_Complex a, Vec x, HYPRE_Complex b, Vec y, PetscBool trans)
119463c07aadSStefano Zampini {
119563c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE*)A->data;
119663c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
119763c07aadSStefano Zampini   hypre_ParVector    *hx,*hy;
119863c07aadSStefano Zampini   PetscErrorCode     ierr;
119963c07aadSStefano Zampini 
120063c07aadSStefano Zampini   PetscFunctionBegin;
120163c07aadSStefano Zampini   if (trans) {
1202*6ea7df73SStefano Zampini     ierr = VecHYPRE_IJVectorPushVecRead(hA->b,x);CHKERRQ(ierr);
1203*6ea7df73SStefano Zampini     if (b != 0.0) { ierr = VecHYPRE_IJVectorPushVec(hA->x,y);CHKERRQ(ierr); }
1204*6ea7df73SStefano Zampini     else { ierr = VecHYPRE_IJVectorPushVecWrite(hA->x,y);CHKERRQ(ierr); }
1205*6ea7df73SStefano Zampini     PetscStackCallStandard(HYPRE_IJVectorGetObject,(hA->b->ij,(void**)&hx));
1206*6ea7df73SStefano Zampini     PetscStackCallStandard(HYPRE_IJVectorGetObject,(hA->x->ij,(void**)&hy));
120763c07aadSStefano Zampini   } else {
1208*6ea7df73SStefano Zampini     ierr = VecHYPRE_IJVectorPushVecRead(hA->x,x);CHKERRQ(ierr);
1209*6ea7df73SStefano Zampini     if (b != 0.0) { ierr = VecHYPRE_IJVectorPushVec(hA->b,y);CHKERRQ(ierr); }
1210*6ea7df73SStefano Zampini     else { ierr = VecHYPRE_IJVectorPushVecWrite(hA->b,y);CHKERRQ(ierr); }
1211*6ea7df73SStefano Zampini     PetscStackCallStandard(HYPRE_IJVectorGetObject,(hA->x->ij,(void**)&hx));
1212*6ea7df73SStefano Zampini     PetscStackCallStandard(HYPRE_IJVectorGetObject,(hA->b->ij,(void**)&hy));
121363c07aadSStefano Zampini   }
1214*6ea7df73SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&parcsr));
1215*6ea7df73SStefano Zampini   if (trans) {
1216*6ea7df73SStefano Zampini     PetscStackCallStandard(hypre_ParCSRMatrixMatvecT,(a,parcsr,hx,b,hy));
1217*6ea7df73SStefano Zampini   } else {
1218*6ea7df73SStefano Zampini     PetscStackCallStandard(hypre_ParCSRMatrixMatvec,(a,parcsr,hx,b,hy));
1219*6ea7df73SStefano Zampini   }
1220*6ea7df73SStefano Zampini   ierr = VecHYPRE_IJVectorPopVec(hA->x);CHKERRQ(ierr);
1221*6ea7df73SStefano Zampini   ierr = VecHYPRE_IJVectorPopVec(hA->b);CHKERRQ(ierr);
122263c07aadSStefano Zampini   PetscFunctionReturn(0);
122363c07aadSStefano Zampini }
122463c07aadSStefano Zampini 
1225ea9daf28SStefano Zampini static PetscErrorCode MatDestroy_HYPRE(Mat A)
122663c07aadSStefano Zampini {
122763c07aadSStefano Zampini   Mat_HYPRE      *hA = (Mat_HYPRE*)A->data;
122863c07aadSStefano Zampini   PetscErrorCode ierr;
122963c07aadSStefano Zampini 
123063c07aadSStefano Zampini   PetscFunctionBegin;
1231*6ea7df73SStefano Zampini   ierr = VecHYPRE_IJVectorDestroy(&hA->x);CHKERRQ(ierr);
1232*6ea7df73SStefano Zampini   ierr = VecHYPRE_IJVectorDestroy(&hA->b);CHKERRQ(ierr);
1233978814f1SStefano Zampini   if (hA->ij) {
1234978814f1SStefano Zampini     if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL;
1235978814f1SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixDestroy,(hA->ij));
1236978814f1SStefano Zampini   }
1237ffc4695bSBarry Smith   if (hA->comm) {ierr = MPI_Comm_free(&hA->comm);CHKERRMPI(ierr);}
1238c69f721fSFande Kong 
1239c69f721fSFande Kong   ierr = MatStashDestroy_Private(&A->stash);CHKERRQ(ierr);
1240c69f721fSFande Kong 
1241c69f721fSFande Kong   ierr = PetscFree(hA->array);CHKERRQ(ierr);
1242c69f721fSFande Kong 
124363c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_hypre_aij_C",NULL);CHKERRQ(ierr);
12442df22349SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_hypre_is_C",NULL);CHKERRQ(ierr);
12454222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_hypre_C",NULL);CHKERRQ(ierr);
12464222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_mpiaij_hypre_C",NULL);CHKERRQ(ierr);
1247d975228cSstefano_zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatHYPRESetPreallocation_C",NULL);CHKERRQ(ierr);
1248dd9c0a25Sstefano_zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatHYPREGetParCSR_C",NULL);CHKERRQ(ierr);
124963c07aadSStefano Zampini   ierr = PetscFree(A->data);CHKERRQ(ierr);
125063c07aadSStefano Zampini   PetscFunctionReturn(0);
125163c07aadSStefano Zampini }
125263c07aadSStefano Zampini 
1253ea9daf28SStefano Zampini static PetscErrorCode MatSetUp_HYPRE(Mat A)
125463c07aadSStefano Zampini {
12554ec6421dSstefano_zampini   PetscErrorCode ierr;
12564ec6421dSstefano_zampini 
12574ec6421dSstefano_zampini   PetscFunctionBegin;
12584ec6421dSstefano_zampini   ierr = MatHYPRESetPreallocation(A,PETSC_DEFAULT,NULL,PETSC_DEFAULT,NULL);CHKERRQ(ierr);
12594ec6421dSstefano_zampini   PetscFunctionReturn(0);
12604ec6421dSstefano_zampini }
12614ec6421dSstefano_zampini 
1262*6ea7df73SStefano Zampini //TODO FIX hypre_CSRMatrixMatvecOutOfPlace
1263*6ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
1264*6ea7df73SStefano Zampini static PetscErrorCode MatBindToCPU_HYPRE(Mat A, PetscBool bind)
1265*6ea7df73SStefano Zampini {
1266*6ea7df73SStefano Zampini   Mat_HYPRE            *hA = (Mat_HYPRE*)A->data;
1267*6ea7df73SStefano Zampini   HYPRE_MemoryLocation hmem = bind ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE;
1268*6ea7df73SStefano Zampini   PetscErrorCode       ierr;
1269*6ea7df73SStefano Zampini 
1270*6ea7df73SStefano Zampini   PetscFunctionBegin;
1271*6ea7df73SStefano Zampini   A->boundtocpu = bind;
1272*6ea7df73SStefano Zampini   if (hypre_IJMatrixAssembleFlag(hA->ij) && hmem != hypre_IJMatrixMemoryLocation(hA->ij)) {
1273*6ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
1274*6ea7df73SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&parcsr));
1275*6ea7df73SStefano Zampini     PetscStackCallStandard(hypre_ParCSRMatrixMigrate,(parcsr, hmem));
1276*6ea7df73SStefano Zampini   }
1277*6ea7df73SStefano Zampini   if (hA->x) { ierr  = VecHYPRE_IJBindToCPU(hA->x,bind);CHKERRQ(ierr); }
1278*6ea7df73SStefano Zampini   if (hA->b) { ierr  = VecHYPRE_IJBindToCPU(hA->b,bind);CHKERRQ(ierr); }
1279*6ea7df73SStefano Zampini   PetscFunctionReturn(0);
1280*6ea7df73SStefano Zampini }
1281*6ea7df73SStefano Zampini #endif
1282*6ea7df73SStefano Zampini 
12834ec6421dSstefano_zampini static PetscErrorCode MatAssemblyEnd_HYPRE(Mat A, MatAssemblyType mode)
12844ec6421dSstefano_zampini {
128563c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE*)A->data;
1286c69f721fSFande Kong   PetscMPIInt        n;
1287c69f721fSFande Kong   PetscInt           i,j,rstart,ncols,flg;
1288c69f721fSFande Kong   PetscInt           *row,*col;
1289c69f721fSFande Kong   PetscScalar        *val;
129063c07aadSStefano Zampini   PetscErrorCode     ierr;
129163c07aadSStefano Zampini 
129263c07aadSStefano Zampini   PetscFunctionBegin;
12934ec6421dSstefano_zampini   if (mode == MAT_FLUSH_ASSEMBLY) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MAT_FLUSH_ASSEMBLY currently not supported with MATHYPRE");
1294c69f721fSFande Kong 
1295c69f721fSFande Kong   if (!A->nooffprocentries) {
1296c69f721fSFande Kong     while (1) {
1297c69f721fSFande Kong       ierr = MatStashScatterGetMesg_Private(&A->stash,&n,&row,&col,&val,&flg);CHKERRQ(ierr);
1298c69f721fSFande Kong       if (!flg) break;
1299c69f721fSFande Kong 
1300c69f721fSFande Kong       for (i=0; i<n;) {
1301c69f721fSFande Kong         /* Now identify the consecutive vals belonging to the same row */
1302c69f721fSFande Kong         for (j=i,rstart=row[j]; j<n; j++) {
1303c69f721fSFande Kong           if (row[j] != rstart) break;
1304c69f721fSFande Kong         }
1305c69f721fSFande Kong         if (j < n) ncols = j-i;
1306c69f721fSFande Kong         else       ncols = n-i;
1307c69f721fSFande Kong         /* Now assemble all these values with a single function call */
1308c69f721fSFande Kong         ierr = MatSetValues_HYPRE(A,1,row+i,ncols,col+i,val+i,A->insertmode);CHKERRQ(ierr);
1309c69f721fSFande Kong 
1310c69f721fSFande Kong         i = j;
1311c69f721fSFande Kong       }
1312c69f721fSFande Kong     }
1313c69f721fSFande Kong     ierr = MatStashScatterEnd_Private(&A->stash);CHKERRQ(ierr);
1314c69f721fSFande Kong   }
1315c69f721fSFande Kong 
13164ec6421dSstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixAssemble,(hA->ij));
1317336664bdSPierre Jolivet   /* The assembly routine destroys the aux_matrix, we recreate it here by calling HYPRE_IJMatrixInitialize */
1318336664bdSPierre 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 */
1319336664bdSPierre Jolivet   if (!hA->sorted_full) {
1320af1cf968SStefano Zampini     hypre_AuxParCSRMatrix *aux_matrix;
1321af1cf968SStefano Zampini 
1322af1cf968SStefano Zampini     /* call destroy just to make sure we do not leak anything */
1323af1cf968SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(hA->ij);
1324af1cf968SStefano Zampini     PetscStackCallStandard(hypre_AuxParCSRMatrixDestroy,(aux_matrix));
1325af1cf968SStefano Zampini     hypre_IJMatrixTranslator(hA->ij) = NULL;
1326af1cf968SStefano Zampini 
1327af1cf968SStefano Zampini     /* Initialize with assembled flag -> it only recreates the aux_par_matrix */
1328af1cf968SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixInitialize,(hA->ij));
1329af1cf968SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(hA->ij);
1330*6ea7df73SStefano Zampini     if (aux_matrix) {
1331af1cf968SStefano Zampini       hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1; /* see comment in MatHYPRESetPreallocation_HYPRE */
133222235d61SPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LT(2,19,0)
1333af1cf968SStefano Zampini       PetscStackCallStandard(hypre_AuxParCSRMatrixInitialize,(aux_matrix));
133422235d61SPierre Jolivet #else
133522235d61SPierre Jolivet       PetscStackCallStandard(hypre_AuxParCSRMatrixInitialize_v2,(aux_matrix,HYPRE_MEMORY_HOST));
133622235d61SPierre Jolivet #endif
1337af1cf968SStefano Zampini     }
1338*6ea7df73SStefano Zampini   }
1339*6ea7df73SStefano Zampini   {
1340*6ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
1341*6ea7df73SStefano Zampini 
1342*6ea7df73SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&parcsr));
1343*6ea7df73SStefano Zampini     if (!hypre_ParCSRMatrixCommPkg(parcsr)) PetscStackCallStandard(hypre_MatvecCommPkgCreate,(parcsr));
1344*6ea7df73SStefano Zampini   }
1345*6ea7df73SStefano Zampini   if (!hA->x) { ierr = VecHYPRE_IJVectorCreate(A->cmap,&hA->x);CHKERRQ(ierr); }
1346*6ea7df73SStefano Zampini   if (!hA->b) { ierr = VecHYPRE_IJVectorCreate(A->rmap,&hA->b);CHKERRQ(ierr); }
1347*6ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
1348*6ea7df73SStefano Zampini   ierr = MatBindToCPU_HYPRE(A,A->boundtocpu);CHKERRQ(ierr);
1349*6ea7df73SStefano Zampini #endif
135063c07aadSStefano Zampini   PetscFunctionReturn(0);
135163c07aadSStefano Zampini }
135263c07aadSStefano Zampini 
1353c69f721fSFande Kong static PetscErrorCode MatGetArray_HYPRE(Mat A, PetscInt size, void **array)
1354c69f721fSFande Kong {
1355c69f721fSFande Kong   Mat_HYPRE          *hA = (Mat_HYPRE*)A->data;
1356c69f721fSFande Kong   PetscErrorCode     ierr;
1357c69f721fSFande Kong 
1358c69f721fSFande Kong   PetscFunctionBegin;
1359c69f721fSFande Kong   if (!hA->available) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Temporary space is in use");
1360c69f721fSFande Kong 
136139accc25SStefano Zampini   if (hA->size >= size) {
136239accc25SStefano Zampini     *array = hA->array;
136339accc25SStefano Zampini   } else {
1364c69f721fSFande Kong     ierr = PetscFree(hA->array);CHKERRQ(ierr);
1365c69f721fSFande Kong     hA->size = size;
1366c69f721fSFande Kong     ierr = PetscMalloc(hA->size,&hA->array);CHKERRQ(ierr);
1367c69f721fSFande Kong     *array = hA->array;
1368c69f721fSFande Kong   }
1369c69f721fSFande Kong 
1370c69f721fSFande Kong   hA->available = PETSC_FALSE;
1371c69f721fSFande Kong   PetscFunctionReturn(0);
1372c69f721fSFande Kong }
1373c69f721fSFande Kong 
1374708542d2SFande Kong static PetscErrorCode MatRestoreArray_HYPRE(Mat A, void **array)
1375c69f721fSFande Kong {
1376c69f721fSFande Kong   Mat_HYPRE          *hA = (Mat_HYPRE*)A->data;
1377c69f721fSFande Kong 
1378c69f721fSFande Kong   PetscFunctionBegin;
1379c69f721fSFande Kong   *array = NULL;
1380c69f721fSFande Kong   hA->available = PETSC_TRUE;
1381c69f721fSFande Kong   PetscFunctionReturn(0);
1382c69f721fSFande Kong }
1383c69f721fSFande Kong 
1384*6ea7df73SStefano Zampini static PetscErrorCode MatSetValues_HYPRE(Mat A, PetscInt nr, const PetscInt rows[], PetscInt nc, const PetscInt cols[], const PetscScalar v[], InsertMode ins)
1385d975228cSstefano_zampini {
1386d975228cSstefano_zampini   Mat_HYPRE      *hA = (Mat_HYPRE*)A->data;
1387d975228cSstefano_zampini   PetscScalar    *vals = (PetscScalar *)v;
138839accc25SStefano Zampini   HYPRE_Complex  *sscr;
1389c69f721fSFande Kong   PetscInt       *cscr[2];
1390c69f721fSFande Kong   PetscInt       i,nzc;
139108defe43SFande Kong   void           *array = NULL;
1392d975228cSstefano_zampini   PetscErrorCode ierr;
1393d975228cSstefano_zampini 
1394d975228cSstefano_zampini   PetscFunctionBegin;
139539accc25SStefano Zampini   ierr = MatGetArray_HYPRE(A,sizeof(PetscInt)*(2*nc)+sizeof(HYPRE_Complex)*nc*nr,&array);CHKERRQ(ierr);
1396c69f721fSFande Kong   cscr[0] = (PetscInt*)array;
1397c69f721fSFande Kong   cscr[1] = ((PetscInt*)array)+nc;
139839accc25SStefano Zampini   sscr = (HYPRE_Complex*)(((PetscInt*)array)+nc*2);
1399d975228cSstefano_zampini   for (i=0,nzc=0;i<nc;i++) {
1400d975228cSstefano_zampini     if (cols[i] >= 0) {
1401d975228cSstefano_zampini       cscr[0][nzc  ] = cols[i];
1402d975228cSstefano_zampini       cscr[1][nzc++] = i;
1403d975228cSstefano_zampini     }
1404d975228cSstefano_zampini   }
1405c69f721fSFande Kong   if (!nzc) {
1406708542d2SFande Kong     ierr = MatRestoreArray_HYPRE(A,&array);CHKERRQ(ierr);
1407c69f721fSFande Kong     PetscFunctionReturn(0);
1408c69f721fSFande Kong   }
1409d975228cSstefano_zampini 
1410*6ea7df73SStefano Zampini #if 0 //defined(PETSC_HAVE_HYPRE_DEVICE)
1411*6ea7df73SStefano Zampini   if (HYPRE_MEMORY_HOST != hypre_IJMatrixMemoryLocation(hA->ij)) {
1412*6ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
1413*6ea7df73SStefano Zampini 
1414*6ea7df73SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&parcsr));
1415*6ea7df73SStefano Zampini     PetscStackCallStandard(hypre_ParCSRMatrixMigrate,(parcsr, HYPRE_MEMORY_HOST));
1416*6ea7df73SStefano Zampini   }
1417*6ea7df73SStefano Zampini #endif
1418*6ea7df73SStefano Zampini 
1419d975228cSstefano_zampini   if (ins == ADD_VALUES) {
1420d975228cSstefano_zampini     for (i=0;i<nr;i++) {
1421*6ea7df73SStefano Zampini       if (rows[i] >= 0) {
1422d975228cSstefano_zampini         PetscInt  j;
14232cf14000SStefano Zampini         HYPRE_Int hnc = (HYPRE_Int)nzc;
14242cf14000SStefano Zampini 
14252cf14000SStefano Zampini         if ((PetscInt)hnc != nzc) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Hypre overflow! number of columns %D for row %D",nzc,rows[i]);
14261e1ea65dSPierre Jolivet         for (j=0;j<nzc;j++) { ierr = PetscHYPREScalarCast(vals[cscr[1][j]],&sscr[j]);CHKERRQ(ierr); }
14272cf14000SStefano Zampini         PetscStackCallStandard(HYPRE_IJMatrixAddToValues,(hA->ij,1,&hnc,(HYPRE_BigInt*)(rows+i),(HYPRE_BigInt*)cscr[0],sscr));
1428d975228cSstefano_zampini       }
1429d975228cSstefano_zampini       vals += nc;
1430d975228cSstefano_zampini     }
1431d975228cSstefano_zampini   } else { /* INSERT_VALUES */
1432d975228cSstefano_zampini     PetscInt rst,ren;
1433c69f721fSFande Kong 
1434c6698e78SStefano Zampini     ierr = MatGetOwnershipRange(A,&rst,&ren);CHKERRQ(ierr);
1435d975228cSstefano_zampini     for (i=0;i<nr;i++) {
1436*6ea7df73SStefano Zampini       if (rows[i] >= 0) {
1437d975228cSstefano_zampini         PetscInt  j;
14382cf14000SStefano Zampini         HYPRE_Int hnc = (HYPRE_Int)nzc;
14392cf14000SStefano Zampini 
14402cf14000SStefano Zampini         if ((PetscInt)hnc != nzc) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Hypre overflow! number of columns %D for row %D",nzc,rows[i]);
14411e1ea65dSPierre Jolivet         for (j=0;j<nzc;j++) { ierr = PetscHYPREScalarCast(vals[cscr[1][j]],&sscr[j]);CHKERRQ(ierr); }
1442c69f721fSFande Kong         /* nonlocal values */
144339accc25SStefano Zampini         if (rows[i] < rst || rows[i] >= ren) { ierr = MatStashValuesRow_Private(&A->stash,rows[i],nzc,cscr[0],(PetscScalar*)sscr,PETSC_FALSE);CHKERRQ(ierr); }
1444c69f721fSFande Kong         /* local values */
14452cf14000SStefano Zampini         else PetscStackCallStandard(HYPRE_IJMatrixSetValues,(hA->ij,1,&hnc,(HYPRE_BigInt*)(rows+i),(HYPRE_BigInt*)cscr[0],sscr));
1446d975228cSstefano_zampini       }
1447d975228cSstefano_zampini       vals += nc;
1448d975228cSstefano_zampini     }
1449d975228cSstefano_zampini   }
1450c69f721fSFande Kong 
1451708542d2SFande Kong   ierr = MatRestoreArray_HYPRE(A,&array);CHKERRQ(ierr);
1452d975228cSstefano_zampini   PetscFunctionReturn(0);
1453d975228cSstefano_zampini }
1454d975228cSstefano_zampini 
1455d975228cSstefano_zampini static PetscErrorCode MatHYPRESetPreallocation_HYPRE(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[])
1456d975228cSstefano_zampini {
1457d975228cSstefano_zampini   Mat_HYPRE      *hA = (Mat_HYPRE*)A->data;
14587d968826Sstefano_zampini   HYPRE_Int      *hdnnz,*honnz;
145906a29025Sstefano_zampini   PetscInt       i,rs,re,cs,ce,bs;
1460d975228cSstefano_zampini   PetscMPIInt    size;
1461d975228cSstefano_zampini   PetscErrorCode ierr;
1462d975228cSstefano_zampini 
1463d975228cSstefano_zampini   PetscFunctionBegin;
146406a29025Sstefano_zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
1465d975228cSstefano_zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1466d975228cSstefano_zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1467d975228cSstefano_zampini   rs   = A->rmap->rstart;
1468d975228cSstefano_zampini   re   = A->rmap->rend;
1469d975228cSstefano_zampini   cs   = A->cmap->rstart;
1470d975228cSstefano_zampini   ce   = A->cmap->rend;
1471d975228cSstefano_zampini   if (!hA->ij) {
1472d975228cSstefano_zampini     PetscStackCallStandard(HYPRE_IJMatrixCreate,(hA->comm,rs,re-1,cs,ce-1,&hA->ij));
1473d975228cSstefano_zampini     PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(hA->ij,HYPRE_PARCSR));
1474d975228cSstefano_zampini   } else {
14752cf14000SStefano Zampini     HYPRE_BigInt hrs,hre,hcs,hce;
1476d975228cSstefano_zampini     PetscStackCallStandard(HYPRE_IJMatrixGetLocalRange,(hA->ij,&hrs,&hre,&hcs,&hce));
14772cf14000SStefano 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);
14782cf14000SStefano 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);
1479d975228cSstefano_zampini   }
148006a29025Sstefano_zampini   if (dnz == PETSC_DEFAULT || dnz == PETSC_DECIDE) dnz = 10*bs;
148106a29025Sstefano_zampini   if (onz == PETSC_DEFAULT || onz == PETSC_DECIDE) onz = 10*bs;
148206a29025Sstefano_zampini 
1483d975228cSstefano_zampini   if (!dnnz) {
1484d975228cSstefano_zampini     ierr = PetscMalloc1(A->rmap->n,&hdnnz);CHKERRQ(ierr);
1485d975228cSstefano_zampini     for (i=0;i<A->rmap->n;i++) hdnnz[i] = dnz;
1486d975228cSstefano_zampini   } else {
14877d968826Sstefano_zampini     hdnnz = (HYPRE_Int*)dnnz;
1488d975228cSstefano_zampini   }
1489ffc4695bSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRMPI(ierr);
1490d975228cSstefano_zampini   if (size > 1) {
1491ddbeb582SStefano Zampini     hypre_AuxParCSRMatrix *aux_matrix;
1492d975228cSstefano_zampini     if (!onnz) {
1493d975228cSstefano_zampini       ierr = PetscMalloc1(A->rmap->n,&honnz);CHKERRQ(ierr);
1494d975228cSstefano_zampini       for (i=0;i<A->rmap->n;i++) honnz[i] = onz;
149522235d61SPierre Jolivet     } else honnz = (HYPRE_Int*)onnz;
1496ddbeb582SStefano Zampini     /* SetDiagOffdSizes sets hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0, since it seems
1497ddbeb582SStefano Zampini        they assume the user will input the entire row values, properly sorted
1498336664bdSPierre Jolivet        In PETSc, we don't make such an assumption and set this flag to 1,
1499336664bdSPierre Jolivet        unless the option MAT_SORTED_FULL is set to true.
1500ddbeb582SStefano Zampini        Also, to avoid possible memory leaks, we destroy and recreate the translator
1501ddbeb582SStefano Zampini        This has to be done here, as HYPRE_IJMatrixInitialize will properly initialize
1502ddbeb582SStefano Zampini        the IJ matrix for us */
1503ddbeb582SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(hA->ij);
1504ddbeb582SStefano Zampini     hypre_AuxParCSRMatrixDestroy(aux_matrix);
1505ddbeb582SStefano Zampini     hypre_IJMatrixTranslator(hA->ij) = NULL;
1506d975228cSstefano_zampini     PetscStackCallStandard(HYPRE_IJMatrixSetDiagOffdSizes,(hA->ij,hdnnz,honnz));
1507ddbeb582SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(hA->ij);
1508336664bdSPierre Jolivet     hypre_AuxParCSRMatrixNeedAux(aux_matrix) = !hA->sorted_full;
1509d975228cSstefano_zampini   } else {
1510d975228cSstefano_zampini     honnz = NULL;
1511d975228cSstefano_zampini     PetscStackCallStandard(HYPRE_IJMatrixSetRowSizes,(hA->ij,hdnnz));
1512d975228cSstefano_zampini   }
1513ddbeb582SStefano Zampini 
1514af1cf968SStefano Zampini   /* reset assembled flag and call the initialize method */
1515af1cf968SStefano Zampini   hypre_IJMatrixAssembleFlag(hA->ij) = 0;
1516*6ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2,19,0)
1517ddbeb582SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixInitialize,(hA->ij));
1518*6ea7df73SStefano Zampini #else
1519*6ea7df73SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixInitialize_v2,(hA->ij,HYPRE_MEMORY_HOST));
1520*6ea7df73SStefano Zampini #endif
1521d975228cSstefano_zampini   if (!dnnz) {
1522d975228cSstefano_zampini     ierr = PetscFree(hdnnz);CHKERRQ(ierr);
1523d975228cSstefano_zampini   }
1524d975228cSstefano_zampini   if (!onnz && honnz) {
1525d975228cSstefano_zampini     ierr = PetscFree(honnz);CHKERRQ(ierr);
1526d975228cSstefano_zampini   }
1527af1cf968SStefano Zampini   /* Match AIJ logic */
152806a29025Sstefano_zampini   A->preallocated = PETSC_TRUE;
1529af1cf968SStefano Zampini   A->assembled    = PETSC_FALSE;
1530d975228cSstefano_zampini   PetscFunctionReturn(0);
1531d975228cSstefano_zampini }
1532d975228cSstefano_zampini 
1533d975228cSstefano_zampini /*@C
1534d975228cSstefano_zampini    MatHYPRESetPreallocation - Preallocates memory for a sparse parallel matrix in HYPRE IJ format
1535d975228cSstefano_zampini 
1536d975228cSstefano_zampini    Collective on Mat
1537d975228cSstefano_zampini 
1538d975228cSstefano_zampini    Input Parameters:
1539d975228cSstefano_zampini +  A - the matrix
1540d975228cSstefano_zampini .  dnz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1541d975228cSstefano_zampini           (same value is used for all local rows)
1542d975228cSstefano_zampini .  dnnz - array containing the number of nonzeros in the various rows of the
1543d975228cSstefano_zampini           DIAGONAL portion of the local submatrix (possibly different for each row)
1544d975228cSstefano_zampini           or NULL (PETSC_NULL_INTEGER in Fortran), if d_nz is used to specify the nonzero structure.
1545d975228cSstefano_zampini           The size of this array is equal to the number of local rows, i.e 'm'.
1546d975228cSstefano_zampini           For matrices that will be factored, you must leave room for (and set)
1547d975228cSstefano_zampini           the diagonal entry even if it is zero.
1548d975228cSstefano_zampini .  onz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1549d975228cSstefano_zampini           submatrix (same value is used for all local rows).
1550d975228cSstefano_zampini -  onnz - array containing the number of nonzeros in the various rows of the
1551d975228cSstefano_zampini           OFF-DIAGONAL portion of the local submatrix (possibly different for
1552d975228cSstefano_zampini           each row) or NULL (PETSC_NULL_INTEGER in Fortran), if o_nz is used to specify the nonzero
1553d975228cSstefano_zampini           structure. The size of this array is equal to the number
1554d975228cSstefano_zampini           of local rows, i.e 'm'.
1555d975228cSstefano_zampini 
155695452b02SPatrick Sanan    Notes:
155795452b02SPatrick Sanan     If the *nnz parameter is given then the *nz parameter is ignored; for sequential matrices, onz and onnz are ignored.
1558d975228cSstefano_zampini 
1559d975228cSstefano_zampini    Level: intermediate
1560d975228cSstefano_zampini 
1561af1cf968SStefano Zampini .seealso: MatCreate(), MatMPIAIJSetPreallocation(), MATHYPRE
1562d975228cSstefano_zampini @*/
1563d975228cSstefano_zampini PetscErrorCode MatHYPRESetPreallocation(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[])
1564d975228cSstefano_zampini {
1565d975228cSstefano_zampini   PetscErrorCode ierr;
1566d975228cSstefano_zampini 
1567d975228cSstefano_zampini   PetscFunctionBegin;
1568d975228cSstefano_zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
1569d975228cSstefano_zampini   PetscValidType(A,1);
1570d975228cSstefano_zampini   ierr = PetscTryMethod(A,"MatHYPRESetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(A,dnz,dnnz,onz,onnz));CHKERRQ(ierr);
1571d975228cSstefano_zampini   PetscFunctionReturn(0);
1572d975228cSstefano_zampini }
1573d975228cSstefano_zampini 
1574225daaf8SStefano Zampini /*
1575225daaf8SStefano Zampini    MatCreateFromParCSR - Creates a matrix from a hypre_ParCSRMatrix
1576225daaf8SStefano Zampini 
1577225daaf8SStefano Zampini    Collective
1578225daaf8SStefano Zampini 
1579225daaf8SStefano Zampini    Input Parameters:
158045b8d346SStefano Zampini +  parcsr   - the pointer to the hypre_ParCSRMatrix
1581bb4689ddSStefano Zampini .  mtype    - matrix type to be created. Currently MATAIJ, MATIS and MATHYPRE are supported.
1582225daaf8SStefano Zampini -  copymode - PETSc copying options
1583225daaf8SStefano Zampini 
1584225daaf8SStefano Zampini    Output Parameter:
1585225daaf8SStefano Zampini .  A  - the matrix
1586225daaf8SStefano Zampini 
1587225daaf8SStefano Zampini    Level: intermediate
1588225daaf8SStefano Zampini 
1589225daaf8SStefano Zampini .seealso: MatHYPRE, PetscCopyMode
1590225daaf8SStefano Zampini */
159145b8d346SStefano Zampini PETSC_EXTERN PetscErrorCode MatCreateFromParCSR(hypre_ParCSRMatrix *parcsr, MatType mtype, PetscCopyMode copymode, Mat* A)
1592978814f1SStefano Zampini {
1593225daaf8SStefano Zampini   Mat            T;
1594978814f1SStefano Zampini   Mat_HYPRE      *hA;
1595978814f1SStefano Zampini   MPI_Comm       comm;
1596978814f1SStefano Zampini   PetscInt       rstart,rend,cstart,cend,M,N;
1597d248a85cSRichard Tran Mills   PetscBool      isseqaij,isseqaijmkl,ismpiaij,isaij,ishyp,isis;
1598978814f1SStefano Zampini   PetscErrorCode ierr;
1599978814f1SStefano Zampini 
1600978814f1SStefano Zampini   PetscFunctionBegin;
1601978814f1SStefano Zampini   comm  = hypre_ParCSRMatrixComm(parcsr);
1602225daaf8SStefano Zampini   ierr  = PetscStrcmp(mtype,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
1603d248a85cSRichard Tran Mills   ierr  = PetscStrcmp(mtype,MATSEQAIJMKL,&isseqaijmkl);CHKERRQ(ierr);
1604225daaf8SStefano Zampini   ierr  = PetscStrcmp(mtype,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
1605225daaf8SStefano Zampini   ierr  = PetscStrcmp(mtype,MATAIJ,&isaij);CHKERRQ(ierr);
1606225daaf8SStefano Zampini   ierr  = PetscStrcmp(mtype,MATHYPRE,&ishyp);CHKERRQ(ierr);
16078cfe8d00SStefano Zampini   ierr  = PetscStrcmp(mtype,MATIS,&isis);CHKERRQ(ierr);
1608d248a85cSRichard Tran Mills   isaij = (PetscBool)(isseqaij || isseqaijmkl || ismpiaij || isaij);
1609*6ea7df73SStefano Zampini   /* TODO */
1610d248a85cSRichard 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);
1611978814f1SStefano Zampini   /* access ParCSRMatrix */
1612978814f1SStefano Zampini   rstart = hypre_ParCSRMatrixFirstRowIndex(parcsr);
1613978814f1SStefano Zampini   rend   = hypre_ParCSRMatrixLastRowIndex(parcsr);
1614978814f1SStefano Zampini   cstart = hypre_ParCSRMatrixFirstColDiag(parcsr);
1615978814f1SStefano Zampini   cend   = hypre_ParCSRMatrixLastColDiag(parcsr);
1616978814f1SStefano Zampini   M      = hypre_ParCSRMatrixGlobalNumRows(parcsr);
1617978814f1SStefano Zampini   N      = hypre_ParCSRMatrixGlobalNumCols(parcsr);
1618978814f1SStefano Zampini 
1619fa92c42cSstefano_zampini   /* fix for empty local rows/columns */
1620fa92c42cSstefano_zampini   if (rend < rstart) rend = rstart;
1621fa92c42cSstefano_zampini   if (cend < cstart) cend = cstart;
1622fa92c42cSstefano_zampini 
1623e6471dc9SStefano Zampini   /* PETSc convention */
1624e6471dc9SStefano Zampini   rend++;
1625e6471dc9SStefano Zampini   cend++;
1626e6471dc9SStefano Zampini   rend = PetscMin(rend,M);
1627e6471dc9SStefano Zampini   cend = PetscMin(cend,N);
1628e6471dc9SStefano Zampini 
1629978814f1SStefano Zampini   /* create PETSc matrix with MatHYPRE */
1630225daaf8SStefano Zampini   ierr = MatCreate(comm,&T);CHKERRQ(ierr);
1631e6471dc9SStefano Zampini   ierr = MatSetSizes(T,rend-rstart,cend-cstart,M,N);CHKERRQ(ierr);
1632225daaf8SStefano Zampini   ierr = MatSetType(T,MATHYPRE);CHKERRQ(ierr);
1633225daaf8SStefano Zampini   hA   = (Mat_HYPRE*)(T->data);
1634978814f1SStefano Zampini 
1635978814f1SStefano Zampini   /* create HYPRE_IJMatrix */
1636978814f1SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixCreate,(hA->comm,rstart,rend-1,cstart,cend-1,&hA->ij));
163745b8d346SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(hA->ij,HYPRE_PARCSR));
163845b8d346SStefano Zampini 
1639*6ea7df73SStefano Zampini // TODO DEV
164045b8d346SStefano Zampini   /* create new ParCSR object if needed */
164145b8d346SStefano Zampini   if (ishyp && copymode == PETSC_COPY_VALUES) {
164245b8d346SStefano Zampini     hypre_ParCSRMatrix *new_parcsr;
1643*6ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2,18,0)
164445b8d346SStefano Zampini     hypre_CSRMatrix    *hdiag,*hoffd,*ndiag,*noffd;
164545b8d346SStefano Zampini 
16460e6427aaSSatish Balay     new_parcsr = hypre_ParCSRMatrixClone(parcsr,0);
164745b8d346SStefano Zampini     hdiag      = hypre_ParCSRMatrixDiag(parcsr);
164845b8d346SStefano Zampini     hoffd      = hypre_ParCSRMatrixOffd(parcsr);
164945b8d346SStefano Zampini     ndiag      = hypre_ParCSRMatrixDiag(new_parcsr);
165045b8d346SStefano Zampini     noffd      = hypre_ParCSRMatrixOffd(new_parcsr);
1651580bdb30SBarry Smith     ierr       = PetscArraycpy(hypre_CSRMatrixData(ndiag),hypre_CSRMatrixData(hdiag),hypre_CSRMatrixNumNonzeros(hdiag));CHKERRQ(ierr);
1652580bdb30SBarry Smith     ierr       = PetscArraycpy(hypre_CSRMatrixData(noffd),hypre_CSRMatrixData(hoffd),hypre_CSRMatrixNumNonzeros(hoffd));CHKERRQ(ierr);
1653*6ea7df73SStefano Zampini #else
1654*6ea7df73SStefano Zampini     new_parcsr = hypre_ParCSRMatrixClone(parcsr,1);
1655*6ea7df73SStefano Zampini #endif
165645b8d346SStefano Zampini     parcsr     = new_parcsr;
165745b8d346SStefano Zampini     copymode   = PETSC_OWN_POINTER;
165845b8d346SStefano Zampini   }
1659978814f1SStefano Zampini 
1660978814f1SStefano Zampini   /* set ParCSR object */
1661978814f1SStefano Zampini   hypre_IJMatrixObject(hA->ij) = parcsr;
16624ec6421dSstefano_zampini   T->preallocated = PETSC_TRUE;
1663978814f1SStefano Zampini 
1664978814f1SStefano Zampini   /* set assembled flag */
1665978814f1SStefano Zampini   hypre_IJMatrixAssembleFlag(hA->ij) = 1;
1666*6ea7df73SStefano Zampini #if 0
1667978814f1SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixInitialize,(hA->ij));
1668*6ea7df73SStefano Zampini #endif
1669225daaf8SStefano Zampini   if (ishyp) {
16706d2a658fSstefano_zampini     PetscMPIInt myid = 0;
16716d2a658fSstefano_zampini 
16726d2a658fSstefano_zampini     /* make sure we always have row_starts and col_starts available */
16736d2a658fSstefano_zampini     if (HYPRE_AssumedPartitionCheck()) {
1674ffc4695bSBarry Smith       ierr = MPI_Comm_rank(comm,&myid);CHKERRMPI(ierr);
16756d2a658fSstefano_zampini     }
1676a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
16776d2a658fSstefano_zampini     if (!hypre_ParCSRMatrixOwnsColStarts(parcsr)) {
16786d2a658fSstefano_zampini       PetscLayout map;
16796d2a658fSstefano_zampini 
16806d2a658fSstefano_zampini       ierr = MatGetLayouts(T,NULL,&map);CHKERRQ(ierr);
16816d2a658fSstefano_zampini       ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
16822cf14000SStefano Zampini       hypre_ParCSRMatrixColStarts(parcsr) = (HYPRE_BigInt*)(map->range + myid);
16836d2a658fSstefano_zampini     }
16846d2a658fSstefano_zampini     if (!hypre_ParCSRMatrixOwnsRowStarts(parcsr)) {
16856d2a658fSstefano_zampini       PetscLayout map;
16866d2a658fSstefano_zampini 
16876d2a658fSstefano_zampini       ierr = MatGetLayouts(T,&map,NULL);CHKERRQ(ierr);
16886d2a658fSstefano_zampini       ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
16892cf14000SStefano Zampini       hypre_ParCSRMatrixRowStarts(parcsr) = (HYPRE_BigInt*)(map->range + myid);
16906d2a658fSstefano_zampini     }
1691a1d2239cSSatish Balay #endif
1692978814f1SStefano Zampini     /* prevent from freeing the pointer */
1693978814f1SStefano Zampini     if (copymode == PETSC_USE_POINTER) hA->inner_free = PETSC_FALSE;
1694225daaf8SStefano Zampini     *A   = T;
1695*6ea7df73SStefano Zampini     ierr = MatSetOption(*A,MAT_SORTED_FULL,PETSC_TRUE);CHKERRQ(ierr);
1696978814f1SStefano Zampini     ierr = MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1697978814f1SStefano Zampini     ierr = MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1698bb4689ddSStefano Zampini   } else if (isaij) {
1699bb4689ddSStefano Zampini     if (copymode != PETSC_OWN_POINTER) {
1700225daaf8SStefano Zampini       /* prevent from freeing the pointer */
1701225daaf8SStefano Zampini       hA->inner_free = PETSC_FALSE;
1702225daaf8SStefano Zampini       ierr = MatConvert_HYPRE_AIJ(T,MATAIJ,MAT_INITIAL_MATRIX,A);CHKERRQ(ierr);
1703225daaf8SStefano Zampini       ierr = MatDestroy(&T);CHKERRQ(ierr);
1704225daaf8SStefano Zampini     } else { /* AIJ return type with PETSC_OWN_POINTER */
1705225daaf8SStefano Zampini       ierr = MatConvert_HYPRE_AIJ(T,MATAIJ,MAT_INPLACE_MATRIX,&T);CHKERRQ(ierr);
1706225daaf8SStefano Zampini       *A   = T;
1707225daaf8SStefano Zampini     }
1708bb4689ddSStefano Zampini   } else if (isis) {
17098cfe8d00SStefano Zampini     ierr = MatConvert_HYPRE_IS(T,MATIS,MAT_INITIAL_MATRIX,A);CHKERRQ(ierr);
17108cfe8d00SStefano Zampini     if (copymode != PETSC_OWN_POINTER) hA->inner_free = PETSC_FALSE;
1711bb4689ddSStefano Zampini     ierr = MatDestroy(&T);CHKERRQ(ierr);
1712bb4689ddSStefano Zampini   }
1713978814f1SStefano Zampini   PetscFunctionReturn(0);
1714978814f1SStefano Zampini }
1715978814f1SStefano Zampini 
171668ec7858SStefano Zampini static PetscErrorCode MatHYPREGetParCSR_HYPRE(Mat A, hypre_ParCSRMatrix **parcsr)
1717dd9c0a25Sstefano_zampini {
1718dd9c0a25Sstefano_zampini   Mat_HYPRE *hA = (Mat_HYPRE*)A->data;
1719dd9c0a25Sstefano_zampini   HYPRE_Int type;
1720dd9c0a25Sstefano_zampini 
1721dd9c0a25Sstefano_zampini   PetscFunctionBegin;
1722dd9c0a25Sstefano_zampini   if (!hA->ij) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"HYPRE_IJMatrix not present");
1723dd9c0a25Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type));
1724dd9c0a25Sstefano_zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"HYPRE_IJMatrix is not of type HYPRE_PARCSR");
1725dd9c0a25Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)parcsr));
1726dd9c0a25Sstefano_zampini   PetscFunctionReturn(0);
1727dd9c0a25Sstefano_zampini }
1728dd9c0a25Sstefano_zampini 
1729dd9c0a25Sstefano_zampini /*
1730dd9c0a25Sstefano_zampini    MatHYPREGetParCSR - Gets the pointer to the ParCSR matrix
1731dd9c0a25Sstefano_zampini 
1732dd9c0a25Sstefano_zampini    Not collective
1733dd9c0a25Sstefano_zampini 
1734dd9c0a25Sstefano_zampini    Input Parameters:
1735dd9c0a25Sstefano_zampini +  A  - the MATHYPRE object
1736dd9c0a25Sstefano_zampini 
1737dd9c0a25Sstefano_zampini    Output Parameter:
1738dd9c0a25Sstefano_zampini .  parcsr  - the pointer to the hypre_ParCSRMatrix
1739dd9c0a25Sstefano_zampini 
1740dd9c0a25Sstefano_zampini    Level: intermediate
1741dd9c0a25Sstefano_zampini 
1742dd9c0a25Sstefano_zampini .seealso: MatHYPRE, PetscCopyMode
1743dd9c0a25Sstefano_zampini */
1744dd9c0a25Sstefano_zampini PetscErrorCode MatHYPREGetParCSR(Mat A, hypre_ParCSRMatrix **parcsr)
1745dd9c0a25Sstefano_zampini {
1746dd9c0a25Sstefano_zampini   PetscErrorCode ierr;
1747dd9c0a25Sstefano_zampini 
1748dd9c0a25Sstefano_zampini   PetscFunctionBegin;
1749dd9c0a25Sstefano_zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
1750dd9c0a25Sstefano_zampini   PetscValidType(A,1);
1751dd9c0a25Sstefano_zampini   ierr = PetscUseMethod(A,"MatHYPREGetParCSR_C",(Mat,hypre_ParCSRMatrix**),(A,parcsr));CHKERRQ(ierr);
1752dd9c0a25Sstefano_zampini   PetscFunctionReturn(0);
1753dd9c0a25Sstefano_zampini }
1754dd9c0a25Sstefano_zampini 
175568ec7858SStefano Zampini static PetscErrorCode MatMissingDiagonal_HYPRE(Mat A, PetscBool *missing, PetscInt *dd)
175668ec7858SStefano Zampini {
175768ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
175868ec7858SStefano Zampini   hypre_CSRMatrix    *ha;
175968ec7858SStefano Zampini   PetscInt           rst;
176068ec7858SStefano Zampini   PetscErrorCode     ierr;
176168ec7858SStefano Zampini 
176268ec7858SStefano Zampini   PetscFunctionBegin;
176368ec7858SStefano Zampini   if (A->rmap->n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented with non-square diagonal blocks");
176468ec7858SStefano Zampini   ierr = MatGetOwnershipRange(A,&rst,NULL);CHKERRQ(ierr);
176568ec7858SStefano Zampini   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
176668ec7858SStefano Zampini   if (missing) *missing = PETSC_FALSE;
176768ec7858SStefano Zampini   if (dd) *dd = -1;
176868ec7858SStefano Zampini   ha = hypre_ParCSRMatrixDiag(parcsr);
176968ec7858SStefano Zampini   if (ha) {
177068299464SStefano Zampini     PetscInt  size,i;
177168299464SStefano Zampini     HYPRE_Int *ii,*jj;
177268ec7858SStefano Zampini 
177368ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
177468ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
177568ec7858SStefano Zampini     jj   = hypre_CSRMatrixJ(ha);
177668ec7858SStefano Zampini     for (i = 0; i < size; i++) {
177768ec7858SStefano Zampini       PetscInt  j;
177868ec7858SStefano Zampini       PetscBool found = PETSC_FALSE;
177968ec7858SStefano Zampini 
178068ec7858SStefano Zampini       for (j = ii[i]; j < ii[i+1] && !found; j++)
178168ec7858SStefano Zampini         found = (jj[j] == i) ? PETSC_TRUE : PETSC_FALSE;
178268ec7858SStefano Zampini 
178368ec7858SStefano Zampini       if (!found) {
178468ec7858SStefano Zampini         PetscInfo1(A,"Matrix is missing local diagonal entry %D\n",i);
178568ec7858SStefano Zampini         if (missing) *missing = PETSC_TRUE;
178668ec7858SStefano Zampini         if (dd) *dd = i+rst;
178768ec7858SStefano Zampini         PetscFunctionReturn(0);
178868ec7858SStefano Zampini       }
178968ec7858SStefano Zampini     }
179068ec7858SStefano Zampini     if (!size) {
179168ec7858SStefano Zampini       PetscInfo(A,"Matrix has no diagonal entries therefore is missing diagonal\n");
179268ec7858SStefano Zampini       if (missing) *missing = PETSC_TRUE;
179368ec7858SStefano Zampini       if (dd) *dd = rst;
179468ec7858SStefano Zampini     }
179568ec7858SStefano Zampini   } else {
179668ec7858SStefano Zampini     PetscInfo(A,"Matrix has no diagonal entries therefore is missing diagonal\n");
179768ec7858SStefano Zampini     if (missing) *missing = PETSC_TRUE;
179868ec7858SStefano Zampini     if (dd) *dd = rst;
179968ec7858SStefano Zampini   }
180068ec7858SStefano Zampini   PetscFunctionReturn(0);
180168ec7858SStefano Zampini }
180268ec7858SStefano Zampini 
180368ec7858SStefano Zampini static PetscErrorCode MatScale_HYPRE(Mat A, PetscScalar s)
180468ec7858SStefano Zampini {
180568ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
1806*6ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2,19,0)
180768ec7858SStefano Zampini   hypre_CSRMatrix    *ha;
1808*6ea7df73SStefano Zampini #endif
180968ec7858SStefano Zampini   PetscErrorCode     ierr;
181039accc25SStefano Zampini   HYPRE_Complex      hs;
181168ec7858SStefano Zampini 
181268ec7858SStefano Zampini   PetscFunctionBegin;
181339accc25SStefano Zampini   ierr = PetscHYPREScalarCast(s,&hs);CHKERRQ(ierr);
181468ec7858SStefano Zampini   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
1815*6ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2,19,0)
1816*6ea7df73SStefano Zampini   PetscStackCallStandard(hypre_ParCSRMatrixScale,(parcsr,hs));
1817*6ea7df73SStefano Zampini #else  /* diagonal part */
181868ec7858SStefano Zampini   ha = hypre_ParCSRMatrixDiag(parcsr);
181968ec7858SStefano Zampini   if (ha) {
182068299464SStefano Zampini     PetscInt      size,i;
182168299464SStefano Zampini     HYPRE_Int     *ii;
182239accc25SStefano Zampini     HYPRE_Complex *a;
182368ec7858SStefano Zampini 
182468ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
182568ec7858SStefano Zampini     a    = hypre_CSRMatrixData(ha);
182668ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
182739accc25SStefano Zampini     for (i = 0; i < ii[size]; i++) a[i] *= hs;
182868ec7858SStefano Zampini   }
182968ec7858SStefano Zampini   /* offdiagonal part */
183068ec7858SStefano Zampini   ha = hypre_ParCSRMatrixOffd(parcsr);
183168ec7858SStefano Zampini   if (ha) {
183268299464SStefano Zampini     PetscInt      size,i;
183368299464SStefano Zampini     HYPRE_Int     *ii;
183439accc25SStefano Zampini     HYPRE_Complex *a;
183568ec7858SStefano Zampini 
183668ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
183768ec7858SStefano Zampini     a    = hypre_CSRMatrixData(ha);
183868ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
183939accc25SStefano Zampini     for (i = 0; i < ii[size]; i++) a[i] *= hs;
184068ec7858SStefano Zampini   }
1841*6ea7df73SStefano Zampini #endif
184268ec7858SStefano Zampini   PetscFunctionReturn(0);
184368ec7858SStefano Zampini }
184468ec7858SStefano Zampini 
184568ec7858SStefano Zampini static PetscErrorCode MatZeroRowsColumns_HYPRE(Mat A, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
184668ec7858SStefano Zampini {
184768ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
184868299464SStefano Zampini   HYPRE_Int          *lrows;
184968299464SStefano Zampini   PetscInt           rst,ren,i;
185068ec7858SStefano Zampini   PetscErrorCode     ierr;
185168ec7858SStefano Zampini 
185268ec7858SStefano Zampini   PetscFunctionBegin;
185368ec7858SStefano Zampini   if (x || b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"To be implemented");
185468ec7858SStefano Zampini   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
185568ec7858SStefano Zampini   ierr = PetscMalloc1(numRows,&lrows);CHKERRQ(ierr);
185668ec7858SStefano Zampini   ierr = MatGetOwnershipRange(A,&rst,&ren);CHKERRQ(ierr);
185768ec7858SStefano Zampini   for (i=0;i<numRows;i++) {
185868ec7858SStefano Zampini     if (rows[i] < rst || rows[i] >= ren)
185968ec7858SStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Non-local rows not yet supported");
186068ec7858SStefano Zampini     lrows[i] = rows[i] - rst;
186168ec7858SStefano Zampini   }
186268ec7858SStefano Zampini   PetscStackCallStandard(hypre_ParCSRMatrixEliminateRowsCols,(parcsr,numRows,lrows));
186368ec7858SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
186468ec7858SStefano Zampini   PetscFunctionReturn(0);
186568ec7858SStefano Zampini }
186668ec7858SStefano Zampini 
1867c69f721fSFande Kong static PetscErrorCode MatZeroEntries_HYPRE_CSRMatrix(hypre_CSRMatrix *ha)
1868c69f721fSFande Kong {
1869c69f721fSFande Kong   PetscErrorCode      ierr;
1870c69f721fSFande Kong 
1871c69f721fSFande Kong   PetscFunctionBegin;
1872c69f721fSFande Kong   if (ha) {
1873c69f721fSFande Kong     HYPRE_Int     *ii, size;
1874c69f721fSFande Kong     HYPRE_Complex *a;
1875c69f721fSFande Kong 
1876c69f721fSFande Kong     size = hypre_CSRMatrixNumRows(ha);
1877c69f721fSFande Kong     a    = hypre_CSRMatrixData(ha);
1878c69f721fSFande Kong     ii   = hypre_CSRMatrixI(ha);
1879c69f721fSFande Kong 
1880580bdb30SBarry Smith     if (a) {ierr = PetscArrayzero(a,ii[size]);CHKERRQ(ierr);}
1881c69f721fSFande Kong   }
1882c69f721fSFande Kong   PetscFunctionReturn(0);
1883c69f721fSFande Kong }
1884c69f721fSFande Kong 
1885c69f721fSFande Kong PetscErrorCode MatZeroEntries_HYPRE(Mat A)
1886c69f721fSFande Kong {
1887*6ea7df73SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE*)A->data;
1888*6ea7df73SStefano Zampini 
1889*6ea7df73SStefano Zampini   PetscFunctionBegin;
1890*6ea7df73SStefano Zampini   if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(hA->ij)) {
1891*6ea7df73SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixSetConstantValues,(hA->ij,0.0));
1892*6ea7df73SStefano Zampini   } else {
1893c69f721fSFande Kong     hypre_ParCSRMatrix *parcsr;
1894c69f721fSFande Kong     PetscErrorCode     ierr;
1895c69f721fSFande Kong 
1896c69f721fSFande Kong     ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
1897c69f721fSFande Kong     ierr = MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr));CHKERRQ(ierr);
1898c69f721fSFande Kong     ierr = MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr));CHKERRQ(ierr);
1899*6ea7df73SStefano Zampini   }
1900c69f721fSFande Kong   PetscFunctionReturn(0);
1901c69f721fSFande Kong }
1902c69f721fSFande Kong 
190339accc25SStefano Zampini static PetscErrorCode MatZeroRows_HYPRE_CSRMatrix(hypre_CSRMatrix *hA,PetscInt N,const PetscInt rows[],HYPRE_Complex diag)
1904c69f721fSFande Kong {
190539accc25SStefano Zampini   PetscInt        ii;
190639accc25SStefano Zampini   HYPRE_Int       *i, *j;
190739accc25SStefano Zampini   HYPRE_Complex   *a;
1908c69f721fSFande Kong 
1909c69f721fSFande Kong   PetscFunctionBegin;
1910c69f721fSFande Kong   if (!hA) PetscFunctionReturn(0);
1911c69f721fSFande Kong 
191239accc25SStefano Zampini   i = hypre_CSRMatrixI(hA);
191339accc25SStefano Zampini   j = hypre_CSRMatrixJ(hA);
1914c69f721fSFande Kong   a = hypre_CSRMatrixData(hA);
1915c69f721fSFande Kong 
1916c69f721fSFande Kong   for (ii = 0; ii < N; ii++) {
191739accc25SStefano Zampini     HYPRE_Int jj, ibeg, iend, irow;
191839accc25SStefano Zampini 
1919c69f721fSFande Kong     irow = rows[ii];
1920c69f721fSFande Kong     ibeg = i[irow];
1921c69f721fSFande Kong     iend = i[irow+1];
1922c69f721fSFande Kong     for (jj = ibeg; jj < iend; jj++)
1923c69f721fSFande Kong       if (j[jj] == irow) a[jj] = diag;
1924c69f721fSFande Kong       else a[jj] = 0.0;
1925c69f721fSFande Kong    }
1926c69f721fSFande Kong    PetscFunctionReturn(0);
1927c69f721fSFande Kong }
1928c69f721fSFande Kong 
1929ddbeb582SStefano Zampini static PetscErrorCode MatZeroRows_HYPRE(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1930c69f721fSFande Kong {
1931c69f721fSFande Kong   hypre_ParCSRMatrix  *parcsr;
1932c69f721fSFande Kong   PetscInt            *lrows,len;
193339accc25SStefano Zampini   HYPRE_Complex       hdiag;
1934c69f721fSFande Kong   PetscErrorCode      ierr;
1935c69f721fSFande Kong 
1936c69f721fSFande Kong   PetscFunctionBegin;
1937c6698e78SStefano Zampini   if (x || b) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Does not support to modify the solution and the right hand size");
193839accc25SStefano Zampini   ierr = PetscHYPREScalarCast(diag,&hdiag);CHKERRQ(ierr);
1939c69f721fSFande Kong   /* retrieve the internal matrix */
1940c69f721fSFande Kong   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
1941c69f721fSFande Kong   /* get locally owned rows */
1942c69f721fSFande Kong   ierr = MatZeroRowsMapLocal_Private(A,N,rows,&len,&lrows);CHKERRQ(ierr);
1943c69f721fSFande Kong   /* zero diagonal part */
194439accc25SStefano Zampini   ierr = MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr),len,lrows,hdiag);CHKERRQ(ierr);
1945c69f721fSFande Kong   /* zero off-diagonal part */
1946c69f721fSFande Kong   ierr = MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr),len,lrows,0.0);CHKERRQ(ierr);
1947c69f721fSFande Kong 
1948c69f721fSFande Kong   ierr = PetscFree(lrows);CHKERRQ(ierr);
1949c69f721fSFande Kong   PetscFunctionReturn(0);
1950c69f721fSFande Kong }
1951c69f721fSFande Kong 
1952ddbeb582SStefano Zampini static PetscErrorCode MatAssemblyBegin_HYPRE(Mat mat,MatAssemblyType mode)
1953c69f721fSFande Kong {
1954c69f721fSFande Kong   PetscErrorCode ierr;
1955c69f721fSFande Kong 
1956c69f721fSFande Kong   PetscFunctionBegin;
1957c69f721fSFande Kong   if (mat->nooffprocentries) PetscFunctionReturn(0);
1958c69f721fSFande Kong 
1959c69f721fSFande Kong   ierr = MatStashScatterBegin_Private(mat,&mat->stash,mat->rmap->range);CHKERRQ(ierr);
1960c69f721fSFande Kong   PetscFunctionReturn(0);
1961c69f721fSFande Kong }
1962c69f721fSFande Kong 
1963ddbeb582SStefano Zampini static PetscErrorCode MatGetRow_HYPRE(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
1964c69f721fSFande Kong {
1965c69f721fSFande Kong   hypre_ParCSRMatrix  *parcsr;
19662cf14000SStefano Zampini   HYPRE_Int           hnz;
1967c69f721fSFande Kong   PetscErrorCode      ierr;
1968c69f721fSFande Kong 
1969c69f721fSFande Kong   PetscFunctionBegin;
1970c69f721fSFande Kong   /* retrieve the internal matrix */
1971c69f721fSFande Kong   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
1972c69f721fSFande Kong   /* call HYPRE API */
197339accc25SStefano Zampini   PetscStackCallStandard(HYPRE_ParCSRMatrixGetRow,(parcsr,row,&hnz,(HYPRE_BigInt**)idx,(HYPRE_Complex**)v));
19742cf14000SStefano Zampini   if (nz) *nz = (PetscInt)hnz;
1975c69f721fSFande Kong   PetscFunctionReturn(0);
1976c69f721fSFande Kong }
1977c69f721fSFande Kong 
1978ddbeb582SStefano Zampini static PetscErrorCode MatRestoreRow_HYPRE(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
1979c69f721fSFande Kong {
1980c69f721fSFande Kong   hypre_ParCSRMatrix  *parcsr;
19812cf14000SStefano Zampini   HYPRE_Int           hnz;
1982c69f721fSFande Kong   PetscErrorCode      ierr;
1983c69f721fSFande Kong 
1984c69f721fSFande Kong   PetscFunctionBegin;
1985c69f721fSFande Kong   /* retrieve the internal matrix */
1986c69f721fSFande Kong   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
1987c69f721fSFande Kong   /* call HYPRE API */
19882cf14000SStefano Zampini   hnz = nz ? (HYPRE_Int)(*nz) : 0;
198939accc25SStefano Zampini   PetscStackCallStandard(HYPRE_ParCSRMatrixRestoreRow,(parcsr,row,&hnz,(HYPRE_BigInt**)idx,(HYPRE_Complex**)v));
1990c69f721fSFande Kong   PetscFunctionReturn(0);
1991c69f721fSFande Kong }
1992c69f721fSFande Kong 
1993ddbeb582SStefano Zampini static PetscErrorCode MatGetValues_HYPRE(Mat A,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],PetscScalar v[])
1994c69f721fSFande Kong {
199545b8d346SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE*)A->data;
1996c69f721fSFande Kong   PetscInt  i;
19971d4906efSStefano Zampini 
1998c69f721fSFande Kong   PetscFunctionBegin;
1999c69f721fSFande Kong   if (!m || !n) PetscFunctionReturn(0);
2000c69f721fSFande Kong   /* Ignore negative row indices
2001c69f721fSFande Kong    * And negative column indices should be automatically ignored in hypre
2002c69f721fSFande Kong    * */
20032cf14000SStefano Zampini   for (i=0; i<m; i++) {
20042cf14000SStefano Zampini     if (idxm[i] >= 0) {
20052cf14000SStefano Zampini       HYPRE_Int hn = (HYPRE_Int)n;
200639accc25SStefano Zampini       PetscStackCallStandard(HYPRE_IJMatrixGetValues,(hA->ij,1,&hn,(HYPRE_BigInt*)&idxm[i],(HYPRE_BigInt*)idxn,(HYPRE_Complex*)(v + i*n)));
20072cf14000SStefano Zampini     }
20082cf14000SStefano Zampini   }
2009c69f721fSFande Kong   PetscFunctionReturn(0);
2010c69f721fSFande Kong }
2011c69f721fSFande Kong 
2012ddbeb582SStefano Zampini static PetscErrorCode MatSetOption_HYPRE(Mat A,MatOption op,PetscBool flg)
2013ddbeb582SStefano Zampini {
2014ddbeb582SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE*)A->data;
2015ddbeb582SStefano Zampini 
2016ddbeb582SStefano Zampini   PetscFunctionBegin;
2017c6698e78SStefano Zampini   switch (op) {
2018ddbeb582SStefano Zampini   case MAT_NO_OFF_PROC_ENTRIES:
2019ddbeb582SStefano Zampini     if (flg) {
2020ddbeb582SStefano Zampini       PetscStackCallStandard(HYPRE_IJMatrixSetMaxOffProcElmts,(hA->ij,0));
2021ddbeb582SStefano Zampini     }
2022ddbeb582SStefano Zampini     break;
2023336664bdSPierre Jolivet   case MAT_SORTED_FULL:
2024336664bdSPierre Jolivet     hA->sorted_full = flg;
2025336664bdSPierre Jolivet     break;
2026ddbeb582SStefano Zampini   default:
2027ddbeb582SStefano Zampini     break;
2028ddbeb582SStefano Zampini   }
2029ddbeb582SStefano Zampini   PetscFunctionReturn(0);
2030ddbeb582SStefano Zampini }
2031c69f721fSFande Kong 
203245b8d346SStefano Zampini static PetscErrorCode MatView_HYPRE(Mat A, PetscViewer view)
203345b8d346SStefano Zampini {
203445b8d346SStefano Zampini   PetscErrorCode     ierr;
203545b8d346SStefano Zampini   PetscViewerFormat  format;
203645b8d346SStefano Zampini 
203745b8d346SStefano Zampini   PetscFunctionBegin;
203845b8d346SStefano Zampini   ierr = PetscViewerGetFormat(view,&format);CHKERRQ(ierr);
2039*6ea7df73SStefano Zampini   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(0);
204045b8d346SStefano Zampini   if (format != PETSC_VIEWER_NATIVE) {
2041*6ea7df73SStefano Zampini     Mat                B;
2042*6ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
2043*6ea7df73SStefano Zampini     PetscErrorCode     (*mview)(Mat,PetscViewer) = NULL;
2044*6ea7df73SStefano Zampini 
204545b8d346SStefano Zampini     ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
204645b8d346SStefano Zampini     ierr = MatCreateFromParCSR(parcsr,MATAIJ,PETSC_USE_POINTER,&B);CHKERRQ(ierr);
204745b8d346SStefano Zampini     ierr = MatGetOperation(B,MATOP_VIEW,(void(**)(void))&mview);CHKERRQ(ierr);
20482758c9b9SBarry Smith     if (!mview) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Missing view operation");
204945b8d346SStefano Zampini     ierr = (*mview)(B,view);CHKERRQ(ierr);
205045b8d346SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
205145b8d346SStefano Zampini   } else {
205245b8d346SStefano Zampini     Mat_HYPRE  *hA = (Mat_HYPRE*)A->data;
205345b8d346SStefano Zampini     PetscMPIInt size;
205445b8d346SStefano Zampini     PetscBool   isascii;
205545b8d346SStefano Zampini     const char *filename;
205645b8d346SStefano Zampini 
205745b8d346SStefano Zampini     /* HYPRE uses only text files */
205845b8d346SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)view,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
205945b8d346SStefano Zampini     if (!isascii) SETERRQ1(PetscObjectComm((PetscObject)view),PETSC_ERR_SUP,"PetscViewerType %s: native HYPRE format needs PETSCVIEWERASCII",((PetscObject)view)->type_name);
206045b8d346SStefano Zampini     ierr = PetscViewerFileGetName(view,&filename);CHKERRQ(ierr);
206145b8d346SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixPrint,(hA->ij,filename));
2062ffc4695bSBarry Smith     ierr = MPI_Comm_size(hA->comm,&size);CHKERRMPI(ierr);
206345b8d346SStefano Zampini     if (size > 1) {
206445b8d346SStefano Zampini       ierr = PetscViewerASCIIPrintf(view,"Matrix files: %s.%05d ... %s.%05d\n",filename,0,filename,size-1);CHKERRQ(ierr);
206545b8d346SStefano Zampini     } else {
206645b8d346SStefano Zampini       ierr = PetscViewerASCIIPrintf(view,"Matrix file: %s.%05d\n",filename,0);CHKERRQ(ierr);
206745b8d346SStefano Zampini     }
206845b8d346SStefano Zampini   }
206945b8d346SStefano Zampini   PetscFunctionReturn(0);
207045b8d346SStefano Zampini }
207145b8d346SStefano Zampini 
207245b8d346SStefano Zampini static PetscErrorCode MatDuplicate_HYPRE(Mat A,MatDuplicateOption op, Mat *B)
207345b8d346SStefano Zampini {
207445b8d346SStefano Zampini   hypre_ParCSRMatrix *parcsr;
207545b8d346SStefano Zampini   PetscErrorCode     ierr;
207645b8d346SStefano Zampini   PetscCopyMode      cpmode;
207745b8d346SStefano Zampini 
207845b8d346SStefano Zampini   PetscFunctionBegin;
207945b8d346SStefano Zampini   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
208045b8d346SStefano Zampini   if (op == MAT_DO_NOT_COPY_VALUES || op == MAT_SHARE_NONZERO_PATTERN) {
20810e6427aaSSatish Balay     parcsr = hypre_ParCSRMatrixClone(parcsr,0);
208245b8d346SStefano Zampini     cpmode = PETSC_OWN_POINTER;
208345b8d346SStefano Zampini   } else {
208445b8d346SStefano Zampini     cpmode = PETSC_COPY_VALUES;
208545b8d346SStefano Zampini   }
208645b8d346SStefano Zampini   ierr = MatCreateFromParCSR(parcsr,MATHYPRE,cpmode,B);CHKERRQ(ierr);
208745b8d346SStefano Zampini   PetscFunctionReturn(0);
208845b8d346SStefano Zampini }
208945b8d346SStefano Zampini 
2090465edc17SStefano Zampini static PetscErrorCode MatCopy_HYPRE(Mat A, Mat B, MatStructure str)
2091465edc17SStefano Zampini {
2092465edc17SStefano Zampini   hypre_ParCSRMatrix *acsr,*bcsr;
2093465edc17SStefano Zampini   PetscErrorCode     ierr;
2094465edc17SStefano Zampini 
2095465edc17SStefano Zampini   PetscFunctionBegin;
2096465edc17SStefano Zampini   if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) {
2097465edc17SStefano Zampini     ierr = MatHYPREGetParCSR_HYPRE(A,&acsr);CHKERRQ(ierr);
2098465edc17SStefano Zampini     ierr = MatHYPREGetParCSR_HYPRE(B,&bcsr);CHKERRQ(ierr);
2099465edc17SStefano Zampini     PetscStackCallStandard(hypre_ParCSRMatrixCopy,(acsr,bcsr,1));
21001e1ea65dSPierre Jolivet     ierr = MatSetOption(B,MAT_SORTED_FULL,PETSC_TRUE);CHKERRQ(ierr); /* "perfect" preallocation, so no need for hypre_AuxParCSRMatrixNeedAux */
2101465edc17SStefano Zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2102465edc17SStefano Zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2103465edc17SStefano Zampini   } else {
2104465edc17SStefano Zampini     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
2105465edc17SStefano Zampini   }
2106465edc17SStefano Zampini   PetscFunctionReturn(0);
2107465edc17SStefano Zampini }
2108465edc17SStefano Zampini 
21096305df00SStefano Zampini static PetscErrorCode MatGetDiagonal_HYPRE(Mat A, Vec d)
21106305df00SStefano Zampini {
21116305df00SStefano Zampini   hypre_ParCSRMatrix *parcsr;
21126305df00SStefano Zampini   hypre_CSRMatrix    *dmat;
211339accc25SStefano Zampini   HYPRE_Complex      *a;
211439accc25SStefano Zampini   HYPRE_Complex      *data = NULL;
21152cf14000SStefano Zampini   HYPRE_Int          *diag = NULL;
21162cf14000SStefano Zampini   PetscInt           i;
21176305df00SStefano Zampini   PetscBool          cong;
21186305df00SStefano Zampini   PetscErrorCode     ierr;
21196305df00SStefano Zampini 
21206305df00SStefano Zampini   PetscFunctionBegin;
21216305df00SStefano Zampini   ierr = MatHasCongruentLayouts(A,&cong);CHKERRQ(ierr);
21226305df00SStefano Zampini   if (!cong) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only for square matrices with same local distributions of rows and columns");
212376bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
21246305df00SStefano Zampini     PetscBool miss;
21256305df00SStefano Zampini     ierr = MatMissingDiagonal(A,&miss,NULL);CHKERRQ(ierr);
21266305df00SStefano Zampini     if (miss && A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented when diagonal entries are missing");
21276305df00SStefano Zampini   }
21286305df00SStefano Zampini   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
21296305df00SStefano Zampini   dmat = hypre_ParCSRMatrixDiag(parcsr);
21306305df00SStefano Zampini   if (dmat) {
213139accc25SStefano Zampini     /* this cast fixes the clang error: implicit conversion from 'HYPRE_Complex' (aka '_Complex double') to 'double' is not permitted in C++ */
213239accc25SStefano Zampini     ierr = VecGetArray(d,(PetscScalar**)&a);CHKERRQ(ierr);
21332cf14000SStefano Zampini     diag = hypre_CSRMatrixI(dmat);
213439accc25SStefano Zampini     data = hypre_CSRMatrixData(dmat);
21356305df00SStefano Zampini     for (i=0;i<A->rmap->n;i++) a[i] = data[diag[i]];
213639accc25SStefano Zampini     ierr = VecRestoreArray(d,(PetscScalar**)&a);CHKERRQ(ierr);
21376305df00SStefano Zampini   }
21386305df00SStefano Zampini   PetscFunctionReturn(0);
21396305df00SStefano Zampini }
21406305df00SStefano Zampini 
2141363d496dSStefano Zampini #include <petscblaslapack.h>
2142363d496dSStefano Zampini 
2143363d496dSStefano Zampini static PetscErrorCode MatAXPY_HYPRE(Mat Y,PetscScalar a,Mat X,MatStructure str)
2144363d496dSStefano Zampini {
2145363d496dSStefano Zampini   PetscErrorCode ierr;
2146363d496dSStefano Zampini 
2147363d496dSStefano Zampini   PetscFunctionBegin;
2148*6ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
2149*6ea7df73SStefano Zampini   {
2150*6ea7df73SStefano Zampini     Mat                B;
2151*6ea7df73SStefano Zampini     hypre_ParCSRMatrix *x,*y,*z;
2152*6ea7df73SStefano Zampini 
2153*6ea7df73SStefano Zampini     ierr = MatHYPREGetParCSR(Y,&y);CHKERRQ(ierr);
2154*6ea7df73SStefano Zampini     ierr = MatHYPREGetParCSR(X,&x);CHKERRQ(ierr);
2155*6ea7df73SStefano Zampini     PetscStackCallStandard(hypre_ParCSRMatrixAdd,(1.0,y,1.0,x,&z));
2156*6ea7df73SStefano Zampini     ierr = MatCreateFromParCSR(z,MATHYPRE,PETSC_OWN_POINTER,&B);CHKERRQ(ierr);
2157*6ea7df73SStefano Zampini     ierr = MatHeaderMerge(Y,&B);CHKERRQ(ierr);
2158*6ea7df73SStefano Zampini   }
2159*6ea7df73SStefano Zampini #else
2160363d496dSStefano Zampini   if (str == SAME_NONZERO_PATTERN) {
2161363d496dSStefano Zampini     hypre_ParCSRMatrix *x,*y;
2162363d496dSStefano Zampini     hypre_CSRMatrix    *xloc,*yloc;
2163363d496dSStefano Zampini     PetscInt           xnnz,ynnz;
216439accc25SStefano Zampini     HYPRE_Complex      *xarr,*yarr;
2165363d496dSStefano Zampini     PetscBLASInt       one=1,bnz;
2166363d496dSStefano Zampini 
2167363d496dSStefano Zampini     ierr = MatHYPREGetParCSR(Y,&y);CHKERRQ(ierr);
2168363d496dSStefano Zampini     ierr = MatHYPREGetParCSR(X,&x);CHKERRQ(ierr);
2169363d496dSStefano Zampini 
2170363d496dSStefano Zampini     /* diagonal block */
2171363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixDiag(x);
2172363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixDiag(y);
2173363d496dSStefano Zampini     xnnz = 0;
2174363d496dSStefano Zampini     ynnz = 0;
2175363d496dSStefano Zampini     xarr = NULL;
2176363d496dSStefano Zampini     yarr = NULL;
2177363d496dSStefano Zampini     if (xloc) {
217839accc25SStefano Zampini       xarr = hypre_CSRMatrixData(xloc);
2179363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
2180363d496dSStefano Zampini     }
2181363d496dSStefano Zampini     if (yloc) {
218239accc25SStefano Zampini       yarr = hypre_CSRMatrixData(yloc);
2183363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
2184363d496dSStefano Zampini     }
2185363d496dSStefano Zampini     if (xnnz != ynnz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Different number of nonzeros in diagonal block %D != %D",xnnz,ynnz);
2186363d496dSStefano Zampini     ierr = PetscBLASIntCast(xnnz,&bnz);CHKERRQ(ierr);
218739accc25SStefano Zampini     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&a,(PetscScalar*)xarr,&one,(PetscScalar*)yarr,&one));
2188363d496dSStefano Zampini 
2189363d496dSStefano Zampini     /* off-diagonal block */
2190363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixOffd(x);
2191363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixOffd(y);
2192363d496dSStefano Zampini     xnnz = 0;
2193363d496dSStefano Zampini     ynnz = 0;
2194363d496dSStefano Zampini     xarr = NULL;
2195363d496dSStefano Zampini     yarr = NULL;
2196363d496dSStefano Zampini     if (xloc) {
219739accc25SStefano Zampini       xarr = hypre_CSRMatrixData(xloc);
2198363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
2199363d496dSStefano Zampini     }
2200363d496dSStefano Zampini     if (yloc) {
220139accc25SStefano Zampini       yarr = hypre_CSRMatrixData(yloc);
2202363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
2203363d496dSStefano Zampini     }
2204363d496dSStefano Zampini     if (xnnz != ynnz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Different number of nonzeros in off-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   } else if (str == SUBSET_NONZERO_PATTERN) {
2208363d496dSStefano Zampini     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
2209363d496dSStefano Zampini   } else {
2210363d496dSStefano Zampini     Mat B;
2211363d496dSStefano Zampini 
2212363d496dSStefano Zampini     ierr = MatAXPY_Basic_Preallocate(Y,X,&B);CHKERRQ(ierr);
2213363d496dSStefano Zampini     ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr);
2214363d496dSStefano Zampini     ierr = MatHeaderReplace(Y,&B);CHKERRQ(ierr);
2215363d496dSStefano Zampini   }
2216*6ea7df73SStefano Zampini #endif
2217363d496dSStefano Zampini   PetscFunctionReturn(0);
2218363d496dSStefano Zampini }
2219363d496dSStefano Zampini 
2220a055b5aaSBarry Smith /*MC
2221a055b5aaSBarry Smith    MATHYPRE - MATHYPRE = "hypre" - A matrix type to be used for sequential and parallel sparse matrices
2222a055b5aaSBarry Smith           based on the hypre IJ interface.
2223a055b5aaSBarry Smith 
2224a055b5aaSBarry Smith    Level: intermediate
2225a055b5aaSBarry Smith 
2226a055b5aaSBarry Smith .seealso: MatCreate()
2227a055b5aaSBarry Smith M*/
2228a055b5aaSBarry Smith 
222963c07aadSStefano Zampini PETSC_EXTERN PetscErrorCode MatCreate_HYPRE(Mat B)
223063c07aadSStefano Zampini {
223163c07aadSStefano Zampini   Mat_HYPRE      *hB;
223263c07aadSStefano Zampini   PetscErrorCode ierr;
223363c07aadSStefano Zampini 
223463c07aadSStefano Zampini   PetscFunctionBegin;
223563c07aadSStefano Zampini   ierr = PetscNewLog(B,&hB);CHKERRQ(ierr);
2236*6ea7df73SStefano Zampini 
2237978814f1SStefano Zampini   hB->inner_free  = PETSC_TRUE;
2238c69f721fSFande Kong   hB->available   = PETSC_TRUE;
2239336664bdSPierre Jolivet   hB->sorted_full = PETSC_FALSE; /* no assumption whether column indices are sorted or not */
2240c69f721fSFande Kong   hB->size        = 0;
2241c69f721fSFande Kong   hB->array       = NULL;
2242978814f1SStefano Zampini 
224363c07aadSStefano Zampini   B->data       = (void*)hB;
224463c07aadSStefano Zampini   B->rmap->bs   = 1;
224563c07aadSStefano Zampini   B->assembled  = PETSC_FALSE;
224663c07aadSStefano Zampini 
2247de393100SStefano Zampini   ierr = PetscMemzero(B->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
224863c07aadSStefano Zampini   B->ops->mult                  = MatMult_HYPRE;
224963c07aadSStefano Zampini   B->ops->multtranspose         = MatMultTranspose_HYPRE;
2250414bd5c3SStefano Zampini   B->ops->multadd               = MatMultAdd_HYPRE;
2251414bd5c3SStefano Zampini   B->ops->multtransposeadd      = MatMultTransposeAdd_HYPRE;
225263c07aadSStefano Zampini   B->ops->setup                 = MatSetUp_HYPRE;
225363c07aadSStefano Zampini   B->ops->destroy               = MatDestroy_HYPRE;
225463c07aadSStefano Zampini   B->ops->assemblyend           = MatAssemblyEnd_HYPRE;
2255c69f721fSFande Kong   B->ops->assemblybegin         = MatAssemblyBegin_HYPRE;
2256d975228cSstefano_zampini   B->ops->setvalues             = MatSetValues_HYPRE;
225768ec7858SStefano Zampini   B->ops->missingdiagonal       = MatMissingDiagonal_HYPRE;
225868ec7858SStefano Zampini   B->ops->scale                 = MatScale_HYPRE;
225968ec7858SStefano Zampini   B->ops->zerorowscolumns       = MatZeroRowsColumns_HYPRE;
2260c69f721fSFande Kong   B->ops->zeroentries           = MatZeroEntries_HYPRE;
2261c69f721fSFande Kong   B->ops->zerorows              = MatZeroRows_HYPRE;
2262c69f721fSFande Kong   B->ops->getrow                = MatGetRow_HYPRE;
2263c69f721fSFande Kong   B->ops->restorerow            = MatRestoreRow_HYPRE;
2264c69f721fSFande Kong   B->ops->getvalues             = MatGetValues_HYPRE;
2265ddbeb582SStefano Zampini   B->ops->setoption             = MatSetOption_HYPRE;
226645b8d346SStefano Zampini   B->ops->duplicate             = MatDuplicate_HYPRE;
2267465edc17SStefano Zampini   B->ops->copy                  = MatCopy_HYPRE;
226845b8d346SStefano Zampini   B->ops->view                  = MatView_HYPRE;
22696305df00SStefano Zampini   B->ops->getdiagonal           = MatGetDiagonal_HYPRE;
2270363d496dSStefano Zampini   B->ops->axpy                  = MatAXPY_HYPRE;
22714222ddf1SHong Zhang   B->ops->productsetfromoptions = MatProductSetFromOptions_HYPRE;
2272*6ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
2273*6ea7df73SStefano Zampini   B->ops->bindtocpu             = MatBindToCPU_HYPRE;
2274*6ea7df73SStefano Zampini   B->boundtocpu                 = PETSC_FALSE;
2275*6ea7df73SStefano Zampini #endif
227645b8d346SStefano Zampini 
227745b8d346SStefano Zampini   /* build cache for off array entries formed */
227845b8d346SStefano Zampini   ierr = MatStashCreate_Private(PetscObjectComm((PetscObject)B),1,&B->stash);CHKERRQ(ierr);
227963c07aadSStefano Zampini 
2280ffc4695bSBarry Smith   ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)B),&hB->comm);CHKERRMPI(ierr);
228163c07aadSStefano Zampini   ierr = PetscObjectChangeTypeName((PetscObject)B,MATHYPRE);CHKERRQ(ierr);
228263c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_hypre_aij_C",MatConvert_HYPRE_AIJ);CHKERRQ(ierr);
22832df22349SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_hypre_is_C",MatConvert_HYPRE_IS);CHKERRQ(ierr);
22844222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_hypre_C",MatProductSetFromOptions_HYPRE);CHKERRQ(ierr);
22854222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_mpiaij_hypre_C",MatProductSetFromOptions_HYPRE);CHKERRQ(ierr);
2286d975228cSstefano_zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatHYPRESetPreallocation_C",MatHYPRESetPreallocation_HYPRE);CHKERRQ(ierr);
2287dd9c0a25Sstefano_zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatHYPREGetParCSR_C",MatHYPREGetParCSR_HYPRE);CHKERRQ(ierr);
2288*6ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
2289*6ea7df73SStefano Zampini #if defined(HYPRE_USING_HIP)
2290*6ea7df73SStefano Zampini   ierr = PetscHIPInitializeCheck();CHKERRQ(ierr);
2291*6ea7df73SStefano Zampini   ierr = MatSetVecType(B,VECHIP);CHKERRQ(ierr);
2292*6ea7df73SStefano Zampini #endif
2293*6ea7df73SStefano Zampini #if defined(HYPRE_USING_CUDA)
2294*6ea7df73SStefano Zampini   ierr = PetscCUDAInitializeCheck();CHKERRQ(ierr);
2295*6ea7df73SStefano Zampini   ierr = MatSetVecType(B,VECCUDA);CHKERRQ(ierr);
2296*6ea7df73SStefano Zampini #endif
2297*6ea7df73SStefano Zampini #endif
229863c07aadSStefano Zampini   PetscFunctionReturn(0);
229963c07aadSStefano Zampini }
230063c07aadSStefano Zampini 
2301225daaf8SStefano Zampini static PetscErrorCode hypre_array_destroy(void *ptr)
2302225daaf8SStefano Zampini {
2303225daaf8SStefano Zampini    PetscFunctionBegin;
2304e6de0934SSatish Balay    hypre_TFree(ptr,HYPRE_MEMORY_HOST);
2305225daaf8SStefano Zampini    PetscFunctionReturn(0);
2306225daaf8SStefano Zampini }
2307