xref: /petsc/src/dm/impls/da/hypre/mhyp.c (revision 2cf14000413ceaa9c8c88da47cb48e334299226b)
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 
1895452b02SPatrick Sanan    Notes:
1995452b02SPatrick 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 {
30*2cf14000SStefano Zampini   HYPRE_Int         index[3],entries[7];
31*2cf14000SStefano Zampini   PetscInt          i,j,stencil,row;
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;
57*2cf14000SStefano Zampini     index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
58*2cf14000SStefano Zampini     index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
59*2cf14000SStefano Zampini     index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
60f4bdf6c4SBarry Smith     if (addv == ADD_VALUES) {
61*2cf14000SStefano Zampini       PetscStackCallStandard(HYPRE_StructMatrixAddToValues,(ex->hmat,index,ncol,entries,(PetscScalar*)values));
62f4bdf6c4SBarry Smith     } else {
63*2cf14000SStefano Zampini       PetscStackCallStandard(HYPRE_StructMatrixSetValues,(ex->hmat,index,ncol,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;
73*2cf14000SStefano Zampini   HYPRE_Int       index[3],entries[7] = {0,1,2,3,4,5,6};
74*2cf14000SStefano Zampini   PetscInt        row,i;
75f4bdf6c4SBarry Smith   PetscScalar     values[7];
76f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
77f4bdf6c4SBarry Smith 
78f4bdf6c4SBarry Smith   PetscFunctionBegin;
79ce94432eSBarry Smith   if (x && b) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"No support");
80f4bdf6c4SBarry Smith   ierr      = PetscMemzero(values,7*sizeof(PetscScalar));CHKERRQ(ierr);
81f4bdf6c4SBarry Smith   values[3] = d;
82f4bdf6c4SBarry Smith   for (i=0; i<nrow; i++) {
83f4bdf6c4SBarry Smith     row      = ex->gindices[irow[i]] - ex->rstart;
84*2cf14000SStefano Zampini     index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
85*2cf14000SStefano Zampini     index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
86*2cf14000SStefano Zampini     index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
87*2cf14000SStefano Zampini     PetscStackCallStandard(HYPRE_StructMatrixSetValues,(ex->hmat,index,7,entries,values));
88f4bdf6c4SBarry Smith   }
89fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixAssemble,(ex->hmat));
90f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
91f4bdf6c4SBarry Smith }
92f4bdf6c4SBarry Smith 
93f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPREStruct_3d(Mat mat)
94f4bdf6c4SBarry Smith {
95*2cf14000SStefano Zampini   HYPRE_Int       indices[7] = {0,1,2,3,4,5,6};
96f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex        = (Mat_HYPREStruct*) mat->data;
97f4bdf6c4SBarry Smith 
98f4bdf6c4SBarry Smith   PetscFunctionBegin;
99f4bdf6c4SBarry Smith   /* hypre has no public interface to do this */
100*2cf14000SStefano Zampini   PetscStackCallStandard(hypre_StructMatrixClearBoxValues,(ex->hmat,&ex->hbox,7,indices,0,1));
101fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixAssemble,(ex->hmat));
102f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
103f4bdf6c4SBarry Smith }
104f4bdf6c4SBarry Smith 
10559cb773eSBarry Smith static PetscErrorCode  MatSetUp_HYPREStruct(Mat mat)
106f4bdf6c4SBarry Smith {
107f4bdf6c4SBarry Smith   PetscErrorCode         ierr;
108f4bdf6c4SBarry Smith   Mat_HYPREStruct        *ex = (Mat_HYPREStruct*) mat->data;
109*2cf14000SStefano Zampini   HYPRE_Int              sw[6];
110*2cf14000SStefano Zampini   HYPRE_Int              hlower[3],hupper[3];
111*2cf14000SStefano Zampini   PetscInt               dim,dof,psw,nx,ny,nz,ilower[3],iupper[3],ssize,i;
112bff4a2f0SMatthew G. Knepley   DMBoundaryType         px,py,pz;
113f4bdf6c4SBarry Smith   DMDAStencilType        st;
114565245c5SBarry Smith   ISLocalToGlobalMapping ltog;
11559cb773eSBarry Smith   DM                     da;
116f4bdf6c4SBarry Smith 
117f4bdf6c4SBarry Smith   PetscFunctionBegin;
11859cb773eSBarry Smith   ierr   = MatGetDM(mat,(DM*)&da);CHKERRQ(ierr);
119f4bdf6c4SBarry Smith   ex->da = da;
120f4bdf6c4SBarry Smith   ierr   = PetscObjectReference((PetscObject)da);CHKERRQ(ierr);
121f4bdf6c4SBarry Smith 
122*2cf14000SStefano Zampini   ierr = DMDAGetInfo(ex->da,&dim,0,0,0,0,0,0,&dof,&psw,&px,&py,&pz,&st);CHKERRQ(ierr);
123f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(ex->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
124*2cf14000SStefano Zampini 
125*2cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
126f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
127f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
128f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
129*2cf14000SStefano Zampini   hlower[0]  = (HYPRE_Int)ilower[0];
130*2cf14000SStefano Zampini   hlower[1]  = (HYPRE_Int)ilower[1];
131*2cf14000SStefano Zampini   hlower[2]  = (HYPRE_Int)ilower[2];
132*2cf14000SStefano Zampini   hupper[0]  = (HYPRE_Int)iupper[0];
133*2cf14000SStefano Zampini   hupper[1]  = (HYPRE_Int)iupper[1];
134*2cf14000SStefano Zampini   hupper[2]  = (HYPRE_Int)iupper[2];
135f4bdf6c4SBarry Smith 
136f4bdf6c4SBarry Smith   /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
137*2cf14000SStefano Zampini   ex->hbox.imin[0] = hlower[0];
138*2cf14000SStefano Zampini   ex->hbox.imin[1] = hlower[1];
139*2cf14000SStefano Zampini   ex->hbox.imin[2] = hlower[2];
140*2cf14000SStefano Zampini   ex->hbox.imax[0] = hupper[0];
141*2cf14000SStefano Zampini   ex->hbox.imax[1] = hupper[1];
142*2cf14000SStefano Zampini   ex->hbox.imax[2] = hupper[2];
143f4bdf6c4SBarry Smith 
144f4bdf6c4SBarry Smith   /* create the hypre grid object and set its information */
145ce94432eSBarry Smith   if (dof > 1) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Currently only support for scalar problems");
146ce94432eSBarry Smith   if (px || py || pz) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add periodic support by calling HYPRE_StructGridSetPeriodic()");
147fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructGridCreate,(ex->hcomm,dim,&ex->hgrid));
148*2cf14000SStefano Zampini   PetscStackCallStandard(HYPRE_StructGridSetExtents,(ex->hgrid,hlower,hupper));
149fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructGridAssemble,(ex->hgrid));
150f4bdf6c4SBarry Smith 
151*2cf14000SStefano Zampini   sw[5] = sw[4] = sw[3] = sw[2] = sw[1] = sw[0] = psw;
152*2cf14000SStefano Zampini   PetscStackCallStandard(HYPRE_StructGridSetNumGhost,(ex->hgrid,sw));
153f4bdf6c4SBarry Smith 
154f4bdf6c4SBarry Smith   /* create the hypre stencil object and set its information */
155ce94432eSBarry Smith   if (sw[0] > 1) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for wider stencils");
156ce94432eSBarry Smith   if (st == DMDA_STENCIL_BOX) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for box stencils");
157f4bdf6c4SBarry Smith   if (dim == 1) {
158*2cf14000SStefano Zampini     HYPRE_Int offsets[3][1] = {{-1},{0},{1}};
159f4bdf6c4SBarry Smith     ssize = 3;
160fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_StructStencilCreate,(dim,ssize,&ex->hstencil));
161f4bdf6c4SBarry Smith     for (i=0; i<ssize; i++) {
162*2cf14000SStefano Zampini       PetscStackCallStandard(HYPRE_StructStencilSetElement,(ex->hstencil,i,offsets[i]));
163f4bdf6c4SBarry Smith     }
164f4bdf6c4SBarry Smith   } else if (dim == 2) {
165*2cf14000SStefano Zampini     HYPRE_Int offsets[5][2] = {{0,-1},{-1,0},{0,0},{1,0},{0,1}};
166f4bdf6c4SBarry Smith     ssize = 5;
167fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_StructStencilCreate,(dim,ssize,&ex->hstencil));
168f4bdf6c4SBarry Smith     for (i=0; i<ssize; i++) {
169*2cf14000SStefano Zampini       PetscStackCallStandard(HYPRE_StructStencilSetElement,(ex->hstencil,i,offsets[i]));
170f4bdf6c4SBarry Smith     }
171f4bdf6c4SBarry Smith   } else if (dim == 3) {
172*2cf14000SStefano Zampini     HYPRE_Int offsets[7][3] = {{0,0,-1},{0,-1,0},{-1,0,0},{0,0,0},{1,0,0},{0,1,0},{0,0,1}};
173f4bdf6c4SBarry Smith     ssize = 7;
174fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_StructStencilCreate,(dim,ssize,&ex->hstencil));
175f4bdf6c4SBarry Smith     for (i=0; i<ssize; i++) {
176*2cf14000SStefano Zampini       PetscStackCallStandard(HYPRE_StructStencilSetElement,(ex->hstencil,i,offsets[i]));
177f4bdf6c4SBarry Smith     }
178f4bdf6c4SBarry Smith   }
179f4bdf6c4SBarry Smith 
180f4bdf6c4SBarry Smith   /* create the HYPRE vector for rhs and solution */
181fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorCreate,(ex->hcomm,ex->hgrid,&ex->hb));
182fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorCreate,(ex->hcomm,ex->hgrid,&ex->hx));
183fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorInitialize,(ex->hb));
184fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorInitialize,(ex->hx));
185fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorAssemble,(ex->hb));
186fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorAssemble,(ex->hx));
187f4bdf6c4SBarry Smith 
188f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
189fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixCreate,(ex->hcomm,ex->hgrid,ex->hstencil,&ex->hmat));
190fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructGridDestroy,(ex->hgrid));
191fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructStencilDestroy,(ex->hstencil));
192f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
193fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_StructMatrixInitialize,(ex->hmat));
194f4bdf6c4SBarry Smith     ex->needsinitialization = PETSC_FALSE;
195f4bdf6c4SBarry Smith   }
196f4bdf6c4SBarry Smith 
197f4bdf6c4SBarry Smith   /* set the global and local sizes of the matrix */
198f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(da,0,0,0,&nx,&ny,&nz);CHKERRQ(ierr);
199f4bdf6c4SBarry Smith   ierr = MatSetSizes(mat,dof*nx*ny*nz,dof*nx*ny*nz,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
200f4bdf6c4SBarry Smith   ierr = PetscLayoutSetBlockSize(mat->rmap,1);CHKERRQ(ierr);
201f4bdf6c4SBarry Smith   ierr = PetscLayoutSetBlockSize(mat->cmap,1);CHKERRQ(ierr);
202f4bdf6c4SBarry Smith   ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr);
203f4bdf6c4SBarry Smith   ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr);
20459cb773eSBarry Smith   mat->preallocated = PETSC_TRUE;
205f4bdf6c4SBarry Smith 
206f4bdf6c4SBarry Smith   if (dim == 3) {
207f4bdf6c4SBarry Smith     mat->ops->setvalueslocal = MatSetValuesLocal_HYPREStruct_3d;
208f4bdf6c4SBarry Smith     mat->ops->zerorowslocal  = MatZeroRowsLocal_HYPREStruct_3d;
209f4bdf6c4SBarry Smith     mat->ops->zeroentries    = MatZeroEntries_HYPREStruct_3d;
2108865f1eaSKarl Rupp 
21159cb773eSBarry Smith     /*        ierr = MatZeroEntries_HYPREStruct_3d(mat);CHKERRQ(ierr); */
212ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Only support for 3d DMDA currently");
213f4bdf6c4SBarry Smith 
214f4bdf6c4SBarry Smith   /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
2150298fd71SBarry Smith   ierr        = MatGetOwnershipRange(mat,&ex->rstart,NULL);CHKERRQ(ierr);
216565245c5SBarry Smith   ierr        = DMGetLocalToGlobalMapping(ex->da,&ltog);CHKERRQ(ierr);
217565245c5SBarry Smith   ierr        = ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **) &ex->gindices);CHKERRQ(ierr);
218f4bdf6c4SBarry Smith   ierr        = DMDAGetGhostCorners(ex->da,0,0,0,&ex->gnx,&ex->gnxgny,0);CHKERRQ(ierr);
219f4bdf6c4SBarry Smith   ex->gnxgny *= ex->gnx;
220f4bdf6c4SBarry Smith   ierr        = DMDAGetCorners(ex->da,&ex->xs,&ex->ys,&ex->zs,&ex->nx,&ex->ny,0);CHKERRQ(ierr);
221f4bdf6c4SBarry Smith   ex->nxny    = ex->nx*ex->ny;
222f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
223f4bdf6c4SBarry Smith }
224f4bdf6c4SBarry Smith 
225f4bdf6c4SBarry Smith PetscErrorCode MatMult_HYPREStruct(Mat A,Vec x,Vec y)
226f4bdf6c4SBarry Smith {
227f4bdf6c4SBarry Smith   PetscErrorCode    ierr;
228b026d285SBarry Smith   const PetscScalar *xx;
229b026d285SBarry Smith   PetscScalar       *yy;
2304ddd07fcSJed Brown   PetscInt          ilower[3],iupper[3];
231*2cf14000SStefano Zampini   HYPRE_Int         hlower[3],hupper[3];
232f4bdf6c4SBarry Smith   Mat_HYPREStruct   *mx = (Mat_HYPREStruct*)(A->data);
233f4bdf6c4SBarry Smith 
234f4bdf6c4SBarry Smith   PetscFunctionBegin;
235f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
236*2cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
237f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
238f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
239f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
240*2cf14000SStefano Zampini   hlower[0]  = (HYPRE_Int)ilower[0];
241*2cf14000SStefano Zampini   hlower[1]  = (HYPRE_Int)ilower[1];
242*2cf14000SStefano Zampini   hlower[2]  = (HYPRE_Int)ilower[2];
243*2cf14000SStefano Zampini   hupper[0]  = (HYPRE_Int)iupper[0];
244*2cf14000SStefano Zampini   hupper[1]  = (HYPRE_Int)iupper[1];
245*2cf14000SStefano Zampini   hupper[2]  = (HYPRE_Int)iupper[2];
246f4bdf6c4SBarry Smith 
247f4bdf6c4SBarry Smith   /* copy x values over to hypre */
248fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorSetConstantValues,(mx->hb,0.0));
249b026d285SBarry Smith   ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
250*2cf14000SStefano Zampini   PetscStackCallStandard(HYPRE_StructVectorSetBoxValues,(mx->hb,hlower,hupper,(PetscScalar*)xx));
251b026d285SBarry Smith   ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
252fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorAssemble,(mx->hb));
253fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixMatvec,(1.0,mx->hmat,mx->hb,0.0,mx->hx));
254f4bdf6c4SBarry Smith 
255f4bdf6c4SBarry Smith   /* copy solution values back to PETSc */
256f4bdf6c4SBarry Smith   ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
257*2cf14000SStefano Zampini   PetscStackCallStandard(HYPRE_StructVectorGetBoxValues,(mx->hx,hlower,hupper,yy));
258f4bdf6c4SBarry Smith   ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
259f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
260f4bdf6c4SBarry Smith }
261f4bdf6c4SBarry Smith 
262f4bdf6c4SBarry Smith PetscErrorCode MatAssemblyEnd_HYPREStruct(Mat mat,MatAssemblyType mode)
263f4bdf6c4SBarry Smith {
264f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
265f4bdf6c4SBarry Smith 
266f4bdf6c4SBarry Smith   PetscFunctionBegin;
267fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixAssemble,(ex->hmat));
268fd3f9acdSBarry Smith   /* PetscStackCallStandard(HYPRE_StructMatrixPrint,("dummy",ex->hmat,0)); */
269f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
270f4bdf6c4SBarry Smith }
271f4bdf6c4SBarry Smith 
272f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPREStruct(Mat mat)
273f4bdf6c4SBarry Smith {
274f4bdf6c4SBarry Smith   PetscFunctionBegin;
275f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
276f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
277f4bdf6c4SBarry Smith }
278f4bdf6c4SBarry Smith 
279f4bdf6c4SBarry Smith PetscErrorCode MatDestroy_HYPREStruct(Mat mat)
280f4bdf6c4SBarry Smith {
281f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
282f4bdf6c4SBarry Smith   PetscErrorCode  ierr;
283f4bdf6c4SBarry Smith 
284f4bdf6c4SBarry Smith   PetscFunctionBegin;
285fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructMatrixDestroy,(ex->hmat));
286fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorDestroy,(ex->hx));
287fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_StructVectorDestroy,(ex->hb));
28859cb773eSBarry Smith   ierr = PetscObjectDereference((PetscObject)ex->da);CHKERRQ(ierr);
28959cb773eSBarry Smith   ierr = MPI_Comm_free(&(ex->hcomm));CHKERRQ(ierr);
29059cb773eSBarry Smith   ierr = PetscFree(ex);CHKERRQ(ierr);
291f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
292f4bdf6c4SBarry Smith }
293f4bdf6c4SBarry Smith 
2948cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_HYPREStruct(Mat B)
295f4bdf6c4SBarry Smith {
296f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex;
297f4bdf6c4SBarry Smith   PetscErrorCode  ierr;
298f4bdf6c4SBarry Smith 
299f4bdf6c4SBarry Smith   PetscFunctionBegin;
300b00a9115SJed Brown   ierr         = PetscNewLog(B,&ex);CHKERRQ(ierr);
301f4bdf6c4SBarry Smith   B->data      = (void*)ex;
302f4bdf6c4SBarry Smith   B->rmap->bs  = 1;
303f4bdf6c4SBarry Smith   B->assembled = PETSC_FALSE;
304f4bdf6c4SBarry Smith 
305f4bdf6c4SBarry Smith   B->insertmode = NOT_SET_VALUES;
306f4bdf6c4SBarry Smith 
307f4bdf6c4SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_HYPREStruct;
308f4bdf6c4SBarry Smith   B->ops->mult        = MatMult_HYPREStruct;
309f4bdf6c4SBarry Smith   B->ops->zeroentries = MatZeroEntries_HYPREStruct;
310f4bdf6c4SBarry Smith   B->ops->destroy     = MatDestroy_HYPREStruct;
31159cb773eSBarry Smith   B->ops->setup       = MatSetUp_HYPREStruct;
312f4bdf6c4SBarry Smith 
313f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
314f4bdf6c4SBarry Smith 
315ce94432eSBarry Smith   ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)B),&(ex->hcomm));CHKERRQ(ierr);
316f4bdf6c4SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATHYPRESTRUCT);CHKERRQ(ierr);
317f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
318f4bdf6c4SBarry Smith }
319f4bdf6c4SBarry Smith 
320f4bdf6c4SBarry Smith /*MC
321f4bdf6c4SBarry Smith    MATHYPRESSTRUCT - MATHYPRESSTRUCT = "hypresstruct" - A matrix type to be used for parallel sparse matrices
322f4bdf6c4SBarry Smith           based on the hypre HYPRE_SStructMatrix.
323f4bdf6c4SBarry Smith 
324f4bdf6c4SBarry Smith 
325f4bdf6c4SBarry Smith    Level: intermediate
326f4bdf6c4SBarry Smith 
32795452b02SPatrick Sanan    Notes:
32895452b02SPatrick Sanan     Unlike hypre's general semi-struct object consisting of a collection of structured-grid objects and unstructured
329b026d285SBarry Smith           grid objects, we restrict the semi-struct objects to consist of only structured-grid components.
330f4bdf6c4SBarry Smith 
331f4bdf6c4SBarry 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
332f4bdf6c4SBarry Smith           be defined by a DMDA.
333f4bdf6c4SBarry Smith 
33459cb773eSBarry Smith           The matrix needs a DMDA associated with it by either a call to MatSetDM() or if the matrix is obtained from DMCreateMatrix()
335f4bdf6c4SBarry Smith 
336f4bdf6c4SBarry Smith M*/
337f4bdf6c4SBarry Smith 
338f4bdf6c4SBarry Smith PetscErrorCode  MatSetValuesLocal_HYPRESStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
339f4bdf6c4SBarry Smith {
340f4bdf6c4SBarry Smith   PetscErrorCode    ierr;
341*2cf14000SStefano Zampini   HYPRE_Int         index[3],*entries;
342*2cf14000SStefano Zampini   PetscInt          i,j,stencil;
343f4bdf6c4SBarry Smith   const PetscScalar *values = y;
344f4bdf6c4SBarry Smith   Mat_HYPRESStruct  *ex     = (Mat_HYPRESStruct*) mat->data;
345f4bdf6c4SBarry Smith 
3464ddd07fcSJed Brown   PetscInt          part = 0;          /* Petsc sstruct interface only allows 1 part */
3474ddd07fcSJed Brown   PetscInt          ordering;
3484ddd07fcSJed Brown   PetscInt          grid_rank, to_grid_rank;
3494ddd07fcSJed Brown   PetscInt          var_type, to_var_type;
3504ddd07fcSJed Brown   PetscInt          to_var_entry = 0;
3514ddd07fcSJed Brown   PetscInt          nvars= ex->nvars;
352*2cf14000SStefano Zampini   PetscInt          row;
353f4bdf6c4SBarry Smith 
354f4bdf6c4SBarry Smith   PetscFunctionBegin;
355785e854fSJed Brown   ierr     = PetscMalloc1(7*nvars,&entries);CHKERRQ(ierr);
356f4bdf6c4SBarry Smith   ordering = ex->dofs_order;  /* ordering= 0   nodal ordering
357f4bdf6c4SBarry Smith                                            1   variable ordering */
35861710fbeSStefano Zampini   /* stencil entries are ordered by variables: var0_stencil0, var0_stencil1, ..., var0_stencil6, var1_stencil0, var1_stencil1, ...  */
359f4bdf6c4SBarry Smith   if (!ordering) {
360f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
361f4bdf6c4SBarry Smith       grid_rank= irow[i]/nvars;
362f4bdf6c4SBarry Smith       var_type = (irow[i] % nvars);
363f4bdf6c4SBarry Smith 
364f4bdf6c4SBarry Smith       for (j=0; j<ncol; j++) {
365f4bdf6c4SBarry Smith         to_grid_rank= icol[j]/nvars;
366f4bdf6c4SBarry Smith         to_var_type = (icol[j] % nvars);
367f4bdf6c4SBarry Smith 
368f4bdf6c4SBarry Smith         to_var_entry= to_var_entry*7;
369f4bdf6c4SBarry Smith         entries[j]  = to_var_entry;
370f4bdf6c4SBarry Smith 
371f4bdf6c4SBarry Smith         stencil = to_grid_rank-grid_rank;
372f4bdf6c4SBarry Smith         if (!stencil) {
373f4bdf6c4SBarry Smith           entries[j] += 3;
374f4bdf6c4SBarry Smith         } else if (stencil == -1) {
375f4bdf6c4SBarry Smith           entries[j] += 2;
376f4bdf6c4SBarry Smith         } else if (stencil == 1) {
377f4bdf6c4SBarry Smith           entries[j] += 4;
378f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnx) {
379f4bdf6c4SBarry Smith           entries[j] += 1;
380f4bdf6c4SBarry Smith         } else if (stencil == ex->gnx) {
381f4bdf6c4SBarry Smith           entries[j] += 5;
382f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnxgny) {
383f4bdf6c4SBarry Smith           entries[j] += 0;
384f4bdf6c4SBarry Smith         } else if (stencil == ex->gnxgny) {
385f4bdf6c4SBarry Smith           entries[j] += 6;
386f4bdf6c4SBarry 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);
387f4bdf6c4SBarry Smith       }
388f4bdf6c4SBarry Smith 
389f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
390*2cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
391*2cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
392*2cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
393f4bdf6c4SBarry Smith 
394f4bdf6c4SBarry Smith       if (addv == ADD_VALUES) {
395*2cf14000SStefano Zampini         PetscStackCallStandard(HYPRE_SStructMatrixAddToValues,(ex->ss_mat,part,index,var_type,ncol,entries,(PetscScalar*)values));
396f4bdf6c4SBarry Smith       } else {
397*2cf14000SStefano Zampini         PetscStackCallStandard(HYPRE_SStructMatrixSetValues,(ex->ss_mat,part,index,var_type,ncol,entries,(PetscScalar*)values));
398f4bdf6c4SBarry Smith       }
399f4bdf6c4SBarry Smith       values += ncol;
400f4bdf6c4SBarry Smith     }
401f4bdf6c4SBarry Smith   } else {
402f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
403f4bdf6c4SBarry Smith       var_type = irow[i]/(ex->gnxgnygnz);
404f4bdf6c4SBarry Smith       grid_rank= irow[i] - var_type*(ex->gnxgnygnz);
405f4bdf6c4SBarry Smith 
406f4bdf6c4SBarry Smith       for (j=0; j<ncol; j++) {
407f4bdf6c4SBarry Smith         to_var_type = icol[j]/(ex->gnxgnygnz);
408f4bdf6c4SBarry Smith         to_grid_rank= icol[j] - to_var_type*(ex->gnxgnygnz);
409f4bdf6c4SBarry Smith 
410f4bdf6c4SBarry Smith         to_var_entry= to_var_entry*7;
411f4bdf6c4SBarry Smith         entries[j]  = to_var_entry;
412f4bdf6c4SBarry Smith 
413f4bdf6c4SBarry Smith         stencil = to_grid_rank-grid_rank;
414f4bdf6c4SBarry Smith         if (!stencil) {
415f4bdf6c4SBarry Smith           entries[j] += 3;
416f4bdf6c4SBarry Smith         } else if (stencil == -1) {
417f4bdf6c4SBarry Smith           entries[j] += 2;
418f4bdf6c4SBarry Smith         } else if (stencil == 1) {
419f4bdf6c4SBarry Smith           entries[j] += 4;
420f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnx) {
421f4bdf6c4SBarry Smith           entries[j] += 1;
422f4bdf6c4SBarry Smith         } else if (stencil == ex->gnx) {
423f4bdf6c4SBarry Smith           entries[j] += 5;
424f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnxgny) {
425f4bdf6c4SBarry Smith           entries[j] += 0;
426f4bdf6c4SBarry Smith         } else if (stencil == ex->gnxgny) {
427f4bdf6c4SBarry Smith           entries[j] += 6;
428f4bdf6c4SBarry 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);
429f4bdf6c4SBarry Smith       }
430f4bdf6c4SBarry Smith 
431f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
432*2cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
433*2cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
434*2cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
435f4bdf6c4SBarry Smith 
436f4bdf6c4SBarry Smith       if (addv == ADD_VALUES) {
437*2cf14000SStefano Zampini         PetscStackCallStandard(HYPRE_SStructMatrixAddToValues,(ex->ss_mat,part,index,var_type,ncol,entries,(PetscScalar*)values));
438f4bdf6c4SBarry Smith       } else {
439*2cf14000SStefano Zampini         PetscStackCallStandard(HYPRE_SStructMatrixSetValues,(ex->ss_mat,part,index,var_type,ncol,entries,(PetscScalar*)values));
440f4bdf6c4SBarry Smith       }
441f4bdf6c4SBarry Smith       values += ncol;
442f4bdf6c4SBarry Smith     }
443f4bdf6c4SBarry Smith   }
444f4bdf6c4SBarry Smith   ierr = PetscFree(entries);CHKERRQ(ierr);
445f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
446f4bdf6c4SBarry Smith }
447f4bdf6c4SBarry Smith 
448f4bdf6c4SBarry Smith PetscErrorCode  MatZeroRowsLocal_HYPRESStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscScalar d,Vec x,Vec b)
449f4bdf6c4SBarry Smith {
450f4bdf6c4SBarry Smith   PetscErrorCode   ierr;
451*2cf14000SStefano Zampini   HYPRE_Int        index[3],*entries;
452*2cf14000SStefano Zampini   PetscInt         i;
453f4bdf6c4SBarry Smith   PetscScalar      **values;
454f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data;
455f4bdf6c4SBarry Smith 
4564ddd07fcSJed Brown   PetscInt         part     = 0;      /* Petsc sstruct interface only allows 1 part */
4574ddd07fcSJed Brown   PetscInt         ordering = ex->dofs_order;
4584ddd07fcSJed Brown   PetscInt         grid_rank;
4594ddd07fcSJed Brown   PetscInt         var_type;
4604ddd07fcSJed Brown   PetscInt         nvars= ex->nvars;
461*2cf14000SStefano Zampini   PetscInt         row;
462f4bdf6c4SBarry Smith 
463f4bdf6c4SBarry Smith   PetscFunctionBegin;
464ce94432eSBarry Smith   if (x && b) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"No support");
465785e854fSJed Brown   ierr = PetscMalloc1(7*nvars,&entries);CHKERRQ(ierr);
466f4bdf6c4SBarry Smith 
467785e854fSJed Brown   ierr = PetscMalloc1(nvars,&values);CHKERRQ(ierr);
468785e854fSJed Brown   ierr = PetscMalloc1(7*nvars*nvars,&values[0]);CHKERRQ(ierr);
469f4bdf6c4SBarry Smith   for (i=1; i<nvars; i++) {
470f4bdf6c4SBarry Smith     values[i] = values[i-1] + nvars*7;
471f4bdf6c4SBarry Smith   }
472f4bdf6c4SBarry Smith 
473f4bdf6c4SBarry Smith   for (i=0; i< nvars; i++) {
474f4bdf6c4SBarry Smith     ierr           = PetscMemzero(values[i],nvars*7*sizeof(PetscScalar));CHKERRQ(ierr);
475f4bdf6c4SBarry Smith     *(values[i]+3) = d;
476f4bdf6c4SBarry Smith   }
477f4bdf6c4SBarry Smith 
4788865f1eaSKarl Rupp   for (i= 0; i< nvars*7; i++) entries[i] = i;
479f4bdf6c4SBarry Smith 
480f4bdf6c4SBarry Smith   if (!ordering) {
481f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
482f4bdf6c4SBarry Smith       grid_rank = irow[i] / nvars;
483f4bdf6c4SBarry Smith       var_type  =(irow[i] % nvars);
484f4bdf6c4SBarry Smith 
485f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
486*2cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
487*2cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
488*2cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
489*2cf14000SStefano Zampini       PetscStackCallStandard(HYPRE_SStructMatrixSetValues,(ex->ss_mat,part,index,var_type,7*nvars,entries,values[var_type]));
490f4bdf6c4SBarry Smith     }
491f4bdf6c4SBarry Smith   } else {
492f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
493f4bdf6c4SBarry Smith       var_type = irow[i]/(ex->gnxgnygnz);
494f4bdf6c4SBarry Smith       grid_rank= irow[i] - var_type*(ex->gnxgnygnz);
495f4bdf6c4SBarry Smith 
496f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
497*2cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
498*2cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
499*2cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
500*2cf14000SStefano Zampini       PetscStackCallStandard(HYPRE_SStructMatrixSetValues,(ex->ss_mat,part,index,var_type,7*nvars,entries,values[var_type]));
501f4bdf6c4SBarry Smith     }
502f4bdf6c4SBarry Smith   }
503fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructMatrixAssemble,(ex->ss_mat));
504f4bdf6c4SBarry Smith   ierr = PetscFree(values[0]);CHKERRQ(ierr);
505f4bdf6c4SBarry Smith   ierr = PetscFree(values);CHKERRQ(ierr);
506f4bdf6c4SBarry Smith   ierr = PetscFree(entries);CHKERRQ(ierr);
507f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
508f4bdf6c4SBarry Smith }
509f4bdf6c4SBarry Smith 
510f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPRESStruct_3d(Mat mat)
511f4bdf6c4SBarry Smith {
512f4bdf6c4SBarry Smith   PetscErrorCode   ierr;
513f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex  = (Mat_HYPRESStruct*) mat->data;
5144ddd07fcSJed Brown   PetscInt         nvars= ex->nvars;
5154ddd07fcSJed Brown   PetscInt         size;
5164ddd07fcSJed Brown   PetscInt         part= 0;   /* only one part */
517f4bdf6c4SBarry Smith 
518f4bdf6c4SBarry Smith   PetscFunctionBegin;
519f4bdf6c4SBarry 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);
520f4bdf6c4SBarry Smith   {
521*2cf14000SStefano Zampini     HYPRE_Int   i,*entries,iupper[3],ilower[3];
522f4bdf6c4SBarry Smith     PetscScalar *values;
5234ddd07fcSJed Brown 
524f4bdf6c4SBarry Smith 
525f4bdf6c4SBarry Smith     for (i= 0; i< 3; i++) {
526f4bdf6c4SBarry Smith       ilower[i] = ex->hbox.imin[i];
527f4bdf6c4SBarry Smith       iupper[i] = ex->hbox.imax[i];
528f4bdf6c4SBarry Smith     }
529f4bdf6c4SBarry Smith 
530dcca6d9dSJed Brown     ierr = PetscMalloc2(nvars*7,&entries,nvars*7*size,&values);CHKERRQ(ierr);
5318865f1eaSKarl Rupp     for (i= 0; i< nvars*7; i++) entries[i] = i;
532f4bdf6c4SBarry Smith     ierr = PetscMemzero(values,nvars*7*size*sizeof(PetscScalar));CHKERRQ(ierr);
533f4bdf6c4SBarry Smith 
534f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
535*2cf14000SStefano Zampini       PetscStackCallStandard(HYPRE_SStructMatrixSetBoxValues,(ex->ss_mat,part,ilower,iupper,i,nvars*7,entries,values));
536f4bdf6c4SBarry Smith     }
537f4bdf6c4SBarry Smith     ierr = PetscFree2(entries,values);CHKERRQ(ierr);
538f4bdf6c4SBarry Smith   }
539fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructMatrixAssemble,(ex->ss_mat));
540f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
541f4bdf6c4SBarry Smith }
542f4bdf6c4SBarry Smith 
543f4bdf6c4SBarry Smith 
54459cb773eSBarry Smith static PetscErrorCode  MatSetUp_HYPRESStruct(Mat mat)
545f4bdf6c4SBarry Smith {
546f4bdf6c4SBarry Smith   PetscErrorCode         ierr;
547f4bdf6c4SBarry Smith   Mat_HYPRESStruct       *ex = (Mat_HYPRESStruct*) mat->data;
548f4bdf6c4SBarry Smith   PetscInt               dim,dof,sw[3],nx,ny,nz;
5494ddd07fcSJed Brown   PetscInt               ilower[3],iupper[3],ssize,i;
550bff4a2f0SMatthew G. Knepley   DMBoundaryType         px,py,pz;
551f4bdf6c4SBarry Smith   DMDAStencilType        st;
5524ddd07fcSJed Brown   PetscInt               nparts= 1;  /* assuming only one part */
5534ddd07fcSJed Brown   PetscInt               part  = 0;
554565245c5SBarry Smith   ISLocalToGlobalMapping ltog;
55559cb773eSBarry Smith   DM                     da;
556b026d285SBarry Smith 
557f4bdf6c4SBarry Smith   PetscFunctionBegin;
55859cb773eSBarry Smith   ierr   = MatGetDM(mat,(DM*)&da);CHKERRQ(ierr);
559f4bdf6c4SBarry Smith   ex->da = da;
560f4bdf6c4SBarry Smith   ierr   = PetscObjectReference((PetscObject)da);CHKERRQ(ierr);
561f4bdf6c4SBarry Smith 
5627ab44359SJed Brown   ierr       = DMDAGetInfo(ex->da,&dim,0,0,0,0,0,0,&dof,&sw[0],&px,&py,&pz,&st);CHKERRQ(ierr);
563f4bdf6c4SBarry Smith   ierr       = DMDAGetCorners(ex->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
564f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
565f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
566f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
567f4bdf6c4SBarry Smith   /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
568f4bdf6c4SBarry Smith   ex->hbox.imin[0] = ilower[0];
569f4bdf6c4SBarry Smith   ex->hbox.imin[1] = ilower[1];
570f4bdf6c4SBarry Smith   ex->hbox.imin[2] = ilower[2];
571f4bdf6c4SBarry Smith   ex->hbox.imax[0] = iupper[0];
572f4bdf6c4SBarry Smith   ex->hbox.imax[1] = iupper[1];
573f4bdf6c4SBarry Smith   ex->hbox.imax[2] = iupper[2];
574f4bdf6c4SBarry Smith 
575f4bdf6c4SBarry Smith   ex->dofs_order = 0;
576f4bdf6c4SBarry Smith 
577f4bdf6c4SBarry Smith   /* assuming that the same number of dofs on each gridpoint. Also assume all cell-centred based */
578f4bdf6c4SBarry Smith   ex->nvars= dof;
579f4bdf6c4SBarry Smith 
580f4bdf6c4SBarry Smith   /* create the hypre grid object and set its information */
581ce94432eSBarry Smith   if (px || py || pz) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add periodic support by calling HYPRE_SStructGridSetPeriodic()");
582fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGridCreate,(ex->hcomm,dim,nparts,&ex->ss_grid));
583fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGridSetExtents,(ex->ss_grid,part,ex->hbox.imin,ex->hbox.imax));
584f4bdf6c4SBarry Smith   {
585f4bdf6c4SBarry Smith     HYPRE_SStructVariable *vartypes;
586785e854fSJed Brown     ierr = PetscMalloc1(ex->nvars,&vartypes);CHKERRQ(ierr);
5878865f1eaSKarl Rupp     for (i= 0; i< ex->nvars; i++) vartypes[i]= HYPRE_SSTRUCT_VARIABLE_CELL;
588fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructGridSetVariables,(ex->ss_grid, part, ex->nvars,vartypes));
589f4bdf6c4SBarry Smith     ierr = PetscFree(vartypes);CHKERRQ(ierr);
590f4bdf6c4SBarry Smith   }
591fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGridAssemble,(ex->ss_grid));
592f4bdf6c4SBarry Smith 
593f4bdf6c4SBarry Smith   sw[1] = sw[0];
594f4bdf6c4SBarry Smith   sw[2] = sw[1];
595fd3f9acdSBarry Smith   /* PetscStackCallStandard(HYPRE_SStructGridSetNumGhost,(ex->ss_grid,sw)); */
596f4bdf6c4SBarry Smith 
597f4bdf6c4SBarry Smith   /* create the hypre stencil object and set its information */
598ce94432eSBarry Smith   if (sw[0] > 1) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for wider stencils");
599ce94432eSBarry Smith   if (st == DMDA_STENCIL_BOX) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for box stencils");
600f4bdf6c4SBarry Smith 
601f4bdf6c4SBarry Smith   if (dim == 1) {
602*2cf14000SStefano Zampini     HYPRE_Int offsets[3][1] = {{-1},{0},{1}};
6034ddd07fcSJed Brown     PetscInt  j, cnt;
604f4bdf6c4SBarry Smith 
605f4bdf6c4SBarry Smith     ssize = 3*(ex->nvars);
606fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructStencilCreate,(dim,ssize,&ex->ss_stencil));
607f4bdf6c4SBarry Smith     cnt= 0;
608f4bdf6c4SBarry Smith     for (i = 0; i < (ex->nvars); i++) {
609f4bdf6c4SBarry Smith       for (j = 0; j < 3; j++) {
610*2cf14000SStefano Zampini         PetscStackCallStandard(HYPRE_SStructStencilSetEntry,(ex->ss_stencil, cnt, offsets[j], i));
611f4bdf6c4SBarry Smith         cnt++;
612f4bdf6c4SBarry Smith       }
613f4bdf6c4SBarry Smith     }
614f4bdf6c4SBarry Smith   } else if (dim == 2) {
615*2cf14000SStefano Zampini     HYPRE_Int offsets[5][2] = {{0,-1},{-1,0},{0,0},{1,0},{0,1}};
6164ddd07fcSJed Brown     PetscInt  j, cnt;
617f4bdf6c4SBarry Smith 
618f4bdf6c4SBarry Smith     ssize = 5*(ex->nvars);
619fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructStencilCreate,(dim,ssize,&ex->ss_stencil));
620f4bdf6c4SBarry Smith     cnt= 0;
621f4bdf6c4SBarry Smith     for (i= 0; i< (ex->nvars); i++) {
622f4bdf6c4SBarry Smith       for (j= 0; j< 5; j++) {
623*2cf14000SStefano Zampini         PetscStackCallStandard(HYPRE_SStructStencilSetEntry,(ex->ss_stencil, cnt, offsets[j], i));
624f4bdf6c4SBarry Smith         cnt++;
625f4bdf6c4SBarry Smith       }
626f4bdf6c4SBarry Smith     }
627f4bdf6c4SBarry Smith   } else if (dim == 3) {
628*2cf14000SStefano Zampini     HYPRE_Int offsets[7][3] = {{0,0,-1},{0,-1,0},{-1,0,0},{0,0,0},{1,0,0},{0,1,0},{0,0,1}};
6294ddd07fcSJed Brown     PetscInt  j, cnt;
630f4bdf6c4SBarry Smith 
631f4bdf6c4SBarry Smith     ssize = 7*(ex->nvars);
632fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructStencilCreate,(dim,ssize,&ex->ss_stencil));
633f4bdf6c4SBarry Smith     cnt= 0;
634f4bdf6c4SBarry Smith     for (i= 0; i< (ex->nvars); i++) {
635f4bdf6c4SBarry Smith       for (j= 0; j< 7; j++) {
636*2cf14000SStefano Zampini         PetscStackCallStandard(HYPRE_SStructStencilSetEntry,(ex->ss_stencil, cnt, offsets[j], i));
637f4bdf6c4SBarry Smith         cnt++;
638f4bdf6c4SBarry Smith       }
639f4bdf6c4SBarry Smith     }
640f4bdf6c4SBarry Smith   }
641f4bdf6c4SBarry Smith 
642f4bdf6c4SBarry Smith   /* create the HYPRE graph */
643fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGraphCreate,(ex->hcomm, ex->ss_grid, &(ex->ss_graph)));
644f4bdf6c4SBarry Smith 
645f4bdf6c4SBarry Smith   /* set the stencil graph. Note that each variable has the same graph. This means that each
646f4bdf6c4SBarry Smith      variable couples to all the other variable and with the same stencil pattern. */
647f4bdf6c4SBarry Smith   for (i= 0; i< (ex->nvars); i++) {
648fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructGraphSetStencil,(ex->ss_graph,part,i,ex->ss_stencil));
649f4bdf6c4SBarry Smith   }
650fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGraphAssemble,(ex->ss_graph));
651f4bdf6c4SBarry Smith 
652f4bdf6c4SBarry Smith   /* create the HYPRE sstruct vectors for rhs and solution */
653fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorCreate,(ex->hcomm,ex->ss_grid,&ex->ss_b));
654fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorCreate,(ex->hcomm,ex->ss_grid,&ex->ss_x));
655fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorInitialize,(ex->ss_b));
656fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorInitialize,(ex->ss_x));
657fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorAssemble,(ex->ss_b));
658fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorAssemble,(ex->ss_x));
659f4bdf6c4SBarry Smith 
660f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
661fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructMatrixCreate,(ex->hcomm,ex->ss_graph,&ex->ss_mat));
662fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGridDestroy,(ex->ss_grid));
663fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructStencilDestroy,(ex->ss_stencil));
664f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
665fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructMatrixInitialize,(ex->ss_mat));
666f4bdf6c4SBarry Smith     ex->needsinitialization = PETSC_FALSE;
667f4bdf6c4SBarry Smith   }
668f4bdf6c4SBarry Smith 
669f4bdf6c4SBarry Smith   /* set the global and local sizes of the matrix */
670f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(da,0,0,0,&nx,&ny,&nz);CHKERRQ(ierr);
671f4bdf6c4SBarry Smith   ierr = MatSetSizes(mat,dof*nx*ny*nz,dof*nx*ny*nz,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
67261710fbeSStefano Zampini   ierr = PetscLayoutSetBlockSize(mat->rmap,dof);CHKERRQ(ierr);
67361710fbeSStefano Zampini   ierr = PetscLayoutSetBlockSize(mat->cmap,dof);CHKERRQ(ierr);
674f4bdf6c4SBarry Smith   ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr);
675f4bdf6c4SBarry Smith   ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr);
67661710fbeSStefano Zampini   mat->preallocated = PETSC_TRUE;
677f4bdf6c4SBarry Smith 
678f4bdf6c4SBarry Smith   if (dim == 3) {
679f4bdf6c4SBarry Smith     mat->ops->setvalueslocal = MatSetValuesLocal_HYPRESStruct_3d;
680f4bdf6c4SBarry Smith     mat->ops->zerorowslocal  = MatZeroRowsLocal_HYPRESStruct_3d;
681f4bdf6c4SBarry Smith     mat->ops->zeroentries    = MatZeroEntries_HYPRESStruct_3d;
6828865f1eaSKarl Rupp 
68361710fbeSStefano Zampini     /* ierr = MatZeroEntries_HYPRESStruct_3d(mat);CHKERRQ(ierr); */
684ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Only support for 3d DMDA currently");
685f4bdf6c4SBarry Smith 
686f4bdf6c4SBarry Smith   /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
6870298fd71SBarry Smith   ierr = MatGetOwnershipRange(mat,&ex->rstart,NULL);CHKERRQ(ierr);
688565245c5SBarry Smith   ierr = DMGetLocalToGlobalMapping(ex->da,&ltog);CHKERRQ(ierr);
689565245c5SBarry Smith   ierr = ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **) &ex->gindices);CHKERRQ(ierr);
690f4bdf6c4SBarry Smith   ierr = DMDAGetGhostCorners(ex->da,0,0,0,&ex->gnx,&ex->gnxgny,&ex->gnxgnygnz);CHKERRQ(ierr);
6918865f1eaSKarl Rupp 
692f4bdf6c4SBarry Smith   ex->gnxgny    *= ex->gnx;
693f4bdf6c4SBarry Smith   ex->gnxgnygnz *= ex->gnxgny;
6948865f1eaSKarl Rupp 
695f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(ex->da,&ex->xs,&ex->ys,&ex->zs,&ex->nx,&ex->ny,&ex->nz);CHKERRQ(ierr);
6968865f1eaSKarl Rupp 
697f4bdf6c4SBarry Smith   ex->nxny   = ex->nx*ex->ny;
698f4bdf6c4SBarry Smith   ex->nxnynz = ex->nz*ex->nxny;
699f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
700f4bdf6c4SBarry Smith }
701f4bdf6c4SBarry Smith 
702f4bdf6c4SBarry Smith PetscErrorCode MatMult_HYPRESStruct(Mat A,Vec x,Vec y)
703f4bdf6c4SBarry Smith {
704f4bdf6c4SBarry Smith   PetscErrorCode    ierr;
705b026d285SBarry Smith   const PetscScalar *xx;
706b026d285SBarry Smith   PetscScalar       *yy;
707*2cf14000SStefano Zampini   HYPRE_Int         hlower[3],hupper[3];
7084ddd07fcSJed Brown   PetscInt          ilower[3],iupper[3];
709f4bdf6c4SBarry Smith   Mat_HYPRESStruct  *mx     = (Mat_HYPRESStruct*)(A->data);
7104ddd07fcSJed Brown   PetscInt          ordering= mx->dofs_order;
7114ddd07fcSJed Brown   PetscInt          nvars   = mx->nvars;
7124ddd07fcSJed Brown   PetscInt          part    = 0;
7134ddd07fcSJed Brown   PetscInt          size;
7144ddd07fcSJed Brown   PetscInt          i;
715f4bdf6c4SBarry Smith 
716f4bdf6c4SBarry Smith   PetscFunctionBegin;
717f4bdf6c4SBarry Smith   ierr = DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr);
718*2cf14000SStefano Zampini 
719*2cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
720f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
721f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
722f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
723*2cf14000SStefano Zampini   hlower[0]  = (HYPRE_Int)ilower[0];
724*2cf14000SStefano Zampini   hlower[1]  = (HYPRE_Int)ilower[1];
725*2cf14000SStefano Zampini   hlower[2]  = (HYPRE_Int)ilower[2];
726*2cf14000SStefano Zampini   hupper[0]  = (HYPRE_Int)iupper[0];
727*2cf14000SStefano Zampini   hupper[1]  = (HYPRE_Int)iupper[1];
728*2cf14000SStefano Zampini   hupper[2]  = (HYPRE_Int)iupper[2];
729f4bdf6c4SBarry Smith 
730f4bdf6c4SBarry Smith   size= 1;
7318865f1eaSKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i]-ilower[i]+1);
732f4bdf6c4SBarry Smith 
733f4bdf6c4SBarry Smith   /* copy x values over to hypre for variable ordering */
734f4bdf6c4SBarry Smith   if (ordering) {
735fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructVectorSetConstantValues,(mx->ss_b,0.0));
736b026d285SBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
737f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
738*2cf14000SStefano Zampini       PetscStackCallStandard(HYPRE_SStructVectorSetBoxValues,(mx->ss_b,part,hlower,hupper,i,(PetscScalar*)xx+(size*i)));
739f4bdf6c4SBarry Smith     }
740b026d285SBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
741fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructVectorAssemble,(mx->ss_b));
742fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructMatrixMatvec,(1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x));
743f4bdf6c4SBarry Smith 
744f4bdf6c4SBarry Smith     /* copy solution values back to PETSc */
745f4bdf6c4SBarry Smith     ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
746f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
747*2cf14000SStefano Zampini       PetscStackCallStandard(HYPRE_SStructVectorGetBoxValues,(mx->ss_x,part,hlower,hupper,i,yy+(size*i)));
748f4bdf6c4SBarry Smith     }
749f4bdf6c4SBarry Smith     ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
750f4bdf6c4SBarry Smith   } else {      /* nodal ordering must be mapped to variable ordering for sys_pfmg */
751f4bdf6c4SBarry Smith     PetscScalar *z;
7524ddd07fcSJed Brown     PetscInt    j, k;
753f4bdf6c4SBarry Smith 
754785e854fSJed Brown     ierr = PetscMalloc1(nvars*size,&z);CHKERRQ(ierr);
755fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructVectorSetConstantValues,(mx->ss_b,0.0));
756b026d285SBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
757f4bdf6c4SBarry Smith 
758f4bdf6c4SBarry Smith     /* transform nodal to hypre's variable ordering for sys_pfmg */
759f4bdf6c4SBarry Smith     for (i= 0; i< size; i++) {
760f4bdf6c4SBarry Smith       k= i*nvars;
7618865f1eaSKarl Rupp       for (j= 0; j< nvars; j++) z[j*size+i]= xx[k+j];
762f4bdf6c4SBarry Smith     }
763f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
764*2cf14000SStefano Zampini       PetscStackCallStandard(HYPRE_SStructVectorSetBoxValues,(mx->ss_b,part,hlower,hupper,i,z+(size*i)));
765f4bdf6c4SBarry Smith     }
766b026d285SBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
767fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructVectorAssemble,(mx->ss_b));
768fd3f9acdSBarry Smith     PetscStackCallStandard(HYPRE_SStructMatrixMatvec,(1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x));
769f4bdf6c4SBarry Smith 
770f4bdf6c4SBarry Smith     /* copy solution values back to PETSc */
771f4bdf6c4SBarry Smith     ierr = VecGetArray(y,&yy);CHKERRQ(ierr);
772f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
773*2cf14000SStefano Zampini       PetscStackCallStandard(HYPRE_SStructVectorGetBoxValues,(mx->ss_x,part,hlower,hupper,i,z+(size*i)));
774f4bdf6c4SBarry Smith     }
775f4bdf6c4SBarry Smith     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
776f4bdf6c4SBarry Smith     for (i= 0; i< size; i++) {
777f4bdf6c4SBarry Smith       k= i*nvars;
7788865f1eaSKarl Rupp       for (j= 0; j< nvars; j++) yy[k+j]= z[j*size+i];
779f4bdf6c4SBarry Smith     }
780f4bdf6c4SBarry Smith     ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr);
781f4bdf6c4SBarry Smith     ierr = PetscFree(z);CHKERRQ(ierr);
782f4bdf6c4SBarry Smith   }
783f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
784f4bdf6c4SBarry Smith }
785f4bdf6c4SBarry Smith 
786f4bdf6c4SBarry Smith PetscErrorCode MatAssemblyEnd_HYPRESStruct(Mat mat,MatAssemblyType mode)
787f4bdf6c4SBarry Smith {
788f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data;
789f4bdf6c4SBarry Smith 
790f4bdf6c4SBarry Smith   PetscFunctionBegin;
791fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructMatrixAssemble,(ex->ss_mat));
792f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
793f4bdf6c4SBarry Smith }
794f4bdf6c4SBarry Smith 
795f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPRESStruct(Mat mat)
796f4bdf6c4SBarry Smith {
797f4bdf6c4SBarry Smith   PetscFunctionBegin;
798f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
799f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
800f4bdf6c4SBarry Smith }
801f4bdf6c4SBarry Smith 
802f4bdf6c4SBarry Smith PetscErrorCode MatDestroy_HYPRESStruct(Mat mat)
803f4bdf6c4SBarry Smith {
804f4bdf6c4SBarry Smith   Mat_HYPRESStruct       *ex = (Mat_HYPRESStruct*) mat->data;
805f4bdf6c4SBarry Smith   PetscErrorCode         ierr;
806d94fc0b6SBarry Smith   ISLocalToGlobalMapping ltog;
807f4bdf6c4SBarry Smith 
808f4bdf6c4SBarry Smith   PetscFunctionBegin;
809d94fc0b6SBarry Smith   ierr = DMGetLocalToGlobalMapping(ex->da,&ltog);CHKERRQ(ierr);
810d94fc0b6SBarry Smith   ierr = ISLocalToGlobalMappingRestoreIndices(ltog, (const PetscInt **) &ex->gindices);CHKERRQ(ierr);
811fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructGraphDestroy,(ex->ss_graph));
812fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructMatrixDestroy,(ex->ss_mat));
813fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorDestroy,(ex->ss_x));
814fd3f9acdSBarry Smith   PetscStackCallStandard(HYPRE_SStructVectorDestroy,(ex->ss_b));
81559cb773eSBarry Smith   ierr = PetscObjectDereference((PetscObject)ex->da);CHKERRQ(ierr);
81659cb773eSBarry Smith   ierr = MPI_Comm_free(&(ex->hcomm));CHKERRQ(ierr);
81759cb773eSBarry Smith   ierr = PetscFree(ex);CHKERRQ(ierr);
818f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
819f4bdf6c4SBarry Smith }
820f4bdf6c4SBarry Smith 
8218cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_HYPRESStruct(Mat B)
822f4bdf6c4SBarry Smith {
823f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex;
824f4bdf6c4SBarry Smith   PetscErrorCode   ierr;
825f4bdf6c4SBarry Smith 
826f4bdf6c4SBarry Smith   PetscFunctionBegin;
827b00a9115SJed Brown   ierr         = PetscNewLog(B,&ex);CHKERRQ(ierr);
828f4bdf6c4SBarry Smith   B->data      = (void*)ex;
829f4bdf6c4SBarry Smith   B->rmap->bs  = 1;
830f4bdf6c4SBarry Smith   B->assembled = PETSC_FALSE;
831f4bdf6c4SBarry Smith 
832f4bdf6c4SBarry Smith   B->insertmode = NOT_SET_VALUES;
833f4bdf6c4SBarry Smith 
834f4bdf6c4SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_HYPRESStruct;
835f4bdf6c4SBarry Smith   B->ops->mult        = MatMult_HYPRESStruct;
836f4bdf6c4SBarry Smith   B->ops->zeroentries = MatZeroEntries_HYPRESStruct;
837f4bdf6c4SBarry Smith   B->ops->destroy     = MatDestroy_HYPRESStruct;
83859cb773eSBarry Smith   B->ops->setup       = MatSetUp_HYPRESStruct;
839f4bdf6c4SBarry Smith 
840f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
841f4bdf6c4SBarry Smith 
842ce94432eSBarry Smith   ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)B),&(ex->hcomm));CHKERRQ(ierr);
843f4bdf6c4SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATHYPRESSTRUCT);CHKERRQ(ierr);
844f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
845f4bdf6c4SBarry Smith }
846f4bdf6c4SBarry Smith 
847