xref: /petsc/src/dm/impls/da/hypre/mhyp.c (revision 95452b02e12c0ee11232c7ff2b24b568a8e07e43)
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 
18*95452b02SPatrick Sanan    Notes:
19*95452b02SPatrick Sanan     Unlike the more general support for blocks in hypre this allows only one block per process and requires the block
20f4bdf6c4SBarry Smith           be defined by a DMDA.
21f4bdf6c4SBarry Smith 
2259cb773eSBarry Smith           The matrix needs a DMDA associated with it by either a call to MatSetDM() or if the matrix is obtained from DMCreateMatrix()
23f4bdf6c4SBarry Smith 
2459cb773eSBarry Smith .seealso: MatCreate(), PCPFMG, MatSetDM(), DMCreateMatrix()
25f4bdf6c4SBarry Smith M*/
26f4bdf6c4SBarry Smith 
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 {
30f4bdf6c4SBarry Smith   PetscErrorCode    ierr;
31f4bdf6c4SBarry Smith   PetscInt          i,j,stencil,index[3],row,entries[7];
32f4bdf6c4SBarry Smith   const PetscScalar *values = y;
33f4bdf6c4SBarry Smith   Mat_HYPREStruct   *ex     = (Mat_HYPREStruct*) mat->data;
34f4bdf6c4SBarry Smith 
35f4bdf6c4SBarry Smith   PetscFunctionBegin;
3659cb773eSBarry Smith   if (PetscUnlikely(ncol > 7)) SETERRQ1(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;
54f4bdf6c4SBarry 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);
55f4bdf6c4SBarry Smith     }
56f4bdf6c4SBarry Smith     row      = ex->gindices[irow[i]] - ex->rstart;
57f4bdf6c4SBarry Smith     index[0] = ex->xs + (row % ex->nx);
58f4bdf6c4SBarry Smith     index[1] = ex->ys + ((row/ex->nx) % ex->ny);
59f4bdf6c4SBarry Smith     index[2] = ex->zs + (row/(ex->nxny));
60f4bdf6c4SBarry Smith     if (addv == ADD_VALUES) {
618b1f7689SBarry Smith       PetscStackCallStandard(HYPRE_StructMatrixAddToValues,(ex->hmat,(HYPRE_Int *)index,ncol,(HYPRE_Int *)entries,(PetscScalar*)values));
62f4bdf6c4SBarry Smith     } else {
638b1f7689SBarry Smith       PetscStackCallStandard(HYPRE_StructMatrixSetValues,(ex->hmat,(HYPRE_Int *)index,ncol,(HYPRE_Int *)entries,(PetscScalar*)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;
73f4bdf6c4SBarry Smith   PetscInt        i,index[3],row,entries[7] = {0,1,2,3,4,5,6};
74f4bdf6c4SBarry Smith   PetscScalar     values[7];
75f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
76f4bdf6c4SBarry Smith 
77f4bdf6c4SBarry Smith   PetscFunctionBegin;
78ce94432eSBarry Smith   if (x && b) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"No support");
79f4bdf6c4SBarry Smith   ierr      = PetscMemzero(values,7*sizeof(PetscScalar));CHKERRQ(ierr);
80f4bdf6c4SBarry Smith   values[3] = d;
81f4bdf6c4SBarry Smith   for (i=0; i<nrow; i++) {
82f4bdf6c4SBarry Smith     row      = ex->gindices[irow[i]] - ex->rstart;
83f4bdf6c4SBarry Smith     index[0] = ex->xs + (row % ex->nx);
84f4bdf6c4SBarry Smith     index[1] = ex->ys + ((row/ex->nx) % ex->ny);
85f4bdf6c4SBarry Smith     index[2] = ex->zs + (row/(ex->nxny));
868b1f7689SBarry Smith     PetscStackCallStandard(HYPRE_StructMatrixSetValues,(ex->hmat,(HYPRE_Int *)index,7,(HYPRE_Int *)entries,values));
87f4bdf6c4SBarry Smith   }
88fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixAssemble,(ex->hmat));
89f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
90f4bdf6c4SBarry Smith }
91f4bdf6c4SBarry Smith 
92f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPREStruct_3d(Mat mat)
93f4bdf6c4SBarry Smith {
94f4bdf6c4SBarry Smith   PetscErrorCode  ierr;
95f4bdf6c4SBarry Smith   PetscInt        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 */
1008b1f7689SBarry Smith   PetscStackCallStandard(hypre_StructMatrixClearBoxValues,(ex->hmat,&ex->hbox,7,(HYPRE_Int *)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;
10959cb773eSBarry Smith   PetscInt               dim,dof,sw[6],nx,ny,nz,ilower[3],iupper[3],ssize,i;
110bff4a2f0SMatthew G. Knepley   DMBoundaryType         px,py,pz;
111f4bdf6c4SBarry Smith   DMDAStencilType        st;
112565245c5SBarry Smith   ISLocalToGlobalMapping ltog;
11359cb773eSBarry Smith   DM                     da;
114f4bdf6c4SBarry Smith 
115f4bdf6c4SBarry Smith   PetscFunctionBegin;
11659cb773eSBarry Smith   ierr   = MatGetDM(mat,(DM*)&da);CHKERRQ(ierr);
117f4bdf6c4SBarry Smith   ex->da = da;
118f4bdf6c4SBarry Smith   ierr   = PetscObjectReference((PetscObject)da);CHKERRQ(ierr);
119f4bdf6c4SBarry Smith 
1207ab44359SJed Brown   ierr       = DMDAGetInfo(ex->da,&dim,0,0,0,0,0,0,&dof,&sw[0],&px,&py,&pz,&st);CHKERRQ(ierr);
121f4bdf6c4SBarry Smith   ierr       = DMDAGetCorners(ex->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
122f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
123f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
124f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
125f4bdf6c4SBarry Smith 
126f4bdf6c4SBarry Smith   /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
127f4bdf6c4SBarry Smith   ex->hbox.imin[0] = ilower[0];
128f4bdf6c4SBarry Smith   ex->hbox.imin[1] = ilower[1];
129f4bdf6c4SBarry Smith   ex->hbox.imin[2] = ilower[2];
130f4bdf6c4SBarry Smith   ex->hbox.imax[0] = iupper[0];
131f4bdf6c4SBarry Smith   ex->hbox.imax[1] = iupper[1];
132f4bdf6c4SBarry Smith   ex->hbox.imax[2] = iupper[2];
133f4bdf6c4SBarry Smith 
134f4bdf6c4SBarry Smith   /* create the hypre grid object and set its information */
135ce94432eSBarry Smith   if (dof > 1) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Currently only support for scalar problems");
136ce94432eSBarry Smith   if (px || py || pz) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add periodic support by calling HYPRE_StructGridSetPeriodic()");
137fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructGridCreate,(ex->hcomm,dim,&ex->hgrid));
1388b1f7689SBarry Smith   PetscStackCallStandard(HYPRE_StructGridSetExtents,(ex->hgrid,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper));
139fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructGridAssemble,(ex->hgrid));
140f4bdf6c4SBarry Smith 
14159cb773eSBarry Smith   sw[5] = sw[4] = sw[3] = sw[2] = sw[1] = sw[0];
1428b1f7689SBarry Smith   PetscStackCallStandard(HYPRE_StructGridSetNumGhost,(ex->hgrid,(HYPRE_Int *)sw));
143f4bdf6c4SBarry Smith 
144f4bdf6c4SBarry Smith   /* create the hypre stencil object and set its information */
145ce94432eSBarry Smith   if (sw[0] > 1) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for wider stencils");
146ce94432eSBarry Smith   if (st == DMDA_STENCIL_BOX) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for box stencils");
147f4bdf6c4SBarry Smith   if (dim == 1) {
1484ddd07fcSJed Brown     PetscInt offsets[3][1] = {{-1},{0},{1}};
149f4bdf6c4SBarry Smith     ssize = 3;
150fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_StructStencilCreate,(dim,ssize,&ex->hstencil));
151f4bdf6c4SBarry Smith     for (i=0; i<ssize; i++) {
1528b1f7689SBarry Smith       PetscStackCallStandard(HYPRE_StructStencilSetElement,(ex->hstencil,i,(HYPRE_Int *)offsets[i]));
153f4bdf6c4SBarry Smith     }
154f4bdf6c4SBarry Smith   } else if (dim == 2) {
1554ddd07fcSJed Brown     PetscInt offsets[5][2] = {{0,-1},{-1,0},{0,0},{1,0},{0,1}};
156f4bdf6c4SBarry Smith     ssize = 5;
157fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_StructStencilCreate,(dim,ssize,&ex->hstencil));
158f4bdf6c4SBarry Smith     for (i=0; i<ssize; i++) {
1598b1f7689SBarry Smith       PetscStackCallStandard(HYPRE_StructStencilSetElement,(ex->hstencil,i,(HYPRE_Int *)offsets[i]));
160f4bdf6c4SBarry Smith     }
161f4bdf6c4SBarry Smith   } else if (dim == 3) {
1624ddd07fcSJed 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}};
163f4bdf6c4SBarry Smith     ssize = 7;
164fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_StructStencilCreate,(dim,ssize,&ex->hstencil));
165f4bdf6c4SBarry Smith     for (i=0; i<ssize; i++) {
1668b1f7689SBarry Smith       PetscStackCallStandard(HYPRE_StructStencilSetElement,(ex->hstencil,i,(HYPRE_Int *)offsets[i]));
167f4bdf6c4SBarry Smith     }
168f4bdf6c4SBarry Smith   }
169f4bdf6c4SBarry Smith 
170f4bdf6c4SBarry Smith   /* create the HYPRE vector for rhs and solution */
171fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorCreate,(ex->hcomm,ex->hgrid,&ex->hb));
172fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorCreate,(ex->hcomm,ex->hgrid,&ex->hx));
173fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorInitialize,(ex->hb));
174fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorInitialize,(ex->hx));
175fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorAssemble,(ex->hb));
176fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorAssemble,(ex->hx));
177f4bdf6c4SBarry Smith 
178f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
179fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixCreate,(ex->hcomm,ex->hgrid,ex->hstencil,&ex->hmat));
180fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructGridDestroy,(ex->hgrid));
181fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructStencilDestroy,(ex->hstencil));
182f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
183fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_StructMatrixInitialize,(ex->hmat));
184f4bdf6c4SBarry Smith     ex->needsinitialization = PETSC_FALSE;
185f4bdf6c4SBarry Smith   }
186f4bdf6c4SBarry Smith 
187f4bdf6c4SBarry Smith   /* set the global and local sizes of the matrix */
188f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(da,0,0,0,&nx,&ny,&nz);CHKERRQ(ierr);
189f4bdf6c4SBarry Smith   ierr = MatSetSizes(mat,dof*nx*ny*nz,dof*nx*ny*nz,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
190f4bdf6c4SBarry Smith   ierr = PetscLayoutSetBlockSize(mat->rmap,1);CHKERRQ(ierr);
191f4bdf6c4SBarry Smith   ierr = PetscLayoutSetBlockSize(mat->cmap,1);CHKERRQ(ierr);
192f4bdf6c4SBarry Smith   ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr);
193f4bdf6c4SBarry Smith   ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr);
19459cb773eSBarry Smith   mat->preallocated = PETSC_TRUE;
195f4bdf6c4SBarry Smith 
196f4bdf6c4SBarry Smith   if (dim == 3) {
197f4bdf6c4SBarry Smith     mat->ops->setvalueslocal = MatSetValuesLocal_HYPREStruct_3d;
198f4bdf6c4SBarry Smith     mat->ops->zerorowslocal  = MatZeroRowsLocal_HYPREStruct_3d;
199f4bdf6c4SBarry Smith     mat->ops->zeroentries    = MatZeroEntries_HYPREStruct_3d;
2008865f1eaSKarl Rupp 
20159cb773eSBarry Smith     /*        ierr = MatZeroEntries_HYPREStruct_3d(mat);CHKERRQ(ierr); */
202ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Only support for 3d DMDA currently");
203f4bdf6c4SBarry Smith 
204f4bdf6c4SBarry Smith   /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
2050298fd71SBarry Smith   ierr        = MatGetOwnershipRange(mat,&ex->rstart,NULL);CHKERRQ(ierr);
206565245c5SBarry Smith   ierr        = DMGetLocalToGlobalMapping(ex->da,&ltog);CHKERRQ(ierr);
207565245c5SBarry Smith   ierr        = ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **) &ex->gindices);CHKERRQ(ierr);
208f4bdf6c4SBarry Smith   ierr        = DMDAGetGhostCorners(ex->da,0,0,0,&ex->gnx,&ex->gnxgny,0);CHKERRQ(ierr);
209f4bdf6c4SBarry Smith   ex->gnxgny *= ex->gnx;
210f4bdf6c4SBarry Smith   ierr        = DMDAGetCorners(ex->da,&ex->xs,&ex->ys,&ex->zs,&ex->nx,&ex->ny,0);CHKERRQ(ierr);
211f4bdf6c4SBarry Smith   ex->nxny    = ex->nx*ex->ny;
212f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
213f4bdf6c4SBarry Smith }
214f4bdf6c4SBarry Smith 
215f4bdf6c4SBarry Smith PetscErrorCode MatMult_HYPREStruct(Mat A,Vec x,Vec y)
216f4bdf6c4SBarry Smith {
217f4bdf6c4SBarry Smith   PetscErrorCode    ierr;
218b026d285SBarry Smith   const PetscScalar *xx;
219b026d285SBarry Smith   PetscScalar       *yy;
2204ddd07fcSJed Brown   PetscInt          ilower[3],iupper[3];
221f4bdf6c4SBarry Smith   Mat_HYPREStruct   *mx = (Mat_HYPREStruct*)(A->data);
222f4bdf6c4SBarry Smith 
223f4bdf6c4SBarry Smith   PetscFunctionBegin;
224f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
2258865f1eaSKarl Rupp 
226f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
227f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
228f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
229f4bdf6c4SBarry Smith 
230f4bdf6c4SBarry Smith   /* copy x values over to hypre */
231fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorSetConstantValues,(mx->hb,0.0));
232b026d285SBarry Smith   ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
233b026d285SBarry Smith   PetscStackCallStandard(HYPRE_StructVectorSetBoxValues,(mx->hb,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,(PetscScalar*)xx));
234b026d285SBarry Smith   ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
235fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorAssemble,(mx->hb));
236fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixMatvec,(1.0,mx->hmat,mx->hb,0.0,mx->hx));
237f4bdf6c4SBarry Smith 
238f4bdf6c4SBarry Smith   /* copy solution values back to PETSc */
239f4bdf6c4SBarry Smith   ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
2408b1f7689SBarry Smith   PetscStackCallStandard(HYPRE_StructVectorGetBoxValues,(mx->hx,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,yy));
241f4bdf6c4SBarry Smith   ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
242f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
243f4bdf6c4SBarry Smith }
244f4bdf6c4SBarry Smith 
245f4bdf6c4SBarry Smith PetscErrorCode MatAssemblyEnd_HYPREStruct(Mat mat,MatAssemblyType mode)
246f4bdf6c4SBarry Smith {
247f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
248f4bdf6c4SBarry Smith   PetscErrorCode  ierr;
249f4bdf6c4SBarry Smith 
250f4bdf6c4SBarry Smith   PetscFunctionBegin;
251fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixAssemble,(ex->hmat));
252fd3f9acdSBarry Smith   /* PetscStackCallStandard(HYPRE_StructMatrixPrint,("dummy",ex->hmat,0)); */
253f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
254f4bdf6c4SBarry Smith }
255f4bdf6c4SBarry Smith 
256f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPREStruct(Mat mat)
257f4bdf6c4SBarry Smith {
258f4bdf6c4SBarry Smith   PetscFunctionBegin;
259f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
260f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
261f4bdf6c4SBarry Smith }
262f4bdf6c4SBarry Smith 
263f4bdf6c4SBarry Smith PetscErrorCode MatDestroy_HYPREStruct(Mat mat)
264f4bdf6c4SBarry Smith {
265f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
266f4bdf6c4SBarry Smith   PetscErrorCode  ierr;
267f4bdf6c4SBarry Smith 
268f4bdf6c4SBarry Smith   PetscFunctionBegin;
269fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixDestroy,(ex->hmat));
270fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorDestroy,(ex->hx));
271fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorDestroy,(ex->hb));
27259cb773eSBarry Smith   ierr = PetscObjectDereference((PetscObject)ex->da);CHKERRQ(ierr);
27359cb773eSBarry Smith   ierr = MPI_Comm_free(&(ex->hcomm));CHKERRQ(ierr);
27459cb773eSBarry Smith   ierr = PetscFree(ex);CHKERRQ(ierr);
275f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
276f4bdf6c4SBarry Smith }
277f4bdf6c4SBarry Smith 
2788cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_HYPREStruct(Mat B)
279f4bdf6c4SBarry Smith {
280f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex;
281f4bdf6c4SBarry Smith   PetscErrorCode  ierr;
282f4bdf6c4SBarry Smith 
283f4bdf6c4SBarry Smith   PetscFunctionBegin;
284b00a9115SJed Brown   ierr         = PetscNewLog(B,&ex);CHKERRQ(ierr);
285f4bdf6c4SBarry Smith   B->data      = (void*)ex;
286f4bdf6c4SBarry Smith   B->rmap->bs  = 1;
287f4bdf6c4SBarry Smith   B->assembled = PETSC_FALSE;
288f4bdf6c4SBarry Smith 
289f4bdf6c4SBarry Smith   B->insertmode = NOT_SET_VALUES;
290f4bdf6c4SBarry Smith 
291f4bdf6c4SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_HYPREStruct;
292f4bdf6c4SBarry Smith   B->ops->mult        = MatMult_HYPREStruct;
293f4bdf6c4SBarry Smith   B->ops->zeroentries = MatZeroEntries_HYPREStruct;
294f4bdf6c4SBarry Smith   B->ops->destroy     = MatDestroy_HYPREStruct;
29559cb773eSBarry Smith   B->ops->setup       = MatSetUp_HYPREStruct;
296f4bdf6c4SBarry Smith 
297f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
298f4bdf6c4SBarry Smith 
299ce94432eSBarry Smith   ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)B),&(ex->hcomm));CHKERRQ(ierr);
300f4bdf6c4SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATHYPRESTRUCT);CHKERRQ(ierr);
301f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
302f4bdf6c4SBarry Smith }
303f4bdf6c4SBarry Smith 
304f4bdf6c4SBarry Smith /*MC
305f4bdf6c4SBarry Smith    MATHYPRESSTRUCT - MATHYPRESSTRUCT = "hypresstruct" - A matrix type to be used for parallel sparse matrices
306f4bdf6c4SBarry Smith           based on the hypre HYPRE_SStructMatrix.
307f4bdf6c4SBarry Smith 
308f4bdf6c4SBarry Smith 
309f4bdf6c4SBarry Smith    Level: intermediate
310f4bdf6c4SBarry Smith 
311*95452b02SPatrick Sanan    Notes:
312*95452b02SPatrick Sanan     Unlike hypre's general semi-struct object consisting of a collection of structured-grid objects and unstructured
313b026d285SBarry Smith           grid objects, we restrict the semi-struct objects to consist of only structured-grid components.
314f4bdf6c4SBarry Smith 
315f4bdf6c4SBarry 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
316f4bdf6c4SBarry Smith           be defined by a DMDA.
317f4bdf6c4SBarry Smith 
31859cb773eSBarry Smith           The matrix needs a DMDA associated with it by either a call to MatSetDM() or if the matrix is obtained from DMCreateMatrix()
319f4bdf6c4SBarry Smith 
320f4bdf6c4SBarry Smith M*/
321f4bdf6c4SBarry Smith 
322f4bdf6c4SBarry Smith PetscErrorCode  MatSetValuesLocal_HYPRESStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
323f4bdf6c4SBarry Smith {
324f4bdf6c4SBarry Smith   PetscErrorCode    ierr;
325f4bdf6c4SBarry Smith   PetscInt          i,j,stencil,index[3];
326f4bdf6c4SBarry Smith   const PetscScalar *values = y;
327f4bdf6c4SBarry Smith   Mat_HYPRESStruct  *ex     = (Mat_HYPRESStruct*) mat->data;
328f4bdf6c4SBarry Smith 
3294ddd07fcSJed Brown   PetscInt          part = 0;          /* Petsc sstruct interface only allows 1 part */
3304ddd07fcSJed Brown   PetscInt          ordering;
3314ddd07fcSJed Brown   PetscInt          grid_rank, to_grid_rank;
3324ddd07fcSJed Brown   PetscInt          var_type, to_var_type;
3334ddd07fcSJed Brown   PetscInt          to_var_entry = 0;
3344ddd07fcSJed Brown   PetscInt          nvars= ex->nvars;
335f4bdf6c4SBarry Smith   PetscInt          row,*entries;
336f4bdf6c4SBarry Smith 
337f4bdf6c4SBarry Smith   PetscFunctionBegin;
338785e854fSJed Brown   ierr     = PetscMalloc1(7*nvars,&entries);CHKERRQ(ierr);
339f4bdf6c4SBarry Smith   ordering = ex->dofs_order;  /* ordering= 0   nodal ordering
340f4bdf6c4SBarry Smith                                            1   variable ordering */
34161710fbeSStefano Zampini   /* stencil entries are ordered by variables: var0_stencil0, var0_stencil1, ..., var0_stencil6, var1_stencil0, var1_stencil1, ...  */
342f4bdf6c4SBarry Smith   if (!ordering) {
343f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
344f4bdf6c4SBarry Smith       grid_rank= irow[i]/nvars;
345f4bdf6c4SBarry Smith       var_type = (irow[i] % nvars);
346f4bdf6c4SBarry Smith 
347f4bdf6c4SBarry Smith       for (j=0; j<ncol; j++) {
348f4bdf6c4SBarry Smith         to_grid_rank= icol[j]/nvars;
349f4bdf6c4SBarry Smith         to_var_type = (icol[j] % nvars);
350f4bdf6c4SBarry Smith 
351f4bdf6c4SBarry Smith         to_var_entry= to_var_entry*7;
352f4bdf6c4SBarry Smith         entries[j]  = to_var_entry;
353f4bdf6c4SBarry Smith 
354f4bdf6c4SBarry Smith         stencil = to_grid_rank-grid_rank;
355f4bdf6c4SBarry Smith         if (!stencil) {
356f4bdf6c4SBarry Smith           entries[j] += 3;
357f4bdf6c4SBarry Smith         } else if (stencil == -1) {
358f4bdf6c4SBarry Smith           entries[j] += 2;
359f4bdf6c4SBarry Smith         } else if (stencil == 1) {
360f4bdf6c4SBarry Smith           entries[j] += 4;
361f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnx) {
362f4bdf6c4SBarry Smith           entries[j] += 1;
363f4bdf6c4SBarry Smith         } else if (stencil == ex->gnx) {
364f4bdf6c4SBarry Smith           entries[j] += 5;
365f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnxgny) {
366f4bdf6c4SBarry Smith           entries[j] += 0;
367f4bdf6c4SBarry Smith         } else if (stencil == ex->gnxgny) {
368f4bdf6c4SBarry Smith           entries[j] += 6;
369f4bdf6c4SBarry 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);
370f4bdf6c4SBarry Smith       }
371f4bdf6c4SBarry Smith 
372f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
373f4bdf6c4SBarry Smith       index[0] = ex->xs + (row % ex->nx);
374f4bdf6c4SBarry Smith       index[1] = ex->ys + ((row/ex->nx) % ex->ny);
375f4bdf6c4SBarry Smith       index[2] = ex->zs + (row/(ex->nxny));
376f4bdf6c4SBarry Smith 
377f4bdf6c4SBarry Smith       if (addv == ADD_VALUES) {
3788b1f7689SBarry Smith         PetscStackCallStandard(HYPRE_SStructMatrixAddToValues,(ex->ss_mat,part,(HYPRE_Int *)index,var_type,ncol,(HYPRE_Int *)entries,(PetscScalar*)values));
379f4bdf6c4SBarry Smith       } else {
3808b1f7689SBarry Smith         PetscStackCallStandard(HYPRE_SStructMatrixSetValues,(ex->ss_mat,part,(HYPRE_Int *)index,var_type,ncol,(HYPRE_Int *)entries,(PetscScalar*)values));
381f4bdf6c4SBarry Smith       }
382f4bdf6c4SBarry Smith       values += ncol;
383f4bdf6c4SBarry Smith     }
384f4bdf6c4SBarry Smith   } else {
385f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
386f4bdf6c4SBarry Smith       var_type = irow[i]/(ex->gnxgnygnz);
387f4bdf6c4SBarry Smith       grid_rank= irow[i] - var_type*(ex->gnxgnygnz);
388f4bdf6c4SBarry Smith 
389f4bdf6c4SBarry Smith       for (j=0; j<ncol; j++) {
390f4bdf6c4SBarry Smith         to_var_type = icol[j]/(ex->gnxgnygnz);
391f4bdf6c4SBarry Smith         to_grid_rank= icol[j] - to_var_type*(ex->gnxgnygnz);
392f4bdf6c4SBarry Smith 
393f4bdf6c4SBarry Smith         to_var_entry= to_var_entry*7;
394f4bdf6c4SBarry Smith         entries[j]  = to_var_entry;
395f4bdf6c4SBarry Smith 
396f4bdf6c4SBarry Smith         stencil = to_grid_rank-grid_rank;
397f4bdf6c4SBarry Smith         if (!stencil) {
398f4bdf6c4SBarry Smith           entries[j] += 3;
399f4bdf6c4SBarry Smith         } else if (stencil == -1) {
400f4bdf6c4SBarry Smith           entries[j] += 2;
401f4bdf6c4SBarry Smith         } else if (stencil == 1) {
402f4bdf6c4SBarry Smith           entries[j] += 4;
403f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnx) {
404f4bdf6c4SBarry Smith           entries[j] += 1;
405f4bdf6c4SBarry Smith         } else if (stencil == ex->gnx) {
406f4bdf6c4SBarry Smith           entries[j] += 5;
407f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnxgny) {
408f4bdf6c4SBarry Smith           entries[j] += 0;
409f4bdf6c4SBarry Smith         } else if (stencil == ex->gnxgny) {
410f4bdf6c4SBarry Smith           entries[j] += 6;
411f4bdf6c4SBarry 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);
412f4bdf6c4SBarry Smith       }
413f4bdf6c4SBarry Smith 
414f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
415f4bdf6c4SBarry Smith       index[0] = ex->xs + (row % ex->nx);
416f4bdf6c4SBarry Smith       index[1] = ex->ys + ((row/ex->nx) % ex->ny);
417f4bdf6c4SBarry Smith       index[2] = ex->zs + (row/(ex->nxny));
418f4bdf6c4SBarry Smith 
419f4bdf6c4SBarry Smith       if (addv == ADD_VALUES) {
4208b1f7689SBarry Smith         PetscStackCallStandard(HYPRE_SStructMatrixAddToValues,(ex->ss_mat,part,(HYPRE_Int *)index,var_type,ncol,(HYPRE_Int *)entries,(PetscScalar*)values));
421f4bdf6c4SBarry Smith       } else {
4228b1f7689SBarry Smith         PetscStackCallStandard(HYPRE_SStructMatrixSetValues,(ex->ss_mat,part,(HYPRE_Int *)index,var_type,ncol,(HYPRE_Int *)entries,(PetscScalar*)values));
423f4bdf6c4SBarry Smith       }
424f4bdf6c4SBarry Smith       values += ncol;
425f4bdf6c4SBarry Smith     }
426f4bdf6c4SBarry Smith   }
427f4bdf6c4SBarry Smith   ierr = PetscFree(entries);CHKERRQ(ierr);
428f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
429f4bdf6c4SBarry Smith }
430f4bdf6c4SBarry Smith 
431f4bdf6c4SBarry Smith PetscErrorCode  MatZeroRowsLocal_HYPRESStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscScalar d,Vec x,Vec b)
432f4bdf6c4SBarry Smith {
433f4bdf6c4SBarry Smith   PetscErrorCode   ierr;
434f4bdf6c4SBarry Smith   PetscInt         i,index[3];
435f4bdf6c4SBarry Smith   PetscScalar      **values;
436f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data;
437f4bdf6c4SBarry Smith 
4384ddd07fcSJed Brown   PetscInt         part     = 0;      /* Petsc sstruct interface only allows 1 part */
4394ddd07fcSJed Brown   PetscInt         ordering = ex->dofs_order;
4404ddd07fcSJed Brown   PetscInt         grid_rank;
4414ddd07fcSJed Brown   PetscInt         var_type;
4424ddd07fcSJed Brown   PetscInt         nvars= ex->nvars;
443f4bdf6c4SBarry Smith   PetscInt         row,*entries;
444f4bdf6c4SBarry Smith 
445f4bdf6c4SBarry Smith   PetscFunctionBegin;
446ce94432eSBarry Smith   if (x && b) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"No support");
447785e854fSJed Brown   ierr = PetscMalloc1(7*nvars,&entries);CHKERRQ(ierr);
448f4bdf6c4SBarry Smith 
449785e854fSJed Brown   ierr = PetscMalloc1(nvars,&values);CHKERRQ(ierr);
450785e854fSJed Brown   ierr = PetscMalloc1(7*nvars*nvars,&values[0]);CHKERRQ(ierr);
451f4bdf6c4SBarry Smith   for (i=1; i<nvars; i++) {
452f4bdf6c4SBarry Smith     values[i] = values[i-1] + nvars*7;
453f4bdf6c4SBarry Smith   }
454f4bdf6c4SBarry Smith 
455f4bdf6c4SBarry Smith   for (i=0; i< nvars; i++) {
456f4bdf6c4SBarry Smith     ierr           = PetscMemzero(values[i],nvars*7*sizeof(PetscScalar));CHKERRQ(ierr);
457f4bdf6c4SBarry Smith     *(values[i]+3) = d;
458f4bdf6c4SBarry Smith   }
459f4bdf6c4SBarry Smith 
4608865f1eaSKarl Rupp   for (i= 0; i< nvars*7; i++) entries[i] = i;
461f4bdf6c4SBarry Smith 
462f4bdf6c4SBarry Smith   if (!ordering) {
463f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
464f4bdf6c4SBarry Smith       grid_rank = irow[i] / nvars;
465f4bdf6c4SBarry Smith       var_type  =(irow[i] % nvars);
466f4bdf6c4SBarry Smith 
467f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
468f4bdf6c4SBarry Smith       index[0] = ex->xs + (row % ex->nx);
469f4bdf6c4SBarry Smith       index[1] = ex->ys + ((row/ex->nx) % ex->ny);
470f4bdf6c4SBarry Smith       index[2] = ex->zs + (row/(ex->nxny));
4718b1f7689SBarry Smith       PetscStackCallStandard(HYPRE_SStructMatrixSetValues,(ex->ss_mat,part,(HYPRE_Int *)index,var_type,7*nvars,(HYPRE_Int *)entries,values[var_type]));
472f4bdf6c4SBarry Smith     }
473f4bdf6c4SBarry Smith   } else {
474f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
475f4bdf6c4SBarry Smith       var_type = irow[i]/(ex->gnxgnygnz);
476f4bdf6c4SBarry Smith       grid_rank= irow[i] - var_type*(ex->gnxgnygnz);
477f4bdf6c4SBarry Smith 
478f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
479f4bdf6c4SBarry Smith       index[0] = ex->xs + (row % ex->nx);
480f4bdf6c4SBarry Smith       index[1] = ex->ys + ((row/ex->nx) % ex->ny);
481f4bdf6c4SBarry Smith       index[2] = ex->zs + (row/(ex->nxny));
4828b1f7689SBarry Smith       PetscStackCallStandard(HYPRE_SStructMatrixSetValues,(ex->ss_mat,part,(HYPRE_Int *)index,var_type,7*nvars,(HYPRE_Int *)entries,values[var_type]));
483f4bdf6c4SBarry Smith     }
484f4bdf6c4SBarry Smith   }
485fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructMatrixAssemble,(ex->ss_mat));
486f4bdf6c4SBarry Smith   ierr = PetscFree(values[0]);CHKERRQ(ierr);
487f4bdf6c4SBarry Smith   ierr = PetscFree(values);CHKERRQ(ierr);
488f4bdf6c4SBarry Smith   ierr = PetscFree(entries);CHKERRQ(ierr);
489f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
490f4bdf6c4SBarry Smith }
491f4bdf6c4SBarry Smith 
492f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPRESStruct_3d(Mat mat)
493f4bdf6c4SBarry Smith {
494f4bdf6c4SBarry Smith   PetscErrorCode   ierr;
495f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex  = (Mat_HYPRESStruct*) mat->data;
4964ddd07fcSJed Brown   PetscInt         nvars= ex->nvars;
4974ddd07fcSJed Brown   PetscInt         size;
4984ddd07fcSJed Brown   PetscInt         part= 0;   /* only one part */
499f4bdf6c4SBarry Smith 
500f4bdf6c4SBarry Smith   PetscFunctionBegin;
501f4bdf6c4SBarry 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);
502f4bdf6c4SBarry Smith   {
5034ddd07fcSJed Brown     PetscInt    i,*entries,iupper[3],ilower[3];
504f4bdf6c4SBarry Smith     PetscScalar *values;
5054ddd07fcSJed Brown 
506f4bdf6c4SBarry Smith 
507f4bdf6c4SBarry Smith     for (i= 0; i< 3; i++) {
508f4bdf6c4SBarry Smith       ilower[i]= ex->hbox.imin[i];
509f4bdf6c4SBarry Smith       iupper[i]= ex->hbox.imax[i];
510f4bdf6c4SBarry Smith     }
511f4bdf6c4SBarry Smith 
512dcca6d9dSJed Brown     ierr = PetscMalloc2(nvars*7,&entries,nvars*7*size,&values);CHKERRQ(ierr);
5138865f1eaSKarl Rupp     for (i= 0; i< nvars*7; i++) entries[i]= i;
514f4bdf6c4SBarry Smith     ierr = PetscMemzero(values,nvars*7*size*sizeof(PetscScalar));CHKERRQ(ierr);
515f4bdf6c4SBarry Smith 
516f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
5178b1f7689SBarry Smith       PetscStackCallStandard(HYPRE_SStructMatrixSetBoxValues,(ex->ss_mat,part,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,i,nvars*7,(HYPRE_Int *)entries,values));
518f4bdf6c4SBarry Smith     }
519f4bdf6c4SBarry Smith     ierr = PetscFree2(entries,values);CHKERRQ(ierr);
520f4bdf6c4SBarry Smith   }
521fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructMatrixAssemble,(ex->ss_mat));
522f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
523f4bdf6c4SBarry Smith }
524f4bdf6c4SBarry Smith 
525f4bdf6c4SBarry Smith 
52659cb773eSBarry Smith static PetscErrorCode  MatSetUp_HYPRESStruct(Mat mat)
527f4bdf6c4SBarry Smith {
528f4bdf6c4SBarry Smith   PetscErrorCode         ierr;
529f4bdf6c4SBarry Smith   Mat_HYPRESStruct       *ex = (Mat_HYPRESStruct*) mat->data;
530f4bdf6c4SBarry Smith   PetscInt               dim,dof,sw[3],nx,ny,nz;
5314ddd07fcSJed Brown   PetscInt               ilower[3],iupper[3],ssize,i;
532bff4a2f0SMatthew G. Knepley   DMBoundaryType         px,py,pz;
533f4bdf6c4SBarry Smith   DMDAStencilType        st;
5344ddd07fcSJed Brown   PetscInt               nparts= 1;  /* assuming only one part */
5354ddd07fcSJed Brown   PetscInt               part  = 0;
536565245c5SBarry Smith   ISLocalToGlobalMapping ltog;
53759cb773eSBarry Smith   DM                     da;
538b026d285SBarry Smith 
539f4bdf6c4SBarry Smith   PetscFunctionBegin;
54059cb773eSBarry Smith   ierr   = MatGetDM(mat,(DM*)&da);CHKERRQ(ierr);
541f4bdf6c4SBarry Smith   ex->da = da;
542f4bdf6c4SBarry Smith   ierr   = PetscObjectReference((PetscObject)da);CHKERRQ(ierr);
543f4bdf6c4SBarry Smith 
5447ab44359SJed Brown   ierr       = DMDAGetInfo(ex->da,&dim,0,0,0,0,0,0,&dof,&sw[0],&px,&py,&pz,&st);CHKERRQ(ierr);
545f4bdf6c4SBarry Smith   ierr       = DMDAGetCorners(ex->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
546f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
547f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
548f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
549f4bdf6c4SBarry Smith   /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
550f4bdf6c4SBarry Smith   ex->hbox.imin[0] = ilower[0];
551f4bdf6c4SBarry Smith   ex->hbox.imin[1] = ilower[1];
552f4bdf6c4SBarry Smith   ex->hbox.imin[2] = ilower[2];
553f4bdf6c4SBarry Smith   ex->hbox.imax[0] = iupper[0];
554f4bdf6c4SBarry Smith   ex->hbox.imax[1] = iupper[1];
555f4bdf6c4SBarry Smith   ex->hbox.imax[2] = iupper[2];
556f4bdf6c4SBarry Smith 
557f4bdf6c4SBarry Smith   ex->dofs_order = 0;
558f4bdf6c4SBarry Smith 
559f4bdf6c4SBarry Smith   /* assuming that the same number of dofs on each gridpoint. Also assume all cell-centred based */
560f4bdf6c4SBarry Smith   ex->nvars= dof;
561f4bdf6c4SBarry Smith 
562f4bdf6c4SBarry Smith   /* create the hypre grid object and set its information */
563ce94432eSBarry Smith   if (px || py || pz) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add periodic support by calling HYPRE_SStructGridSetPeriodic()");
564fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGridCreate,(ex->hcomm,dim,nparts,&ex->ss_grid));
565fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGridSetExtents,(ex->ss_grid,part,ex->hbox.imin,ex->hbox.imax));
566f4bdf6c4SBarry Smith   {
567f4bdf6c4SBarry Smith     HYPRE_SStructVariable *vartypes;
568785e854fSJed Brown     ierr = PetscMalloc1(ex->nvars,&vartypes);CHKERRQ(ierr);
5698865f1eaSKarl Rupp     for (i= 0; i< ex->nvars; i++) vartypes[i]= HYPRE_SSTRUCT_VARIABLE_CELL;
570fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructGridSetVariables,(ex->ss_grid, part, ex->nvars,vartypes));
571f4bdf6c4SBarry Smith     ierr = PetscFree(vartypes);CHKERRQ(ierr);
572f4bdf6c4SBarry Smith   }
573fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGridAssemble,(ex->ss_grid));
574f4bdf6c4SBarry Smith 
575f4bdf6c4SBarry Smith   sw[1] = sw[0];
576f4bdf6c4SBarry Smith   sw[2] = sw[1];
577fd3f9acdSBarry Smith   /* PetscStackCallStandard(HYPRE_SStructGridSetNumGhost,(ex->ss_grid,sw)); */
578f4bdf6c4SBarry Smith 
579f4bdf6c4SBarry Smith   /* create the hypre stencil object and set its information */
580ce94432eSBarry Smith   if (sw[0] > 1) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for wider stencils");
581ce94432eSBarry Smith   if (st == DMDA_STENCIL_BOX) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for box stencils");
582f4bdf6c4SBarry Smith 
583f4bdf6c4SBarry Smith   if (dim == 1) {
5844ddd07fcSJed Brown     PetscInt offsets[3][1] = {{-1},{0},{1}};
5854ddd07fcSJed Brown     PetscInt j, cnt;
586f4bdf6c4SBarry Smith 
587f4bdf6c4SBarry Smith     ssize = 3*(ex->nvars);
588fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructStencilCreate,(dim,ssize,&ex->ss_stencil));
589f4bdf6c4SBarry Smith     cnt= 0;
590f4bdf6c4SBarry Smith     for (i = 0; i < (ex->nvars); i++) {
591f4bdf6c4SBarry Smith       for (j = 0; j < 3; j++) {
5928b1f7689SBarry Smith         PetscStackCallStandard(HYPRE_SStructStencilSetEntry,(ex->ss_stencil, cnt, (HYPRE_Int *)offsets[j], i));
593f4bdf6c4SBarry Smith         cnt++;
594f4bdf6c4SBarry Smith       }
595f4bdf6c4SBarry Smith     }
596f4bdf6c4SBarry Smith   } else if (dim == 2) {
5974ddd07fcSJed Brown     PetscInt offsets[5][2] = {{0,-1},{-1,0},{0,0},{1,0},{0,1}};
5984ddd07fcSJed Brown     PetscInt j, cnt;
599f4bdf6c4SBarry Smith 
600f4bdf6c4SBarry Smith     ssize = 5*(ex->nvars);
601fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructStencilCreate,(dim,ssize,&ex->ss_stencil));
602f4bdf6c4SBarry Smith     cnt= 0;
603f4bdf6c4SBarry Smith     for (i= 0; i< (ex->nvars); i++) {
604f4bdf6c4SBarry Smith       for (j= 0; j< 5; j++) {
6058b1f7689SBarry Smith         PetscStackCallStandard(HYPRE_SStructStencilSetEntry,(ex->ss_stencil, cnt, (HYPRE_Int *)offsets[j], i));
606f4bdf6c4SBarry Smith         cnt++;
607f4bdf6c4SBarry Smith       }
608f4bdf6c4SBarry Smith     }
609f4bdf6c4SBarry Smith   } else if (dim == 3) {
6104ddd07fcSJed 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}};
6114ddd07fcSJed Brown     PetscInt j, cnt;
612f4bdf6c4SBarry Smith 
613f4bdf6c4SBarry Smith     ssize = 7*(ex->nvars);
614fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructStencilCreate,(dim,ssize,&ex->ss_stencil));
615f4bdf6c4SBarry Smith     cnt= 0;
616f4bdf6c4SBarry Smith     for (i= 0; i< (ex->nvars); i++) {
617f4bdf6c4SBarry Smith       for (j= 0; j< 7; j++) {
6188b1f7689SBarry Smith         PetscStackCallStandard(HYPRE_SStructStencilSetEntry,(ex->ss_stencil, cnt, (HYPRE_Int *)offsets[j], i));
619f4bdf6c4SBarry Smith         cnt++;
620f4bdf6c4SBarry Smith       }
621f4bdf6c4SBarry Smith     }
622f4bdf6c4SBarry Smith   }
623f4bdf6c4SBarry Smith 
624f4bdf6c4SBarry Smith   /* create the HYPRE graph */
625fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGraphCreate,(ex->hcomm, ex->ss_grid, &(ex->ss_graph)));
626f4bdf6c4SBarry Smith 
627f4bdf6c4SBarry Smith   /* set the stencil graph. Note that each variable has the same graph. This means that each
628f4bdf6c4SBarry Smith      variable couples to all the other variable and with the same stencil pattern. */
629f4bdf6c4SBarry Smith   for (i= 0; i< (ex->nvars); i++) {
630fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructGraphSetStencil,(ex->ss_graph,part,i,ex->ss_stencil));
631f4bdf6c4SBarry Smith   }
632fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGraphAssemble,(ex->ss_graph));
633f4bdf6c4SBarry Smith 
634f4bdf6c4SBarry Smith   /* create the HYPRE sstruct vectors for rhs and solution */
635fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorCreate,(ex->hcomm,ex->ss_grid,&ex->ss_b));
636fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorCreate,(ex->hcomm,ex->ss_grid,&ex->ss_x));
637fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorInitialize,(ex->ss_b));
638fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorInitialize,(ex->ss_x));
639fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorAssemble,(ex->ss_b));
640fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorAssemble,(ex->ss_x));
641f4bdf6c4SBarry Smith 
642f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
643fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructMatrixCreate,(ex->hcomm,ex->ss_graph,&ex->ss_mat));
644fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGridDestroy,(ex->ss_grid));
645fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructStencilDestroy,(ex->ss_stencil));
646f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
647fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructMatrixInitialize,(ex->ss_mat));
648f4bdf6c4SBarry Smith     ex->needsinitialization = PETSC_FALSE;
649f4bdf6c4SBarry Smith   }
650f4bdf6c4SBarry Smith 
651f4bdf6c4SBarry Smith   /* set the global and local sizes of the matrix */
652f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(da,0,0,0,&nx,&ny,&nz);CHKERRQ(ierr);
653f4bdf6c4SBarry Smith   ierr = MatSetSizes(mat,dof*nx*ny*nz,dof*nx*ny*nz,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
65461710fbeSStefano Zampini   ierr = PetscLayoutSetBlockSize(mat->rmap,dof);CHKERRQ(ierr);
65561710fbeSStefano Zampini   ierr = PetscLayoutSetBlockSize(mat->cmap,dof);CHKERRQ(ierr);
656f4bdf6c4SBarry Smith   ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr);
657f4bdf6c4SBarry Smith   ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr);
65861710fbeSStefano Zampini   mat->preallocated = PETSC_TRUE;
659f4bdf6c4SBarry Smith 
660f4bdf6c4SBarry Smith   if (dim == 3) {
661f4bdf6c4SBarry Smith     mat->ops->setvalueslocal = MatSetValuesLocal_HYPRESStruct_3d;
662f4bdf6c4SBarry Smith     mat->ops->zerorowslocal  = MatZeroRowsLocal_HYPRESStruct_3d;
663f4bdf6c4SBarry Smith     mat->ops->zeroentries    = MatZeroEntries_HYPRESStruct_3d;
6648865f1eaSKarl Rupp 
66561710fbeSStefano Zampini     /* ierr = MatZeroEntries_HYPRESStruct_3d(mat);CHKERRQ(ierr); */
666ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Only support for 3d DMDA currently");
667f4bdf6c4SBarry Smith 
668f4bdf6c4SBarry Smith   /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
6690298fd71SBarry Smith   ierr = MatGetOwnershipRange(mat,&ex->rstart,NULL);CHKERRQ(ierr);
670565245c5SBarry Smith   ierr = DMGetLocalToGlobalMapping(ex->da,&ltog);CHKERRQ(ierr);
671565245c5SBarry Smith   ierr = ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **) &ex->gindices);CHKERRQ(ierr);
672f4bdf6c4SBarry Smith   ierr = DMDAGetGhostCorners(ex->da,0,0,0,&ex->gnx,&ex->gnxgny,&ex->gnxgnygnz);CHKERRQ(ierr);
6738865f1eaSKarl Rupp 
674f4bdf6c4SBarry Smith   ex->gnxgny    *= ex->gnx;
675f4bdf6c4SBarry Smith   ex->gnxgnygnz *= ex->gnxgny;
6768865f1eaSKarl Rupp 
677f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(ex->da,&ex->xs,&ex->ys,&ex->zs,&ex->nx,&ex->ny,&ex->nz);CHKERRQ(ierr);
6788865f1eaSKarl Rupp 
679f4bdf6c4SBarry Smith   ex->nxny   = ex->nx*ex->ny;
680f4bdf6c4SBarry Smith   ex->nxnynz = ex->nz*ex->nxny;
681f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
682f4bdf6c4SBarry Smith }
683f4bdf6c4SBarry Smith 
684f4bdf6c4SBarry Smith PetscErrorCode MatMult_HYPRESStruct(Mat A,Vec x,Vec y)
685f4bdf6c4SBarry Smith {
686f4bdf6c4SBarry Smith   PetscErrorCode    ierr;
687b026d285SBarry Smith   const PetscScalar *xx;
688b026d285SBarry Smith   PetscScalar       *yy;
6894ddd07fcSJed Brown   PetscInt          ilower[3],iupper[3];
690f4bdf6c4SBarry Smith   Mat_HYPRESStruct  *mx     = (Mat_HYPRESStruct*)(A->data);
6914ddd07fcSJed Brown   PetscInt          ordering= mx->dofs_order;
6924ddd07fcSJed Brown   PetscInt          nvars   = mx->nvars;
6934ddd07fcSJed Brown   PetscInt          part    = 0;
6944ddd07fcSJed Brown   PetscInt          size;
6954ddd07fcSJed Brown   PetscInt          i;
696f4bdf6c4SBarry Smith 
697f4bdf6c4SBarry Smith   PetscFunctionBegin;
698f4bdf6c4SBarry Smith   ierr       = DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
699f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
700f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
701f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
702f4bdf6c4SBarry Smith 
703f4bdf6c4SBarry Smith   size= 1;
7048865f1eaSKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i]-ilower[i]+1);
705f4bdf6c4SBarry Smith 
706f4bdf6c4SBarry Smith   /* copy x values over to hypre for variable ordering */
707f4bdf6c4SBarry Smith   if (ordering) {
708fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructVectorSetConstantValues,(mx->ss_b,0.0));
709b026d285SBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
710f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
711b026d285SBarry Smith       PetscStackCallStandard(HYPRE_SStructVectorSetBoxValues,(mx->ss_b,part,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,i,(PetscScalar*)xx+(size*i)));
712f4bdf6c4SBarry Smith     }
713b026d285SBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
714fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructVectorAssemble,(mx->ss_b));
715fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructMatrixMatvec,(1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x));
716f4bdf6c4SBarry Smith 
717f4bdf6c4SBarry Smith     /* copy solution values back to PETSc */
718f4bdf6c4SBarry Smith     ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
719f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
7208b1f7689SBarry Smith       PetscStackCallStandard(HYPRE_SStructVectorGetBoxValues,(mx->ss_x,part,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,i,yy+(size*i)));
721f4bdf6c4SBarry Smith     }
722f4bdf6c4SBarry Smith     ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
723f4bdf6c4SBarry Smith   } else {      /* nodal ordering must be mapped to variable ordering for sys_pfmg */
724f4bdf6c4SBarry Smith     PetscScalar *z;
7254ddd07fcSJed Brown     PetscInt    j, k;
726f4bdf6c4SBarry Smith 
727785e854fSJed Brown     ierr = PetscMalloc1(nvars*size,&z);CHKERRQ(ierr);
728fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructVectorSetConstantValues,(mx->ss_b,0.0));
729b026d285SBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
730f4bdf6c4SBarry Smith 
731f4bdf6c4SBarry Smith     /* transform nodal to hypre's variable ordering for sys_pfmg */
732f4bdf6c4SBarry Smith     for (i= 0; i< size; i++) {
733f4bdf6c4SBarry Smith       k= i*nvars;
7348865f1eaSKarl Rupp       for (j= 0; j< nvars; j++) z[j*size+i]= xx[k+j];
735f4bdf6c4SBarry Smith     }
736f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
7378b1f7689SBarry Smith       PetscStackCallStandard(HYPRE_SStructVectorSetBoxValues,(mx->ss_b,part,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,i,z+(size*i)));
738f4bdf6c4SBarry Smith     }
739b026d285SBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
740fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructVectorAssemble,(mx->ss_b));
741fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructMatrixMatvec,(1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x));
742f4bdf6c4SBarry Smith 
743f4bdf6c4SBarry Smith     /* copy solution values back to PETSc */
744f4bdf6c4SBarry Smith     ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
745f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
7468b1f7689SBarry Smith       PetscStackCallStandard(HYPRE_SStructVectorGetBoxValues,(mx->ss_x,part,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,i,z+(size*i)));
747f4bdf6c4SBarry Smith     }
748f4bdf6c4SBarry Smith     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
749f4bdf6c4SBarry Smith     for (i= 0; i< size; i++) {
750f4bdf6c4SBarry Smith       k= i*nvars;
7518865f1eaSKarl Rupp       for (j= 0; j< nvars; j++) yy[k+j]= z[j*size+i];
752f4bdf6c4SBarry Smith     }
753f4bdf6c4SBarry Smith     ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
754f4bdf6c4SBarry Smith     ierr = PetscFree(z);CHKERRQ(ierr);
755f4bdf6c4SBarry Smith   }
756f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
757f4bdf6c4SBarry Smith }
758f4bdf6c4SBarry Smith 
759f4bdf6c4SBarry Smith PetscErrorCode MatAssemblyEnd_HYPRESStruct(Mat mat,MatAssemblyType mode)
760f4bdf6c4SBarry Smith {
761f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data;
762f4bdf6c4SBarry Smith   PetscErrorCode   ierr;
763f4bdf6c4SBarry Smith 
764f4bdf6c4SBarry Smith   PetscFunctionBegin;
765fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructMatrixAssemble,(ex->ss_mat));
766f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
767f4bdf6c4SBarry Smith }
768f4bdf6c4SBarry Smith 
769f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPRESStruct(Mat mat)
770f4bdf6c4SBarry Smith {
771f4bdf6c4SBarry Smith   PetscFunctionBegin;
772f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
773f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
774f4bdf6c4SBarry Smith }
775f4bdf6c4SBarry Smith 
776f4bdf6c4SBarry Smith PetscErrorCode MatDestroy_HYPRESStruct(Mat mat)
777f4bdf6c4SBarry Smith {
778f4bdf6c4SBarry Smith   Mat_HYPRESStruct       *ex = (Mat_HYPRESStruct*) mat->data;
779f4bdf6c4SBarry Smith   PetscErrorCode         ierr;
780d94fc0b6SBarry Smith   ISLocalToGlobalMapping ltog;
781f4bdf6c4SBarry Smith 
782f4bdf6c4SBarry Smith   PetscFunctionBegin;
783d94fc0b6SBarry Smith   ierr = DMGetLocalToGlobalMapping(ex->da,&ltog);CHKERRQ(ierr);
784d94fc0b6SBarry Smith   ierr = ISLocalToGlobalMappingRestoreIndices(ltog, (const PetscInt **) &ex->gindices);CHKERRQ(ierr);
785fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGraphDestroy,(ex->ss_graph));
786fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructMatrixDestroy,(ex->ss_mat));
787fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorDestroy,(ex->ss_x));
788fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorDestroy,(ex->ss_b));
78959cb773eSBarry Smith   ierr = PetscObjectDereference((PetscObject)ex->da);CHKERRQ(ierr);
79059cb773eSBarry Smith   ierr = MPI_Comm_free(&(ex->hcomm));CHKERRQ(ierr);
79159cb773eSBarry Smith   ierr = PetscFree(ex);CHKERRQ(ierr);
792f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
793f4bdf6c4SBarry Smith }
794f4bdf6c4SBarry Smith 
7958cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_HYPRESStruct(Mat B)
796f4bdf6c4SBarry Smith {
797f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex;
798f4bdf6c4SBarry Smith   PetscErrorCode   ierr;
799f4bdf6c4SBarry Smith 
800f4bdf6c4SBarry Smith   PetscFunctionBegin;
801b00a9115SJed Brown   ierr         = PetscNewLog(B,&ex);CHKERRQ(ierr);
802f4bdf6c4SBarry Smith   B->data      = (void*)ex;
803f4bdf6c4SBarry Smith   B->rmap->bs  = 1;
804f4bdf6c4SBarry Smith   B->assembled = PETSC_FALSE;
805f4bdf6c4SBarry Smith 
806f4bdf6c4SBarry Smith   B->insertmode = NOT_SET_VALUES;
807f4bdf6c4SBarry Smith 
808f4bdf6c4SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_HYPRESStruct;
809f4bdf6c4SBarry Smith   B->ops->mult        = MatMult_HYPRESStruct;
810f4bdf6c4SBarry Smith   B->ops->zeroentries = MatZeroEntries_HYPRESStruct;
811f4bdf6c4SBarry Smith   B->ops->destroy     = MatDestroy_HYPRESStruct;
81259cb773eSBarry Smith   B->ops->setup       = MatSetUp_HYPRESStruct;
813f4bdf6c4SBarry Smith 
814f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
815f4bdf6c4SBarry Smith 
816ce94432eSBarry Smith   ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)B),&(ex->hcomm));CHKERRQ(ierr);
817f4bdf6c4SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATHYPRESSTRUCT);CHKERRQ(ierr);
818f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
819f4bdf6c4SBarry Smith }
820f4bdf6c4SBarry Smith 
821f4bdf6c4SBarry Smith 
822f4bdf6c4SBarry Smith 
823