xref: /petsc/src/mat/impls/hypre/mhypre.c (revision 41073d710092a75ce18d397101144c768a8ad705)
163c07aadSStefano Zampini 
263c07aadSStefano Zampini /*
363c07aadSStefano Zampini     Creates hypre ijmatrix from PETSc matrix
463c07aadSStefano Zampini */
5225daaf8SStefano Zampini 
6225daaf8SStefano Zampini /*MC
7225daaf8SStefano Zampini    MATHYPRE - MATHYPRE = "hypre" - A matrix type to be used for sequential and parallel sparse matrices
8225daaf8SStefano Zampini           based on the hypre IJ interface.
9225daaf8SStefano Zampini 
10225daaf8SStefano Zampini    Level: intermediate
11225daaf8SStefano Zampini 
12225daaf8SStefano Zampini .seealso: MatCreate()
13225daaf8SStefano Zampini M*/
14225daaf8SStefano Zampini 
1563c07aadSStefano Zampini #include <petscsys.h>
1663c07aadSStefano Zampini #include <petsc/private/matimpl.h>
1763c07aadSStefano Zampini #include <../src/mat/impls/hypre/mhypre.h>
1863c07aadSStefano Zampini #include <../src/mat/impls/aij/mpi/mpiaij.h>
1958968eb6SStefano Zampini #include <../src/vec/vec/impls/hypre/vhyp.h>
2058968eb6SStefano Zampini #include <HYPRE.h>
21c1a070e6SStefano Zampini #include <HYPRE_utilities.h>
22cd8bc7baSStefano Zampini #include <_hypre_parcsr_ls.h>
2363c07aadSStefano Zampini 
2463c07aadSStefano Zampini static PetscErrorCode MatHYPRE_CreateFromMat(Mat,Mat_HYPRE*);
2563c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat,Mat,HYPRE_IJMatrix);
2663c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixFastCopy_MPIAIJ(Mat,HYPRE_IJMatrix);
2763c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixFastCopy_SeqAIJ(Mat,HYPRE_IJMatrix);
2863c07aadSStefano Zampini static PetscErrorCode MatHYPRE_MultKernel_Private(Mat,Vec,Vec,PetscBool);
29225daaf8SStefano Zampini static PetscErrorCode hypre_array_destroy(void*);
3063c07aadSStefano Zampini 
3163c07aadSStefano Zampini #undef __FUNCT__
3263c07aadSStefano Zampini #define __FUNCT__ "MatHYPRE_IJMatrixPreallocate"
3363c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixPreallocate(Mat A_d, Mat A_o, HYPRE_IJMatrix ij)
3463c07aadSStefano Zampini {
3563c07aadSStefano Zampini   PetscErrorCode ierr;
3663c07aadSStefano Zampini   PetscInt       i,n_d,n_o;
3763c07aadSStefano Zampini   const PetscInt *ia_d,*ia_o;
3863c07aadSStefano Zampini   PetscBool      done_d=PETSC_FALSE,done_o=PETSC_FALSE;
3963c07aadSStefano Zampini   PetscInt       *nnz_d=NULL,*nnz_o=NULL;
4063c07aadSStefano Zampini 
4163c07aadSStefano Zampini   PetscFunctionBegin;
4263c07aadSStefano Zampini   if (A_d) { /* determine number of nonzero entries in local diagonal part */
4363c07aadSStefano Zampini     ierr = MatGetRowIJ(A_d,0,PETSC_FALSE,PETSC_FALSE,&n_d,&ia_d,NULL,&done_d);CHKERRQ(ierr);
4463c07aadSStefano Zampini     if (done_d) {
4563c07aadSStefano Zampini       ierr = PetscMalloc1(n_d,&nnz_d);CHKERRQ(ierr);
4663c07aadSStefano Zampini       for (i=0; i<n_d; i++) {
4763c07aadSStefano Zampini         nnz_d[i] = ia_d[i+1] - ia_d[i];
4863c07aadSStefano Zampini       }
4963c07aadSStefano Zampini     }
5063c07aadSStefano Zampini     ierr = MatRestoreRowIJ(A_d,0,PETSC_FALSE,PETSC_FALSE,NULL,&ia_d,NULL,&done_d);CHKERRQ(ierr);
5163c07aadSStefano Zampini   }
5263c07aadSStefano Zampini   if (A_o) { /* determine number of nonzero entries in local off-diagonal part */
5363c07aadSStefano Zampini     ierr = MatGetRowIJ(A_o,0,PETSC_FALSE,PETSC_FALSE,&n_o,&ia_o,NULL,&done_o);CHKERRQ(ierr);
5463c07aadSStefano Zampini     if (done_o) {
5563c07aadSStefano Zampini       ierr = PetscMalloc1(n_o,&nnz_o);CHKERRQ(ierr);
5663c07aadSStefano Zampini       for (i=0; i<n_o; i++) {
5763c07aadSStefano Zampini         nnz_o[i] = ia_o[i+1] - ia_o[i];
5863c07aadSStefano Zampini       }
5963c07aadSStefano Zampini     }
6063c07aadSStefano Zampini     ierr = MatRestoreRowIJ(A_o,0,PETSC_FALSE,PETSC_FALSE,&n_o,&ia_o,NULL,&done_o);CHKERRQ(ierr);
6163c07aadSStefano Zampini   }
6263c07aadSStefano Zampini   if (done_d) {    /* set number of nonzeros in HYPRE IJ matrix */
6363c07aadSStefano Zampini     if (!done_o) { /* only diagonal part */
6463c07aadSStefano Zampini       ierr = PetscMalloc1(n_d,&nnz_o);CHKERRQ(ierr);
6563c07aadSStefano Zampini       for (i=0; i<n_d; i++) {
6663c07aadSStefano Zampini         nnz_o[i] = 0;
6763c07aadSStefano Zampini       }
6863c07aadSStefano Zampini     }
6963c07aadSStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixSetDiagOffdSizes,(ij,(HYPRE_Int *)nnz_d,(HYPRE_Int *)nnz_o));
7063c07aadSStefano Zampini     ierr = PetscFree(nnz_d);CHKERRQ(ierr);
7163c07aadSStefano Zampini     ierr = PetscFree(nnz_o);CHKERRQ(ierr);
7263c07aadSStefano Zampini   }
7363c07aadSStefano Zampini   PetscFunctionReturn(0);
7463c07aadSStefano Zampini }
7563c07aadSStefano Zampini 
7663c07aadSStefano Zampini #undef __FUNCT__
7763c07aadSStefano Zampini #define __FUNCT__ "MatHYPRE_CreateFromMat"
7863c07aadSStefano Zampini static PetscErrorCode MatHYPRE_CreateFromMat(Mat A, Mat_HYPRE *hA)
7963c07aadSStefano Zampini {
8063c07aadSStefano Zampini   PetscErrorCode ierr;
8163c07aadSStefano Zampini   PetscInt       rstart,rend,cstart,cend;
8263c07aadSStefano Zampini 
8363c07aadSStefano Zampini   PetscFunctionBegin;
8463c07aadSStefano Zampini   ierr   = MatSetUp(A);CHKERRQ(ierr);
8563c07aadSStefano Zampini   rstart = A->rmap->rstart;
8663c07aadSStefano Zampini   rend   = A->rmap->rend;
8763c07aadSStefano Zampini   cstart = A->cmap->rstart;
8863c07aadSStefano Zampini   cend   = A->cmap->rend;
8963c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixCreate,(hA->comm,rstart,rend-1,cstart,cend-1,&hA->ij));
9063c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(hA->ij,HYPRE_PARCSR));
9163c07aadSStefano Zampini   {
9263c07aadSStefano Zampini     PetscBool      same;
9363c07aadSStefano Zampini     Mat            A_d,A_o;
9463c07aadSStefano Zampini     const PetscInt *colmap;
9563c07aadSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&same);CHKERRQ(ierr);
9663c07aadSStefano Zampini     if (same) {
9763c07aadSStefano Zampini       ierr = MatMPIAIJGetSeqAIJ(A,&A_d,&A_o,&colmap);CHKERRQ(ierr);
9863c07aadSStefano Zampini       ierr = MatHYPRE_IJMatrixPreallocate(A_d,A_o,hA->ij);CHKERRQ(ierr);
9963c07aadSStefano Zampini       PetscFunctionReturn(0);
10063c07aadSStefano Zampini     }
10163c07aadSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIBAIJ,&same);CHKERRQ(ierr);
10263c07aadSStefano Zampini     if (same) {
10363c07aadSStefano Zampini       ierr = MatMPIBAIJGetSeqBAIJ(A,&A_d,&A_o,&colmap);CHKERRQ(ierr);
10463c07aadSStefano Zampini       ierr = MatHYPRE_IJMatrixPreallocate(A_d,A_o,hA->ij);CHKERRQ(ierr);
10563c07aadSStefano Zampini       PetscFunctionReturn(0);
10663c07aadSStefano Zampini     }
10763c07aadSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&same);CHKERRQ(ierr);
10863c07aadSStefano Zampini     if (same) {
10963c07aadSStefano Zampini       ierr = MatHYPRE_IJMatrixPreallocate(A,NULL,hA->ij);CHKERRQ(ierr);
11063c07aadSStefano Zampini       PetscFunctionReturn(0);
11163c07aadSStefano Zampini     }
11263c07aadSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQBAIJ,&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   }
11863c07aadSStefano Zampini   PetscFunctionReturn(0);
11963c07aadSStefano Zampini }
12063c07aadSStefano Zampini 
12163c07aadSStefano Zampini #undef __FUNCT__
12263c07aadSStefano Zampini #define __FUNCT__ "MatHYPRE_IJMatrixCopy"
12363c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixCopy(Mat A, HYPRE_IJMatrix ij)
12463c07aadSStefano Zampini {
12563c07aadSStefano Zampini   PetscErrorCode    ierr;
12663c07aadSStefano Zampini   PetscInt          i,rstart,rend,ncols,nr,nc;
12763c07aadSStefano Zampini   const PetscScalar *values;
12863c07aadSStefano Zampini   const PetscInt    *cols;
12963c07aadSStefano Zampini   PetscBool         flg;
13063c07aadSStefano Zampini 
13163c07aadSStefano Zampini   PetscFunctionBegin;
13263c07aadSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&flg);CHKERRQ(ierr);
13363c07aadSStefano Zampini   ierr = MatGetSize(A,&nr,&nc);CHKERRQ(ierr);
13463c07aadSStefano Zampini   if (flg && nr == nc) {
13563c07aadSStefano Zampini     ierr = MatHYPRE_IJMatrixFastCopy_MPIAIJ(A,ij);CHKERRQ(ierr);
13663c07aadSStefano Zampini     PetscFunctionReturn(0);
13763c07aadSStefano Zampini   }
13863c07aadSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&flg);CHKERRQ(ierr);
13963c07aadSStefano Zampini   if (flg) {
14063c07aadSStefano Zampini     ierr = MatHYPRE_IJMatrixFastCopy_SeqAIJ(A,ij);CHKERRQ(ierr);
14163c07aadSStefano Zampini     PetscFunctionReturn(0);
14263c07aadSStefano Zampini   }
14363c07aadSStefano Zampini 
14463c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixInitialize,(ij));
14563c07aadSStefano Zampini   ierr = MatGetOwnershipRange(A,&rstart,&rend);CHKERRQ(ierr);
14663c07aadSStefano Zampini   for (i=rstart; i<rend; i++) {
14763c07aadSStefano Zampini     ierr = MatGetRow(A,i,&ncols,&cols,&values);CHKERRQ(ierr);
14863c07aadSStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixSetValues,(ij,1,(HYPRE_Int *)&ncols,(HYPRE_Int *)&i,(HYPRE_Int *)cols,values));
14963c07aadSStefano Zampini     ierr = MatRestoreRow(A,i,&ncols,&cols,&values);CHKERRQ(ierr);
15063c07aadSStefano Zampini   }
15163c07aadSStefano Zampini   PetscFunctionReturn(0);
15263c07aadSStefano Zampini }
15363c07aadSStefano Zampini 
15463c07aadSStefano Zampini #undef __FUNCT__
15563c07aadSStefano Zampini #define __FUNCT__ "MatHYPRE_IJMatrixFastCopy_SeqAIJ"
15663c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixFastCopy_SeqAIJ(Mat A, HYPRE_IJMatrix ij)
15763c07aadSStefano Zampini {
15863c07aadSStefano Zampini   PetscErrorCode        ierr;
15963c07aadSStefano Zampini   Mat_SeqAIJ            *pdiag = (Mat_SeqAIJ*)A->data;
16058968eb6SStefano Zampini   HYPRE_Int             type;
16163c07aadSStefano Zampini   hypre_ParCSRMatrix    *par_matrix;
16263c07aadSStefano Zampini   hypre_AuxParCSRMatrix *aux_matrix;
16363c07aadSStefano Zampini   hypre_CSRMatrix       *hdiag;
16463c07aadSStefano Zampini 
16563c07aadSStefano Zampini   PetscFunctionBegin;
16663c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixInitialize,(ij));
167ea9daf28SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(ij,&type));
168ea9daf28SStefano Zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
169ea9daf28SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(ij,(void**)&par_matrix));
17063c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(par_matrix);
17163c07aadSStefano Zampini   /*
17263c07aadSStefano Zampini        this is the Hack part where we monkey directly with the hypre datastructures
17363c07aadSStefano Zampini   */
17463c07aadSStefano Zampini   ierr = PetscMemcpy(hdiag->i,pdiag->i,(A->rmap->n + 1)*sizeof(PetscInt));
17563c07aadSStefano Zampini   ierr = PetscMemcpy(hdiag->j,pdiag->j,pdiag->nz*sizeof(PetscInt));
17663c07aadSStefano Zampini   ierr = PetscMemcpy(hdiag->data,pdiag->a,pdiag->nz*sizeof(PetscScalar));
177ea9daf28SStefano Zampini 
178ea9daf28SStefano Zampini   aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(ij);
17963c07aadSStefano Zampini   hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
18063c07aadSStefano Zampini   PetscFunctionReturn(0);
18163c07aadSStefano Zampini }
18263c07aadSStefano Zampini 
18363c07aadSStefano Zampini #undef __FUNCT__
18463c07aadSStefano Zampini #define __FUNCT__ "MatHYPRE_IJMatrixFastCopy_MPIAIJ"
18563c07aadSStefano Zampini static PetscErrorCode MatHYPRE_IJMatrixFastCopy_MPIAIJ(Mat A, HYPRE_IJMatrix ij)
18663c07aadSStefano Zampini {
18763c07aadSStefano Zampini   PetscErrorCode        ierr;
18863c07aadSStefano Zampini   Mat_MPIAIJ            *pA = (Mat_MPIAIJ*)A->data;
18963c07aadSStefano Zampini   Mat_SeqAIJ            *pdiag,*poffd;
19063c07aadSStefano Zampini   PetscInt              i,*garray = pA->garray,*jj,cstart,*pjj;
19158968eb6SStefano Zampini   HYPRE_Int             type;
19263c07aadSStefano Zampini   hypre_ParCSRMatrix    *par_matrix;
19363c07aadSStefano Zampini   hypre_AuxParCSRMatrix *aux_matrix;
19463c07aadSStefano Zampini   hypre_CSRMatrix       *hdiag,*hoffd;
19563c07aadSStefano Zampini 
19663c07aadSStefano Zampini   PetscFunctionBegin;
19763c07aadSStefano Zampini   pdiag = (Mat_SeqAIJ*) pA->A->data;
19863c07aadSStefano Zampini   poffd = (Mat_SeqAIJ*) pA->B->data;
19963c07aadSStefano Zampini   /* cstart is only valid for square MPIAIJ layed out in the usual way */
20063c07aadSStefano Zampini   ierr = MatGetOwnershipRange(A,&cstart,NULL);CHKERRQ(ierr);
20163c07aadSStefano Zampini 
20263c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixInitialize,(ij));
203ea9daf28SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(ij,&type));
204ea9daf28SStefano Zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
205ea9daf28SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(ij,(void**)&par_matrix));
20663c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(par_matrix);
20763c07aadSStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(par_matrix);
20863c07aadSStefano Zampini 
20963c07aadSStefano Zampini   /*
21063c07aadSStefano Zampini        this is the Hack part where we monkey directly with the hypre datastructures
21163c07aadSStefano Zampini   */
21263c07aadSStefano Zampini   ierr = PetscMemcpy(hdiag->i,pdiag->i,(pA->A->rmap->n + 1)*sizeof(PetscInt));
21363c07aadSStefano Zampini   /* need to shift the diag column indices (hdiag->j) back to global numbering since hypre is expecting this */
21463c07aadSStefano Zampini   jj  = (PetscInt*)hdiag->j;
21563c07aadSStefano Zampini   pjj = (PetscInt*)pdiag->j;
21663c07aadSStefano Zampini   for (i=0; i<pdiag->nz; i++) jj[i] = cstart + pjj[i];
21763c07aadSStefano Zampini   ierr = PetscMemcpy(hdiag->data,pdiag->a,pdiag->nz*sizeof(PetscScalar));
21863c07aadSStefano Zampini   ierr = PetscMemcpy(hoffd->i,poffd->i,(pA->A->rmap->n + 1)*sizeof(PetscInt));
21963c07aadSStefano Zampini   /* need to move the offd column indices (hoffd->j) back to global numbering since hypre is expecting this
22063c07aadSStefano Zampini      If we hacked a hypre a bit more we might be able to avoid this step */
22163c07aadSStefano Zampini   jj  = (PetscInt*) hoffd->j;
22263c07aadSStefano Zampini   pjj = (PetscInt*) poffd->j;
22363c07aadSStefano Zampini   for (i=0; i<poffd->nz; i++) jj[i] = garray[pjj[i]];
22463c07aadSStefano Zampini   ierr = PetscMemcpy(hoffd->data,poffd->a,poffd->nz*sizeof(PetscScalar));
22563c07aadSStefano Zampini 
226ea9daf28SStefano Zampini   aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(ij);
22763c07aadSStefano Zampini   hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
22863c07aadSStefano Zampini   PetscFunctionReturn(0);
22963c07aadSStefano Zampini }
23063c07aadSStefano Zampini 
23163c07aadSStefano Zampini #undef __FUNCT__
2322df22349SStefano Zampini #define __FUNCT__ "MatConvert_HYPRE_IS"
2332df22349SStefano Zampini static PetscErrorCode MatConvert_HYPRE_IS(Mat A, MatType mtype, MatReuse reuse, Mat* B)
2342df22349SStefano Zampini {
2352df22349SStefano Zampini   Mat_HYPRE*             mhA = (Mat_HYPRE*)(A->data);
2362df22349SStefano Zampini   Mat                    lA;
2372df22349SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
2382df22349SStefano Zampini   IS                     is;
2392df22349SStefano Zampini   hypre_ParCSRMatrix     *hA;
2402df22349SStefano Zampini   hypre_CSRMatrix        *hdiag,*hoffd;
2412df22349SStefano Zampini   MPI_Comm               comm;
2422df22349SStefano Zampini   PetscScalar            *hdd,*hod,*aa,*data;
2432df22349SStefano Zampini   PetscInt               *col_map_offd,*hdi,*hdj,*hoi,*hoj;
2442df22349SStefano Zampini   PetscInt               *ii,*jj,*iptr,*jptr;
2452df22349SStefano Zampini   PetscInt               cum,dr,dc,oc,str,stc,nnz,i,jd,jo,M,N;
24658968eb6SStefano Zampini   HYPRE_Int              type;
2472df22349SStefano Zampini   PetscErrorCode         ierr;
2482df22349SStefano Zampini 
2492df22349SStefano Zampini   PetscFunctionBegin;
250a1787963SStefano Zampini   comm = PetscObjectComm((PetscObject)A);
2512df22349SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(mhA->ij,&type));
2522df22349SStefano Zampini   if (type != HYPRE_PARCSR) SETERRQ(comm,PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
2532df22349SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(mhA->ij,(void**)&hA));
2542df22349SStefano Zampini   M     = hypre_ParCSRMatrixGlobalNumRows(hA);
2552df22349SStefano Zampini   N     = hypre_ParCSRMatrixGlobalNumCols(hA);
2562df22349SStefano Zampini   str   = hypre_ParCSRMatrixFirstRowIndex(hA);
2572df22349SStefano Zampini   stc   = hypre_ParCSRMatrixFirstColDiag(hA);
2582df22349SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(hA);
2592df22349SStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(hA);
2602df22349SStefano Zampini   dr    = hypre_CSRMatrixNumRows(hdiag);
2612df22349SStefano Zampini   dc    = hypre_CSRMatrixNumCols(hdiag);
2622df22349SStefano Zampini   nnz   = hypre_CSRMatrixNumNonzeros(hdiag);
2632df22349SStefano Zampini   hdi   = hypre_CSRMatrixI(hdiag);
2642df22349SStefano Zampini   hdj   = hypre_CSRMatrixJ(hdiag);
2652df22349SStefano Zampini   hdd   = hypre_CSRMatrixData(hdiag);
2662df22349SStefano Zampini   oc    = hypre_CSRMatrixNumCols(hoffd);
2672df22349SStefano Zampini   nnz  += hypre_CSRMatrixNumNonzeros(hoffd);
2682df22349SStefano Zampini   hoi   = hypre_CSRMatrixI(hoffd);
2692df22349SStefano Zampini   hoj   = hypre_CSRMatrixJ(hoffd);
2702df22349SStefano Zampini   hod   = hypre_CSRMatrixData(hoffd);
2712df22349SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
2722df22349SStefano Zampini     PetscInt *aux;
2732df22349SStefano Zampini 
2742df22349SStefano Zampini     /* generate l2g maps for rows and cols */
2752df22349SStefano Zampini     ierr = ISCreateStride(comm,dr,str,1,&is);CHKERRQ(ierr);
2762df22349SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
2772df22349SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
2782df22349SStefano Zampini     col_map_offd = hypre_ParCSRMatrixColMapOffd(hA);
2792df22349SStefano Zampini     ierr = PetscMalloc1(dc+oc,&aux);CHKERRQ(ierr);
2802df22349SStefano Zampini     for (i=0; i<dc; i++) aux[i] = i+stc;
2812df22349SStefano Zampini     for (i=0; i<oc; i++) aux[i+dc] = col_map_offd[i];
2822df22349SStefano Zampini     ierr = ISCreateGeneral(comm,dc+oc,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
2832df22349SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
2842df22349SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
2852df22349SStefano Zampini     /* create MATIS object */
2862df22349SStefano Zampini     ierr = MatCreate(comm,B);CHKERRQ(ierr);
2872df22349SStefano Zampini     ierr = MatSetSizes(*B,dr,dc,M,N);CHKERRQ(ierr);
2882df22349SStefano Zampini     ierr = MatSetType(*B,MATIS);CHKERRQ(ierr);
2892df22349SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*B,rl2g,cl2g);CHKERRQ(ierr);
2902df22349SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2912df22349SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2922df22349SStefano Zampini 
2932df22349SStefano Zampini     /* allocate CSR for local matrix */
2942df22349SStefano Zampini     ierr = PetscMalloc1(dr+1,&iptr);CHKERRQ(ierr);
2952df22349SStefano Zampini     ierr = PetscMalloc1(nnz,&jptr);CHKERRQ(ierr);
2962df22349SStefano Zampini     ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr);
2972df22349SStefano Zampini   } else {
2982df22349SStefano Zampini     PetscInt  nr;
2992df22349SStefano Zampini     PetscBool done;
3002df22349SStefano Zampini     ierr = MatISGetLocalMat(*B,&lA);CHKERRQ(ierr);
3012df22349SStefano Zampini     ierr = MatGetRowIJ(lA,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&iptr,(const PetscInt**)&jptr,&done);CHKERRQ(ierr);
3022df22349SStefano 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);
3032df22349SStefano 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);
3042df22349SStefano Zampini     ierr = MatSeqAIJGetArray(lA,&data);CHKERRQ(ierr);
3052df22349SStefano Zampini   }
3062df22349SStefano Zampini   /* merge local matrices */
3072df22349SStefano Zampini   ii   = iptr;
3082df22349SStefano Zampini   jj   = jptr;
3092df22349SStefano Zampini   aa   = data;
3102df22349SStefano Zampini   *ii  = *(hdi++) + *(hoi++);
3112df22349SStefano Zampini   for (jd=0,jo=0,cum=0; *ii<nnz; cum++) {
3122df22349SStefano Zampini     PetscScalar *aold = aa;
3132df22349SStefano Zampini     PetscInt    *jold = jj,nc = jd+jo;
3142df22349SStefano Zampini     for (; jd<*hdi; jd++) { *jj++ = *hdj++;      *aa++ = *hdd++; }
3152df22349SStefano Zampini     for (; jo<*hoi; jo++) { *jj++ = *hoj++ + dc; *aa++ = *hod++; }
3162df22349SStefano Zampini     *(++ii) = *(hdi++) + *(hoi++);
3172df22349SStefano Zampini     ierr = PetscSortIntWithScalarArray(jd+jo-nc,jold,aold);CHKERRQ(ierr);
3182df22349SStefano Zampini   }
3192df22349SStefano Zampini   for (; cum<dr; cum++) *(++ii) = nnz;
3202df22349SStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
321a033916dSStefano Zampini     Mat_SeqAIJ* a;
322a033916dSStefano Zampini 
3232df22349SStefano Zampini     ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,dc+oc,iptr,jptr,data,&lA);CHKERRQ(ierr);
3242df22349SStefano Zampini     ierr = MatISSetLocalMat(*B,lA);CHKERRQ(ierr);
325a033916dSStefano Zampini     /* hack SeqAIJ */
326a033916dSStefano Zampini     a          = (Mat_SeqAIJ*)(lA->data);
327a033916dSStefano Zampini     a->free_a  = PETSC_TRUE;
328a033916dSStefano Zampini     a->free_ij = PETSC_TRUE;
3292df22349SStefano Zampini     ierr = MatDestroy(&lA);CHKERRQ(ierr);
3302df22349SStefano Zampini   }
3312df22349SStefano Zampini   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3322df22349SStefano Zampini   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3332df22349SStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
3342df22349SStefano Zampini     ierr = MatHeaderReplace(A,B);CHKERRQ(ierr);
3352df22349SStefano Zampini   }
3362df22349SStefano Zampini   PetscFunctionReturn(0);
3372df22349SStefano Zampini }
3382df22349SStefano Zampini 
3392df22349SStefano Zampini #undef __FUNCT__
34063c07aadSStefano Zampini #define __FUNCT__ "MatConvert_AIJ_HYPRE"
34163c07aadSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A, MatType type, MatReuse reuse, Mat *B)
34263c07aadSStefano Zampini {
34363c07aadSStefano Zampini   Mat_HYPRE      *hB;
34463c07aadSStefano Zampini   MPI_Comm       comm = PetscObjectComm((PetscObject)A);
34563c07aadSStefano Zampini   PetscErrorCode ierr;
34663c07aadSStefano Zampini 
34763c07aadSStefano Zampini   PetscFunctionBegin;
34863c07aadSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) SETERRQ(comm,PETSC_ERR_SUP,"Unsupported MAT_INPLACE_MATRIX");
34963c07aadSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
35063c07aadSStefano Zampini     /* always destroy the old matrix and create a new memory;
35163c07aadSStefano Zampini        hope this does not churn the memory too much. The problem
35263c07aadSStefano Zampini        is I do not know if it is possible to put the matrix back to
35363c07aadSStefano Zampini        its initial state so that we can directly copy the values
35463c07aadSStefano Zampini        the second time through. */
35563c07aadSStefano Zampini     hB = (Mat_HYPRE*)((*B)->data);
35663c07aadSStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixDestroy,(hB->ij));
35763c07aadSStefano Zampini   } else {
35863c07aadSStefano Zampini     ierr = MatCreate(comm,B);CHKERRQ(ierr);
35963c07aadSStefano Zampini     ierr = MatSetType(*B,MATHYPRE);CHKERRQ(ierr);
36063c07aadSStefano Zampini     ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
36163c07aadSStefano Zampini     ierr = MatSetUp(*B);CHKERRQ(ierr);
36263c07aadSStefano Zampini     hB   = (Mat_HYPRE*)((*B)->data);
36363c07aadSStefano Zampini   }
36463c07aadSStefano Zampini   ierr = MatHYPRE_CreateFromMat(A,hB);CHKERRQ(ierr);
36563c07aadSStefano Zampini   ierr = MatHYPRE_IJMatrixCopy(A,hB->ij);CHKERRQ(ierr);
36663c07aadSStefano Zampini   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
36763c07aadSStefano Zampini   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
36863c07aadSStefano Zampini   PetscFunctionReturn(0);
36963c07aadSStefano Zampini }
37063c07aadSStefano Zampini 
37163c07aadSStefano Zampini #undef __FUNCT__
37263c07aadSStefano Zampini #define __FUNCT__ "MatConvert_HYPRE_AIJ"
373ea9daf28SStefano Zampini static PetscErrorCode MatConvert_HYPRE_AIJ(Mat A, MatType mtype, MatReuse reuse, Mat *B)
37463c07aadSStefano Zampini {
37563c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE*)A->data;
37663c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
37763c07aadSStefano Zampini   hypre_CSRMatrix    *hdiag,*hoffd;
37863c07aadSStefano Zampini   MPI_Comm           comm;
37963c07aadSStefano Zampini   PetscScalar        *da,*oa,*aptr;
38063c07aadSStefano Zampini   PetscInt           *dii,*djj,*oii,*ojj,*iptr;
38163c07aadSStefano Zampini   PetscInt           i,dnnz,onnz,m,n;
38258968eb6SStefano Zampini   HYPRE_Int          type;
38363c07aadSStefano Zampini   PetscMPIInt        size;
38463c07aadSStefano Zampini   PetscErrorCode     ierr;
38563c07aadSStefano Zampini 
38663c07aadSStefano Zampini   PetscFunctionBegin;
38763c07aadSStefano Zampini   comm = PetscObjectComm((PetscObject)A);
38863c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type));
38963c07aadSStefano Zampini   if (type != HYPRE_PARCSR) SETERRQ(comm,PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
39063c07aadSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
39163c07aadSStefano Zampini     PetscBool ismpiaij,isseqaij;
39263c07aadSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*B,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
39363c07aadSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*B,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
39463c07aadSStefano Zampini     if (!ismpiaij && !isseqaij) SETERRQ(comm,PETSC_ERR_SUP,"Only MATMPIAIJ or MATSEQAIJ are supported");
39563c07aadSStefano Zampini   }
39663c07aadSStefano Zampini   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
39763c07aadSStefano Zampini 
39863c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&parcsr));
39963c07aadSStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(parcsr);
40063c07aadSStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(parcsr);
40163c07aadSStefano Zampini   m     = hypre_CSRMatrixNumRows(hdiag);
40263c07aadSStefano Zampini   n     = hypre_CSRMatrixNumCols(hdiag);
40363c07aadSStefano Zampini   dnnz  = hypre_CSRMatrixNumNonzeros(hdiag);
40463c07aadSStefano Zampini   onnz  = hypre_CSRMatrixNumNonzeros(hoffd);
405225daaf8SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
40663c07aadSStefano Zampini     ierr = PetscMalloc1(m+1,&dii);CHKERRQ(ierr);
40763c07aadSStefano Zampini     ierr = PetscMalloc1(dnnz,&djj);CHKERRQ(ierr);
40863c07aadSStefano Zampini     ierr = PetscMalloc1(dnnz,&da);CHKERRQ(ierr);
409225daaf8SStefano Zampini   } else if (reuse == MAT_REUSE_MATRIX) {
41063c07aadSStefano Zampini     PetscInt  nr;
41163c07aadSStefano Zampini     PetscBool done;
41263c07aadSStefano Zampini     if (size > 1) {
41363c07aadSStefano Zampini       Mat_MPIAIJ *b = (Mat_MPIAIJ*)((*B)->data);
41463c07aadSStefano Zampini 
41563c07aadSStefano Zampini       ierr = MatGetRowIJ(b->A,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&dii,(const PetscInt**)&djj,&done);CHKERRQ(ierr);
41663c07aadSStefano 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);
41763c07aadSStefano 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);
41863c07aadSStefano Zampini       ierr = MatSeqAIJGetArray(b->A,&da);CHKERRQ(ierr);
41963c07aadSStefano Zampini     } else {
42063c07aadSStefano Zampini       ierr = MatGetRowIJ(*B,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&dii,(const PetscInt**)&djj,&done);CHKERRQ(ierr);
42163c07aadSStefano Zampini       if (nr != m) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"Cannot reuse mat: invalid number of local rows! %D != %D",nr,m);
42263c07aadSStefano 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);
42363c07aadSStefano Zampini       ierr = MatSeqAIJGetArray(*B,&da);CHKERRQ(ierr);
42463c07aadSStefano Zampini     }
425225daaf8SStefano Zampini   } else { /* MAT_INPLACE_MATRIX */
426225daaf8SStefano Zampini     dii = hypre_CSRMatrixI(hdiag);
427225daaf8SStefano Zampini     djj = hypre_CSRMatrixJ(hdiag);
428225daaf8SStefano Zampini     da  = hypre_CSRMatrixData(hdiag);
42963c07aadSStefano Zampini   }
43063c07aadSStefano Zampini   ierr = PetscMemcpy(dii,hypre_CSRMatrixI(hdiag),(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
43163c07aadSStefano Zampini   ierr = PetscMemcpy(djj,hypre_CSRMatrixJ(hdiag),dnnz*sizeof(PetscInt));CHKERRQ(ierr);
43263c07aadSStefano Zampini   ierr = PetscMemcpy(da,hypre_CSRMatrixData(hdiag),dnnz*sizeof(PetscScalar));CHKERRQ(ierr);
43363c07aadSStefano Zampini   iptr = djj;
43463c07aadSStefano Zampini   aptr = da;
43563c07aadSStefano Zampini   for (i=0; i<m; i++) {
43663c07aadSStefano Zampini     PetscInt nc = dii[i+1]-dii[i];
43763c07aadSStefano Zampini     ierr = PetscSortIntWithScalarArray(nc,iptr,aptr);CHKERRQ(ierr);
43863c07aadSStefano Zampini     iptr += nc;
43963c07aadSStefano Zampini     aptr += nc;
44063c07aadSStefano Zampini   }
44163c07aadSStefano Zampini   if (size > 1) {
44263c07aadSStefano Zampini     PetscInt *offdj,*coffd;
44363c07aadSStefano Zampini 
444225daaf8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
44563c07aadSStefano Zampini       ierr = PetscMalloc1(m+1,&oii);CHKERRQ(ierr);
44663c07aadSStefano Zampini       ierr = PetscMalloc1(onnz,&ojj);CHKERRQ(ierr);
44763c07aadSStefano Zampini       ierr = PetscMalloc1(onnz,&oa);CHKERRQ(ierr);
448225daaf8SStefano Zampini     } else if (reuse == MAT_REUSE_MATRIX) {
44963c07aadSStefano Zampini       Mat_MPIAIJ *b = (Mat_MPIAIJ*)((*B)->data);
45063c07aadSStefano Zampini       PetscInt   nr,hr = hypre_CSRMatrixNumRows(hoffd);
45163c07aadSStefano Zampini       PetscBool  done;
45263c07aadSStefano Zampini 
45363c07aadSStefano Zampini       ierr = MatGetRowIJ(b->B,0,PETSC_FALSE,PETSC_FALSE,&nr,(const PetscInt**)&oii,(const PetscInt**)&ojj,&done);CHKERRQ(ierr);
45463c07aadSStefano 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);
45563c07aadSStefano 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);
45663c07aadSStefano Zampini       ierr = MatSeqAIJGetArray(b->B,&oa);CHKERRQ(ierr);
457225daaf8SStefano Zampini     } else { /* MAT_INPLACE_MATRIX */
458225daaf8SStefano Zampini       oii = hypre_CSRMatrixI(hoffd);
459225daaf8SStefano Zampini       ojj = hypre_CSRMatrixJ(hoffd);
460225daaf8SStefano Zampini       oa  = hypre_CSRMatrixData(hoffd);
46163c07aadSStefano Zampini     }
46263c07aadSStefano Zampini     ierr  = PetscMemcpy(oii,hypre_CSRMatrixI(hoffd),(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
46363c07aadSStefano Zampini     offdj = hypre_CSRMatrixJ(hoffd);
46463c07aadSStefano Zampini     coffd = hypre_ParCSRMatrixColMapOffd(parcsr);
46563c07aadSStefano Zampini     for (i=0; i<onnz; i++) ojj[i] = coffd[offdj[i]];
46663c07aadSStefano Zampini     ierr = PetscMemcpy(oa,hypre_CSRMatrixData(hoffd),onnz*sizeof(PetscScalar));CHKERRQ(ierr);
46763c07aadSStefano Zampini     iptr = ojj;
46863c07aadSStefano Zampini     aptr = oa;
46963c07aadSStefano Zampini     for (i=0; i<m; i++) {
47063c07aadSStefano Zampini        PetscInt nc = oii[i+1]-oii[i];
47163c07aadSStefano Zampini        ierr = PetscSortIntWithScalarArray(nc,iptr,aptr);CHKERRQ(ierr);
47263c07aadSStefano Zampini        iptr += nc;
47363c07aadSStefano Zampini        aptr += nc;
47463c07aadSStefano Zampini     }
475225daaf8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
47663c07aadSStefano Zampini       Mat_MPIAIJ *b;
47763c07aadSStefano Zampini       Mat_SeqAIJ *d,*o;
478225daaf8SStefano Zampini 
479*41073d71Sstefano_zampini       ierr = MatCreateMPIAIJWithSplitArrays(comm,m,n,PETSC_DECIDE,PETSC_DECIDE,dii,djj,da,oii,ojj,oa,B);CHKERRQ(ierr);
48063c07aadSStefano Zampini       /* hack MPIAIJ */
48163c07aadSStefano Zampini       b          = (Mat_MPIAIJ*)((*B)->data);
48263c07aadSStefano Zampini       d          = (Mat_SeqAIJ*)b->A->data;
48363c07aadSStefano Zampini       o          = (Mat_SeqAIJ*)b->B->data;
48463c07aadSStefano Zampini       d->free_a  = PETSC_TRUE;
48563c07aadSStefano Zampini       d->free_ij = PETSC_TRUE;
48663c07aadSStefano Zampini       o->free_a  = PETSC_TRUE;
48763c07aadSStefano Zampini       o->free_ij = PETSC_TRUE;
488225daaf8SStefano Zampini     } else if (reuse == MAT_INPLACE_MATRIX) {
489225daaf8SStefano Zampini       Mat T;
490*41073d71Sstefano_zampini       ierr = MatCreateMPIAIJWithSplitArrays(comm,m,n,PETSC_DECIDE,PETSC_DECIDE,dii,djj,da,oii,ojj,oa,&T);CHKERRQ(ierr);
491225daaf8SStefano Zampini       hypre_CSRMatrixI(hdiag)    = NULL;
492225daaf8SStefano Zampini       hypre_CSRMatrixJ(hdiag)    = NULL;
493225daaf8SStefano Zampini       hypre_CSRMatrixData(hdiag) = NULL;
494225daaf8SStefano Zampini       hypre_CSRMatrixI(hoffd)    = NULL;
495225daaf8SStefano Zampini       hypre_CSRMatrixJ(hoffd)    = NULL;
496225daaf8SStefano Zampini       hypre_CSRMatrixData(hoffd) = NULL;
497225daaf8SStefano Zampini       ierr = MatHeaderReplace(A,&T);CHKERRQ(ierr);
49863c07aadSStefano Zampini     }
499225daaf8SStefano Zampini   } else {
500225daaf8SStefano Zampini     oii  = NULL;
501225daaf8SStefano Zampini     ojj  = NULL;
502225daaf8SStefano Zampini     oa   = NULL;
503225daaf8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
50463c07aadSStefano Zampini       Mat_SeqAIJ* b;
50563c07aadSStefano Zampini       ierr = MatCreateSeqAIJWithArrays(comm,m,n,dii,djj,da,B);CHKERRQ(ierr);
50663c07aadSStefano Zampini       /* hack SeqAIJ */
50763c07aadSStefano Zampini       b          = (Mat_SeqAIJ*)((*B)->data);
50863c07aadSStefano Zampini       b->free_a  = PETSC_TRUE;
50963c07aadSStefano Zampini       b->free_ij = PETSC_TRUE;
510225daaf8SStefano Zampini     } else if (reuse == MAT_INPLACE_MATRIX) {
511225daaf8SStefano Zampini       Mat T;
512225daaf8SStefano Zampini       ierr = MatCreateSeqAIJWithArrays(comm,m,n,dii,djj,da,&T);CHKERRQ(ierr);
513225daaf8SStefano Zampini       hypre_CSRMatrixI(hdiag)    = NULL;
514225daaf8SStefano Zampini       hypre_CSRMatrixJ(hdiag)    = NULL;
515225daaf8SStefano Zampini       hypre_CSRMatrixData(hdiag) = NULL;
516225daaf8SStefano Zampini       ierr = MatHeaderReplace(A,&T);CHKERRQ(ierr);
51763c07aadSStefano Zampini     }
518225daaf8SStefano Zampini   }
519225daaf8SStefano Zampini 
520225daaf8SStefano Zampini   /* we have to use hypre_Tfree to free the arrays */
52163c07aadSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
522225daaf8SStefano Zampini     void *ptrs[6] = {dii,djj,da,oii,ojj,oa};
523225daaf8SStefano Zampini     const char *names[6] = {"_hypre_csr_dii",
524225daaf8SStefano Zampini                             "_hypre_csr_djj",
525225daaf8SStefano Zampini                             "_hypre_csr_da",
526225daaf8SStefano Zampini                             "_hypre_csr_oii",
527225daaf8SStefano Zampini                             "_hypre_csr_ojj",
528225daaf8SStefano Zampini                             "_hypre_csr_oa"};
529225daaf8SStefano Zampini     for (i=0; i<6; i++) {
530225daaf8SStefano Zampini       PetscContainer c;
531225daaf8SStefano Zampini 
532225daaf8SStefano Zampini       ierr = PetscContainerCreate(comm,&c);CHKERRQ(ierr);
533225daaf8SStefano Zampini       ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr);
534225daaf8SStefano Zampini       ierr = PetscContainerSetUserDestroy(c,hypre_array_destroy);CHKERRQ(ierr);
535225daaf8SStefano Zampini       ierr = PetscObjectCompose((PetscObject)(*B),names[i],(PetscObject)c);CHKERRQ(ierr);
536225daaf8SStefano Zampini       ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
537225daaf8SStefano Zampini     }
53863c07aadSStefano Zampini   }
53963c07aadSStefano Zampini   PetscFunctionReturn(0);
54063c07aadSStefano Zampini }
54163c07aadSStefano Zampini 
54263c07aadSStefano Zampini #undef __FUNCT__
543c1a070e6SStefano Zampini #define __FUNCT__ "MatPtAP_AIJ_HYPRE"
544c1a070e6SStefano Zampini static PetscErrorCode MatPtAP_AIJ_HYPRE(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C)
545c1a070e6SStefano Zampini {
546c1a070e6SStefano Zampini   Mat_HYPRE          *hP = (Mat_HYPRE*)P->data;
547c1a070e6SStefano Zampini   hypre_ParCSRMatrix *tA,*Pparcsr,*ptapparcsr;
548c1a070e6SStefano Zampini   hypre_CSRMatrix    *hdiag,*hoffd;
549c1a070e6SStefano Zampini   Mat_SeqAIJ         *diag,*offd;
550c1a070e6SStefano Zampini   PetscInt           *garray,noffd,dnnz,onnz,*row_starts,*col_starts;
551c1a070e6SStefano Zampini   HYPRE_Int          type,P_owns_col_starts;
552c1a070e6SStefano Zampini   PetscBool          ismpiaij,isseqaij;
553c1a070e6SStefano Zampini   MPI_Comm           comm = PetscObjectComm((PetscObject)A);
554225daaf8SStefano Zampini   char               mtype[256];
555c1a070e6SStefano Zampini   PetscErrorCode     ierr;
556c1a070e6SStefano Zampini 
557c1a070e6SStefano Zampini   PetscFunctionBegin;
558c1a070e6SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hP->ij,&type));
559c1a070e6SStefano Zampini   if (type != HYPRE_PARCSR) SETERRQ(comm,PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
560c1a070e6SStefano Zampini   if (scall == MAT_REUSE_MATRIX) SETERRQ(comm,PETSC_ERR_SUP,"Unsupported MAT_REUSE_MATRIX");
561c1a070e6SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
562c1a070e6SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
563c1a070e6SStefano Zampini   if (!ismpiaij && !isseqaij) SETERRQ1(comm,PETSC_ERR_SUP,"Unsupported type %s",((PetscObject)A)->type);
564225daaf8SStefano Zampini 
565225daaf8SStefano Zampini   /* It looks like we don't need to have the diagonal entries
566225daaf8SStefano Zampini      ordered first in the rows of the diagonal part
567225daaf8SStefano Zampini      for boomerAMGBuildCoarseOperator to work */
568c1a070e6SStefano Zampini   if (ismpiaij) {
569c1a070e6SStefano Zampini     Mat_MPIAIJ *a = (Mat_MPIAIJ*)(A->data);
570c1a070e6SStefano Zampini 
571c1a070e6SStefano Zampini     diag   = (Mat_SeqAIJ*)a->A->data;
572c1a070e6SStefano Zampini     offd   = (Mat_SeqAIJ*)a->B->data;
573c1a070e6SStefano Zampini     garray = a->garray;
574c1a070e6SStefano Zampini     noffd  = a->B->cmap->N;
575c1a070e6SStefano Zampini     dnnz   = diag->nz;
576c1a070e6SStefano Zampini     onnz   = offd->nz;
577c1a070e6SStefano Zampini   } else {
578c1a070e6SStefano Zampini     diag    = (Mat_SeqAIJ*)A->data;
579c1a070e6SStefano Zampini     offd    = NULL;
580c1a070e6SStefano Zampini     garray  = NULL;
581c1a070e6SStefano Zampini     noffd   = 0;
582c1a070e6SStefano Zampini     dnnz    = diag->nz;
583c1a070e6SStefano Zampini     onnz    = 0;
584c1a070e6SStefano Zampini   }
585225daaf8SStefano Zampini 
586c1a070e6SStefano Zampini   /* create a temporary ParCSR */
587c1a070e6SStefano Zampini   if (HYPRE_AssumedPartitionCheck()) {
588c1a070e6SStefano Zampini    PetscMPIInt myid;
589c1a070e6SStefano Zampini 
590c1a070e6SStefano Zampini    ierr       = MPI_Comm_rank(comm,&myid);CHKERRQ(ierr);
591c1a070e6SStefano Zampini    row_starts = A->rmap->range + myid;
592c1a070e6SStefano Zampini    col_starts = A->cmap->range + myid;
593c1a070e6SStefano Zampini   } else {
594c1a070e6SStefano Zampini    row_starts = A->rmap->range;
595c1a070e6SStefano Zampini    col_starts = A->cmap->range;
596c1a070e6SStefano Zampini   }
597c1a070e6SStefano Zampini   tA = hypre_ParCSRMatrixCreate(comm,A->rmap->N,A->cmap->N,row_starts,col_starts,noffd,dnnz,onnz);
598c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetRowStartsOwner(tA,0);
599c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetColStartsOwner(tA,0);
600c1a070e6SStefano Zampini 
601225daaf8SStefano Zampini   /* set diagonal part */
602c1a070e6SStefano Zampini   hdiag = hypre_ParCSRMatrixDiag(tA);
603c1a070e6SStefano Zampini   hypre_CSRMatrixI(hdiag)           = diag->i;
604c1a070e6SStefano Zampini   hypre_CSRMatrixJ(hdiag)           = diag->j;
605c1a070e6SStefano Zampini   hypre_CSRMatrixData(hdiag)        = diag->a;
606c1a070e6SStefano Zampini   hypre_CSRMatrixNumNonzeros(hdiag) = diag->nz;
607c1a070e6SStefano Zampini   hypre_CSRMatrixSetRownnz(hdiag);
608c1a070e6SStefano Zampini   hypre_CSRMatrixSetDataOwner(hdiag,0);
609c1a070e6SStefano Zampini 
610225daaf8SStefano Zampini   /* set offdiagonal part */
611c1a070e6SStefano Zampini   hoffd = hypre_ParCSRMatrixOffd(tA);
612c1a070e6SStefano Zampini   if (offd) {
613c1a070e6SStefano Zampini     hypre_CSRMatrixI(hoffd)           = offd->i;
614c1a070e6SStefano Zampini     hypre_CSRMatrixJ(hoffd)           = offd->j;
615c1a070e6SStefano Zampini     hypre_CSRMatrixData(hoffd)        = offd->a;
616c1a070e6SStefano Zampini     hypre_CSRMatrixNumNonzeros(hoffd) = offd->nz;
617c1a070e6SStefano Zampini     hypre_CSRMatrixSetRownnz(hoffd);
618c1a070e6SStefano Zampini     hypre_CSRMatrixSetDataOwner(hoffd,0);
619c1a070e6SStefano Zampini     hypre_ParCSRMatrixSetNumNonzeros(tA);
620c1a070e6SStefano Zampini     hypre_ParCSRMatrixColMapOffd(tA) = garray;
621c1a070e6SStefano Zampini   }
622c1a070e6SStefano Zampini 
623c1a070e6SStefano Zampini   /* call RAP from BoomerAMG */
624c1a070e6SStefano Zampini   /* Warning: hypre_BoomerAMGBuildCoarseOperator steals the col_starts
625c1a070e6SStefano Zampini      from Pparcsr (even if it does not own them)! */
626c1a070e6SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hP->ij,(void**)&Pparcsr));
627c1a070e6SStefano Zampini   P_owns_col_starts = hypre_ParCSRMatrixOwnsColStarts(Pparcsr);
628c1a070e6SStefano Zampini   ierr = PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
629c1a070e6SStefano Zampini   PetscStackCallStandard(hypre_BoomerAMGBuildCoarseOperator,(Pparcsr,tA,Pparcsr,&ptapparcsr));
630c1a070e6SStefano Zampini   ierr = PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
631c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetRowStartsOwner(ptapparcsr,0);
632c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetColStartsOwner(ptapparcsr,0);
633c1a070e6SStefano Zampini   if (P_owns_col_starts) hypre_ParCSRMatrixSetColStartsOwner(Pparcsr, 1);
634c1a070e6SStefano Zampini 
635c1a070e6SStefano Zampini   /* set pointers to NULL before destroying tA */
636c1a070e6SStefano Zampini   hypre_CSRMatrixI(hdiag)          = NULL;
637c1a070e6SStefano Zampini   hypre_CSRMatrixJ(hdiag)          = NULL;
638c1a070e6SStefano Zampini   hypre_CSRMatrixData(hdiag)       = NULL;
639c1a070e6SStefano Zampini   hypre_CSRMatrixI(hoffd)          = NULL;
640c1a070e6SStefano Zampini   hypre_CSRMatrixJ(hoffd)          = NULL;
641c1a070e6SStefano Zampini   hypre_CSRMatrixData(hoffd)       = NULL;
642c1a070e6SStefano Zampini   hypre_ParCSRMatrixColMapOffd(tA) = NULL;
643c1a070e6SStefano Zampini   hypre_ParCSRMatrixDestroy(tA);
644225daaf8SStefano Zampini 
645225daaf8SStefano Zampini   /* create C depending on mtype */
646225daaf8SStefano Zampini   sprintf(mtype,MATAIJ);
647225daaf8SStefano Zampini   ierr = PetscOptionsGetString(((PetscObject)A)->options,((PetscObject)A)->prefix,"-matptap_hypre_outtype",mtype,256,NULL);CHKERRQ(ierr);
648225daaf8SStefano Zampini   ierr = MatCreateFromParCSR(ptapparcsr,mtype,PETSC_OWN_POINTER,C);CHKERRQ(ierr);
649c1a070e6SStefano Zampini   PetscFunctionReturn(0);
650c1a070e6SStefano Zampini }
651c1a070e6SStefano Zampini 
652c1a070e6SStefano Zampini #undef __FUNCT__
653cd8bc7baSStefano Zampini #define __FUNCT__ "MatPtAP_HYPRE_HYPRE"
654cd8bc7baSStefano Zampini static PetscErrorCode MatPtAP_HYPRE_HYPRE(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C)
655cd8bc7baSStefano Zampini {
656cd8bc7baSStefano Zampini   hypre_ParCSRMatrix *Aparcsr,*Pparcsr,*ptapparcsr;
657cd8bc7baSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE*)A->data, *hP = (Mat_HYPRE*)P->data;
658c1a070e6SStefano Zampini   HYPRE_Int          type,P_owns_col_starts;
659cd8bc7baSStefano Zampini   PetscErrorCode     ierr;
660cd8bc7baSStefano Zampini 
661cd8bc7baSStefano Zampini   PetscFunctionBegin;
662cd8bc7baSStefano Zampini   if (scall == MAT_REUSE_MATRIX) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Unsupported MAT_REUSE_MATRIX");
663cd8bc7baSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hA->ij,&type));
664cd8bc7baSStefano Zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
665cd8bc7baSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObjectType,(hP->ij,&type));
666cd8bc7baSStefano Zampini   if (type != HYPRE_PARCSR) SETERRQ(PetscObjectComm((PetscObject)P),PETSC_ERR_SUP,"Only HYPRE_PARCSR is supported");
667cd8bc7baSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&Aparcsr));
668cd8bc7baSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hP->ij,(void**)&Pparcsr));
669c1a070e6SStefano Zampini 
670c1a070e6SStefano Zampini   /* call RAP from BoomerAMG */
671c1a070e6SStefano Zampini   /* Warning: hypre_BoomerAMGBuildCoarseOperator steals the col_starts
672c1a070e6SStefano Zampini      from Pparcsr (even if it does not own them)! */
673c1a070e6SStefano Zampini   P_owns_col_starts = hypre_ParCSRMatrixOwnsColStarts(Pparcsr);
674c1a070e6SStefano Zampini   ierr = PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
675cd8bc7baSStefano Zampini   PetscStackCallStandard(hypre_BoomerAMGBuildCoarseOperator,(Pparcsr,Aparcsr,Pparcsr,&ptapparcsr));
676cd8bc7baSStefano Zampini   ierr = PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
677c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetRowStartsOwner(ptapparcsr,0);
678c1a070e6SStefano Zampini   hypre_ParCSRMatrixSetColStartsOwner(ptapparcsr,0);
679c1a070e6SStefano Zampini   if (P_owns_col_starts) hypre_ParCSRMatrixSetColStartsOwner(Pparcsr, 1);
680c1a070e6SStefano Zampini 
681c1a070e6SStefano Zampini   /* create MatHYPRE */
682225daaf8SStefano Zampini   ierr = MatCreateFromParCSR(ptapparcsr,MATHYPRE,PETSC_OWN_POINTER,C);CHKERRQ(ierr);
683cd8bc7baSStefano Zampini   PetscFunctionReturn(0);
684cd8bc7baSStefano Zampini }
685cd8bc7baSStefano Zampini 
686cd8bc7baSStefano Zampini #undef __FUNCT__
68763c07aadSStefano Zampini #define __FUNCT__ "MatMultTranspose_HYPRE"
688ea9daf28SStefano Zampini static PetscErrorCode MatMultTranspose_HYPRE(Mat A, Vec x, Vec y)
68963c07aadSStefano Zampini {
69063c07aadSStefano Zampini   PetscErrorCode ierr;
69163c07aadSStefano Zampini 
69263c07aadSStefano Zampini   PetscFunctionBegin;
69363c07aadSStefano Zampini   ierr = MatHYPRE_MultKernel_Private(A,x,y,PETSC_TRUE);CHKERRQ(ierr);
69463c07aadSStefano Zampini   PetscFunctionReturn(0);
69563c07aadSStefano Zampini }
69663c07aadSStefano Zampini 
69763c07aadSStefano Zampini #undef __FUNCT__
69863c07aadSStefano Zampini #define __FUNCT__ "MatMult_HYPRE"
699ea9daf28SStefano Zampini static PetscErrorCode MatMult_HYPRE(Mat A, Vec x, Vec y)
70063c07aadSStefano Zampini {
70163c07aadSStefano Zampini   PetscErrorCode ierr;
70263c07aadSStefano Zampini 
70363c07aadSStefano Zampini   PetscFunctionBegin;
70463c07aadSStefano Zampini   ierr = MatHYPRE_MultKernel_Private(A,x,y,PETSC_FALSE);CHKERRQ(ierr);
70563c07aadSStefano Zampini   PetscFunctionReturn(0);
70663c07aadSStefano Zampini }
70763c07aadSStefano Zampini 
70863c07aadSStefano Zampini #undef __FUNCT__
70963c07aadSStefano Zampini #define __FUNCT__ "MatHYPRE_MultKernel_Private"
710ea9daf28SStefano Zampini static PetscErrorCode MatHYPRE_MultKernel_Private(Mat A, Vec x, Vec y, PetscBool trans)
71163c07aadSStefano Zampini {
71263c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE*)A->data;
71363c07aadSStefano Zampini   hypre_ParCSRMatrix *parcsr;
71463c07aadSStefano Zampini   hypre_ParVector    *hx,*hy;
71563c07aadSStefano Zampini   PetscScalar        *ax,*ay,*sax,*say;
71663c07aadSStefano Zampini   PetscErrorCode     ierr;
71763c07aadSStefano Zampini 
71863c07aadSStefano Zampini   PetscFunctionBegin;
71963c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixGetObject,(hA->ij,(void**)&parcsr));
72063c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJVectorGetObject,(hA->x,(void**)&hx));
72163c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJVectorGetObject,(hA->b,(void**)&hy));
72263c07aadSStefano Zampini   ierr = VecGetArrayRead(x,(const PetscScalar**)&ax);CHKERRQ(ierr);
72363c07aadSStefano Zampini   ierr = VecGetArray(y,&ay);CHKERRQ(ierr);
72463c07aadSStefano Zampini   if (trans) {
72558968eb6SStefano Zampini     VecHYPRE_ParVectorReplacePointer(hA->x,ay,say);
72658968eb6SStefano Zampini     VecHYPRE_ParVectorReplacePointer(hA->b,ax,sax);
72763c07aadSStefano Zampini     hypre_ParCSRMatrixMatvecT(1.,parcsr,hy,0.,hx);
72858968eb6SStefano Zampini     VecHYPRE_ParVectorReplacePointer(hA->x,say,ay);
72958968eb6SStefano Zampini     VecHYPRE_ParVectorReplacePointer(hA->b,sax,ax);
73063c07aadSStefano Zampini   } else {
73158968eb6SStefano Zampini     VecHYPRE_ParVectorReplacePointer(hA->x,ax,sax);
73258968eb6SStefano Zampini     VecHYPRE_ParVectorReplacePointer(hA->b,ay,say);
73363c07aadSStefano Zampini     hypre_ParCSRMatrixMatvec(1.,parcsr,hx,0.,hy);
73458968eb6SStefano Zampini     VecHYPRE_ParVectorReplacePointer(hA->x,sax,ax);
73558968eb6SStefano Zampini     VecHYPRE_ParVectorReplacePointer(hA->b,say,ay);
73663c07aadSStefano Zampini   }
73763c07aadSStefano Zampini   ierr = VecRestoreArrayRead(x,(const PetscScalar**)&ax);CHKERRQ(ierr);
73863c07aadSStefano Zampini   ierr = VecRestoreArray(y,&ay);CHKERRQ(ierr);
73963c07aadSStefano Zampini   PetscFunctionReturn(0);
74063c07aadSStefano Zampini }
74163c07aadSStefano Zampini 
74263c07aadSStefano Zampini #undef __FUNCT__
74363c07aadSStefano Zampini #define __FUNCT__ "MatDestroy_HYPRE"
744ea9daf28SStefano Zampini static PetscErrorCode MatDestroy_HYPRE(Mat A)
74563c07aadSStefano Zampini {
74663c07aadSStefano Zampini   Mat_HYPRE      *hA = (Mat_HYPRE*)A->data;
74763c07aadSStefano Zampini   PetscErrorCode ierr;
74863c07aadSStefano Zampini 
74963c07aadSStefano Zampini   PetscFunctionBegin;
75063c07aadSStefano Zampini   if (hA->x) PetscStackCallStandard(HYPRE_IJVectorDestroy,(hA->x));
75163c07aadSStefano Zampini   if (hA->b) PetscStackCallStandard(HYPRE_IJVectorDestroy,(hA->b));
752978814f1SStefano Zampini   if (hA->ij) {
753978814f1SStefano Zampini     if (!hA->inner_free) hypre_IJMatrixObject(hA->ij) = NULL;
754978814f1SStefano Zampini     PetscStackCallStandard(HYPRE_IJMatrixDestroy,(hA->ij));
755978814f1SStefano Zampini   }
75663c07aadSStefano Zampini   if (hA->comm) { ierr = MPI_Comm_free(&hA->comm);CHKERRQ(ierr); }
75763c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_hypre_aij_C",NULL);CHKERRQ(ierr);
7582df22349SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_hypre_is_C",NULL);CHKERRQ(ierr);
759c1a070e6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatPtAP_seqaij_hypre_C",NULL);CHKERRQ(ierr);
760c1a070e6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatPtAP_mpiaij_hypre_C",NULL);CHKERRQ(ierr);
76163c07aadSStefano Zampini   ierr = PetscFree(A->data);CHKERRQ(ierr);
76263c07aadSStefano Zampini   PetscFunctionReturn(0);
76363c07aadSStefano Zampini }
76463c07aadSStefano Zampini 
76563c07aadSStefano Zampini #undef __FUNCT__
76663c07aadSStefano Zampini #define __FUNCT__ "MatSetUp_HYPRE"
767ea9daf28SStefano Zampini static PetscErrorCode MatSetUp_HYPRE(Mat A)
76863c07aadSStefano Zampini {
76963c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE*)A->data;
77063c07aadSStefano Zampini   Vec                x,b;
77163c07aadSStefano Zampini   PetscErrorCode     ierr;
77263c07aadSStefano Zampini 
77363c07aadSStefano Zampini   PetscFunctionBegin;
77463c07aadSStefano Zampini   if (hA->x) PetscFunctionReturn(0);
77563c07aadSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
77663c07aadSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
77763c07aadSStefano Zampini   ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)A),1,A->cmap->n,A->cmap->N,NULL,&x);CHKERRQ(ierr);
77863c07aadSStefano Zampini   ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)A),1,A->rmap->n,A->rmap->N,NULL,&b);CHKERRQ(ierr);
77963c07aadSStefano Zampini   ierr = VecHYPRE_IJVectorCreate(x,&hA->x);CHKERRQ(ierr);
78063c07aadSStefano Zampini   ierr = VecHYPRE_IJVectorCreate(b,&hA->b);CHKERRQ(ierr);
78163c07aadSStefano Zampini   ierr = VecDestroy(&x);CHKERRQ(ierr);
78263c07aadSStefano Zampini   ierr = VecDestroy(&b);CHKERRQ(ierr);
78363c07aadSStefano Zampini   PetscFunctionReturn(0);
78463c07aadSStefano Zampini }
78563c07aadSStefano Zampini 
78663c07aadSStefano Zampini #undef __FUNCT__
78763c07aadSStefano Zampini #define __FUNCT__ "MatAssemblyEnd_HYPRE"
788ea9daf28SStefano Zampini static PetscErrorCode MatAssemblyEnd_HYPRE(Mat A, MatAssemblyType mode)
78963c07aadSStefano Zampini {
79063c07aadSStefano Zampini   Mat_HYPRE          *hA = (Mat_HYPRE*)A->data;
79163c07aadSStefano Zampini   PetscErrorCode     ierr;
79263c07aadSStefano Zampini 
79363c07aadSStefano Zampini   PetscFunctionBegin;
79463c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixAssemble,(hA->ij));
79563c07aadSStefano Zampini   PetscFunctionReturn(0);
79663c07aadSStefano Zampini }
79763c07aadSStefano Zampini 
798225daaf8SStefano Zampini /*
799225daaf8SStefano Zampini    MatCreateFromParCSR - Creates a matrix from a hypre_ParCSRMatrix
800225daaf8SStefano Zampini 
801225daaf8SStefano Zampini    Collective
802225daaf8SStefano Zampini 
803225daaf8SStefano Zampini    Input Parameters:
804225daaf8SStefano Zampini +  vparcsr  - the pointer to the hypre_ParCSRMatrix
805bb4689ddSStefano Zampini .  mtype    - matrix type to be created. Currently MATAIJ, MATIS and MATHYPRE are supported.
806225daaf8SStefano Zampini -  copymode - PETSc copying options
807225daaf8SStefano Zampini 
808225daaf8SStefano Zampini    Output Parameter:
809225daaf8SStefano Zampini .  A  - the matrix
810225daaf8SStefano Zampini 
811225daaf8SStefano Zampini    Level: intermediate
812225daaf8SStefano Zampini 
813225daaf8SStefano Zampini .seealso: MatHYPRE, PetscCopyMode
814225daaf8SStefano Zampini */
815978814f1SStefano Zampini #undef __FUNCT__
816225daaf8SStefano Zampini #define __FUNCT__ "MatCreateFromParCSR"
817225daaf8SStefano Zampini PETSC_EXTERN PetscErrorCode MatCreateFromParCSR(void *vparcsr, MatType mtype, PetscCopyMode copymode, Mat* A)
818978814f1SStefano Zampini {
819225daaf8SStefano Zampini   Mat                   T;
820978814f1SStefano Zampini   Mat_HYPRE             *hA;
82163c07aadSStefano Zampini   hypre_ParCSRMatrix    *parcsr;
822978814f1SStefano Zampini   MPI_Comm              comm;
823978814f1SStefano Zampini   PetscInt              rstart,rend,cstart,cend,M,N;
824bb4689ddSStefano Zampini   PetscBool             isseqaij,ismpiaij,isaij,ishyp,isis;
825978814f1SStefano Zampini   PetscErrorCode        ierr;
826978814f1SStefano Zampini 
827978814f1SStefano Zampini   PetscFunctionBegin;
828978814f1SStefano Zampini   parcsr = (hypre_ParCSRMatrix *)vparcsr;
829978814f1SStefano Zampini   comm   = hypre_ParCSRMatrixComm(parcsr);
830225daaf8SStefano Zampini   ierr   = PetscStrcmp(mtype,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
831225daaf8SStefano Zampini   ierr   = PetscStrcmp(mtype,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
832225daaf8SStefano Zampini   ierr   = PetscStrcmp(mtype,MATAIJ,&isaij);CHKERRQ(ierr);
833225daaf8SStefano Zampini   ierr   = PetscStrcmp(mtype,MATHYPRE,&ishyp);CHKERRQ(ierr);
8348cfe8d00SStefano Zampini   ierr   = PetscStrcmp(mtype,MATIS,&isis);CHKERRQ(ierr);
835225daaf8SStefano Zampini   isaij  = (PetscBool)(isseqaij || ismpiaij || isaij);
836bb4689ddSStefano 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);
837225daaf8SStefano Zampini   if (ishyp && copymode == PETSC_COPY_VALUES) SETERRQ(comm,PETSC_ERR_SUP,"Unsupported copymode PETSC_COPY_VALUES");
838978814f1SStefano Zampini 
839978814f1SStefano Zampini   /* access ParCSRMatrix */
840978814f1SStefano Zampini   rstart = hypre_ParCSRMatrixFirstRowIndex(parcsr);
841978814f1SStefano Zampini   rend   = hypre_ParCSRMatrixLastRowIndex(parcsr);
842978814f1SStefano Zampini   cstart = hypre_ParCSRMatrixFirstColDiag(parcsr);
843978814f1SStefano Zampini   cend   = hypre_ParCSRMatrixLastColDiag(parcsr);
844978814f1SStefano Zampini   M      = hypre_ParCSRMatrixGlobalNumRows(parcsr);
845978814f1SStefano Zampini   N      = hypre_ParCSRMatrixGlobalNumCols(parcsr);
846978814f1SStefano Zampini 
847978814f1SStefano Zampini   /* create PETSc matrix with MatHYPRE */
848225daaf8SStefano Zampini   ierr = MatCreate(comm,&T);CHKERRQ(ierr);
849225daaf8SStefano Zampini   ierr = MatSetSizes(T,rend-rstart+1,cend-cstart+1,M,N);CHKERRQ(ierr);
850225daaf8SStefano Zampini   ierr = MatSetType(T,MATHYPRE);CHKERRQ(ierr);
851225daaf8SStefano Zampini   ierr = MatSetUp(T);CHKERRQ(ierr);
852225daaf8SStefano Zampini   hA   = (Mat_HYPRE*)(T->data);
853978814f1SStefano Zampini 
854978814f1SStefano Zampini   /* create HYPRE_IJMatrix */
855978814f1SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixCreate,(hA->comm,rstart,rend-1,cstart,cend-1,&hA->ij));
856978814f1SStefano Zampini 
857978814f1SStefano Zampini   /* set ParCSR object */
858978814f1SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(hA->ij,HYPRE_PARCSR));
859978814f1SStefano Zampini   hypre_IJMatrixObject(hA->ij) = parcsr;
860978814f1SStefano Zampini 
861978814f1SStefano Zampini   /* set assembled flag */
862978814f1SStefano Zampini   hypre_IJMatrixAssembleFlag(hA->ij) = 1;
863978814f1SStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixInitialize,(hA->ij));
864225daaf8SStefano Zampini   if (ishyp) {
865978814f1SStefano Zampini     /* prevent from freeing the pointer */
866978814f1SStefano Zampini     if (copymode == PETSC_USE_POINTER) hA->inner_free = PETSC_FALSE;
867225daaf8SStefano Zampini     *A = T;
868978814f1SStefano Zampini     ierr = MatAssemblyBegin(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
869978814f1SStefano Zampini     ierr = MatAssemblyEnd(*A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
870bb4689ddSStefano Zampini   } else if (isaij) {
871bb4689ddSStefano Zampini     if (copymode != PETSC_OWN_POINTER) {
872225daaf8SStefano Zampini       /* prevent from freeing the pointer */
873225daaf8SStefano Zampini       hA->inner_free = PETSC_FALSE;
874225daaf8SStefano Zampini       ierr = MatConvert_HYPRE_AIJ(T,MATAIJ,MAT_INITIAL_MATRIX,A);CHKERRQ(ierr);
875225daaf8SStefano Zampini       ierr = MatDestroy(&T);CHKERRQ(ierr);
876225daaf8SStefano Zampini     } else { /* AIJ return type with PETSC_OWN_POINTER */
877225daaf8SStefano Zampini       ierr = MatConvert_HYPRE_AIJ(T,MATAIJ,MAT_INPLACE_MATRIX,&T);CHKERRQ(ierr);
878225daaf8SStefano Zampini       *A   = T;
879225daaf8SStefano Zampini     }
880bb4689ddSStefano Zampini   } else if (isis) {
8818cfe8d00SStefano Zampini     ierr = MatConvert_HYPRE_IS(T,MATIS,MAT_INITIAL_MATRIX,A);CHKERRQ(ierr);
8828cfe8d00SStefano Zampini     if (copymode != PETSC_OWN_POINTER) hA->inner_free = PETSC_FALSE;
883bb4689ddSStefano Zampini     ierr = MatDestroy(&T);CHKERRQ(ierr);
884bb4689ddSStefano Zampini   }
885978814f1SStefano Zampini   PetscFunctionReturn(0);
886978814f1SStefano Zampini }
887978814f1SStefano Zampini 
88863c07aadSStefano Zampini #undef __FUNCT__
88963c07aadSStefano Zampini #define __FUNCT__ "MatCreate_HYPRE"
89063c07aadSStefano Zampini PETSC_EXTERN PetscErrorCode MatCreate_HYPRE(Mat B)
89163c07aadSStefano Zampini {
89263c07aadSStefano Zampini   Mat_HYPRE      *hB;
89363c07aadSStefano Zampini   PetscErrorCode ierr;
89463c07aadSStefano Zampini 
89563c07aadSStefano Zampini   PetscFunctionBegin;
89663c07aadSStefano Zampini   ierr           = PetscNewLog(B,&hB);CHKERRQ(ierr);
897978814f1SStefano Zampini   hB->inner_free = PETSC_TRUE;
898978814f1SStefano Zampini 
89963c07aadSStefano Zampini   B->data       = (void*)hB;
90063c07aadSStefano Zampini   B->rmap->bs   = 1;
90163c07aadSStefano Zampini   B->assembled  = PETSC_FALSE;
90263c07aadSStefano Zampini 
90363c07aadSStefano Zampini   B->ops->mult          = MatMult_HYPRE;
90463c07aadSStefano Zampini   B->ops->multtranspose = MatMultTranspose_HYPRE;
90563c07aadSStefano Zampini   B->ops->setup         = MatSetUp_HYPRE;
90663c07aadSStefano Zampini   B->ops->destroy       = MatDestroy_HYPRE;
90763c07aadSStefano Zampini   B->ops->assemblyend   = MatAssemblyEnd_HYPRE;
908cd8bc7baSStefano Zampini   B->ops->ptap          = MatPtAP_HYPRE_HYPRE;
90963c07aadSStefano Zampini 
91063c07aadSStefano Zampini   ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)B),&hB->comm);CHKERRQ(ierr);
91163c07aadSStefano Zampini   ierr = PetscObjectChangeTypeName((PetscObject)B,MATHYPRE);CHKERRQ(ierr);
91263c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_hypre_aij_C",MatConvert_HYPRE_AIJ);CHKERRQ(ierr);
9132df22349SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_hypre_is_C",MatConvert_HYPRE_IS);CHKERRQ(ierr);
914c1a070e6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatPtAP_seqaij_hypre_C",MatPtAP_AIJ_HYPRE);CHKERRQ(ierr);
915c1a070e6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatPtAP_mpiaij_hypre_C",MatPtAP_AIJ_HYPRE);CHKERRQ(ierr);
91663c07aadSStefano Zampini   PetscFunctionReturn(0);
91763c07aadSStefano Zampini }
91863c07aadSStefano Zampini 
919225daaf8SStefano Zampini #undef __FUNCT__
920225daaf8SStefano Zampini #define __FUNCT__ "hypre_array_destroy"
921225daaf8SStefano Zampini static PetscErrorCode hypre_array_destroy(void *ptr)
922225daaf8SStefano Zampini {
923225daaf8SStefano Zampini    PetscFunctionBegin;
924225daaf8SStefano Zampini    hypre_TFree(ptr);
925225daaf8SStefano Zampini    PetscFunctionReturn(0);
926225daaf8SStefano Zampini }
927225daaf8SStefano Zampini 
92863c07aadSStefano Zampini #if 0
92963c07aadSStefano Zampini /*
93063c07aadSStefano Zampini     Does NOT copy the data over, instead uses DIRECTLY the pointers from the PETSc MPIAIJ format
93163c07aadSStefano Zampini 
93263c07aadSStefano Zampini     This is UNFINISHED and does NOT work! The problem is that hypre puts the diagonal entry first
93363c07aadSStefano Zampini     which will corrupt the PETSc data structure if we did this. Need a work around to this problem.
93463c07aadSStefano Zampini */
93563c07aadSStefano Zampini #include <_hypre_IJ_mv.h>
93663c07aadSStefano Zampini #include <HYPRE_IJ_mv.h>
93763c07aadSStefano Zampini 
93863c07aadSStefano Zampini #undef __FUNCT__
93963c07aadSStefano Zampini #define __FUNCT__ "MatHYPRE_IJMatrixLink"
94063c07aadSStefano Zampini PetscErrorCode MatHYPRE_IJMatrixLink(Mat A, HYPRE_IJMatrix *ij)
94163c07aadSStefano Zampini {
94263c07aadSStefano Zampini   PetscErrorCode        ierr;
94363c07aadSStefano Zampini   PetscInt              rstart,rend,cstart,cend;
94463c07aadSStefano Zampini   PetscBool             flg;
94563c07aadSStefano Zampini   hypre_AuxParCSRMatrix *aux_matrix;
94663c07aadSStefano Zampini 
94763c07aadSStefano Zampini   PetscFunctionBegin;
94863c07aadSStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
94963c07aadSStefano Zampini   PetscValidType(A,1);
95063c07aadSStefano Zampini   PetscValidPointer(ij,2);
95163c07aadSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&flg);CHKERRQ(ierr);
95263c07aadSStefano Zampini   if (!flg) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Can only use with PETSc MPIAIJ matrices");
95363c07aadSStefano Zampini   ierr = MatSetUp(A);CHKERRQ(ierr);
95463c07aadSStefano Zampini 
95563c07aadSStefano Zampini   ierr   = PetscLogEventBegin(MAT_Convert,A,0,0,0);CHKERRQ(ierr);
95663c07aadSStefano Zampini   rstart = A->rmap->rstart;
95763c07aadSStefano Zampini   rend   = A->rmap->rend;
95863c07aadSStefano Zampini   cstart = A->cmap->rstart;
95963c07aadSStefano Zampini   cend   = A->cmap->rend;
96063c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixCreate,(PetscObjectComm((PetscObject)A),rstart,rend-1,cstart,cend-1,ij));
96163c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixSetObjectType,(*ij,HYPRE_PARCSR));
96263c07aadSStefano Zampini 
96363c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixInitialize,(*ij));
96463c07aadSStefano Zampini   PetscStackCall("hypre_IJMatrixTranslator",aux_matrix = (hypre_AuxParCSRMatrix*)hypre_IJMatrixTranslator(*ij));
96563c07aadSStefano Zampini 
96663c07aadSStefano Zampini   hypre_AuxParCSRMatrixNeedAux(aux_matrix) = 0;
96763c07aadSStefano Zampini 
96863c07aadSStefano Zampini   /* this is the Hack part where we monkey directly with the hypre datastructures */
96963c07aadSStefano Zampini 
97063c07aadSStefano Zampini   PetscStackCallStandard(HYPRE_IJMatrixAssemble,(*ij));
97163c07aadSStefano Zampini   ierr = PetscLogEventEnd(MAT_Convert,A,0,0,0);CHKERRQ(ierr);
97263c07aadSStefano Zampini   PetscFunctionReturn(0);
97363c07aadSStefano Zampini }
97463c07aadSStefano Zampini #endif
975