xref: /petsc/src/mat/impls/hypre/mhypre.c (revision a4af0ceea8a251db97ee0dc5c0d52d4adf50264a)
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>
10*a4af0ceeSJacob Faibussowitsch #include <petsc/private/deviceimpl.h>
1163c07aadSStefano Zampini #include <../src/mat/impls/hypre/mhypre.h>
1263c07aadSStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
1358968eb6SStefano Zampini #include <../src/vec/vec/impls/hypre/vhyp.h>
1458968eb6SStefano Zampini #include <HYPRE.h>
15c1a070e6SStefano Zampini #include <HYPRE_utilities.h>
16cd8bc7baSStefano Zampini #include <_hypre_parcsr_ls.h>
1768ec7858SStefano Zampini #include <_hypre_sstruct_ls.h>
1863c07aadSStefano Zampini 
190e6427aaSSatish Balay #if PETSC_PKG_HYPRE_VERSION_LT(2,18,0)
200e6427aaSSatish Balay #define  hypre_ParCSRMatrixClone(A,B) hypre_ParCSRMatrixCompleteClone(A)
210e6427aaSSatish Balay #endif
220e6427aaSSatish Balay 
2363c07aadSStefano Zampini static PetscErrorCode MatHYPRE_CreateFromMat(Mat,Mat_HYPRE*);
2463c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat,Mat,HYPRE_IJMatrix);
2563c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixFastCopy_MPIAIJ(Mat,HYPRE_IJMatrix);
2663c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixFastCopy_SeqAIJ(Mat,HYPRE_IJMatrix);
2739accc25SStefano Zampini static PetscErrorCode MatHYPRE_MultKernel_Private(Mat,HYPRE_Complex,Vec,HYPRE_Complex,Vec,PetscBool);
28225daaf8SStefano Zampini static PetscErrorCode hypre_array_destroy(void*);
296ea7df73SStefano Zampini static PetscErrorCode MatSetValues_HYPRE(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[],const PetscScalar[],InsertMode ins);
3063c07aadSStefano Zampini 
3163c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat A_d, Mat A_o, HYPRE_IJMatrix ij)
3263c07aadSStefano Zampini {
3363c07aadSStefano Zampini   PetscErrorCode ierr;
3463c07aadSStefano Zampini   PetscInt       i,n_d,n_o;
3563c07aadSStefano Zampini   const PetscInt *ia_d,*ia_o;
3663c07aadSStefano Zampini   PetscBool      done_d=PETSC_FALSE,done_o=PETSC_FALSE;
372cf14000SStefano Zampini   HYPRE_Int      *nnz_d=NULL,*nnz_o=NULL;
3863c07aadSStefano Zampini 
3963c07aadSStefano Zampini   PetscFunctionBegin;
4063c07aadSStefano Zampini   if (A_d) { /* determine number of nonzero entries in local diagonal part */
4163c07aadSStefano Zampini     ierr = MatGetRowIJ(A_d,0,PETSC_FALSE,PETSC_FALSE,&n_d,&ia_d,NULL,&done_d);CHKERRQ(ierr);
4263c07aadSStefano Zampini     if (done_d) {
4363c07aadSStefano Zampini       ierr = PetscMalloc1(n_d,&nnz_d);CHKERRQ(ierr);
4463c07aadSStefano Zampini       for (i=0; i<n_d; i++) {
4563c07aadSStefano Zampini         nnz_d[i] = ia_d[i+1] - ia_d[i];
4663c07aadSStefano Zampini       }
4763c07aadSStefano Zampini     }
4863c07aadSStefano Zampini     ierr = MatRestoreRowIJ(A_d,0,PETSC_FALSE,PETSC_FALSE,NULL,&ia_d,NULL,&done_d);CHKERRQ(ierr);
4963c07aadSStefano Zampini   }
5063c07aadSStefano Zampini   if (A_o) { /* determine number of nonzero entries in local off-diagonal part */
5163c07aadSStefano Zampini     ierr = MatGetRowIJ(A_o,0,PETSC_FALSE,PETSC_FALSE,&n_o,&ia_o,NULL,&done_o);CHKERRQ(ierr);
5263c07aadSStefano Zampini     if (done_o) {
5363c07aadSStefano Zampini       ierr = PetscMalloc1(n_o,&nnz_o);CHKERRQ(ierr);
5463c07aadSStefano Zampini       for (i=0; i<n_o; i++) {
5563c07aadSStefano Zampini         nnz_o[i] = ia_o[i+1] - ia_o[i];
5663c07aadSStefano Zampini       }
5763c07aadSStefano Zampini     }
5863c07aadSStefano Zampini     ierr = MatRestoreRowIJ(A_o,0,PETSC_FALSE,PETSC_FALSE,&n_o,&ia_o,NULL,&done_o);CHKERRQ(ierr);
5963c07aadSStefano Zampini   }
6063c07aadSStefano Zampini   if (done_d) {    /* set number of nonzeros in HYPRE IJ matrix */
6163c07aadSStefano Zampini     if (!done_o) { /* only diagonal part */
6222235d61SPierre Jolivet       ierr = PetscCalloc1(n_d,&nnz_o);CHKERRQ(ierr);
6363c07aadSStefano Zampini     }
64c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2,16,0)
65c6698e78SStefano Zampini     { /* If we don't do this, the columns of the matrix will be all zeros! */
66c6698e78SStefano Zampini       hypre_AuxParCSRMatrix *aux_matrix;
67c6698e78SStefano Zampini       aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(ij);
68c6698e78SStefano Zampini       hypre_AuxParCSRMatrixDestroy(aux_matrix);
69c6698e78SStefano Zampini       hypre_IJMatrixTranslator(ij) = NULL;
702cf14000SStefano Zampini       PetscStackCallStandard(HYPRE_IJMatrixSetDiagOffdSizes,(ij,nnz_d,nnz_o));
7122235d61SPierre Jolivet       /* it seems they partially fixed it in 2.19.0 */
7222235d61SPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LT(2,19,0)
73c6698e78SStefano Zampini       aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(ij);
74c6698e78SStefano Zampini       hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1;
7522235d61SPierre Jolivet #endif
76c6698e78SStefano Zampini     }
77c6698e78SStefano Zampini #else
782cf14000SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixSetDiagOffdSizes,(ij,nnz_d,nnz_o));
79c6698e78SStefano Zampini #endif
8063c07aadSStefano Zampini     ierr = PetscFree(nnz_d);CHKERRQ(ierr);
8163c07aadSStefano Zampini     ierr = PetscFree(nnz_o);CHKERRQ(ierr);
8263c07aadSStefano Zampini   }
8363c07aadSStefano Zampini   PetscFunctionReturn(0);
8463c07aadSStefano Zampini }
8563c07aadSStefano Zampini 
8663c07aadSStefano Zampini static PetscErrorCode MatHYPRE_CreateFromMat(Mat A, Mat_HYPRE *hA)
8763c07aadSStefano Zampini {
8863c07aadSStefano Zampini   PetscErrorCode ierr;
8963c07aadSStefano Zampini   PetscInt       rstart,rend,cstart,cend;
9063c07aadSStefano Zampini 
9163c07aadSStefano Zampini   PetscFunctionBegin;
92d975228cSstefano_zampini   ierr   = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
93d975228cSstefano_zampini   ierr   = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
9463c07aadSStefano Zampini   rstart = A->rmap->rstart;
9563c07aadSStefano Zampini   rend   = A->rmap->rend;
9663c07aadSStefano Zampini   cstart = A->cmap->rstart;
9763c07aadSStefano Zampini   cend   = A->cmap->rend;
9863c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixCreate,(hA->comm,rstart,rend-1,cstart,cend-1,&hA->ij));
9963c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(hA->ij,HYPRE_PARCSR));
10063c07aadSStefano Zampini   {
10163c07aadSStefano Zampini     PetscBool      same;
10263c07aadSStefano Zampini     Mat            A_d,A_o;
10363c07aadSStefano Zampini     const PetscInt *colmap;
104b9e7e5c1SBarry Smith     ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATMPIAIJ,&same);CHKERRQ(ierr);
10563c07aadSStefano Zampini     if (same) {
10663c07aadSStefano Zampini       ierr = MatMPIAIJGetSeqAIJ(A,&A_d,&A_o,&colmap);CHKERRQ(ierr);
10763c07aadSStefano Zampini       ierr = MatHYPRE_IJMatrixPreallocate(A_d,A_o,hA->ij);CHKERRQ(ierr);
10863c07aadSStefano Zampini       PetscFunctionReturn(0);
10963c07aadSStefano Zampini     }
110b9e7e5c1SBarry Smith     ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATMPIBAIJ,&same);CHKERRQ(ierr);
11163c07aadSStefano Zampini     if (same) {
11263c07aadSStefano Zampini       ierr = MatMPIBAIJGetSeqBAIJ(A,&A_d,&A_o,&colmap);CHKERRQ(ierr);
11363c07aadSStefano Zampini       ierr = MatHYPRE_IJMatrixPreallocate(A_d,A_o,hA->ij);CHKERRQ(ierr);
11463c07aadSStefano Zampini       PetscFunctionReturn(0);
11563c07aadSStefano Zampini     }
116b9e7e5c1SBarry Smith     ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATSEQAIJ,&same);CHKERRQ(ierr);
11763c07aadSStefano Zampini     if (same) {
11863c07aadSStefano Zampini       ierr = MatHYPRE_IJMatrixPreallocate(A,NULL,hA->ij);CHKERRQ(ierr);
11963c07aadSStefano Zampini       PetscFunctionReturn(0);
12063c07aadSStefano Zampini     }
121b9e7e5c1SBarry Smith     ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATSEQBAIJ,&same);CHKERRQ(ierr);
12263c07aadSStefano Zampini     if (same) {
12363c07aadSStefano Zampini       ierr = MatHYPRE_IJMatrixPreallocate(A,NULL,hA->ij);CHKERRQ(ierr);
12463c07aadSStefano Zampini       PetscFunctionReturn(0);
12563c07aadSStefano Zampini     }
12663c07aadSStefano Zampini   }
12763c07aadSStefano Zampini   PetscFunctionReturn(0);
12863c07aadSStefano Zampini }
12963c07aadSStefano Zampini 
13063c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopy(Mat A, HYPRE_IJMatrix ij)
13163c07aadSStefano Zampini {
13263c07aadSStefano Zampini   PetscErrorCode    ierr;
13363c07aadSStefano Zampini   PetscInt          i,rstart,rend,ncols,nr,nc;
13463c07aadSStefano Zampini   const PetscScalar *values;
13563c07aadSStefano Zampini   const PetscInt    *cols;
13663c07aadSStefano Zampini   PetscBool         flg;
13763c07aadSStefano Zampini 
13863c07aadSStefano Zampini   PetscFunctionBegin;
1396ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2,19,0)
1406ea7df73SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixInitialize,(ij));
1416ea7df73SStefano Zampini #else
1426ea7df73SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixInitialize_v2,(ij,HYPRE_MEMORY_HOST));
1436ea7df73SStefano Zampini #endif
144b9e7e5c1SBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATMPIAIJ,&flg);CHKERRQ(ierr);
14563c07aadSStefano Zampini   ierr = MatGetSize(A,&nr,&nc);CHKERRQ(ierr);
14663c07aadSStefano Zampini   if (flg && nr == nc) {
14763c07aadSStefano Zampini     ierr = MatHYPRE_IJMatrixFastCopy_MPIAIJ(A,ij);CHKERRQ(ierr);
14863c07aadSStefano Zampini     PetscFunctionReturn(0);
14963c07aadSStefano Zampini   }
150b9e7e5c1SBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATSEQAIJ,&flg);CHKERRQ(ierr);
15163c07aadSStefano Zampini   if (flg) {
15263c07aadSStefano Zampini     ierr = MatHYPRE_IJMatrixFastCopy_SeqAIJ(A,ij);CHKERRQ(ierr);
15363c07aadSStefano Zampini     PetscFunctionReturn(0);
15463c07aadSStefano Zampini   }
15563c07aadSStefano Zampini 
15663c07aadSStefano Zampini   ierr = MatGetOwnershipRange(A,&rstart,&rend);CHKERRQ(ierr);
15763c07aadSStefano Zampini   for (i=rstart; i<rend; i++) {
15863c07aadSStefano Zampini     ierr = MatGetRow(A,i,&ncols,&cols,&values);CHKERRQ(ierr);
159e3977e59Sstefano_zampini     if (ncols) {
1602cf14000SStefano Zampini       HYPRE_Int nc = (HYPRE_Int)ncols;
1612cf14000SStefano Zampini 
1622cf14000SStefano Zampini       if ((PetscInt)nc != ncols) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Hypre overflow! number of columns %D for row %D",ncols,i);
16339accc25SStefano Zampini       PetscStackCallStandard(HYPRE_IJMatrixSetValues,(ij,1,&nc,(HYPRE_BigInt *)&i,(HYPRE_BigInt *)cols,(HYPRE_Complex *)values));
164e3977e59Sstefano_zampini     }
16563c07aadSStefano Zampini     ierr = MatRestoreRow(A,i,&ncols,&cols,&values);CHKERRQ(ierr);
16663c07aadSStefano Zampini   }
16763c07aadSStefano Zampini   PetscFunctionReturn(0);
16863c07aadSStefano Zampini }
16963c07aadSStefano Zampini 
17063c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixFastCopy_SeqAIJ(Mat A, HYPRE_IJMatrix ij)
17163c07aadSStefano Zampini {
17263c07aadSStefano Zampini   PetscErrorCode        ierr;
17363c07aadSStefano Zampini   Mat_SeqAIJ            *pdiag = (Mat_SeqAIJ*)A->data;
17458968eb6SStefano Zampini   HYPRE_Int             type;
17563c07aadSStefano Zampini   hypre_ParCSRMatrix    *par_matrix;
17663c07aadSStefano Zampini   hypre_AuxParCSRMatrix *aux_matrix;
17763c07aadSStefano Zampini   hypre_CSRMatrix       *hdiag;
1782cf14000SStefano Zampini   PetscBool             sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
1796ea7df73SStefano Zampini   const PetscScalar     *pa;
18063c07aadSStefano Zampini 
18163c07aadSStefano Zampini   PetscFunctionBegin;
182ea9daf28SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(ij,&type));
183ea9daf28SStefano Zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
184ea9daf28SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(ij,(void**)&par_matrix));
18563c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(par_matrix);
18663c07aadSStefano Zampini   /*
18763c07aadSStefano Zampini        this is the Hack part where we monkey directly with the hypre datastructures
18863c07aadSStefano Zampini   */
1892cf14000SStefano Zampini   if (sameint) {
190580bdb30SBarry Smith     ierr = PetscArraycpy(hdiag->i,pdiag->i,A->rmap->n + 1);CHKERRQ(ierr);
191580bdb30SBarry Smith     ierr = PetscArraycpy(hdiag->j,pdiag->j,pdiag->nz);CHKERRQ(ierr);
1922cf14000SStefano Zampini   } else {
1932cf14000SStefano Zampini     PetscInt i;
1942cf14000SStefano Zampini 
1952cf14000SStefano Zampini     for (i=0;i<A->rmap->n + 1;i++) hdiag->i[i] = (HYPRE_Int)pdiag->i[i];
1962cf14000SStefano Zampini     for (i=0;i<pdiag->nz;i++)      hdiag->j[i] = (HYPRE_Int)pdiag->j[i];
1972cf14000SStefano Zampini   }
1986ea7df73SStefano Zampini 
1996ea7df73SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&pa);CHKERRQ(ierr);
2006ea7df73SStefano Zampini   ierr = PetscArraycpy(hdiag->data,pa,pdiag->nz);CHKERRQ(ierr);
2016ea7df73SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&pa);CHKERRQ(ierr);
202ea9daf28SStefano Zampini 
203ea9daf28SStefano Zampini   aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(ij);
20463c07aadSStefano Zampini   hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
20563c07aadSStefano Zampini   PetscFunctionReturn(0);
20663c07aadSStefano Zampini }
20763c07aadSStefano Zampini 
20863c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixFastCopy_MPIAIJ(Mat A, HYPRE_IJMatrix ij)
20963c07aadSStefano Zampini {
21063c07aadSStefano Zampini   PetscErrorCode        ierr;
21163c07aadSStefano Zampini   Mat_MPIAIJ            *pA = (Mat_MPIAIJ*)A->data;
21263c07aadSStefano Zampini   Mat_SeqAIJ            *pdiag,*poffd;
21363c07aadSStefano Zampini   PetscInt              i,*garray = pA->garray,*jj,cstart,*pjj;
2142cf14000SStefano Zampini   HYPRE_Int             *hjj,type;
21563c07aadSStefano Zampini   hypre_ParCSRMatrix    *par_matrix;
21663c07aadSStefano Zampini   hypre_AuxParCSRMatrix *aux_matrix;
21763c07aadSStefano Zampini   hypre_CSRMatrix       *hdiag,*hoffd;
2182cf14000SStefano Zampini   PetscBool             sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
2196ea7df73SStefano Zampini   const PetscScalar     *pa;
22063c07aadSStefano Zampini 
22163c07aadSStefano Zampini   PetscFunctionBegin;
22263c07aadSStefano Zampini   pdiag = (Mat_SeqAIJ*) pA->A->data;
22363c07aadSStefano Zampini   poffd = (Mat_SeqAIJ*) pA->B->data;
22463c07aadSStefano Zampini   /* cstart is only valid for square MPIAIJ layed out in the usual way */
22563c07aadSStefano Zampini   ierr = MatGetOwnershipRange(A,&cstart,NULL);CHKERRQ(ierr);
22663c07aadSStefano Zampini 
227ea9daf28SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(ij,&type));
228ea9daf28SStefano Zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
229ea9daf28SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(ij,(void**)&par_matrix));
23063c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(par_matrix);
23163c07aadSStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(par_matrix);
23263c07aadSStefano Zampini 
23363c07aadSStefano Zampini   /*
23463c07aadSStefano Zampini        this is the Hack part where we monkey directly with the hypre datastructures
23563c07aadSStefano Zampini   */
2362cf14000SStefano Zampini   if (sameint) {
237580bdb30SBarry Smith     ierr = PetscArraycpy(hdiag->i,pdiag->i,pA->A->rmap->n + 1);CHKERRQ(ierr);
2382cf14000SStefano Zampini   } else {
2392cf14000SStefano Zampini     for (i=0; i<pA->A->rmap->n + 1; i++) hdiag->i[i] = (HYPRE_Int)(pdiag->i[i]);
2402cf14000SStefano Zampini   }
24163c07aadSStefano Zampini   /* need to shift the diag column indices (hdiag->j) back to global numbering since hypre is expecting this */
2422cf14000SStefano Zampini   hjj = hdiag->j;
2432cf14000SStefano Zampini   pjj = pdiag->j;
244c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2,16,0)
2452cf14000SStefano Zampini   for (i=0; i<pdiag->nz; i++) hjj[i] = pjj[i];
246c6698e78SStefano Zampini #else
2472cf14000SStefano Zampini   for (i=0; i<pdiag->nz; i++) hjj[i] = cstart + pjj[i];
248c6698e78SStefano Zampini #endif
2496ea7df73SStefano Zampini   ierr = MatSeqAIJGetArrayRead(pA->A,&pa);CHKERRQ(ierr);
2506ea7df73SStefano Zampini   ierr = PetscArraycpy(hdiag->data,pa,pdiag->nz);CHKERRQ(ierr);
2516ea7df73SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(pA->A,&pa);CHKERRQ(ierr);
2522cf14000SStefano Zampini   if (sameint) {
253580bdb30SBarry Smith     ierr = PetscArraycpy(hoffd->i,poffd->i,pA->A->rmap->n + 1);CHKERRQ(ierr);
2542cf14000SStefano Zampini   } else {
2552cf14000SStefano Zampini     for (i=0; i<pA->A->rmap->n + 1; i++) hoffd->i[i] = (HYPRE_Int)(poffd->i[i]);
2562cf14000SStefano Zampini   }
2572cf14000SStefano Zampini 
25863c07aadSStefano Zampini   /* need to move the offd column indices (hoffd->j) back to global numbering since hypre is expecting this
25963c07aadSStefano Zampini      If we hacked a hypre a bit more we might be able to avoid this step */
260c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2,16,0)
261c6698e78SStefano Zampini   PetscStackCallStandard(hypre_CSRMatrixBigInitialize,(hoffd));
262c6698e78SStefano Zampini   jj  = (PetscInt*) hoffd->big_j;
263c6698e78SStefano Zampini #else
26463c07aadSStefano Zampini   jj  = (PetscInt*) hoffd->j;
265c6698e78SStefano Zampini #endif
2662cf14000SStefano Zampini   pjj = poffd->j;
26763c07aadSStefano Zampini   for (i=0; i<poffd->nz; i++) jj[i] = garray[pjj[i]];
268c6698e78SStefano Zampini 
2696ea7df73SStefano Zampini   ierr = MatSeqAIJGetArrayRead(pA->B,&pa);CHKERRQ(ierr);
2706ea7df73SStefano Zampini   ierr = PetscArraycpy(hoffd->data,pa,poffd->nz);CHKERRQ(ierr);
2716ea7df73SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(pA->B,&pa);CHKERRQ(ierr);
27263c07aadSStefano Zampini 
273ea9daf28SStefano Zampini   aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(ij);
27463c07aadSStefano Zampini   hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
27563c07aadSStefano Zampini   PetscFunctionReturn(0);
27663c07aadSStefano Zampini }
27763c07aadSStefano Zampini 
2782df22349SStefano Zampini static PetscErrorCode MatConvert_HYPRE_IS(Mat A, MatType mtype, MatReuse reuse, Mat* B)
2792df22349SStefano Zampini {
2802df22349SStefano Zampini   Mat_HYPRE*             mhA = (Mat_HYPRE*)(A->data);
2812df22349SStefano Zampini   Mat                    lA;
2822df22349SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
2832df22349SStefano Zampini   IS                     is;
2842df22349SStefano Zampini   hypre_ParCSRMatrix     *hA;
2852df22349SStefano Zampini   hypre_CSRMatrix        *hdiag,*hoffd;
2862df22349SStefano Zampini   MPI_Comm               comm;
28739accc25SStefano Zampini   HYPRE_Complex          *hdd,*hod,*aa;
28839accc25SStefano Zampini   PetscScalar            *data;
2892cf14000SStefano Zampini   HYPRE_BigInt           *col_map_offd;
2902cf14000SStefano Zampini   HYPRE_Int              *hdi,*hdj,*hoi,*hoj;
2912df22349SStefano Zampini   PetscInt               *ii,*jj,*iptr,*jptr;
2922df22349SStefano Zampini   PetscInt               cum,dr,dc,oc,str,stc,nnz,i,jd,jo,M,N;
29358968eb6SStefano Zampini   HYPRE_Int              type;
2942df22349SStefano Zampini   PetscErrorCode         ierr;
2952df22349SStefano Zampini 
2962df22349SStefano Zampini   PetscFunctionBegin;
297a1787963SStefano Zampini   comm = PetscObjectComm((PetscObject)A);
2982df22349SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(mhA->ij,&type));
2992df22349SStefano Zampini   if (type != HYPRE_PARCSR) SETERRQ(comm,PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
3002df22349SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(mhA->ij,(void**)&hA));
3012df22349SStefano Zampini   M     = hypre_ParCSRMatrixGlobalNumRows(hA);
3022df22349SStefano Zampini   N     = hypre_ParCSRMatrixGlobalNumCols(hA);
3032df22349SStefano Zampini   str   = hypre_ParCSRMatrixFirstRowIndex(hA);
3042df22349SStefano Zampini   stc   = hypre_ParCSRMatrixFirstColDiag(hA);
3052df22349SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(hA);
3062df22349SStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(hA);
3072df22349SStefano Zampini   dr    = hypre_CSRMatrixNumRows(hdiag);
3082df22349SStefano Zampini   dc    = hypre_CSRMatrixNumCols(hdiag);
3092df22349SStefano Zampini   nnz   = hypre_CSRMatrixNumNonzeros(hdiag);
3102df22349SStefano Zampini   hdi   = hypre_CSRMatrixI(hdiag);
3112df22349SStefano Zampini   hdj   = hypre_CSRMatrixJ(hdiag);
3122df22349SStefano Zampini   hdd   = hypre_CSRMatrixData(hdiag);
3132df22349SStefano Zampini   oc    = hypre_CSRMatrixNumCols(hoffd);
3142df22349SStefano Zampini   nnz  += hypre_CSRMatrixNumNonzeros(hoffd);
3152df22349SStefano Zampini   hoi   = hypre_CSRMatrixI(hoffd);
3162df22349SStefano Zampini   hoj   = hypre_CSRMatrixJ(hoffd);
3172df22349SStefano Zampini   hod   = hypre_CSRMatrixData(hoffd);
3182df22349SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
3192df22349SStefano Zampini     PetscInt *aux;
3202df22349SStefano Zampini 
3212df22349SStefano Zampini     /* generate l2g maps for rows and cols */
3222df22349SStefano Zampini     ierr = ISCreateStride(comm,dr,str,1,&is);CHKERRQ(ierr);
3232df22349SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
3242df22349SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
3252df22349SStefano Zampini     col_map_offd = hypre_ParCSRMatrixColMapOffd(hA);
3262df22349SStefano Zampini     ierr = PetscMalloc1(dc+oc,&aux);CHKERRQ(ierr);
3272df22349SStefano Zampini     for (i=0; i<dc; i++) aux[i] = i+stc;
3282df22349SStefano Zampini     for (i=0; i<oc; i++) aux[i+dc] = col_map_offd[i];
3292df22349SStefano Zampini     ierr = ISCreateGeneral(comm,dc+oc,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
3302df22349SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
3312df22349SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
3322df22349SStefano Zampini     /* create MATIS object */
3332df22349SStefano Zampini     ierr = MatCreate(comm,B);CHKERRQ(ierr);
3342df22349SStefano Zampini     ierr = MatSetSizes(*B,dr,dc,M,N);CHKERRQ(ierr);
3352df22349SStefano Zampini     ierr = MatSetType(*B,MATIS);CHKERRQ(ierr);
3362df22349SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*B,rl2g,cl2g);CHKERRQ(ierr);
3372df22349SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
3382df22349SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
3392df22349SStefano Zampini 
3402df22349SStefano Zampini     /* allocate CSR for local matrix */
3412df22349SStefano Zampini     ierr = PetscMalloc1(dr+1,&iptr);CHKERRQ(ierr);
3422df22349SStefano Zampini     ierr = PetscMalloc1(nnz,&jptr);CHKERRQ(ierr);
3432df22349SStefano Zampini     ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr);
3442df22349SStefano Zampini   } else {
3452df22349SStefano Zampini     PetscInt  nr;
3462df22349SStefano Zampini     PetscBool done;
3472df22349SStefano Zampini     ierr = MatISGetLocalMat(*B,&lA);CHKERRQ(ierr);
3482df22349SStefano Zampini     ierr = MatGetRowIJ(lA,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&iptr,(const PetscInt**)&jptr,&done);CHKERRQ(ierr);
3492df22349SStefano 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);
3502df22349SStefano 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);
3512df22349SStefano Zampini     ierr = MatSeqAIJGetArray(lA,&data);CHKERRQ(ierr);
3522df22349SStefano Zampini   }
3532df22349SStefano Zampini   /* merge local matrices */
3542df22349SStefano Zampini   ii  = iptr;
3552df22349SStefano Zampini   jj  = jptr;
35639accc25SStefano 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++ */
3572df22349SStefano Zampini   *ii = *(hdi++) + *(hoi++);
3582df22349SStefano Zampini   for (jd=0,jo=0,cum=0; *ii<nnz; cum++) {
35939accc25SStefano Zampini     PetscScalar *aold = (PetscScalar*)aa;
3602df22349SStefano Zampini     PetscInt    *jold = jj,nc = jd+jo;
3612df22349SStefano Zampini     for (; jd<*hdi; jd++) { *jj++ = *hdj++;      *aa++ = *hdd++; }
3622df22349SStefano Zampini     for (; jo<*hoi; jo++) { *jj++ = *hoj++ + dc; *aa++ = *hod++; }
3632df22349SStefano Zampini     *(++ii) = *(hdi++) + *(hoi++);
3642df22349SStefano Zampini     ierr = PetscSortIntWithScalarArray(jd+jo-nc,jold,aold);CHKERRQ(ierr);
3652df22349SStefano Zampini   }
3662df22349SStefano Zampini   for (; cum<dr; cum++) *(++ii) = nnz;
3672df22349SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
368a033916dSStefano Zampini     Mat_SeqAIJ* a;
369a033916dSStefano Zampini 
3702df22349SStefano Zampini     ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,dc+oc,iptr,jptr,data,&lA);CHKERRQ(ierr);
3712df22349SStefano Zampini     ierr = MatISSetLocalMat(*B,lA);CHKERRQ(ierr);
372a033916dSStefano Zampini     /* hack SeqAIJ */
373a033916dSStefano Zampini     a          = (Mat_SeqAIJ*)(lA->data);
374a033916dSStefano Zampini     a->free_a  = PETSC_TRUE;
375a033916dSStefano Zampini     a->free_ij = PETSC_TRUE;
3762df22349SStefano Zampini     ierr = MatDestroy(&lA);CHKERRQ(ierr);
3772df22349SStefano Zampini   }
3782df22349SStefano Zampini   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3792df22349SStefano Zampini   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3802df22349SStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
3812df22349SStefano Zampini     ierr = MatHeaderReplace(A,B);CHKERRQ(ierr);
3822df22349SStefano Zampini   }
3832df22349SStefano Zampini   PetscFunctionReturn(0);
3842df22349SStefano Zampini }
3852df22349SStefano Zampini 
38663c07aadSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType type, MatReuse reuse, Mat *B)
38763c07aadSStefano Zampini {
38884d4e069SStefano Zampini   Mat            M = NULL;
38963c07aadSStefano Zampini   Mat_HYPRE      *hB;
39063c07aadSStefano Zampini   MPI_Comm       comm = PetscObjectComm((PetscObject)A);
39163c07aadSStefano Zampini   PetscErrorCode ierr;
39263c07aadSStefano Zampini 
39363c07aadSStefano Zampini   PetscFunctionBegin;
39463c07aadSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
39563c07aadSStefano Zampini     /* always destroy the old matrix and create a new memory;
39663c07aadSStefano Zampini        hope this does not churn the memory too much. The problem
39763c07aadSStefano Zampini        is I do not know if it is possible to put the matrix back to
39863c07aadSStefano Zampini        its initial state so that we can directly copy the values
39963c07aadSStefano Zampini        the second time through. */
40063c07aadSStefano Zampini     hB = (Mat_HYPRE*)((*B)->data);
40163c07aadSStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixDestroy,(hB->ij));
40263c07aadSStefano Zampini   } else {
40384d4e069SStefano Zampini     ierr = MatCreate(comm,&M);CHKERRQ(ierr);
40484d4e069SStefano Zampini     ierr = MatSetType(M,MATHYPRE);CHKERRQ(ierr);
40584d4e069SStefano Zampini     ierr = MatSetSizes(M,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
40684d4e069SStefano Zampini     hB   = (Mat_HYPRE*)(M->data);
40784d4e069SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) *B = M;
40863c07aadSStefano Zampini   }
409d04e6649SStefano Zampini   ierr = MatSetOption(*B,MAT_SORTED_FULL,PETSC_TRUE);CHKERRQ(ierr); /* "perfect" preallocation, so no need for hypre_AuxParCSRMatrixNeedAux */
410d04e6649SStefano Zampini   ierr = MatSetOption(*B,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
41163c07aadSStefano Zampini   ierr = MatHYPRE_CreateFromMat(A,hB);CHKERRQ(ierr);
41263c07aadSStefano Zampini   ierr = MatHYPRE_IJMatrixCopy(A,hB->ij);CHKERRQ(ierr);
41384d4e069SStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
41484d4e069SStefano Zampini     ierr = MatHeaderReplace(A,&M);CHKERRQ(ierr);
41584d4e069SStefano Zampini   }
4164ec6421dSstefano_zampini   (*B)->preallocated = PETSC_TRUE;
41763c07aadSStefano Zampini   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
41863c07aadSStefano Zampini   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
41963c07aadSStefano Zampini   PetscFunctionReturn(0);
42063c07aadSStefano Zampini }
42163c07aadSStefano Zampini 
422ea9daf28SStefano Zampini static PetscErrorCode MatConvert_HYPRE_AIJ(Mat A, MatType mtype, MatReuse reuse, Mat *B)
42363c07aadSStefano Zampini {
42463c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE*)A->data;
42563c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
42663c07aadSStefano Zampini   hypre_CSRMatrix    *hdiag,*hoffd;
42763c07aadSStefano Zampini   MPI_Comm           comm;
42863c07aadSStefano Zampini   PetscScalar        *da,*oa,*aptr;
42963c07aadSStefano Zampini   PetscInt           *dii,*djj,*oii,*ojj,*iptr;
43063c07aadSStefano Zampini   PetscInt           i,dnnz,onnz,m,n;
43158968eb6SStefano Zampini   HYPRE_Int          type;
43263c07aadSStefano Zampini   PetscMPIInt        size;
4332cf14000SStefano Zampini   PetscBool          sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
43463c07aadSStefano Zampini   PetscErrorCode     ierr;
43563c07aadSStefano Zampini 
43663c07aadSStefano Zampini   PetscFunctionBegin;
43763c07aadSStefano Zampini   comm = PetscObjectComm((PetscObject)A);
43863c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type));
43963c07aadSStefano Zampini   if (type != HYPRE_PARCSR) SETERRQ(comm,PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
44063c07aadSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
44163c07aadSStefano Zampini     PetscBool ismpiaij,isseqaij;
442b9e7e5c1SBarry Smith     ierr = PetscObjectBaseTypeCompare((PetscObject)*B,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
4434099cc6bSBarry Smith     ierr = PetscObjectBaseTypeCompare((PetscObject)*B,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
44463c07aadSStefano Zampini     if (!ismpiaij && !isseqaij) SETERRQ(comm,PETSC_ERR_SUP,"Only MATMPIAIJ or MATSEQAIJ are supported");
44563c07aadSStefano Zampini   }
4466ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
4476ea7df73SStefano Zampini   if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(hA->ij)) SETERRQ(comm,PETSC_ERR_SUP,"Not yet implemented");
4486ea7df73SStefano Zampini #endif
449ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
45063c07aadSStefano Zampini 
45163c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&parcsr));
45263c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(parcsr);
45363c07aadSStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(parcsr);
45463c07aadSStefano Zampini   m     = hypre_CSRMatrixNumRows(hdiag);
45563c07aadSStefano Zampini   n     = hypre_CSRMatrixNumCols(hdiag);
45663c07aadSStefano Zampini   dnnz  = hypre_CSRMatrixNumNonzeros(hdiag);
45763c07aadSStefano Zampini   onnz  = hypre_CSRMatrixNumNonzeros(hoffd);
458225daaf8SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
45963c07aadSStefano Zampini     ierr = PetscMalloc1(m+1,&dii);CHKERRQ(ierr);
46063c07aadSStefano Zampini     ierr = PetscMalloc1(dnnz,&djj);CHKERRQ(ierr);
46163c07aadSStefano Zampini     ierr = PetscMalloc1(dnnz,&da);CHKERRQ(ierr);
462225daaf8SStefano Zampini   } else if (reuse == MAT_REUSE_MATRIX) {
46363c07aadSStefano Zampini     PetscInt  nr;
46463c07aadSStefano Zampini     PetscBool done;
46563c07aadSStefano Zampini     if (size > 1) {
46663c07aadSStefano Zampini       Mat_MPIAIJ *b = (Mat_MPIAIJ*)((*B)->data);
46763c07aadSStefano Zampini 
46863c07aadSStefano Zampini       ierr = MatGetRowIJ(b->A,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&dii,(const PetscInt**)&djj,&done);CHKERRQ(ierr);
46963c07aadSStefano 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);
47063c07aadSStefano 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);
47163c07aadSStefano Zampini       ierr = MatSeqAIJGetArray(b->A,&da);CHKERRQ(ierr);
47263c07aadSStefano Zampini     } else {
47363c07aadSStefano Zampini       ierr = MatGetRowIJ(*B,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&dii,(const PetscInt**)&djj,&done);CHKERRQ(ierr);
47463c07aadSStefano Zampini       if (nr != m) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot reuse mat: invalid number of local rows! %D != %D",nr,m);
47563c07aadSStefano 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);
47663c07aadSStefano Zampini       ierr = MatSeqAIJGetArray(*B,&da);CHKERRQ(ierr);
47763c07aadSStefano Zampini     }
478225daaf8SStefano Zampini   } else { /* MAT_INPLACE_MATRIX */
4792cf14000SStefano Zampini     if (!sameint) {
4802cf14000SStefano Zampini       ierr = PetscMalloc1(m+1,&dii);CHKERRQ(ierr);
4812cf14000SStefano Zampini       ierr = PetscMalloc1(dnnz,&djj);CHKERRQ(ierr);
4822cf14000SStefano Zampini     } else {
4837d968826Sstefano_zampini       dii = (PetscInt*)hypre_CSRMatrixI(hdiag);
4847d968826Sstefano_zampini       djj = (PetscInt*)hypre_CSRMatrixJ(hdiag);
48563c07aadSStefano Zampini     }
48639accc25SStefano Zampini     da = (PetscScalar*)hypre_CSRMatrixData(hdiag);
48763c07aadSStefano Zampini   }
4882cf14000SStefano Zampini 
4892cf14000SStefano Zampini   if (!sameint) {
4902cf14000SStefano Zampini     for (i=0;i<m+1;i++)  dii[i] = (PetscInt)(hypre_CSRMatrixI(hdiag)[i]);
4912cf14000SStefano Zampini     for (i=0;i<dnnz;i++) djj[i] = (PetscInt)(hypre_CSRMatrixJ(hdiag)[i]);
4922cf14000SStefano Zampini   } else {
493580bdb30SBarry Smith     ierr = PetscArraycpy(dii,hypre_CSRMatrixI(hdiag),m+1);CHKERRQ(ierr);
494580bdb30SBarry Smith     ierr = PetscArraycpy(djj,hypre_CSRMatrixJ(hdiag),dnnz);CHKERRQ(ierr);
4952cf14000SStefano Zampini   }
496580bdb30SBarry Smith   ierr = PetscArraycpy(da,hypre_CSRMatrixData(hdiag),dnnz);CHKERRQ(ierr);
49763c07aadSStefano Zampini   iptr = djj;
49863c07aadSStefano Zampini   aptr = da;
49963c07aadSStefano Zampini   for (i=0; i<m; i++) {
50063c07aadSStefano Zampini     PetscInt nc = dii[i+1]-dii[i];
50163c07aadSStefano Zampini     ierr = PetscSortIntWithScalarArray(nc,iptr,aptr);CHKERRQ(ierr);
50263c07aadSStefano Zampini     iptr += nc;
50363c07aadSStefano Zampini     aptr += nc;
50463c07aadSStefano Zampini   }
50563c07aadSStefano Zampini   if (size > 1) {
5062cf14000SStefano Zampini     HYPRE_BigInt *coffd;
5072cf14000SStefano Zampini     HYPRE_Int    *offdj;
50863c07aadSStefano Zampini 
509225daaf8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
51063c07aadSStefano Zampini       ierr = PetscMalloc1(m+1,&oii);CHKERRQ(ierr);
51163c07aadSStefano Zampini       ierr = PetscMalloc1(onnz,&ojj);CHKERRQ(ierr);
51263c07aadSStefano Zampini       ierr = PetscMalloc1(onnz,&oa);CHKERRQ(ierr);
513225daaf8SStefano Zampini     } else if (reuse == MAT_REUSE_MATRIX) {
51463c07aadSStefano Zampini       Mat_MPIAIJ *b = (Mat_MPIAIJ*)((*B)->data);
51563c07aadSStefano Zampini       PetscInt   nr,hr = hypre_CSRMatrixNumRows(hoffd);
51663c07aadSStefano Zampini       PetscBool  done;
51763c07aadSStefano Zampini 
51863c07aadSStefano Zampini       ierr = MatGetRowIJ(b->B,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&oii,(const PetscInt**)&ojj,&done);CHKERRQ(ierr);
51963c07aadSStefano 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);
52063c07aadSStefano 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);
52163c07aadSStefano Zampini       ierr = MatSeqAIJGetArray(b->B,&oa);CHKERRQ(ierr);
522225daaf8SStefano Zampini     } else { /* MAT_INPLACE_MATRIX */
5232cf14000SStefano Zampini       if (!sameint) {
5242cf14000SStefano Zampini         ierr = PetscMalloc1(m+1,&oii);CHKERRQ(ierr);
5252cf14000SStefano Zampini         ierr = PetscMalloc1(onnz,&ojj);CHKERRQ(ierr);
5262cf14000SStefano Zampini       } else {
5277d968826Sstefano_zampini         oii = (PetscInt*)hypre_CSRMatrixI(hoffd);
5287d968826Sstefano_zampini         ojj = (PetscInt*)hypre_CSRMatrixJ(hoffd);
52963c07aadSStefano Zampini       }
53039accc25SStefano Zampini       oa = (PetscScalar*)hypre_CSRMatrixData(hoffd);
53163c07aadSStefano Zampini     }
5322cf14000SStefano Zampini     if (!sameint) {
5332cf14000SStefano Zampini       for (i=0;i<m+1;i++) oii[i] = (PetscInt)(hypre_CSRMatrixI(hoffd)[i]);
5342cf14000SStefano Zampini     } else {
535580bdb30SBarry Smith       ierr = PetscArraycpy(oii,hypre_CSRMatrixI(hoffd),m+1);CHKERRQ(ierr);
5362cf14000SStefano Zampini     }
53763c07aadSStefano Zampini     offdj = hypre_CSRMatrixJ(hoffd);
53863c07aadSStefano Zampini     coffd = hypre_ParCSRMatrixColMapOffd(parcsr);
53963c07aadSStefano Zampini     for (i=0; i<onnz; i++) ojj[i] = coffd[offdj[i]];
540580bdb30SBarry Smith     ierr = PetscArraycpy(oa,hypre_CSRMatrixData(hoffd),onnz);CHKERRQ(ierr);
54163c07aadSStefano Zampini     iptr = ojj;
54263c07aadSStefano Zampini     aptr = oa;
54363c07aadSStefano Zampini     for (i=0; i<m; i++) {
54463c07aadSStefano Zampini        PetscInt nc = oii[i+1]-oii[i];
54563c07aadSStefano Zampini        ierr = PetscSortIntWithScalarArray(nc,iptr,aptr);CHKERRQ(ierr);
54663c07aadSStefano Zampini        iptr += nc;
54763c07aadSStefano Zampini        aptr += nc;
54863c07aadSStefano Zampini     }
549225daaf8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
55063c07aadSStefano Zampini       Mat_MPIAIJ *b;
55163c07aadSStefano Zampini       Mat_SeqAIJ *d,*o;
552225daaf8SStefano Zampini 
55341073d71Sstefano_zampini       ierr = MatCreateMPIAIJWithSplitArrays(comm,m,n,PETSC_DECIDE,PETSC_DECIDE,dii,djj,da,oii,ojj,oa,B);CHKERRQ(ierr);
55463c07aadSStefano Zampini       /* hack MPIAIJ */
55563c07aadSStefano Zampini       b          = (Mat_MPIAIJ*)((*B)->data);
55663c07aadSStefano Zampini       d          = (Mat_SeqAIJ*)b->A->data;
55763c07aadSStefano Zampini       o          = (Mat_SeqAIJ*)b->B->data;
55863c07aadSStefano Zampini       d->free_a  = PETSC_TRUE;
55963c07aadSStefano Zampini       d->free_ij = PETSC_TRUE;
56063c07aadSStefano Zampini       o->free_a  = PETSC_TRUE;
56163c07aadSStefano Zampini       o->free_ij = PETSC_TRUE;
562225daaf8SStefano Zampini     } else if (reuse == MAT_INPLACE_MATRIX) {
563225daaf8SStefano Zampini       Mat T;
5642cf14000SStefano Zampini 
56541073d71Sstefano_zampini       ierr = MatCreateMPIAIJWithSplitArrays(comm,m,n,PETSC_DECIDE,PETSC_DECIDE,dii,djj,da,oii,ojj,oa,&T);CHKERRQ(ierr);
5662cf14000SStefano Zampini       if (sameint) { /* ownership of CSR pointers is transferred to PETSc */
567225daaf8SStefano Zampini         hypre_CSRMatrixI(hdiag) = NULL;
568225daaf8SStefano Zampini         hypre_CSRMatrixJ(hdiag) = NULL;
569225daaf8SStefano Zampini         hypre_CSRMatrixI(hoffd) = NULL;
570225daaf8SStefano Zampini         hypre_CSRMatrixJ(hoffd) = NULL;
5712cf14000SStefano Zampini       } else { /* Hack MPIAIJ -> free ij but not a */
5722cf14000SStefano Zampini         Mat_MPIAIJ *b = (Mat_MPIAIJ*)(T->data);
5732cf14000SStefano Zampini         Mat_SeqAIJ *d = (Mat_SeqAIJ*)(b->A->data);
5742cf14000SStefano Zampini         Mat_SeqAIJ *o = (Mat_SeqAIJ*)(b->B->data);
5752cf14000SStefano Zampini 
5762cf14000SStefano Zampini         d->free_ij = PETSC_TRUE;
5772cf14000SStefano Zampini         o->free_ij = PETSC_TRUE;
5782cf14000SStefano Zampini       }
5792cf14000SStefano Zampini       hypre_CSRMatrixData(hdiag) = NULL;
580225daaf8SStefano Zampini       hypre_CSRMatrixData(hoffd) = NULL;
581225daaf8SStefano Zampini       ierr = MatHeaderReplace(A,&T);CHKERRQ(ierr);
58263c07aadSStefano Zampini     }
583225daaf8SStefano Zampini   } else {
584225daaf8SStefano Zampini     oii  = NULL;
585225daaf8SStefano Zampini     ojj  = NULL;
586225daaf8SStefano Zampini     oa   = NULL;
587225daaf8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
58863c07aadSStefano Zampini       Mat_SeqAIJ* b;
5892cf14000SStefano Zampini 
59063c07aadSStefano Zampini       ierr = MatCreateSeqAIJWithArrays(comm,m,n,dii,djj,da,B);CHKERRQ(ierr);
59163c07aadSStefano Zampini       /* hack SeqAIJ */
59263c07aadSStefano Zampini       b          = (Mat_SeqAIJ*)((*B)->data);
59363c07aadSStefano Zampini       b->free_a  = PETSC_TRUE;
59463c07aadSStefano Zampini       b->free_ij = PETSC_TRUE;
595225daaf8SStefano Zampini     } else if (reuse == MAT_INPLACE_MATRIX) {
596225daaf8SStefano Zampini       Mat T;
5972cf14000SStefano Zampini 
598225daaf8SStefano Zampini       ierr = MatCreateSeqAIJWithArrays(comm,m,n,dii,djj,da,&T);CHKERRQ(ierr);
5992cf14000SStefano Zampini       if (sameint) { /* ownership of CSR pointers is transferred to PETSc */
600225daaf8SStefano Zampini         hypre_CSRMatrixI(hdiag) = NULL;
601225daaf8SStefano Zampini         hypre_CSRMatrixJ(hdiag) = NULL;
6022cf14000SStefano Zampini       } else { /* free ij but not a */
6032cf14000SStefano Zampini         Mat_SeqAIJ* b = (Mat_SeqAIJ*)(T->data);
6042cf14000SStefano Zampini 
6052cf14000SStefano Zampini         b->free_ij = PETSC_TRUE;
6062cf14000SStefano Zampini       }
607225daaf8SStefano Zampini       hypre_CSRMatrixData(hdiag) = NULL;
608225daaf8SStefano Zampini       ierr = MatHeaderReplace(A,&T);CHKERRQ(ierr);
60963c07aadSStefano Zampini     }
610225daaf8SStefano Zampini   }
611225daaf8SStefano Zampini 
6122cf14000SStefano Zampini   /* we have to use hypre_Tfree to free the HYPRE arrays
6132cf14000SStefano Zampini      that PETSc now onws */
61463c07aadSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
6152cf14000SStefano Zampini     PetscInt nh;
6162cf14000SStefano Zampini     void *ptrs[6] = {da,oa,dii,djj,oii,ojj};
6172cf14000SStefano Zampini     const char *names[6] = {"_hypre_csr_da",
6182cf14000SStefano Zampini                             "_hypre_csr_oa",
6192cf14000SStefano Zampini                             "_hypre_csr_dii",
620225daaf8SStefano Zampini                             "_hypre_csr_djj",
621225daaf8SStefano Zampini                             "_hypre_csr_oii",
6222cf14000SStefano Zampini                             "_hypre_csr_ojj"};
6232cf14000SStefano Zampini     nh = sameint ? 6 : 2;
6242cf14000SStefano Zampini     for (i=0; i<nh; i++) {
625225daaf8SStefano Zampini       PetscContainer c;
626225daaf8SStefano Zampini 
627225daaf8SStefano Zampini       ierr = PetscContainerCreate(comm,&c);CHKERRQ(ierr);
628225daaf8SStefano Zampini       ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr);
629225daaf8SStefano Zampini       ierr = PetscContainerSetUserDestroy(c,hypre_array_destroy);CHKERRQ(ierr);
630225daaf8SStefano Zampini       ierr = PetscObjectCompose((PetscObject)(*B),names[i],(PetscObject)c);CHKERRQ(ierr);
631225daaf8SStefano Zampini       ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
632225daaf8SStefano Zampini     }
63363c07aadSStefano Zampini   }
63463c07aadSStefano Zampini   PetscFunctionReturn(0);
63563c07aadSStefano Zampini }
63663c07aadSStefano Zampini 
637613e5ff0Sstefano_zampini static PetscErrorCode MatAIJGetParCSR_Private(Mat A, hypre_ParCSRMatrix **hA)
638c1a070e6SStefano Zampini {
639613e5ff0Sstefano_zampini   hypre_ParCSRMatrix *tA;
640c1a070e6SStefano Zampini   hypre_CSRMatrix    *hdiag,*hoffd;
641c1a070e6SStefano Zampini   Mat_SeqAIJ         *diag,*offd;
6422cf14000SStefano Zampini   PetscInt           *garray,i,noffd,dnnz,onnz,*row_starts,*col_starts;
643c1a070e6SStefano Zampini   MPI_Comm           comm = PetscObjectComm((PetscObject)A);
644613e5ff0Sstefano_zampini   PetscBool          ismpiaij,isseqaij;
6452cf14000SStefano Zampini   PetscBool          sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
646c1a070e6SStefano Zampini   PetscErrorCode     ierr;
6476ea7df73SStefano Zampini   HYPRE_Int          *hdi = NULL,*hdj = NULL,*hoi = NULL,*hoj = NULL;
6486ea7df73SStefano Zampini   PetscInt           *pdi,*pdj,*poi,*poj;
6496ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
6506ea7df73SStefano Zampini   PetscBool          iscuda = PETSC_FALSE;
6516ea7df73SStefano Zampini #endif
652c1a070e6SStefano Zampini 
653c1a070e6SStefano Zampini   PetscFunctionBegin;
6543937f725SBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
6554099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
656a32993e3SJed Brown   if (!ismpiaij && !isseqaij) SETERRQ1(comm,PETSC_ERR_SUP,"Unsupported type %s",((PetscObject)A)->type_name);
657c1a070e6SStefano Zampini   if (ismpiaij) {
658c1a070e6SStefano Zampini     Mat_MPIAIJ *a = (Mat_MPIAIJ*)(A->data);
659c1a070e6SStefano Zampini 
660c1a070e6SStefano Zampini     diag = (Mat_SeqAIJ*)a->A->data;
661c1a070e6SStefano Zampini     offd = (Mat_SeqAIJ*)a->B->data;
6626ea7df73SStefano Zampini #if defined(PETSC_HAVE_CUDA) && defined(PETSC_HAVE_HYPRE_DEVICE) && defined(HYPRE_USING_CUDA)
6636ea7df73SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJCUSPARSE,&iscuda);CHKERRQ(ierr);
6646ea7df73SStefano Zampini     if (iscuda && !A->boundtocpu) {
6656ea7df73SStefano Zampini       sameint = PETSC_TRUE;
6666ea7df73SStefano Zampini       ierr = MatSeqAIJCUSPARSEGetIJ(a->A,PETSC_FALSE,(const HYPRE_Int**)&hdi,(const HYPRE_Int**)&hdj);CHKERRQ(ierr);
6676ea7df73SStefano Zampini       ierr = MatSeqAIJCUSPARSEGetIJ(a->B,PETSC_FALSE,(const HYPRE_Int**)&hoi,(const HYPRE_Int**)&hoj);CHKERRQ(ierr);
6686ea7df73SStefano Zampini     } else {
6696ea7df73SStefano Zampini #else
6706ea7df73SStefano Zampini     {
6716ea7df73SStefano Zampini #endif
6726ea7df73SStefano Zampini       pdi = diag->i;
6736ea7df73SStefano Zampini       pdj = diag->j;
6746ea7df73SStefano Zampini       poi = offd->i;
6756ea7df73SStefano Zampini       poj = offd->j;
6766ea7df73SStefano Zampini       if (sameint) {
6776ea7df73SStefano Zampini         hdi = (HYPRE_Int*)pdi;
6786ea7df73SStefano Zampini         hdj = (HYPRE_Int*)pdj;
6796ea7df73SStefano Zampini         hoi = (HYPRE_Int*)poi;
6806ea7df73SStefano Zampini         hoj = (HYPRE_Int*)poj;
6816ea7df73SStefano Zampini       }
6826ea7df73SStefano Zampini     }
683c1a070e6SStefano Zampini     garray = a->garray;
684c1a070e6SStefano Zampini     noffd  = a->B->cmap->N;
685c1a070e6SStefano Zampini     dnnz   = diag->nz;
686c1a070e6SStefano Zampini     onnz   = offd->nz;
687c1a070e6SStefano Zampini   } else {
688c1a070e6SStefano Zampini     diag = (Mat_SeqAIJ*)A->data;
689c1a070e6SStefano Zampini     offd = NULL;
6906ea7df73SStefano Zampini #if defined(PETSC_HAVE_CUDA) && defined(PETSC_HAVE_HYPRE_DEVICE)
6916ea7df73SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJCUSPARSE,&iscuda);CHKERRQ(ierr);
6926ea7df73SStefano Zampini     if (iscuda && !A->boundtocpu) {
6936ea7df73SStefano Zampini       sameint = PETSC_TRUE;
6946ea7df73SStefano Zampini       ierr = MatSeqAIJCUSPARSEGetIJ(A,PETSC_FALSE,(const HYPRE_Int**)&hdi,(const HYPRE_Int**)&hdj);CHKERRQ(ierr);
6956ea7df73SStefano Zampini     } else {
6966ea7df73SStefano Zampini #else
6976ea7df73SStefano Zampini     {
6986ea7df73SStefano Zampini #endif
6996ea7df73SStefano Zampini       pdi = diag->i;
7006ea7df73SStefano Zampini       pdj = diag->j;
7016ea7df73SStefano Zampini       if (sameint) {
7026ea7df73SStefano Zampini         hdi = (HYPRE_Int*)pdi;
7036ea7df73SStefano Zampini         hdj = (HYPRE_Int*)pdj;
7046ea7df73SStefano Zampini       }
7056ea7df73SStefano Zampini     }
706c1a070e6SStefano Zampini     garray = NULL;
707c1a070e6SStefano Zampini     noffd  = 0;
708c1a070e6SStefano Zampini     dnnz   = diag->nz;
709c1a070e6SStefano Zampini     onnz   = 0;
710c1a070e6SStefano Zampini   }
711225daaf8SStefano Zampini 
712c1a070e6SStefano Zampini   /* create a temporary ParCSR */
713c1a070e6SStefano Zampini   if (HYPRE_AssumedPartitionCheck()) {
714c1a070e6SStefano Zampini     PetscMPIInt myid;
715c1a070e6SStefano Zampini 
71655b25c41SPierre Jolivet     ierr       = MPI_Comm_rank(comm,&myid);CHKERRMPI(ierr);
717c1a070e6SStefano Zampini     row_starts = A->rmap->range + myid;
718c1a070e6SStefano Zampini     col_starts = A->cmap->range + myid;
719c1a070e6SStefano Zampini   } else {
720c1a070e6SStefano Zampini     row_starts = A->rmap->range;
721c1a070e6SStefano Zampini     col_starts = A->cmap->range;
722c1a070e6SStefano Zampini   }
7232cf14000SStefano Zampini   tA = hypre_ParCSRMatrixCreate(comm,A->rmap->N,A->cmap->N,(HYPRE_BigInt*)row_starts,(HYPRE_BigInt*)col_starts,noffd,dnnz,onnz);
724a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
725c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetRowStartsOwner(tA,0);
726c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetColStartsOwner(tA,0);
727a1d2239cSSatish Balay #endif
728c1a070e6SStefano Zampini 
729225daaf8SStefano Zampini   /* set diagonal part */
730c1a070e6SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(tA);
7316ea7df73SStefano Zampini   if (!sameint) { /* malloc CSR pointers */
7326ea7df73SStefano Zampini     ierr = PetscMalloc2(A->rmap->n+1,&hdi,dnnz,&hdj);CHKERRQ(ierr);
7336ea7df73SStefano Zampini     for (i = 0; i < A->rmap->n+1; i++) hdi[i] = (HYPRE_Int)(pdi[i]);
7346ea7df73SStefano Zampini     for (i = 0; i < dnnz; i++)         hdj[i] = (HYPRE_Int)(pdj[i]);
7352cf14000SStefano Zampini   }
7366ea7df73SStefano Zampini   hypre_CSRMatrixI(hdiag)           = hdi;
7376ea7df73SStefano Zampini   hypre_CSRMatrixJ(hdiag)           = hdj;
73839accc25SStefano Zampini   hypre_CSRMatrixData(hdiag)        = (HYPRE_Complex*)diag->a;
739c1a070e6SStefano Zampini   hypre_CSRMatrixNumNonzeros(hdiag) = diag->nz;
740c1a070e6SStefano Zampini   hypre_CSRMatrixSetRownnz(hdiag);
741c1a070e6SStefano Zampini   hypre_CSRMatrixSetDataOwner(hdiag,0);
742c1a070e6SStefano Zampini 
743225daaf8SStefano Zampini   /* set offdiagonal part */
744c1a070e6SStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(tA);
745c1a070e6SStefano Zampini   if (offd) {
7466ea7df73SStefano Zampini     if (!sameint) { /* malloc CSR pointers */
7476ea7df73SStefano Zampini       ierr = PetscMalloc2(A->rmap->n+1,&hoi,onnz,&hoj);CHKERRQ(ierr);
7486ea7df73SStefano Zampini       for (i = 0; i < A->rmap->n+1; i++) hoi[i] = (HYPRE_Int)(poi[i]);
7496ea7df73SStefano Zampini       for (i = 0; i < onnz; i++)         hoj[i] = (HYPRE_Int)(poj[i]);
7502cf14000SStefano Zampini     }
7516ea7df73SStefano Zampini     hypre_CSRMatrixI(hoffd)           = hoi;
7526ea7df73SStefano Zampini     hypre_CSRMatrixJ(hoffd)           = hoj;
75339accc25SStefano Zampini     hypre_CSRMatrixData(hoffd)        = (HYPRE_Complex*)offd->a;
754c1a070e6SStefano Zampini     hypre_CSRMatrixNumNonzeros(hoffd) = offd->nz;
755c1a070e6SStefano Zampini     hypre_CSRMatrixSetRownnz(hoffd);
756c1a070e6SStefano Zampini     hypre_CSRMatrixSetDataOwner(hoffd,0);
7576ea7df73SStefano Zampini   }
7586ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
7596ea7df73SStefano Zampini   PetscStackCallStandard(hypre_ParCSRMatrixInitialize_v2,(tA,iscuda ? HYPRE_MEMORY_DEVICE : HYPRE_MEMORY_HOST));
7606ea7df73SStefano Zampini #else
7616ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2,18,0)
7626ea7df73SStefano Zampini   PetscStackCallStandard(hypre_ParCSRMatrixInitialize,(tA));
7636ea7df73SStefano Zampini #else
7646ea7df73SStefano Zampini   PetscStackCallStandard(hypre_ParCSRMatrixInitialize_v2,(tA,HYPRE_MEMORY_HOST));
7656ea7df73SStefano Zampini #endif
7666ea7df73SStefano Zampini #endif
7676ea7df73SStefano Zampini   hypre_TFree(hypre_ParCSRMatrixColMapOffd(tA),HYPRE_MEMORY_HOST);
768c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetNumNonzeros(tA);
7692cf14000SStefano Zampini   hypre_ParCSRMatrixColMapOffd(tA) = (HYPRE_BigInt*)garray;
7706ea7df73SStefano Zampini   if (!hypre_ParCSRMatrixCommPkg(tA)) PetscStackCallStandard(hypre_MatvecCommPkgCreate,(tA));
771613e5ff0Sstefano_zampini   *hA = tA;
772613e5ff0Sstefano_zampini   PetscFunctionReturn(0);
773613e5ff0Sstefano_zampini }
774c1a070e6SStefano Zampini 
775613e5ff0Sstefano_zampini static PetscErrorCode MatAIJRestoreParCSR_Private(Mat A, hypre_ParCSRMatrix **hA)
776613e5ff0Sstefano_zampini {
777613e5ff0Sstefano_zampini   hypre_CSRMatrix *hdiag,*hoffd;
7786ea7df73SStefano Zampini   PetscBool       ismpiaij,sameint = (PetscBool)(sizeof(PetscInt) == sizeof(HYPRE_Int));
7792cf14000SStefano Zampini   PetscErrorCode  ierr;
7806ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
7816ea7df73SStefano Zampini   PetscBool       iscuda = PETSC_FALSE;
7826ea7df73SStefano Zampini #endif
783c1a070e6SStefano Zampini 
784613e5ff0Sstefano_zampini   PetscFunctionBegin;
7856ea7df73SStefano Zampini   ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
7866ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
7876ea7df73SStefano Zampini   ierr = PetscObjectTypeCompareAny((PetscObject)A,&iscuda,MATSEQAIJCUSPARSE,MATMPIAIJCUSPARSE,"");CHKERRQ(ierr);
7886ea7df73SStefano Zampini   if (iscuda) sameint = PETSC_TRUE;
7896ea7df73SStefano Zampini #endif
790613e5ff0Sstefano_zampini   hdiag = hypre_ParCSRMatrixDiag(*hA);
791613e5ff0Sstefano_zampini   hoffd = hypre_ParCSRMatrixOffd(*hA);
7926ea7df73SStefano Zampini   /* free temporary memory allocated by PETSc
7936ea7df73SStefano Zampini      set pointers to NULL before destroying tA */
7942cf14000SStefano Zampini   if (!sameint) {
7952cf14000SStefano Zampini     HYPRE_Int *hi,*hj;
7962cf14000SStefano Zampini 
7972cf14000SStefano Zampini     hi = hypre_CSRMatrixI(hdiag);
7982cf14000SStefano Zampini     hj = hypre_CSRMatrixJ(hdiag);
7992cf14000SStefano Zampini     ierr = PetscFree2(hi,hj);CHKERRQ(ierr);
8006ea7df73SStefano Zampini     if (ismpiaij) {
8012cf14000SStefano Zampini       hi = hypre_CSRMatrixI(hoffd);
8022cf14000SStefano Zampini       hj = hypre_CSRMatrixJ(hoffd);
8032cf14000SStefano Zampini       ierr = PetscFree2(hi,hj);CHKERRQ(ierr);
8042cf14000SStefano Zampini     }
8052cf14000SStefano Zampini   }
806c1a070e6SStefano Zampini   hypre_CSRMatrixI(hdiag)    = NULL;
807c1a070e6SStefano Zampini   hypre_CSRMatrixJ(hdiag)    = NULL;
808c1a070e6SStefano Zampini   hypre_CSRMatrixData(hdiag) = NULL;
8096ea7df73SStefano Zampini   if (ismpiaij) {
810c1a070e6SStefano Zampini     hypre_CSRMatrixI(hoffd)    = NULL;
811c1a070e6SStefano Zampini     hypre_CSRMatrixJ(hoffd)    = NULL;
812c1a070e6SStefano Zampini     hypre_CSRMatrixData(hoffd) = NULL;
8136ea7df73SStefano Zampini   }
814613e5ff0Sstefano_zampini   hypre_ParCSRMatrixColMapOffd(*hA) = NULL;
815613e5ff0Sstefano_zampini   hypre_ParCSRMatrixDestroy(*hA);
816613e5ff0Sstefano_zampini   *hA = NULL;
817613e5ff0Sstefano_zampini   PetscFunctionReturn(0);
818613e5ff0Sstefano_zampini }
819613e5ff0Sstefano_zampini 
820613e5ff0Sstefano_zampini /* calls RAP from BoomerAMG:
8213dad0653Sstefano_zampini    the resulting ParCSR will not own the column and row starts
8226ea7df73SStefano Zampini    It looks like we don't need to have the diagonal entries ordered first */
823a055b5aaSBarry Smith static PetscErrorCode MatHYPRE_ParCSR_RAP(hypre_ParCSRMatrix *hR, hypre_ParCSRMatrix *hA,hypre_ParCSRMatrix *hP, hypre_ParCSRMatrix **hRAP)
824613e5ff0Sstefano_zampini {
825a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
826613e5ff0Sstefano_zampini   HYPRE_Int P_owns_col_starts,R_owns_row_starts;
827a1d2239cSSatish Balay #endif
828613e5ff0Sstefano_zampini 
829613e5ff0Sstefano_zampini   PetscFunctionBegin;
830a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
831613e5ff0Sstefano_zampini   P_owns_col_starts = hypre_ParCSRMatrixOwnsColStarts(hP);
832613e5ff0Sstefano_zampini   R_owns_row_starts = hypre_ParCSRMatrixOwnsRowStarts(hR);
833a1d2239cSSatish Balay #endif
8346ea7df73SStefano Zampini   /* can be replaced by version test later */
8356ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
8366ea7df73SStefano Zampini   PetscStackPush("hypre_ParCSRMatrixRAP");
8376ea7df73SStefano Zampini   *hRAP = hypre_ParCSRMatrixRAP(hR,hA,hP);
8386ea7df73SStefano Zampini   PetscStackPop;
8396ea7df73SStefano Zampini #else
840613e5ff0Sstefano_zampini   PetscStackCallStandard(hypre_BoomerAMGBuildCoarseOperator,(hR,hA,hP,hRAP));
841613e5ff0Sstefano_zampini   PetscStackCallStandard(hypre_ParCSRMatrixSetNumNonzeros,(*hRAP));
8426ea7df73SStefano Zampini #endif
843613e5ff0Sstefano_zampini   /* hypre_BoomerAMGBuildCoarseOperator steals the col_starts from P and the row_starts from R */
844a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
845613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetRowStartsOwner(*hRAP,0);
846613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetColStartsOwner(*hRAP,0);
847613e5ff0Sstefano_zampini   if (P_owns_col_starts) hypre_ParCSRMatrixSetColStartsOwner(hP,1);
848613e5ff0Sstefano_zampini   if (R_owns_row_starts) hypre_ParCSRMatrixSetRowStartsOwner(hR,1);
849a1d2239cSSatish Balay #endif
850613e5ff0Sstefano_zampini   PetscFunctionReturn(0);
851613e5ff0Sstefano_zampini }
852613e5ff0Sstefano_zampini 
8536f231fbdSstefano_zampini static PetscErrorCode MatPtAPNumeric_AIJ_AIJ_wHYPRE(Mat A,Mat P,Mat C)
854613e5ff0Sstefano_zampini {
8556f231fbdSstefano_zampini   Mat                B;
8566abb4441SStefano Zampini   hypre_ParCSRMatrix *hA,*hP,*hPtAP = NULL;
857613e5ff0Sstefano_zampini   PetscErrorCode     ierr;
8584222ddf1SHong Zhang   Mat_Product        *product=C->product;
859613e5ff0Sstefano_zampini 
860613e5ff0Sstefano_zampini   PetscFunctionBegin;
861613e5ff0Sstefano_zampini   ierr = MatAIJGetParCSR_Private(A,&hA);CHKERRQ(ierr);
862613e5ff0Sstefano_zampini   ierr = MatAIJGetParCSR_Private(P,&hP);CHKERRQ(ierr);
863613e5ff0Sstefano_zampini   ierr = MatHYPRE_ParCSR_RAP(hP,hA,hP,&hPtAP);CHKERRQ(ierr);
8646f231fbdSstefano_zampini   ierr = MatCreateFromParCSR(hPtAP,MATAIJ,PETSC_OWN_POINTER,&B);CHKERRQ(ierr);
8654222ddf1SHong Zhang 
8666f231fbdSstefano_zampini   ierr = MatHeaderMerge(C,&B);CHKERRQ(ierr);
8674222ddf1SHong Zhang   C->product = product;
8684222ddf1SHong Zhang 
869613e5ff0Sstefano_zampini   ierr = MatAIJRestoreParCSR_Private(A,&hA);CHKERRQ(ierr);
870613e5ff0Sstefano_zampini   ierr = MatAIJRestoreParCSR_Private(P,&hP);CHKERRQ(ierr);
8716f231fbdSstefano_zampini   PetscFunctionReturn(0);
8726f231fbdSstefano_zampini }
8736f231fbdSstefano_zampini 
8744222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatPtAPSymbolic_AIJ_AIJ_wHYPRE(Mat A,Mat P,PetscReal fill,Mat C)
8756f231fbdSstefano_zampini {
8766f231fbdSstefano_zampini   PetscErrorCode ierr;
877ab4d48faSStefano Zampini 
8786f231fbdSstefano_zampini   PetscFunctionBegin;
8794222ddf1SHong Zhang   ierr                   = MatSetType(C,MATAIJ);CHKERRQ(ierr);
8804222ddf1SHong Zhang   C->ops->ptapnumeric    = MatPtAPNumeric_AIJ_AIJ_wHYPRE;
8814222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
882613e5ff0Sstefano_zampini   PetscFunctionReturn(0);
883613e5ff0Sstefano_zampini }
884613e5ff0Sstefano_zampini 
8854cc28894Sstefano_zampini static PetscErrorCode MatPtAPNumeric_AIJ_HYPRE(Mat A,Mat P,Mat C)
886613e5ff0Sstefano_zampini {
8874cc28894Sstefano_zampini   Mat                B;
8884cc28894Sstefano_zampini   Mat_HYPRE          *hP;
8896abb4441SStefano Zampini   hypre_ParCSRMatrix *hA = NULL,*Pparcsr,*ptapparcsr = NULL;
890613e5ff0Sstefano_zampini   HYPRE_Int          type;
891613e5ff0Sstefano_zampini   MPI_Comm           comm = PetscObjectComm((PetscObject)A);
8924cc28894Sstefano_zampini   PetscBool          ishypre;
893613e5ff0Sstefano_zampini   PetscErrorCode     ierr;
894613e5ff0Sstefano_zampini 
895613e5ff0Sstefano_zampini   PetscFunctionBegin;
8964cc28894Sstefano_zampini   ierr = PetscObjectTypeCompare((PetscObject)P,MATHYPRE,&ishypre);CHKERRQ(ierr);
8974cc28894Sstefano_zampini   if (!ishypre) SETERRQ1(comm,PETSC_ERR_USER,"P should be of type %s",MATHYPRE);
8984cc28894Sstefano_zampini   hP = (Mat_HYPRE*)P->data;
899613e5ff0Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hP->ij,&type));
900613e5ff0Sstefano_zampini   if (type != HYPRE_PARCSR) SETERRQ(comm,PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
901613e5ff0Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hP->ij,(void**)&Pparcsr));
902613e5ff0Sstefano_zampini 
903613e5ff0Sstefano_zampini   ierr = MatAIJGetParCSR_Private(A,&hA);CHKERRQ(ierr);
904613e5ff0Sstefano_zampini   ierr = MatHYPRE_ParCSR_RAP(Pparcsr,hA,Pparcsr,&ptapparcsr);CHKERRQ(ierr);
905613e5ff0Sstefano_zampini   ierr = MatAIJRestoreParCSR_Private(A,&hA);CHKERRQ(ierr);
906225daaf8SStefano Zampini 
9074cc28894Sstefano_zampini   /* create temporary matrix and merge to C */
9084cc28894Sstefano_zampini   ierr = MatCreateFromParCSR(ptapparcsr,((PetscObject)C)->type_name,PETSC_OWN_POINTER,&B);CHKERRQ(ierr);
9094cc28894Sstefano_zampini   ierr = MatHeaderMerge(C,&B);CHKERRQ(ierr);
9104cc28894Sstefano_zampini   PetscFunctionReturn(0);
9114cc28894Sstefano_zampini }
9124cc28894Sstefano_zampini 
9134cc28894Sstefano_zampini static PetscErrorCode MatPtAPNumeric_HYPRE_HYPRE(Mat A,Mat P,Mat C)
9144cc28894Sstefano_zampini {
9154cc28894Sstefano_zampini   Mat                B;
9166abb4441SStefano Zampini   hypre_ParCSRMatrix *Aparcsr,*Pparcsr,*ptapparcsr = NULL;
9174cc28894Sstefano_zampini   Mat_HYPRE          *hA,*hP;
9184cc28894Sstefano_zampini   PetscBool          ishypre;
9194cc28894Sstefano_zampini   HYPRE_Int          type;
9204cc28894Sstefano_zampini   PetscErrorCode     ierr;
9214cc28894Sstefano_zampini 
9224cc28894Sstefano_zampini   PetscFunctionBegin;
9234cc28894Sstefano_zampini   ierr = PetscObjectTypeCompare((PetscObject)P,MATHYPRE,&ishypre);CHKERRQ(ierr);
9244cc28894Sstefano_zampini   if (!ishypre) SETERRQ1(PetscObjectComm((PetscObject)P),PETSC_ERR_USER,"P should be of type %s",MATHYPRE);
9254cc28894Sstefano_zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATHYPRE,&ishypre);CHKERRQ(ierr);
9264cc28894Sstefano_zampini   if (!ishypre) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_USER,"A should be of type %s",MATHYPRE);
9274cc28894Sstefano_zampini   hA = (Mat_HYPRE*)A->data;
9284cc28894Sstefano_zampini   hP = (Mat_HYPRE*)P->data;
9294cc28894Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type));
9304cc28894Sstefano_zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
9314cc28894Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hP->ij,&type));
9324cc28894Sstefano_zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)P),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
9334cc28894Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&Aparcsr));
9344cc28894Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hP->ij,(void**)&Pparcsr));
9354cc28894Sstefano_zampini   ierr = MatHYPRE_ParCSR_RAP(Pparcsr,Aparcsr,Pparcsr,&ptapparcsr);CHKERRQ(ierr);
9364cc28894Sstefano_zampini   ierr = MatCreateFromParCSR(ptapparcsr,MATHYPRE,PETSC_OWN_POINTER,&B);CHKERRQ(ierr);
9374cc28894Sstefano_zampini   ierr = MatHeaderMerge(C,&B);CHKERRQ(ierr);
9384cc28894Sstefano_zampini   PetscFunctionReturn(0);
9394cc28894Sstefano_zampini }
9404cc28894Sstefano_zampini 
941d501dc42Sstefano_zampini /* calls hypre_ParMatmul
942d501dc42Sstefano_zampini    hypre_ParMatMul uses hypre_ParMatrixCreate with the communicator of hA
9433dad0653Sstefano_zampini    hypre_ParMatrixCreate does not duplicate the communicator
9446ea7df73SStefano Zampini    It looks like we don't need to have the diagonal entries ordered first */
945d501dc42Sstefano_zampini static PetscErrorCode MatHYPRE_ParCSR_MatMatMult(hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hB, hypre_ParCSRMatrix **hAB)
946d501dc42Sstefano_zampini {
947d501dc42Sstefano_zampini   PetscFunctionBegin;
9486ea7df73SStefano Zampini   /* can be replaced by version test later */
9496ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
9506ea7df73SStefano Zampini   PetscStackPush("hypre_ParCSRMatMat");
9516ea7df73SStefano Zampini   *hAB = hypre_ParCSRMatMat(hA,hB);
9526ea7df73SStefano Zampini #else
953d501dc42Sstefano_zampini   PetscStackPush("hypre_ParMatmul");
954d501dc42Sstefano_zampini   *hAB = hypre_ParMatmul(hA,hB);
9556ea7df73SStefano Zampini #endif
956d501dc42Sstefano_zampini   PetscStackPop;
957d501dc42Sstefano_zampini   PetscFunctionReturn(0);
958d501dc42Sstefano_zampini }
959d501dc42Sstefano_zampini 
9605e5acdf2Sstefano_zampini static PetscErrorCode MatMatMultNumeric_AIJ_AIJ_wHYPRE(Mat A,Mat B,Mat C)
9615e5acdf2Sstefano_zampini {
9625e5acdf2Sstefano_zampini   Mat                D;
963d501dc42Sstefano_zampini   hypre_ParCSRMatrix *hA,*hB,*hAB = NULL;
9645e5acdf2Sstefano_zampini   PetscErrorCode     ierr;
9654222ddf1SHong Zhang   Mat_Product        *product=C->product;
9665e5acdf2Sstefano_zampini 
9675e5acdf2Sstefano_zampini   PetscFunctionBegin;
9685e5acdf2Sstefano_zampini   ierr = MatAIJGetParCSR_Private(A,&hA);CHKERRQ(ierr);
9695e5acdf2Sstefano_zampini   ierr = MatAIJGetParCSR_Private(B,&hB);CHKERRQ(ierr);
970d501dc42Sstefano_zampini   ierr = MatHYPRE_ParCSR_MatMatMult(hA,hB,&hAB);CHKERRQ(ierr);
9715e5acdf2Sstefano_zampini   ierr = MatCreateFromParCSR(hAB,MATAIJ,PETSC_OWN_POINTER,&D);CHKERRQ(ierr);
9724222ddf1SHong Zhang 
9735e5acdf2Sstefano_zampini   ierr = MatHeaderMerge(C,&D);CHKERRQ(ierr);
9744222ddf1SHong Zhang   C->product = product;
9754222ddf1SHong Zhang 
9765e5acdf2Sstefano_zampini   ierr = MatAIJRestoreParCSR_Private(A,&hA);CHKERRQ(ierr);
9775e5acdf2Sstefano_zampini   ierr = MatAIJRestoreParCSR_Private(B,&hB);CHKERRQ(ierr);
9785e5acdf2Sstefano_zampini   PetscFunctionReturn(0);
9795e5acdf2Sstefano_zampini }
9805e5acdf2Sstefano_zampini 
9814222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatMatMultSymbolic_AIJ_AIJ_wHYPRE(Mat A,Mat B,PetscReal fill,Mat C)
9825e5acdf2Sstefano_zampini {
9835e5acdf2Sstefano_zampini   PetscErrorCode ierr;
98420e1dc0dSstefano_zampini 
9855e5acdf2Sstefano_zampini   PetscFunctionBegin;
9864222ddf1SHong Zhang   ierr = MatSetType(C,MATAIJ);CHKERRQ(ierr);
9874222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_AIJ_AIJ_wHYPRE;
9884222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
9895e5acdf2Sstefano_zampini   PetscFunctionReturn(0);
9905e5acdf2Sstefano_zampini }
9915e5acdf2Sstefano_zampini 
992d501dc42Sstefano_zampini static PetscErrorCode MatMatMultNumeric_HYPRE_HYPRE(Mat A,Mat B,Mat C)
993d501dc42Sstefano_zampini {
994d501dc42Sstefano_zampini   Mat                D;
995d501dc42Sstefano_zampini   hypre_ParCSRMatrix *Aparcsr,*Bparcsr,*ABparcsr = NULL;
996d501dc42Sstefano_zampini   Mat_HYPRE          *hA,*hB;
997d501dc42Sstefano_zampini   PetscBool          ishypre;
998d501dc42Sstefano_zampini   HYPRE_Int          type;
999d501dc42Sstefano_zampini   PetscErrorCode     ierr;
10004222ddf1SHong Zhang   Mat_Product        *product;
1001d501dc42Sstefano_zampini 
1002d501dc42Sstefano_zampini   PetscFunctionBegin;
1003d501dc42Sstefano_zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATHYPRE,&ishypre);CHKERRQ(ierr);
1004d501dc42Sstefano_zampini   if (!ishypre) SETERRQ1(PetscObjectComm((PetscObject)B),PETSC_ERR_USER,"B should be of type %s",MATHYPRE);
1005d501dc42Sstefano_zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATHYPRE,&ishypre);CHKERRQ(ierr);
1006d501dc42Sstefano_zampini   if (!ishypre) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_USER,"A should be of type %s",MATHYPRE);
1007d501dc42Sstefano_zampini   hA = (Mat_HYPRE*)A->data;
1008d501dc42Sstefano_zampini   hB = (Mat_HYPRE*)B->data;
1009d501dc42Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type));
1010d501dc42Sstefano_zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
1011d501dc42Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hB->ij,&type));
1012d501dc42Sstefano_zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
1013d501dc42Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&Aparcsr));
1014d501dc42Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hB->ij,(void**)&Bparcsr));
1015d501dc42Sstefano_zampini   ierr = MatHYPRE_ParCSR_MatMatMult(Aparcsr,Bparcsr,&ABparcsr);CHKERRQ(ierr);
1016d501dc42Sstefano_zampini   ierr = MatCreateFromParCSR(ABparcsr,MATHYPRE,PETSC_OWN_POINTER,&D);CHKERRQ(ierr);
10174222ddf1SHong Zhang 
1018d501dc42Sstefano_zampini   /* need to use HeaderReplace because HeaderMerge messes up with the communicator */
10194222ddf1SHong Zhang   product    = C->product;  /* save it from MatHeaderReplace() */
10204222ddf1SHong Zhang   C->product = NULL;
1021d501dc42Sstefano_zampini   ierr = MatHeaderReplace(C,&D);CHKERRQ(ierr);
10224222ddf1SHong Zhang   C->product = product;
1023d501dc42Sstefano_zampini   C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE;
10244222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
1025d501dc42Sstefano_zampini   PetscFunctionReturn(0);
1026d501dc42Sstefano_zampini }
1027d501dc42Sstefano_zampini 
10283dad0653Sstefano_zampini PETSC_INTERN PetscErrorCode MatTransposeMatMatMultNumeric_AIJ_AIJ_AIJ_wHYPRE(Mat A,Mat B,Mat C,Mat D)
102920e1dc0dSstefano_zampini {
103020e1dc0dSstefano_zampini   Mat                E;
10316abb4441SStefano Zampini   hypre_ParCSRMatrix *hA,*hB,*hC,*hABC = NULL;
103220e1dc0dSstefano_zampini   PetscErrorCode     ierr;
103320e1dc0dSstefano_zampini 
103420e1dc0dSstefano_zampini   PetscFunctionBegin;
103520e1dc0dSstefano_zampini   ierr = MatAIJGetParCSR_Private(A,&hA);CHKERRQ(ierr);
103620e1dc0dSstefano_zampini   ierr = MatAIJGetParCSR_Private(B,&hB);CHKERRQ(ierr);
103720e1dc0dSstefano_zampini   ierr = MatAIJGetParCSR_Private(C,&hC);CHKERRQ(ierr);
103820e1dc0dSstefano_zampini   ierr = MatHYPRE_ParCSR_RAP(hA,hB,hC,&hABC);CHKERRQ(ierr);
103920e1dc0dSstefano_zampini   ierr = MatCreateFromParCSR(hABC,MATAIJ,PETSC_OWN_POINTER,&E);CHKERRQ(ierr);
104020e1dc0dSstefano_zampini   ierr = MatHeaderMerge(D,&E);CHKERRQ(ierr);
104120e1dc0dSstefano_zampini   ierr = MatAIJRestoreParCSR_Private(A,&hA);CHKERRQ(ierr);
104220e1dc0dSstefano_zampini   ierr = MatAIJRestoreParCSR_Private(B,&hB);CHKERRQ(ierr);
104320e1dc0dSstefano_zampini   ierr = MatAIJRestoreParCSR_Private(C,&hC);CHKERRQ(ierr);
104420e1dc0dSstefano_zampini   PetscFunctionReturn(0);
104520e1dc0dSstefano_zampini }
104620e1dc0dSstefano_zampini 
10474222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatTransposeMatMatMultSymbolic_AIJ_AIJ_AIJ_wHYPRE(Mat A,Mat B,Mat C,PetscReal fill,Mat D)
104820e1dc0dSstefano_zampini {
104920e1dc0dSstefano_zampini   PetscErrorCode ierr;
105020e1dc0dSstefano_zampini 
105120e1dc0dSstefano_zampini   PetscFunctionBegin;
10524222ddf1SHong Zhang   ierr = MatSetType(D,MATAIJ);CHKERRQ(ierr);
105320e1dc0dSstefano_zampini   PetscFunctionReturn(0);
105420e1dc0dSstefano_zampini }
105520e1dc0dSstefano_zampini 
10564222ddf1SHong Zhang /* ---------------------------------------------------- */
10574222ddf1SHong Zhang static PetscErrorCode MatProductSymbolic_AB_HYPRE(Mat C)
10584222ddf1SHong Zhang {
10594222ddf1SHong Zhang   PetscFunctionBegin;
10604222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_AB;
10614222ddf1SHong Zhang   PetscFunctionReturn(0);
10624222ddf1SHong Zhang }
10634222ddf1SHong Zhang 
10644222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_HYPRE_AB(Mat C)
10654222ddf1SHong Zhang {
10664222ddf1SHong Zhang   PetscErrorCode ierr;
10674222ddf1SHong Zhang   Mat_Product    *product = C->product;
10684222ddf1SHong Zhang   PetscBool      Ahypre;
10694222ddf1SHong Zhang 
10704222ddf1SHong Zhang   PetscFunctionBegin;
10714222ddf1SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)product->A,MATHYPRE,&Ahypre);CHKERRQ(ierr);
10724222ddf1SHong Zhang   if (Ahypre) { /* A is a Hypre matrix */
10734222ddf1SHong Zhang     ierr = MatSetType(C,MATHYPRE);CHKERRQ(ierr);
10744222ddf1SHong Zhang     C->ops->productsymbolic = MatProductSymbolic_AB_HYPRE;
10754222ddf1SHong Zhang     C->ops->matmultnumeric  = MatMatMultNumeric_HYPRE_HYPRE;
10764222ddf1SHong Zhang     PetscFunctionReturn(0);
10776718818eSStefano Zampini   }
10784222ddf1SHong Zhang   PetscFunctionReturn(0);
10794222ddf1SHong Zhang }
10804222ddf1SHong Zhang 
10814222ddf1SHong Zhang static PetscErrorCode MatProductSymbolic_PtAP_HYPRE(Mat C)
10824222ddf1SHong Zhang {
10834222ddf1SHong Zhang   PetscFunctionBegin;
10844222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
10854222ddf1SHong Zhang   PetscFunctionReturn(0);
10864222ddf1SHong Zhang }
10874222ddf1SHong Zhang 
10884222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_HYPRE_PtAP(Mat C)
10894222ddf1SHong Zhang {
10904222ddf1SHong Zhang   PetscErrorCode ierr;
10914222ddf1SHong Zhang   Mat_Product    *product = C->product;
10924222ddf1SHong Zhang   PetscBool      flg;
10934222ddf1SHong Zhang   PetscInt       type = 0;
10944222ddf1SHong Zhang   const char     *outTypes[4] = {"aij","seqaij","mpiaij","hypre"};
10954222ddf1SHong Zhang   PetscInt       ntype = 4;
10964222ddf1SHong Zhang   Mat            A = product->A;
10974222ddf1SHong Zhang   PetscBool      Ahypre;
10984222ddf1SHong Zhang 
10994222ddf1SHong Zhang   PetscFunctionBegin;
11004222ddf1SHong Zhang   ierr = PetscObjectTypeCompare((PetscObject)A,MATHYPRE,&Ahypre);CHKERRQ(ierr);
11014222ddf1SHong Zhang   if (Ahypre) { /* A is a Hypre matrix */
11024222ddf1SHong Zhang     ierr = MatSetType(C,MATHYPRE);CHKERRQ(ierr);
11034222ddf1SHong Zhang     C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE;
11044222ddf1SHong Zhang     C->ops->ptapnumeric     = MatPtAPNumeric_HYPRE_HYPRE;
11054222ddf1SHong Zhang     PetscFunctionReturn(0);
11064222ddf1SHong Zhang   }
11074222ddf1SHong Zhang 
11084222ddf1SHong Zhang   /* A is AIJ, P is Hypre, C = PtAP can be either AIJ or Hypre format */
11094222ddf1SHong Zhang   /* Get runtime option */
11104222ddf1SHong Zhang   if (product->api_user) {
11114222ddf1SHong Zhang     ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)C),((PetscObject)C)->prefix,"MatPtAP_HYPRE","Mat");CHKERRQ(ierr);
11124222ddf1SHong Zhang     ierr = PetscOptionsEList("-matptap_hypre_outtype","MatPtAP outtype","MatPtAP outtype",outTypes,ntype,outTypes[type],&type,&flg);CHKERRQ(ierr);
11134222ddf1SHong Zhang     ierr = PetscOptionsEnd();CHKERRQ(ierr);
11144222ddf1SHong Zhang   } else {
11154222ddf1SHong Zhang     ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)C),((PetscObject)C)->prefix,"MatProduct_PtAP_HYPRE","Mat");CHKERRQ(ierr);
11164222ddf1SHong Zhang     ierr = PetscOptionsEList("-matproduct_ptap_hypre_outtype","MatProduct_PtAP outtype","MatProduct_PtAP",outTypes,ntype,outTypes[type],&type,&flg);CHKERRQ(ierr);
11174222ddf1SHong Zhang     ierr = PetscOptionsEnd();CHKERRQ(ierr);
11184222ddf1SHong Zhang   }
11194222ddf1SHong Zhang 
11204222ddf1SHong Zhang   if (type == 0 || type == 1 || type == 2) {
11214222ddf1SHong Zhang     ierr = MatSetType(C,MATAIJ);CHKERRQ(ierr);
11224222ddf1SHong Zhang   } else if (type == 3) {
11234222ddf1SHong Zhang     ierr = MatSetType(C,MATHYPRE);CHKERRQ(ierr);
11244222ddf1SHong Zhang   } else SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_SUP,"MatPtAP outtype is not supported");
11254222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_PtAP_HYPRE;
11264222ddf1SHong Zhang   C->ops->ptapnumeric     = MatPtAPNumeric_AIJ_HYPRE;
11274222ddf1SHong Zhang   PetscFunctionReturn(0);
11284222ddf1SHong Zhang }
11294222ddf1SHong Zhang 
11304222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_HYPRE(Mat C)
11314222ddf1SHong Zhang {
11324222ddf1SHong Zhang   PetscErrorCode ierr;
11334222ddf1SHong Zhang   Mat_Product    *product = C->product;
11344222ddf1SHong Zhang 
11354222ddf1SHong Zhang   PetscFunctionBegin;
11364222ddf1SHong Zhang   switch (product->type) {
11374222ddf1SHong Zhang   case MATPRODUCT_AB:
11384222ddf1SHong Zhang     ierr = MatProductSetFromOptions_HYPRE_AB(C);CHKERRQ(ierr);
11394222ddf1SHong Zhang     break;
11404222ddf1SHong Zhang   case MATPRODUCT_PtAP:
11414222ddf1SHong Zhang     ierr = MatProductSetFromOptions_HYPRE_PtAP(C);CHKERRQ(ierr);
11424222ddf1SHong Zhang     break;
11436718818eSStefano Zampini   default:
11446718818eSStefano Zampini     break;
11454222ddf1SHong Zhang   }
11464222ddf1SHong Zhang   PetscFunctionReturn(0);
11474222ddf1SHong Zhang }
11484222ddf1SHong Zhang 
11494222ddf1SHong Zhang /* -------------------------------------------------------- */
11504222ddf1SHong Zhang 
1151ea9daf28SStefano Zampini static PetscErrorCode MatMultTranspose_HYPRE(Mat A, Vec x, Vec y)
115263c07aadSStefano Zampini {
115363c07aadSStefano Zampini   PetscErrorCode ierr;
115463c07aadSStefano Zampini 
115563c07aadSStefano Zampini   PetscFunctionBegin;
1156414bd5c3SStefano Zampini   ierr = MatHYPRE_MultKernel_Private(A,1.0,x,0.0,y,PETSC_TRUE);CHKERRQ(ierr);
115763c07aadSStefano Zampini   PetscFunctionReturn(0);
115863c07aadSStefano Zampini }
115963c07aadSStefano Zampini 
1160ea9daf28SStefano Zampini static PetscErrorCode MatMult_HYPRE(Mat A, Vec x, Vec y)
116163c07aadSStefano Zampini {
116263c07aadSStefano Zampini   PetscErrorCode ierr;
116363c07aadSStefano Zampini 
116463c07aadSStefano Zampini   PetscFunctionBegin;
1165414bd5c3SStefano Zampini   ierr = MatHYPRE_MultKernel_Private(A,1.0,x,0.0,y,PETSC_FALSE);CHKERRQ(ierr);
116663c07aadSStefano Zampini   PetscFunctionReturn(0);
116763c07aadSStefano Zampini }
116863c07aadSStefano Zampini 
1169414bd5c3SStefano Zampini static PetscErrorCode MatMultAdd_HYPRE(Mat A, Vec x, Vec y, Vec z)
1170414bd5c3SStefano Zampini {
1171414bd5c3SStefano Zampini   PetscErrorCode ierr;
1172414bd5c3SStefano Zampini 
1173414bd5c3SStefano Zampini   PetscFunctionBegin;
1174414bd5c3SStefano Zampini   if (y != z) {
1175414bd5c3SStefano Zampini     ierr = VecCopy(y,z);CHKERRQ(ierr);
1176414bd5c3SStefano Zampini   }
1177414bd5c3SStefano Zampini   ierr = MatHYPRE_MultKernel_Private(A,1.0,x,1.0,z,PETSC_FALSE);CHKERRQ(ierr);
1178414bd5c3SStefano Zampini   PetscFunctionReturn(0);
1179414bd5c3SStefano Zampini }
1180414bd5c3SStefano Zampini 
1181414bd5c3SStefano Zampini static PetscErrorCode MatMultTransposeAdd_HYPRE(Mat A, Vec x, Vec y, Vec z)
1182414bd5c3SStefano Zampini {
1183414bd5c3SStefano Zampini   PetscErrorCode ierr;
1184414bd5c3SStefano Zampini 
1185414bd5c3SStefano Zampini   PetscFunctionBegin;
1186414bd5c3SStefano Zampini   if (y != z) {
1187414bd5c3SStefano Zampini     ierr = VecCopy(y,z);CHKERRQ(ierr);
1188414bd5c3SStefano Zampini   }
1189414bd5c3SStefano Zampini   ierr = MatHYPRE_MultKernel_Private(A,1.0,x,1.0,z,PETSC_TRUE);CHKERRQ(ierr);
1190414bd5c3SStefano Zampini   PetscFunctionReturn(0);
1191414bd5c3SStefano Zampini }
1192414bd5c3SStefano Zampini 
1193414bd5c3SStefano Zampini /* y = a * A * x + b * y or y = a * A^t * x + b * y depending on trans */
119439accc25SStefano Zampini static PetscErrorCode MatHYPRE_MultKernel_Private(Mat A, HYPRE_Complex a, Vec x, HYPRE_Complex b, Vec y, PetscBool trans)
119563c07aadSStefano Zampini {
119663c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE*)A->data;
119763c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
119863c07aadSStefano Zampini   hypre_ParVector    *hx,*hy;
119963c07aadSStefano Zampini   PetscErrorCode     ierr;
120063c07aadSStefano Zampini 
120163c07aadSStefano Zampini   PetscFunctionBegin;
120263c07aadSStefano Zampini   if (trans) {
12036ea7df73SStefano Zampini     ierr = VecHYPRE_IJVectorPushVecRead(hA->b,x);CHKERRQ(ierr);
12046ea7df73SStefano Zampini     if (b != 0.0) { ierr = VecHYPRE_IJVectorPushVec(hA->x,y);CHKERRQ(ierr); }
12056ea7df73SStefano Zampini     else { ierr = VecHYPRE_IJVectorPushVecWrite(hA->x,y);CHKERRQ(ierr); }
12066ea7df73SStefano Zampini     PetscStackCallStandard(HYPRE_IJVectorGetObject,(hA->b->ij,(void**)&hx));
12076ea7df73SStefano Zampini     PetscStackCallStandard(HYPRE_IJVectorGetObject,(hA->x->ij,(void**)&hy));
120863c07aadSStefano Zampini   } else {
12096ea7df73SStefano Zampini     ierr = VecHYPRE_IJVectorPushVecRead(hA->x,x);CHKERRQ(ierr);
12106ea7df73SStefano Zampini     if (b != 0.0) { ierr = VecHYPRE_IJVectorPushVec(hA->b,y);CHKERRQ(ierr); }
12116ea7df73SStefano Zampini     else { ierr = VecHYPRE_IJVectorPushVecWrite(hA->b,y);CHKERRQ(ierr); }
12126ea7df73SStefano Zampini     PetscStackCallStandard(HYPRE_IJVectorGetObject,(hA->x->ij,(void**)&hx));
12136ea7df73SStefano Zampini     PetscStackCallStandard(HYPRE_IJVectorGetObject,(hA->b->ij,(void**)&hy));
121463c07aadSStefano Zampini   }
12156ea7df73SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&parcsr));
12166ea7df73SStefano Zampini   if (trans) {
12176ea7df73SStefano Zampini     PetscStackCallStandard(hypre_ParCSRMatrixMatvecT,(a,parcsr,hx,b,hy));
12186ea7df73SStefano Zampini   } else {
12196ea7df73SStefano Zampini     PetscStackCallStandard(hypre_ParCSRMatrixMatvec,(a,parcsr,hx,b,hy));
12206ea7df73SStefano Zampini   }
12216ea7df73SStefano Zampini   ierr = VecHYPRE_IJVectorPopVec(hA->x);CHKERRQ(ierr);
12226ea7df73SStefano Zampini   ierr = VecHYPRE_IJVectorPopVec(hA->b);CHKERRQ(ierr);
122363c07aadSStefano Zampini   PetscFunctionReturn(0);
122463c07aadSStefano Zampini }
122563c07aadSStefano Zampini 
1226ea9daf28SStefano Zampini static PetscErrorCode MatDestroy_HYPRE(Mat A)
122763c07aadSStefano Zampini {
122863c07aadSStefano Zampini   Mat_HYPRE      *hA = (Mat_HYPRE*)A->data;
122963c07aadSStefano Zampini   PetscErrorCode ierr;
123063c07aadSStefano Zampini 
123163c07aadSStefano Zampini   PetscFunctionBegin;
12326ea7df73SStefano Zampini   ierr = VecHYPRE_IJVectorDestroy(&hA->x);CHKERRQ(ierr);
12336ea7df73SStefano Zampini   ierr = VecHYPRE_IJVectorDestroy(&hA->b);CHKERRQ(ierr);
1234978814f1SStefano Zampini   if (hA->ij) {
1235978814f1SStefano Zampini     if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL;
1236978814f1SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixDestroy,(hA->ij));
1237978814f1SStefano Zampini   }
1238ffc4695bSBarry Smith   if (hA->comm) {ierr = MPI_Comm_free(&hA->comm);CHKERRMPI(ierr);}
1239c69f721fSFande Kong 
1240c69f721fSFande Kong   ierr = MatStashDestroy_Private(&A->stash);CHKERRQ(ierr);
1241c69f721fSFande Kong 
1242c69f721fSFande Kong   ierr = PetscFree(hA->array);CHKERRQ(ierr);
1243c69f721fSFande Kong 
124463c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_hypre_aij_C",NULL);CHKERRQ(ierr);
12452df22349SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_hypre_is_C",NULL);CHKERRQ(ierr);
12464222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_hypre_C",NULL);CHKERRQ(ierr);
12474222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_mpiaij_hypre_C",NULL);CHKERRQ(ierr);
1248d975228cSstefano_zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatHYPRESetPreallocation_C",NULL);CHKERRQ(ierr);
1249dd9c0a25Sstefano_zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatHYPREGetParCSR_C",NULL);CHKERRQ(ierr);
125063c07aadSStefano Zampini   ierr = PetscFree(A->data);CHKERRQ(ierr);
125163c07aadSStefano Zampini   PetscFunctionReturn(0);
125263c07aadSStefano Zampini }
125363c07aadSStefano Zampini 
1254ea9daf28SStefano Zampini static PetscErrorCode MatSetUp_HYPRE(Mat A)
125563c07aadSStefano Zampini {
12564ec6421dSstefano_zampini   PetscErrorCode ierr;
12574ec6421dSstefano_zampini 
12584ec6421dSstefano_zampini   PetscFunctionBegin;
12594ec6421dSstefano_zampini   ierr = MatHYPRESetPreallocation(A,PETSC_DEFAULT,NULL,PETSC_DEFAULT,NULL);CHKERRQ(ierr);
12604ec6421dSstefano_zampini   PetscFunctionReturn(0);
12614ec6421dSstefano_zampini }
12624ec6421dSstefano_zampini 
12636ea7df73SStefano Zampini //TODO FIX hypre_CSRMatrixMatvecOutOfPlace
12646ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
12656ea7df73SStefano Zampini static PetscErrorCode MatBindToCPU_HYPRE(Mat A, PetscBool bind)
12666ea7df73SStefano Zampini {
12676ea7df73SStefano Zampini   Mat_HYPRE            *hA = (Mat_HYPRE*)A->data;
12686ea7df73SStefano Zampini   HYPRE_MemoryLocation hmem = bind ? HYPRE_MEMORY_HOST : HYPRE_MEMORY_DEVICE;
12696ea7df73SStefano Zampini   PetscErrorCode       ierr;
12706ea7df73SStefano Zampini 
12716ea7df73SStefano Zampini   PetscFunctionBegin;
12726ea7df73SStefano Zampini   A->boundtocpu = bind;
12736ea7df73SStefano Zampini   if (hypre_IJMatrixAssembleFlag(hA->ij) && hmem != hypre_IJMatrixMemoryLocation(hA->ij)) {
12746ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
12756ea7df73SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&parcsr));
12766ea7df73SStefano Zampini     PetscStackCallStandard(hypre_ParCSRMatrixMigrate,(parcsr, hmem));
12776ea7df73SStefano Zampini   }
12786ea7df73SStefano Zampini   if (hA->x) { ierr  = VecHYPRE_IJBindToCPU(hA->x,bind);CHKERRQ(ierr); }
12796ea7df73SStefano Zampini   if (hA->b) { ierr  = VecHYPRE_IJBindToCPU(hA->b,bind);CHKERRQ(ierr); }
12806ea7df73SStefano Zampini   PetscFunctionReturn(0);
12816ea7df73SStefano Zampini }
12826ea7df73SStefano Zampini #endif
12836ea7df73SStefano Zampini 
12844ec6421dSstefano_zampini static PetscErrorCode MatAssemblyEnd_HYPRE(Mat A, MatAssemblyType mode)
12854ec6421dSstefano_zampini {
128663c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE*)A->data;
1287c69f721fSFande Kong   PetscMPIInt        n;
1288c69f721fSFande Kong   PetscInt           i,j,rstart,ncols,flg;
1289c69f721fSFande Kong   PetscInt           *row,*col;
1290c69f721fSFande Kong   PetscScalar        *val;
129163c07aadSStefano Zampini   PetscErrorCode     ierr;
129263c07aadSStefano Zampini 
129363c07aadSStefano Zampini   PetscFunctionBegin;
12944ec6421dSstefano_zampini   if (mode == MAT_FLUSH_ASSEMBLY) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MAT_FLUSH_ASSEMBLY currently not supported with MATHYPRE");
1295c69f721fSFande Kong 
1296c69f721fSFande Kong   if (!A->nooffprocentries) {
1297c69f721fSFande Kong     while (1) {
1298c69f721fSFande Kong       ierr = MatStashScatterGetMesg_Private(&A->stash,&n,&row,&col,&val,&flg);CHKERRQ(ierr);
1299c69f721fSFande Kong       if (!flg) break;
1300c69f721fSFande Kong 
1301c69f721fSFande Kong       for (i=0; i<n;) {
1302c69f721fSFande Kong         /* Now identify the consecutive vals belonging to the same row */
1303c69f721fSFande Kong         for (j=i,rstart=row[j]; j<n; j++) {
1304c69f721fSFande Kong           if (row[j] != rstart) break;
1305c69f721fSFande Kong         }
1306c69f721fSFande Kong         if (j < n) ncols = j-i;
1307c69f721fSFande Kong         else       ncols = n-i;
1308c69f721fSFande Kong         /* Now assemble all these values with a single function call */
1309c69f721fSFande Kong         ierr = MatSetValues_HYPRE(A,1,row+i,ncols,col+i,val+i,A->insertmode);CHKERRQ(ierr);
1310c69f721fSFande Kong 
1311c69f721fSFande Kong         i = j;
1312c69f721fSFande Kong       }
1313c69f721fSFande Kong     }
1314c69f721fSFande Kong     ierr = MatStashScatterEnd_Private(&A->stash);CHKERRQ(ierr);
1315c69f721fSFande Kong   }
1316c69f721fSFande Kong 
13174ec6421dSstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixAssemble,(hA->ij));
1318336664bdSPierre Jolivet   /* The assembly routine destroys the aux_matrix, we recreate it here by calling HYPRE_IJMatrixInitialize */
1319336664bdSPierre 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 */
1320336664bdSPierre Jolivet   if (!hA->sorted_full) {
1321af1cf968SStefano Zampini     hypre_AuxParCSRMatrix *aux_matrix;
1322af1cf968SStefano Zampini 
1323af1cf968SStefano Zampini     /* call destroy just to make sure we do not leak anything */
1324af1cf968SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(hA->ij);
1325af1cf968SStefano Zampini     PetscStackCallStandard(hypre_AuxParCSRMatrixDestroy,(aux_matrix));
1326af1cf968SStefano Zampini     hypre_IJMatrixTranslator(hA->ij) = NULL;
1327af1cf968SStefano Zampini 
1328af1cf968SStefano Zampini     /* Initialize with assembled flag -> it only recreates the aux_par_matrix */
1329af1cf968SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixInitialize,(hA->ij));
1330af1cf968SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(hA->ij);
13316ea7df73SStefano Zampini     if (aux_matrix) {
1332af1cf968SStefano Zampini       hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1; /* see comment in MatHYPRESetPreallocation_HYPRE */
133322235d61SPierre Jolivet #if PETSC_PKG_HYPRE_VERSION_LT(2,19,0)
1334af1cf968SStefano Zampini       PetscStackCallStandard(hypre_AuxParCSRMatrixInitialize,(aux_matrix));
133522235d61SPierre Jolivet #else
133622235d61SPierre Jolivet       PetscStackCallStandard(hypre_AuxParCSRMatrixInitialize_v2,(aux_matrix,HYPRE_MEMORY_HOST));
133722235d61SPierre Jolivet #endif
1338af1cf968SStefano Zampini     }
13396ea7df73SStefano Zampini   }
13406ea7df73SStefano Zampini   {
13416ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
13426ea7df73SStefano Zampini 
13436ea7df73SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&parcsr));
13446ea7df73SStefano Zampini     if (!hypre_ParCSRMatrixCommPkg(parcsr)) PetscStackCallStandard(hypre_MatvecCommPkgCreate,(parcsr));
13456ea7df73SStefano Zampini   }
13466ea7df73SStefano Zampini   if (!hA->x) { ierr = VecHYPRE_IJVectorCreate(A->cmap,&hA->x);CHKERRQ(ierr); }
13476ea7df73SStefano Zampini   if (!hA->b) { ierr = VecHYPRE_IJVectorCreate(A->rmap,&hA->b);CHKERRQ(ierr); }
13486ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
13496ea7df73SStefano Zampini   ierr = MatBindToCPU_HYPRE(A,A->boundtocpu);CHKERRQ(ierr);
13506ea7df73SStefano Zampini #endif
135163c07aadSStefano Zampini   PetscFunctionReturn(0);
135263c07aadSStefano Zampini }
135363c07aadSStefano Zampini 
1354c69f721fSFande Kong static PetscErrorCode MatGetArray_HYPRE(Mat A, PetscInt size, void **array)
1355c69f721fSFande Kong {
1356c69f721fSFande Kong   Mat_HYPRE          *hA = (Mat_HYPRE*)A->data;
1357c69f721fSFande Kong   PetscErrorCode     ierr;
1358c69f721fSFande Kong 
1359c69f721fSFande Kong   PetscFunctionBegin;
1360c69f721fSFande Kong   if (!hA->available) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Temporary space is in use");
1361c69f721fSFande Kong 
136239accc25SStefano Zampini   if (hA->size >= size) {
136339accc25SStefano Zampini     *array = hA->array;
136439accc25SStefano Zampini   } else {
1365c69f721fSFande Kong     ierr = PetscFree(hA->array);CHKERRQ(ierr);
1366c69f721fSFande Kong     hA->size = size;
1367c69f721fSFande Kong     ierr = PetscMalloc(hA->size,&hA->array);CHKERRQ(ierr);
1368c69f721fSFande Kong     *array = hA->array;
1369c69f721fSFande Kong   }
1370c69f721fSFande Kong 
1371c69f721fSFande Kong   hA->available = PETSC_FALSE;
1372c69f721fSFande Kong   PetscFunctionReturn(0);
1373c69f721fSFande Kong }
1374c69f721fSFande Kong 
1375708542d2SFande Kong static PetscErrorCode MatRestoreArray_HYPRE(Mat A, void **array)
1376c69f721fSFande Kong {
1377c69f721fSFande Kong   Mat_HYPRE          *hA = (Mat_HYPRE*)A->data;
1378c69f721fSFande Kong 
1379c69f721fSFande Kong   PetscFunctionBegin;
1380c69f721fSFande Kong   *array = NULL;
1381c69f721fSFande Kong   hA->available = PETSC_TRUE;
1382c69f721fSFande Kong   PetscFunctionReturn(0);
1383c69f721fSFande Kong }
1384c69f721fSFande Kong 
13856ea7df73SStefano Zampini static PetscErrorCode MatSetValues_HYPRE(Mat A, PetscInt nr, const PetscInt rows[], PetscInt nc, const PetscInt cols[], const PetscScalar v[], InsertMode ins)
1386d975228cSstefano_zampini {
1387d975228cSstefano_zampini   Mat_HYPRE      *hA = (Mat_HYPRE*)A->data;
1388d975228cSstefano_zampini   PetscScalar    *vals = (PetscScalar *)v;
138939accc25SStefano Zampini   HYPRE_Complex  *sscr;
1390c69f721fSFande Kong   PetscInt       *cscr[2];
1391c69f721fSFande Kong   PetscInt       i,nzc;
139208defe43SFande Kong   void           *array = NULL;
1393d975228cSstefano_zampini   PetscErrorCode ierr;
1394d975228cSstefano_zampini 
1395d975228cSstefano_zampini   PetscFunctionBegin;
139639accc25SStefano Zampini   ierr = MatGetArray_HYPRE(A,sizeof(PetscInt)*(2*nc)+sizeof(HYPRE_Complex)*nc*nr,&array);CHKERRQ(ierr);
1397c69f721fSFande Kong   cscr[0] = (PetscInt*)array;
1398c69f721fSFande Kong   cscr[1] = ((PetscInt*)array)+nc;
139939accc25SStefano Zampini   sscr = (HYPRE_Complex*)(((PetscInt*)array)+nc*2);
1400d975228cSstefano_zampini   for (i=0,nzc=0;i<nc;i++) {
1401d975228cSstefano_zampini     if (cols[i] >= 0) {
1402d975228cSstefano_zampini       cscr[0][nzc  ] = cols[i];
1403d975228cSstefano_zampini       cscr[1][nzc++] = i;
1404d975228cSstefano_zampini     }
1405d975228cSstefano_zampini   }
1406c69f721fSFande Kong   if (!nzc) {
1407708542d2SFande Kong     ierr = MatRestoreArray_HYPRE(A,&array);CHKERRQ(ierr);
1408c69f721fSFande Kong     PetscFunctionReturn(0);
1409c69f721fSFande Kong   }
1410d975228cSstefano_zampini 
14116ea7df73SStefano Zampini #if 0 //defined(PETSC_HAVE_HYPRE_DEVICE)
14126ea7df73SStefano Zampini   if (HYPRE_MEMORY_HOST != hypre_IJMatrixMemoryLocation(hA->ij)) {
14136ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
14146ea7df73SStefano Zampini 
14156ea7df73SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&parcsr));
14166ea7df73SStefano Zampini     PetscStackCallStandard(hypre_ParCSRMatrixMigrate,(parcsr, HYPRE_MEMORY_HOST));
14176ea7df73SStefano Zampini   }
14186ea7df73SStefano Zampini #endif
14196ea7df73SStefano Zampini 
1420d975228cSstefano_zampini   if (ins == ADD_VALUES) {
1421d975228cSstefano_zampini     for (i=0;i<nr;i++) {
14226ea7df73SStefano Zampini       if (rows[i] >= 0) {
1423d975228cSstefano_zampini         PetscInt  j;
14242cf14000SStefano Zampini         HYPRE_Int hnc = (HYPRE_Int)nzc;
14252cf14000SStefano Zampini 
14262cf14000SStefano Zampini         if ((PetscInt)hnc != nzc) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Hypre overflow! number of columns %D for row %D",nzc,rows[i]);
14271e1ea65dSPierre Jolivet         for (j=0;j<nzc;j++) { ierr = PetscHYPREScalarCast(vals[cscr[1][j]],&sscr[j]);CHKERRQ(ierr); }
14282cf14000SStefano Zampini         PetscStackCallStandard(HYPRE_IJMatrixAddToValues,(hA->ij,1,&hnc,(HYPRE_BigInt*)(rows+i),(HYPRE_BigInt*)cscr[0],sscr));
1429d975228cSstefano_zampini       }
1430d975228cSstefano_zampini       vals += nc;
1431d975228cSstefano_zampini     }
1432d975228cSstefano_zampini   } else { /* INSERT_VALUES */
1433d975228cSstefano_zampini     PetscInt rst,ren;
1434c69f721fSFande Kong 
1435c6698e78SStefano Zampini     ierr = MatGetOwnershipRange(A,&rst,&ren);CHKERRQ(ierr);
1436d975228cSstefano_zampini     for (i=0;i<nr;i++) {
14376ea7df73SStefano Zampini       if (rows[i] >= 0) {
1438d975228cSstefano_zampini         PetscInt  j;
14392cf14000SStefano Zampini         HYPRE_Int hnc = (HYPRE_Int)nzc;
14402cf14000SStefano Zampini 
14412cf14000SStefano Zampini         if ((PetscInt)hnc != nzc) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Hypre overflow! number of columns %D for row %D",nzc,rows[i]);
14421e1ea65dSPierre Jolivet         for (j=0;j<nzc;j++) { ierr = PetscHYPREScalarCast(vals[cscr[1][j]],&sscr[j]);CHKERRQ(ierr); }
1443c69f721fSFande Kong         /* nonlocal values */
144439accc25SStefano Zampini         if (rows[i] < rst || rows[i] >= ren) { ierr = MatStashValuesRow_Private(&A->stash,rows[i],nzc,cscr[0],(PetscScalar*)sscr,PETSC_FALSE);CHKERRQ(ierr); }
1445c69f721fSFande Kong         /* local values */
14462cf14000SStefano Zampini         else PetscStackCallStandard(HYPRE_IJMatrixSetValues,(hA->ij,1,&hnc,(HYPRE_BigInt*)(rows+i),(HYPRE_BigInt*)cscr[0],sscr));
1447d975228cSstefano_zampini       }
1448d975228cSstefano_zampini       vals += nc;
1449d975228cSstefano_zampini     }
1450d975228cSstefano_zampini   }
1451c69f721fSFande Kong 
1452708542d2SFande Kong   ierr = MatRestoreArray_HYPRE(A,&array);CHKERRQ(ierr);
1453d975228cSstefano_zampini   PetscFunctionReturn(0);
1454d975228cSstefano_zampini }
1455d975228cSstefano_zampini 
1456d975228cSstefano_zampini static PetscErrorCode MatHYPRESetPreallocation_HYPRE(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[])
1457d975228cSstefano_zampini {
1458d975228cSstefano_zampini   Mat_HYPRE      *hA = (Mat_HYPRE*)A->data;
14597d968826Sstefano_zampini   HYPRE_Int      *hdnnz,*honnz;
146006a29025Sstefano_zampini   PetscInt       i,rs,re,cs,ce,bs;
1461d975228cSstefano_zampini   PetscMPIInt    size;
1462d975228cSstefano_zampini   PetscErrorCode ierr;
1463d975228cSstefano_zampini 
1464d975228cSstefano_zampini   PetscFunctionBegin;
146506a29025Sstefano_zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
1466d975228cSstefano_zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1467d975228cSstefano_zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1468d975228cSstefano_zampini   rs   = A->rmap->rstart;
1469d975228cSstefano_zampini   re   = A->rmap->rend;
1470d975228cSstefano_zampini   cs   = A->cmap->rstart;
1471d975228cSstefano_zampini   ce   = A->cmap->rend;
1472d975228cSstefano_zampini   if (!hA->ij) {
1473d975228cSstefano_zampini     PetscStackCallStandard(HYPRE_IJMatrixCreate,(hA->comm,rs,re-1,cs,ce-1,&hA->ij));
1474d975228cSstefano_zampini     PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(hA->ij,HYPRE_PARCSR));
1475d975228cSstefano_zampini   } else {
14762cf14000SStefano Zampini     HYPRE_BigInt hrs,hre,hcs,hce;
1477d975228cSstefano_zampini     PetscStackCallStandard(HYPRE_IJMatrixGetLocalRange,(hA->ij,&hrs,&hre,&hcs,&hce));
14782cf14000SStefano 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);
14792cf14000SStefano 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);
1480d975228cSstefano_zampini   }
148106a29025Sstefano_zampini   if (dnz == PETSC_DEFAULT || dnz == PETSC_DECIDE) dnz = 10*bs;
148206a29025Sstefano_zampini   if (onz == PETSC_DEFAULT || onz == PETSC_DECIDE) onz = 10*bs;
148306a29025Sstefano_zampini 
1484d975228cSstefano_zampini   if (!dnnz) {
1485d975228cSstefano_zampini     ierr = PetscMalloc1(A->rmap->n,&hdnnz);CHKERRQ(ierr);
1486d975228cSstefano_zampini     for (i=0;i<A->rmap->n;i++) hdnnz[i] = dnz;
1487d975228cSstefano_zampini   } else {
14887d968826Sstefano_zampini     hdnnz = (HYPRE_Int*)dnnz;
1489d975228cSstefano_zampini   }
1490ffc4695bSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRMPI(ierr);
1491d975228cSstefano_zampini   if (size > 1) {
1492ddbeb582SStefano Zampini     hypre_AuxParCSRMatrix *aux_matrix;
1493d975228cSstefano_zampini     if (!onnz) {
1494d975228cSstefano_zampini       ierr = PetscMalloc1(A->rmap->n,&honnz);CHKERRQ(ierr);
1495d975228cSstefano_zampini       for (i=0;i<A->rmap->n;i++) honnz[i] = onz;
149622235d61SPierre Jolivet     } else honnz = (HYPRE_Int*)onnz;
1497ddbeb582SStefano Zampini     /* SetDiagOffdSizes sets hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0, since it seems
1498ddbeb582SStefano Zampini        they assume the user will input the entire row values, properly sorted
1499336664bdSPierre Jolivet        In PETSc, we don't make such an assumption and set this flag to 1,
1500336664bdSPierre Jolivet        unless the option MAT_SORTED_FULL is set to true.
1501ddbeb582SStefano Zampini        Also, to avoid possible memory leaks, we destroy and recreate the translator
1502ddbeb582SStefano Zampini        This has to be done here, as HYPRE_IJMatrixInitialize will properly initialize
1503ddbeb582SStefano Zampini        the IJ matrix for us */
1504ddbeb582SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(hA->ij);
1505ddbeb582SStefano Zampini     hypre_AuxParCSRMatrixDestroy(aux_matrix);
1506ddbeb582SStefano Zampini     hypre_IJMatrixTranslator(hA->ij) = NULL;
1507d975228cSstefano_zampini     PetscStackCallStandard(HYPRE_IJMatrixSetDiagOffdSizes,(hA->ij,hdnnz,honnz));
1508ddbeb582SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(hA->ij);
1509336664bdSPierre Jolivet     hypre_AuxParCSRMatrixNeedAux(aux_matrix) = !hA->sorted_full;
1510d975228cSstefano_zampini   } else {
1511d975228cSstefano_zampini     honnz = NULL;
1512d975228cSstefano_zampini     PetscStackCallStandard(HYPRE_IJMatrixSetRowSizes,(hA->ij,hdnnz));
1513d975228cSstefano_zampini   }
1514ddbeb582SStefano Zampini 
1515af1cf968SStefano Zampini   /* reset assembled flag and call the initialize method */
1516af1cf968SStefano Zampini   hypre_IJMatrixAssembleFlag(hA->ij) = 0;
15176ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2,19,0)
1518ddbeb582SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixInitialize,(hA->ij));
15196ea7df73SStefano Zampini #else
15206ea7df73SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixInitialize_v2,(hA->ij,HYPRE_MEMORY_HOST));
15216ea7df73SStefano Zampini #endif
1522d975228cSstefano_zampini   if (!dnnz) {
1523d975228cSstefano_zampini     ierr = PetscFree(hdnnz);CHKERRQ(ierr);
1524d975228cSstefano_zampini   }
1525d975228cSstefano_zampini   if (!onnz && honnz) {
1526d975228cSstefano_zampini     ierr = PetscFree(honnz);CHKERRQ(ierr);
1527d975228cSstefano_zampini   }
1528af1cf968SStefano Zampini   /* Match AIJ logic */
152906a29025Sstefano_zampini   A->preallocated = PETSC_TRUE;
1530af1cf968SStefano Zampini   A->assembled    = PETSC_FALSE;
1531d975228cSstefano_zampini   PetscFunctionReturn(0);
1532d975228cSstefano_zampini }
1533d975228cSstefano_zampini 
1534d975228cSstefano_zampini /*@C
1535d975228cSstefano_zampini    MatHYPRESetPreallocation - Preallocates memory for a sparse parallel matrix in HYPRE IJ format
1536d975228cSstefano_zampini 
1537d975228cSstefano_zampini    Collective on Mat
1538d975228cSstefano_zampini 
1539d975228cSstefano_zampini    Input Parameters:
1540d975228cSstefano_zampini +  A - the matrix
1541d975228cSstefano_zampini .  dnz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1542d975228cSstefano_zampini           (same value is used for all local rows)
1543d975228cSstefano_zampini .  dnnz - array containing the number of nonzeros in the various rows of the
1544d975228cSstefano_zampini           DIAGONAL portion of the local submatrix (possibly different for each row)
1545d975228cSstefano_zampini           or NULL (PETSC_NULL_INTEGER in Fortran), if d_nz is used to specify the nonzero structure.
1546d975228cSstefano_zampini           The size of this array is equal to the number of local rows, i.e 'm'.
1547d975228cSstefano_zampini           For matrices that will be factored, you must leave room for (and set)
1548d975228cSstefano_zampini           the diagonal entry even if it is zero.
1549d975228cSstefano_zampini .  onz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1550d975228cSstefano_zampini           submatrix (same value is used for all local rows).
1551d975228cSstefano_zampini -  onnz - array containing the number of nonzeros in the various rows of the
1552d975228cSstefano_zampini           OFF-DIAGONAL portion of the local submatrix (possibly different for
1553d975228cSstefano_zampini           each row) or NULL (PETSC_NULL_INTEGER in Fortran), if o_nz is used to specify the nonzero
1554d975228cSstefano_zampini           structure. The size of this array is equal to the number
1555d975228cSstefano_zampini           of local rows, i.e 'm'.
1556d975228cSstefano_zampini 
155795452b02SPatrick Sanan    Notes:
155895452b02SPatrick Sanan     If the *nnz parameter is given then the *nz parameter is ignored; for sequential matrices, onz and onnz are ignored.
1559d975228cSstefano_zampini 
1560d975228cSstefano_zampini    Level: intermediate
1561d975228cSstefano_zampini 
1562af1cf968SStefano Zampini .seealso: MatCreate(), MatMPIAIJSetPreallocation(), MATHYPRE
1563d975228cSstefano_zampini @*/
1564d975228cSstefano_zampini PetscErrorCode MatHYPRESetPreallocation(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[])
1565d975228cSstefano_zampini {
1566d975228cSstefano_zampini   PetscErrorCode ierr;
1567d975228cSstefano_zampini 
1568d975228cSstefano_zampini   PetscFunctionBegin;
1569d975228cSstefano_zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
1570d975228cSstefano_zampini   PetscValidType(A,1);
1571d975228cSstefano_zampini   ierr = PetscTryMethod(A,"MatHYPRESetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(A,dnz,dnnz,onz,onnz));CHKERRQ(ierr);
1572d975228cSstefano_zampini   PetscFunctionReturn(0);
1573d975228cSstefano_zampini }
1574d975228cSstefano_zampini 
1575225daaf8SStefano Zampini /*
1576225daaf8SStefano Zampini    MatCreateFromParCSR - Creates a matrix from a hypre_ParCSRMatrix
1577225daaf8SStefano Zampini 
1578225daaf8SStefano Zampini    Collective
1579225daaf8SStefano Zampini 
1580225daaf8SStefano Zampini    Input Parameters:
158145b8d346SStefano Zampini +  parcsr   - the pointer to the hypre_ParCSRMatrix
1582bb4689ddSStefano Zampini .  mtype    - matrix type to be created. Currently MATAIJ, MATIS and MATHYPRE are supported.
1583225daaf8SStefano Zampini -  copymode - PETSc copying options
1584225daaf8SStefano Zampini 
1585225daaf8SStefano Zampini    Output Parameter:
1586225daaf8SStefano Zampini .  A  - the matrix
1587225daaf8SStefano Zampini 
1588225daaf8SStefano Zampini    Level: intermediate
1589225daaf8SStefano Zampini 
1590225daaf8SStefano Zampini .seealso: MatHYPRE, PetscCopyMode
1591225daaf8SStefano Zampini */
159245b8d346SStefano Zampini PETSC_EXTERN PetscErrorCode MatCreateFromParCSR(hypre_ParCSRMatrix *parcsr, MatType mtype, PetscCopyMode copymode, Mat* A)
1593978814f1SStefano Zampini {
1594225daaf8SStefano Zampini   Mat            T;
1595978814f1SStefano Zampini   Mat_HYPRE      *hA;
1596978814f1SStefano Zampini   MPI_Comm       comm;
1597978814f1SStefano Zampini   PetscInt       rstart,rend,cstart,cend,M,N;
1598d248a85cSRichard Tran Mills   PetscBool      isseqaij,isseqaijmkl,ismpiaij,isaij,ishyp,isis;
1599978814f1SStefano Zampini   PetscErrorCode ierr;
1600978814f1SStefano Zampini 
1601978814f1SStefano Zampini   PetscFunctionBegin;
1602978814f1SStefano Zampini   comm  = hypre_ParCSRMatrixComm(parcsr);
1603225daaf8SStefano Zampini   ierr  = PetscStrcmp(mtype,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
1604d248a85cSRichard Tran Mills   ierr  = PetscStrcmp(mtype,MATSEQAIJMKL,&isseqaijmkl);CHKERRQ(ierr);
1605225daaf8SStefano Zampini   ierr  = PetscStrcmp(mtype,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
1606225daaf8SStefano Zampini   ierr  = PetscStrcmp(mtype,MATAIJ,&isaij);CHKERRQ(ierr);
1607225daaf8SStefano Zampini   ierr  = PetscStrcmp(mtype,MATHYPRE,&ishyp);CHKERRQ(ierr);
16088cfe8d00SStefano Zampini   ierr  = PetscStrcmp(mtype,MATIS,&isis);CHKERRQ(ierr);
1609d248a85cSRichard Tran Mills   isaij = (PetscBool)(isseqaij || isseqaijmkl || ismpiaij || isaij);
16106ea7df73SStefano Zampini   /* TODO */
1611d248a85cSRichard 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);
1612978814f1SStefano Zampini   /* access ParCSRMatrix */
1613978814f1SStefano Zampini   rstart = hypre_ParCSRMatrixFirstRowIndex(parcsr);
1614978814f1SStefano Zampini   rend   = hypre_ParCSRMatrixLastRowIndex(parcsr);
1615978814f1SStefano Zampini   cstart = hypre_ParCSRMatrixFirstColDiag(parcsr);
1616978814f1SStefano Zampini   cend   = hypre_ParCSRMatrixLastColDiag(parcsr);
1617978814f1SStefano Zampini   M      = hypre_ParCSRMatrixGlobalNumRows(parcsr);
1618978814f1SStefano Zampini   N      = hypre_ParCSRMatrixGlobalNumCols(parcsr);
1619978814f1SStefano Zampini 
1620fa92c42cSstefano_zampini   /* fix for empty local rows/columns */
1621fa92c42cSstefano_zampini   if (rend < rstart) rend = rstart;
1622fa92c42cSstefano_zampini   if (cend < cstart) cend = cstart;
1623fa92c42cSstefano_zampini 
1624e6471dc9SStefano Zampini   /* PETSc convention */
1625e6471dc9SStefano Zampini   rend++;
1626e6471dc9SStefano Zampini   cend++;
1627e6471dc9SStefano Zampini   rend = PetscMin(rend,M);
1628e6471dc9SStefano Zampini   cend = PetscMin(cend,N);
1629e6471dc9SStefano Zampini 
1630978814f1SStefano Zampini   /* create PETSc matrix with MatHYPRE */
1631225daaf8SStefano Zampini   ierr = MatCreate(comm,&T);CHKERRQ(ierr);
1632e6471dc9SStefano Zampini   ierr = MatSetSizes(T,rend-rstart,cend-cstart,M,N);CHKERRQ(ierr);
1633225daaf8SStefano Zampini   ierr = MatSetType(T,MATHYPRE);CHKERRQ(ierr);
1634225daaf8SStefano Zampini   hA   = (Mat_HYPRE*)(T->data);
1635978814f1SStefano Zampini 
1636978814f1SStefano Zampini   /* create HYPRE_IJMatrix */
1637978814f1SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixCreate,(hA->comm,rstart,rend-1,cstart,cend-1,&hA->ij));
163845b8d346SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(hA->ij,HYPRE_PARCSR));
163945b8d346SStefano Zampini 
16406ea7df73SStefano Zampini // TODO DEV
164145b8d346SStefano Zampini   /* create new ParCSR object if needed */
164245b8d346SStefano Zampini   if (ishyp && copymode == PETSC_COPY_VALUES) {
164345b8d346SStefano Zampini     hypre_ParCSRMatrix *new_parcsr;
16446ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2,18,0)
164545b8d346SStefano Zampini     hypre_CSRMatrix    *hdiag,*hoffd,*ndiag,*noffd;
164645b8d346SStefano Zampini 
16470e6427aaSSatish Balay     new_parcsr = hypre_ParCSRMatrixClone(parcsr,0);
164845b8d346SStefano Zampini     hdiag      = hypre_ParCSRMatrixDiag(parcsr);
164945b8d346SStefano Zampini     hoffd      = hypre_ParCSRMatrixOffd(parcsr);
165045b8d346SStefano Zampini     ndiag      = hypre_ParCSRMatrixDiag(new_parcsr);
165145b8d346SStefano Zampini     noffd      = hypre_ParCSRMatrixOffd(new_parcsr);
1652580bdb30SBarry Smith     ierr       = PetscArraycpy(hypre_CSRMatrixData(ndiag),hypre_CSRMatrixData(hdiag),hypre_CSRMatrixNumNonzeros(hdiag));CHKERRQ(ierr);
1653580bdb30SBarry Smith     ierr       = PetscArraycpy(hypre_CSRMatrixData(noffd),hypre_CSRMatrixData(hoffd),hypre_CSRMatrixNumNonzeros(hoffd));CHKERRQ(ierr);
16546ea7df73SStefano Zampini #else
16556ea7df73SStefano Zampini     new_parcsr = hypre_ParCSRMatrixClone(parcsr,1);
16566ea7df73SStefano Zampini #endif
165745b8d346SStefano Zampini     parcsr     = new_parcsr;
165845b8d346SStefano Zampini     copymode   = PETSC_OWN_POINTER;
165945b8d346SStefano Zampini   }
1660978814f1SStefano Zampini 
1661978814f1SStefano Zampini   /* set ParCSR object */
1662978814f1SStefano Zampini   hypre_IJMatrixObject(hA->ij) = parcsr;
16634ec6421dSstefano_zampini   T->preallocated = PETSC_TRUE;
1664978814f1SStefano Zampini 
1665978814f1SStefano Zampini   /* set assembled flag */
1666978814f1SStefano Zampini   hypre_IJMatrixAssembleFlag(hA->ij) = 1;
16676ea7df73SStefano Zampini #if 0
1668978814f1SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixInitialize,(hA->ij));
16696ea7df73SStefano Zampini #endif
1670225daaf8SStefano Zampini   if (ishyp) {
16716d2a658fSstefano_zampini     PetscMPIInt myid = 0;
16726d2a658fSstefano_zampini 
16736d2a658fSstefano_zampini     /* make sure we always have row_starts and col_starts available */
16746d2a658fSstefano_zampini     if (HYPRE_AssumedPartitionCheck()) {
1675ffc4695bSBarry Smith       ierr = MPI_Comm_rank(comm,&myid);CHKERRMPI(ierr);
16766d2a658fSstefano_zampini     }
1677a1d2239cSSatish Balay #if defined(hypre_ParCSRMatrixOwnsRowStarts)
16786d2a658fSstefano_zampini     if (!hypre_ParCSRMatrixOwnsColStarts(parcsr)) {
16796d2a658fSstefano_zampini       PetscLayout map;
16806d2a658fSstefano_zampini 
16816d2a658fSstefano_zampini       ierr = MatGetLayouts(T,NULL,&map);CHKERRQ(ierr);
16826d2a658fSstefano_zampini       ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
16832cf14000SStefano Zampini       hypre_ParCSRMatrixColStarts(parcsr) = (HYPRE_BigInt*)(map->range + myid);
16846d2a658fSstefano_zampini     }
16856d2a658fSstefano_zampini     if (!hypre_ParCSRMatrixOwnsRowStarts(parcsr)) {
16866d2a658fSstefano_zampini       PetscLayout map;
16876d2a658fSstefano_zampini 
16886d2a658fSstefano_zampini       ierr = MatGetLayouts(T,&map,NULL);CHKERRQ(ierr);
16896d2a658fSstefano_zampini       ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
16902cf14000SStefano Zampini       hypre_ParCSRMatrixRowStarts(parcsr) = (HYPRE_BigInt*)(map->range + myid);
16916d2a658fSstefano_zampini     }
1692a1d2239cSSatish Balay #endif
1693978814f1SStefano Zampini     /* prevent from freeing the pointer */
1694978814f1SStefano Zampini     if (copymode == PETSC_USE_POINTER) hA->inner_free = PETSC_FALSE;
1695225daaf8SStefano Zampini     *A   = T;
16966ea7df73SStefano Zampini     ierr = MatSetOption(*A,MAT_SORTED_FULL,PETSC_TRUE);CHKERRQ(ierr);
1697978814f1SStefano Zampini     ierr = MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1698978814f1SStefano Zampini     ierr = MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1699bb4689ddSStefano Zampini   } else if (isaij) {
1700bb4689ddSStefano Zampini     if (copymode != PETSC_OWN_POINTER) {
1701225daaf8SStefano Zampini       /* prevent from freeing the pointer */
1702225daaf8SStefano Zampini       hA->inner_free = PETSC_FALSE;
1703225daaf8SStefano Zampini       ierr = MatConvert_HYPRE_AIJ(T,MATAIJ,MAT_INITIAL_MATRIX,A);CHKERRQ(ierr);
1704225daaf8SStefano Zampini       ierr = MatDestroy(&T);CHKERRQ(ierr);
1705225daaf8SStefano Zampini     } else { /* AIJ return type with PETSC_OWN_POINTER */
1706225daaf8SStefano Zampini       ierr = MatConvert_HYPRE_AIJ(T,MATAIJ,MAT_INPLACE_MATRIX,&T);CHKERRQ(ierr);
1707225daaf8SStefano Zampini       *A   = T;
1708225daaf8SStefano Zampini     }
1709bb4689ddSStefano Zampini   } else if (isis) {
17108cfe8d00SStefano Zampini     ierr = MatConvert_HYPRE_IS(T,MATIS,MAT_INITIAL_MATRIX,A);CHKERRQ(ierr);
17118cfe8d00SStefano Zampini     if (copymode != PETSC_OWN_POINTER) hA->inner_free = PETSC_FALSE;
1712bb4689ddSStefano Zampini     ierr = MatDestroy(&T);CHKERRQ(ierr);
1713bb4689ddSStefano Zampini   }
1714978814f1SStefano Zampini   PetscFunctionReturn(0);
1715978814f1SStefano Zampini }
1716978814f1SStefano Zampini 
171768ec7858SStefano Zampini static PetscErrorCode MatHYPREGetParCSR_HYPRE(Mat A, hypre_ParCSRMatrix **parcsr)
1718dd9c0a25Sstefano_zampini {
1719dd9c0a25Sstefano_zampini   Mat_HYPRE *hA = (Mat_HYPRE*)A->data;
1720dd9c0a25Sstefano_zampini   HYPRE_Int type;
1721dd9c0a25Sstefano_zampini 
1722dd9c0a25Sstefano_zampini   PetscFunctionBegin;
1723dd9c0a25Sstefano_zampini   if (!hA->ij) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"HYPRE_IJMatrix not present");
1724dd9c0a25Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type));
1725dd9c0a25Sstefano_zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"HYPRE_IJMatrix is not of type HYPRE_PARCSR");
1726dd9c0a25Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)parcsr));
1727dd9c0a25Sstefano_zampini   PetscFunctionReturn(0);
1728dd9c0a25Sstefano_zampini }
1729dd9c0a25Sstefano_zampini 
1730dd9c0a25Sstefano_zampini /*
1731dd9c0a25Sstefano_zampini    MatHYPREGetParCSR - Gets the pointer to the ParCSR matrix
1732dd9c0a25Sstefano_zampini 
1733dd9c0a25Sstefano_zampini    Not collective
1734dd9c0a25Sstefano_zampini 
1735dd9c0a25Sstefano_zampini    Input Parameters:
1736dd9c0a25Sstefano_zampini +  A  - the MATHYPRE object
1737dd9c0a25Sstefano_zampini 
1738dd9c0a25Sstefano_zampini    Output Parameter:
1739dd9c0a25Sstefano_zampini .  parcsr  - the pointer to the hypre_ParCSRMatrix
1740dd9c0a25Sstefano_zampini 
1741dd9c0a25Sstefano_zampini    Level: intermediate
1742dd9c0a25Sstefano_zampini 
1743dd9c0a25Sstefano_zampini .seealso: MatHYPRE, PetscCopyMode
1744dd9c0a25Sstefano_zampini */
1745dd9c0a25Sstefano_zampini PetscErrorCode MatHYPREGetParCSR(Mat A, hypre_ParCSRMatrix **parcsr)
1746dd9c0a25Sstefano_zampini {
1747dd9c0a25Sstefano_zampini   PetscErrorCode ierr;
1748dd9c0a25Sstefano_zampini 
1749dd9c0a25Sstefano_zampini   PetscFunctionBegin;
1750dd9c0a25Sstefano_zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
1751dd9c0a25Sstefano_zampini   PetscValidType(A,1);
1752dd9c0a25Sstefano_zampini   ierr = PetscUseMethod(A,"MatHYPREGetParCSR_C",(Mat,hypre_ParCSRMatrix**),(A,parcsr));CHKERRQ(ierr);
1753dd9c0a25Sstefano_zampini   PetscFunctionReturn(0);
1754dd9c0a25Sstefano_zampini }
1755dd9c0a25Sstefano_zampini 
175668ec7858SStefano Zampini static PetscErrorCode MatMissingDiagonal_HYPRE(Mat A, PetscBool *missing, PetscInt *dd)
175768ec7858SStefano Zampini {
175868ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
175968ec7858SStefano Zampini   hypre_CSRMatrix    *ha;
176068ec7858SStefano Zampini   PetscInt           rst;
176168ec7858SStefano Zampini   PetscErrorCode     ierr;
176268ec7858SStefano Zampini 
176368ec7858SStefano Zampini   PetscFunctionBegin;
176468ec7858SStefano Zampini   if (A->rmap->n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented with non-square diagonal blocks");
176568ec7858SStefano Zampini   ierr = MatGetOwnershipRange(A,&rst,NULL);CHKERRQ(ierr);
176668ec7858SStefano Zampini   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
176768ec7858SStefano Zampini   if (missing) *missing = PETSC_FALSE;
176868ec7858SStefano Zampini   if (dd) *dd = -1;
176968ec7858SStefano Zampini   ha = hypre_ParCSRMatrixDiag(parcsr);
177068ec7858SStefano Zampini   if (ha) {
177168299464SStefano Zampini     PetscInt  size,i;
177268299464SStefano Zampini     HYPRE_Int *ii,*jj;
177368ec7858SStefano Zampini 
177468ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
177568ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
177668ec7858SStefano Zampini     jj   = hypre_CSRMatrixJ(ha);
177768ec7858SStefano Zampini     for (i = 0; i < size; i++) {
177868ec7858SStefano Zampini       PetscInt  j;
177968ec7858SStefano Zampini       PetscBool found = PETSC_FALSE;
178068ec7858SStefano Zampini 
178168ec7858SStefano Zampini       for (j = ii[i]; j < ii[i+1] && !found; j++)
178268ec7858SStefano Zampini         found = (jj[j] == i) ? PETSC_TRUE : PETSC_FALSE;
178368ec7858SStefano Zampini 
178468ec7858SStefano Zampini       if (!found) {
178568ec7858SStefano Zampini         PetscInfo1(A,"Matrix is missing local diagonal entry %D\n",i);
178668ec7858SStefano Zampini         if (missing) *missing = PETSC_TRUE;
178768ec7858SStefano Zampini         if (dd) *dd = i+rst;
178868ec7858SStefano Zampini         PetscFunctionReturn(0);
178968ec7858SStefano Zampini       }
179068ec7858SStefano Zampini     }
179168ec7858SStefano Zampini     if (!size) {
179268ec7858SStefano Zampini       PetscInfo(A,"Matrix has no diagonal entries therefore is missing diagonal\n");
179368ec7858SStefano Zampini       if (missing) *missing = PETSC_TRUE;
179468ec7858SStefano Zampini       if (dd) *dd = rst;
179568ec7858SStefano Zampini     }
179668ec7858SStefano Zampini   } else {
179768ec7858SStefano Zampini     PetscInfo(A,"Matrix has no diagonal entries therefore is missing diagonal\n");
179868ec7858SStefano Zampini     if (missing) *missing = PETSC_TRUE;
179968ec7858SStefano Zampini     if (dd) *dd = rst;
180068ec7858SStefano Zampini   }
180168ec7858SStefano Zampini   PetscFunctionReturn(0);
180268ec7858SStefano Zampini }
180368ec7858SStefano Zampini 
180468ec7858SStefano Zampini static PetscErrorCode MatScale_HYPRE(Mat A, PetscScalar s)
180568ec7858SStefano Zampini {
180668ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
18076ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_LT(2,19,0)
180868ec7858SStefano Zampini   hypre_CSRMatrix    *ha;
18096ea7df73SStefano Zampini #endif
181068ec7858SStefano Zampini   PetscErrorCode     ierr;
181139accc25SStefano Zampini   HYPRE_Complex      hs;
181268ec7858SStefano Zampini 
181368ec7858SStefano Zampini   PetscFunctionBegin;
181439accc25SStefano Zampini   ierr = PetscHYPREScalarCast(s,&hs);CHKERRQ(ierr);
181568ec7858SStefano Zampini   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
18166ea7df73SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2,19,0)
18176ea7df73SStefano Zampini   PetscStackCallStandard(hypre_ParCSRMatrixScale,(parcsr,hs));
18186ea7df73SStefano Zampini #else  /* diagonal part */
181968ec7858SStefano Zampini   ha = hypre_ParCSRMatrixDiag(parcsr);
182068ec7858SStefano Zampini   if (ha) {
182168299464SStefano Zampini     PetscInt      size,i;
182268299464SStefano Zampini     HYPRE_Int     *ii;
182339accc25SStefano Zampini     HYPRE_Complex *a;
182468ec7858SStefano Zampini 
182568ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
182668ec7858SStefano Zampini     a    = hypre_CSRMatrixData(ha);
182768ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
182839accc25SStefano Zampini     for (i = 0; i < ii[size]; i++) a[i] *= hs;
182968ec7858SStefano Zampini   }
183068ec7858SStefano Zampini   /* offdiagonal part */
183168ec7858SStefano Zampini   ha = hypre_ParCSRMatrixOffd(parcsr);
183268ec7858SStefano Zampini   if (ha) {
183368299464SStefano Zampini     PetscInt      size,i;
183468299464SStefano Zampini     HYPRE_Int     *ii;
183539accc25SStefano Zampini     HYPRE_Complex *a;
183668ec7858SStefano Zampini 
183768ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
183868ec7858SStefano Zampini     a    = hypre_CSRMatrixData(ha);
183968ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
184039accc25SStefano Zampini     for (i = 0; i < ii[size]; i++) a[i] *= hs;
184168ec7858SStefano Zampini   }
18426ea7df73SStefano Zampini #endif
184368ec7858SStefano Zampini   PetscFunctionReturn(0);
184468ec7858SStefano Zampini }
184568ec7858SStefano Zampini 
184668ec7858SStefano Zampini static PetscErrorCode MatZeroRowsColumns_HYPRE(Mat A, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
184768ec7858SStefano Zampini {
184868ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
184968299464SStefano Zampini   HYPRE_Int          *lrows;
185068299464SStefano Zampini   PetscInt           rst,ren,i;
185168ec7858SStefano Zampini   PetscErrorCode     ierr;
185268ec7858SStefano Zampini 
185368ec7858SStefano Zampini   PetscFunctionBegin;
185468ec7858SStefano Zampini   if (x || b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"To be implemented");
185568ec7858SStefano Zampini   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
185668ec7858SStefano Zampini   ierr = PetscMalloc1(numRows,&lrows);CHKERRQ(ierr);
185768ec7858SStefano Zampini   ierr = MatGetOwnershipRange(A,&rst,&ren);CHKERRQ(ierr);
185868ec7858SStefano Zampini   for (i=0;i<numRows;i++) {
185968ec7858SStefano Zampini     if (rows[i] < rst || rows[i] >= ren)
186068ec7858SStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Non-local rows not yet supported");
186168ec7858SStefano Zampini     lrows[i] = rows[i] - rst;
186268ec7858SStefano Zampini   }
186368ec7858SStefano Zampini   PetscStackCallStandard(hypre_ParCSRMatrixEliminateRowsCols,(parcsr,numRows,lrows));
186468ec7858SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
186568ec7858SStefano Zampini   PetscFunctionReturn(0);
186668ec7858SStefano Zampini }
186768ec7858SStefano Zampini 
1868c69f721fSFande Kong static PetscErrorCode MatZeroEntries_HYPRE_CSRMatrix(hypre_CSRMatrix *ha)
1869c69f721fSFande Kong {
1870c69f721fSFande Kong   PetscErrorCode      ierr;
1871c69f721fSFande Kong 
1872c69f721fSFande Kong   PetscFunctionBegin;
1873c69f721fSFande Kong   if (ha) {
1874c69f721fSFande Kong     HYPRE_Int     *ii, size;
1875c69f721fSFande Kong     HYPRE_Complex *a;
1876c69f721fSFande Kong 
1877c69f721fSFande Kong     size = hypre_CSRMatrixNumRows(ha);
1878c69f721fSFande Kong     a    = hypre_CSRMatrixData(ha);
1879c69f721fSFande Kong     ii   = hypre_CSRMatrixI(ha);
1880c69f721fSFande Kong 
1881580bdb30SBarry Smith     if (a) {ierr = PetscArrayzero(a,ii[size]);CHKERRQ(ierr);}
1882c69f721fSFande Kong   }
1883c69f721fSFande Kong   PetscFunctionReturn(0);
1884c69f721fSFande Kong }
1885c69f721fSFande Kong 
1886c69f721fSFande Kong PetscErrorCode MatZeroEntries_HYPRE(Mat A)
1887c69f721fSFande Kong {
18886ea7df73SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE*)A->data;
18896ea7df73SStefano Zampini 
18906ea7df73SStefano Zampini   PetscFunctionBegin;
18916ea7df73SStefano Zampini   if (HYPRE_MEMORY_DEVICE == hypre_IJMatrixMemoryLocation(hA->ij)) {
18926ea7df73SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixSetConstantValues,(hA->ij,0.0));
18936ea7df73SStefano Zampini   } else {
1894c69f721fSFande Kong     hypre_ParCSRMatrix *parcsr;
1895c69f721fSFande Kong     PetscErrorCode     ierr;
1896c69f721fSFande Kong 
1897c69f721fSFande Kong     ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
1898c69f721fSFande Kong     ierr = MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr));CHKERRQ(ierr);
1899c69f721fSFande Kong     ierr = MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr));CHKERRQ(ierr);
19006ea7df73SStefano Zampini   }
1901c69f721fSFande Kong   PetscFunctionReturn(0);
1902c69f721fSFande Kong }
1903c69f721fSFande Kong 
190439accc25SStefano Zampini static PetscErrorCode MatZeroRows_HYPRE_CSRMatrix(hypre_CSRMatrix *hA,PetscInt N,const PetscInt rows[],HYPRE_Complex diag)
1905c69f721fSFande Kong {
190639accc25SStefano Zampini   PetscInt        ii;
190739accc25SStefano Zampini   HYPRE_Int       *i, *j;
190839accc25SStefano Zampini   HYPRE_Complex   *a;
1909c69f721fSFande Kong 
1910c69f721fSFande Kong   PetscFunctionBegin;
1911c69f721fSFande Kong   if (!hA) PetscFunctionReturn(0);
1912c69f721fSFande Kong 
191339accc25SStefano Zampini   i = hypre_CSRMatrixI(hA);
191439accc25SStefano Zampini   j = hypre_CSRMatrixJ(hA);
1915c69f721fSFande Kong   a = hypre_CSRMatrixData(hA);
1916c69f721fSFande Kong 
1917c69f721fSFande Kong   for (ii = 0; ii < N; ii++) {
191839accc25SStefano Zampini     HYPRE_Int jj, ibeg, iend, irow;
191939accc25SStefano Zampini 
1920c69f721fSFande Kong     irow = rows[ii];
1921c69f721fSFande Kong     ibeg = i[irow];
1922c69f721fSFande Kong     iend = i[irow+1];
1923c69f721fSFande Kong     for (jj = ibeg; jj < iend; jj++)
1924c69f721fSFande Kong       if (j[jj] == irow) a[jj] = diag;
1925c69f721fSFande Kong       else a[jj] = 0.0;
1926c69f721fSFande Kong    }
1927c69f721fSFande Kong    PetscFunctionReturn(0);
1928c69f721fSFande Kong }
1929c69f721fSFande Kong 
1930ddbeb582SStefano Zampini static PetscErrorCode MatZeroRows_HYPRE(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1931c69f721fSFande Kong {
1932c69f721fSFande Kong   hypre_ParCSRMatrix  *parcsr;
1933c69f721fSFande Kong   PetscInt            *lrows,len;
193439accc25SStefano Zampini   HYPRE_Complex       hdiag;
1935c69f721fSFande Kong   PetscErrorCode      ierr;
1936c69f721fSFande Kong 
1937c69f721fSFande Kong   PetscFunctionBegin;
1938c6698e78SStefano Zampini   if (x || b) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Does not support to modify the solution and the right hand size");
193939accc25SStefano Zampini   ierr = PetscHYPREScalarCast(diag,&hdiag);CHKERRQ(ierr);
1940c69f721fSFande Kong   /* retrieve the internal matrix */
1941c69f721fSFande Kong   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
1942c69f721fSFande Kong   /* get locally owned rows */
1943c69f721fSFande Kong   ierr = MatZeroRowsMapLocal_Private(A,N,rows,&len,&lrows);CHKERRQ(ierr);
1944c69f721fSFande Kong   /* zero diagonal part */
194539accc25SStefano Zampini   ierr = MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr),len,lrows,hdiag);CHKERRQ(ierr);
1946c69f721fSFande Kong   /* zero off-diagonal part */
1947c69f721fSFande Kong   ierr = MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr),len,lrows,0.0);CHKERRQ(ierr);
1948c69f721fSFande Kong 
1949c69f721fSFande Kong   ierr = PetscFree(lrows);CHKERRQ(ierr);
1950c69f721fSFande Kong   PetscFunctionReturn(0);
1951c69f721fSFande Kong }
1952c69f721fSFande Kong 
1953ddbeb582SStefano Zampini static PetscErrorCode MatAssemblyBegin_HYPRE(Mat mat,MatAssemblyType mode)
1954c69f721fSFande Kong {
1955c69f721fSFande Kong   PetscErrorCode ierr;
1956c69f721fSFande Kong 
1957c69f721fSFande Kong   PetscFunctionBegin;
1958c69f721fSFande Kong   if (mat->nooffprocentries) PetscFunctionReturn(0);
1959c69f721fSFande Kong 
1960c69f721fSFande Kong   ierr = MatStashScatterBegin_Private(mat,&mat->stash,mat->rmap->range);CHKERRQ(ierr);
1961c69f721fSFande Kong   PetscFunctionReturn(0);
1962c69f721fSFande Kong }
1963c69f721fSFande Kong 
1964ddbeb582SStefano Zampini static PetscErrorCode MatGetRow_HYPRE(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
1965c69f721fSFande Kong {
1966c69f721fSFande Kong   hypre_ParCSRMatrix  *parcsr;
19672cf14000SStefano Zampini   HYPRE_Int           hnz;
1968c69f721fSFande Kong   PetscErrorCode      ierr;
1969c69f721fSFande Kong 
1970c69f721fSFande Kong   PetscFunctionBegin;
1971c69f721fSFande Kong   /* retrieve the internal matrix */
1972c69f721fSFande Kong   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
1973c69f721fSFande Kong   /* call HYPRE API */
197439accc25SStefano Zampini   PetscStackCallStandard(HYPRE_ParCSRMatrixGetRow,(parcsr,row,&hnz,(HYPRE_BigInt**)idx,(HYPRE_Complex**)v));
19752cf14000SStefano Zampini   if (nz) *nz = (PetscInt)hnz;
1976c69f721fSFande Kong   PetscFunctionReturn(0);
1977c69f721fSFande Kong }
1978c69f721fSFande Kong 
1979ddbeb582SStefano Zampini static PetscErrorCode MatRestoreRow_HYPRE(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
1980c69f721fSFande Kong {
1981c69f721fSFande Kong   hypre_ParCSRMatrix  *parcsr;
19822cf14000SStefano Zampini   HYPRE_Int           hnz;
1983c69f721fSFande Kong   PetscErrorCode      ierr;
1984c69f721fSFande Kong 
1985c69f721fSFande Kong   PetscFunctionBegin;
1986c69f721fSFande Kong   /* retrieve the internal matrix */
1987c69f721fSFande Kong   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
1988c69f721fSFande Kong   /* call HYPRE API */
19892cf14000SStefano Zampini   hnz = nz ? (HYPRE_Int)(*nz) : 0;
199039accc25SStefano Zampini   PetscStackCallStandard(HYPRE_ParCSRMatrixRestoreRow,(parcsr,row,&hnz,(HYPRE_BigInt**)idx,(HYPRE_Complex**)v));
1991c69f721fSFande Kong   PetscFunctionReturn(0);
1992c69f721fSFande Kong }
1993c69f721fSFande Kong 
1994ddbeb582SStefano Zampini static PetscErrorCode MatGetValues_HYPRE(Mat A,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],PetscScalar v[])
1995c69f721fSFande Kong {
199645b8d346SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE*)A->data;
1997c69f721fSFande Kong   PetscInt  i;
19981d4906efSStefano Zampini 
1999c69f721fSFande Kong   PetscFunctionBegin;
2000c69f721fSFande Kong   if (!m || !n) PetscFunctionReturn(0);
2001c69f721fSFande Kong   /* Ignore negative row indices
2002c69f721fSFande Kong    * And negative column indices should be automatically ignored in hypre
2003c69f721fSFande Kong    * */
20042cf14000SStefano Zampini   for (i=0; i<m; i++) {
20052cf14000SStefano Zampini     if (idxm[i] >= 0) {
20062cf14000SStefano Zampini       HYPRE_Int hn = (HYPRE_Int)n;
200739accc25SStefano Zampini       PetscStackCallStandard(HYPRE_IJMatrixGetValues,(hA->ij,1,&hn,(HYPRE_BigInt*)&idxm[i],(HYPRE_BigInt*)idxn,(HYPRE_Complex*)(v + i*n)));
20082cf14000SStefano Zampini     }
20092cf14000SStefano Zampini   }
2010c69f721fSFande Kong   PetscFunctionReturn(0);
2011c69f721fSFande Kong }
2012c69f721fSFande Kong 
2013ddbeb582SStefano Zampini static PetscErrorCode MatSetOption_HYPRE(Mat A,MatOption op,PetscBool flg)
2014ddbeb582SStefano Zampini {
2015ddbeb582SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE*)A->data;
2016ddbeb582SStefano Zampini 
2017ddbeb582SStefano Zampini   PetscFunctionBegin;
2018c6698e78SStefano Zampini   switch (op) {
2019ddbeb582SStefano Zampini   case MAT_NO_OFF_PROC_ENTRIES:
2020ddbeb582SStefano Zampini     if (flg) {
2021ddbeb582SStefano Zampini       PetscStackCallStandard(HYPRE_IJMatrixSetMaxOffProcElmts,(hA->ij,0));
2022ddbeb582SStefano Zampini     }
2023ddbeb582SStefano Zampini     break;
2024336664bdSPierre Jolivet   case MAT_SORTED_FULL:
2025336664bdSPierre Jolivet     hA->sorted_full = flg;
2026336664bdSPierre Jolivet     break;
2027ddbeb582SStefano Zampini   default:
2028ddbeb582SStefano Zampini     break;
2029ddbeb582SStefano Zampini   }
2030ddbeb582SStefano Zampini   PetscFunctionReturn(0);
2031ddbeb582SStefano Zampini }
2032c69f721fSFande Kong 
203345b8d346SStefano Zampini static PetscErrorCode MatView_HYPRE(Mat A, PetscViewer view)
203445b8d346SStefano Zampini {
203545b8d346SStefano Zampini   PetscErrorCode     ierr;
203645b8d346SStefano Zampini   PetscViewerFormat  format;
203745b8d346SStefano Zampini 
203845b8d346SStefano Zampini   PetscFunctionBegin;
203945b8d346SStefano Zampini   ierr = PetscViewerGetFormat(view,&format);CHKERRQ(ierr);
20406ea7df73SStefano Zampini   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(0);
204145b8d346SStefano Zampini   if (format != PETSC_VIEWER_NATIVE) {
20426ea7df73SStefano Zampini     Mat                B;
20436ea7df73SStefano Zampini     hypre_ParCSRMatrix *parcsr;
20446ea7df73SStefano Zampini     PetscErrorCode     (*mview)(Mat,PetscViewer) = NULL;
20456ea7df73SStefano Zampini 
204645b8d346SStefano Zampini     ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
204745b8d346SStefano Zampini     ierr = MatCreateFromParCSR(parcsr,MATAIJ,PETSC_USE_POINTER,&B);CHKERRQ(ierr);
204845b8d346SStefano Zampini     ierr = MatGetOperation(B,MATOP_VIEW,(void(**)(void))&mview);CHKERRQ(ierr);
20492758c9b9SBarry Smith     if (!mview) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Missing view operation");
205045b8d346SStefano Zampini     ierr = (*mview)(B,view);CHKERRQ(ierr);
205145b8d346SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
205245b8d346SStefano Zampini   } else {
205345b8d346SStefano Zampini     Mat_HYPRE  *hA = (Mat_HYPRE*)A->data;
205445b8d346SStefano Zampini     PetscMPIInt size;
205545b8d346SStefano Zampini     PetscBool   isascii;
205645b8d346SStefano Zampini     const char *filename;
205745b8d346SStefano Zampini 
205845b8d346SStefano Zampini     /* HYPRE uses only text files */
205945b8d346SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)view,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
206045b8d346SStefano Zampini     if (!isascii) SETERRQ1(PetscObjectComm((PetscObject)view),PETSC_ERR_SUP,"PetscViewerType %s: native HYPRE format needs PETSCVIEWERASCII",((PetscObject)view)->type_name);
206145b8d346SStefano Zampini     ierr = PetscViewerFileGetName(view,&filename);CHKERRQ(ierr);
206245b8d346SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixPrint,(hA->ij,filename));
2063ffc4695bSBarry Smith     ierr = MPI_Comm_size(hA->comm,&size);CHKERRMPI(ierr);
206445b8d346SStefano Zampini     if (size > 1) {
206545b8d346SStefano Zampini       ierr = PetscViewerASCIIPrintf(view,"Matrix files: %s.%05d ... %s.%05d\n",filename,0,filename,size-1);CHKERRQ(ierr);
206645b8d346SStefano Zampini     } else {
206745b8d346SStefano Zampini       ierr = PetscViewerASCIIPrintf(view,"Matrix file: %s.%05d\n",filename,0);CHKERRQ(ierr);
206845b8d346SStefano Zampini     }
206945b8d346SStefano Zampini   }
207045b8d346SStefano Zampini   PetscFunctionReturn(0);
207145b8d346SStefano Zampini }
207245b8d346SStefano Zampini 
207345b8d346SStefano Zampini static PetscErrorCode MatDuplicate_HYPRE(Mat A,MatDuplicateOption op, Mat *B)
207445b8d346SStefano Zampini {
20756abb4441SStefano Zampini   hypre_ParCSRMatrix *parcsr = NULL;
207645b8d346SStefano Zampini   PetscErrorCode     ierr;
207745b8d346SStefano Zampini   PetscCopyMode      cpmode;
207845b8d346SStefano Zampini 
207945b8d346SStefano Zampini   PetscFunctionBegin;
208045b8d346SStefano Zampini   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
208145b8d346SStefano Zampini   if (op == MAT_DO_NOT_COPY_VALUES || op == MAT_SHARE_NONZERO_PATTERN) {
20820e6427aaSSatish Balay     parcsr = hypre_ParCSRMatrixClone(parcsr,0);
208345b8d346SStefano Zampini     cpmode = PETSC_OWN_POINTER;
208445b8d346SStefano Zampini   } else {
208545b8d346SStefano Zampini     cpmode = PETSC_COPY_VALUES;
208645b8d346SStefano Zampini   }
208745b8d346SStefano Zampini   ierr = MatCreateFromParCSR(parcsr,MATHYPRE,cpmode,B);CHKERRQ(ierr);
208845b8d346SStefano Zampini   PetscFunctionReturn(0);
208945b8d346SStefano Zampini }
209045b8d346SStefano Zampini 
2091465edc17SStefano Zampini static PetscErrorCode MatCopy_HYPRE(Mat A, Mat B, MatStructure str)
2092465edc17SStefano Zampini {
2093465edc17SStefano Zampini   hypre_ParCSRMatrix *acsr,*bcsr;
2094465edc17SStefano Zampini   PetscErrorCode     ierr;
2095465edc17SStefano Zampini 
2096465edc17SStefano Zampini   PetscFunctionBegin;
2097465edc17SStefano Zampini   if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) {
2098465edc17SStefano Zampini     ierr = MatHYPREGetParCSR_HYPRE(A,&acsr);CHKERRQ(ierr);
2099465edc17SStefano Zampini     ierr = MatHYPREGetParCSR_HYPRE(B,&bcsr);CHKERRQ(ierr);
2100465edc17SStefano Zampini     PetscStackCallStandard(hypre_ParCSRMatrixCopy,(acsr,bcsr,1));
21011e1ea65dSPierre Jolivet     ierr = MatSetOption(B,MAT_SORTED_FULL,PETSC_TRUE);CHKERRQ(ierr); /* "perfect" preallocation, so no need for hypre_AuxParCSRMatrixNeedAux */
2102465edc17SStefano Zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2103465edc17SStefano Zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2104465edc17SStefano Zampini   } else {
2105465edc17SStefano Zampini     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
2106465edc17SStefano Zampini   }
2107465edc17SStefano Zampini   PetscFunctionReturn(0);
2108465edc17SStefano Zampini }
2109465edc17SStefano Zampini 
21106305df00SStefano Zampini static PetscErrorCode MatGetDiagonal_HYPRE(Mat A, Vec d)
21116305df00SStefano Zampini {
21126305df00SStefano Zampini   hypre_ParCSRMatrix *parcsr;
21136305df00SStefano Zampini   hypre_CSRMatrix    *dmat;
211439accc25SStefano Zampini   HYPRE_Complex      *a;
211539accc25SStefano Zampini   HYPRE_Complex      *data = NULL;
21162cf14000SStefano Zampini   HYPRE_Int          *diag = NULL;
21172cf14000SStefano Zampini   PetscInt           i;
21186305df00SStefano Zampini   PetscBool          cong;
21196305df00SStefano Zampini   PetscErrorCode     ierr;
21206305df00SStefano Zampini 
21216305df00SStefano Zampini   PetscFunctionBegin;
21226305df00SStefano Zampini   ierr = MatHasCongruentLayouts(A,&cong);CHKERRQ(ierr);
21236305df00SStefano Zampini   if (!cong) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only for square matrices with same local distributions of rows and columns");
212476bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
21256305df00SStefano Zampini     PetscBool miss;
21266305df00SStefano Zampini     ierr = MatMissingDiagonal(A,&miss,NULL);CHKERRQ(ierr);
21276305df00SStefano Zampini     if (miss && A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented when diagonal entries are missing");
21286305df00SStefano Zampini   }
21296305df00SStefano Zampini   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
21306305df00SStefano Zampini   dmat = hypre_ParCSRMatrixDiag(parcsr);
21316305df00SStefano Zampini   if (dmat) {
213239accc25SStefano Zampini     /* this cast fixes the clang error: implicit conversion from 'HYPRE_Complex' (aka '_Complex double') to 'double' is not permitted in C++ */
213339accc25SStefano Zampini     ierr = VecGetArray(d,(PetscScalar**)&a);CHKERRQ(ierr);
21342cf14000SStefano Zampini     diag = hypre_CSRMatrixI(dmat);
213539accc25SStefano Zampini     data = hypre_CSRMatrixData(dmat);
21366305df00SStefano Zampini     for (i=0;i<A->rmap->n;i++) a[i] = data[diag[i]];
213739accc25SStefano Zampini     ierr = VecRestoreArray(d,(PetscScalar**)&a);CHKERRQ(ierr);
21386305df00SStefano Zampini   }
21396305df00SStefano Zampini   PetscFunctionReturn(0);
21406305df00SStefano Zampini }
21416305df00SStefano Zampini 
2142363d496dSStefano Zampini #include <petscblaslapack.h>
2143363d496dSStefano Zampini 
2144363d496dSStefano Zampini static PetscErrorCode MatAXPY_HYPRE(Mat Y,PetscScalar a,Mat X,MatStructure str)
2145363d496dSStefano Zampini {
2146363d496dSStefano Zampini   PetscErrorCode ierr;
2147363d496dSStefano Zampini 
2148363d496dSStefano Zampini   PetscFunctionBegin;
21496ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
21506ea7df73SStefano Zampini   {
21516ea7df73SStefano Zampini     Mat                B;
21526ea7df73SStefano Zampini     hypre_ParCSRMatrix *x,*y,*z;
21536ea7df73SStefano Zampini 
21546ea7df73SStefano Zampini     ierr = MatHYPREGetParCSR(Y,&y);CHKERRQ(ierr);
21556ea7df73SStefano Zampini     ierr = MatHYPREGetParCSR(X,&x);CHKERRQ(ierr);
21566ea7df73SStefano Zampini     PetscStackCallStandard(hypre_ParCSRMatrixAdd,(1.0,y,1.0,x,&z));
21576ea7df73SStefano Zampini     ierr = MatCreateFromParCSR(z,MATHYPRE,PETSC_OWN_POINTER,&B);CHKERRQ(ierr);
21586ea7df73SStefano Zampini     ierr = MatHeaderMerge(Y,&B);CHKERRQ(ierr);
21596ea7df73SStefano Zampini   }
21606ea7df73SStefano Zampini #else
2161363d496dSStefano Zampini   if (str == SAME_NONZERO_PATTERN) {
2162363d496dSStefano Zampini     hypre_ParCSRMatrix *x,*y;
2163363d496dSStefano Zampini     hypre_CSRMatrix    *xloc,*yloc;
2164363d496dSStefano Zampini     PetscInt           xnnz,ynnz;
216539accc25SStefano Zampini     HYPRE_Complex      *xarr,*yarr;
2166363d496dSStefano Zampini     PetscBLASInt       one=1,bnz;
2167363d496dSStefano Zampini 
2168363d496dSStefano Zampini     ierr = MatHYPREGetParCSR(Y,&y);CHKERRQ(ierr);
2169363d496dSStefano Zampini     ierr = MatHYPREGetParCSR(X,&x);CHKERRQ(ierr);
2170363d496dSStefano Zampini 
2171363d496dSStefano Zampini     /* diagonal block */
2172363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixDiag(x);
2173363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixDiag(y);
2174363d496dSStefano Zampini     xnnz = 0;
2175363d496dSStefano Zampini     ynnz = 0;
2176363d496dSStefano Zampini     xarr = NULL;
2177363d496dSStefano Zampini     yarr = NULL;
2178363d496dSStefano Zampini     if (xloc) {
217939accc25SStefano Zampini       xarr = hypre_CSRMatrixData(xloc);
2180363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
2181363d496dSStefano Zampini     }
2182363d496dSStefano Zampini     if (yloc) {
218339accc25SStefano Zampini       yarr = hypre_CSRMatrixData(yloc);
2184363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
2185363d496dSStefano Zampini     }
2186363d496dSStefano Zampini     if (xnnz != ynnz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Different number of nonzeros in diagonal block %D != %D",xnnz,ynnz);
2187363d496dSStefano Zampini     ierr = PetscBLASIntCast(xnnz,&bnz);CHKERRQ(ierr);
218839accc25SStefano Zampini     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&a,(PetscScalar*)xarr,&one,(PetscScalar*)yarr,&one));
2189363d496dSStefano Zampini 
2190363d496dSStefano Zampini     /* off-diagonal block */
2191363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixOffd(x);
2192363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixOffd(y);
2193363d496dSStefano Zampini     xnnz = 0;
2194363d496dSStefano Zampini     ynnz = 0;
2195363d496dSStefano Zampini     xarr = NULL;
2196363d496dSStefano Zampini     yarr = NULL;
2197363d496dSStefano Zampini     if (xloc) {
219839accc25SStefano Zampini       xarr = hypre_CSRMatrixData(xloc);
2199363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
2200363d496dSStefano Zampini     }
2201363d496dSStefano Zampini     if (yloc) {
220239accc25SStefano Zampini       yarr = hypre_CSRMatrixData(yloc);
2203363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
2204363d496dSStefano Zampini     }
2205363d496dSStefano Zampini     if (xnnz != ynnz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Different number of nonzeros in off-diagonal block %D != %D",xnnz,ynnz);
2206363d496dSStefano Zampini     ierr = PetscBLASIntCast(xnnz,&bnz);CHKERRQ(ierr);
220739accc25SStefano Zampini     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&a,(PetscScalar*)xarr,&one,(PetscScalar*)yarr,&one));
2208363d496dSStefano Zampini   } else if (str == SUBSET_NONZERO_PATTERN) {
2209363d496dSStefano Zampini     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
2210363d496dSStefano Zampini   } else {
2211363d496dSStefano Zampini     Mat B;
2212363d496dSStefano Zampini 
2213363d496dSStefano Zampini     ierr = MatAXPY_Basic_Preallocate(Y,X,&B);CHKERRQ(ierr);
2214363d496dSStefano Zampini     ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr);
2215363d496dSStefano Zampini     ierr = MatHeaderReplace(Y,&B);CHKERRQ(ierr);
2216363d496dSStefano Zampini   }
22176ea7df73SStefano Zampini #endif
2218363d496dSStefano Zampini   PetscFunctionReturn(0);
2219363d496dSStefano Zampini }
2220363d496dSStefano Zampini 
2221a055b5aaSBarry Smith /*MC
2222a055b5aaSBarry Smith    MATHYPRE - MATHYPRE = "hypre" - A matrix type to be used for sequential and parallel sparse matrices
2223a055b5aaSBarry Smith           based on the hypre IJ interface.
2224a055b5aaSBarry Smith 
2225a055b5aaSBarry Smith    Level: intermediate
2226a055b5aaSBarry Smith 
2227a055b5aaSBarry Smith .seealso: MatCreate()
2228a055b5aaSBarry Smith M*/
2229a055b5aaSBarry Smith 
223063c07aadSStefano Zampini PETSC_EXTERN PetscErrorCode MatCreate_HYPRE(Mat B)
223163c07aadSStefano Zampini {
223263c07aadSStefano Zampini   Mat_HYPRE      *hB;
223363c07aadSStefano Zampini   PetscErrorCode ierr;
223463c07aadSStefano Zampini 
223563c07aadSStefano Zampini   PetscFunctionBegin;
223663c07aadSStefano Zampini   ierr = PetscNewLog(B,&hB);CHKERRQ(ierr);
22376ea7df73SStefano Zampini 
2238978814f1SStefano Zampini   hB->inner_free  = PETSC_TRUE;
2239c69f721fSFande Kong   hB->available   = PETSC_TRUE;
2240336664bdSPierre Jolivet   hB->sorted_full = PETSC_FALSE; /* no assumption whether column indices are sorted or not */
2241c69f721fSFande Kong   hB->size        = 0;
2242c69f721fSFande Kong   hB->array       = NULL;
2243978814f1SStefano Zampini 
224463c07aadSStefano Zampini   B->data       = (void*)hB;
224563c07aadSStefano Zampini   B->rmap->bs   = 1;
224663c07aadSStefano Zampini   B->assembled  = PETSC_FALSE;
224763c07aadSStefano Zampini 
2248de393100SStefano Zampini   ierr = PetscMemzero(B->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
224963c07aadSStefano Zampini   B->ops->mult                  = MatMult_HYPRE;
225063c07aadSStefano Zampini   B->ops->multtranspose         = MatMultTranspose_HYPRE;
2251414bd5c3SStefano Zampini   B->ops->multadd               = MatMultAdd_HYPRE;
2252414bd5c3SStefano Zampini   B->ops->multtransposeadd      = MatMultTransposeAdd_HYPRE;
225363c07aadSStefano Zampini   B->ops->setup                 = MatSetUp_HYPRE;
225463c07aadSStefano Zampini   B->ops->destroy               = MatDestroy_HYPRE;
225563c07aadSStefano Zampini   B->ops->assemblyend           = MatAssemblyEnd_HYPRE;
2256c69f721fSFande Kong   B->ops->assemblybegin         = MatAssemblyBegin_HYPRE;
2257d975228cSstefano_zampini   B->ops->setvalues             = MatSetValues_HYPRE;
225868ec7858SStefano Zampini   B->ops->missingdiagonal       = MatMissingDiagonal_HYPRE;
225968ec7858SStefano Zampini   B->ops->scale                 = MatScale_HYPRE;
226068ec7858SStefano Zampini   B->ops->zerorowscolumns       = MatZeroRowsColumns_HYPRE;
2261c69f721fSFande Kong   B->ops->zeroentries           = MatZeroEntries_HYPRE;
2262c69f721fSFande Kong   B->ops->zerorows              = MatZeroRows_HYPRE;
2263c69f721fSFande Kong   B->ops->getrow                = MatGetRow_HYPRE;
2264c69f721fSFande Kong   B->ops->restorerow            = MatRestoreRow_HYPRE;
2265c69f721fSFande Kong   B->ops->getvalues             = MatGetValues_HYPRE;
2266ddbeb582SStefano Zampini   B->ops->setoption             = MatSetOption_HYPRE;
226745b8d346SStefano Zampini   B->ops->duplicate             = MatDuplicate_HYPRE;
2268465edc17SStefano Zampini   B->ops->copy                  = MatCopy_HYPRE;
226945b8d346SStefano Zampini   B->ops->view                  = MatView_HYPRE;
22706305df00SStefano Zampini   B->ops->getdiagonal           = MatGetDiagonal_HYPRE;
2271363d496dSStefano Zampini   B->ops->axpy                  = MatAXPY_HYPRE;
22724222ddf1SHong Zhang   B->ops->productsetfromoptions = MatProductSetFromOptions_HYPRE;
22736ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
22746ea7df73SStefano Zampini   B->ops->bindtocpu             = MatBindToCPU_HYPRE;
22756ea7df73SStefano Zampini   B->boundtocpu                 = PETSC_FALSE;
22766ea7df73SStefano Zampini #endif
227745b8d346SStefano Zampini 
227845b8d346SStefano Zampini   /* build cache for off array entries formed */
227945b8d346SStefano Zampini   ierr = MatStashCreate_Private(PetscObjectComm((PetscObject)B),1,&B->stash);CHKERRQ(ierr);
228063c07aadSStefano Zampini 
2281ffc4695bSBarry Smith   ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)B),&hB->comm);CHKERRMPI(ierr);
228263c07aadSStefano Zampini   ierr = PetscObjectChangeTypeName((PetscObject)B,MATHYPRE);CHKERRQ(ierr);
228363c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_hypre_aij_C",MatConvert_HYPRE_AIJ);CHKERRQ(ierr);
22842df22349SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_hypre_is_C",MatConvert_HYPRE_IS);CHKERRQ(ierr);
22854222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_hypre_C",MatProductSetFromOptions_HYPRE);CHKERRQ(ierr);
22864222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_mpiaij_hypre_C",MatProductSetFromOptions_HYPRE);CHKERRQ(ierr);
2287d975228cSstefano_zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatHYPRESetPreallocation_C",MatHYPRESetPreallocation_HYPRE);CHKERRQ(ierr);
2288dd9c0a25Sstefano_zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatHYPREGetParCSR_C",MatHYPREGetParCSR_HYPRE);CHKERRQ(ierr);
22896ea7df73SStefano Zampini #if defined(PETSC_HAVE_HYPRE_DEVICE)
22906ea7df73SStefano Zampini #if defined(HYPRE_USING_HIP)
2291*a4af0ceeSJacob Faibussowitsch   ierr = PetscDeviceInitialize(PETSC_DEVICE_HIP);CHKERRQ(ierr);
22926ea7df73SStefano Zampini   ierr = MatSetVecType(B,VECHIP);CHKERRQ(ierr);
22936ea7df73SStefano Zampini #endif
22946ea7df73SStefano Zampini #if defined(HYPRE_USING_CUDA)
2295*a4af0ceeSJacob Faibussowitsch   ierr = PetscDeviceInitialize(PETSC_DEVICE_CUDA);CHKERRQ(ierr);
22966ea7df73SStefano Zampini   ierr = MatSetVecType(B,VECCUDA);CHKERRQ(ierr);
22976ea7df73SStefano Zampini #endif
22986ea7df73SStefano Zampini #endif
229963c07aadSStefano Zampini   PetscFunctionReturn(0);
230063c07aadSStefano Zampini }
230163c07aadSStefano Zampini 
2302225daaf8SStefano Zampini static PetscErrorCode hypre_array_destroy(void *ptr)
2303225daaf8SStefano Zampini {
2304225daaf8SStefano Zampini    PetscFunctionBegin;
2305e6de0934SSatish Balay    hypre_TFree(ptr,HYPRE_MEMORY_HOST);
2306225daaf8SStefano Zampini    PetscFunctionReturn(0);
2307225daaf8SStefano Zampini }
2308