xref: /petsc/src/dm/impls/da/hypre/mhyp.c (revision 98921bda46e76d7aaed9e0138c5ff9d0ce93f355)
1f4bdf6c4SBarry Smith 
2f4bdf6c4SBarry Smith /*
3f4bdf6c4SBarry Smith     Creates hypre ijmatrix from PETSc matrix
4f4bdf6c4SBarry Smith */
5c6db04a5SJed Brown #include <petscsys.h>
639accc25SStefano Zampini #include <petsc/private/petschypre.h>
7af0996ceSBarry Smith #include <petsc/private/matimpl.h>
8c6db04a5SJed Brown #include <petscdmda.h>                /*I "petscdmda.h" I*/
9c6db04a5SJed Brown #include <../src/dm/impls/da/hypre/mhyp.h>
10f4bdf6c4SBarry Smith 
11f4bdf6c4SBarry Smith /* -----------------------------------------------------------------------------------------------------------------*/
12f4bdf6c4SBarry Smith 
13f4bdf6c4SBarry Smith /*MC
14f4bdf6c4SBarry Smith    MATHYPRESTRUCT - MATHYPRESTRUCT = "hyprestruct" - A matrix type to be used for parallel sparse matrices
15f4bdf6c4SBarry Smith           based on the hypre HYPRE_StructMatrix.
16f4bdf6c4SBarry Smith 
17f4bdf6c4SBarry Smith    Level: intermediate
18f4bdf6c4SBarry Smith 
1995452b02SPatrick Sanan    Notes:
2095452b02SPatrick Sanan     Unlike the more general support for blocks in hypre this allows only one block per process and requires the block
21f4bdf6c4SBarry Smith           be defined by a DMDA.
22f4bdf6c4SBarry Smith 
2359cb773eSBarry Smith           The matrix needs a DMDA associated with it by either a call to MatSetDM() or if the matrix is obtained from DMCreateMatrix()
24f4bdf6c4SBarry Smith 
2559cb773eSBarry Smith .seealso: MatCreate(), PCPFMG, MatSetDM(), DMCreateMatrix()
26f4bdf6c4SBarry Smith M*/
27f4bdf6c4SBarry Smith 
28f4bdf6c4SBarry Smith PetscErrorCode  MatSetValuesLocal_HYPREStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
29f4bdf6c4SBarry Smith {
302cf14000SStefano Zampini   HYPRE_Int       index[3],entries[7];
312cf14000SStefano Zampini   PetscInt        i,j,stencil,row;
3239accc25SStefano Zampini   HYPRE_Complex   *values = (HYPRE_Complex*)y;
33f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex     = (Mat_HYPREStruct*) mat->data;
34f4bdf6c4SBarry Smith 
35f4bdf6c4SBarry Smith   PetscFunctionBegin;
36*98921bdaSJacob Faibussowitsch   if (PetscUnlikely(ncol > 7)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"ncol %D > 7 too large",ncol);
37f4bdf6c4SBarry Smith   for (i=0; i<nrow; i++) {
38f4bdf6c4SBarry Smith     for (j=0; j<ncol; j++) {
39f4bdf6c4SBarry Smith       stencil = icol[j] - irow[i];
40f4bdf6c4SBarry Smith       if (!stencil) {
41f4bdf6c4SBarry Smith         entries[j] = 3;
42f4bdf6c4SBarry Smith       } else if (stencil == -1) {
43f4bdf6c4SBarry Smith         entries[j] = 2;
44f4bdf6c4SBarry Smith       } else if (stencil == 1) {
45f4bdf6c4SBarry Smith         entries[j] = 4;
46f4bdf6c4SBarry Smith       } else if (stencil == -ex->gnx) {
47f4bdf6c4SBarry Smith         entries[j] = 1;
48f4bdf6c4SBarry Smith       } else if (stencil == ex->gnx) {
49f4bdf6c4SBarry Smith         entries[j] = 5;
50f4bdf6c4SBarry Smith       } else if (stencil == -ex->gnxgny) {
51f4bdf6c4SBarry Smith         entries[j] = 0;
52f4bdf6c4SBarry Smith       } else if (stencil == ex->gnxgny) {
53f4bdf6c4SBarry Smith         entries[j] = 6;
54*98921bdaSJacob Faibussowitsch       } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row %D local column %D have bad stencil %D",irow[i],icol[j],stencil);
55f4bdf6c4SBarry Smith     }
56f4bdf6c4SBarry Smith     row      = ex->gindices[irow[i]] - ex->rstart;
572cf14000SStefano Zampini     index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
582cf14000SStefano Zampini     index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
592cf14000SStefano Zampini     index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
60f4bdf6c4SBarry Smith     if (addv == ADD_VALUES) {
6139accc25SStefano Zampini       PetscStackCallStandard(HYPRE_StructMatrixAddToValues,(ex->hmat,index,ncol,entries,values));
62f4bdf6c4SBarry Smith     } else {
6339accc25SStefano Zampini       PetscStackCallStandard(HYPRE_StructMatrixSetValues,(ex->hmat,index,ncol,entries,values));
64f4bdf6c4SBarry Smith     }
65f4bdf6c4SBarry Smith     values += ncol;
66f4bdf6c4SBarry Smith   }
67f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
68f4bdf6c4SBarry Smith }
69f4bdf6c4SBarry Smith 
70f4bdf6c4SBarry Smith PetscErrorCode  MatZeroRowsLocal_HYPREStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscScalar d,Vec x,Vec b)
71f4bdf6c4SBarry Smith {
72f4bdf6c4SBarry Smith   PetscErrorCode  ierr;
732cf14000SStefano Zampini   HYPRE_Int       index[3],entries[7] = {0,1,2,3,4,5,6};
742cf14000SStefano Zampini   PetscInt        row,i;
7539accc25SStefano Zampini   HYPRE_Complex   values[7];
76f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
77f4bdf6c4SBarry Smith 
78f4bdf6c4SBarry Smith   PetscFunctionBegin;
79ce94432eSBarry Smith   if (x && b) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"No support");
80580bdb30SBarry Smith   ierr = PetscArrayzero(values,7);CHKERRQ(ierr);
8139accc25SStefano Zampini   ierr = PetscHYPREScalarCast(d,&values[3]);CHKERRQ(ierr);
82f4bdf6c4SBarry Smith   for (i=0; i<nrow; i++) {
83f4bdf6c4SBarry Smith     row      = ex->gindices[irow[i]] - ex->rstart;
842cf14000SStefano Zampini     index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
852cf14000SStefano Zampini     index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
862cf14000SStefano Zampini     index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
872cf14000SStefano Zampini     PetscStackCallStandard(HYPRE_StructMatrixSetValues,(ex->hmat,index,7,entries,values));
88f4bdf6c4SBarry Smith   }
89fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixAssemble,(ex->hmat));
90f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
91f4bdf6c4SBarry Smith }
92f4bdf6c4SBarry Smith 
93f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPREStruct_3d(Mat mat)
94f4bdf6c4SBarry Smith {
952cf14000SStefano Zampini   HYPRE_Int       indices[7] = {0,1,2,3,4,5,6};
96f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex        = (Mat_HYPREStruct*) mat->data;
97f4bdf6c4SBarry Smith 
98f4bdf6c4SBarry Smith   PetscFunctionBegin;
99f4bdf6c4SBarry Smith   /* hypre has no public interface to do this */
1002cf14000SStefano Zampini   PetscStackCallStandard(hypre_StructMatrixClearBoxValues,(ex->hmat,&ex->hbox,7,indices,0,1));
101fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixAssemble,(ex->hmat));
102f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
103f4bdf6c4SBarry Smith }
104f4bdf6c4SBarry Smith 
10559cb773eSBarry Smith static PetscErrorCode  MatSetUp_HYPREStruct(Mat mat)
106f4bdf6c4SBarry Smith {
107f4bdf6c4SBarry Smith   PetscErrorCode         ierr;
108f4bdf6c4SBarry Smith   Mat_HYPREStruct        *ex = (Mat_HYPREStruct*) mat->data;
1092cf14000SStefano Zampini   HYPRE_Int              sw[6];
1102cf14000SStefano Zampini   HYPRE_Int              hlower[3],hupper[3];
1112cf14000SStefano Zampini   PetscInt               dim,dof,psw,nx,ny,nz,ilower[3],iupper[3],ssize,i;
112bff4a2f0SMatthew G. Knepley   DMBoundaryType         px,py,pz;
113f4bdf6c4SBarry Smith   DMDAStencilType        st;
114565245c5SBarry Smith   ISLocalToGlobalMapping ltog;
11559cb773eSBarry Smith   DM                     da;
116f4bdf6c4SBarry Smith 
117f4bdf6c4SBarry Smith   PetscFunctionBegin;
11859cb773eSBarry Smith   ierr   = MatGetDM(mat,(DM*)&da);CHKERRQ(ierr);
119f4bdf6c4SBarry Smith   ex->da = da;
120f4bdf6c4SBarry Smith   ierr   = PetscObjectReference((PetscObject)da);CHKERRQ(ierr);
121f4bdf6c4SBarry Smith 
1222cf14000SStefano Zampini   ierr = DMDAGetInfo(ex->da,&dim,0,0,0,0,0,0,&dof,&psw,&px,&py,&pz,&st);CHKERRQ(ierr);
123f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(ex->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
1242cf14000SStefano Zampini 
1252cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
126f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
127f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
128f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
1292cf14000SStefano Zampini   hlower[0]  = (HYPRE_Int)ilower[0];
1302cf14000SStefano Zampini   hlower[1]  = (HYPRE_Int)ilower[1];
1312cf14000SStefano Zampini   hlower[2]  = (HYPRE_Int)ilower[2];
1322cf14000SStefano Zampini   hupper[0]  = (HYPRE_Int)iupper[0];
1332cf14000SStefano Zampini   hupper[1]  = (HYPRE_Int)iupper[1];
1342cf14000SStefano Zampini   hupper[2]  = (HYPRE_Int)iupper[2];
135f4bdf6c4SBarry Smith 
136f4bdf6c4SBarry Smith   /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
1372cf14000SStefano Zampini   ex->hbox.imin[0] = hlower[0];
1382cf14000SStefano Zampini   ex->hbox.imin[1] = hlower[1];
1392cf14000SStefano Zampini   ex->hbox.imin[2] = hlower[2];
1402cf14000SStefano Zampini   ex->hbox.imax[0] = hupper[0];
1412cf14000SStefano Zampini   ex->hbox.imax[1] = hupper[1];
1422cf14000SStefano Zampini   ex->hbox.imax[2] = hupper[2];
143f4bdf6c4SBarry Smith 
144f4bdf6c4SBarry Smith   /* create the hypre grid object and set its information */
145ce94432eSBarry Smith   if (dof > 1) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Currently only support for scalar problems");
146ce94432eSBarry Smith   if (px || py || pz) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add periodic support by calling HYPRE_StructGridSetPeriodic()");
147fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructGridCreate,(ex->hcomm,dim,&ex->hgrid));
1482cf14000SStefano Zampini   PetscStackCallStandard(HYPRE_StructGridSetExtents,(ex->hgrid,hlower,hupper));
149fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructGridAssemble,(ex->hgrid));
150f4bdf6c4SBarry Smith 
1512cf14000SStefano Zampini   sw[5] = sw[4] = sw[3] = sw[2] = sw[1] = sw[0] = psw;
1522cf14000SStefano Zampini   PetscStackCallStandard(HYPRE_StructGridSetNumGhost,(ex->hgrid,sw));
153f4bdf6c4SBarry Smith 
154f4bdf6c4SBarry Smith   /* create the hypre stencil object and set its information */
155ce94432eSBarry Smith   if (sw[0] > 1) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for wider stencils");
156ce94432eSBarry Smith   if (st == DMDA_STENCIL_BOX) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for box stencils");
157f4bdf6c4SBarry Smith   if (dim == 1) {
1582cf14000SStefano Zampini     HYPRE_Int offsets[3][1] = {{-1},{0},{1}};
159f4bdf6c4SBarry Smith     ssize = 3;
160fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_StructStencilCreate,(dim,ssize,&ex->hstencil));
161f4bdf6c4SBarry Smith     for (i=0; i<ssize; i++) {
1622cf14000SStefano Zampini       PetscStackCallStandard(HYPRE_StructStencilSetElement,(ex->hstencil,i,offsets[i]));
163f4bdf6c4SBarry Smith     }
164f4bdf6c4SBarry Smith   } else if (dim == 2) {
1652cf14000SStefano Zampini     HYPRE_Int offsets[5][2] = {{0,-1},{-1,0},{0,0},{1,0},{0,1}};
166f4bdf6c4SBarry Smith     ssize = 5;
167fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_StructStencilCreate,(dim,ssize,&ex->hstencil));
168f4bdf6c4SBarry Smith     for (i=0; i<ssize; i++) {
1692cf14000SStefano Zampini       PetscStackCallStandard(HYPRE_StructStencilSetElement,(ex->hstencil,i,offsets[i]));
170f4bdf6c4SBarry Smith     }
171f4bdf6c4SBarry Smith   } else if (dim == 3) {
1722cf14000SStefano Zampini     HYPRE_Int offsets[7][3] = {{0,0,-1},{0,-1,0},{-1,0,0},{0,0,0},{1,0,0},{0,1,0},{0,0,1}};
173f4bdf6c4SBarry Smith     ssize = 7;
174fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_StructStencilCreate,(dim,ssize,&ex->hstencil));
175f4bdf6c4SBarry Smith     for (i=0; i<ssize; i++) {
1762cf14000SStefano Zampini       PetscStackCallStandard(HYPRE_StructStencilSetElement,(ex->hstencil,i,offsets[i]));
177f4bdf6c4SBarry Smith     }
178f4bdf6c4SBarry Smith   }
179f4bdf6c4SBarry Smith 
180f4bdf6c4SBarry Smith   /* create the HYPRE vector for rhs and solution */
181fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorCreate,(ex->hcomm,ex->hgrid,&ex->hb));
182fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorCreate,(ex->hcomm,ex->hgrid,&ex->hx));
183fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorInitialize,(ex->hb));
184fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorInitialize,(ex->hx));
185fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorAssemble,(ex->hb));
186fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorAssemble,(ex->hx));
187f4bdf6c4SBarry Smith 
188f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
189fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixCreate,(ex->hcomm,ex->hgrid,ex->hstencil,&ex->hmat));
190fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructGridDestroy,(ex->hgrid));
191fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructStencilDestroy,(ex->hstencil));
192f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
193fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_StructMatrixInitialize,(ex->hmat));
194f4bdf6c4SBarry Smith     ex->needsinitialization = PETSC_FALSE;
195f4bdf6c4SBarry Smith   }
196f4bdf6c4SBarry Smith 
197f4bdf6c4SBarry Smith   /* set the global and local sizes of the matrix */
198f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(da,0,0,0,&nx,&ny,&nz);CHKERRQ(ierr);
199f4bdf6c4SBarry Smith   ierr = MatSetSizes(mat,dof*nx*ny*nz,dof*nx*ny*nz,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
200f4bdf6c4SBarry Smith   ierr = PetscLayoutSetBlockSize(mat->rmap,1);CHKERRQ(ierr);
201f4bdf6c4SBarry Smith   ierr = PetscLayoutSetBlockSize(mat->cmap,1);CHKERRQ(ierr);
202f4bdf6c4SBarry Smith   ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr);
203f4bdf6c4SBarry Smith   ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr);
20459cb773eSBarry Smith   mat->preallocated = PETSC_TRUE;
205f4bdf6c4SBarry Smith 
206f4bdf6c4SBarry Smith   if (dim == 3) {
207f4bdf6c4SBarry Smith     mat->ops->setvalueslocal = MatSetValuesLocal_HYPREStruct_3d;
208f4bdf6c4SBarry Smith     mat->ops->zerorowslocal  = MatZeroRowsLocal_HYPREStruct_3d;
209f4bdf6c4SBarry Smith     mat->ops->zeroentries    = MatZeroEntries_HYPREStruct_3d;
2108865f1eaSKarl Rupp 
21159cb773eSBarry Smith     /*        ierr = MatZeroEntries_HYPREStruct_3d(mat);CHKERRQ(ierr); */
212ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Only support for 3d DMDA currently");
213f4bdf6c4SBarry Smith 
214f4bdf6c4SBarry Smith   /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
2150298fd71SBarry Smith   ierr        = MatGetOwnershipRange(mat,&ex->rstart,NULL);CHKERRQ(ierr);
216565245c5SBarry Smith   ierr        = DMGetLocalToGlobalMapping(ex->da,&ltog);CHKERRQ(ierr);
217565245c5SBarry Smith   ierr        = ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **) &ex->gindices);CHKERRQ(ierr);
218f4bdf6c4SBarry Smith   ierr        = DMDAGetGhostCorners(ex->da,0,0,0,&ex->gnx,&ex->gnxgny,0);CHKERRQ(ierr);
219f4bdf6c4SBarry Smith   ex->gnxgny *= ex->gnx;
220f4bdf6c4SBarry Smith   ierr        = DMDAGetCorners(ex->da,&ex->xs,&ex->ys,&ex->zs,&ex->nx,&ex->ny,0);CHKERRQ(ierr);
221f4bdf6c4SBarry Smith   ex->nxny    = ex->nx*ex->ny;
222f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
223f4bdf6c4SBarry Smith }
224f4bdf6c4SBarry Smith 
225f4bdf6c4SBarry Smith PetscErrorCode MatMult_HYPREStruct(Mat A,Vec x,Vec y)
226f4bdf6c4SBarry Smith {
227f4bdf6c4SBarry Smith   PetscErrorCode    ierr;
228b026d285SBarry Smith   const PetscScalar *xx;
229b026d285SBarry Smith   PetscScalar       *yy;
2304ddd07fcSJed Brown   PetscInt          ilower[3],iupper[3];
2312cf14000SStefano Zampini   HYPRE_Int         hlower[3],hupper[3];
232f4bdf6c4SBarry Smith   Mat_HYPREStruct   *mx = (Mat_HYPREStruct*)(A->data);
233f4bdf6c4SBarry Smith 
234f4bdf6c4SBarry Smith   PetscFunctionBegin;
235f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
2362cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
237f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
238f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
239f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
2402cf14000SStefano Zampini   hlower[0]  = (HYPRE_Int)ilower[0];
2412cf14000SStefano Zampini   hlower[1]  = (HYPRE_Int)ilower[1];
2422cf14000SStefano Zampini   hlower[2]  = (HYPRE_Int)ilower[2];
2432cf14000SStefano Zampini   hupper[0]  = (HYPRE_Int)iupper[0];
2442cf14000SStefano Zampini   hupper[1]  = (HYPRE_Int)iupper[1];
2452cf14000SStefano Zampini   hupper[2]  = (HYPRE_Int)iupper[2];
246f4bdf6c4SBarry Smith 
247f4bdf6c4SBarry Smith   /* copy x values over to hypre */
248fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorSetConstantValues,(mx->hb,0.0));
249b026d285SBarry Smith   ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
25039accc25SStefano Zampini   PetscStackCallStandard(HYPRE_StructVectorSetBoxValues,(mx->hb,hlower,hupper,(HYPRE_Complex*)xx));
251b026d285SBarry Smith   ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
252fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorAssemble,(mx->hb));
253fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixMatvec,(1.0,mx->hmat,mx->hb,0.0,mx->hx));
254f4bdf6c4SBarry Smith 
255f4bdf6c4SBarry Smith   /* copy solution values back to PETSc */
256f4bdf6c4SBarry Smith   ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
25739accc25SStefano Zampini   PetscStackCallStandard(HYPRE_StructVectorGetBoxValues,(mx->hx,hlower,hupper,(HYPRE_Complex*)yy));
258f4bdf6c4SBarry Smith   ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
259f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
260f4bdf6c4SBarry Smith }
261f4bdf6c4SBarry Smith 
262f4bdf6c4SBarry Smith PetscErrorCode MatAssemblyEnd_HYPREStruct(Mat mat,MatAssemblyType mode)
263f4bdf6c4SBarry Smith {
264f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
265f4bdf6c4SBarry Smith 
266f4bdf6c4SBarry Smith   PetscFunctionBegin;
267fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixAssemble,(ex->hmat));
268fd3f9acdSBarry Smith   /* PetscStackCallStandard(HYPRE_StructMatrixPrint,("dummy",ex->hmat,0)); */
269f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
270f4bdf6c4SBarry Smith }
271f4bdf6c4SBarry Smith 
272f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPREStruct(Mat mat)
273f4bdf6c4SBarry Smith {
274f4bdf6c4SBarry Smith   PetscFunctionBegin;
275f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
276f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
277f4bdf6c4SBarry Smith }
278f4bdf6c4SBarry Smith 
279f4bdf6c4SBarry Smith PetscErrorCode MatDestroy_HYPREStruct(Mat mat)
280f4bdf6c4SBarry Smith {
281f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
282f4bdf6c4SBarry Smith   PetscErrorCode  ierr;
283f4bdf6c4SBarry Smith 
284f4bdf6c4SBarry Smith   PetscFunctionBegin;
285fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixDestroy,(ex->hmat));
286fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorDestroy,(ex->hx));
287fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorDestroy,(ex->hb));
28859cb773eSBarry Smith   ierr = PetscObjectDereference((PetscObject)ex->da);CHKERRQ(ierr);
289ffc4695bSBarry Smith   ierr = MPI_Comm_free(&(ex->hcomm));CHKERRMPI(ierr);
29059cb773eSBarry Smith   ierr = PetscFree(ex);CHKERRQ(ierr);
291f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
292f4bdf6c4SBarry Smith }
293f4bdf6c4SBarry Smith 
2948cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_HYPREStruct(Mat B)
295f4bdf6c4SBarry Smith {
296f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex;
297f4bdf6c4SBarry Smith   PetscErrorCode  ierr;
298f4bdf6c4SBarry Smith 
299f4bdf6c4SBarry Smith   PetscFunctionBegin;
300b00a9115SJed Brown   ierr         = PetscNewLog(B,&ex);CHKERRQ(ierr);
301f4bdf6c4SBarry Smith   B->data      = (void*)ex;
302f4bdf6c4SBarry Smith   B->rmap->bs  = 1;
303f4bdf6c4SBarry Smith   B->assembled = PETSC_FALSE;
304f4bdf6c4SBarry Smith 
305f4bdf6c4SBarry Smith   B->insertmode = NOT_SET_VALUES;
306f4bdf6c4SBarry Smith 
307f4bdf6c4SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_HYPREStruct;
308f4bdf6c4SBarry Smith   B->ops->mult        = MatMult_HYPREStruct;
309f4bdf6c4SBarry Smith   B->ops->zeroentries = MatZeroEntries_HYPREStruct;
310f4bdf6c4SBarry Smith   B->ops->destroy     = MatDestroy_HYPREStruct;
31159cb773eSBarry Smith   B->ops->setup       = MatSetUp_HYPREStruct;
312f4bdf6c4SBarry Smith 
313f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
314f4bdf6c4SBarry Smith 
315ffc4695bSBarry Smith   ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)B),&(ex->hcomm));CHKERRMPI(ierr);
316f4bdf6c4SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATHYPRESTRUCT);CHKERRQ(ierr);
317f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
318f4bdf6c4SBarry Smith }
319f4bdf6c4SBarry Smith 
320f4bdf6c4SBarry Smith /*MC
321f4bdf6c4SBarry Smith    MATHYPRESSTRUCT - MATHYPRESSTRUCT = "hypresstruct" - A matrix type to be used for parallel sparse matrices
322f4bdf6c4SBarry Smith           based on the hypre HYPRE_SStructMatrix.
323f4bdf6c4SBarry Smith 
324f4bdf6c4SBarry Smith    Level: intermediate
325f4bdf6c4SBarry Smith 
32695452b02SPatrick Sanan    Notes:
32795452b02SPatrick Sanan     Unlike hypre's general semi-struct object consisting of a collection of structured-grid objects and unstructured
328b026d285SBarry Smith           grid objects, we restrict the semi-struct objects to consist of only structured-grid components.
329f4bdf6c4SBarry Smith 
330f4bdf6c4SBarry Smith           Unlike the more general support for parts and blocks in hypre this allows only one part, and one block per process and requires the block
331f4bdf6c4SBarry Smith           be defined by a DMDA.
332f4bdf6c4SBarry Smith 
33359cb773eSBarry Smith           The matrix needs a DMDA associated with it by either a call to MatSetDM() or if the matrix is obtained from DMCreateMatrix()
334f4bdf6c4SBarry Smith 
335f4bdf6c4SBarry Smith M*/
336f4bdf6c4SBarry Smith 
337f4bdf6c4SBarry Smith PetscErrorCode  MatSetValuesLocal_HYPRESStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
338f4bdf6c4SBarry Smith {
339f4bdf6c4SBarry Smith   PetscErrorCode    ierr;
3402cf14000SStefano Zampini   HYPRE_Int         index[3],*entries;
3412cf14000SStefano Zampini   PetscInt          i,j,stencil;
34239accc25SStefano Zampini   HYPRE_Complex     *values = (HYPRE_Complex*)y;
343f4bdf6c4SBarry Smith   Mat_HYPRESStruct  *ex     = (Mat_HYPRESStruct*) mat->data;
344f4bdf6c4SBarry Smith 
3454ddd07fcSJed Brown   PetscInt          part = 0;          /* Petsc sstruct interface only allows 1 part */
3464ddd07fcSJed Brown   PetscInt          ordering;
3474ddd07fcSJed Brown   PetscInt          grid_rank, to_grid_rank;
3484ddd07fcSJed Brown   PetscInt          var_type, to_var_type;
3494ddd07fcSJed Brown   PetscInt          to_var_entry = 0;
3504ddd07fcSJed Brown   PetscInt          nvars= ex->nvars;
3512cf14000SStefano Zampini   PetscInt          row;
352f4bdf6c4SBarry Smith 
353f4bdf6c4SBarry Smith   PetscFunctionBegin;
354785e854fSJed Brown   ierr     = PetscMalloc1(7*nvars,&entries);CHKERRQ(ierr);
355f4bdf6c4SBarry Smith   ordering = ex->dofs_order;  /* ordering= 0   nodal ordering
356f4bdf6c4SBarry Smith                                            1   variable ordering */
35761710fbeSStefano Zampini   /* stencil entries are ordered by variables: var0_stencil0, var0_stencil1, ..., var0_stencil6, var1_stencil0, var1_stencil1, ...  */
358f4bdf6c4SBarry Smith   if (!ordering) {
359f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
360f4bdf6c4SBarry Smith       grid_rank= irow[i]/nvars;
361f4bdf6c4SBarry Smith       var_type = (irow[i] % nvars);
362f4bdf6c4SBarry Smith 
363f4bdf6c4SBarry Smith       for (j=0; j<ncol; j++) {
364f4bdf6c4SBarry Smith         to_grid_rank= icol[j]/nvars;
365f4bdf6c4SBarry Smith         to_var_type = (icol[j] % nvars);
366f4bdf6c4SBarry Smith 
367f4bdf6c4SBarry Smith         to_var_entry= to_var_entry*7;
368f4bdf6c4SBarry Smith         entries[j]  = to_var_entry;
369f4bdf6c4SBarry Smith 
370f4bdf6c4SBarry Smith         stencil = to_grid_rank-grid_rank;
371f4bdf6c4SBarry Smith         if (!stencil) {
372f4bdf6c4SBarry Smith           entries[j] += 3;
373f4bdf6c4SBarry Smith         } else if (stencil == -1) {
374f4bdf6c4SBarry Smith           entries[j] += 2;
375f4bdf6c4SBarry Smith         } else if (stencil == 1) {
376f4bdf6c4SBarry Smith           entries[j] += 4;
377f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnx) {
378f4bdf6c4SBarry Smith           entries[j] += 1;
379f4bdf6c4SBarry Smith         } else if (stencil == ex->gnx) {
380f4bdf6c4SBarry Smith           entries[j] += 5;
381f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnxgny) {
382f4bdf6c4SBarry Smith           entries[j] += 0;
383f4bdf6c4SBarry Smith         } else if (stencil == ex->gnxgny) {
384f4bdf6c4SBarry Smith           entries[j] += 6;
385*98921bdaSJacob Faibussowitsch         } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row %D local column %D have bad stencil %D",irow[i],icol[j],stencil);
386f4bdf6c4SBarry Smith       }
387f4bdf6c4SBarry Smith 
388f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
3892cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
3902cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
3912cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
392f4bdf6c4SBarry Smith 
393f4bdf6c4SBarry Smith       if (addv == ADD_VALUES) {
39439accc25SStefano Zampini         PetscStackCallStandard(HYPRE_SStructMatrixAddToValues,(ex->ss_mat,part,index,var_type,ncol,entries,values));
395f4bdf6c4SBarry Smith       } else {
39639accc25SStefano Zampini         PetscStackCallStandard(HYPRE_SStructMatrixSetValues,(ex->ss_mat,part,index,var_type,ncol,entries,values));
397f4bdf6c4SBarry Smith       }
398f4bdf6c4SBarry Smith       values += ncol;
399f4bdf6c4SBarry Smith     }
400f4bdf6c4SBarry Smith   } else {
401f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
402f4bdf6c4SBarry Smith       var_type = irow[i]/(ex->gnxgnygnz);
403f4bdf6c4SBarry Smith       grid_rank= irow[i] - var_type*(ex->gnxgnygnz);
404f4bdf6c4SBarry Smith 
405f4bdf6c4SBarry Smith       for (j=0; j<ncol; j++) {
406f4bdf6c4SBarry Smith         to_var_type = icol[j]/(ex->gnxgnygnz);
407f4bdf6c4SBarry Smith         to_grid_rank= icol[j] - to_var_type*(ex->gnxgnygnz);
408f4bdf6c4SBarry Smith 
409f4bdf6c4SBarry Smith         to_var_entry= to_var_entry*7;
410f4bdf6c4SBarry Smith         entries[j]  = to_var_entry;
411f4bdf6c4SBarry Smith 
412f4bdf6c4SBarry Smith         stencil = to_grid_rank-grid_rank;
413f4bdf6c4SBarry Smith         if (!stencil) {
414f4bdf6c4SBarry Smith           entries[j] += 3;
415f4bdf6c4SBarry Smith         } else if (stencil == -1) {
416f4bdf6c4SBarry Smith           entries[j] += 2;
417f4bdf6c4SBarry Smith         } else if (stencil == 1) {
418f4bdf6c4SBarry Smith           entries[j] += 4;
419f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnx) {
420f4bdf6c4SBarry Smith           entries[j] += 1;
421f4bdf6c4SBarry Smith         } else if (stencil == ex->gnx) {
422f4bdf6c4SBarry Smith           entries[j] += 5;
423f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnxgny) {
424f4bdf6c4SBarry Smith           entries[j] += 0;
425f4bdf6c4SBarry Smith         } else if (stencil == ex->gnxgny) {
426f4bdf6c4SBarry Smith           entries[j] += 6;
427*98921bdaSJacob Faibussowitsch         } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row %D local column %D have bad stencil %D",irow[i],icol[j],stencil);
428f4bdf6c4SBarry Smith       }
429f4bdf6c4SBarry Smith 
430f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
4312cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
4322cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
4332cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
434f4bdf6c4SBarry Smith 
435f4bdf6c4SBarry Smith       if (addv == ADD_VALUES) {
43639accc25SStefano Zampini         PetscStackCallStandard(HYPRE_SStructMatrixAddToValues,(ex->ss_mat,part,index,var_type,ncol,entries,values));
437f4bdf6c4SBarry Smith       } else {
43839accc25SStefano Zampini         PetscStackCallStandard(HYPRE_SStructMatrixSetValues,(ex->ss_mat,part,index,var_type,ncol,entries,values));
439f4bdf6c4SBarry Smith       }
440f4bdf6c4SBarry Smith       values += ncol;
441f4bdf6c4SBarry Smith     }
442f4bdf6c4SBarry Smith   }
443f4bdf6c4SBarry Smith   ierr = PetscFree(entries);CHKERRQ(ierr);
444f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
445f4bdf6c4SBarry Smith }
446f4bdf6c4SBarry Smith 
447f4bdf6c4SBarry Smith PetscErrorCode  MatZeroRowsLocal_HYPRESStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscScalar d,Vec x,Vec b)
448f4bdf6c4SBarry Smith {
449f4bdf6c4SBarry Smith   PetscErrorCode   ierr;
4502cf14000SStefano Zampini   HYPRE_Int        index[3],*entries;
4512cf14000SStefano Zampini   PetscInt         i;
45239accc25SStefano Zampini   HYPRE_Complex    **values;
453f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data;
454f4bdf6c4SBarry Smith 
4554ddd07fcSJed Brown   PetscInt         part     = 0;      /* Petsc sstruct interface only allows 1 part */
4564ddd07fcSJed Brown   PetscInt         ordering = ex->dofs_order;
4574ddd07fcSJed Brown   PetscInt         grid_rank;
4584ddd07fcSJed Brown   PetscInt         var_type;
4594ddd07fcSJed Brown   PetscInt         nvars= ex->nvars;
4602cf14000SStefano Zampini   PetscInt         row;
461f4bdf6c4SBarry Smith 
462f4bdf6c4SBarry Smith   PetscFunctionBegin;
463ce94432eSBarry Smith   if (x && b) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"No support");
464785e854fSJed Brown   ierr = PetscMalloc1(7*nvars,&entries);CHKERRQ(ierr);
465f4bdf6c4SBarry Smith 
466785e854fSJed Brown   ierr = PetscMalloc1(nvars,&values);CHKERRQ(ierr);
467785e854fSJed Brown   ierr = PetscMalloc1(7*nvars*nvars,&values[0]);CHKERRQ(ierr);
468f4bdf6c4SBarry Smith   for (i=1; i<nvars; i++) {
469f4bdf6c4SBarry Smith     values[i] = values[i-1] + nvars*7;
470f4bdf6c4SBarry Smith   }
471f4bdf6c4SBarry Smith 
472f4bdf6c4SBarry Smith   for (i=0; i< nvars; i++) {
473580bdb30SBarry Smith     ierr = PetscArrayzero(values[i],nvars*7*sizeof(HYPRE_Complex));CHKERRQ(ierr);
47439accc25SStefano Zampini     ierr = PetscHYPREScalarCast(d,values[i]+3);CHKERRQ(ierr);
475f4bdf6c4SBarry Smith   }
476f4bdf6c4SBarry Smith 
4778865f1eaSKarl Rupp   for (i=0; i< nvars*7; i++) entries[i] = i;
478f4bdf6c4SBarry Smith 
479f4bdf6c4SBarry Smith   if (!ordering) {
480f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
481f4bdf6c4SBarry Smith       grid_rank = irow[i] / nvars;
482f4bdf6c4SBarry Smith       var_type  = (irow[i] % nvars);
483f4bdf6c4SBarry Smith 
484f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
4852cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
4862cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
4872cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
4882cf14000SStefano Zampini       PetscStackCallStandard(HYPRE_SStructMatrixSetValues,(ex->ss_mat,part,index,var_type,7*nvars,entries,values[var_type]));
489f4bdf6c4SBarry Smith     }
490f4bdf6c4SBarry Smith   } else {
491f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
492f4bdf6c4SBarry Smith       var_type = irow[i]/(ex->gnxgnygnz);
493f4bdf6c4SBarry Smith       grid_rank= irow[i] - var_type*(ex->gnxgnygnz);
494f4bdf6c4SBarry Smith 
495f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
4962cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
4972cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
4982cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
4992cf14000SStefano Zampini       PetscStackCallStandard(HYPRE_SStructMatrixSetValues,(ex->ss_mat,part,index,var_type,7*nvars,entries,values[var_type]));
500f4bdf6c4SBarry Smith     }
501f4bdf6c4SBarry Smith   }
502fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructMatrixAssemble,(ex->ss_mat));
503f4bdf6c4SBarry Smith   ierr = PetscFree(values[0]);CHKERRQ(ierr);
504f4bdf6c4SBarry Smith   ierr = PetscFree(values);CHKERRQ(ierr);
505f4bdf6c4SBarry Smith   ierr = PetscFree(entries);CHKERRQ(ierr);
506f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
507f4bdf6c4SBarry Smith }
508f4bdf6c4SBarry Smith 
509f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPRESStruct_3d(Mat mat)
510f4bdf6c4SBarry Smith {
511f4bdf6c4SBarry Smith   PetscErrorCode   ierr;
512f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex  = (Mat_HYPRESStruct*) mat->data;
5134ddd07fcSJed Brown   PetscInt         nvars= ex->nvars;
5144ddd07fcSJed Brown   PetscInt         size;
5154ddd07fcSJed Brown   PetscInt         part= 0;   /* only one part */
516f4bdf6c4SBarry Smith 
517f4bdf6c4SBarry Smith   PetscFunctionBegin;
518f4bdf6c4SBarry Smith   size = ((ex->hbox.imax[0])-(ex->hbox.imin[0])+1)*((ex->hbox.imax[1])-(ex->hbox.imin[1])+1)*((ex->hbox.imax[2])-(ex->hbox.imin[2])+1);
519f4bdf6c4SBarry Smith   {
5202cf14000SStefano Zampini     HYPRE_Int     i,*entries,iupper[3],ilower[3];
52139accc25SStefano Zampini     HYPRE_Complex *values;
5224ddd07fcSJed Brown 
523f4bdf6c4SBarry Smith     for (i= 0; i< 3; i++) {
524f4bdf6c4SBarry Smith       ilower[i] = ex->hbox.imin[i];
525f4bdf6c4SBarry Smith       iupper[i] = ex->hbox.imax[i];
526f4bdf6c4SBarry Smith     }
527f4bdf6c4SBarry Smith 
528dcca6d9dSJed Brown     ierr = PetscMalloc2(nvars*7,&entries,nvars*7*size,&values);CHKERRQ(ierr);
5298865f1eaSKarl Rupp     for (i= 0; i< nvars*7; i++) entries[i] = i;
530580bdb30SBarry Smith     ierr = PetscArrayzero(values,nvars*7*size);CHKERRQ(ierr);
531f4bdf6c4SBarry Smith 
532f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
5332cf14000SStefano Zampini       PetscStackCallStandard(HYPRE_SStructMatrixSetBoxValues,(ex->ss_mat,part,ilower,iupper,i,nvars*7,entries,values));
534f4bdf6c4SBarry Smith     }
535f4bdf6c4SBarry Smith     ierr = PetscFree2(entries,values);CHKERRQ(ierr);
536f4bdf6c4SBarry Smith   }
537fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructMatrixAssemble,(ex->ss_mat));
538f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
539f4bdf6c4SBarry Smith }
540f4bdf6c4SBarry Smith 
54159cb773eSBarry Smith static PetscErrorCode  MatSetUp_HYPRESStruct(Mat mat)
542f4bdf6c4SBarry Smith {
543f4bdf6c4SBarry Smith   PetscErrorCode         ierr;
544f4bdf6c4SBarry Smith   Mat_HYPRESStruct       *ex = (Mat_HYPRESStruct*) mat->data;
545f4bdf6c4SBarry Smith   PetscInt               dim,dof,sw[3],nx,ny,nz;
5464ddd07fcSJed Brown   PetscInt               ilower[3],iupper[3],ssize,i;
547bff4a2f0SMatthew G. Knepley   DMBoundaryType         px,py,pz;
548f4bdf6c4SBarry Smith   DMDAStencilType        st;
5494ddd07fcSJed Brown   PetscInt               nparts= 1;  /* assuming only one part */
5504ddd07fcSJed Brown   PetscInt               part  = 0;
551565245c5SBarry Smith   ISLocalToGlobalMapping ltog;
55259cb773eSBarry Smith   DM                     da;
553b026d285SBarry Smith 
554f4bdf6c4SBarry Smith   PetscFunctionBegin;
55559cb773eSBarry Smith   ierr   = MatGetDM(mat,(DM*)&da);CHKERRQ(ierr);
556f4bdf6c4SBarry Smith   ex->da = da;
557f4bdf6c4SBarry Smith   ierr   = PetscObjectReference((PetscObject)da);CHKERRQ(ierr);
558f4bdf6c4SBarry Smith 
5597ab44359SJed Brown   ierr       = DMDAGetInfo(ex->da,&dim,0,0,0,0,0,0,&dof,&sw[0],&px,&py,&pz,&st);CHKERRQ(ierr);
560f4bdf6c4SBarry Smith   ierr       = DMDAGetCorners(ex->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
561f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
562f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
563f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
564f4bdf6c4SBarry Smith   /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
565f4bdf6c4SBarry Smith   ex->hbox.imin[0] = ilower[0];
566f4bdf6c4SBarry Smith   ex->hbox.imin[1] = ilower[1];
567f4bdf6c4SBarry Smith   ex->hbox.imin[2] = ilower[2];
568f4bdf6c4SBarry Smith   ex->hbox.imax[0] = iupper[0];
569f4bdf6c4SBarry Smith   ex->hbox.imax[1] = iupper[1];
570f4bdf6c4SBarry Smith   ex->hbox.imax[2] = iupper[2];
571f4bdf6c4SBarry Smith 
572f4bdf6c4SBarry Smith   ex->dofs_order = 0;
573f4bdf6c4SBarry Smith 
574f4bdf6c4SBarry Smith   /* assuming that the same number of dofs on each gridpoint. Also assume all cell-centred based */
575f4bdf6c4SBarry Smith   ex->nvars= dof;
576f4bdf6c4SBarry Smith 
577f4bdf6c4SBarry Smith   /* create the hypre grid object and set its information */
578ce94432eSBarry Smith   if (px || py || pz) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add periodic support by calling HYPRE_SStructGridSetPeriodic()");
579fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGridCreate,(ex->hcomm,dim,nparts,&ex->ss_grid));
580fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGridSetExtents,(ex->ss_grid,part,ex->hbox.imin,ex->hbox.imax));
581f4bdf6c4SBarry Smith   {
582f4bdf6c4SBarry Smith     HYPRE_SStructVariable *vartypes;
583785e854fSJed Brown     ierr = PetscMalloc1(ex->nvars,&vartypes);CHKERRQ(ierr);
5848865f1eaSKarl Rupp     for (i= 0; i< ex->nvars; i++) vartypes[i]= HYPRE_SSTRUCT_VARIABLE_CELL;
585fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructGridSetVariables,(ex->ss_grid, part, ex->nvars,vartypes));
586f4bdf6c4SBarry Smith     ierr = PetscFree(vartypes);CHKERRQ(ierr);
587f4bdf6c4SBarry Smith   }
588fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGridAssemble,(ex->ss_grid));
589f4bdf6c4SBarry Smith 
590f4bdf6c4SBarry Smith   sw[1] = sw[0];
591f4bdf6c4SBarry Smith   sw[2] = sw[1];
592fd3f9acdSBarry Smith   /* PetscStackCallStandard(HYPRE_SStructGridSetNumGhost,(ex->ss_grid,sw)); */
593f4bdf6c4SBarry Smith 
594f4bdf6c4SBarry Smith   /* create the hypre stencil object and set its information */
595ce94432eSBarry Smith   if (sw[0] > 1) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for wider stencils");
596ce94432eSBarry Smith   if (st == DMDA_STENCIL_BOX) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for box stencils");
597f4bdf6c4SBarry Smith 
598f4bdf6c4SBarry Smith   if (dim == 1) {
5992cf14000SStefano Zampini     HYPRE_Int offsets[3][1] = {{-1},{0},{1}};
6004ddd07fcSJed Brown     PetscInt  j, cnt;
601f4bdf6c4SBarry Smith 
602f4bdf6c4SBarry Smith     ssize = 3*(ex->nvars);
603fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructStencilCreate,(dim,ssize,&ex->ss_stencil));
604f4bdf6c4SBarry Smith     cnt= 0;
605f4bdf6c4SBarry Smith     for (i = 0; i < (ex->nvars); i++) {
606f4bdf6c4SBarry Smith       for (j = 0; j < 3; j++) {
6072cf14000SStefano Zampini         PetscStackCallStandard(HYPRE_SStructStencilSetEntry,(ex->ss_stencil, cnt, offsets[j], i));
608f4bdf6c4SBarry Smith         cnt++;
609f4bdf6c4SBarry Smith       }
610f4bdf6c4SBarry Smith     }
611f4bdf6c4SBarry Smith   } else if (dim == 2) {
6122cf14000SStefano Zampini     HYPRE_Int offsets[5][2] = {{0,-1},{-1,0},{0,0},{1,0},{0,1}};
6134ddd07fcSJed Brown     PetscInt  j, cnt;
614f4bdf6c4SBarry Smith 
615f4bdf6c4SBarry Smith     ssize = 5*(ex->nvars);
616fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructStencilCreate,(dim,ssize,&ex->ss_stencil));
617f4bdf6c4SBarry Smith     cnt= 0;
618f4bdf6c4SBarry Smith     for (i= 0; i< (ex->nvars); i++) {
619f4bdf6c4SBarry Smith       for (j= 0; j< 5; j++) {
6202cf14000SStefano Zampini         PetscStackCallStandard(HYPRE_SStructStencilSetEntry,(ex->ss_stencil, cnt, offsets[j], i));
621f4bdf6c4SBarry Smith         cnt++;
622f4bdf6c4SBarry Smith       }
623f4bdf6c4SBarry Smith     }
624f4bdf6c4SBarry Smith   } else if (dim == 3) {
6252cf14000SStefano Zampini     HYPRE_Int offsets[7][3] = {{0,0,-1},{0,-1,0},{-1,0,0},{0,0,0},{1,0,0},{0,1,0},{0,0,1}};
6264ddd07fcSJed Brown     PetscInt  j, cnt;
627f4bdf6c4SBarry Smith 
628f4bdf6c4SBarry Smith     ssize = 7*(ex->nvars);
629fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructStencilCreate,(dim,ssize,&ex->ss_stencil));
630f4bdf6c4SBarry Smith     cnt= 0;
631f4bdf6c4SBarry Smith     for (i= 0; i< (ex->nvars); i++) {
632f4bdf6c4SBarry Smith       for (j= 0; j< 7; j++) {
6332cf14000SStefano Zampini         PetscStackCallStandard(HYPRE_SStructStencilSetEntry,(ex->ss_stencil, cnt, offsets[j], i));
634f4bdf6c4SBarry Smith         cnt++;
635f4bdf6c4SBarry Smith       }
636f4bdf6c4SBarry Smith     }
637f4bdf6c4SBarry Smith   }
638f4bdf6c4SBarry Smith 
639f4bdf6c4SBarry Smith   /* create the HYPRE graph */
640fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGraphCreate,(ex->hcomm, ex->ss_grid, &(ex->ss_graph)));
641f4bdf6c4SBarry Smith 
642f4bdf6c4SBarry Smith   /* set the stencil graph. Note that each variable has the same graph. This means that each
643f4bdf6c4SBarry Smith      variable couples to all the other variable and with the same stencil pattern. */
644f4bdf6c4SBarry Smith   for (i= 0; i< (ex->nvars); i++) {
645fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructGraphSetStencil,(ex->ss_graph,part,i,ex->ss_stencil));
646f4bdf6c4SBarry Smith   }
647fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGraphAssemble,(ex->ss_graph));
648f4bdf6c4SBarry Smith 
649f4bdf6c4SBarry Smith   /* create the HYPRE sstruct vectors for rhs and solution */
650fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorCreate,(ex->hcomm,ex->ss_grid,&ex->ss_b));
651fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorCreate,(ex->hcomm,ex->ss_grid,&ex->ss_x));
652fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorInitialize,(ex->ss_b));
653fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorInitialize,(ex->ss_x));
654fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorAssemble,(ex->ss_b));
655fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorAssemble,(ex->ss_x));
656f4bdf6c4SBarry Smith 
657f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
658fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructMatrixCreate,(ex->hcomm,ex->ss_graph,&ex->ss_mat));
659fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGridDestroy,(ex->ss_grid));
660fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructStencilDestroy,(ex->ss_stencil));
661f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
662fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructMatrixInitialize,(ex->ss_mat));
663f4bdf6c4SBarry Smith     ex->needsinitialization = PETSC_FALSE;
664f4bdf6c4SBarry Smith   }
665f4bdf6c4SBarry Smith 
666f4bdf6c4SBarry Smith   /* set the global and local sizes of the matrix */
667f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(da,0,0,0,&nx,&ny,&nz);CHKERRQ(ierr);
668f4bdf6c4SBarry Smith   ierr = MatSetSizes(mat,dof*nx*ny*nz,dof*nx*ny*nz,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
66961710fbeSStefano Zampini   ierr = PetscLayoutSetBlockSize(mat->rmap,dof);CHKERRQ(ierr);
67061710fbeSStefano Zampini   ierr = PetscLayoutSetBlockSize(mat->cmap,dof);CHKERRQ(ierr);
671f4bdf6c4SBarry Smith   ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr);
672f4bdf6c4SBarry Smith   ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr);
67361710fbeSStefano Zampini   mat->preallocated = PETSC_TRUE;
674f4bdf6c4SBarry Smith 
675f4bdf6c4SBarry Smith   if (dim == 3) {
676f4bdf6c4SBarry Smith     mat->ops->setvalueslocal = MatSetValuesLocal_HYPRESStruct_3d;
677f4bdf6c4SBarry Smith     mat->ops->zerorowslocal  = MatZeroRowsLocal_HYPRESStruct_3d;
678f4bdf6c4SBarry Smith     mat->ops->zeroentries    = MatZeroEntries_HYPRESStruct_3d;
6798865f1eaSKarl Rupp 
68061710fbeSStefano Zampini     /* ierr = MatZeroEntries_HYPRESStruct_3d(mat);CHKERRQ(ierr); */
681ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Only support for 3d DMDA currently");
682f4bdf6c4SBarry Smith 
683f4bdf6c4SBarry Smith   /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
6840298fd71SBarry Smith   ierr = MatGetOwnershipRange(mat,&ex->rstart,NULL);CHKERRQ(ierr);
685565245c5SBarry Smith   ierr = DMGetLocalToGlobalMapping(ex->da,&ltog);CHKERRQ(ierr);
686565245c5SBarry Smith   ierr = ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **) &ex->gindices);CHKERRQ(ierr);
687f4bdf6c4SBarry Smith   ierr = DMDAGetGhostCorners(ex->da,0,0,0,&ex->gnx,&ex->gnxgny,&ex->gnxgnygnz);CHKERRQ(ierr);
6888865f1eaSKarl Rupp 
689f4bdf6c4SBarry Smith   ex->gnxgny    *= ex->gnx;
690f4bdf6c4SBarry Smith   ex->gnxgnygnz *= ex->gnxgny;
6918865f1eaSKarl Rupp 
692f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(ex->da,&ex->xs,&ex->ys,&ex->zs,&ex->nx,&ex->ny,&ex->nz);CHKERRQ(ierr);
6938865f1eaSKarl Rupp 
694f4bdf6c4SBarry Smith   ex->nxny   = ex->nx*ex->ny;
695f4bdf6c4SBarry Smith   ex->nxnynz = ex->nz*ex->nxny;
696f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
697f4bdf6c4SBarry Smith }
698f4bdf6c4SBarry Smith 
699f4bdf6c4SBarry Smith PetscErrorCode MatMult_HYPRESStruct(Mat A,Vec x,Vec y)
700f4bdf6c4SBarry Smith {
701f4bdf6c4SBarry Smith   PetscErrorCode    ierr;
702b026d285SBarry Smith   const PetscScalar *xx;
703b026d285SBarry Smith   PetscScalar       *yy;
7042cf14000SStefano Zampini   HYPRE_Int         hlower[3],hupper[3];
7054ddd07fcSJed Brown   PetscInt          ilower[3],iupper[3];
706f4bdf6c4SBarry Smith   Mat_HYPRESStruct  *mx     = (Mat_HYPRESStruct*)(A->data);
7074ddd07fcSJed Brown   PetscInt          ordering= mx->dofs_order;
7084ddd07fcSJed Brown   PetscInt          nvars   = mx->nvars;
7094ddd07fcSJed Brown   PetscInt          part    = 0;
7104ddd07fcSJed Brown   PetscInt          size;
7114ddd07fcSJed Brown   PetscInt          i;
712f4bdf6c4SBarry Smith 
713f4bdf6c4SBarry Smith   PetscFunctionBegin;
714f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
7152cf14000SStefano Zampini 
7162cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
717f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
718f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
719f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
7202cf14000SStefano Zampini   hlower[0]  = (HYPRE_Int)ilower[0];
7212cf14000SStefano Zampini   hlower[1]  = (HYPRE_Int)ilower[1];
7222cf14000SStefano Zampini   hlower[2]  = (HYPRE_Int)ilower[2];
7232cf14000SStefano Zampini   hupper[0]  = (HYPRE_Int)iupper[0];
7242cf14000SStefano Zampini   hupper[1]  = (HYPRE_Int)iupper[1];
7252cf14000SStefano Zampini   hupper[2]  = (HYPRE_Int)iupper[2];
726f4bdf6c4SBarry Smith 
727f4bdf6c4SBarry Smith   size= 1;
7288865f1eaSKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i]-ilower[i]+1);
729f4bdf6c4SBarry Smith 
730f4bdf6c4SBarry Smith   /* copy x values over to hypre for variable ordering */
731f4bdf6c4SBarry Smith   if (ordering) {
732fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructVectorSetConstantValues,(mx->ss_b,0.0));
733b026d285SBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
734f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
73539accc25SStefano Zampini       PetscStackCallStandard(HYPRE_SStructVectorSetBoxValues,(mx->ss_b,part,hlower,hupper,i,(HYPRE_Complex*)(xx+(size*i))));
736f4bdf6c4SBarry Smith     }
737b026d285SBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
738fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructVectorAssemble,(mx->ss_b));
739fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructMatrixMatvec,(1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x));
740f4bdf6c4SBarry Smith 
741f4bdf6c4SBarry Smith     /* copy solution values back to PETSc */
742f4bdf6c4SBarry Smith     ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
743f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
74439accc25SStefano Zampini       PetscStackCallStandard(HYPRE_SStructVectorGetBoxValues,(mx->ss_x,part,hlower,hupper,i,(HYPRE_Complex*)(yy+(size*i))));
745f4bdf6c4SBarry Smith     }
746f4bdf6c4SBarry Smith     ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
747f4bdf6c4SBarry Smith   } else {      /* nodal ordering must be mapped to variable ordering for sys_pfmg */
748f4bdf6c4SBarry Smith     PetscScalar *z;
7494ddd07fcSJed Brown     PetscInt    j, k;
750f4bdf6c4SBarry Smith 
751785e854fSJed Brown     ierr = PetscMalloc1(nvars*size,&z);CHKERRQ(ierr);
752fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructVectorSetConstantValues,(mx->ss_b,0.0));
753b026d285SBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
754f4bdf6c4SBarry Smith 
755f4bdf6c4SBarry Smith     /* transform nodal to hypre's variable ordering for sys_pfmg */
756f4bdf6c4SBarry Smith     for (i= 0; i< size; i++) {
757f4bdf6c4SBarry Smith       k= i*nvars;
7588865f1eaSKarl Rupp       for (j= 0; j< nvars; j++) z[j*size+i]= xx[k+j];
759f4bdf6c4SBarry Smith     }
760f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
76139accc25SStefano Zampini       PetscStackCallStandard(HYPRE_SStructVectorSetBoxValues,(mx->ss_b,part,hlower,hupper,i,(HYPRE_Complex*)(z+(size*i))));
762f4bdf6c4SBarry Smith     }
763b026d285SBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
764fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructVectorAssemble,(mx->ss_b));
765fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructMatrixMatvec,(1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x));
766f4bdf6c4SBarry Smith 
767f4bdf6c4SBarry Smith     /* copy solution values back to PETSc */
768f4bdf6c4SBarry Smith     ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
769f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
77039accc25SStefano Zampini       PetscStackCallStandard(HYPRE_SStructVectorGetBoxValues,(mx->ss_x,part,hlower,hupper,i,(HYPRE_Complex*)(z+(size*i))));
771f4bdf6c4SBarry Smith     }
772f4bdf6c4SBarry Smith     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
773f4bdf6c4SBarry Smith     for (i= 0; i< size; i++) {
774f4bdf6c4SBarry Smith       k= i*nvars;
7758865f1eaSKarl Rupp       for (j= 0; j< nvars; j++) yy[k+j]= z[j*size+i];
776f4bdf6c4SBarry Smith     }
777f4bdf6c4SBarry Smith     ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
778f4bdf6c4SBarry Smith     ierr = PetscFree(z);CHKERRQ(ierr);
779f4bdf6c4SBarry Smith   }
780f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
781f4bdf6c4SBarry Smith }
782f4bdf6c4SBarry Smith 
783f4bdf6c4SBarry Smith PetscErrorCode MatAssemblyEnd_HYPRESStruct(Mat mat,MatAssemblyType mode)
784f4bdf6c4SBarry Smith {
785f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data;
786f4bdf6c4SBarry Smith 
787f4bdf6c4SBarry Smith   PetscFunctionBegin;
788fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructMatrixAssemble,(ex->ss_mat));
789f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
790f4bdf6c4SBarry Smith }
791f4bdf6c4SBarry Smith 
792f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPRESStruct(Mat mat)
793f4bdf6c4SBarry Smith {
794f4bdf6c4SBarry Smith   PetscFunctionBegin;
795f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
796f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
797f4bdf6c4SBarry Smith }
798f4bdf6c4SBarry Smith 
799f4bdf6c4SBarry Smith PetscErrorCode MatDestroy_HYPRESStruct(Mat mat)
800f4bdf6c4SBarry Smith {
801f4bdf6c4SBarry Smith   Mat_HYPRESStruct       *ex = (Mat_HYPRESStruct*) mat->data;
802f4bdf6c4SBarry Smith   PetscErrorCode         ierr;
803d94fc0b6SBarry Smith   ISLocalToGlobalMapping ltog;
804f4bdf6c4SBarry Smith 
805f4bdf6c4SBarry Smith   PetscFunctionBegin;
806d94fc0b6SBarry Smith   ierr = DMGetLocalToGlobalMapping(ex->da,&ltog);CHKERRQ(ierr);
807d94fc0b6SBarry Smith   ierr = ISLocalToGlobalMappingRestoreIndices(ltog, (const PetscInt **) &ex->gindices);CHKERRQ(ierr);
808fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGraphDestroy,(ex->ss_graph));
809fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructMatrixDestroy,(ex->ss_mat));
810fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorDestroy,(ex->ss_x));
811fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorDestroy,(ex->ss_b));
81259cb773eSBarry Smith   ierr = PetscObjectDereference((PetscObject)ex->da);CHKERRQ(ierr);
813ffc4695bSBarry Smith   ierr = MPI_Comm_free(&(ex->hcomm));CHKERRMPI(ierr);
81459cb773eSBarry Smith   ierr = PetscFree(ex);CHKERRQ(ierr);
815f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
816f4bdf6c4SBarry Smith }
817f4bdf6c4SBarry Smith 
8188cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_HYPRESStruct(Mat B)
819f4bdf6c4SBarry Smith {
820f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex;
821f4bdf6c4SBarry Smith   PetscErrorCode   ierr;
822f4bdf6c4SBarry Smith 
823f4bdf6c4SBarry Smith   PetscFunctionBegin;
824b00a9115SJed Brown   ierr         = PetscNewLog(B,&ex);CHKERRQ(ierr);
825f4bdf6c4SBarry Smith   B->data      = (void*)ex;
826f4bdf6c4SBarry Smith   B->rmap->bs  = 1;
827f4bdf6c4SBarry Smith   B->assembled = PETSC_FALSE;
828f4bdf6c4SBarry Smith 
829f4bdf6c4SBarry Smith   B->insertmode = NOT_SET_VALUES;
830f4bdf6c4SBarry Smith 
831f4bdf6c4SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_HYPRESStruct;
832f4bdf6c4SBarry Smith   B->ops->mult        = MatMult_HYPRESStruct;
833f4bdf6c4SBarry Smith   B->ops->zeroentries = MatZeroEntries_HYPRESStruct;
834f4bdf6c4SBarry Smith   B->ops->destroy     = MatDestroy_HYPRESStruct;
83559cb773eSBarry Smith   B->ops->setup       = MatSetUp_HYPRESStruct;
836f4bdf6c4SBarry Smith 
837f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
838f4bdf6c4SBarry Smith 
839ffc4695bSBarry Smith   ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)B),&(ex->hcomm));CHKERRMPI(ierr);
840f4bdf6c4SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATHYPRESSTRUCT);CHKERRQ(ierr);
841f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
842f4bdf6c4SBarry Smith }
843f4bdf6c4SBarry Smith 
844