xref: /petsc/src/mat/impls/hypre/mhypre.c (revision c6698e78f8adf436f7cbc6005862862d444e5930)
163c07aadSStefano Zampini 
263c07aadSStefano Zampini /*
363c07aadSStefano Zampini     Creates hypre ijmatrix from PETSc matrix
463c07aadSStefano Zampini */
5225daaf8SStefano Zampini 
6*c6698e78SStefano Zampini #include <petscpkg_version.h>
7dd9c0a25Sstefano_zampini #include <petscmathypre.h>
863c07aadSStefano Zampini #include <petsc/private/matimpl.h>
963c07aadSStefano Zampini #include <../src/mat/impls/hypre/mhypre.h>
1063c07aadSStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
1158968eb6SStefano Zampini #include <../src/vec/vec/impls/hypre/vhyp.h>
1258968eb6SStefano Zampini #include <HYPRE.h>
13c1a070e6SStefano Zampini #include <HYPRE_utilities.h>
14cd8bc7baSStefano Zampini #include <_hypre_parcsr_ls.h>
1568ec7858SStefano Zampini #include <_hypre_sstruct_ls.h>
1663c07aadSStefano Zampini 
1775d48cdbSStefano Zampini PETSC_INTERN PetscErrorCode MatPtAP_IS_XAIJ(Mat,Mat,MatReuse,PetscReal,Mat*);
1875d48cdbSStefano Zampini 
1963c07aadSStefano Zampini static PetscErrorCode MatHYPRE_CreateFromMat(Mat,Mat_HYPRE*);
2063c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat,Mat,HYPRE_IJMatrix);
2163c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixFastCopy_MPIAIJ(Mat,HYPRE_IJMatrix);
2263c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixFastCopy_SeqAIJ(Mat,HYPRE_IJMatrix);
23414bd5c3SStefano Zampini static PetscErrorCode MatHYPRE_MultKernel_Private(Mat,PetscScalar,Vec,PetscScalar,Vec,PetscBool);
24225daaf8SStefano Zampini static PetscErrorCode hypre_array_destroy(void*);
25c69f721fSFande Kong PetscErrorCode MatSetValues_HYPRE(Mat, PetscInt,const PetscInt[],PetscInt,const PetscInt[],const PetscScalar[],InsertMode ins);
2663c07aadSStefano Zampini 
2763c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat A_d, Mat A_o, HYPRE_IJMatrix ij)
2863c07aadSStefano Zampini {
2963c07aadSStefano Zampini   PetscErrorCode ierr;
3063c07aadSStefano Zampini   PetscInt       i,n_d,n_o;
3163c07aadSStefano Zampini   const PetscInt *ia_d,*ia_o;
3263c07aadSStefano Zampini   PetscBool      done_d=PETSC_FALSE,done_o=PETSC_FALSE;
3363c07aadSStefano Zampini   PetscInt       *nnz_d=NULL,*nnz_o=NULL;
3463c07aadSStefano Zampini 
3563c07aadSStefano Zampini   PetscFunctionBegin;
3663c07aadSStefano Zampini   if (A_d) { /* determine number of nonzero entries in local diagonal part */
3763c07aadSStefano Zampini     ierr = MatGetRowIJ(A_d,0,PETSC_FALSE,PETSC_FALSE,&n_d,&ia_d,NULL,&done_d);CHKERRQ(ierr);
3863c07aadSStefano Zampini     if (done_d) {
3963c07aadSStefano Zampini       ierr = PetscMalloc1(n_d,&nnz_d);CHKERRQ(ierr);
4063c07aadSStefano Zampini       for (i=0; i<n_d; i++) {
4163c07aadSStefano Zampini         nnz_d[i] = ia_d[i+1] - ia_d[i];
4263c07aadSStefano Zampini       }
4363c07aadSStefano Zampini     }
4463c07aadSStefano Zampini     ierr = MatRestoreRowIJ(A_d,0,PETSC_FALSE,PETSC_FALSE,NULL,&ia_d,NULL,&done_d);CHKERRQ(ierr);
4563c07aadSStefano Zampini   }
4663c07aadSStefano Zampini   if (A_o) { /* determine number of nonzero entries in local off-diagonal part */
4763c07aadSStefano Zampini     ierr = MatGetRowIJ(A_o,0,PETSC_FALSE,PETSC_FALSE,&n_o,&ia_o,NULL,&done_o);CHKERRQ(ierr);
4863c07aadSStefano Zampini     if (done_o) {
4963c07aadSStefano Zampini       ierr = PetscMalloc1(n_o,&nnz_o);CHKERRQ(ierr);
5063c07aadSStefano Zampini       for (i=0; i<n_o; i++) {
5163c07aadSStefano Zampini         nnz_o[i] = ia_o[i+1] - ia_o[i];
5263c07aadSStefano Zampini       }
5363c07aadSStefano Zampini     }
5463c07aadSStefano Zampini     ierr = MatRestoreRowIJ(A_o,0,PETSC_FALSE,PETSC_FALSE,&n_o,&ia_o,NULL,&done_o);CHKERRQ(ierr);
5563c07aadSStefano Zampini   }
5663c07aadSStefano Zampini   if (done_d) {    /* set number of nonzeros in HYPRE IJ matrix */
5763c07aadSStefano Zampini     if (!done_o) { /* only diagonal part */
5863c07aadSStefano Zampini       ierr = PetscMalloc1(n_d,&nnz_o);CHKERRQ(ierr);
5963c07aadSStefano Zampini       for (i=0; i<n_d; i++) {
6063c07aadSStefano Zampini         nnz_o[i] = 0;
6163c07aadSStefano Zampini       }
6263c07aadSStefano Zampini     }
63*c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2,16,0)
64*c6698e78SStefano Zampini     { /* If we don't do this, the columns of the matrix will be all zeros! */
65*c6698e78SStefano Zampini       hypre_AuxParCSRMatrix *aux_matrix;
66*c6698e78SStefano Zampini       aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(ij);
67*c6698e78SStefano Zampini       hypre_AuxParCSRMatrixDestroy(aux_matrix);
68*c6698e78SStefano Zampini       hypre_IJMatrixTranslator(ij) = NULL;
6963c07aadSStefano Zampini       PetscStackCallStandard(HYPRE_IJMatrixSetDiagOffdSizes,(ij,(HYPRE_Int *)nnz_d,(HYPRE_Int *)nnz_o));
70*c6698e78SStefano Zampini       aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(ij);
71*c6698e78SStefano Zampini       hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1;
72*c6698e78SStefano Zampini     }
73*c6698e78SStefano Zampini #else
74*c6698e78SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixSetDiagOffdSizes,(ij,(HYPRE_Int *)nnz_d,(HYPRE_Int *)nnz_o));
75*c6698e78SStefano Zampini #endif
7663c07aadSStefano Zampini     ierr = PetscFree(nnz_d);CHKERRQ(ierr);
7763c07aadSStefano Zampini     ierr = PetscFree(nnz_o);CHKERRQ(ierr);
7863c07aadSStefano Zampini   }
7963c07aadSStefano Zampini   PetscFunctionReturn(0);
8063c07aadSStefano Zampini }
8163c07aadSStefano Zampini 
8263c07aadSStefano Zampini static PetscErrorCode MatHYPRE_CreateFromMat(Mat A, Mat_HYPRE *hA)
8363c07aadSStefano Zampini {
8463c07aadSStefano Zampini   PetscErrorCode ierr;
8563c07aadSStefano Zampini   PetscInt       rstart,rend,cstart,cend;
8663c07aadSStefano Zampini 
8763c07aadSStefano Zampini   PetscFunctionBegin;
88d975228cSstefano_zampini   ierr   = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
89d975228cSstefano_zampini   ierr   = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
9063c07aadSStefano Zampini   rstart = A->rmap->rstart;
9163c07aadSStefano Zampini   rend   = A->rmap->rend;
9263c07aadSStefano Zampini   cstart = A->cmap->rstart;
9363c07aadSStefano Zampini   cend   = A->cmap->rend;
9463c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixCreate,(hA->comm,rstart,rend-1,cstart,cend-1,&hA->ij));
9563c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(hA->ij,HYPRE_PARCSR));
9663c07aadSStefano Zampini   {
9763c07aadSStefano Zampini     PetscBool      same;
9863c07aadSStefano Zampini     Mat            A_d,A_o;
9963c07aadSStefano Zampini     const PetscInt *colmap;
10063c07aadSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&same);CHKERRQ(ierr);
10163c07aadSStefano Zampini     if (same) {
10263c07aadSStefano Zampini       ierr = MatMPIAIJGetSeqAIJ(A,&A_d,&A_o,&colmap);CHKERRQ(ierr);
10363c07aadSStefano Zampini       ierr = MatHYPRE_IJMatrixPreallocate(A_d,A_o,hA->ij);CHKERRQ(ierr);
10463c07aadSStefano Zampini       PetscFunctionReturn(0);
10563c07aadSStefano Zampini     }
10663c07aadSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIBAIJ,&same);CHKERRQ(ierr);
10763c07aadSStefano Zampini     if (same) {
10863c07aadSStefano Zampini       ierr = MatMPIBAIJGetSeqBAIJ(A,&A_d,&A_o,&colmap);CHKERRQ(ierr);
10963c07aadSStefano Zampini       ierr = MatHYPRE_IJMatrixPreallocate(A_d,A_o,hA->ij);CHKERRQ(ierr);
11063c07aadSStefano Zampini       PetscFunctionReturn(0);
11163c07aadSStefano Zampini     }
11263c07aadSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&same);CHKERRQ(ierr);
11363c07aadSStefano Zampini     if (same) {
11463c07aadSStefano Zampini       ierr = MatHYPRE_IJMatrixPreallocate(A,NULL,hA->ij);CHKERRQ(ierr);
11563c07aadSStefano Zampini       PetscFunctionReturn(0);
11663c07aadSStefano Zampini     }
11763c07aadSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQBAIJ,&same);CHKERRQ(ierr);
11863c07aadSStefano Zampini     if (same) {
11963c07aadSStefano Zampini       ierr = MatHYPRE_IJMatrixPreallocate(A,NULL,hA->ij);CHKERRQ(ierr);
12063c07aadSStefano Zampini       PetscFunctionReturn(0);
12163c07aadSStefano Zampini     }
12263c07aadSStefano Zampini   }
12363c07aadSStefano Zampini   PetscFunctionReturn(0);
12463c07aadSStefano Zampini }
12563c07aadSStefano Zampini 
12663c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopy(Mat A, HYPRE_IJMatrix ij)
12763c07aadSStefano Zampini {
12863c07aadSStefano Zampini   PetscErrorCode    ierr;
12963c07aadSStefano Zampini   PetscInt          i,rstart,rend,ncols,nr,nc;
13063c07aadSStefano Zampini   const PetscScalar *values;
13163c07aadSStefano Zampini   const PetscInt    *cols;
13263c07aadSStefano Zampini   PetscBool         flg;
13363c07aadSStefano Zampini 
13463c07aadSStefano Zampini   PetscFunctionBegin;
13563c07aadSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&flg);CHKERRQ(ierr);
13663c07aadSStefano Zampini   ierr = MatGetSize(A,&nr,&nc);CHKERRQ(ierr);
13763c07aadSStefano Zampini   if (flg && nr == nc) {
13863c07aadSStefano Zampini     ierr = MatHYPRE_IJMatrixFastCopy_MPIAIJ(A,ij);CHKERRQ(ierr);
13963c07aadSStefano Zampini     PetscFunctionReturn(0);
14063c07aadSStefano Zampini   }
14163c07aadSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&flg);CHKERRQ(ierr);
14263c07aadSStefano Zampini   if (flg) {
14363c07aadSStefano Zampini     ierr = MatHYPRE_IJMatrixFastCopy_SeqAIJ(A,ij);CHKERRQ(ierr);
14463c07aadSStefano Zampini     PetscFunctionReturn(0);
14563c07aadSStefano Zampini   }
14663c07aadSStefano Zampini 
14763c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixInitialize,(ij));
14863c07aadSStefano Zampini   ierr = MatGetOwnershipRange(A,&rstart,&rend);CHKERRQ(ierr);
14963c07aadSStefano Zampini   for (i=rstart; i<rend; i++) {
15063c07aadSStefano Zampini     ierr = MatGetRow(A,i,&ncols,&cols,&values);CHKERRQ(ierr);
151e3977e59Sstefano_zampini     if (ncols) {
15263c07aadSStefano Zampini       PetscStackCallStandard(HYPRE_IJMatrixSetValues,(ij,1,(HYPRE_Int *)&ncols,(HYPRE_Int *)&i,(HYPRE_Int *)cols,values));
153e3977e59Sstefano_zampini     }
15463c07aadSStefano Zampini     ierr = MatRestoreRow(A,i,&ncols,&cols,&values);CHKERRQ(ierr);
15563c07aadSStefano Zampini   }
15663c07aadSStefano Zampini   PetscFunctionReturn(0);
15763c07aadSStefano Zampini }
15863c07aadSStefano Zampini 
15963c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixFastCopy_SeqAIJ(Mat A, HYPRE_IJMatrix ij)
16063c07aadSStefano Zampini {
16163c07aadSStefano Zampini   PetscErrorCode        ierr;
16263c07aadSStefano Zampini   Mat_SeqAIJ            *pdiag = (Mat_SeqAIJ*)A->data;
16358968eb6SStefano Zampini   HYPRE_Int             type;
16463c07aadSStefano Zampini   hypre_ParCSRMatrix    *par_matrix;
16563c07aadSStefano Zampini   hypre_AuxParCSRMatrix *aux_matrix;
16663c07aadSStefano Zampini   hypre_CSRMatrix       *hdiag;
16763c07aadSStefano Zampini 
16863c07aadSStefano Zampini   PetscFunctionBegin;
16963c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixInitialize,(ij));
170ea9daf28SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(ij,&type));
171ea9daf28SStefano Zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
172ea9daf28SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(ij,(void**)&par_matrix));
17363c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(par_matrix);
17463c07aadSStefano Zampini   /*
17563c07aadSStefano Zampini        this is the Hack part where we monkey directly with the hypre datastructures
17663c07aadSStefano Zampini   */
1771d4906efSStefano Zampini   ierr = PetscMemcpy(hdiag->i,pdiag->i,(A->rmap->n + 1)*sizeof(PetscInt));CHKERRQ(ierr);
1781d4906efSStefano Zampini   ierr = PetscMemcpy(hdiag->j,pdiag->j,pdiag->nz*sizeof(PetscInt));CHKERRQ(ierr);
1791d4906efSStefano Zampini   ierr = PetscMemcpy(hdiag->data,pdiag->a,pdiag->nz*sizeof(PetscScalar));CHKERRQ(ierr);
180ea9daf28SStefano Zampini 
181ea9daf28SStefano Zampini   aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(ij);
18263c07aadSStefano Zampini   hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
18363c07aadSStefano Zampini   PetscFunctionReturn(0);
18463c07aadSStefano Zampini }
18563c07aadSStefano Zampini 
18663c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixFastCopy_MPIAIJ(Mat A, HYPRE_IJMatrix ij)
18763c07aadSStefano Zampini {
18863c07aadSStefano Zampini   PetscErrorCode        ierr;
18963c07aadSStefano Zampini   Mat_MPIAIJ            *pA = (Mat_MPIAIJ*)A->data;
19063c07aadSStefano Zampini   Mat_SeqAIJ            *pdiag,*poffd;
19163c07aadSStefano Zampini   PetscInt              i,*garray = pA->garray,*jj,cstart,*pjj;
19258968eb6SStefano Zampini   HYPRE_Int             type;
19363c07aadSStefano Zampini   hypre_ParCSRMatrix    *par_matrix;
19463c07aadSStefano Zampini   hypre_AuxParCSRMatrix *aux_matrix;
19563c07aadSStefano Zampini   hypre_CSRMatrix       *hdiag,*hoffd;
19663c07aadSStefano Zampini 
19763c07aadSStefano Zampini   PetscFunctionBegin;
19863c07aadSStefano Zampini   pdiag = (Mat_SeqAIJ*) pA->A->data;
19963c07aadSStefano Zampini   poffd = (Mat_SeqAIJ*) pA->B->data;
20063c07aadSStefano Zampini   /* cstart is only valid for square MPIAIJ layed out in the usual way */
20163c07aadSStefano Zampini   ierr = MatGetOwnershipRange(A,&cstart,NULL);CHKERRQ(ierr);
20263c07aadSStefano Zampini 
20363c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixInitialize,(ij));
204ea9daf28SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(ij,&type));
205ea9daf28SStefano Zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
206ea9daf28SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(ij,(void**)&par_matrix));
20763c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(par_matrix);
20863c07aadSStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(par_matrix);
20963c07aadSStefano Zampini 
21063c07aadSStefano Zampini   /*
21163c07aadSStefano Zampini        this is the Hack part where we monkey directly with the hypre datastructures
21263c07aadSStefano Zampini   */
21363c07aadSStefano Zampini   ierr = PetscMemcpy(hdiag->i,pdiag->i,(pA->A->rmap->n + 1)*sizeof(PetscInt));
21463c07aadSStefano Zampini   /* need to shift the diag column indices (hdiag->j) back to global numbering since hypre is expecting this */
21563c07aadSStefano Zampini   jj  = (PetscInt*)hdiag->j;
21663c07aadSStefano Zampini   pjj = (PetscInt*)pdiag->j;
217*c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2,16,0)
218*c6698e78SStefano Zampini   for (i=0; i<pdiag->nz; i++) jj[i] = pjj[i];
219*c6698e78SStefano Zampini #else
22063c07aadSStefano Zampini   for (i=0; i<pdiag->nz; i++) jj[i] = cstart + pjj[i];
221*c6698e78SStefano Zampini #endif
22263c07aadSStefano Zampini   ierr = PetscMemcpy(hdiag->data,pdiag->a,pdiag->nz*sizeof(PetscScalar));
22363c07aadSStefano Zampini   ierr = PetscMemcpy(hoffd->i,poffd->i,(pA->A->rmap->n + 1)*sizeof(PetscInt));
22463c07aadSStefano Zampini   /* need to move the offd column indices (hoffd->j) back to global numbering since hypre is expecting this
22563c07aadSStefano Zampini      If we hacked a hypre a bit more we might be able to avoid this step */
226*c6698e78SStefano Zampini #if PETSC_PKG_HYPRE_VERSION_GE(2,16,0)
227*c6698e78SStefano Zampini   PetscStackCallStandard(hypre_CSRMatrixBigInitialize,(hoffd));
228*c6698e78SStefano Zampini   jj  = (PetscInt*) hoffd->big_j;
229*c6698e78SStefano Zampini #else
23063c07aadSStefano Zampini   jj  = (PetscInt*) hoffd->j;
231*c6698e78SStefano Zampini #endif
23263c07aadSStefano Zampini   pjj = (PetscInt*) poffd->j;
23363c07aadSStefano Zampini   for (i=0; i<poffd->nz; i++) jj[i] = garray[pjj[i]];
234*c6698e78SStefano Zampini 
23563c07aadSStefano Zampini   ierr = PetscMemcpy(hoffd->data,poffd->a,poffd->nz*sizeof(PetscScalar));
23663c07aadSStefano Zampini 
237ea9daf28SStefano Zampini   aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(ij);
23863c07aadSStefano Zampini   hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
23963c07aadSStefano Zampini   PetscFunctionReturn(0);
24063c07aadSStefano Zampini }
24163c07aadSStefano Zampini 
2422df22349SStefano Zampini static PetscErrorCode MatConvert_HYPRE_IS(Mat A, MatType mtype, MatReuse reuse, Mat* B)
2432df22349SStefano Zampini {
2442df22349SStefano Zampini   Mat_HYPRE*             mhA = (Mat_HYPRE*)(A->data);
2452df22349SStefano Zampini   Mat                    lA;
2462df22349SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
2472df22349SStefano Zampini   IS                     is;
2482df22349SStefano Zampini   hypre_ParCSRMatrix     *hA;
2492df22349SStefano Zampini   hypre_CSRMatrix        *hdiag,*hoffd;
2502df22349SStefano Zampini   MPI_Comm               comm;
2512df22349SStefano Zampini   PetscScalar            *hdd,*hod,*aa,*data;
2527d968826Sstefano_zampini   HYPRE_Int              *col_map_offd,*hdi,*hdj,*hoi,*hoj;
2532df22349SStefano Zampini   PetscInt               *ii,*jj,*iptr,*jptr;
2542df22349SStefano Zampini   PetscInt               cum,dr,dc,oc,str,stc,nnz,i,jd,jo,M,N;
25558968eb6SStefano Zampini   HYPRE_Int              type;
2562df22349SStefano Zampini   PetscErrorCode         ierr;
2572df22349SStefano Zampini 
2582df22349SStefano Zampini   PetscFunctionBegin;
259a1787963SStefano Zampini   comm = PetscObjectComm((PetscObject)A);
2602df22349SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(mhA->ij,&type));
2612df22349SStefano Zampini   if (type != HYPRE_PARCSR) SETERRQ(comm,PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
2622df22349SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(mhA->ij,(void**)&hA));
2632df22349SStefano Zampini   M     = hypre_ParCSRMatrixGlobalNumRows(hA);
2642df22349SStefano Zampini   N     = hypre_ParCSRMatrixGlobalNumCols(hA);
2652df22349SStefano Zampini   str   = hypre_ParCSRMatrixFirstRowIndex(hA);
2662df22349SStefano Zampini   stc   = hypre_ParCSRMatrixFirstColDiag(hA);
2672df22349SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(hA);
2682df22349SStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(hA);
2692df22349SStefano Zampini   dr    = hypre_CSRMatrixNumRows(hdiag);
2702df22349SStefano Zampini   dc    = hypre_CSRMatrixNumCols(hdiag);
2712df22349SStefano Zampini   nnz   = hypre_CSRMatrixNumNonzeros(hdiag);
2722df22349SStefano Zampini   hdi   = hypre_CSRMatrixI(hdiag);
2732df22349SStefano Zampini   hdj   = hypre_CSRMatrixJ(hdiag);
2742df22349SStefano Zampini   hdd   = hypre_CSRMatrixData(hdiag);
2752df22349SStefano Zampini   oc    = hypre_CSRMatrixNumCols(hoffd);
2762df22349SStefano Zampini   nnz  += hypre_CSRMatrixNumNonzeros(hoffd);
2772df22349SStefano Zampini   hoi   = hypre_CSRMatrixI(hoffd);
2782df22349SStefano Zampini   hoj   = hypre_CSRMatrixJ(hoffd);
2792df22349SStefano Zampini   hod   = hypre_CSRMatrixData(hoffd);
2802df22349SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
2812df22349SStefano Zampini     PetscInt *aux;
2822df22349SStefano Zampini 
2832df22349SStefano Zampini     /* generate l2g maps for rows and cols */
2842df22349SStefano Zampini     ierr = ISCreateStride(comm,dr,str,1,&is);CHKERRQ(ierr);
2852df22349SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
2862df22349SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
2872df22349SStefano Zampini     col_map_offd = hypre_ParCSRMatrixColMapOffd(hA);
2882df22349SStefano Zampini     ierr = PetscMalloc1(dc+oc,&aux);CHKERRQ(ierr);
2892df22349SStefano Zampini     for (i=0; i<dc; i++) aux[i] = i+stc;
2902df22349SStefano Zampini     for (i=0; i<oc; i++) aux[i+dc] = col_map_offd[i];
2912df22349SStefano Zampini     ierr = ISCreateGeneral(comm,dc+oc,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2922df22349SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
2932df22349SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
2942df22349SStefano Zampini     /* create MATIS object */
2952df22349SStefano Zampini     ierr = MatCreate(comm,B);CHKERRQ(ierr);
2962df22349SStefano Zampini     ierr = MatSetSizes(*B,dr,dc,M,N);CHKERRQ(ierr);
2972df22349SStefano Zampini     ierr = MatSetType(*B,MATIS);CHKERRQ(ierr);
2982df22349SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*B,rl2g,cl2g);CHKERRQ(ierr);
2992df22349SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
3002df22349SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
3012df22349SStefano Zampini 
3022df22349SStefano Zampini     /* allocate CSR for local matrix */
3032df22349SStefano Zampini     ierr = PetscMalloc1(dr+1,&iptr);CHKERRQ(ierr);
3042df22349SStefano Zampini     ierr = PetscMalloc1(nnz,&jptr);CHKERRQ(ierr);
3052df22349SStefano Zampini     ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr);
3062df22349SStefano Zampini   } else {
3072df22349SStefano Zampini     PetscInt  nr;
3082df22349SStefano Zampini     PetscBool done;
3092df22349SStefano Zampini     ierr = MatISGetLocalMat(*B,&lA);CHKERRQ(ierr);
3102df22349SStefano Zampini     ierr = MatGetRowIJ(lA,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&iptr,(const PetscInt**)&jptr,&done);CHKERRQ(ierr);
3112df22349SStefano 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);
3122df22349SStefano 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);
3132df22349SStefano Zampini     ierr = MatSeqAIJGetArray(lA,&data);CHKERRQ(ierr);
3142df22349SStefano Zampini   }
3152df22349SStefano Zampini   /* merge local matrices */
3162df22349SStefano Zampini   ii   = iptr;
3172df22349SStefano Zampini   jj   = jptr;
3182df22349SStefano Zampini   aa   = data;
3192df22349SStefano Zampini   *ii  = *(hdi++) + *(hoi++);
3202df22349SStefano Zampini   for (jd=0,jo=0,cum=0; *ii<nnz; cum++) {
3212df22349SStefano Zampini     PetscScalar *aold = aa;
3222df22349SStefano Zampini     PetscInt    *jold = jj,nc = jd+jo;
3232df22349SStefano Zampini     for (; jd<*hdi; jd++) { *jj++ = *hdj++;      *aa++ = *hdd++; }
3242df22349SStefano Zampini     for (; jo<*hoi; jo++) { *jj++ = *hoj++ + dc; *aa++ = *hod++; }
3252df22349SStefano Zampini     *(++ii) = *(hdi++) + *(hoi++);
3262df22349SStefano Zampini     ierr = PetscSortIntWithScalarArray(jd+jo-nc,jold,aold);CHKERRQ(ierr);
3272df22349SStefano Zampini   }
3282df22349SStefano Zampini   for (; cum<dr; cum++) *(++ii) = nnz;
3292df22349SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
330a033916dSStefano Zampini     Mat_SeqAIJ* a;
331a033916dSStefano Zampini 
3322df22349SStefano Zampini     ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,dc+oc,iptr,jptr,data,&lA);CHKERRQ(ierr);
3332df22349SStefano Zampini     ierr = MatISSetLocalMat(*B,lA);CHKERRQ(ierr);
334a033916dSStefano Zampini     /* hack SeqAIJ */
335a033916dSStefano Zampini     a          = (Mat_SeqAIJ*)(lA->data);
336a033916dSStefano Zampini     a->free_a  = PETSC_TRUE;
337a033916dSStefano Zampini     a->free_ij = PETSC_TRUE;
3382df22349SStefano Zampini     ierr = MatDestroy(&lA);CHKERRQ(ierr);
3392df22349SStefano Zampini   }
3402df22349SStefano Zampini   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3412df22349SStefano Zampini   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3422df22349SStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
3432df22349SStefano Zampini     ierr = MatHeaderReplace(A,B);CHKERRQ(ierr);
3442df22349SStefano Zampini   }
3452df22349SStefano Zampini   PetscFunctionReturn(0);
3462df22349SStefano Zampini }
3472df22349SStefano Zampini 
34863c07aadSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType type, MatReuse reuse, Mat *B)
34963c07aadSStefano Zampini {
35084d4e069SStefano Zampini   Mat            M = NULL;
35163c07aadSStefano Zampini   Mat_HYPRE      *hB;
35263c07aadSStefano Zampini   MPI_Comm       comm = PetscObjectComm((PetscObject)A);
35363c07aadSStefano Zampini   PetscErrorCode ierr;
35463c07aadSStefano Zampini 
35563c07aadSStefano Zampini   PetscFunctionBegin;
35663c07aadSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
35763c07aadSStefano Zampini     /* always destroy the old matrix and create a new memory;
35863c07aadSStefano Zampini        hope this does not churn the memory too much. The problem
35963c07aadSStefano Zampini        is I do not know if it is possible to put the matrix back to
36063c07aadSStefano Zampini        its initial state so that we can directly copy the values
36163c07aadSStefano Zampini        the second time through. */
36263c07aadSStefano Zampini     hB = (Mat_HYPRE*)((*B)->data);
36363c07aadSStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixDestroy,(hB->ij));
36463c07aadSStefano Zampini   } else {
36584d4e069SStefano Zampini     ierr = MatCreate(comm,&M);CHKERRQ(ierr);
36684d4e069SStefano Zampini     ierr = MatSetType(M,MATHYPRE);CHKERRQ(ierr);
36784d4e069SStefano Zampini     ierr = MatSetSizes(M,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
36884d4e069SStefano Zampini     hB   = (Mat_HYPRE*)(M->data);
36984d4e069SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) *B = M;
37063c07aadSStefano Zampini   }
37163c07aadSStefano Zampini   ierr = MatHYPRE_CreateFromMat(A,hB);CHKERRQ(ierr);
37263c07aadSStefano Zampini   ierr = MatHYPRE_IJMatrixCopy(A,hB->ij);CHKERRQ(ierr);
37384d4e069SStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
37484d4e069SStefano Zampini     ierr = MatHeaderReplace(A,&M);CHKERRQ(ierr);
37584d4e069SStefano Zampini   }
3764ec6421dSstefano_zampini   (*B)->preallocated = PETSC_TRUE;
37763c07aadSStefano Zampini   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
37863c07aadSStefano Zampini   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
37963c07aadSStefano Zampini   PetscFunctionReturn(0);
38063c07aadSStefano Zampini }
38163c07aadSStefano Zampini 
382ea9daf28SStefano Zampini static PetscErrorCode MatConvert_HYPRE_AIJ(Mat A, MatType mtype, MatReuse reuse, Mat *B)
38363c07aadSStefano Zampini {
38463c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE*)A->data;
38563c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
38663c07aadSStefano Zampini   hypre_CSRMatrix    *hdiag,*hoffd;
38763c07aadSStefano Zampini   MPI_Comm           comm;
38863c07aadSStefano Zampini   PetscScalar        *da,*oa,*aptr;
38963c07aadSStefano Zampini   PetscInt           *dii,*djj,*oii,*ojj,*iptr;
39063c07aadSStefano Zampini   PetscInt           i,dnnz,onnz,m,n;
39158968eb6SStefano Zampini   HYPRE_Int          type;
39263c07aadSStefano Zampini   PetscMPIInt        size;
39363c07aadSStefano Zampini   PetscErrorCode     ierr;
39463c07aadSStefano Zampini 
39563c07aadSStefano Zampini   PetscFunctionBegin;
39663c07aadSStefano Zampini   comm = PetscObjectComm((PetscObject)A);
39763c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type));
39863c07aadSStefano Zampini   if (type != HYPRE_PARCSR) SETERRQ(comm,PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
39963c07aadSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
40063c07aadSStefano Zampini     PetscBool ismpiaij,isseqaij;
40163c07aadSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*B,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
4024099cc6bSBarry Smith     ierr = PetscObjectBaseTypeCompare((PetscObject)*B,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
40363c07aadSStefano Zampini     if (!ismpiaij && !isseqaij) SETERRQ(comm,PETSC_ERR_SUP,"Only MATMPIAIJ or MATSEQAIJ are supported");
40463c07aadSStefano Zampini   }
40563c07aadSStefano Zampini   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
40663c07aadSStefano Zampini 
40763c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&parcsr));
40863c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(parcsr);
40963c07aadSStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(parcsr);
41063c07aadSStefano Zampini   m     = hypre_CSRMatrixNumRows(hdiag);
41163c07aadSStefano Zampini   n     = hypre_CSRMatrixNumCols(hdiag);
41263c07aadSStefano Zampini   dnnz  = hypre_CSRMatrixNumNonzeros(hdiag);
41363c07aadSStefano Zampini   onnz  = hypre_CSRMatrixNumNonzeros(hoffd);
414225daaf8SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
41563c07aadSStefano Zampini     ierr = PetscMalloc1(m+1,&dii);CHKERRQ(ierr);
41663c07aadSStefano Zampini     ierr = PetscMalloc1(dnnz,&djj);CHKERRQ(ierr);
41763c07aadSStefano Zampini     ierr = PetscMalloc1(dnnz,&da);CHKERRQ(ierr);
418225daaf8SStefano Zampini   } else if (reuse == MAT_REUSE_MATRIX) {
41963c07aadSStefano Zampini     PetscInt  nr;
42063c07aadSStefano Zampini     PetscBool done;
42163c07aadSStefano Zampini     if (size > 1) {
42263c07aadSStefano Zampini       Mat_MPIAIJ *b = (Mat_MPIAIJ*)((*B)->data);
42363c07aadSStefano Zampini 
42463c07aadSStefano Zampini       ierr = MatGetRowIJ(b->A,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&dii,(const PetscInt**)&djj,&done);CHKERRQ(ierr);
42563c07aadSStefano 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);
42663c07aadSStefano 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);
42763c07aadSStefano Zampini       ierr = MatSeqAIJGetArray(b->A,&da);CHKERRQ(ierr);
42863c07aadSStefano Zampini     } else {
42963c07aadSStefano Zampini       ierr = MatGetRowIJ(*B,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&dii,(const PetscInt**)&djj,&done);CHKERRQ(ierr);
43063c07aadSStefano Zampini       if (nr != m) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot reuse mat: invalid number of local rows! %D != %D",nr,m);
43163c07aadSStefano 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);
43263c07aadSStefano Zampini       ierr = MatSeqAIJGetArray(*B,&da);CHKERRQ(ierr);
43363c07aadSStefano Zampini     }
434225daaf8SStefano Zampini   } else { /* MAT_INPLACE_MATRIX */
4357d968826Sstefano_zampini     dii = (PetscInt*)hypre_CSRMatrixI(hdiag);
4367d968826Sstefano_zampini     djj = (PetscInt*)hypre_CSRMatrixJ(hdiag);
437225daaf8SStefano Zampini     da  = hypre_CSRMatrixData(hdiag);
43863c07aadSStefano Zampini   }
43963c07aadSStefano Zampini   ierr = PetscMemcpy(dii,hypre_CSRMatrixI(hdiag),(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
44063c07aadSStefano Zampini   ierr = PetscMemcpy(djj,hypre_CSRMatrixJ(hdiag),dnnz*sizeof(PetscInt));CHKERRQ(ierr);
44163c07aadSStefano Zampini   ierr = PetscMemcpy(da,hypre_CSRMatrixData(hdiag),dnnz*sizeof(PetscScalar));CHKERRQ(ierr);
44263c07aadSStefano Zampini   iptr = djj;
44363c07aadSStefano Zampini   aptr = da;
44463c07aadSStefano Zampini   for (i=0; i<m; i++) {
44563c07aadSStefano Zampini     PetscInt nc = dii[i+1]-dii[i];
44663c07aadSStefano Zampini     ierr = PetscSortIntWithScalarArray(nc,iptr,aptr);CHKERRQ(ierr);
44763c07aadSStefano Zampini     iptr += nc;
44863c07aadSStefano Zampini     aptr += nc;
44963c07aadSStefano Zampini   }
45063c07aadSStefano Zampini   if (size > 1) {
4517d968826Sstefano_zampini     HYPRE_Int *offdj,*coffd;
45263c07aadSStefano Zampini 
453225daaf8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
45463c07aadSStefano Zampini       ierr = PetscMalloc1(m+1,&oii);CHKERRQ(ierr);
45563c07aadSStefano Zampini       ierr = PetscMalloc1(onnz,&ojj);CHKERRQ(ierr);
45663c07aadSStefano Zampini       ierr = PetscMalloc1(onnz,&oa);CHKERRQ(ierr);
457225daaf8SStefano Zampini     } else if (reuse == MAT_REUSE_MATRIX) {
45863c07aadSStefano Zampini       Mat_MPIAIJ *b = (Mat_MPIAIJ*)((*B)->data);
45963c07aadSStefano Zampini       PetscInt   nr,hr = hypre_CSRMatrixNumRows(hoffd);
46063c07aadSStefano Zampini       PetscBool  done;
46163c07aadSStefano Zampini 
46263c07aadSStefano Zampini       ierr = MatGetRowIJ(b->B,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&oii,(const PetscInt**)&ojj,&done);CHKERRQ(ierr);
46363c07aadSStefano 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);
46463c07aadSStefano 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);
46563c07aadSStefano Zampini       ierr = MatSeqAIJGetArray(b->B,&oa);CHKERRQ(ierr);
466225daaf8SStefano Zampini     } else { /* MAT_INPLACE_MATRIX */
4677d968826Sstefano_zampini       oii = (PetscInt*)hypre_CSRMatrixI(hoffd);
4687d968826Sstefano_zampini       ojj = (PetscInt*)hypre_CSRMatrixJ(hoffd);
469225daaf8SStefano Zampini       oa  = hypre_CSRMatrixData(hoffd);
47063c07aadSStefano Zampini     }
47163c07aadSStefano Zampini     ierr  = PetscMemcpy(oii,hypre_CSRMatrixI(hoffd),(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
47263c07aadSStefano Zampini     offdj = hypre_CSRMatrixJ(hoffd);
47363c07aadSStefano Zampini     coffd = hypre_ParCSRMatrixColMapOffd(parcsr);
47463c07aadSStefano Zampini     for (i=0; i<onnz; i++) ojj[i] = coffd[offdj[i]];
47563c07aadSStefano Zampini     ierr = PetscMemcpy(oa,hypre_CSRMatrixData(hoffd),onnz*sizeof(PetscScalar));CHKERRQ(ierr);
47663c07aadSStefano Zampini     iptr = ojj;
47763c07aadSStefano Zampini     aptr = oa;
47863c07aadSStefano Zampini     for (i=0; i<m; i++) {
47963c07aadSStefano Zampini        PetscInt nc = oii[i+1]-oii[i];
48063c07aadSStefano Zampini        ierr = PetscSortIntWithScalarArray(nc,iptr,aptr);CHKERRQ(ierr);
48163c07aadSStefano Zampini        iptr += nc;
48263c07aadSStefano Zampini        aptr += nc;
48363c07aadSStefano Zampini     }
484225daaf8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
48563c07aadSStefano Zampini       Mat_MPIAIJ *b;
48663c07aadSStefano Zampini       Mat_SeqAIJ *d,*o;
487225daaf8SStefano Zampini 
48841073d71Sstefano_zampini       ierr = MatCreateMPIAIJWithSplitArrays(comm,m,n,PETSC_DECIDE,PETSC_DECIDE,dii,djj,da,oii,ojj,oa,B);CHKERRQ(ierr);
48963c07aadSStefano Zampini       /* hack MPIAIJ */
49063c07aadSStefano Zampini       b          = (Mat_MPIAIJ*)((*B)->data);
49163c07aadSStefano Zampini       d          = (Mat_SeqAIJ*)b->A->data;
49263c07aadSStefano Zampini       o          = (Mat_SeqAIJ*)b->B->data;
49363c07aadSStefano Zampini       d->free_a  = PETSC_TRUE;
49463c07aadSStefano Zampini       d->free_ij = PETSC_TRUE;
49563c07aadSStefano Zampini       o->free_a  = PETSC_TRUE;
49663c07aadSStefano Zampini       o->free_ij = PETSC_TRUE;
497225daaf8SStefano Zampini     } else if (reuse == MAT_INPLACE_MATRIX) {
498225daaf8SStefano Zampini       Mat T;
49941073d71Sstefano_zampini       ierr = MatCreateMPIAIJWithSplitArrays(comm,m,n,PETSC_DECIDE,PETSC_DECIDE,dii,djj,da,oii,ojj,oa,&T);CHKERRQ(ierr);
500225daaf8SStefano Zampini       hypre_CSRMatrixI(hdiag)    = NULL;
501225daaf8SStefano Zampini       hypre_CSRMatrixJ(hdiag)    = NULL;
502225daaf8SStefano Zampini       hypre_CSRMatrixData(hdiag) = NULL;
503225daaf8SStefano Zampini       hypre_CSRMatrixI(hoffd)    = NULL;
504225daaf8SStefano Zampini       hypre_CSRMatrixJ(hoffd)    = NULL;
505225daaf8SStefano Zampini       hypre_CSRMatrixData(hoffd) = NULL;
506225daaf8SStefano Zampini       ierr = MatHeaderReplace(A,&T);CHKERRQ(ierr);
50763c07aadSStefano Zampini     }
508225daaf8SStefano Zampini   } else {
509225daaf8SStefano Zampini     oii  = NULL;
510225daaf8SStefano Zampini     ojj  = NULL;
511225daaf8SStefano Zampini     oa   = NULL;
512225daaf8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
51363c07aadSStefano Zampini       Mat_SeqAIJ* b;
51463c07aadSStefano Zampini       ierr = MatCreateSeqAIJWithArrays(comm,m,n,dii,djj,da,B);CHKERRQ(ierr);
51563c07aadSStefano Zampini       /* hack SeqAIJ */
51663c07aadSStefano Zampini       b          = (Mat_SeqAIJ*)((*B)->data);
51763c07aadSStefano Zampini       b->free_a  = PETSC_TRUE;
51863c07aadSStefano Zampini       b->free_ij = PETSC_TRUE;
519225daaf8SStefano Zampini     } else if (reuse == MAT_INPLACE_MATRIX) {
520225daaf8SStefano Zampini       Mat T;
521225daaf8SStefano Zampini       ierr = MatCreateSeqAIJWithArrays(comm,m,n,dii,djj,da,&T);CHKERRQ(ierr);
522225daaf8SStefano Zampini       hypre_CSRMatrixI(hdiag)    = NULL;
523225daaf8SStefano Zampini       hypre_CSRMatrixJ(hdiag)    = NULL;
524225daaf8SStefano Zampini       hypre_CSRMatrixData(hdiag) = NULL;
525225daaf8SStefano Zampini       ierr = MatHeaderReplace(A,&T);CHKERRQ(ierr);
52663c07aadSStefano Zampini     }
527225daaf8SStefano Zampini   }
528225daaf8SStefano Zampini 
529225daaf8SStefano Zampini   /* we have to use hypre_Tfree to free the arrays */
53063c07aadSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
531225daaf8SStefano Zampini     void *ptrs[6] = {dii,djj,da,oii,ojj,oa};
532225daaf8SStefano Zampini     const char *names[6] = {"_hypre_csr_dii",
533225daaf8SStefano Zampini                             "_hypre_csr_djj",
534225daaf8SStefano Zampini                             "_hypre_csr_da",
535225daaf8SStefano Zampini                             "_hypre_csr_oii",
536225daaf8SStefano Zampini                             "_hypre_csr_ojj",
537225daaf8SStefano Zampini                             "_hypre_csr_oa"};
538225daaf8SStefano Zampini     for (i=0; i<6; i++) {
539225daaf8SStefano Zampini       PetscContainer c;
540225daaf8SStefano Zampini 
541225daaf8SStefano Zampini       ierr = PetscContainerCreate(comm,&c);CHKERRQ(ierr);
542225daaf8SStefano Zampini       ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr);
543225daaf8SStefano Zampini       ierr = PetscContainerSetUserDestroy(c,hypre_array_destroy);CHKERRQ(ierr);
544225daaf8SStefano Zampini       ierr = PetscObjectCompose((PetscObject)(*B),names[i],(PetscObject)c);CHKERRQ(ierr);
545225daaf8SStefano Zampini       ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
546225daaf8SStefano Zampini     }
54763c07aadSStefano Zampini   }
54863c07aadSStefano Zampini   PetscFunctionReturn(0);
54963c07aadSStefano Zampini }
55063c07aadSStefano Zampini 
551613e5ff0Sstefano_zampini static PetscErrorCode MatAIJGetParCSR_Private(Mat A, hypre_ParCSRMatrix **hA)
552c1a070e6SStefano Zampini {
553613e5ff0Sstefano_zampini   hypre_ParCSRMatrix *tA;
554c1a070e6SStefano Zampini   hypre_CSRMatrix    *hdiag,*hoffd;
555c1a070e6SStefano Zampini   Mat_SeqAIJ         *diag,*offd;
556c1a070e6SStefano Zampini   PetscInt           *garray,noffd,dnnz,onnz,*row_starts,*col_starts;
557c1a070e6SStefano Zampini   MPI_Comm           comm = PetscObjectComm((PetscObject)A);
558613e5ff0Sstefano_zampini   PetscBool          ismpiaij,isseqaij;
559c1a070e6SStefano Zampini   PetscErrorCode     ierr;
560c1a070e6SStefano Zampini 
561c1a070e6SStefano Zampini   PetscFunctionBegin;
562c1a070e6SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
5634099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
564c1a070e6SStefano Zampini   if (!ismpiaij && !isseqaij) SETERRQ1(comm,PETSC_ERR_SUP,"Unsupported type %s",((PetscObject)A)->type);
565c1a070e6SStefano Zampini   if (ismpiaij) {
566c1a070e6SStefano Zampini     Mat_MPIAIJ *a = (Mat_MPIAIJ*)(A->data);
567c1a070e6SStefano Zampini 
568c1a070e6SStefano Zampini     diag   = (Mat_SeqAIJ*)a->A->data;
569c1a070e6SStefano Zampini     offd   = (Mat_SeqAIJ*)a->B->data;
570c1a070e6SStefano Zampini     garray = a->garray;
571c1a070e6SStefano Zampini     noffd  = a->B->cmap->N;
572c1a070e6SStefano Zampini     dnnz   = diag->nz;
573c1a070e6SStefano Zampini     onnz   = offd->nz;
574c1a070e6SStefano Zampini   } else {
575c1a070e6SStefano Zampini     diag   = (Mat_SeqAIJ*)A->data;
576c1a070e6SStefano Zampini     offd   = NULL;
577c1a070e6SStefano Zampini     garray = NULL;
578c1a070e6SStefano Zampini     noffd  = 0;
579c1a070e6SStefano Zampini     dnnz   = diag->nz;
580c1a070e6SStefano Zampini     onnz   = 0;
581c1a070e6SStefano Zampini   }
582225daaf8SStefano Zampini 
583c1a070e6SStefano Zampini   /* create a temporary ParCSR */
584c1a070e6SStefano Zampini   if (HYPRE_AssumedPartitionCheck()) {
585c1a070e6SStefano Zampini     PetscMPIInt myid;
586c1a070e6SStefano Zampini 
587c1a070e6SStefano Zampini     ierr       = MPI_Comm_rank(comm,&myid);CHKERRQ(ierr);
588c1a070e6SStefano Zampini     row_starts = A->rmap->range + myid;
589c1a070e6SStefano Zampini     col_starts = A->cmap->range + myid;
590c1a070e6SStefano Zampini   } else {
591c1a070e6SStefano Zampini     row_starts = A->rmap->range;
592c1a070e6SStefano Zampini     col_starts = A->cmap->range;
593c1a070e6SStefano Zampini   }
5947d968826Sstefano_zampini   tA = hypre_ParCSRMatrixCreate(comm,A->rmap->N,A->cmap->N,(HYPRE_Int*)row_starts,(HYPRE_Int*)col_starts,noffd,dnnz,onnz);
595c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetRowStartsOwner(tA,0);
596c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetColStartsOwner(tA,0);
597c1a070e6SStefano Zampini 
598225daaf8SStefano Zampini   /* set diagonal part */
599c1a070e6SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(tA);
6007d968826Sstefano_zampini   hypre_CSRMatrixI(hdiag)           = (HYPRE_Int*)diag->i;
6017d968826Sstefano_zampini   hypre_CSRMatrixJ(hdiag)           = (HYPRE_Int*)diag->j;
602c1a070e6SStefano Zampini   hypre_CSRMatrixData(hdiag)        = diag->a;
603c1a070e6SStefano Zampini   hypre_CSRMatrixNumNonzeros(hdiag) = diag->nz;
604c1a070e6SStefano Zampini   hypre_CSRMatrixSetRownnz(hdiag);
605c1a070e6SStefano Zampini   hypre_CSRMatrixSetDataOwner(hdiag,0);
606c1a070e6SStefano Zampini 
607225daaf8SStefano Zampini   /* set offdiagonal part */
608c1a070e6SStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(tA);
609c1a070e6SStefano Zampini   if (offd) {
6107d968826Sstefano_zampini     hypre_CSRMatrixI(hoffd)           = (HYPRE_Int*)offd->i;
6117d968826Sstefano_zampini     hypre_CSRMatrixJ(hoffd)           = (HYPRE_Int*)offd->j;
612c1a070e6SStefano Zampini     hypre_CSRMatrixData(hoffd)        = offd->a;
613c1a070e6SStefano Zampini     hypre_CSRMatrixNumNonzeros(hoffd) = offd->nz;
614c1a070e6SStefano Zampini     hypre_CSRMatrixSetRownnz(hoffd);
615c1a070e6SStefano Zampini     hypre_CSRMatrixSetDataOwner(hoffd,0);
616c1a070e6SStefano Zampini     hypre_ParCSRMatrixSetNumNonzeros(tA);
6177d968826Sstefano_zampini     hypre_ParCSRMatrixColMapOffd(tA) = (HYPRE_Int*)garray;
618c1a070e6SStefano Zampini   }
619613e5ff0Sstefano_zampini   *hA = tA;
620613e5ff0Sstefano_zampini   PetscFunctionReturn(0);
621613e5ff0Sstefano_zampini }
622c1a070e6SStefano Zampini 
623613e5ff0Sstefano_zampini static PetscErrorCode MatAIJRestoreParCSR_Private(Mat A, hypre_ParCSRMatrix **hA)
624613e5ff0Sstefano_zampini {
625613e5ff0Sstefano_zampini   hypre_CSRMatrix    *hdiag,*hoffd;
626c1a070e6SStefano Zampini 
627613e5ff0Sstefano_zampini   PetscFunctionBegin;
628613e5ff0Sstefano_zampini   hdiag = hypre_ParCSRMatrixDiag(*hA);
629613e5ff0Sstefano_zampini   hoffd = hypre_ParCSRMatrixOffd(*hA);
630c1a070e6SStefano Zampini   /* set pointers to NULL before destroying tA */
631c1a070e6SStefano Zampini   hypre_CSRMatrixI(hdiag)           = NULL;
632c1a070e6SStefano Zampini   hypre_CSRMatrixJ(hdiag)           = NULL;
633c1a070e6SStefano Zampini   hypre_CSRMatrixData(hdiag)        = NULL;
634c1a070e6SStefano Zampini   hypre_CSRMatrixI(hoffd)           = NULL;
635c1a070e6SStefano Zampini   hypre_CSRMatrixJ(hoffd)           = NULL;
636c1a070e6SStefano Zampini   hypre_CSRMatrixData(hoffd)        = NULL;
637613e5ff0Sstefano_zampini   hypre_ParCSRMatrixColMapOffd(*hA) = NULL;
638613e5ff0Sstefano_zampini   hypre_ParCSRMatrixDestroy(*hA);
639613e5ff0Sstefano_zampini   *hA = NULL;
640613e5ff0Sstefano_zampini   PetscFunctionReturn(0);
641613e5ff0Sstefano_zampini }
642613e5ff0Sstefano_zampini 
643613e5ff0Sstefano_zampini /* calls RAP from BoomerAMG:
6443dad0653Sstefano_zampini    the resulting ParCSR will not own the column and row starts
6453dad0653Sstefano_zampini    It looks like we don't need to have the diagonal entries
6463dad0653Sstefano_zampini    ordered first in the rows of the diagonal part
6473dad0653Sstefano_zampini    for boomerAMGBuildCoarseOperator to work */
648a055b5aaSBarry Smith static PetscErrorCode MatHYPRE_ParCSR_RAP(hypre_ParCSRMatrix *hR, hypre_ParCSRMatrix *hA,hypre_ParCSRMatrix *hP, hypre_ParCSRMatrix **hRAP)
649613e5ff0Sstefano_zampini {
650613e5ff0Sstefano_zampini   HYPRE_Int P_owns_col_starts,R_owns_row_starts;
651613e5ff0Sstefano_zampini 
652613e5ff0Sstefano_zampini   PetscFunctionBegin;
653613e5ff0Sstefano_zampini   P_owns_col_starts = hypre_ParCSRMatrixOwnsColStarts(hP);
654613e5ff0Sstefano_zampini   R_owns_row_starts = hypre_ParCSRMatrixOwnsRowStarts(hR);
655613e5ff0Sstefano_zampini   PetscStackCallStandard(hypre_BoomerAMGBuildCoarseOperator,(hR,hA,hP,hRAP));
656613e5ff0Sstefano_zampini   PetscStackCallStandard(hypre_ParCSRMatrixSetNumNonzeros,(*hRAP));
657613e5ff0Sstefano_zampini   /* hypre_BoomerAMGBuildCoarseOperator steals the col_starts from P and the row_starts from R */
658613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetRowStartsOwner(*hRAP,0);
659613e5ff0Sstefano_zampini   hypre_ParCSRMatrixSetColStartsOwner(*hRAP,0);
660613e5ff0Sstefano_zampini   if (P_owns_col_starts) hypre_ParCSRMatrixSetColStartsOwner(hP,1);
661613e5ff0Sstefano_zampini   if (R_owns_row_starts) hypre_ParCSRMatrixSetRowStartsOwner(hR,1);
662613e5ff0Sstefano_zampini   PetscFunctionReturn(0);
663613e5ff0Sstefano_zampini }
664613e5ff0Sstefano_zampini 
6656f231fbdSstefano_zampini static PetscErrorCode MatPtAPNumeric_AIJ_AIJ_wHYPRE(Mat A,Mat P,Mat C)
666613e5ff0Sstefano_zampini {
6676f231fbdSstefano_zampini   Mat                B;
668613e5ff0Sstefano_zampini   hypre_ParCSRMatrix *hA,*hP,*hPtAP;
669613e5ff0Sstefano_zampini   PetscErrorCode     ierr;
670613e5ff0Sstefano_zampini 
671613e5ff0Sstefano_zampini   PetscFunctionBegin;
672613e5ff0Sstefano_zampini   ierr = MatAIJGetParCSR_Private(A,&hA);CHKERRQ(ierr);
673613e5ff0Sstefano_zampini   ierr = MatAIJGetParCSR_Private(P,&hP);CHKERRQ(ierr);
674613e5ff0Sstefano_zampini   ierr = MatHYPRE_ParCSR_RAP(hP,hA,hP,&hPtAP);CHKERRQ(ierr);
6756f231fbdSstefano_zampini   ierr = MatCreateFromParCSR(hPtAP,MATAIJ,PETSC_OWN_POINTER,&B);CHKERRQ(ierr);
6766f231fbdSstefano_zampini   ierr = MatHeaderMerge(C,&B);CHKERRQ(ierr);
677613e5ff0Sstefano_zampini   ierr = MatAIJRestoreParCSR_Private(A,&hA);CHKERRQ(ierr);
678613e5ff0Sstefano_zampini   ierr = MatAIJRestoreParCSR_Private(P,&hP);CHKERRQ(ierr);
6796f231fbdSstefano_zampini   PetscFunctionReturn(0);
6806f231fbdSstefano_zampini }
6816f231fbdSstefano_zampini 
6826f231fbdSstefano_zampini PETSC_INTERN PetscErrorCode MatPtAPSymbolic_AIJ_AIJ_wHYPRE(Mat A,Mat P,PetscReal fill,Mat *C)
6836f231fbdSstefano_zampini {
6846f231fbdSstefano_zampini   PetscErrorCode ierr;
685ab4d48faSStefano Zampini 
6866f231fbdSstefano_zampini   PetscFunctionBegin;
6876f231fbdSstefano_zampini   ierr                   = MatCreate(PetscObjectComm((PetscObject)A),C);CHKERRQ(ierr);
6886f231fbdSstefano_zampini   ierr                   = MatSetType(*C,MATAIJ);CHKERRQ(ierr);
6896f231fbdSstefano_zampini   (*C)->ops->ptapnumeric = MatPtAPNumeric_AIJ_AIJ_wHYPRE;
690613e5ff0Sstefano_zampini   PetscFunctionReturn(0);
691613e5ff0Sstefano_zampini }
692613e5ff0Sstefano_zampini 
6934cc28894Sstefano_zampini static PetscErrorCode MatPtAPNumeric_AIJ_HYPRE(Mat A,Mat P,Mat C)
694613e5ff0Sstefano_zampini {
6954cc28894Sstefano_zampini   Mat                B;
6964cc28894Sstefano_zampini   Mat_HYPRE          *hP;
697613e5ff0Sstefano_zampini   hypre_ParCSRMatrix *hA = NULL,*Pparcsr,*ptapparcsr;
698613e5ff0Sstefano_zampini   HYPRE_Int          type;
699613e5ff0Sstefano_zampini   MPI_Comm           comm = PetscObjectComm((PetscObject)A);
7004cc28894Sstefano_zampini   PetscBool          ishypre;
701613e5ff0Sstefano_zampini   PetscErrorCode     ierr;
702613e5ff0Sstefano_zampini 
703613e5ff0Sstefano_zampini   PetscFunctionBegin;
7044cc28894Sstefano_zampini   ierr = PetscObjectTypeCompare((PetscObject)P,MATHYPRE,&ishypre);CHKERRQ(ierr);
7054cc28894Sstefano_zampini   if (!ishypre) SETERRQ1(comm,PETSC_ERR_USER,"P should be of type %s",MATHYPRE);
7064cc28894Sstefano_zampini   hP = (Mat_HYPRE*)P->data;
707613e5ff0Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hP->ij,&type));
708613e5ff0Sstefano_zampini   if (type != HYPRE_PARCSR) SETERRQ(comm,PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
709613e5ff0Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hP->ij,(void**)&Pparcsr));
710613e5ff0Sstefano_zampini 
711613e5ff0Sstefano_zampini   ierr = MatAIJGetParCSR_Private(A,&hA);CHKERRQ(ierr);
712613e5ff0Sstefano_zampini   ierr = MatHYPRE_ParCSR_RAP(Pparcsr,hA,Pparcsr,&ptapparcsr);CHKERRQ(ierr);
713613e5ff0Sstefano_zampini   ierr = MatAIJRestoreParCSR_Private(A,&hA);CHKERRQ(ierr);
714225daaf8SStefano Zampini 
7154cc28894Sstefano_zampini   /* create temporary matrix and merge to C */
7164cc28894Sstefano_zampini   ierr = MatCreateFromParCSR(ptapparcsr,((PetscObject)C)->type_name,PETSC_OWN_POINTER,&B);CHKERRQ(ierr);
7174cc28894Sstefano_zampini   ierr = MatHeaderMerge(C,&B);CHKERRQ(ierr);
7184cc28894Sstefano_zampini   PetscFunctionReturn(0);
7194cc28894Sstefano_zampini }
7204cc28894Sstefano_zampini 
7214cc28894Sstefano_zampini static PetscErrorCode MatPtAP_AIJ_HYPRE(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C)
7224cc28894Sstefano_zampini {
7234cc28894Sstefano_zampini   PetscErrorCode ierr;
7244cc28894Sstefano_zampini 
7254cc28894Sstefano_zampini   PetscFunctionBegin;
7264cc28894Sstefano_zampini   if (scall == MAT_INITIAL_MATRIX) {
7274cc28894Sstefano_zampini     const char *deft = MATAIJ;
7284cc28894Sstefano_zampini     char       type[256];
7294cc28894Sstefano_zampini     PetscBool  flg;
7304cc28894Sstefano_zampini 
7314cc28894Sstefano_zampini     ierr = PetscObjectOptionsBegin((PetscObject)A);CHKERRQ(ierr);
7324cc28894Sstefano_zampini     ierr = PetscOptionsFList("-matptap_hypre_outtype","Matrix type",NULL,MatList,deft,type,256,&flg);CHKERRQ(ierr);
7334cc28894Sstefano_zampini     ierr = PetscOptionsEnd();CHKERRQ(ierr);
7344cc28894Sstefano_zampini     ierr = PetscLogEventBegin(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr);
7354cc28894Sstefano_zampini     ierr = MatCreate(PetscObjectComm((PetscObject)A),C);CHKERRQ(ierr);
7364cc28894Sstefano_zampini     if (flg) {
7374cc28894Sstefano_zampini       ierr = MatSetType(*C,type);CHKERRQ(ierr);
7384cc28894Sstefano_zampini     } else {
7394cc28894Sstefano_zampini       ierr = MatSetType(*C,deft);CHKERRQ(ierr);
7404cc28894Sstefano_zampini     }
7414cc28894Sstefano_zampini     (*C)->ops->ptapnumeric = MatPtAPNumeric_AIJ_HYPRE;
7424cc28894Sstefano_zampini     ierr = PetscLogEventEnd(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr);
7434cc28894Sstefano_zampini   }
7444cc28894Sstefano_zampini   ierr = PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
7454cc28894Sstefano_zampini   ierr = (*(*C)->ops->ptapnumeric)(A,P,*C);CHKERRQ(ierr);
746613e5ff0Sstefano_zampini   ierr = PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
747c1a070e6SStefano Zampini   PetscFunctionReturn(0);
748c1a070e6SStefano Zampini }
749c1a070e6SStefano Zampini 
7504cc28894Sstefano_zampini static PetscErrorCode MatPtAPNumeric_HYPRE_HYPRE(Mat A,Mat P,Mat C)
7514cc28894Sstefano_zampini {
7524cc28894Sstefano_zampini   Mat                B;
7534cc28894Sstefano_zampini   hypre_ParCSRMatrix *Aparcsr,*Pparcsr,*ptapparcsr;
7544cc28894Sstefano_zampini   Mat_HYPRE          *hA,*hP;
7554cc28894Sstefano_zampini   PetscBool          ishypre;
7564cc28894Sstefano_zampini   HYPRE_Int          type;
7574cc28894Sstefano_zampini   PetscErrorCode     ierr;
7584cc28894Sstefano_zampini 
7594cc28894Sstefano_zampini   PetscFunctionBegin;
7604cc28894Sstefano_zampini   ierr = PetscObjectTypeCompare((PetscObject)P,MATHYPRE,&ishypre);CHKERRQ(ierr);
7614cc28894Sstefano_zampini   if (!ishypre) SETERRQ1(PetscObjectComm((PetscObject)P),PETSC_ERR_USER,"P should be of type %s",MATHYPRE);
7624cc28894Sstefano_zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATHYPRE,&ishypre);CHKERRQ(ierr);
7634cc28894Sstefano_zampini   if (!ishypre) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_USER,"A should be of type %s",MATHYPRE);
7644cc28894Sstefano_zampini   hA = (Mat_HYPRE*)A->data;
7654cc28894Sstefano_zampini   hP = (Mat_HYPRE*)P->data;
7664cc28894Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type));
7674cc28894Sstefano_zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
7684cc28894Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hP->ij,&type));
7694cc28894Sstefano_zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)P),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
7704cc28894Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&Aparcsr));
7714cc28894Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hP->ij,(void**)&Pparcsr));
7724cc28894Sstefano_zampini   ierr = MatHYPRE_ParCSR_RAP(Pparcsr,Aparcsr,Pparcsr,&ptapparcsr);CHKERRQ(ierr);
7734cc28894Sstefano_zampini   ierr = MatCreateFromParCSR(ptapparcsr,MATHYPRE,PETSC_OWN_POINTER,&B);CHKERRQ(ierr);
7744cc28894Sstefano_zampini   ierr = MatHeaderMerge(C,&B);CHKERRQ(ierr);
7754cc28894Sstefano_zampini   PetscFunctionReturn(0);
7764cc28894Sstefano_zampini }
7774cc28894Sstefano_zampini 
778cd8bc7baSStefano Zampini static PetscErrorCode MatPtAP_HYPRE_HYPRE(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C)
779cd8bc7baSStefano Zampini {
780cd8bc7baSStefano Zampini   PetscErrorCode ierr;
781cd8bc7baSStefano Zampini 
782cd8bc7baSStefano Zampini   PetscFunctionBegin;
7834cc28894Sstefano_zampini   if (scall == MAT_INITIAL_MATRIX) {
7844cc28894Sstefano_zampini     ierr = PetscLogEventBegin(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr);
7854cc28894Sstefano_zampini     ierr                   = MatCreate(PetscObjectComm((PetscObject)A),C);CHKERRQ(ierr);
7864cc28894Sstefano_zampini     ierr                   = MatSetType(*C,MATHYPRE);CHKERRQ(ierr);
7874cc28894Sstefano_zampini     (*C)->ops->ptapnumeric = MatPtAPNumeric_HYPRE_HYPRE;
7884cc28894Sstefano_zampini     ierr = PetscLogEventEnd(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr);
7894cc28894Sstefano_zampini   }
790613e5ff0Sstefano_zampini   ierr = PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
7914cc28894Sstefano_zampini   ierr = (*(*C)->ops->ptapnumeric)(A,P,*C);CHKERRQ(ierr);
792613e5ff0Sstefano_zampini   ierr = PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
793cd8bc7baSStefano Zampini   PetscFunctionReturn(0);
794cd8bc7baSStefano Zampini }
795cd8bc7baSStefano Zampini 
796d501dc42Sstefano_zampini /* calls hypre_ParMatmul
797d501dc42Sstefano_zampini    hypre_ParMatMul uses hypre_ParMatrixCreate with the communicator of hA
7983dad0653Sstefano_zampini    hypre_ParMatrixCreate does not duplicate the communicator
7993dad0653Sstefano_zampini    It looks like we don't need to have the diagonal entries
8003dad0653Sstefano_zampini    ordered first in the rows of the diagonal part
8013dad0653Sstefano_zampini    for boomerAMGBuildCoarseOperator to work */
802d501dc42Sstefano_zampini static PetscErrorCode MatHYPRE_ParCSR_MatMatMult(hypre_ParCSRMatrix *hA, hypre_ParCSRMatrix *hB, hypre_ParCSRMatrix **hAB)
803d501dc42Sstefano_zampini {
804d501dc42Sstefano_zampini   PetscFunctionBegin;
805d501dc42Sstefano_zampini   PetscStackPush("hypre_ParMatmul");
806d501dc42Sstefano_zampini   *hAB = hypre_ParMatmul(hA,hB);
807d501dc42Sstefano_zampini   PetscStackPop;
808d501dc42Sstefano_zampini   PetscFunctionReturn(0);
809d501dc42Sstefano_zampini }
810d501dc42Sstefano_zampini 
8115e5acdf2Sstefano_zampini static PetscErrorCode MatMatMultNumeric_AIJ_AIJ_wHYPRE(Mat A,Mat B,Mat C)
8125e5acdf2Sstefano_zampini {
8135e5acdf2Sstefano_zampini   Mat                D;
814d501dc42Sstefano_zampini   hypre_ParCSRMatrix *hA,*hB,*hAB = NULL;
8155e5acdf2Sstefano_zampini   PetscErrorCode     ierr;
8165e5acdf2Sstefano_zampini 
8175e5acdf2Sstefano_zampini   PetscFunctionBegin;
8185e5acdf2Sstefano_zampini   ierr = MatAIJGetParCSR_Private(A,&hA);CHKERRQ(ierr);
8195e5acdf2Sstefano_zampini   ierr = MatAIJGetParCSR_Private(B,&hB);CHKERRQ(ierr);
820d501dc42Sstefano_zampini   ierr = MatHYPRE_ParCSR_MatMatMult(hA,hB,&hAB);CHKERRQ(ierr);
8215e5acdf2Sstefano_zampini   ierr = MatCreateFromParCSR(hAB,MATAIJ,PETSC_OWN_POINTER,&D);CHKERRQ(ierr);
8225e5acdf2Sstefano_zampini   ierr = MatHeaderMerge(C,&D);CHKERRQ(ierr);
8235e5acdf2Sstefano_zampini   ierr = MatAIJRestoreParCSR_Private(A,&hA);CHKERRQ(ierr);
8245e5acdf2Sstefano_zampini   ierr = MatAIJRestoreParCSR_Private(B,&hB);CHKERRQ(ierr);
8255e5acdf2Sstefano_zampini   PetscFunctionReturn(0);
8265e5acdf2Sstefano_zampini }
8275e5acdf2Sstefano_zampini 
8285e5acdf2Sstefano_zampini PETSC_INTERN PetscErrorCode MatMatMultSymbolic_AIJ_AIJ_wHYPRE(Mat A,Mat B,PetscReal fill,Mat *C)
8295e5acdf2Sstefano_zampini {
8305e5acdf2Sstefano_zampini   PetscErrorCode ierr;
83120e1dc0dSstefano_zampini 
8325e5acdf2Sstefano_zampini   PetscFunctionBegin;
8335e5acdf2Sstefano_zampini   ierr                      = MatCreate(PetscObjectComm((PetscObject)A),C);CHKERRQ(ierr);
8345e5acdf2Sstefano_zampini   ierr                      = MatSetType(*C,MATAIJ);CHKERRQ(ierr);
8355e5acdf2Sstefano_zampini   (*C)->ops->matmultnumeric = MatMatMultNumeric_AIJ_AIJ_wHYPRE;
8365e5acdf2Sstefano_zampini   PetscFunctionReturn(0);
8375e5acdf2Sstefano_zampini }
8385e5acdf2Sstefano_zampini 
839d501dc42Sstefano_zampini static PetscErrorCode MatMatMultNumeric_HYPRE_HYPRE(Mat A,Mat B,Mat C)
840d501dc42Sstefano_zampini {
841d501dc42Sstefano_zampini   Mat                D;
842d501dc42Sstefano_zampini   hypre_ParCSRMatrix *Aparcsr,*Bparcsr,*ABparcsr = NULL;
843d501dc42Sstefano_zampini   Mat_HYPRE          *hA,*hB;
844d501dc42Sstefano_zampini   PetscBool          ishypre;
845d501dc42Sstefano_zampini   HYPRE_Int          type;
846d501dc42Sstefano_zampini   PetscErrorCode     ierr;
847d501dc42Sstefano_zampini 
848d501dc42Sstefano_zampini   PetscFunctionBegin;
849d501dc42Sstefano_zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATHYPRE,&ishypre);CHKERRQ(ierr);
850d501dc42Sstefano_zampini   if (!ishypre) SETERRQ1(PetscObjectComm((PetscObject)B),PETSC_ERR_USER,"B should be of type %s",MATHYPRE);
851d501dc42Sstefano_zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATHYPRE,&ishypre);CHKERRQ(ierr);
852d501dc42Sstefano_zampini   if (!ishypre) SETERRQ1(PetscObjectComm((PetscObject)A),PETSC_ERR_USER,"A should be of type %s",MATHYPRE);
853d501dc42Sstefano_zampini   hA = (Mat_HYPRE*)A->data;
854d501dc42Sstefano_zampini   hB = (Mat_HYPRE*)B->data;
855d501dc42Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type));
856d501dc42Sstefano_zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
857d501dc42Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hB->ij,&type));
858d501dc42Sstefano_zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
859d501dc42Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&Aparcsr));
860d501dc42Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hB->ij,(void**)&Bparcsr));
861d501dc42Sstefano_zampini   ierr = MatHYPRE_ParCSR_MatMatMult(Aparcsr,Bparcsr,&ABparcsr);CHKERRQ(ierr);
862d501dc42Sstefano_zampini   ierr = MatCreateFromParCSR(ABparcsr,MATHYPRE,PETSC_OWN_POINTER,&D);CHKERRQ(ierr);
863d501dc42Sstefano_zampini   /* need to use HeaderReplace because HeaderMerge messes up with the communicator */
864d501dc42Sstefano_zampini   ierr = MatHeaderReplace(C,&D);CHKERRQ(ierr);
865d501dc42Sstefano_zampini   C->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE;
866d501dc42Sstefano_zampini   PetscFunctionReturn(0);
867d501dc42Sstefano_zampini }
868d501dc42Sstefano_zampini 
869d501dc42Sstefano_zampini static PetscErrorCode MatMatMult_HYPRE_HYPRE(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
870d501dc42Sstefano_zampini {
871d501dc42Sstefano_zampini   PetscErrorCode ierr;
872d501dc42Sstefano_zampini 
873d501dc42Sstefano_zampini   PetscFunctionBegin;
874d501dc42Sstefano_zampini   if (scall == MAT_INITIAL_MATRIX) {
875d501dc42Sstefano_zampini     ierr = PetscLogEventBegin(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr);
876d501dc42Sstefano_zampini     ierr                      = MatCreate(PetscObjectComm((PetscObject)A),C);CHKERRQ(ierr);
877d501dc42Sstefano_zampini     ierr                      = MatSetType(*C,MATHYPRE);CHKERRQ(ierr);
878d501dc42Sstefano_zampini     (*C)->ops->matmultnumeric = MatMatMultNumeric_HYPRE_HYPRE;
879d501dc42Sstefano_zampini     ierr = PetscLogEventEnd(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr);
880d501dc42Sstefano_zampini   }
881d501dc42Sstefano_zampini   ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
882d501dc42Sstefano_zampini   ierr = (*(*C)->ops->matmultnumeric)(A,B,*C);CHKERRQ(ierr);
883d501dc42Sstefano_zampini   ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
884d501dc42Sstefano_zampini   PetscFunctionReturn(0);
885d501dc42Sstefano_zampini }
886d501dc42Sstefano_zampini 
8873dad0653Sstefano_zampini PETSC_INTERN PetscErrorCode MatTransposeMatMatMultNumeric_AIJ_AIJ_AIJ_wHYPRE(Mat A,Mat B,Mat C,Mat D)
88820e1dc0dSstefano_zampini {
88920e1dc0dSstefano_zampini   Mat                E;
89020e1dc0dSstefano_zampini   hypre_ParCSRMatrix *hA,*hB,*hC,*hABC;
89120e1dc0dSstefano_zampini   PetscErrorCode     ierr;
89220e1dc0dSstefano_zampini 
89320e1dc0dSstefano_zampini   PetscFunctionBegin;
89420e1dc0dSstefano_zampini   ierr = MatAIJGetParCSR_Private(A,&hA);CHKERRQ(ierr);
89520e1dc0dSstefano_zampini   ierr = MatAIJGetParCSR_Private(B,&hB);CHKERRQ(ierr);
89620e1dc0dSstefano_zampini   ierr = MatAIJGetParCSR_Private(C,&hC);CHKERRQ(ierr);
89720e1dc0dSstefano_zampini   ierr = MatHYPRE_ParCSR_RAP(hA,hB,hC,&hABC);CHKERRQ(ierr);
89820e1dc0dSstefano_zampini   ierr = MatCreateFromParCSR(hABC,MATAIJ,PETSC_OWN_POINTER,&E);CHKERRQ(ierr);
89920e1dc0dSstefano_zampini   ierr = MatHeaderMerge(D,&E);CHKERRQ(ierr);
90020e1dc0dSstefano_zampini   ierr = MatAIJRestoreParCSR_Private(A,&hA);CHKERRQ(ierr);
90120e1dc0dSstefano_zampini   ierr = MatAIJRestoreParCSR_Private(B,&hB);CHKERRQ(ierr);
90220e1dc0dSstefano_zampini   ierr = MatAIJRestoreParCSR_Private(C,&hC);CHKERRQ(ierr);
90320e1dc0dSstefano_zampini   PetscFunctionReturn(0);
90420e1dc0dSstefano_zampini }
90520e1dc0dSstefano_zampini 
9063dad0653Sstefano_zampini PETSC_INTERN PetscErrorCode MatTransposeMatMatMultSymbolic_AIJ_AIJ_AIJ_wHYPRE(Mat A,Mat B,Mat C,PetscReal fill,Mat *D)
90720e1dc0dSstefano_zampini {
90820e1dc0dSstefano_zampini   PetscErrorCode ierr;
90920e1dc0dSstefano_zampini 
91020e1dc0dSstefano_zampini   PetscFunctionBegin;
91120e1dc0dSstefano_zampini   ierr = MatCreate(PetscObjectComm((PetscObject)A),D);CHKERRQ(ierr);
91220e1dc0dSstefano_zampini   ierr = MatSetType(*D,MATAIJ);CHKERRQ(ierr);
91320e1dc0dSstefano_zampini   PetscFunctionReturn(0);
91420e1dc0dSstefano_zampini }
91520e1dc0dSstefano_zampini 
916ea9daf28SStefano Zampini static PetscErrorCode MatMultTranspose_HYPRE(Mat A, Vec x, Vec y)
91763c07aadSStefano Zampini {
91863c07aadSStefano Zampini   PetscErrorCode ierr;
91963c07aadSStefano Zampini 
92063c07aadSStefano Zampini   PetscFunctionBegin;
921414bd5c3SStefano Zampini   ierr = MatHYPRE_MultKernel_Private(A,1.0,x,0.0,y,PETSC_TRUE);CHKERRQ(ierr);
92263c07aadSStefano Zampini   PetscFunctionReturn(0);
92363c07aadSStefano Zampini }
92463c07aadSStefano Zampini 
925ea9daf28SStefano Zampini static PetscErrorCode MatMult_HYPRE(Mat A, Vec x, Vec y)
92663c07aadSStefano Zampini {
92763c07aadSStefano Zampini   PetscErrorCode ierr;
92863c07aadSStefano Zampini 
92963c07aadSStefano Zampini   PetscFunctionBegin;
930414bd5c3SStefano Zampini   ierr = MatHYPRE_MultKernel_Private(A,1.0,x,0.0,y,PETSC_FALSE);CHKERRQ(ierr);
93163c07aadSStefano Zampini   PetscFunctionReturn(0);
93263c07aadSStefano Zampini }
93363c07aadSStefano Zampini 
934414bd5c3SStefano Zampini static PetscErrorCode MatMultAdd_HYPRE(Mat A, Vec x, Vec y, Vec z)
935414bd5c3SStefano Zampini {
936414bd5c3SStefano Zampini   PetscErrorCode ierr;
937414bd5c3SStefano Zampini 
938414bd5c3SStefano Zampini   PetscFunctionBegin;
939414bd5c3SStefano Zampini   if (y != z) {
940414bd5c3SStefano Zampini     ierr = VecCopy(y,z);CHKERRQ(ierr);
941414bd5c3SStefano Zampini   }
942414bd5c3SStefano Zampini   ierr = MatHYPRE_MultKernel_Private(A,1.0,x,1.0,z,PETSC_FALSE);CHKERRQ(ierr);
943414bd5c3SStefano Zampini   PetscFunctionReturn(0);
944414bd5c3SStefano Zampini }
945414bd5c3SStefano Zampini 
946414bd5c3SStefano Zampini static PetscErrorCode MatMultTransposeAdd_HYPRE(Mat A, Vec x, Vec y, Vec z)
947414bd5c3SStefano Zampini {
948414bd5c3SStefano Zampini   PetscErrorCode ierr;
949414bd5c3SStefano Zampini 
950414bd5c3SStefano Zampini   PetscFunctionBegin;
951414bd5c3SStefano Zampini   if (y != z) {
952414bd5c3SStefano Zampini     ierr = VecCopy(y,z);CHKERRQ(ierr);
953414bd5c3SStefano Zampini   }
954414bd5c3SStefano Zampini   ierr = MatHYPRE_MultKernel_Private(A,1.0,x,1.0,z,PETSC_TRUE);CHKERRQ(ierr);
955414bd5c3SStefano Zampini   PetscFunctionReturn(0);
956414bd5c3SStefano Zampini }
957414bd5c3SStefano Zampini 
958414bd5c3SStefano Zampini /* y = a * A * x + b * y or y = a * A^t * x + b * y depending on trans */
959414bd5c3SStefano Zampini static PetscErrorCode MatHYPRE_MultKernel_Private(Mat A, PetscScalar a, Vec x, PetscScalar b, Vec y, PetscBool trans)
96063c07aadSStefano Zampini {
96163c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE*)A->data;
96263c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
96363c07aadSStefano Zampini   hypre_ParVector    *hx,*hy;
96463c07aadSStefano Zampini   PetscScalar        *ax,*ay,*sax,*say;
96563c07aadSStefano Zampini   PetscErrorCode     ierr;
96663c07aadSStefano Zampini 
96763c07aadSStefano Zampini   PetscFunctionBegin;
96863c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&parcsr));
96963c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJVectorGetObject,(hA->x,(void**)&hx));
97063c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJVectorGetObject,(hA->b,(void**)&hy));
97163c07aadSStefano Zampini   ierr = VecGetArrayRead(x,(const PetscScalar**)&ax);CHKERRQ(ierr);
97263c07aadSStefano Zampini   ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
97363c07aadSStefano Zampini   if (trans) {
97458968eb6SStefano Zampini     VecHYPRE_ParVectorReplacePointer(hA->x,ay,say);
97558968eb6SStefano Zampini     VecHYPRE_ParVectorReplacePointer(hA->b,ax,sax);
976414bd5c3SStefano Zampini     hypre_ParCSRMatrixMatvecT(a,parcsr,hy,b,hx);
97758968eb6SStefano Zampini     VecHYPRE_ParVectorReplacePointer(hA->x,say,ay);
97858968eb6SStefano Zampini     VecHYPRE_ParVectorReplacePointer(hA->b,sax,ax);
97963c07aadSStefano Zampini   } else {
98058968eb6SStefano Zampini     VecHYPRE_ParVectorReplacePointer(hA->x,ax,sax);
98158968eb6SStefano Zampini     VecHYPRE_ParVectorReplacePointer(hA->b,ay,say);
982414bd5c3SStefano Zampini     hypre_ParCSRMatrixMatvec(a,parcsr,hx,b,hy);
98358968eb6SStefano Zampini     VecHYPRE_ParVectorReplacePointer(hA->x,sax,ax);
98458968eb6SStefano Zampini     VecHYPRE_ParVectorReplacePointer(hA->b,say,ay);
98563c07aadSStefano Zampini   }
98663c07aadSStefano Zampini   ierr = VecRestoreArrayRead(x,(const PetscScalar**)&ax);CHKERRQ(ierr);
98763c07aadSStefano Zampini   ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
98863c07aadSStefano Zampini   PetscFunctionReturn(0);
98963c07aadSStefano Zampini }
99063c07aadSStefano Zampini 
991ea9daf28SStefano Zampini static PetscErrorCode MatDestroy_HYPRE(Mat A)
99263c07aadSStefano Zampini {
99363c07aadSStefano Zampini   Mat_HYPRE      *hA = (Mat_HYPRE*)A->data;
99463c07aadSStefano Zampini   PetscErrorCode ierr;
99563c07aadSStefano Zampini 
99663c07aadSStefano Zampini   PetscFunctionBegin;
99763c07aadSStefano Zampini   if (hA->x) PetscStackCallStandard(HYPRE_IJVectorDestroy,(hA->x));
99863c07aadSStefano Zampini   if (hA->b) PetscStackCallStandard(HYPRE_IJVectorDestroy,(hA->b));
999978814f1SStefano Zampini   if (hA->ij) {
1000978814f1SStefano Zampini     if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL;
1001978814f1SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixDestroy,(hA->ij));
1002978814f1SStefano Zampini   }
100363c07aadSStefano Zampini   if (hA->comm) { ierr = MPI_Comm_free(&hA->comm);CHKERRQ(ierr); }
1004c69f721fSFande Kong 
1005c69f721fSFande Kong   ierr = MatStashDestroy_Private(&A->stash);CHKERRQ(ierr);
1006c69f721fSFande Kong 
1007c69f721fSFande Kong   ierr = PetscFree(hA->array);CHKERRQ(ierr);
1008c69f721fSFande Kong 
100963c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_hypre_aij_C",NULL);CHKERRQ(ierr);
10102df22349SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_hypre_is_C",NULL);CHKERRQ(ierr);
1011c1a070e6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatPtAP_seqaij_hypre_C",NULL);CHKERRQ(ierr);
1012c1a070e6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatPtAP_mpiaij_hypre_C",NULL);CHKERRQ(ierr);
1013d975228cSstefano_zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatHYPRESetPreallocation_C",NULL);CHKERRQ(ierr);
1014dd9c0a25Sstefano_zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatHYPREGetParCSR_C",NULL);CHKERRQ(ierr);
101575d48cdbSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatPtAP_is_hypre_C",NULL);CHKERRQ(ierr);
101663c07aadSStefano Zampini   ierr = PetscFree(A->data);CHKERRQ(ierr);
101763c07aadSStefano Zampini   PetscFunctionReturn(0);
101863c07aadSStefano Zampini }
101963c07aadSStefano Zampini 
1020ea9daf28SStefano Zampini static PetscErrorCode MatSetUp_HYPRE(Mat A)
102163c07aadSStefano Zampini {
10224ec6421dSstefano_zampini   PetscErrorCode ierr;
10234ec6421dSstefano_zampini 
10244ec6421dSstefano_zampini   PetscFunctionBegin;
10254ec6421dSstefano_zampini   ierr = MatHYPRESetPreallocation(A,PETSC_DEFAULT,NULL,PETSC_DEFAULT,NULL);CHKERRQ(ierr);
10264ec6421dSstefano_zampini   PetscFunctionReturn(0);
10274ec6421dSstefano_zampini }
10284ec6421dSstefano_zampini 
10294ec6421dSstefano_zampini static PetscErrorCode MatAssemblyEnd_HYPRE(Mat A, MatAssemblyType mode)
10304ec6421dSstefano_zampini {
103163c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE*)A->data;
103263c07aadSStefano Zampini   Vec                x,b;
1033c69f721fSFande Kong   PetscMPIInt        n;
1034c69f721fSFande Kong   PetscInt           i,j,rstart,ncols,flg;
1035c69f721fSFande Kong   PetscInt           *row,*col;
1036c69f721fSFande Kong   PetscScalar        *val;
103763c07aadSStefano Zampini   PetscErrorCode     ierr;
103863c07aadSStefano Zampini 
103963c07aadSStefano Zampini   PetscFunctionBegin;
10404ec6421dSstefano_zampini   if (mode == MAT_FLUSH_ASSEMBLY) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"MAT_FLUSH_ASSEMBLY currently not supported with MATHYPRE");
1041c69f721fSFande Kong 
1042c69f721fSFande Kong   if (!A->nooffprocentries) {
1043c69f721fSFande Kong     while (1) {
1044c69f721fSFande Kong       ierr = MatStashScatterGetMesg_Private(&A->stash,&n,&row,&col,&val,&flg);CHKERRQ(ierr);
1045c69f721fSFande Kong       if (!flg) break;
1046c69f721fSFande Kong 
1047c69f721fSFande Kong       for (i=0; i<n; ) {
1048c69f721fSFande Kong         /* Now identify the consecutive vals belonging to the same row */
1049c69f721fSFande Kong         for (j=i,rstart=row[j]; j<n; j++) {
1050c69f721fSFande Kong           if (row[j] != rstart) break;
1051c69f721fSFande Kong         }
1052c69f721fSFande Kong         if (j < n) ncols = j-i;
1053c69f721fSFande Kong         else       ncols = n-i;
1054c69f721fSFande Kong         /* Now assemble all these values with a single function call */
1055c69f721fSFande Kong         ierr = MatSetValues_HYPRE(A,1,row+i,ncols,col+i,val+i,A->insertmode);CHKERRQ(ierr);
1056c69f721fSFande Kong 
1057c69f721fSFande Kong         i = j;
1058c69f721fSFande Kong       }
1059c69f721fSFande Kong     }
1060c69f721fSFande Kong     ierr = MatStashScatterEnd_Private(&A->stash);CHKERRQ(ierr);
1061c69f721fSFande Kong   }
1062c69f721fSFande Kong 
10634ec6421dSstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixAssemble,(hA->ij));
1064af1cf968SStefano Zampini   /* The assembly routine destroys the aux_matrix, we recreate it here by calling HYPRE_IJMatrixInitalize */
1065af1cf968SStefano Zampini   {
1066af1cf968SStefano Zampini     hypre_AuxParCSRMatrix *aux_matrix;
1067af1cf968SStefano Zampini 
1068af1cf968SStefano Zampini     /* call destroy just to make sure we do not leak anything */
1069af1cf968SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(hA->ij);
1070af1cf968SStefano Zampini     PetscStackCallStandard(hypre_AuxParCSRMatrixDestroy,(aux_matrix));
1071af1cf968SStefano Zampini     hypre_IJMatrixTranslator(hA->ij) = NULL;
1072af1cf968SStefano Zampini 
1073af1cf968SStefano Zampini     /* Initialize with assembled flag -> it only recreates the aux_par_matrix */
1074af1cf968SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixInitialize,(hA->ij));
1075af1cf968SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(hA->ij);
1076af1cf968SStefano Zampini     hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1; /* see comment in MatHYPRESetPreallocation_HYPRE */
1077af1cf968SStefano Zampini     PetscStackCallStandard(hypre_AuxParCSRMatrixInitialize,(aux_matrix));
1078af1cf968SStefano Zampini   }
107963c07aadSStefano Zampini   if (hA->x) PetscFunctionReturn(0);
108063c07aadSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
108163c07aadSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
108263c07aadSStefano Zampini   ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)A),1,A->cmap->n,A->cmap->N,NULL,&x);CHKERRQ(ierr);
108363c07aadSStefano Zampini   ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)A),1,A->rmap->n,A->rmap->N,NULL,&b);CHKERRQ(ierr);
108463c07aadSStefano Zampini   ierr = VecHYPRE_IJVectorCreate(x,&hA->x);CHKERRQ(ierr);
108563c07aadSStefano Zampini   ierr = VecHYPRE_IJVectorCreate(b,&hA->b);CHKERRQ(ierr);
108663c07aadSStefano Zampini   ierr = VecDestroy(&x);CHKERRQ(ierr);
108763c07aadSStefano Zampini   ierr = VecDestroy(&b);CHKERRQ(ierr);
108863c07aadSStefano Zampini   PetscFunctionReturn(0);
108963c07aadSStefano Zampini }
109063c07aadSStefano Zampini 
1091c69f721fSFande Kong static PetscErrorCode MatGetArray_HYPRE(Mat A, PetscInt size, void **array)
1092c69f721fSFande Kong {
1093c69f721fSFande Kong   Mat_HYPRE          *hA = (Mat_HYPRE*)A->data;
1094c69f721fSFande Kong   PetscErrorCode     ierr;
1095c69f721fSFande Kong 
1096c69f721fSFande Kong   PetscFunctionBegin;
1097c69f721fSFande Kong   if (!hA->available) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Temporary space is in use");
1098c69f721fSFande Kong 
1099c69f721fSFande Kong   if (hA->size >= size) *array = hA->array;
1100c69f721fSFande Kong   else {
1101c69f721fSFande Kong     ierr = PetscFree(hA->array);CHKERRQ(ierr);
1102c69f721fSFande Kong     hA->size = size;
1103c69f721fSFande Kong     ierr = PetscMalloc(hA->size,&hA->array);CHKERRQ(ierr);
1104c69f721fSFande Kong     *array = hA->array;
1105c69f721fSFande Kong   }
1106c69f721fSFande Kong 
1107c69f721fSFande Kong   hA->available = PETSC_FALSE;
1108c69f721fSFande Kong   PetscFunctionReturn(0);
1109c69f721fSFande Kong }
1110c69f721fSFande Kong 
1111708542d2SFande Kong static PetscErrorCode MatRestoreArray_HYPRE(Mat A, void **array)
1112c69f721fSFande Kong {
1113c69f721fSFande Kong   Mat_HYPRE          *hA = (Mat_HYPRE*)A->data;
1114c69f721fSFande Kong 
1115c69f721fSFande Kong   PetscFunctionBegin;
1116c69f721fSFande Kong   *array = NULL;
1117c69f721fSFande Kong   hA->available = PETSC_TRUE;
1118c69f721fSFande Kong   PetscFunctionReturn(0);
1119c69f721fSFande Kong }
1120c69f721fSFande Kong 
1121d975228cSstefano_zampini PetscErrorCode MatSetValues_HYPRE(Mat A, PetscInt nr, const PetscInt rows[], PetscInt nc, const PetscInt cols[], const PetscScalar v[], InsertMode ins)
1122d975228cSstefano_zampini {
1123d975228cSstefano_zampini   Mat_HYPRE          *hA = (Mat_HYPRE*)A->data;
1124d975228cSstefano_zampini   PetscScalar        *vals = (PetscScalar *)v;
1125c69f721fSFande Kong   PetscScalar        *sscr;
1126c69f721fSFande Kong   PetscInt           *cscr[2];
1127c69f721fSFande Kong   PetscInt           i,nzc;
112808defe43SFande Kong   void               *array = NULL;
1129d975228cSstefano_zampini   PetscErrorCode     ierr;
1130d975228cSstefano_zampini 
1131d975228cSstefano_zampini   PetscFunctionBegin;
1132c69f721fSFande Kong   ierr = MatGetArray_HYPRE(A,sizeof(PetscInt)*(2*nc)+sizeof(PetscScalar)*nc*nr,&array);CHKERRQ(ierr);
1133c69f721fSFande Kong   cscr[0] = (PetscInt*)array;
1134c69f721fSFande Kong   cscr[1] = ((PetscInt*)array)+nc;
1135c69f721fSFande Kong   sscr = (PetscScalar*)(((PetscInt*)array)+nc*2);
1136d975228cSstefano_zampini   for (i=0,nzc=0;i<nc;i++) {
1137d975228cSstefano_zampini     if (cols[i] >= 0) {
1138d975228cSstefano_zampini       cscr[0][nzc  ] = cols[i];
1139d975228cSstefano_zampini       cscr[1][nzc++] = i;
1140d975228cSstefano_zampini     }
1141d975228cSstefano_zampini   }
1142c69f721fSFande Kong   if (!nzc) {
1143708542d2SFande Kong     ierr = MatRestoreArray_HYPRE(A,&array);CHKERRQ(ierr);
1144c69f721fSFande Kong     PetscFunctionReturn(0);
1145c69f721fSFande Kong   }
1146d975228cSstefano_zampini 
1147d975228cSstefano_zampini   if (ins == ADD_VALUES) {
1148d975228cSstefano_zampini     for (i=0;i<nr;i++) {
1149e3977e59Sstefano_zampini       if (rows[i] >= 0 && nzc) {
1150d975228cSstefano_zampini         PetscInt j;
1151d975228cSstefano_zampini         for (j=0;j<nzc;j++) sscr[j] = vals[cscr[1][j]];
115208defe43SFande Kong         PetscStackCallStandard(HYPRE_IJMatrixAddToValues,(hA->ij,1,(HYPRE_Int*)&nzc,(HYPRE_Int*)(rows+i),(HYPRE_Int*)cscr[0],sscr));
1153d975228cSstefano_zampini       }
1154d975228cSstefano_zampini       vals += nc;
1155d975228cSstefano_zampini     }
1156d975228cSstefano_zampini   } else { /* INSERT_VALUES */
1157d975228cSstefano_zampini     PetscInt rst,ren;
1158c69f721fSFande Kong 
1159*c6698e78SStefano Zampini     ierr = MatGetOwnershipRange(A,&rst,&ren);CHKERRQ(ierr);
1160d975228cSstefano_zampini     for (i=0;i<nr;i++) {
1161e3977e59Sstefano_zampini       if (rows[i] >= 0 && nzc) {
1162d975228cSstefano_zampini         PetscInt j;
1163d975228cSstefano_zampini         for (j=0;j<nzc;j++) sscr[j] = vals[cscr[1][j]];
1164c69f721fSFande Kong         /* nonlocal values */
1165c69f721fSFande Kong         if (rows[i] < rst || rows[i] >= ren) { ierr = MatStashValuesRow_Private(&A->stash,rows[i],nzc,cscr[0],sscr,PETSC_FALSE);CHKERRQ(ierr); }
1166c69f721fSFande Kong         /* local values */
116708defe43SFande Kong         else PetscStackCallStandard(HYPRE_IJMatrixSetValues,(hA->ij,1,(HYPRE_Int*)&nzc,(HYPRE_Int*)(rows+i),(HYPRE_Int*)cscr[0],sscr));
1168d975228cSstefano_zampini       }
1169d975228cSstefano_zampini       vals += nc;
1170d975228cSstefano_zampini     }
1171d975228cSstefano_zampini   }
1172c69f721fSFande Kong 
1173708542d2SFande Kong   ierr = MatRestoreArray_HYPRE(A,&array);CHKERRQ(ierr);
1174d975228cSstefano_zampini   PetscFunctionReturn(0);
1175d975228cSstefano_zampini }
1176d975228cSstefano_zampini 
1177d975228cSstefano_zampini static PetscErrorCode MatHYPRESetPreallocation_HYPRE(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[])
1178d975228cSstefano_zampini {
1179d975228cSstefano_zampini   Mat_HYPRE      *hA = (Mat_HYPRE*)A->data;
11807d968826Sstefano_zampini   HYPRE_Int      *hdnnz,*honnz;
118106a29025Sstefano_zampini   PetscInt       i,rs,re,cs,ce,bs;
1182d975228cSstefano_zampini   PetscMPIInt    size;
1183d975228cSstefano_zampini   PetscErrorCode ierr;
1184d975228cSstefano_zampini 
1185d975228cSstefano_zampini   PetscFunctionBegin;
118606a29025Sstefano_zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
1187d975228cSstefano_zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
1188d975228cSstefano_zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
1189d975228cSstefano_zampini   rs   = A->rmap->rstart;
1190d975228cSstefano_zampini   re   = A->rmap->rend;
1191d975228cSstefano_zampini   cs   = A->cmap->rstart;
1192d975228cSstefano_zampini   ce   = A->cmap->rend;
1193d975228cSstefano_zampini   if (!hA->ij) {
1194d975228cSstefano_zampini     PetscStackCallStandard(HYPRE_IJMatrixCreate,(hA->comm,rs,re-1,cs,ce-1,&hA->ij));
1195d975228cSstefano_zampini     PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(hA->ij,HYPRE_PARCSR));
1196d975228cSstefano_zampini   } else {
11977d968826Sstefano_zampini     HYPRE_Int hrs,hre,hcs,hce;
1198d975228cSstefano_zampini     PetscStackCallStandard(HYPRE_IJMatrixGetLocalRange,(hA->ij,&hrs,&hre,&hcs,&hce));
1199d975228cSstefano_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);
1200d975228cSstefano_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);
1201d975228cSstefano_zampini   }
120206a29025Sstefano_zampini   if (dnz == PETSC_DEFAULT || dnz == PETSC_DECIDE) dnz = 10*bs;
120306a29025Sstefano_zampini   if (onz == PETSC_DEFAULT || onz == PETSC_DECIDE) onz = 10*bs;
120406a29025Sstefano_zampini 
1205d975228cSstefano_zampini   if (!dnnz) {
1206d975228cSstefano_zampini     ierr = PetscMalloc1(A->rmap->n,&hdnnz);CHKERRQ(ierr);
1207d975228cSstefano_zampini     for (i=0;i<A->rmap->n;i++) hdnnz[i] = dnz;
1208d975228cSstefano_zampini   } else {
12097d968826Sstefano_zampini     hdnnz = (HYPRE_Int*)dnnz;
1210d975228cSstefano_zampini   }
1211d975228cSstefano_zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRQ(ierr);
1212d975228cSstefano_zampini   if (size > 1) {
1213ddbeb582SStefano Zampini     hypre_AuxParCSRMatrix *aux_matrix;
1214d975228cSstefano_zampini     if (!onnz) {
1215d975228cSstefano_zampini       ierr = PetscMalloc1(A->rmap->n,&honnz);CHKERRQ(ierr);
1216d975228cSstefano_zampini       for (i=0;i<A->rmap->n;i++) honnz[i] = onz;
1217d975228cSstefano_zampini     } else {
12187d968826Sstefano_zampini       honnz = (HYPRE_Int*)onnz;
1219d975228cSstefano_zampini     }
1220ddbeb582SStefano Zampini     /* SetDiagOffdSizes sets hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0, since it seems
1221ddbeb582SStefano Zampini        they assume the user will input the entire row values, properly sorted
1222ddbeb582SStefano Zampini        In PETSc, we don't make such an assumption, and we instead set this flag to 1
1223ddbeb582SStefano Zampini        Also, to avoid possible memory leaks, we destroy and recreate the translator
1224ddbeb582SStefano Zampini        This has to be done here, as HYPRE_IJMatrixInitialize will properly initialize
1225ddbeb582SStefano Zampini        the IJ matrix for us */
1226ddbeb582SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(hA->ij);
1227ddbeb582SStefano Zampini     hypre_AuxParCSRMatrixDestroy(aux_matrix);
1228ddbeb582SStefano Zampini     hypre_IJMatrixTranslator(hA->ij) = NULL;
1229d975228cSstefano_zampini     PetscStackCallStandard(HYPRE_IJMatrixSetDiagOffdSizes,(hA->ij,hdnnz,honnz));
1230ddbeb582SStefano Zampini     aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(hA->ij);
1231ddbeb582SStefano Zampini     hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 1;
1232d975228cSstefano_zampini   } else {
1233d975228cSstefano_zampini     honnz = NULL;
1234d975228cSstefano_zampini     PetscStackCallStandard(HYPRE_IJMatrixSetRowSizes,(hA->ij,hdnnz));
1235d975228cSstefano_zampini   }
1236ddbeb582SStefano Zampini 
1237af1cf968SStefano Zampini   /* reset assembled flag and call the initialize method */
1238af1cf968SStefano Zampini   hypre_IJMatrixAssembleFlag(hA->ij) = 0;
1239ddbeb582SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixInitialize,(hA->ij));
1240d975228cSstefano_zampini   if (!dnnz) {
1241d975228cSstefano_zampini     ierr = PetscFree(hdnnz);CHKERRQ(ierr);
1242d975228cSstefano_zampini   }
1243d975228cSstefano_zampini   if (!onnz && honnz) {
1244d975228cSstefano_zampini     ierr = PetscFree(honnz);CHKERRQ(ierr);
1245d975228cSstefano_zampini   }
1246af1cf968SStefano Zampini 
1247af1cf968SStefano Zampini   /* Match AIJ logic */
124806a29025Sstefano_zampini   A->preallocated = PETSC_TRUE;
1249af1cf968SStefano Zampini   A->assembled    = PETSC_FALSE;
1250d975228cSstefano_zampini   PetscFunctionReturn(0);
1251d975228cSstefano_zampini }
1252d975228cSstefano_zampini 
1253d975228cSstefano_zampini /*@C
1254d975228cSstefano_zampini    MatHYPRESetPreallocation - Preallocates memory for a sparse parallel matrix in HYPRE IJ format
1255d975228cSstefano_zampini 
1256d975228cSstefano_zampini    Collective on Mat
1257d975228cSstefano_zampini 
1258d975228cSstefano_zampini    Input Parameters:
1259d975228cSstefano_zampini +  A - the matrix
1260d975228cSstefano_zampini .  dnz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1261d975228cSstefano_zampini           (same value is used for all local rows)
1262d975228cSstefano_zampini .  dnnz - array containing the number of nonzeros in the various rows of the
1263d975228cSstefano_zampini           DIAGONAL portion of the local submatrix (possibly different for each row)
1264d975228cSstefano_zampini           or NULL (PETSC_NULL_INTEGER in Fortran), if d_nz is used to specify the nonzero structure.
1265d975228cSstefano_zampini           The size of this array is equal to the number of local rows, i.e 'm'.
1266d975228cSstefano_zampini           For matrices that will be factored, you must leave room for (and set)
1267d975228cSstefano_zampini           the diagonal entry even if it is zero.
1268d975228cSstefano_zampini .  onz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1269d975228cSstefano_zampini           submatrix (same value is used for all local rows).
1270d975228cSstefano_zampini -  onnz - array containing the number of nonzeros in the various rows of the
1271d975228cSstefano_zampini           OFF-DIAGONAL portion of the local submatrix (possibly different for
1272d975228cSstefano_zampini           each row) or NULL (PETSC_NULL_INTEGER in Fortran), if o_nz is used to specify the nonzero
1273d975228cSstefano_zampini           structure. The size of this array is equal to the number
1274d975228cSstefano_zampini           of local rows, i.e 'm'.
1275d975228cSstefano_zampini 
127695452b02SPatrick Sanan    Notes:
127795452b02SPatrick Sanan     If the *nnz parameter is given then the *nz parameter is ignored; for sequential matrices, onz and onnz are ignored.
1278d975228cSstefano_zampini 
1279d975228cSstefano_zampini    Level: intermediate
1280d975228cSstefano_zampini 
1281d975228cSstefano_zampini .keywords: matrix, aij, compressed row, sparse, parallel
1282d975228cSstefano_zampini 
1283af1cf968SStefano Zampini .seealso: MatCreate(), MatMPIAIJSetPreallocation(), MATHYPRE
1284d975228cSstefano_zampini @*/
1285d975228cSstefano_zampini PetscErrorCode MatHYPRESetPreallocation(Mat A, PetscInt dnz, const PetscInt dnnz[], PetscInt onz, const PetscInt onnz[])
1286d975228cSstefano_zampini {
1287d975228cSstefano_zampini   PetscErrorCode ierr;
1288d975228cSstefano_zampini 
1289d975228cSstefano_zampini   PetscFunctionBegin;
1290d975228cSstefano_zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
1291d975228cSstefano_zampini   PetscValidType(A,1);
1292d975228cSstefano_zampini   ierr = PetscTryMethod(A,"MatHYPRESetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(A,dnz,dnnz,onz,onnz));CHKERRQ(ierr);
1293d975228cSstefano_zampini   PetscFunctionReturn(0);
1294d975228cSstefano_zampini }
1295d975228cSstefano_zampini 
1296225daaf8SStefano Zampini /*
1297225daaf8SStefano Zampini    MatCreateFromParCSR - Creates a matrix from a hypre_ParCSRMatrix
1298225daaf8SStefano Zampini 
1299225daaf8SStefano Zampini    Collective
1300225daaf8SStefano Zampini 
1301225daaf8SStefano Zampini    Input Parameters:
130245b8d346SStefano Zampini +  parcsr   - the pointer to the hypre_ParCSRMatrix
1303bb4689ddSStefano Zampini .  mtype    - matrix type to be created. Currently MATAIJ, MATIS and MATHYPRE are supported.
1304225daaf8SStefano Zampini -  copymode - PETSc copying options
1305225daaf8SStefano Zampini 
1306225daaf8SStefano Zampini    Output Parameter:
1307225daaf8SStefano Zampini .  A  - the matrix
1308225daaf8SStefano Zampini 
1309225daaf8SStefano Zampini    Level: intermediate
1310225daaf8SStefano Zampini 
1311225daaf8SStefano Zampini .seealso: MatHYPRE, PetscCopyMode
1312225daaf8SStefano Zampini */
131345b8d346SStefano Zampini PETSC_EXTERN PetscErrorCode MatCreateFromParCSR(hypre_ParCSRMatrix *parcsr, MatType mtype, PetscCopyMode copymode, Mat* A)
1314978814f1SStefano Zampini {
1315225daaf8SStefano Zampini   Mat                   T;
1316978814f1SStefano Zampini   Mat_HYPRE             *hA;
1317978814f1SStefano Zampini   MPI_Comm              comm;
1318978814f1SStefano Zampini   PetscInt              rstart,rend,cstart,cend,M,N;
1319bb4689ddSStefano Zampini   PetscBool             isseqaij,ismpiaij,isaij,ishyp,isis;
1320978814f1SStefano Zampini   PetscErrorCode        ierr;
1321978814f1SStefano Zampini 
1322978814f1SStefano Zampini   PetscFunctionBegin;
1323978814f1SStefano Zampini   comm   = hypre_ParCSRMatrixComm(parcsr);
1324225daaf8SStefano Zampini   ierr   = PetscStrcmp(mtype,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
1325225daaf8SStefano Zampini   ierr   = PetscStrcmp(mtype,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
1326225daaf8SStefano Zampini   ierr   = PetscStrcmp(mtype,MATAIJ,&isaij);CHKERRQ(ierr);
1327225daaf8SStefano Zampini   ierr   = PetscStrcmp(mtype,MATHYPRE,&ishyp);CHKERRQ(ierr);
13288cfe8d00SStefano Zampini   ierr   = PetscStrcmp(mtype,MATIS,&isis);CHKERRQ(ierr);
1329225daaf8SStefano Zampini   isaij  = (PetscBool)(isseqaij || ismpiaij || isaij);
1330bb4689ddSStefano Zampini   if (!isaij && !ishyp && !isis) SETERRQ6(comm,PETSC_ERR_SUP,"Unsupported MatType %s! Supported types are %s, %s, %s, %s, and %s",mtype,MATAIJ,MATSEQAIJ,MATMPIAIJ,MATIS,MATHYPRE);
1331978814f1SStefano Zampini   /* access ParCSRMatrix */
1332978814f1SStefano Zampini   rstart = hypre_ParCSRMatrixFirstRowIndex(parcsr);
1333978814f1SStefano Zampini   rend   = hypre_ParCSRMatrixLastRowIndex(parcsr);
1334978814f1SStefano Zampini   cstart = hypre_ParCSRMatrixFirstColDiag(parcsr);
1335978814f1SStefano Zampini   cend   = hypre_ParCSRMatrixLastColDiag(parcsr);
1336978814f1SStefano Zampini   M      = hypre_ParCSRMatrixGlobalNumRows(parcsr);
1337978814f1SStefano Zampini   N      = hypre_ParCSRMatrixGlobalNumCols(parcsr);
1338978814f1SStefano Zampini 
1339fa92c42cSstefano_zampini   /* fix for empty local rows/columns */
1340fa92c42cSstefano_zampini   if (rend < rstart) rend = rstart;
1341fa92c42cSstefano_zampini   if (cend < cstart) cend = cstart;
1342fa92c42cSstefano_zampini 
1343e6471dc9SStefano Zampini   /* PETSc convention */
1344e6471dc9SStefano Zampini   rend++;
1345e6471dc9SStefano Zampini   cend++;
1346e6471dc9SStefano Zampini   rend = PetscMin(rend,M);
1347e6471dc9SStefano Zampini   cend = PetscMin(cend,N);
1348e6471dc9SStefano Zampini 
1349978814f1SStefano Zampini   /* create PETSc matrix with MatHYPRE */
1350225daaf8SStefano Zampini   ierr = MatCreate(comm,&T);CHKERRQ(ierr);
1351e6471dc9SStefano Zampini   ierr = MatSetSizes(T,rend-rstart,cend-cstart,M,N);CHKERRQ(ierr);
1352225daaf8SStefano Zampini   ierr = MatSetType(T,MATHYPRE);CHKERRQ(ierr);
1353225daaf8SStefano Zampini   hA   = (Mat_HYPRE*)(T->data);
1354978814f1SStefano Zampini 
1355978814f1SStefano Zampini   /* create HYPRE_IJMatrix */
1356978814f1SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixCreate,(hA->comm,rstart,rend-1,cstart,cend-1,&hA->ij));
135745b8d346SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(hA->ij,HYPRE_PARCSR));
135845b8d346SStefano Zampini 
135945b8d346SStefano Zampini   /* create new ParCSR object if needed */
136045b8d346SStefano Zampini   if (ishyp && copymode == PETSC_COPY_VALUES) {
136145b8d346SStefano Zampini     hypre_ParCSRMatrix *new_parcsr;
136245b8d346SStefano Zampini     hypre_CSRMatrix    *hdiag,*hoffd,*ndiag,*noffd;
136345b8d346SStefano Zampini 
136445b8d346SStefano Zampini     new_parcsr = hypre_ParCSRMatrixCompleteClone(parcsr);
136545b8d346SStefano Zampini     hdiag      = hypre_ParCSRMatrixDiag(parcsr);
136645b8d346SStefano Zampini     hoffd      = hypre_ParCSRMatrixOffd(parcsr);
136745b8d346SStefano Zampini     ndiag      = hypre_ParCSRMatrixDiag(new_parcsr);
136845b8d346SStefano Zampini     noffd      = hypre_ParCSRMatrixOffd(new_parcsr);
136945b8d346SStefano Zampini     ierr       = PetscMemcpy(hypre_CSRMatrixData(ndiag),hypre_CSRMatrixData(hdiag),hypre_CSRMatrixNumNonzeros(hdiag)*sizeof(PetscScalar));CHKERRQ(ierr);
137045b8d346SStefano Zampini     ierr       = PetscMemcpy(hypre_CSRMatrixData(noffd),hypre_CSRMatrixData(hoffd),hypre_CSRMatrixNumNonzeros(hoffd)*sizeof(PetscScalar));CHKERRQ(ierr);
137145b8d346SStefano Zampini     parcsr     = new_parcsr;
137245b8d346SStefano Zampini     copymode   = PETSC_OWN_POINTER;
137345b8d346SStefano Zampini   }
1374978814f1SStefano Zampini 
1375978814f1SStefano Zampini   /* set ParCSR object */
1376978814f1SStefano Zampini   hypre_IJMatrixObject(hA->ij) = parcsr;
13774ec6421dSstefano_zampini   T->preallocated = PETSC_TRUE;
1378978814f1SStefano Zampini 
1379978814f1SStefano Zampini   /* set assembled flag */
1380978814f1SStefano Zampini   hypre_IJMatrixAssembleFlag(hA->ij) = 1;
1381978814f1SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixInitialize,(hA->ij));
1382225daaf8SStefano Zampini   if (ishyp) {
13836d2a658fSstefano_zampini     PetscMPIInt myid = 0;
13846d2a658fSstefano_zampini 
13856d2a658fSstefano_zampini     /* make sure we always have row_starts and col_starts available */
13866d2a658fSstefano_zampini     if (HYPRE_AssumedPartitionCheck()) {
13876d2a658fSstefano_zampini       ierr = MPI_Comm_rank(comm,&myid);CHKERRQ(ierr);
13886d2a658fSstefano_zampini     }
13896d2a658fSstefano_zampini     if (!hypre_ParCSRMatrixOwnsColStarts(parcsr)) {
13906d2a658fSstefano_zampini       PetscLayout map;
13916d2a658fSstefano_zampini 
13926d2a658fSstefano_zampini       ierr = MatGetLayouts(T,NULL,&map);CHKERRQ(ierr);
13936d2a658fSstefano_zampini       ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
13941c92d2d0Sstefano_zampini       hypre_ParCSRMatrixColStarts(parcsr) = (HYPRE_Int*)(map->range + myid);
13956d2a658fSstefano_zampini     }
13966d2a658fSstefano_zampini     if (!hypre_ParCSRMatrixOwnsRowStarts(parcsr)) {
13976d2a658fSstefano_zampini       PetscLayout map;
13986d2a658fSstefano_zampini 
13996d2a658fSstefano_zampini       ierr = MatGetLayouts(T,&map,NULL);CHKERRQ(ierr);
14006d2a658fSstefano_zampini       ierr = PetscLayoutSetUp(map);CHKERRQ(ierr);
14011c92d2d0Sstefano_zampini       hypre_ParCSRMatrixRowStarts(parcsr) = (HYPRE_Int*)(map->range + myid);
14026d2a658fSstefano_zampini     }
1403978814f1SStefano Zampini     /* prevent from freeing the pointer */
1404978814f1SStefano Zampini     if (copymode == PETSC_USE_POINTER) hA->inner_free = PETSC_FALSE;
1405225daaf8SStefano Zampini     *A   = T;
1406978814f1SStefano Zampini     ierr = MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1407978814f1SStefano Zampini     ierr = MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1408bb4689ddSStefano Zampini   } else if (isaij) {
1409bb4689ddSStefano Zampini     if (copymode != PETSC_OWN_POINTER) {
1410225daaf8SStefano Zampini       /* prevent from freeing the pointer */
1411225daaf8SStefano Zampini       hA->inner_free = PETSC_FALSE;
1412225daaf8SStefano Zampini       ierr = MatConvert_HYPRE_AIJ(T,MATAIJ,MAT_INITIAL_MATRIX,A);CHKERRQ(ierr);
1413225daaf8SStefano Zampini       ierr = MatDestroy(&T);CHKERRQ(ierr);
1414225daaf8SStefano Zampini     } else { /* AIJ return type with PETSC_OWN_POINTER */
1415225daaf8SStefano Zampini       ierr = MatConvert_HYPRE_AIJ(T,MATAIJ,MAT_INPLACE_MATRIX,&T);CHKERRQ(ierr);
1416225daaf8SStefano Zampini       *A   = T;
1417225daaf8SStefano Zampini     }
1418bb4689ddSStefano Zampini   } else if (isis) {
14198cfe8d00SStefano Zampini     ierr = MatConvert_HYPRE_IS(T,MATIS,MAT_INITIAL_MATRIX,A);CHKERRQ(ierr);
14208cfe8d00SStefano Zampini     if (copymode != PETSC_OWN_POINTER) hA->inner_free = PETSC_FALSE;
1421bb4689ddSStefano Zampini     ierr = MatDestroy(&T);CHKERRQ(ierr);
1422bb4689ddSStefano Zampini   }
1423978814f1SStefano Zampini   PetscFunctionReturn(0);
1424978814f1SStefano Zampini }
1425978814f1SStefano Zampini 
142668ec7858SStefano Zampini static PetscErrorCode MatHYPREGetParCSR_HYPRE(Mat A, hypre_ParCSRMatrix **parcsr)
1427dd9c0a25Sstefano_zampini {
1428dd9c0a25Sstefano_zampini   Mat_HYPRE *hA = (Mat_HYPRE*)A->data;
1429dd9c0a25Sstefano_zampini   HYPRE_Int type;
1430dd9c0a25Sstefano_zampini 
1431dd9c0a25Sstefano_zampini   PetscFunctionBegin;
1432dd9c0a25Sstefano_zampini   if (!hA->ij) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"HYPRE_IJMatrix not present");
1433dd9c0a25Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type));
1434dd9c0a25Sstefano_zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"HYPRE_IJMatrix is not of type HYPRE_PARCSR");
1435dd9c0a25Sstefano_zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)parcsr));
1436dd9c0a25Sstefano_zampini   PetscFunctionReturn(0);
1437dd9c0a25Sstefano_zampini }
1438dd9c0a25Sstefano_zampini 
1439dd9c0a25Sstefano_zampini /*
1440dd9c0a25Sstefano_zampini    MatHYPREGetParCSR - Gets the pointer to the ParCSR matrix
1441dd9c0a25Sstefano_zampini 
1442dd9c0a25Sstefano_zampini    Not collective
1443dd9c0a25Sstefano_zampini 
1444dd9c0a25Sstefano_zampini    Input Parameters:
1445dd9c0a25Sstefano_zampini +  A  - the MATHYPRE object
1446dd9c0a25Sstefano_zampini 
1447dd9c0a25Sstefano_zampini    Output Parameter:
1448dd9c0a25Sstefano_zampini .  parcsr  - the pointer to the hypre_ParCSRMatrix
1449dd9c0a25Sstefano_zampini 
1450dd9c0a25Sstefano_zampini    Level: intermediate
1451dd9c0a25Sstefano_zampini 
1452dd9c0a25Sstefano_zampini .seealso: MatHYPRE, PetscCopyMode
1453dd9c0a25Sstefano_zampini */
1454dd9c0a25Sstefano_zampini PetscErrorCode MatHYPREGetParCSR(Mat A, hypre_ParCSRMatrix **parcsr)
1455dd9c0a25Sstefano_zampini {
1456dd9c0a25Sstefano_zampini   PetscErrorCode ierr;
1457dd9c0a25Sstefano_zampini 
1458dd9c0a25Sstefano_zampini   PetscFunctionBegin;
1459dd9c0a25Sstefano_zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
1460dd9c0a25Sstefano_zampini   PetscValidType(A,1);
1461dd9c0a25Sstefano_zampini   ierr = PetscUseMethod(A,"MatHYPREGetParCSR_C",(Mat,hypre_ParCSRMatrix**),(A,parcsr));CHKERRQ(ierr);
1462dd9c0a25Sstefano_zampini   PetscFunctionReturn(0);
1463dd9c0a25Sstefano_zampini }
1464dd9c0a25Sstefano_zampini 
146568ec7858SStefano Zampini static PetscErrorCode MatMissingDiagonal_HYPRE(Mat A, PetscBool *missing, PetscInt *dd)
146668ec7858SStefano Zampini {
146768ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
146868ec7858SStefano Zampini   hypre_CSRMatrix    *ha;
146968ec7858SStefano Zampini   PetscInt           rst;
147068ec7858SStefano Zampini   PetscErrorCode     ierr;
147168ec7858SStefano Zampini 
147268ec7858SStefano Zampini   PetscFunctionBegin;
147368ec7858SStefano Zampini   if (A->rmap->n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented with non-square diagonal blocks");
147468ec7858SStefano Zampini   ierr = MatGetOwnershipRange(A,&rst,NULL);CHKERRQ(ierr);
147568ec7858SStefano Zampini   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
147668ec7858SStefano Zampini   if (missing) *missing = PETSC_FALSE;
147768ec7858SStefano Zampini   if (dd) *dd = -1;
147868ec7858SStefano Zampini   ha = hypre_ParCSRMatrixDiag(parcsr);
147968ec7858SStefano Zampini   if (ha) {
148068299464SStefano Zampini     PetscInt  size,i;
148168299464SStefano Zampini     HYPRE_Int *ii,*jj;
148268ec7858SStefano Zampini 
148368ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
148468ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
148568ec7858SStefano Zampini     jj   = hypre_CSRMatrixJ(ha);
148668ec7858SStefano Zampini     for (i = 0; i < size; i++) {
148768ec7858SStefano Zampini       PetscInt  j;
148868ec7858SStefano Zampini       PetscBool found = PETSC_FALSE;
148968ec7858SStefano Zampini 
149068ec7858SStefano Zampini       for (j = ii[i]; j < ii[i+1] && !found; j++)
149168ec7858SStefano Zampini         found = (jj[j] == i) ? PETSC_TRUE : PETSC_FALSE;
149268ec7858SStefano Zampini 
149368ec7858SStefano Zampini       if (!found) {
149468ec7858SStefano Zampini         PetscInfo1(A,"Matrix is missing local diagonal entry %D\n",i);
149568ec7858SStefano Zampini         if (missing) *missing = PETSC_TRUE;
149668ec7858SStefano Zampini         if (dd) *dd = i+rst;
149768ec7858SStefano Zampini         PetscFunctionReturn(0);
149868ec7858SStefano Zampini       }
149968ec7858SStefano Zampini     }
150068ec7858SStefano Zampini     if (!size) {
150168ec7858SStefano Zampini       PetscInfo(A,"Matrix has no diagonal entries therefore is missing diagonal\n");
150268ec7858SStefano Zampini       if (missing) *missing = PETSC_TRUE;
150368ec7858SStefano Zampini       if (dd) *dd = rst;
150468ec7858SStefano Zampini     }
150568ec7858SStefano Zampini   } else {
150668ec7858SStefano Zampini     PetscInfo(A,"Matrix has no diagonal entries therefore is missing diagonal\n");
150768ec7858SStefano Zampini     if (missing) *missing = PETSC_TRUE;
150868ec7858SStefano Zampini     if (dd) *dd = rst;
150968ec7858SStefano Zampini   }
151068ec7858SStefano Zampini   PetscFunctionReturn(0);
151168ec7858SStefano Zampini }
151268ec7858SStefano Zampini 
151368ec7858SStefano Zampini static PetscErrorCode MatScale_HYPRE(Mat A, PetscScalar s)
151468ec7858SStefano Zampini {
151568ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
151668ec7858SStefano Zampini   hypre_CSRMatrix    *ha;
151768ec7858SStefano Zampini   PetscErrorCode     ierr;
151868ec7858SStefano Zampini 
151968ec7858SStefano Zampini   PetscFunctionBegin;
152068ec7858SStefano Zampini   ierr  = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
152168ec7858SStefano Zampini   /* diagonal part */
152268ec7858SStefano Zampini   ha = hypre_ParCSRMatrixDiag(parcsr);
152368ec7858SStefano Zampini   if (ha) {
152468299464SStefano Zampini     PetscInt    size,i;
152568299464SStefano Zampini     HYPRE_Int   *ii;
152668ec7858SStefano Zampini     PetscScalar *a;
152768ec7858SStefano Zampini 
152868ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
152968ec7858SStefano Zampini     a    = hypre_CSRMatrixData(ha);
153068ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
153168ec7858SStefano Zampini     for (i = 0; i < ii[size]; i++) a[i] *= s;
153268ec7858SStefano Zampini   }
153368ec7858SStefano Zampini   /* offdiagonal part */
153468ec7858SStefano Zampini   ha = hypre_ParCSRMatrixOffd(parcsr);
153568ec7858SStefano Zampini   if (ha) {
153668299464SStefano Zampini     PetscInt    size,i;
153768299464SStefano Zampini     HYPRE_Int   *ii;
153868ec7858SStefano Zampini     PetscScalar *a;
153968ec7858SStefano Zampini 
154068ec7858SStefano Zampini     size = hypre_CSRMatrixNumRows(ha);
154168ec7858SStefano Zampini     a    = hypre_CSRMatrixData(ha);
154268ec7858SStefano Zampini     ii   = hypre_CSRMatrixI(ha);
154368ec7858SStefano Zampini     for (i = 0; i < ii[size]; i++) a[i] *= s;
154468ec7858SStefano Zampini   }
154568ec7858SStefano Zampini   PetscFunctionReturn(0);
154668ec7858SStefano Zampini }
154768ec7858SStefano Zampini 
154868ec7858SStefano Zampini static PetscErrorCode MatZeroRowsColumns_HYPRE(Mat A, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
154968ec7858SStefano Zampini {
155068ec7858SStefano Zampini   hypre_ParCSRMatrix *parcsr;
155168299464SStefano Zampini   HYPRE_Int          *lrows;
155268299464SStefano Zampini   PetscInt           rst,ren,i;
155368ec7858SStefano Zampini   PetscErrorCode     ierr;
155468ec7858SStefano Zampini 
155568ec7858SStefano Zampini   PetscFunctionBegin;
155668ec7858SStefano Zampini   if (x || b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"To be implemented");
155768ec7858SStefano Zampini   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
155868ec7858SStefano Zampini   ierr = PetscMalloc1(numRows,&lrows);CHKERRQ(ierr);
155968ec7858SStefano Zampini   ierr = MatGetOwnershipRange(A,&rst,&ren);CHKERRQ(ierr);
156068ec7858SStefano Zampini   for (i=0;i<numRows;i++) {
156168ec7858SStefano Zampini     if (rows[i] < rst || rows[i] >= ren)
156268ec7858SStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Non-local rows not yet supported");
156368ec7858SStefano Zampini     lrows[i] = rows[i] - rst;
156468ec7858SStefano Zampini   }
156568ec7858SStefano Zampini   PetscStackCallStandard(hypre_ParCSRMatrixEliminateRowsCols,(parcsr,numRows,lrows));
156668ec7858SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
156768ec7858SStefano Zampini   PetscFunctionReturn(0);
156868ec7858SStefano Zampini }
156968ec7858SStefano Zampini 
1570c69f721fSFande Kong static PetscErrorCode MatZeroEntries_HYPRE_CSRMatrix(hypre_CSRMatrix *ha)
1571c69f721fSFande Kong {
1572c69f721fSFande Kong   PetscErrorCode      ierr;
1573c69f721fSFande Kong 
1574c69f721fSFande Kong   PetscFunctionBegin;
1575c69f721fSFande Kong   if (ha) {
1576c69f721fSFande Kong     HYPRE_Int     *ii, size;
1577c69f721fSFande Kong     HYPRE_Complex *a;
1578c69f721fSFande Kong 
1579c69f721fSFande Kong     size = hypre_CSRMatrixNumRows(ha);
1580c69f721fSFande Kong     a    = hypre_CSRMatrixData(ha);
1581c69f721fSFande Kong     ii   = hypre_CSRMatrixI(ha);
1582c69f721fSFande Kong 
1583c69f721fSFande Kong     if (a) { ierr = PetscMemzero(a,(ii[size])*sizeof(HYPRE_Complex));CHKERRQ(ierr); }
1584c69f721fSFande Kong   }
1585c69f721fSFande Kong   PetscFunctionReturn(0);
1586c69f721fSFande Kong }
1587c69f721fSFande Kong 
1588c69f721fSFande Kong PetscErrorCode MatZeroEntries_HYPRE(Mat A)
1589c69f721fSFande Kong {
1590c69f721fSFande Kong   hypre_ParCSRMatrix  *parcsr;
1591c69f721fSFande Kong   PetscErrorCode      ierr;
1592c69f721fSFande Kong 
1593c69f721fSFande Kong   PetscFunctionBegin;
1594c69f721fSFande Kong   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
1595c69f721fSFande Kong   /* diagonal part */
1596c69f721fSFande Kong   ierr = MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr));CHKERRQ(ierr);
1597c69f721fSFande Kong   /* off-diagonal part */
1598c69f721fSFande Kong   ierr = MatZeroEntries_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr));CHKERRQ(ierr);
1599c69f721fSFande Kong   PetscFunctionReturn(0);
1600c69f721fSFande Kong }
1601c69f721fSFande Kong 
1602c69f721fSFande Kong static PetscErrorCode MatZeroRows_HYPRE_CSRMatrix(hypre_CSRMatrix *hA,PetscInt N,const PetscInt rows[],PetscScalar diag)
1603c69f721fSFande Kong {
1604c69f721fSFande Kong   PetscInt        ii, jj, ibeg, iend, irow;
1605c69f721fSFande Kong   PetscInt        *i, *j;
1606c69f721fSFande Kong   PetscScalar     *a;
1607c69f721fSFande Kong 
1608c69f721fSFande Kong   PetscFunctionBegin;
1609c69f721fSFande Kong   if (!hA) PetscFunctionReturn(0);
1610c69f721fSFande Kong 
161108defe43SFande Kong   i = (PetscInt*) hypre_CSRMatrixI(hA);
161208defe43SFande Kong   j = (PetscInt*) hypre_CSRMatrixJ(hA);
1613c69f721fSFande Kong   a = hypre_CSRMatrixData(hA);
1614c69f721fSFande Kong 
1615c69f721fSFande Kong   for (ii = 0; ii < N; ii++) {
1616c69f721fSFande Kong     irow = rows[ii];
1617c69f721fSFande Kong     ibeg = i[irow];
1618c69f721fSFande Kong     iend = i[irow+1];
1619c69f721fSFande Kong     for (jj = ibeg; jj < iend; jj++)
1620c69f721fSFande Kong       if (j[jj] == irow) a[jj] = diag;
1621c69f721fSFande Kong       else a[jj] = 0.0;
1622c69f721fSFande Kong    }
1623c69f721fSFande Kong    PetscFunctionReturn(0);
1624c69f721fSFande Kong }
1625c69f721fSFande Kong 
1626ddbeb582SStefano Zampini static PetscErrorCode MatZeroRows_HYPRE(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1627c69f721fSFande Kong {
1628c69f721fSFande Kong   hypre_ParCSRMatrix  *parcsr;
1629c69f721fSFande Kong   PetscInt            *lrows,len;
1630c69f721fSFande Kong   PetscErrorCode      ierr;
1631c69f721fSFande Kong 
1632c69f721fSFande Kong   PetscFunctionBegin;
1633*c6698e78SStefano Zampini   if (x || b) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Does not support to modify the solution and the right hand size");
1634c69f721fSFande Kong   /* retrieve the internal matrix */
1635c69f721fSFande Kong   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
1636c69f721fSFande Kong   /* get locally owned rows */
1637c69f721fSFande Kong   ierr = MatZeroRowsMapLocal_Private(A,N,rows,&len,&lrows);CHKERRQ(ierr);
1638c69f721fSFande Kong   /* zero diagonal part */
1639c69f721fSFande Kong   ierr = MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixDiag(parcsr),len,lrows,diag);CHKERRQ(ierr);
1640c69f721fSFande Kong   /* zero off-diagonal part */
1641c69f721fSFande Kong   ierr = MatZeroRows_HYPRE_CSRMatrix(hypre_ParCSRMatrixOffd(parcsr),len,lrows,0.0);CHKERRQ(ierr);
1642c69f721fSFande Kong 
1643c69f721fSFande Kong   ierr = PetscFree(lrows);CHKERRQ(ierr);
1644c69f721fSFande Kong   PetscFunctionReturn(0);
1645c69f721fSFande Kong }
1646c69f721fSFande Kong 
1647ddbeb582SStefano Zampini static PetscErrorCode MatAssemblyBegin_HYPRE(Mat mat,MatAssemblyType mode)
1648c69f721fSFande Kong {
1649c69f721fSFande Kong   PetscErrorCode ierr;
1650c69f721fSFande Kong 
1651c69f721fSFande Kong   PetscFunctionBegin;
1652c69f721fSFande Kong   if (mat->nooffprocentries) PetscFunctionReturn(0);
1653c69f721fSFande Kong 
1654c69f721fSFande Kong   ierr = MatStashScatterBegin_Private(mat,&mat->stash,mat->rmap->range);CHKERRQ(ierr);
1655c69f721fSFande Kong   PetscFunctionReturn(0);
1656c69f721fSFande Kong }
1657c69f721fSFande Kong 
1658ddbeb582SStefano Zampini static PetscErrorCode MatGetRow_HYPRE(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
1659c69f721fSFande Kong {
1660c69f721fSFande Kong   hypre_ParCSRMatrix  *parcsr;
1661c69f721fSFande Kong   PetscErrorCode      ierr;
1662c69f721fSFande Kong 
1663c69f721fSFande Kong   PetscFunctionBegin;
1664c69f721fSFande Kong   /* retrieve the internal matrix */
1665c69f721fSFande Kong   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
1666c69f721fSFande Kong   /* call HYPRE API */
166708defe43SFande Kong   PetscStackCallStandard(HYPRE_ParCSRMatrixGetRow,(parcsr,row,(HYPRE_Int*)nz,(HYPRE_Int**)idx,v));
1668c69f721fSFande Kong   PetscFunctionReturn(0);
1669c69f721fSFande Kong }
1670c69f721fSFande Kong 
1671ddbeb582SStefano Zampini static PetscErrorCode MatRestoreRow_HYPRE(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
1672c69f721fSFande Kong {
1673c69f721fSFande Kong   hypre_ParCSRMatrix  *parcsr;
1674c69f721fSFande Kong   PetscErrorCode      ierr;
1675c69f721fSFande Kong 
1676c69f721fSFande Kong   PetscFunctionBegin;
1677c69f721fSFande Kong   /* retrieve the internal matrix */
1678c69f721fSFande Kong   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
1679c69f721fSFande Kong   /* call HYPRE API */
168008defe43SFande Kong   PetscStackCallStandard(HYPRE_ParCSRMatrixRestoreRow,(parcsr,row,(HYPRE_Int*)nz,(HYPRE_Int**)idx,v));
1681c69f721fSFande Kong   PetscFunctionReturn(0);
1682c69f721fSFande Kong }
1683c69f721fSFande Kong 
1684ddbeb582SStefano Zampini static PetscErrorCode MatGetValues_HYPRE(Mat A,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],PetscScalar v[])
1685c69f721fSFande Kong {
168645b8d346SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE*)A->data;
1687c69f721fSFande Kong   PetscInt  i;
16881d4906efSStefano Zampini 
1689c69f721fSFande Kong   PetscFunctionBegin;
1690c69f721fSFande Kong   if (!m || !n) PetscFunctionReturn(0);
1691c69f721fSFande Kong   /* Ignore negative row indices
1692c69f721fSFande Kong    * And negative column indices should be automatically ignored in hypre
1693c69f721fSFande Kong    * */
1694c69f721fSFande Kong   for (i=0; i<m; i++)
169545b8d346SStefano Zampini     if (idxm[i] >= 0) PetscStackCallStandard(HYPRE_IJMatrixGetValues,(hA->ij,1,(HYPRE_Int*)&n,(HYPRE_Int*)&idxm[i],(HYPRE_Int*)idxn,&v[i*n]));
1696c69f721fSFande Kong   PetscFunctionReturn(0);
1697c69f721fSFande Kong }
1698c69f721fSFande Kong 
1699ddbeb582SStefano Zampini static PetscErrorCode MatSetOption_HYPRE(Mat A,MatOption op,PetscBool flg)
1700ddbeb582SStefano Zampini {
1701ddbeb582SStefano Zampini   Mat_HYPRE *hA = (Mat_HYPRE*)A->data;
1702ddbeb582SStefano Zampini 
1703ddbeb582SStefano Zampini   PetscFunctionBegin;
1704*c6698e78SStefano Zampini   switch (op) {
1705ddbeb582SStefano Zampini   case MAT_NO_OFF_PROC_ENTRIES:
1706ddbeb582SStefano Zampini     if (flg) {
1707ddbeb582SStefano Zampini       PetscStackCallStandard(HYPRE_IJMatrixSetMaxOffProcElmts,(hA->ij,0));
1708ddbeb582SStefano Zampini     }
1709ddbeb582SStefano Zampini     break;
1710ddbeb582SStefano Zampini   default:
1711ddbeb582SStefano Zampini     break;
1712ddbeb582SStefano Zampini   }
1713ddbeb582SStefano Zampini   PetscFunctionReturn(0);
1714ddbeb582SStefano Zampini }
1715c69f721fSFande Kong 
171645b8d346SStefano Zampini static PetscErrorCode MatView_HYPRE(Mat A, PetscViewer view)
171745b8d346SStefano Zampini {
171845b8d346SStefano Zampini   hypre_ParCSRMatrix *parcsr;
171945b8d346SStefano Zampini   PetscErrorCode     ierr;
172045b8d346SStefano Zampini   Mat                B;
172145b8d346SStefano Zampini   PetscViewerFormat  format;
172245b8d346SStefano Zampini   PetscErrorCode     (*mview)(Mat,PetscViewer) = NULL;
172345b8d346SStefano Zampini 
172445b8d346SStefano Zampini   PetscFunctionBegin;
172545b8d346SStefano Zampini   ierr = PetscViewerGetFormat(view,&format);CHKERRQ(ierr);
172645b8d346SStefano Zampini   if (format != PETSC_VIEWER_NATIVE) {
172745b8d346SStefano Zampini     ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
172845b8d346SStefano Zampini     ierr = MatCreateFromParCSR(parcsr,MATAIJ,PETSC_USE_POINTER,&B);CHKERRQ(ierr);
172945b8d346SStefano Zampini     ierr = MatGetOperation(B,MATOP_VIEW,(void(**)(void))&mview);CHKERRQ(ierr);
173045b8d346SStefano Zampini     if (!mview) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Missing view operation");CHKERRQ(ierr);
173145b8d346SStefano Zampini     ierr = (*mview)(B,view);CHKERRQ(ierr);
173245b8d346SStefano Zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
173345b8d346SStefano Zampini   } else {
173445b8d346SStefano Zampini     Mat_HYPRE  *hA = (Mat_HYPRE*)A->data;
173545b8d346SStefano Zampini     PetscMPIInt size;
173645b8d346SStefano Zampini     PetscBool   isascii;
173745b8d346SStefano Zampini     const char *filename;
173845b8d346SStefano Zampini 
173945b8d346SStefano Zampini     /* HYPRE uses only text files */
174045b8d346SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)view,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
174145b8d346SStefano Zampini     if (!isascii) SETERRQ1(PetscObjectComm((PetscObject)view),PETSC_ERR_SUP,"PetscViewerType %s: native HYPRE format needs PETSCVIEWERASCII",((PetscObject)view)->type_name);
174245b8d346SStefano Zampini     ierr = PetscViewerFileGetName(view,&filename);CHKERRQ(ierr);
174345b8d346SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixPrint,(hA->ij,filename));
174445b8d346SStefano Zampini     ierr = MPI_Comm_size(hA->comm,&size);CHKERRQ(ierr);
174545b8d346SStefano Zampini     if (size > 1) {
174645b8d346SStefano Zampini       ierr = PetscViewerASCIIPrintf(view,"Matrix files: %s.%05d ... %s.%05d\n",filename,0,filename,size-1);CHKERRQ(ierr);
174745b8d346SStefano Zampini     } else {
174845b8d346SStefano Zampini       ierr = PetscViewerASCIIPrintf(view,"Matrix file: %s.%05d\n",filename,0);CHKERRQ(ierr);
174945b8d346SStefano Zampini     }
175045b8d346SStefano Zampini   }
175145b8d346SStefano Zampini   PetscFunctionReturn(0);
175245b8d346SStefano Zampini }
175345b8d346SStefano Zampini 
175445b8d346SStefano Zampini static PetscErrorCode MatDuplicate_HYPRE(Mat A,MatDuplicateOption op, Mat *B)
175545b8d346SStefano Zampini {
175645b8d346SStefano Zampini   hypre_ParCSRMatrix *parcsr;
175745b8d346SStefano Zampini   PetscErrorCode     ierr;
175845b8d346SStefano Zampini   PetscCopyMode      cpmode;
175945b8d346SStefano Zampini 
176045b8d346SStefano Zampini   PetscFunctionBegin;
176145b8d346SStefano Zampini   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
176245b8d346SStefano Zampini   if (op == MAT_DO_NOT_COPY_VALUES || op == MAT_SHARE_NONZERO_PATTERN) {
176345b8d346SStefano Zampini     parcsr = hypre_ParCSRMatrixCompleteClone(parcsr);
176445b8d346SStefano Zampini     cpmode = PETSC_OWN_POINTER;
176545b8d346SStefano Zampini   } else {
176645b8d346SStefano Zampini     cpmode = PETSC_COPY_VALUES;
176745b8d346SStefano Zampini   }
176845b8d346SStefano Zampini   ierr = MatCreateFromParCSR(parcsr,MATHYPRE,cpmode,B);CHKERRQ(ierr);
176945b8d346SStefano Zampini   PetscFunctionReturn(0);
177045b8d346SStefano Zampini }
177145b8d346SStefano Zampini 
1772465edc17SStefano Zampini static PetscErrorCode MatCopy_HYPRE(Mat A, Mat B, MatStructure str)
1773465edc17SStefano Zampini {
1774465edc17SStefano Zampini   hypre_ParCSRMatrix *acsr,*bcsr;
1775465edc17SStefano Zampini   PetscErrorCode     ierr;
1776465edc17SStefano Zampini 
1777465edc17SStefano Zampini   PetscFunctionBegin;
1778465edc17SStefano Zampini   if (str == SAME_NONZERO_PATTERN && A->ops->copy == B->ops->copy) {
1779465edc17SStefano Zampini     ierr = MatHYPREGetParCSR_HYPRE(A,&acsr);CHKERRQ(ierr);
1780465edc17SStefano Zampini     ierr = MatHYPREGetParCSR_HYPRE(B,&bcsr);CHKERRQ(ierr);
1781465edc17SStefano Zampini     PetscStackCallStandard(hypre_ParCSRMatrixCopy,(acsr,bcsr,1));
1782465edc17SStefano Zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1783465edc17SStefano Zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1784465edc17SStefano Zampini   } else {
1785465edc17SStefano Zampini     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
1786465edc17SStefano Zampini   }
1787465edc17SStefano Zampini   PetscFunctionReturn(0);
1788465edc17SStefano Zampini }
1789465edc17SStefano Zampini 
17906305df00SStefano Zampini static PetscErrorCode MatGetDiagonal_HYPRE(Mat A, Vec d)
17916305df00SStefano Zampini {
17926305df00SStefano Zampini   hypre_ParCSRMatrix *parcsr;
17936305df00SStefano Zampini   hypre_CSRMatrix    *dmat;
17946305df00SStefano Zampini   PetscScalar        *a,*data = NULL;
17956305df00SStefano Zampini   PetscInt           i,*diag = NULL;
17966305df00SStefano Zampini   PetscBool          cong;
17976305df00SStefano Zampini   PetscErrorCode     ierr;
17986305df00SStefano Zampini 
17996305df00SStefano Zampini   PetscFunctionBegin;
18006305df00SStefano Zampini   ierr = MatHasCongruentLayouts(A,&cong);CHKERRQ(ierr);
18016305df00SStefano Zampini   if (!cong) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only for square matrices with same local distributions of rows and columns");
18026305df00SStefano Zampini #if defined(PETSC_USE_DEBUG)
18036305df00SStefano Zampini   {
18046305df00SStefano Zampini     PetscBool miss;
18056305df00SStefano Zampini     ierr = MatMissingDiagonal(A,&miss,NULL);CHKERRQ(ierr);
18066305df00SStefano Zampini     if (miss && A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented when diagonal entries are missing");
18076305df00SStefano Zampini   }
18086305df00SStefano Zampini #endif
18096305df00SStefano Zampini   ierr = MatHYPREGetParCSR_HYPRE(A,&parcsr);CHKERRQ(ierr);
18106305df00SStefano Zampini   dmat = hypre_ParCSRMatrixDiag(parcsr);
18116305df00SStefano Zampini   if (dmat) {
18126305df00SStefano Zampini     ierr = VecGetArray(d,&a);CHKERRQ(ierr);
18136305df00SStefano Zampini     diag = (PetscInt*)(hypre_CSRMatrixI(dmat));
18146305df00SStefano Zampini     data = (PetscScalar*)(hypre_CSRMatrixData(dmat));
18156305df00SStefano Zampini     for (i=0;i<A->rmap->n;i++) a[i] = data[diag[i]];
18166305df00SStefano Zampini     ierr = VecRestoreArray(d,&a);CHKERRQ(ierr);
18176305df00SStefano Zampini   }
18186305df00SStefano Zampini   PetscFunctionReturn(0);
18196305df00SStefano Zampini }
18206305df00SStefano Zampini 
1821363d496dSStefano Zampini #include <petscblaslapack.h>
1822363d496dSStefano Zampini 
1823363d496dSStefano Zampini static PetscErrorCode MatAXPY_HYPRE(Mat Y,PetscScalar a,Mat X,MatStructure str)
1824363d496dSStefano Zampini {
1825363d496dSStefano Zampini   PetscErrorCode ierr;
1826363d496dSStefano Zampini 
1827363d496dSStefano Zampini   PetscFunctionBegin;
1828363d496dSStefano Zampini   if (str == SAME_NONZERO_PATTERN) {
1829363d496dSStefano Zampini     hypre_ParCSRMatrix *x,*y;
1830363d496dSStefano Zampini     hypre_CSRMatrix    *xloc,*yloc;
1831363d496dSStefano Zampini     PetscInt           xnnz,ynnz;
1832363d496dSStefano Zampini     PetscScalar        *xarr,*yarr;
1833363d496dSStefano Zampini     PetscBLASInt       one=1,bnz;
1834363d496dSStefano Zampini 
1835363d496dSStefano Zampini     ierr = MatHYPREGetParCSR(Y,&y);CHKERRQ(ierr);
1836363d496dSStefano Zampini     ierr = MatHYPREGetParCSR(X,&x);CHKERRQ(ierr);
1837363d496dSStefano Zampini 
1838363d496dSStefano Zampini     /* diagonal block */
1839363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixDiag(x);
1840363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixDiag(y);
1841363d496dSStefano Zampini     xnnz = 0;
1842363d496dSStefano Zampini     ynnz = 0;
1843363d496dSStefano Zampini     xarr = NULL;
1844363d496dSStefano Zampini     yarr = NULL;
1845363d496dSStefano Zampini     if (xloc) {
1846363d496dSStefano Zampini       xarr = (PetscScalar*)(hypre_CSRMatrixData(xloc));
1847363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
1848363d496dSStefano Zampini     }
1849363d496dSStefano Zampini     if (yloc) {
1850363d496dSStefano Zampini       yarr = (PetscScalar*)(hypre_CSRMatrixData(yloc));
1851363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
1852363d496dSStefano Zampini     }
1853363d496dSStefano Zampini     if (xnnz != ynnz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Different number of nonzeros in diagonal block %D != %D",xnnz,ynnz);
1854363d496dSStefano Zampini     ierr = PetscBLASIntCast(xnnz,&bnz);CHKERRQ(ierr);
1855363d496dSStefano Zampini     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&a,xarr,&one,yarr,&one));
1856363d496dSStefano Zampini 
1857363d496dSStefano Zampini     /* off-diagonal block */
1858363d496dSStefano Zampini     xloc = hypre_ParCSRMatrixOffd(x);
1859363d496dSStefano Zampini     yloc = hypre_ParCSRMatrixOffd(y);
1860363d496dSStefano Zampini     xnnz = 0;
1861363d496dSStefano Zampini     ynnz = 0;
1862363d496dSStefano Zampini     xarr = NULL;
1863363d496dSStefano Zampini     yarr = NULL;
1864363d496dSStefano Zampini     if (xloc) {
1865363d496dSStefano Zampini       xarr = (PetscScalar*)(hypre_CSRMatrixData(xloc));
1866363d496dSStefano Zampini       xnnz = hypre_CSRMatrixNumNonzeros(xloc);
1867363d496dSStefano Zampini     }
1868363d496dSStefano Zampini     if (yloc) {
1869363d496dSStefano Zampini       yarr = (PetscScalar*)(hypre_CSRMatrixData(yloc));
1870363d496dSStefano Zampini       ynnz = hypre_CSRMatrixNumNonzeros(yloc);
1871363d496dSStefano Zampini     }
1872363d496dSStefano Zampini     if (xnnz != ynnz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Different number of nonzeros in off-diagonal block %D != %D",xnnz,ynnz);
1873363d496dSStefano Zampini     ierr = PetscBLASIntCast(xnnz,&bnz);CHKERRQ(ierr);
1874363d496dSStefano Zampini     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&a,xarr,&one,yarr,&one));
1875363d496dSStefano Zampini   } else if (str == SUBSET_NONZERO_PATTERN) {
1876363d496dSStefano Zampini     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
1877363d496dSStefano Zampini   } else {
1878363d496dSStefano Zampini     Mat B;
1879363d496dSStefano Zampini 
1880363d496dSStefano Zampini     ierr = MatAXPY_Basic_Preallocate(Y,X,&B);CHKERRQ(ierr);
1881363d496dSStefano Zampini     ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr);
1882363d496dSStefano Zampini     ierr = MatHeaderReplace(Y,&B);CHKERRQ(ierr);
1883363d496dSStefano Zampini   }
1884363d496dSStefano Zampini   PetscFunctionReturn(0);
1885363d496dSStefano Zampini }
1886363d496dSStefano Zampini 
1887a055b5aaSBarry Smith /*MC
1888a055b5aaSBarry Smith    MATHYPRE - MATHYPRE = "hypre" - A matrix type to be used for sequential and parallel sparse matrices
1889a055b5aaSBarry Smith           based on the hypre IJ interface.
1890a055b5aaSBarry Smith 
1891a055b5aaSBarry Smith    Level: intermediate
1892a055b5aaSBarry Smith 
1893a055b5aaSBarry Smith .seealso: MatCreate()
1894a055b5aaSBarry Smith M*/
1895a055b5aaSBarry Smith 
189663c07aadSStefano Zampini PETSC_EXTERN PetscErrorCode MatCreate_HYPRE(Mat B)
189763c07aadSStefano Zampini {
189863c07aadSStefano Zampini   Mat_HYPRE      *hB;
189963c07aadSStefano Zampini   PetscErrorCode ierr;
190063c07aadSStefano Zampini 
190163c07aadSStefano Zampini   PetscFunctionBegin;
190263c07aadSStefano Zampini   ierr           = PetscNewLog(B,&hB);CHKERRQ(ierr);
1903978814f1SStefano Zampini   hB->inner_free = PETSC_TRUE;
1904c69f721fSFande Kong   hB->available  = PETSC_TRUE;
1905c69f721fSFande Kong   hB->size       = 0;
1906c69f721fSFande Kong   hB->array      = NULL;
1907978814f1SStefano Zampini 
190863c07aadSStefano Zampini   B->data       = (void*)hB;
190963c07aadSStefano Zampini   B->rmap->bs   = 1;
191063c07aadSStefano Zampini   B->assembled  = PETSC_FALSE;
191163c07aadSStefano Zampini 
1912de393100SStefano Zampini   ierr = PetscMemzero(B->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
191363c07aadSStefano Zampini   B->ops->mult             = MatMult_HYPRE;
191463c07aadSStefano Zampini   B->ops->multtranspose    = MatMultTranspose_HYPRE;
1915414bd5c3SStefano Zampini   B->ops->multadd          = MatMultAdd_HYPRE;
1916414bd5c3SStefano Zampini   B->ops->multtransposeadd = MatMultTransposeAdd_HYPRE;
191763c07aadSStefano Zampini   B->ops->setup            = MatSetUp_HYPRE;
191863c07aadSStefano Zampini   B->ops->destroy          = MatDestroy_HYPRE;
191963c07aadSStefano Zampini   B->ops->assemblyend      = MatAssemblyEnd_HYPRE;
1920c69f721fSFande Kong   B->ops->assemblybegin    = MatAssemblyBegin_HYPRE;
1921cd8bc7baSStefano Zampini   B->ops->ptap             = MatPtAP_HYPRE_HYPRE;
1922d501dc42Sstefano_zampini   B->ops->matmult          = MatMatMult_HYPRE_HYPRE;
1923d975228cSstefano_zampini   B->ops->setvalues        = MatSetValues_HYPRE;
192468ec7858SStefano Zampini   B->ops->missingdiagonal  = MatMissingDiagonal_HYPRE;
192568ec7858SStefano Zampini   B->ops->scale            = MatScale_HYPRE;
192668ec7858SStefano Zampini   B->ops->zerorowscolumns  = MatZeroRowsColumns_HYPRE;
1927c69f721fSFande Kong   B->ops->zeroentries      = MatZeroEntries_HYPRE;
1928c69f721fSFande Kong   B->ops->zerorows         = MatZeroRows_HYPRE;
1929c69f721fSFande Kong   B->ops->getrow           = MatGetRow_HYPRE;
1930c69f721fSFande Kong   B->ops->restorerow       = MatRestoreRow_HYPRE;
1931c69f721fSFande Kong   B->ops->getvalues        = MatGetValues_HYPRE;
1932ddbeb582SStefano Zampini   B->ops->setoption        = MatSetOption_HYPRE;
193345b8d346SStefano Zampini   B->ops->duplicate        = MatDuplicate_HYPRE;
1934465edc17SStefano Zampini   B->ops->copy             = MatCopy_HYPRE;
193545b8d346SStefano Zampini   B->ops->view             = MatView_HYPRE;
19366305df00SStefano Zampini   B->ops->getdiagonal      = MatGetDiagonal_HYPRE;
1937363d496dSStefano Zampini   B->ops->axpy             = MatAXPY_HYPRE;
193845b8d346SStefano Zampini 
193945b8d346SStefano Zampini   /* build cache for off array entries formed */
194045b8d346SStefano Zampini   ierr = MatStashCreate_Private(PetscObjectComm((PetscObject)B),1,&B->stash);CHKERRQ(ierr);
194163c07aadSStefano Zampini 
194263c07aadSStefano Zampini   ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)B),&hB->comm);CHKERRQ(ierr);
194363c07aadSStefano Zampini   ierr = PetscObjectChangeTypeName((PetscObject)B,MATHYPRE);CHKERRQ(ierr);
194463c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_hypre_aij_C",MatConvert_HYPRE_AIJ);CHKERRQ(ierr);
19452df22349SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_hypre_is_C",MatConvert_HYPRE_IS);CHKERRQ(ierr);
1946c1a070e6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatPtAP_seqaij_hypre_C",MatPtAP_AIJ_HYPRE);CHKERRQ(ierr);
1947c1a070e6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatPtAP_mpiaij_hypre_C",MatPtAP_AIJ_HYPRE);CHKERRQ(ierr);
1948d975228cSstefano_zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatHYPRESetPreallocation_C",MatHYPRESetPreallocation_HYPRE);CHKERRQ(ierr);
1949dd9c0a25Sstefano_zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatHYPREGetParCSR_C",MatHYPREGetParCSR_HYPRE);CHKERRQ(ierr);
195075d48cdbSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatPtAP_is_hypre_C",MatPtAP_IS_XAIJ);CHKERRQ(ierr);
195163c07aadSStefano Zampini   PetscFunctionReturn(0);
195263c07aadSStefano Zampini }
195363c07aadSStefano Zampini 
1954225daaf8SStefano Zampini static PetscErrorCode hypre_array_destroy(void *ptr)
1955225daaf8SStefano Zampini {
1956225daaf8SStefano Zampini    PetscFunctionBegin;
1957e6de0934SSatish Balay    hypre_TFree(ptr,HYPRE_MEMORY_HOST);
1958225daaf8SStefano Zampini    PetscFunctionReturn(0);
1959225daaf8SStefano Zampini }
1960