xref: /petsc/src/dm/impls/da/hypre/mhyp.c (revision d94fc0b6cf22a878497ee22bbf61333f8d21cfbe)
1f4bdf6c4SBarry Smith 
2f4bdf6c4SBarry Smith /*
3f4bdf6c4SBarry Smith     Creates hypre ijmatrix from PETSc matrix
4f4bdf6c4SBarry Smith */
5c6db04a5SJed Brown #include <petscsys.h>
6af0996ceSBarry Smith #include <petsc/private/matimpl.h>
7c6db04a5SJed Brown #include <petscdmda.h>                /*I "petscdmda.h" I*/
8c6db04a5SJed Brown #include <../src/dm/impls/da/hypre/mhyp.h>
9f4bdf6c4SBarry Smith 
10f4bdf6c4SBarry Smith /* -----------------------------------------------------------------------------------------------------------------*/
11f4bdf6c4SBarry Smith 
12f4bdf6c4SBarry Smith /*MC
13f4bdf6c4SBarry Smith    MATHYPRESTRUCT - MATHYPRESTRUCT = "hyprestruct" - A matrix type to be used for parallel sparse matrices
14f4bdf6c4SBarry Smith           based on the hypre HYPRE_StructMatrix.
15f4bdf6c4SBarry Smith 
16f4bdf6c4SBarry Smith    Level: intermediate
17f4bdf6c4SBarry Smith 
18f4bdf6c4SBarry Smith    Notes: Unlike the more general support for blocks in hypre this allows only one block per process and requires the block
19f4bdf6c4SBarry Smith           be defined by a DMDA.
20f4bdf6c4SBarry Smith 
2159cb773eSBarry Smith           The matrix needs a DMDA associated with it by either a call to MatSetDM() or if the matrix is obtained from DMCreateMatrix()
22f4bdf6c4SBarry Smith 
2359cb773eSBarry Smith .seealso: MatCreate(), PCPFMG, MatSetDM(), DMCreateMatrix()
24f4bdf6c4SBarry Smith M*/
25f4bdf6c4SBarry Smith 
26f4bdf6c4SBarry Smith 
27f4bdf6c4SBarry Smith PetscErrorCode  MatSetValuesLocal_HYPREStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
28f4bdf6c4SBarry Smith {
29f4bdf6c4SBarry Smith   PetscErrorCode    ierr;
30f4bdf6c4SBarry Smith   PetscInt          i,j,stencil,index[3],row,entries[7];
31f4bdf6c4SBarry Smith   const PetscScalar *values = y;
32f4bdf6c4SBarry Smith   Mat_HYPREStruct   *ex     = (Mat_HYPREStruct*) mat->data;
33f4bdf6c4SBarry Smith 
34f4bdf6c4SBarry Smith   PetscFunctionBegin;
3559cb773eSBarry Smith   if (PetscUnlikely(ncol > 7)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"ncol %D > 7 too large",ncol);
36f4bdf6c4SBarry Smith   for (i=0; i<nrow; i++) {
37f4bdf6c4SBarry Smith     for (j=0; j<ncol; j++) {
38f4bdf6c4SBarry Smith       stencil = icol[j] - irow[i];
39f4bdf6c4SBarry Smith       if (!stencil) {
40f4bdf6c4SBarry Smith         entries[j] = 3;
41f4bdf6c4SBarry Smith       } else if (stencil == -1) {
42f4bdf6c4SBarry Smith         entries[j] = 2;
43f4bdf6c4SBarry Smith       } else if (stencil == 1) {
44f4bdf6c4SBarry Smith         entries[j] = 4;
45f4bdf6c4SBarry Smith       } else if (stencil == -ex->gnx) {
46f4bdf6c4SBarry Smith         entries[j] = 1;
47f4bdf6c4SBarry Smith       } else if (stencil == ex->gnx) {
48f4bdf6c4SBarry Smith         entries[j] = 5;
49f4bdf6c4SBarry Smith       } else if (stencil == -ex->gnxgny) {
50f4bdf6c4SBarry Smith         entries[j] = 0;
51f4bdf6c4SBarry Smith       } else if (stencil == ex->gnxgny) {
52f4bdf6c4SBarry Smith         entries[j] = 6;
53f4bdf6c4SBarry Smith       } else SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row %D local column %D have bad stencil %D",irow[i],icol[j],stencil);
54f4bdf6c4SBarry Smith     }
55f4bdf6c4SBarry Smith     row      = ex->gindices[irow[i]] - ex->rstart;
56f4bdf6c4SBarry Smith     index[0] = ex->xs + (row % ex->nx);
57f4bdf6c4SBarry Smith     index[1] = ex->ys + ((row/ex->nx) % ex->ny);
58f4bdf6c4SBarry Smith     index[2] = ex->zs + (row/(ex->nxny));
59f4bdf6c4SBarry Smith     if (addv == ADD_VALUES) {
608b1f7689SBarry Smith       PetscStackCallStandard(HYPRE_StructMatrixAddToValues,(ex->hmat,(HYPRE_Int *)index,ncol,(HYPRE_Int *)entries,(PetscScalar*)values));
61f4bdf6c4SBarry Smith     } else {
628b1f7689SBarry Smith       PetscStackCallStandard(HYPRE_StructMatrixSetValues,(ex->hmat,(HYPRE_Int *)index,ncol,(HYPRE_Int *)entries,(PetscScalar*)values));
63f4bdf6c4SBarry Smith     }
64f4bdf6c4SBarry Smith     values += ncol;
65f4bdf6c4SBarry Smith   }
66f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
67f4bdf6c4SBarry Smith }
68f4bdf6c4SBarry Smith 
69f4bdf6c4SBarry Smith PetscErrorCode  MatZeroRowsLocal_HYPREStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscScalar d,Vec x,Vec b)
70f4bdf6c4SBarry Smith {
71f4bdf6c4SBarry Smith   PetscErrorCode  ierr;
72f4bdf6c4SBarry Smith   PetscInt        i,index[3],row,entries[7] = {0,1,2,3,4,5,6};
73f4bdf6c4SBarry Smith   PetscScalar     values[7];
74f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
75f4bdf6c4SBarry Smith 
76f4bdf6c4SBarry Smith   PetscFunctionBegin;
77ce94432eSBarry Smith   if (x && b) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"No support");
78f4bdf6c4SBarry Smith   ierr      = PetscMemzero(values,7*sizeof(PetscScalar));CHKERRQ(ierr);
79f4bdf6c4SBarry Smith   values[3] = d;
80f4bdf6c4SBarry Smith   for (i=0; i<nrow; i++) {
81f4bdf6c4SBarry Smith     row      = ex->gindices[irow[i]] - ex->rstart;
82f4bdf6c4SBarry Smith     index[0] = ex->xs + (row % ex->nx);
83f4bdf6c4SBarry Smith     index[1] = ex->ys + ((row/ex->nx) % ex->ny);
84f4bdf6c4SBarry Smith     index[2] = ex->zs + (row/(ex->nxny));
858b1f7689SBarry Smith     PetscStackCallStandard(HYPRE_StructMatrixSetValues,(ex->hmat,(HYPRE_Int *)index,7,(HYPRE_Int *)entries,values));
86f4bdf6c4SBarry Smith   }
87fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixAssemble,(ex->hmat));
88f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
89f4bdf6c4SBarry Smith }
90f4bdf6c4SBarry Smith 
91f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPREStruct_3d(Mat mat)
92f4bdf6c4SBarry Smith {
93f4bdf6c4SBarry Smith   PetscErrorCode  ierr;
94f4bdf6c4SBarry Smith   PetscInt        indices[7] = {0,1,2,3,4,5,6};
95f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex        = (Mat_HYPREStruct*) mat->data;
96f4bdf6c4SBarry Smith 
97f4bdf6c4SBarry Smith   PetscFunctionBegin;
98f4bdf6c4SBarry Smith   /* hypre has no public interface to do this */
998b1f7689SBarry Smith   PetscStackCallStandard(hypre_StructMatrixClearBoxValues,(ex->hmat,&ex->hbox,7,(HYPRE_Int *)indices,0,1));
100fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixAssemble,(ex->hmat));
101f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
102f4bdf6c4SBarry Smith }
103f4bdf6c4SBarry Smith 
10459cb773eSBarry Smith static PetscErrorCode  MatSetUp_HYPREStruct(Mat mat)
105f4bdf6c4SBarry Smith {
106f4bdf6c4SBarry Smith   PetscErrorCode         ierr;
107f4bdf6c4SBarry Smith   Mat_HYPREStruct        *ex = (Mat_HYPREStruct*) mat->data;
10859cb773eSBarry Smith   PetscInt               dim,dof,sw[6],nx,ny,nz,ilower[3],iupper[3],ssize,i;
109bff4a2f0SMatthew G. Knepley   DMBoundaryType         px,py,pz;
110f4bdf6c4SBarry Smith   DMDAStencilType        st;
111565245c5SBarry Smith   ISLocalToGlobalMapping ltog;
11259cb773eSBarry Smith   DM                     da;
113f4bdf6c4SBarry Smith 
114f4bdf6c4SBarry Smith   PetscFunctionBegin;
11559cb773eSBarry Smith   ierr   = MatGetDM(mat,(DM*)&da);CHKERRQ(ierr);
116f4bdf6c4SBarry Smith   ex->da = da;
117f4bdf6c4SBarry Smith   ierr   = PetscObjectReference((PetscObject)da);CHKERRQ(ierr);
118f4bdf6c4SBarry Smith 
1197ab44359SJed Brown   ierr       = DMDAGetInfo(ex->da,&dim,0,0,0,0,0,0,&dof,&sw[0],&px,&py,&pz,&st);CHKERRQ(ierr);
120f4bdf6c4SBarry Smith   ierr       = DMDAGetCorners(ex->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
121f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
122f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
123f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
124f4bdf6c4SBarry Smith 
125f4bdf6c4SBarry Smith   /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
126f4bdf6c4SBarry Smith   ex->hbox.imin[0] = ilower[0];
127f4bdf6c4SBarry Smith   ex->hbox.imin[1] = ilower[1];
128f4bdf6c4SBarry Smith   ex->hbox.imin[2] = ilower[2];
129f4bdf6c4SBarry Smith   ex->hbox.imax[0] = iupper[0];
130f4bdf6c4SBarry Smith   ex->hbox.imax[1] = iupper[1];
131f4bdf6c4SBarry Smith   ex->hbox.imax[2] = iupper[2];
132f4bdf6c4SBarry Smith 
133f4bdf6c4SBarry Smith   /* create the hypre grid object and set its information */
134ce94432eSBarry Smith   if (dof > 1) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Currently only support for scalar problems");
135ce94432eSBarry Smith   if (px || py || pz) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add periodic support by calling HYPRE_StructGridSetPeriodic()");
136fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructGridCreate,(ex->hcomm,dim,&ex->hgrid));
1378b1f7689SBarry Smith   PetscStackCallStandard(HYPRE_StructGridSetExtents,(ex->hgrid,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper));
138fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructGridAssemble,(ex->hgrid));
139f4bdf6c4SBarry Smith 
14059cb773eSBarry Smith   sw[5] = sw[4] = sw[3] = sw[2] = sw[1] = sw[0];
1418b1f7689SBarry Smith   PetscStackCallStandard(HYPRE_StructGridSetNumGhost,(ex->hgrid,(HYPRE_Int *)sw));
142f4bdf6c4SBarry Smith 
143f4bdf6c4SBarry Smith   /* create the hypre stencil object and set its information */
144ce94432eSBarry Smith   if (sw[0] > 1) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for wider stencils");
145ce94432eSBarry Smith   if (st == DMDA_STENCIL_BOX) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for box stencils");
146f4bdf6c4SBarry Smith   if (dim == 1) {
1474ddd07fcSJed Brown     PetscInt offsets[3][1] = {{-1},{0},{1}};
148f4bdf6c4SBarry Smith     ssize = 3;
149fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_StructStencilCreate,(dim,ssize,&ex->hstencil));
150f4bdf6c4SBarry Smith     for (i=0; i<ssize; i++) {
1518b1f7689SBarry Smith       PetscStackCallStandard(HYPRE_StructStencilSetElement,(ex->hstencil,i,(HYPRE_Int *)offsets[i]));
152f4bdf6c4SBarry Smith     }
153f4bdf6c4SBarry Smith   } else if (dim == 2) {
1544ddd07fcSJed Brown     PetscInt offsets[5][2] = {{0,-1},{-1,0},{0,0},{1,0},{0,1}};
155f4bdf6c4SBarry Smith     ssize = 5;
156fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_StructStencilCreate,(dim,ssize,&ex->hstencil));
157f4bdf6c4SBarry Smith     for (i=0; i<ssize; i++) {
1588b1f7689SBarry Smith       PetscStackCallStandard(HYPRE_StructStencilSetElement,(ex->hstencil,i,(HYPRE_Int *)offsets[i]));
159f4bdf6c4SBarry Smith     }
160f4bdf6c4SBarry Smith   } else if (dim == 3) {
1614ddd07fcSJed Brown     PetscInt offsets[7][3] = {{0,0,-1},{0,-1,0},{-1,0,0},{0,0,0},{1,0,0},{0,1,0},{0,0,1}};
162f4bdf6c4SBarry Smith     ssize = 7;
163fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_StructStencilCreate,(dim,ssize,&ex->hstencil));
164f4bdf6c4SBarry Smith     for (i=0; i<ssize; i++) {
1658b1f7689SBarry Smith       PetscStackCallStandard(HYPRE_StructStencilSetElement,(ex->hstencil,i,(HYPRE_Int *)offsets[i]));
166f4bdf6c4SBarry Smith     }
167f4bdf6c4SBarry Smith   }
168f4bdf6c4SBarry Smith 
169f4bdf6c4SBarry Smith   /* create the HYPRE vector for rhs and solution */
170fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorCreate,(ex->hcomm,ex->hgrid,&ex->hb));
171fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorCreate,(ex->hcomm,ex->hgrid,&ex->hx));
172fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorInitialize,(ex->hb));
173fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorInitialize,(ex->hx));
174fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorAssemble,(ex->hb));
175fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorAssemble,(ex->hx));
176f4bdf6c4SBarry Smith 
177f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
178fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixCreate,(ex->hcomm,ex->hgrid,ex->hstencil,&ex->hmat));
179fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructGridDestroy,(ex->hgrid));
180fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructStencilDestroy,(ex->hstencil));
181f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
182fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_StructMatrixInitialize,(ex->hmat));
183f4bdf6c4SBarry Smith     ex->needsinitialization = PETSC_FALSE;
184f4bdf6c4SBarry Smith   }
185f4bdf6c4SBarry Smith 
186f4bdf6c4SBarry Smith   /* set the global and local sizes of the matrix */
187f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(da,0,0,0,&nx,&ny,&nz);CHKERRQ(ierr);
188f4bdf6c4SBarry Smith   ierr = MatSetSizes(mat,dof*nx*ny*nz,dof*nx*ny*nz,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
189f4bdf6c4SBarry Smith   ierr = PetscLayoutSetBlockSize(mat->rmap,1);CHKERRQ(ierr);
190f4bdf6c4SBarry Smith   ierr = PetscLayoutSetBlockSize(mat->cmap,1);CHKERRQ(ierr);
191f4bdf6c4SBarry Smith   ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr);
192f4bdf6c4SBarry Smith   ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr);
19359cb773eSBarry Smith   mat->preallocated = PETSC_TRUE;
194f4bdf6c4SBarry Smith 
195f4bdf6c4SBarry Smith   if (dim == 3) {
196f4bdf6c4SBarry Smith     mat->ops->setvalueslocal = MatSetValuesLocal_HYPREStruct_3d;
197f4bdf6c4SBarry Smith     mat->ops->zerorowslocal  = MatZeroRowsLocal_HYPREStruct_3d;
198f4bdf6c4SBarry Smith     mat->ops->zeroentries    = MatZeroEntries_HYPREStruct_3d;
1998865f1eaSKarl Rupp 
20059cb773eSBarry Smith     /*        ierr = MatZeroEntries_HYPREStruct_3d(mat);CHKERRQ(ierr); */
201ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Only support for 3d DMDA currently");
202f4bdf6c4SBarry Smith 
203f4bdf6c4SBarry Smith   /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
2040298fd71SBarry Smith   ierr        = MatGetOwnershipRange(mat,&ex->rstart,NULL);CHKERRQ(ierr);
205565245c5SBarry Smith   ierr        = DMGetLocalToGlobalMapping(ex->da,&ltog);CHKERRQ(ierr);
206565245c5SBarry Smith   ierr        = ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **) &ex->gindices);CHKERRQ(ierr);
207f4bdf6c4SBarry Smith   ierr        = DMDAGetGhostCorners(ex->da,0,0,0,&ex->gnx,&ex->gnxgny,0);CHKERRQ(ierr);
208f4bdf6c4SBarry Smith   ex->gnxgny *= ex->gnx;
209f4bdf6c4SBarry Smith   ierr        = DMDAGetCorners(ex->da,&ex->xs,&ex->ys,&ex->zs,&ex->nx,&ex->ny,0);CHKERRQ(ierr);
210f4bdf6c4SBarry Smith   ex->nxny    = ex->nx*ex->ny;
211f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
212f4bdf6c4SBarry Smith }
213f4bdf6c4SBarry Smith 
214f4bdf6c4SBarry Smith PetscErrorCode MatMult_HYPREStruct(Mat A,Vec x,Vec y)
215f4bdf6c4SBarry Smith {
216f4bdf6c4SBarry Smith   PetscErrorCode    ierr;
217b026d285SBarry Smith   const PetscScalar *xx;
218b026d285SBarry Smith   PetscScalar       *yy;
2194ddd07fcSJed Brown   PetscInt          ilower[3],iupper[3];
220f4bdf6c4SBarry Smith   Mat_HYPREStruct   *mx = (Mat_HYPREStruct*)(A->data);
221f4bdf6c4SBarry Smith 
222f4bdf6c4SBarry Smith   PetscFunctionBegin;
223f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
2248865f1eaSKarl Rupp 
225f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
226f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
227f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
228f4bdf6c4SBarry Smith 
229f4bdf6c4SBarry Smith   /* copy x values over to hypre */
230fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorSetConstantValues,(mx->hb,0.0));
231b026d285SBarry Smith   ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
232b026d285SBarry Smith   PetscStackCallStandard(HYPRE_StructVectorSetBoxValues,(mx->hb,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,(PetscScalar*)xx));
233b026d285SBarry Smith   ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
234fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorAssemble,(mx->hb));
235fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixMatvec,(1.0,mx->hmat,mx->hb,0.0,mx->hx));
236f4bdf6c4SBarry Smith 
237f4bdf6c4SBarry Smith   /* copy solution values back to PETSc */
238f4bdf6c4SBarry Smith   ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
2398b1f7689SBarry Smith   PetscStackCallStandard(HYPRE_StructVectorGetBoxValues,(mx->hx,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,yy));
240f4bdf6c4SBarry Smith   ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
241f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
242f4bdf6c4SBarry Smith }
243f4bdf6c4SBarry Smith 
244f4bdf6c4SBarry Smith PetscErrorCode MatAssemblyEnd_HYPREStruct(Mat mat,MatAssemblyType mode)
245f4bdf6c4SBarry Smith {
246f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
247f4bdf6c4SBarry Smith   PetscErrorCode  ierr;
248f4bdf6c4SBarry Smith 
249f4bdf6c4SBarry Smith   PetscFunctionBegin;
250fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixAssemble,(ex->hmat));
251fd3f9acdSBarry Smith   /* PetscStackCallStandard(HYPRE_StructMatrixPrint,("dummy",ex->hmat,0)); */
252f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
253f4bdf6c4SBarry Smith }
254f4bdf6c4SBarry Smith 
255f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPREStruct(Mat mat)
256f4bdf6c4SBarry Smith {
257f4bdf6c4SBarry Smith   PetscFunctionBegin;
258f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
259f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
260f4bdf6c4SBarry Smith }
261f4bdf6c4SBarry Smith 
262f4bdf6c4SBarry Smith PetscErrorCode MatDestroy_HYPREStruct(Mat mat)
263f4bdf6c4SBarry Smith {
264f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
265f4bdf6c4SBarry Smith   PetscErrorCode  ierr;
266f4bdf6c4SBarry Smith 
267f4bdf6c4SBarry Smith   PetscFunctionBegin;
268fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixDestroy,(ex->hmat));
269fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorDestroy,(ex->hx));
270fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorDestroy,(ex->hb));
27159cb773eSBarry Smith   ierr = PetscObjectDereference((PetscObject)ex->da);CHKERRQ(ierr);
27259cb773eSBarry Smith   ierr = MPI_Comm_free(&(ex->hcomm));CHKERRQ(ierr);
27359cb773eSBarry Smith   ierr = PetscFree(ex);CHKERRQ(ierr);
274f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
275f4bdf6c4SBarry Smith }
276f4bdf6c4SBarry Smith 
2778cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_HYPREStruct(Mat B)
278f4bdf6c4SBarry Smith {
279f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex;
280f4bdf6c4SBarry Smith   PetscErrorCode  ierr;
281f4bdf6c4SBarry Smith 
282f4bdf6c4SBarry Smith   PetscFunctionBegin;
283b00a9115SJed Brown   ierr         = PetscNewLog(B,&ex);CHKERRQ(ierr);
284f4bdf6c4SBarry Smith   B->data      = (void*)ex;
285f4bdf6c4SBarry Smith   B->rmap->bs  = 1;
286f4bdf6c4SBarry Smith   B->assembled = PETSC_FALSE;
287f4bdf6c4SBarry Smith 
288f4bdf6c4SBarry Smith   B->insertmode = NOT_SET_VALUES;
289f4bdf6c4SBarry Smith 
290f4bdf6c4SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_HYPREStruct;
291f4bdf6c4SBarry Smith   B->ops->mult        = MatMult_HYPREStruct;
292f4bdf6c4SBarry Smith   B->ops->zeroentries = MatZeroEntries_HYPREStruct;
293f4bdf6c4SBarry Smith   B->ops->destroy     = MatDestroy_HYPREStruct;
29459cb773eSBarry Smith   B->ops->setup       = MatSetUp_HYPREStruct;
295f4bdf6c4SBarry Smith 
296f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
297f4bdf6c4SBarry Smith 
298ce94432eSBarry Smith   ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)B),&(ex->hcomm));CHKERRQ(ierr);
299f4bdf6c4SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATHYPRESTRUCT);CHKERRQ(ierr);
300f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
301f4bdf6c4SBarry Smith }
302f4bdf6c4SBarry Smith 
303f4bdf6c4SBarry Smith /*MC
304f4bdf6c4SBarry Smith    MATHYPRESSTRUCT - MATHYPRESSTRUCT = "hypresstruct" - A matrix type to be used for parallel sparse matrices
305f4bdf6c4SBarry Smith           based on the hypre HYPRE_SStructMatrix.
306f4bdf6c4SBarry Smith 
307f4bdf6c4SBarry Smith 
308f4bdf6c4SBarry Smith    Level: intermediate
309f4bdf6c4SBarry Smith 
310f4bdf6c4SBarry Smith    Notes: Unlike hypre's general semi-struct object consisting of a collection of structured-grid objects and unstructured
311b026d285SBarry Smith           grid objects, we restrict the semi-struct objects to consist of only structured-grid components.
312f4bdf6c4SBarry Smith 
313f4bdf6c4SBarry 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
314f4bdf6c4SBarry Smith           be defined by a DMDA.
315f4bdf6c4SBarry Smith 
31659cb773eSBarry Smith           The matrix needs a DMDA associated with it by either a call to MatSetDM() or if the matrix is obtained from DMCreateMatrix()
317f4bdf6c4SBarry Smith 
318f4bdf6c4SBarry Smith M*/
319f4bdf6c4SBarry Smith 
320f4bdf6c4SBarry Smith PetscErrorCode  MatSetValuesLocal_HYPRESStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
321f4bdf6c4SBarry Smith {
322f4bdf6c4SBarry Smith   PetscErrorCode    ierr;
323f4bdf6c4SBarry Smith   PetscInt          i,j,stencil,index[3];
324f4bdf6c4SBarry Smith   const PetscScalar *values = y;
325f4bdf6c4SBarry Smith   Mat_HYPRESStruct  *ex     = (Mat_HYPRESStruct*) mat->data;
326f4bdf6c4SBarry Smith 
3274ddd07fcSJed Brown   PetscInt          part = 0;          /* Petsc sstruct interface only allows 1 part */
3284ddd07fcSJed Brown   PetscInt          ordering;
3294ddd07fcSJed Brown   PetscInt          grid_rank, to_grid_rank;
3304ddd07fcSJed Brown   PetscInt          var_type, to_var_type;
3314ddd07fcSJed Brown   PetscInt          to_var_entry = 0;
3324ddd07fcSJed Brown   PetscInt          nvars= ex->nvars;
333f4bdf6c4SBarry Smith   PetscInt          row,*entries;
334f4bdf6c4SBarry Smith 
335f4bdf6c4SBarry Smith   PetscFunctionBegin;
336785e854fSJed Brown   ierr     = PetscMalloc1(7*nvars,&entries);CHKERRQ(ierr);
337f4bdf6c4SBarry Smith   ordering = ex->dofs_order;  /* ordering= 0   nodal ordering
338f4bdf6c4SBarry Smith                                            1   variable ordering */
33961710fbeSStefano Zampini   /* stencil entries are ordered by variables: var0_stencil0, var0_stencil1, ..., var0_stencil6, var1_stencil0, var1_stencil1, ...  */
340f4bdf6c4SBarry Smith   if (!ordering) {
341f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
342f4bdf6c4SBarry Smith       grid_rank= irow[i]/nvars;
343f4bdf6c4SBarry Smith       var_type = (irow[i] % nvars);
344f4bdf6c4SBarry Smith 
345f4bdf6c4SBarry Smith       for (j=0; j<ncol; j++) {
346f4bdf6c4SBarry Smith         to_grid_rank= icol[j]/nvars;
347f4bdf6c4SBarry Smith         to_var_type = (icol[j] % nvars);
348f4bdf6c4SBarry Smith 
349f4bdf6c4SBarry Smith         to_var_entry= to_var_entry*7;
350f4bdf6c4SBarry Smith         entries[j]  = to_var_entry;
351f4bdf6c4SBarry Smith 
352f4bdf6c4SBarry Smith         stencil = to_grid_rank-grid_rank;
353f4bdf6c4SBarry Smith         if (!stencil) {
354f4bdf6c4SBarry Smith           entries[j] += 3;
355f4bdf6c4SBarry Smith         } else if (stencil == -1) {
356f4bdf6c4SBarry Smith           entries[j] += 2;
357f4bdf6c4SBarry Smith         } else if (stencil == 1) {
358f4bdf6c4SBarry Smith           entries[j] += 4;
359f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnx) {
360f4bdf6c4SBarry Smith           entries[j] += 1;
361f4bdf6c4SBarry Smith         } else if (stencil == ex->gnx) {
362f4bdf6c4SBarry Smith           entries[j] += 5;
363f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnxgny) {
364f4bdf6c4SBarry Smith           entries[j] += 0;
365f4bdf6c4SBarry Smith         } else if (stencil == ex->gnxgny) {
366f4bdf6c4SBarry Smith           entries[j] += 6;
367f4bdf6c4SBarry Smith         } else SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row %D local column %D have bad stencil %D",irow[i],icol[j],stencil);
368f4bdf6c4SBarry Smith       }
369f4bdf6c4SBarry Smith 
370f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
371f4bdf6c4SBarry Smith       index[0] = ex->xs + (row % ex->nx);
372f4bdf6c4SBarry Smith       index[1] = ex->ys + ((row/ex->nx) % ex->ny);
373f4bdf6c4SBarry Smith       index[2] = ex->zs + (row/(ex->nxny));
374f4bdf6c4SBarry Smith 
375f4bdf6c4SBarry Smith       if (addv == ADD_VALUES) {
3768b1f7689SBarry Smith         PetscStackCallStandard(HYPRE_SStructMatrixAddToValues,(ex->ss_mat,part,(HYPRE_Int *)index,var_type,ncol,(HYPRE_Int *)entries,(PetscScalar*)values));
377f4bdf6c4SBarry Smith       } else {
3788b1f7689SBarry Smith         PetscStackCallStandard(HYPRE_SStructMatrixSetValues,(ex->ss_mat,part,(HYPRE_Int *)index,var_type,ncol,(HYPRE_Int *)entries,(PetscScalar*)values));
379f4bdf6c4SBarry Smith       }
380f4bdf6c4SBarry Smith       values += ncol;
381f4bdf6c4SBarry Smith     }
382f4bdf6c4SBarry Smith   } else {
383f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
384f4bdf6c4SBarry Smith       var_type = irow[i]/(ex->gnxgnygnz);
385f4bdf6c4SBarry Smith       grid_rank= irow[i] - var_type*(ex->gnxgnygnz);
386f4bdf6c4SBarry Smith 
387f4bdf6c4SBarry Smith       for (j=0; j<ncol; j++) {
388f4bdf6c4SBarry Smith         to_var_type = icol[j]/(ex->gnxgnygnz);
389f4bdf6c4SBarry Smith         to_grid_rank= icol[j] - to_var_type*(ex->gnxgnygnz);
390f4bdf6c4SBarry Smith 
391f4bdf6c4SBarry Smith         to_var_entry= to_var_entry*7;
392f4bdf6c4SBarry Smith         entries[j]  = to_var_entry;
393f4bdf6c4SBarry Smith 
394f4bdf6c4SBarry Smith         stencil = to_grid_rank-grid_rank;
395f4bdf6c4SBarry Smith         if (!stencil) {
396f4bdf6c4SBarry Smith           entries[j] += 3;
397f4bdf6c4SBarry Smith         } else if (stencil == -1) {
398f4bdf6c4SBarry Smith           entries[j] += 2;
399f4bdf6c4SBarry Smith         } else if (stencil == 1) {
400f4bdf6c4SBarry Smith           entries[j] += 4;
401f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnx) {
402f4bdf6c4SBarry Smith           entries[j] += 1;
403f4bdf6c4SBarry Smith         } else if (stencil == ex->gnx) {
404f4bdf6c4SBarry Smith           entries[j] += 5;
405f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnxgny) {
406f4bdf6c4SBarry Smith           entries[j] += 0;
407f4bdf6c4SBarry Smith         } else if (stencil == ex->gnxgny) {
408f4bdf6c4SBarry Smith           entries[j] += 6;
409f4bdf6c4SBarry Smith         } else SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row %D local column %D have bad stencil %D",irow[i],icol[j],stencil);
410f4bdf6c4SBarry Smith       }
411f4bdf6c4SBarry Smith 
412f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
413f4bdf6c4SBarry Smith       index[0] = ex->xs + (row % ex->nx);
414f4bdf6c4SBarry Smith       index[1] = ex->ys + ((row/ex->nx) % ex->ny);
415f4bdf6c4SBarry Smith       index[2] = ex->zs + (row/(ex->nxny));
416f4bdf6c4SBarry Smith 
417f4bdf6c4SBarry Smith       if (addv == ADD_VALUES) {
4188b1f7689SBarry Smith         PetscStackCallStandard(HYPRE_SStructMatrixAddToValues,(ex->ss_mat,part,(HYPRE_Int *)index,var_type,ncol,(HYPRE_Int *)entries,(PetscScalar*)values));
419f4bdf6c4SBarry Smith       } else {
4208b1f7689SBarry Smith         PetscStackCallStandard(HYPRE_SStructMatrixSetValues,(ex->ss_mat,part,(HYPRE_Int *)index,var_type,ncol,(HYPRE_Int *)entries,(PetscScalar*)values));
421f4bdf6c4SBarry Smith       }
422f4bdf6c4SBarry Smith       values += ncol;
423f4bdf6c4SBarry Smith     }
424f4bdf6c4SBarry Smith   }
425f4bdf6c4SBarry Smith   ierr = PetscFree(entries);CHKERRQ(ierr);
426f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
427f4bdf6c4SBarry Smith }
428f4bdf6c4SBarry Smith 
429f4bdf6c4SBarry Smith PetscErrorCode  MatZeroRowsLocal_HYPRESStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscScalar d,Vec x,Vec b)
430f4bdf6c4SBarry Smith {
431f4bdf6c4SBarry Smith   PetscErrorCode   ierr;
432f4bdf6c4SBarry Smith   PetscInt         i,index[3];
433f4bdf6c4SBarry Smith   PetscScalar      **values;
434f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data;
435f4bdf6c4SBarry Smith 
4364ddd07fcSJed Brown   PetscInt         part     = 0;      /* Petsc sstruct interface only allows 1 part */
4374ddd07fcSJed Brown   PetscInt         ordering = ex->dofs_order;
4384ddd07fcSJed Brown   PetscInt         grid_rank;
4394ddd07fcSJed Brown   PetscInt         var_type;
4404ddd07fcSJed Brown   PetscInt         nvars= ex->nvars;
441f4bdf6c4SBarry Smith   PetscInt         row,*entries;
442f4bdf6c4SBarry Smith 
443f4bdf6c4SBarry Smith   PetscFunctionBegin;
444ce94432eSBarry Smith   if (x && b) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"No support");
445785e854fSJed Brown   ierr = PetscMalloc1(7*nvars,&entries);CHKERRQ(ierr);
446f4bdf6c4SBarry Smith 
447785e854fSJed Brown   ierr = PetscMalloc1(nvars,&values);CHKERRQ(ierr);
448785e854fSJed Brown   ierr = PetscMalloc1(7*nvars*nvars,&values[0]);CHKERRQ(ierr);
449f4bdf6c4SBarry Smith   for (i=1; i<nvars; i++) {
450f4bdf6c4SBarry Smith     values[i] = values[i-1] + nvars*7;
451f4bdf6c4SBarry Smith   }
452f4bdf6c4SBarry Smith 
453f4bdf6c4SBarry Smith   for (i=0; i< nvars; i++) {
454f4bdf6c4SBarry Smith     ierr           = PetscMemzero(values[i],nvars*7*sizeof(PetscScalar));CHKERRQ(ierr);
455f4bdf6c4SBarry Smith     *(values[i]+3) = d;
456f4bdf6c4SBarry Smith   }
457f4bdf6c4SBarry Smith 
4588865f1eaSKarl Rupp   for (i= 0; i< nvars*7; i++) entries[i] = i;
459f4bdf6c4SBarry Smith 
460f4bdf6c4SBarry Smith   if (!ordering) {
461f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
462f4bdf6c4SBarry Smith       grid_rank = irow[i] / nvars;
463f4bdf6c4SBarry Smith       var_type  =(irow[i] % nvars);
464f4bdf6c4SBarry Smith 
465f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
466f4bdf6c4SBarry Smith       index[0] = ex->xs + (row % ex->nx);
467f4bdf6c4SBarry Smith       index[1] = ex->ys + ((row/ex->nx) % ex->ny);
468f4bdf6c4SBarry Smith       index[2] = ex->zs + (row/(ex->nxny));
4698b1f7689SBarry Smith       PetscStackCallStandard(HYPRE_SStructMatrixSetValues,(ex->ss_mat,part,(HYPRE_Int *)index,var_type,7*nvars,(HYPRE_Int *)entries,values[var_type]));
470f4bdf6c4SBarry Smith     }
471f4bdf6c4SBarry Smith   } else {
472f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
473f4bdf6c4SBarry Smith       var_type = irow[i]/(ex->gnxgnygnz);
474f4bdf6c4SBarry Smith       grid_rank= irow[i] - var_type*(ex->gnxgnygnz);
475f4bdf6c4SBarry Smith 
476f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
477f4bdf6c4SBarry Smith       index[0] = ex->xs + (row % ex->nx);
478f4bdf6c4SBarry Smith       index[1] = ex->ys + ((row/ex->nx) % ex->ny);
479f4bdf6c4SBarry Smith       index[2] = ex->zs + (row/(ex->nxny));
4808b1f7689SBarry Smith       PetscStackCallStandard(HYPRE_SStructMatrixSetValues,(ex->ss_mat,part,(HYPRE_Int *)index,var_type,7*nvars,(HYPRE_Int *)entries,values[var_type]));
481f4bdf6c4SBarry Smith     }
482f4bdf6c4SBarry Smith   }
483fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructMatrixAssemble,(ex->ss_mat));
484f4bdf6c4SBarry Smith   ierr = PetscFree(values[0]);CHKERRQ(ierr);
485f4bdf6c4SBarry Smith   ierr = PetscFree(values);CHKERRQ(ierr);
486f4bdf6c4SBarry Smith   ierr = PetscFree(entries);CHKERRQ(ierr);
487f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
488f4bdf6c4SBarry Smith }
489f4bdf6c4SBarry Smith 
490f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPRESStruct_3d(Mat mat)
491f4bdf6c4SBarry Smith {
492f4bdf6c4SBarry Smith   PetscErrorCode   ierr;
493f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex  = (Mat_HYPRESStruct*) mat->data;
4944ddd07fcSJed Brown   PetscInt         nvars= ex->nvars;
4954ddd07fcSJed Brown   PetscInt         size;
4964ddd07fcSJed Brown   PetscInt         part= 0;   /* only one part */
497f4bdf6c4SBarry Smith 
498f4bdf6c4SBarry Smith   PetscFunctionBegin;
499f4bdf6c4SBarry 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);
500f4bdf6c4SBarry Smith   {
5014ddd07fcSJed Brown     PetscInt    i,*entries,iupper[3],ilower[3];
502f4bdf6c4SBarry Smith     PetscScalar *values;
5034ddd07fcSJed Brown 
504f4bdf6c4SBarry Smith 
505f4bdf6c4SBarry Smith     for (i= 0; i< 3; i++) {
506f4bdf6c4SBarry Smith       ilower[i]= ex->hbox.imin[i];
507f4bdf6c4SBarry Smith       iupper[i]= ex->hbox.imax[i];
508f4bdf6c4SBarry Smith     }
509f4bdf6c4SBarry Smith 
510dcca6d9dSJed Brown     ierr = PetscMalloc2(nvars*7,&entries,nvars*7*size,&values);CHKERRQ(ierr);
5118865f1eaSKarl Rupp     for (i= 0; i< nvars*7; i++) entries[i]= i;
512f4bdf6c4SBarry Smith     ierr = PetscMemzero(values,nvars*7*size*sizeof(PetscScalar));CHKERRQ(ierr);
513f4bdf6c4SBarry Smith 
514f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
5158b1f7689SBarry Smith       PetscStackCallStandard(HYPRE_SStructMatrixSetBoxValues,(ex->ss_mat,part,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,i,nvars*7,(HYPRE_Int *)entries,values));
516f4bdf6c4SBarry Smith     }
517f4bdf6c4SBarry Smith     ierr = PetscFree2(entries,values);CHKERRQ(ierr);
518f4bdf6c4SBarry Smith   }
519fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructMatrixAssemble,(ex->ss_mat));
520f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
521f4bdf6c4SBarry Smith }
522f4bdf6c4SBarry Smith 
523f4bdf6c4SBarry Smith 
52459cb773eSBarry Smith static PetscErrorCode  MatSetUp_HYPRESStruct(Mat mat)
525f4bdf6c4SBarry Smith {
526f4bdf6c4SBarry Smith   PetscErrorCode         ierr;
527f4bdf6c4SBarry Smith   Mat_HYPRESStruct       *ex = (Mat_HYPRESStruct*) mat->data;
528f4bdf6c4SBarry Smith   PetscInt               dim,dof,sw[3],nx,ny,nz;
5294ddd07fcSJed Brown   PetscInt               ilower[3],iupper[3],ssize,i;
530bff4a2f0SMatthew G. Knepley   DMBoundaryType         px,py,pz;
531f4bdf6c4SBarry Smith   DMDAStencilType        st;
5324ddd07fcSJed Brown   PetscInt               nparts= 1;  /* assuming only one part */
5334ddd07fcSJed Brown   PetscInt               part  = 0;
534565245c5SBarry Smith   ISLocalToGlobalMapping ltog;
53559cb773eSBarry Smith   DM                     da;
536b026d285SBarry Smith 
537f4bdf6c4SBarry Smith   PetscFunctionBegin;
53859cb773eSBarry Smith   ierr   = MatGetDM(mat,(DM*)&da);CHKERRQ(ierr);
539f4bdf6c4SBarry Smith   ex->da = da;
540f4bdf6c4SBarry Smith   ierr   = PetscObjectReference((PetscObject)da);CHKERRQ(ierr);
541f4bdf6c4SBarry Smith 
5427ab44359SJed Brown   ierr       = DMDAGetInfo(ex->da,&dim,0,0,0,0,0,0,&dof,&sw[0],&px,&py,&pz,&st);CHKERRQ(ierr);
543f4bdf6c4SBarry Smith   ierr       = DMDAGetCorners(ex->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
544f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
545f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
546f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
547f4bdf6c4SBarry Smith   /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
548f4bdf6c4SBarry Smith   ex->hbox.imin[0] = ilower[0];
549f4bdf6c4SBarry Smith   ex->hbox.imin[1] = ilower[1];
550f4bdf6c4SBarry Smith   ex->hbox.imin[2] = ilower[2];
551f4bdf6c4SBarry Smith   ex->hbox.imax[0] = iupper[0];
552f4bdf6c4SBarry Smith   ex->hbox.imax[1] = iupper[1];
553f4bdf6c4SBarry Smith   ex->hbox.imax[2] = iupper[2];
554f4bdf6c4SBarry Smith 
555f4bdf6c4SBarry Smith   ex->dofs_order = 0;
556f4bdf6c4SBarry Smith 
557f4bdf6c4SBarry Smith   /* assuming that the same number of dofs on each gridpoint. Also assume all cell-centred based */
558f4bdf6c4SBarry Smith   ex->nvars= dof;
559f4bdf6c4SBarry Smith 
560f4bdf6c4SBarry Smith   /* create the hypre grid object and set its information */
561ce94432eSBarry Smith   if (px || py || pz) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add periodic support by calling HYPRE_SStructGridSetPeriodic()");
562fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGridCreate,(ex->hcomm,dim,nparts,&ex->ss_grid));
563fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGridSetExtents,(ex->ss_grid,part,ex->hbox.imin,ex->hbox.imax));
564f4bdf6c4SBarry Smith   {
565f4bdf6c4SBarry Smith     HYPRE_SStructVariable *vartypes;
566785e854fSJed Brown     ierr = PetscMalloc1(ex->nvars,&vartypes);CHKERRQ(ierr);
5678865f1eaSKarl Rupp     for (i= 0; i< ex->nvars; i++) vartypes[i]= HYPRE_SSTRUCT_VARIABLE_CELL;
568fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructGridSetVariables,(ex->ss_grid, part, ex->nvars,vartypes));
569f4bdf6c4SBarry Smith     ierr = PetscFree(vartypes);CHKERRQ(ierr);
570f4bdf6c4SBarry Smith   }
571fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGridAssemble,(ex->ss_grid));
572f4bdf6c4SBarry Smith 
573f4bdf6c4SBarry Smith   sw[1] = sw[0];
574f4bdf6c4SBarry Smith   sw[2] = sw[1];
575fd3f9acdSBarry Smith   /* PetscStackCallStandard(HYPRE_SStructGridSetNumGhost,(ex->ss_grid,sw)); */
576f4bdf6c4SBarry Smith 
577f4bdf6c4SBarry Smith   /* create the hypre stencil object and set its information */
578ce94432eSBarry Smith   if (sw[0] > 1) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for wider stencils");
579ce94432eSBarry Smith   if (st == DMDA_STENCIL_BOX) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for box stencils");
580f4bdf6c4SBarry Smith 
581f4bdf6c4SBarry Smith   if (dim == 1) {
5824ddd07fcSJed Brown     PetscInt offsets[3][1] = {{-1},{0},{1}};
5834ddd07fcSJed Brown     PetscInt j, cnt;
584f4bdf6c4SBarry Smith 
585f4bdf6c4SBarry Smith     ssize = 3*(ex->nvars);
586fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructStencilCreate,(dim,ssize,&ex->ss_stencil));
587f4bdf6c4SBarry Smith     cnt= 0;
588f4bdf6c4SBarry Smith     for (i = 0; i < (ex->nvars); i++) {
589f4bdf6c4SBarry Smith       for (j = 0; j < 3; j++) {
5908b1f7689SBarry Smith         PetscStackCallStandard(HYPRE_SStructStencilSetEntry,(ex->ss_stencil, cnt, (HYPRE_Int *)offsets[j], i));
591f4bdf6c4SBarry Smith         cnt++;
592f4bdf6c4SBarry Smith       }
593f4bdf6c4SBarry Smith     }
594f4bdf6c4SBarry Smith   } else if (dim == 2) {
5954ddd07fcSJed Brown     PetscInt offsets[5][2] = {{0,-1},{-1,0},{0,0},{1,0},{0,1}};
5964ddd07fcSJed Brown     PetscInt j, cnt;
597f4bdf6c4SBarry Smith 
598f4bdf6c4SBarry Smith     ssize = 5*(ex->nvars);
599fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructStencilCreate,(dim,ssize,&ex->ss_stencil));
600f4bdf6c4SBarry Smith     cnt= 0;
601f4bdf6c4SBarry Smith     for (i= 0; i< (ex->nvars); i++) {
602f4bdf6c4SBarry Smith       for (j= 0; j< 5; j++) {
6038b1f7689SBarry Smith         PetscStackCallStandard(HYPRE_SStructStencilSetEntry,(ex->ss_stencil, cnt, (HYPRE_Int *)offsets[j], i));
604f4bdf6c4SBarry Smith         cnt++;
605f4bdf6c4SBarry Smith       }
606f4bdf6c4SBarry Smith     }
607f4bdf6c4SBarry Smith   } else if (dim == 3) {
6084ddd07fcSJed Brown     PetscInt offsets[7][3] = {{0,0,-1},{0,-1,0},{-1,0,0},{0,0,0},{1,0,0},{0,1,0},{0,0,1}};
6094ddd07fcSJed Brown     PetscInt j, cnt;
610f4bdf6c4SBarry Smith 
611f4bdf6c4SBarry Smith     ssize = 7*(ex->nvars);
612fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructStencilCreate,(dim,ssize,&ex->ss_stencil));
613f4bdf6c4SBarry Smith     cnt= 0;
614f4bdf6c4SBarry Smith     for (i= 0; i< (ex->nvars); i++) {
615f4bdf6c4SBarry Smith       for (j= 0; j< 7; j++) {
6168b1f7689SBarry Smith         PetscStackCallStandard(HYPRE_SStructStencilSetEntry,(ex->ss_stencil, cnt, (HYPRE_Int *)offsets[j], i));
617f4bdf6c4SBarry Smith         cnt++;
618f4bdf6c4SBarry Smith       }
619f4bdf6c4SBarry Smith     }
620f4bdf6c4SBarry Smith   }
621f4bdf6c4SBarry Smith 
622f4bdf6c4SBarry Smith   /* create the HYPRE graph */
623fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGraphCreate,(ex->hcomm, ex->ss_grid, &(ex->ss_graph)));
624f4bdf6c4SBarry Smith 
625f4bdf6c4SBarry Smith   /* set the stencil graph. Note that each variable has the same graph. This means that each
626f4bdf6c4SBarry Smith      variable couples to all the other variable and with the same stencil pattern. */
627f4bdf6c4SBarry Smith   for (i= 0; i< (ex->nvars); i++) {
628fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructGraphSetStencil,(ex->ss_graph,part,i,ex->ss_stencil));
629f4bdf6c4SBarry Smith   }
630fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGraphAssemble,(ex->ss_graph));
631f4bdf6c4SBarry Smith 
632f4bdf6c4SBarry Smith   /* create the HYPRE sstruct vectors for rhs and solution */
633fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorCreate,(ex->hcomm,ex->ss_grid,&ex->ss_b));
634fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorCreate,(ex->hcomm,ex->ss_grid,&ex->ss_x));
635fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorInitialize,(ex->ss_b));
636fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorInitialize,(ex->ss_x));
637fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorAssemble,(ex->ss_b));
638fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorAssemble,(ex->ss_x));
639f4bdf6c4SBarry Smith 
640f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
641fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructMatrixCreate,(ex->hcomm,ex->ss_graph,&ex->ss_mat));
642fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGridDestroy,(ex->ss_grid));
643fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructStencilDestroy,(ex->ss_stencil));
644f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
645fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructMatrixInitialize,(ex->ss_mat));
646f4bdf6c4SBarry Smith     ex->needsinitialization = PETSC_FALSE;
647f4bdf6c4SBarry Smith   }
648f4bdf6c4SBarry Smith 
649f4bdf6c4SBarry Smith   /* set the global and local sizes of the matrix */
650f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(da,0,0,0,&nx,&ny,&nz);CHKERRQ(ierr);
651f4bdf6c4SBarry Smith   ierr = MatSetSizes(mat,dof*nx*ny*nz,dof*nx*ny*nz,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
65261710fbeSStefano Zampini   ierr = PetscLayoutSetBlockSize(mat->rmap,dof);CHKERRQ(ierr);
65361710fbeSStefano Zampini   ierr = PetscLayoutSetBlockSize(mat->cmap,dof);CHKERRQ(ierr);
654f4bdf6c4SBarry Smith   ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr);
655f4bdf6c4SBarry Smith   ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr);
65661710fbeSStefano Zampini   mat->preallocated = PETSC_TRUE;
657f4bdf6c4SBarry Smith 
658f4bdf6c4SBarry Smith   if (dim == 3) {
659f4bdf6c4SBarry Smith     mat->ops->setvalueslocal = MatSetValuesLocal_HYPRESStruct_3d;
660f4bdf6c4SBarry Smith     mat->ops->zerorowslocal  = MatZeroRowsLocal_HYPRESStruct_3d;
661f4bdf6c4SBarry Smith     mat->ops->zeroentries    = MatZeroEntries_HYPRESStruct_3d;
6628865f1eaSKarl Rupp 
66361710fbeSStefano Zampini     /* ierr = MatZeroEntries_HYPRESStruct_3d(mat);CHKERRQ(ierr); */
664ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Only support for 3d DMDA currently");
665f4bdf6c4SBarry Smith 
666f4bdf6c4SBarry Smith   /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
6670298fd71SBarry Smith   ierr = MatGetOwnershipRange(mat,&ex->rstart,NULL);CHKERRQ(ierr);
668565245c5SBarry Smith   ierr = DMGetLocalToGlobalMapping(ex->da,&ltog);CHKERRQ(ierr);
669565245c5SBarry Smith   ierr = ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **) &ex->gindices);CHKERRQ(ierr);
670f4bdf6c4SBarry Smith   ierr = DMDAGetGhostCorners(ex->da,0,0,0,&ex->gnx,&ex->gnxgny,&ex->gnxgnygnz);CHKERRQ(ierr);
6718865f1eaSKarl Rupp 
672f4bdf6c4SBarry Smith   ex->gnxgny    *= ex->gnx;
673f4bdf6c4SBarry Smith   ex->gnxgnygnz *= ex->gnxgny;
6748865f1eaSKarl Rupp 
675f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(ex->da,&ex->xs,&ex->ys,&ex->zs,&ex->nx,&ex->ny,&ex->nz);CHKERRQ(ierr);
6768865f1eaSKarl Rupp 
677f4bdf6c4SBarry Smith   ex->nxny   = ex->nx*ex->ny;
678f4bdf6c4SBarry Smith   ex->nxnynz = ex->nz*ex->nxny;
679f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
680f4bdf6c4SBarry Smith }
681f4bdf6c4SBarry Smith 
682f4bdf6c4SBarry Smith PetscErrorCode MatMult_HYPRESStruct(Mat A,Vec x,Vec y)
683f4bdf6c4SBarry Smith {
684f4bdf6c4SBarry Smith   PetscErrorCode    ierr;
685b026d285SBarry Smith   const PetscScalar *xx;
686b026d285SBarry Smith   PetscScalar       *yy;
6874ddd07fcSJed Brown   PetscInt          ilower[3],iupper[3];
688f4bdf6c4SBarry Smith   Mat_HYPRESStruct  *mx     = (Mat_HYPRESStruct*)(A->data);
6894ddd07fcSJed Brown   PetscInt          ordering= mx->dofs_order;
6904ddd07fcSJed Brown   PetscInt          nvars   = mx->nvars;
6914ddd07fcSJed Brown   PetscInt          part    = 0;
6924ddd07fcSJed Brown   PetscInt          size;
6934ddd07fcSJed Brown   PetscInt          i;
694f4bdf6c4SBarry Smith 
695f4bdf6c4SBarry Smith   PetscFunctionBegin;
696f4bdf6c4SBarry Smith   ierr       = DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
697f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
698f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
699f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
700f4bdf6c4SBarry Smith 
701f4bdf6c4SBarry Smith   size= 1;
7028865f1eaSKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i]-ilower[i]+1);
703f4bdf6c4SBarry Smith 
704f4bdf6c4SBarry Smith   /* copy x values over to hypre for variable ordering */
705f4bdf6c4SBarry Smith   if (ordering) {
706fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructVectorSetConstantValues,(mx->ss_b,0.0));
707b026d285SBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
708f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
709b026d285SBarry Smith       PetscStackCallStandard(HYPRE_SStructVectorSetBoxValues,(mx->ss_b,part,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,i,(PetscScalar*)xx+(size*i)));
710f4bdf6c4SBarry Smith     }
711b026d285SBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
712fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructVectorAssemble,(mx->ss_b));
713fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructMatrixMatvec,(1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x));
714f4bdf6c4SBarry Smith 
715f4bdf6c4SBarry Smith     /* copy solution values back to PETSc */
716f4bdf6c4SBarry Smith     ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
717f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
7188b1f7689SBarry Smith       PetscStackCallStandard(HYPRE_SStructVectorGetBoxValues,(mx->ss_x,part,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,i,yy+(size*i)));
719f4bdf6c4SBarry Smith     }
720f4bdf6c4SBarry Smith     ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
721f4bdf6c4SBarry Smith   } else {      /* nodal ordering must be mapped to variable ordering for sys_pfmg */
722f4bdf6c4SBarry Smith     PetscScalar *z;
7234ddd07fcSJed Brown     PetscInt    j, k;
724f4bdf6c4SBarry Smith 
725785e854fSJed Brown     ierr = PetscMalloc1(nvars*size,&z);CHKERRQ(ierr);
726fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructVectorSetConstantValues,(mx->ss_b,0.0));
727b026d285SBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
728f4bdf6c4SBarry Smith 
729f4bdf6c4SBarry Smith     /* transform nodal to hypre's variable ordering for sys_pfmg */
730f4bdf6c4SBarry Smith     for (i= 0; i< size; i++) {
731f4bdf6c4SBarry Smith       k= i*nvars;
7328865f1eaSKarl Rupp       for (j= 0; j< nvars; j++) z[j*size+i]= xx[k+j];
733f4bdf6c4SBarry Smith     }
734f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
7358b1f7689SBarry Smith       PetscStackCallStandard(HYPRE_SStructVectorSetBoxValues,(mx->ss_b,part,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,i,z+(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++) {
7448b1f7689SBarry Smith       PetscStackCallStandard(HYPRE_SStructVectorGetBoxValues,(mx->ss_x,part,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,i,z+(size*i)));
745f4bdf6c4SBarry Smith     }
746f4bdf6c4SBarry Smith     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
747f4bdf6c4SBarry Smith     for (i= 0; i< size; i++) {
748f4bdf6c4SBarry Smith       k= i*nvars;
7498865f1eaSKarl Rupp       for (j= 0; j< nvars; j++) yy[k+j]= z[j*size+i];
750f4bdf6c4SBarry Smith     }
751f4bdf6c4SBarry Smith     ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
752f4bdf6c4SBarry Smith     ierr = PetscFree(z);CHKERRQ(ierr);
753f4bdf6c4SBarry Smith   }
754f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
755f4bdf6c4SBarry Smith }
756f4bdf6c4SBarry Smith 
757f4bdf6c4SBarry Smith PetscErrorCode MatAssemblyEnd_HYPRESStruct(Mat mat,MatAssemblyType mode)
758f4bdf6c4SBarry Smith {
759f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data;
760f4bdf6c4SBarry Smith   PetscErrorCode   ierr;
761f4bdf6c4SBarry Smith 
762f4bdf6c4SBarry Smith   PetscFunctionBegin;
763fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructMatrixAssemble,(ex->ss_mat));
764f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
765f4bdf6c4SBarry Smith }
766f4bdf6c4SBarry Smith 
767f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPRESStruct(Mat mat)
768f4bdf6c4SBarry Smith {
769f4bdf6c4SBarry Smith   PetscFunctionBegin;
770f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
771f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
772f4bdf6c4SBarry Smith }
773f4bdf6c4SBarry Smith 
774f4bdf6c4SBarry Smith PetscErrorCode MatDestroy_HYPRESStruct(Mat mat)
775f4bdf6c4SBarry Smith {
776f4bdf6c4SBarry Smith   Mat_HYPRESStruct       *ex = (Mat_HYPRESStruct*) mat->data;
777f4bdf6c4SBarry Smith   PetscErrorCode         ierr;
778*d94fc0b6SBarry Smith   ISLocalToGlobalMapping ltog;
779f4bdf6c4SBarry Smith 
780f4bdf6c4SBarry Smith   PetscFunctionBegin;
781*d94fc0b6SBarry Smith   ierr = DMGetLocalToGlobalMapping(ex->da,&ltog);CHKERRQ(ierr);
782*d94fc0b6SBarry Smith   ierr = ISLocalToGlobalMappingRestoreIndices(ltog, (const PetscInt **) &ex->gindices);CHKERRQ(ierr);
783fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGraphDestroy,(ex->ss_graph));
784fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructMatrixDestroy,(ex->ss_mat));
785fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorDestroy,(ex->ss_x));
786fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorDestroy,(ex->ss_b));
78759cb773eSBarry Smith   ierr = PetscObjectDereference((PetscObject)ex->da);CHKERRQ(ierr);
78859cb773eSBarry Smith   ierr = MPI_Comm_free(&(ex->hcomm));CHKERRQ(ierr);
78959cb773eSBarry Smith   ierr = PetscFree(ex);CHKERRQ(ierr);
790f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
791f4bdf6c4SBarry Smith }
792f4bdf6c4SBarry Smith 
7938cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_HYPRESStruct(Mat B)
794f4bdf6c4SBarry Smith {
795f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex;
796f4bdf6c4SBarry Smith   PetscErrorCode   ierr;
797f4bdf6c4SBarry Smith 
798f4bdf6c4SBarry Smith   PetscFunctionBegin;
799b00a9115SJed Brown   ierr         = PetscNewLog(B,&ex);CHKERRQ(ierr);
800f4bdf6c4SBarry Smith   B->data      = (void*)ex;
801f4bdf6c4SBarry Smith   B->rmap->bs  = 1;
802f4bdf6c4SBarry Smith   B->assembled = PETSC_FALSE;
803f4bdf6c4SBarry Smith 
804f4bdf6c4SBarry Smith   B->insertmode = NOT_SET_VALUES;
805f4bdf6c4SBarry Smith 
806f4bdf6c4SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_HYPRESStruct;
807f4bdf6c4SBarry Smith   B->ops->mult        = MatMult_HYPRESStruct;
808f4bdf6c4SBarry Smith   B->ops->zeroentries = MatZeroEntries_HYPRESStruct;
809f4bdf6c4SBarry Smith   B->ops->destroy     = MatDestroy_HYPRESStruct;
81059cb773eSBarry Smith   B->ops->setup       = MatSetUp_HYPRESStruct;
811f4bdf6c4SBarry Smith 
812f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
813f4bdf6c4SBarry Smith 
814ce94432eSBarry Smith   ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)B),&(ex->hcomm));CHKERRQ(ierr);
815f4bdf6c4SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATHYPRESSTRUCT);CHKERRQ(ierr);
816f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
817f4bdf6c4SBarry Smith }
818f4bdf6c4SBarry Smith 
819f4bdf6c4SBarry Smith 
820f4bdf6c4SBarry Smith 
821