xref: /petsc/src/dm/impls/da/hypre/mhyp.c (revision e33d7e9514ae79a8ab458c2f6258f19c2b6e7e24)
1f4bdf6c4SBarry Smith 
2f4bdf6c4SBarry Smith /*
3f4bdf6c4SBarry Smith     Creates hypre ijmatrix from PETSc matrix
4f4bdf6c4SBarry Smith */
5c6db04a5SJed Brown #include <petscsys.h>
639accc25SStefano Zampini #include <petsc/private/petschypre.h>
7af0996ceSBarry Smith #include <petsc/private/matimpl.h>
8c6db04a5SJed Brown #include <petscdmda.h>                /*I "petscdmda.h" I*/
9c6db04a5SJed Brown #include <../src/dm/impls/da/hypre/mhyp.h>
10f4bdf6c4SBarry Smith 
11f4bdf6c4SBarry Smith /* -----------------------------------------------------------------------------------------------------------------*/
12f4bdf6c4SBarry Smith 
13f4bdf6c4SBarry Smith /*MC
14f4bdf6c4SBarry Smith    MATHYPRESTRUCT - MATHYPRESTRUCT = "hyprestruct" - A matrix type to be used for parallel sparse matrices
15f4bdf6c4SBarry Smith           based on the hypre HYPRE_StructMatrix.
16f4bdf6c4SBarry Smith 
17f4bdf6c4SBarry Smith    Level: intermediate
18f4bdf6c4SBarry Smith 
1995452b02SPatrick Sanan    Notes:
2095452b02SPatrick Sanan     Unlike the more general support for blocks in hypre this allows only one block per process and requires the block
21f4bdf6c4SBarry Smith           be defined by a DMDA.
22f4bdf6c4SBarry Smith 
2359cb773eSBarry Smith           The matrix needs a DMDA associated with it by either a call to MatSetDM() or if the matrix is obtained from DMCreateMatrix()
24f4bdf6c4SBarry Smith 
25db781477SPatrick Sanan .seealso: `MatCreate()`, `PCPFMG`, `MatSetDM()`, `DMCreateMatrix()`
26f4bdf6c4SBarry Smith M*/
27f4bdf6c4SBarry Smith 
28f4bdf6c4SBarry Smith PetscErrorCode  MatSetValuesLocal_HYPREStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
29f4bdf6c4SBarry Smith {
3076a007c6Sftrigaux   HYPRE_Int       index[3],entries[9];
312cf14000SStefano Zampini   PetscInt        i,j,stencil,row;
3239accc25SStefano Zampini   HYPRE_Complex   *values = (HYPRE_Complex*)y;
33f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex     = (Mat_HYPREStruct*) mat->data;
34f4bdf6c4SBarry Smith 
35f4bdf6c4SBarry Smith   PetscFunctionBegin;
3676a007c6Sftrigaux   PetscCheck(ncol <= 9,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"ncol %" PetscInt_FMT " > 9 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;
5463a3b9bcSJacob Faibussowitsch       } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row %" PetscInt_FMT " local column %" PetscInt_FMT " have bad stencil %" PetscInt_FMT,irow[i],icol[j],stencil);
55f4bdf6c4SBarry Smith     }
56f4bdf6c4SBarry Smith     row      = ex->gindices[irow[i]] - ex->rstart;
572cf14000SStefano Zampini     index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
582cf14000SStefano Zampini     index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
592cf14000SStefano Zampini     index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
60792fecdfSBarry Smith     if (addv == ADD_VALUES) PetscCallExternal(HYPRE_StructMatrixAddToValues,ex->hmat,index,ncol,entries,values);
61792fecdfSBarry Smith     else PetscCallExternal(HYPRE_StructMatrixSetValues,ex->hmat,index,ncol,entries,values);
62f4bdf6c4SBarry Smith     values += ncol;
63f4bdf6c4SBarry Smith   }
64f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
65f4bdf6c4SBarry Smith }
66f4bdf6c4SBarry Smith 
67f4bdf6c4SBarry Smith PetscErrorCode  MatZeroRowsLocal_HYPREStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscScalar d,Vec x,Vec b)
68f4bdf6c4SBarry Smith {
692cf14000SStefano Zampini   HYPRE_Int       index[3],entries[7] = {0,1,2,3,4,5,6};
702cf14000SStefano Zampini   PetscInt        row,i;
7139accc25SStefano Zampini   HYPRE_Complex   values[7];
72f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
73f4bdf6c4SBarry Smith 
74f4bdf6c4SBarry Smith   PetscFunctionBegin;
7508401ef6SPierre Jolivet   PetscCheck(!x || !b,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"No support");
769566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(values,7));
779566063dSJacob Faibussowitsch   PetscCall(PetscHYPREScalarCast(d,&values[3]));
78f4bdf6c4SBarry Smith   for (i=0; i<nrow; i++) {
79f4bdf6c4SBarry Smith     row      = ex->gindices[irow[i]] - ex->rstart;
802cf14000SStefano Zampini     index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
812cf14000SStefano Zampini     index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
822cf14000SStefano Zampini     index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
83792fecdfSBarry Smith     PetscCallExternal(HYPRE_StructMatrixSetValues,ex->hmat,index,7,entries,values);
84f4bdf6c4SBarry Smith   }
85792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixAssemble,ex->hmat);
86f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
87f4bdf6c4SBarry Smith }
88f4bdf6c4SBarry Smith 
89f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPREStruct_3d(Mat mat)
90f4bdf6c4SBarry Smith {
912cf14000SStefano Zampini   HYPRE_Int       indices[7] = {0,1,2,3,4,5,6};
92f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex        = (Mat_HYPREStruct*) mat->data;
93f4bdf6c4SBarry Smith 
94f4bdf6c4SBarry Smith   PetscFunctionBegin;
95f4bdf6c4SBarry Smith   /* hypre has no public interface to do this */
96792fecdfSBarry Smith   PetscCallExternal(hypre_StructMatrixClearBoxValues,ex->hmat,&ex->hbox,7,indices,0,1);
97792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixAssemble,ex->hmat);
98f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
99f4bdf6c4SBarry Smith }
100f4bdf6c4SBarry Smith 
10159cb773eSBarry Smith static PetscErrorCode  MatSetUp_HYPREStruct(Mat mat)
102f4bdf6c4SBarry Smith {
103f4bdf6c4SBarry Smith   Mat_HYPREStruct        *ex = (Mat_HYPREStruct*) mat->data;
1042cf14000SStefano Zampini   HYPRE_Int              sw[6];
105*e33d7e95Sftrigaux   HYPRE_Int              hlower[3],hupper[3],period[3]={0,0,0};
106*e33d7e95Sftrigaux   PetscInt               dim,dof,psw,Nx,Ny,Nz,nx,ny,nz,ilower[3],iupper[3],ssize,i;
107bff4a2f0SMatthew G. Knepley   DMBoundaryType         px,py,pz;
108f4bdf6c4SBarry Smith   DMDAStencilType        st;
109565245c5SBarry Smith   ISLocalToGlobalMapping ltog;
11059cb773eSBarry Smith   DM                     da;
111f4bdf6c4SBarry Smith 
112f4bdf6c4SBarry Smith   PetscFunctionBegin;
1139566063dSJacob Faibussowitsch   PetscCall(MatGetDM(mat,(DM*)&da));
114f4bdf6c4SBarry Smith   ex->da = da;
1159566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)da));
116f4bdf6c4SBarry Smith 
117*e33d7e95Sftrigaux   PetscCall(DMDAGetInfo(ex->da,&dim,&Nx,&Ny,&Nz,0,0,0,&dof,&psw,&px,&py,&pz,&st));
1189566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]));
1192cf14000SStefano Zampini 
1202cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
121f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
122f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
123f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
1242cf14000SStefano Zampini   hlower[0]  = (HYPRE_Int)ilower[0];
1252cf14000SStefano Zampini   hlower[1]  = (HYPRE_Int)ilower[1];
1262cf14000SStefano Zampini   hlower[2]  = (HYPRE_Int)ilower[2];
1272cf14000SStefano Zampini   hupper[0]  = (HYPRE_Int)iupper[0];
1282cf14000SStefano Zampini   hupper[1]  = (HYPRE_Int)iupper[1];
1292cf14000SStefano Zampini   hupper[2]  = (HYPRE_Int)iupper[2];
130f4bdf6c4SBarry Smith 
131f4bdf6c4SBarry Smith   /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
1322cf14000SStefano Zampini   ex->hbox.imin[0] = hlower[0];
1332cf14000SStefano Zampini   ex->hbox.imin[1] = hlower[1];
1342cf14000SStefano Zampini   ex->hbox.imin[2] = hlower[2];
1352cf14000SStefano Zampini   ex->hbox.imax[0] = hupper[0];
1362cf14000SStefano Zampini   ex->hbox.imax[1] = hupper[1];
1372cf14000SStefano Zampini   ex->hbox.imax[2] = hupper[2];
138f4bdf6c4SBarry Smith 
139f4bdf6c4SBarry Smith   /* create the hypre grid object and set its information */
14008401ef6SPierre Jolivet   PetscCheck(dof <= 1,PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Currently only support for scalar problems");
141*e33d7e95Sftrigaux   if (px || py || pz) {
142*e33d7e95Sftrigaux     if (px==DM_BOUNDARY_PERIODIC) period[0] = (HYPRE_Int) Nx;
143*e33d7e95Sftrigaux     if (py==DM_BOUNDARY_PERIODIC) period[1] = (HYPRE_Int) Ny;
144*e33d7e95Sftrigaux     if (pz==DM_BOUNDARY_PERIODIC) period[2] = (HYPRE_Int) Nz;
145*e33d7e95Sftrigaux   }
146792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructGridCreate,ex->hcomm,dim,&ex->hgrid);
147792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructGridSetExtents,ex->hgrid,hlower,hupper);
148*e33d7e95Sftrigaux   PetscCallExternal(HYPRE_StructGridSetPeriodic,ex->hgrid,period);
149792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructGridAssemble,ex->hgrid);
150f4bdf6c4SBarry Smith 
1512cf14000SStefano Zampini   sw[5] = sw[4] = sw[3] = sw[2] = sw[1] = sw[0] = psw;
152792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructGridSetNumGhost,ex->hgrid,sw);
153f4bdf6c4SBarry Smith 
154f4bdf6c4SBarry Smith   /* create the hypre stencil object and set its information */
15508401ef6SPierre Jolivet   PetscCheck(sw[0] <= 1,PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for wider stencils");
15608401ef6SPierre Jolivet   PetscCheck(st != DMDA_STENCIL_BOX,PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for box stencils");
157f4bdf6c4SBarry Smith   if (dim == 1) {
1582cf14000SStefano Zampini     HYPRE_Int offsets[3][1] = {{-1},{0},{1}};
159f4bdf6c4SBarry Smith     ssize = 3;
160792fecdfSBarry Smith     PetscCallExternal(HYPRE_StructStencilCreate,dim,ssize,&ex->hstencil);
161f4bdf6c4SBarry Smith     for (i=0; i<ssize; i++) {
162792fecdfSBarry Smith       PetscCallExternal(HYPRE_StructStencilSetElement,ex->hstencil,i,offsets[i]);
163f4bdf6c4SBarry Smith     }
164f4bdf6c4SBarry Smith   } else if (dim == 2) {
1652cf14000SStefano Zampini     HYPRE_Int offsets[5][2] = {{0,-1},{-1,0},{0,0},{1,0},{0,1}};
166f4bdf6c4SBarry Smith     ssize = 5;
167792fecdfSBarry Smith     PetscCallExternal(HYPRE_StructStencilCreate,dim,ssize,&ex->hstencil);
168f4bdf6c4SBarry Smith     for (i=0; i<ssize; i++) {
169792fecdfSBarry Smith       PetscCallExternal(HYPRE_StructStencilSetElement,ex->hstencil,i,offsets[i]);
170f4bdf6c4SBarry Smith     }
171f4bdf6c4SBarry Smith   } else if (dim == 3) {
1722cf14000SStefano Zampini     HYPRE_Int offsets[7][3] = {{0,0,-1},{0,-1,0},{-1,0,0},{0,0,0},{1,0,0},{0,1,0},{0,0,1}};
173f4bdf6c4SBarry Smith     ssize = 7;
174792fecdfSBarry Smith     PetscCallExternal(HYPRE_StructStencilCreate,dim,ssize,&ex->hstencil);
175f4bdf6c4SBarry Smith     for (i=0; i<ssize; i++) {
176792fecdfSBarry Smith       PetscCallExternal(HYPRE_StructStencilSetElement,ex->hstencil,i,offsets[i]);
177f4bdf6c4SBarry Smith     }
178f4bdf6c4SBarry Smith   }
179f4bdf6c4SBarry Smith 
180f4bdf6c4SBarry Smith   /* create the HYPRE vector for rhs and solution */
181792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorCreate,ex->hcomm,ex->hgrid,&ex->hb);
182792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorCreate,ex->hcomm,ex->hgrid,&ex->hx);
183792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorInitialize,ex->hb);
184792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorInitialize,ex->hx);
185792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble,ex->hb);
186792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble,ex->hx);
187f4bdf6c4SBarry Smith 
188f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
189792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixCreate,ex->hcomm,ex->hgrid,ex->hstencil,&ex->hmat);
190792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructGridDestroy,ex->hgrid);
191792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructStencilDestroy,ex->hstencil);
192f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
193792fecdfSBarry Smith     PetscCallExternal(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 */
1989566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da,0,0,0,&nx,&ny,&nz));
1999566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat,dof*nx*ny*nz,dof*nx*ny*nz,PETSC_DECIDE,PETSC_DECIDE));
2009566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->rmap,1));
2019566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->cmap,1));
2029566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->rmap));
2039566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->cmap));
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 
2119566063dSJacob Faibussowitsch     /*        PetscCall(MatZeroEntries_HYPREStruct_3d(mat)); */
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 */
2159566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(mat,&ex->rstart,NULL));
2169566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(ex->da,&ltog));
2179566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **) &ex->gindices));
2189566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(ex->da,0,0,0,&ex->gnx,&ex->gnxgny,0));
219f4bdf6c4SBarry Smith   ex->gnxgny *= ex->gnx;
2209566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da,&ex->xs,&ex->ys,&ex->zs,&ex->nx,&ex->ny,0));
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 {
227b026d285SBarry Smith   const PetscScalar *xx;
228b026d285SBarry Smith   PetscScalar       *yy;
2294ddd07fcSJed Brown   PetscInt          ilower[3],iupper[3];
2302cf14000SStefano Zampini   HYPRE_Int         hlower[3],hupper[3];
231f4bdf6c4SBarry Smith   Mat_HYPREStruct   *mx = (Mat_HYPREStruct*)(A->data);
232f4bdf6c4SBarry Smith 
233f4bdf6c4SBarry Smith   PetscFunctionBegin;
2349566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]));
2352cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
236f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
237f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
238f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
2392cf14000SStefano Zampini   hlower[0]  = (HYPRE_Int)ilower[0];
2402cf14000SStefano Zampini   hlower[1]  = (HYPRE_Int)ilower[1];
2412cf14000SStefano Zampini   hlower[2]  = (HYPRE_Int)ilower[2];
2422cf14000SStefano Zampini   hupper[0]  = (HYPRE_Int)iupper[0];
2432cf14000SStefano Zampini   hupper[1]  = (HYPRE_Int)iupper[1];
2442cf14000SStefano Zampini   hupper[2]  = (HYPRE_Int)iupper[2];
245f4bdf6c4SBarry Smith 
246f4bdf6c4SBarry Smith   /* copy x values over to hypre */
247792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetConstantValues,mx->hb,0.0);
2489566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x,&xx));
249792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetBoxValues,mx->hb,hlower,hupper,(HYPRE_Complex*)xx);
2509566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x,&xx));
251792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble,mx->hb);
252792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixMatvec,1.0,mx->hmat,mx->hb,0.0,mx->hx);
253f4bdf6c4SBarry Smith 
254f4bdf6c4SBarry Smith   /* copy solution values back to PETSc */
2559566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y,&yy));
256792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorGetBoxValues,mx->hx,hlower,hupper,(HYPRE_Complex*)yy);
2579566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y,&yy));
258f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
259f4bdf6c4SBarry Smith }
260f4bdf6c4SBarry Smith 
261f4bdf6c4SBarry Smith PetscErrorCode MatAssemblyEnd_HYPREStruct(Mat mat,MatAssemblyType mode)
262f4bdf6c4SBarry Smith {
263f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
264f4bdf6c4SBarry Smith 
265f4bdf6c4SBarry Smith   PetscFunctionBegin;
266792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixAssemble,ex->hmat);
267792fecdfSBarry Smith   /* PetscCallExternal(HYPRE_StructMatrixPrint,"dummy",ex->hmat,0); */
268f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
269f4bdf6c4SBarry Smith }
270f4bdf6c4SBarry Smith 
271f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPREStruct(Mat mat)
272f4bdf6c4SBarry Smith {
273f4bdf6c4SBarry Smith   PetscFunctionBegin;
274f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
275f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
276f4bdf6c4SBarry Smith }
277f4bdf6c4SBarry Smith 
278f4bdf6c4SBarry Smith PetscErrorCode MatDestroy_HYPREStruct(Mat mat)
279f4bdf6c4SBarry Smith {
280f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
281f4bdf6c4SBarry Smith 
282f4bdf6c4SBarry Smith   PetscFunctionBegin;
283792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixDestroy,ex->hmat);
284792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorDestroy,ex->hx);
285792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorDestroy,ex->hb);
2869566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)ex->da));
2879566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&(ex->hcomm)));
2889566063dSJacob Faibussowitsch   PetscCall(PetscFree(ex));
289f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
290f4bdf6c4SBarry Smith }
291f4bdf6c4SBarry Smith 
2928cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_HYPREStruct(Mat B)
293f4bdf6c4SBarry Smith {
294f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex;
295f4bdf6c4SBarry Smith 
296f4bdf6c4SBarry Smith   PetscFunctionBegin;
2979566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(B,&ex));
298f4bdf6c4SBarry Smith   B->data      = (void*)ex;
299f4bdf6c4SBarry Smith   B->rmap->bs  = 1;
300f4bdf6c4SBarry Smith   B->assembled = PETSC_FALSE;
301f4bdf6c4SBarry Smith 
302f4bdf6c4SBarry Smith   B->insertmode = NOT_SET_VALUES;
303f4bdf6c4SBarry Smith 
304f4bdf6c4SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_HYPREStruct;
305f4bdf6c4SBarry Smith   B->ops->mult        = MatMult_HYPREStruct;
306f4bdf6c4SBarry Smith   B->ops->zeroentries = MatZeroEntries_HYPREStruct;
307f4bdf6c4SBarry Smith   B->ops->destroy     = MatDestroy_HYPREStruct;
30859cb773eSBarry Smith   B->ops->setup       = MatSetUp_HYPREStruct;
309f4bdf6c4SBarry Smith 
310f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
311f4bdf6c4SBarry Smith 
3129566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_dup(PetscObjectComm((PetscObject)B),&(ex->hcomm)));
3139566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B,MATHYPRESTRUCT));
314f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
315f4bdf6c4SBarry Smith }
316f4bdf6c4SBarry Smith 
317f4bdf6c4SBarry Smith /*MC
318f4bdf6c4SBarry Smith    MATHYPRESSTRUCT - MATHYPRESSTRUCT = "hypresstruct" - A matrix type to be used for parallel sparse matrices
319f4bdf6c4SBarry Smith           based on the hypre HYPRE_SStructMatrix.
320f4bdf6c4SBarry Smith 
321f4bdf6c4SBarry Smith    Level: intermediate
322f4bdf6c4SBarry Smith 
32395452b02SPatrick Sanan    Notes:
32495452b02SPatrick Sanan     Unlike hypre's general semi-struct object consisting of a collection of structured-grid objects and unstructured
325b026d285SBarry Smith           grid objects, we restrict the semi-struct objects to consist of only structured-grid components.
326f4bdf6c4SBarry Smith 
327f4bdf6c4SBarry 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
328f4bdf6c4SBarry Smith           be defined by a DMDA.
329f4bdf6c4SBarry Smith 
33059cb773eSBarry Smith           The matrix needs a DMDA associated with it by either a call to MatSetDM() or if the matrix is obtained from DMCreateMatrix()
331f4bdf6c4SBarry Smith 
332f4bdf6c4SBarry Smith M*/
333f4bdf6c4SBarry Smith 
334f4bdf6c4SBarry Smith PetscErrorCode  MatSetValuesLocal_HYPRESStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
335f4bdf6c4SBarry Smith {
3362cf14000SStefano Zampini   HYPRE_Int         index[3],*entries;
3372cf14000SStefano Zampini   PetscInt          i,j,stencil;
33839accc25SStefano Zampini   HYPRE_Complex     *values = (HYPRE_Complex*)y;
339f4bdf6c4SBarry Smith   Mat_HYPRESStruct  *ex     = (Mat_HYPRESStruct*) mat->data;
340f4bdf6c4SBarry Smith 
3414ddd07fcSJed Brown   PetscInt          part = 0;          /* Petsc sstruct interface only allows 1 part */
3424ddd07fcSJed Brown   PetscInt          ordering;
3434ddd07fcSJed Brown   PetscInt          grid_rank, to_grid_rank;
3444ddd07fcSJed Brown   PetscInt          var_type, to_var_type;
3454ddd07fcSJed Brown   PetscInt          to_var_entry = 0;
3464ddd07fcSJed Brown   PetscInt          nvars= ex->nvars;
3472cf14000SStefano Zampini   PetscInt          row;
348f4bdf6c4SBarry Smith 
349f4bdf6c4SBarry Smith   PetscFunctionBegin;
3509566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(7*nvars,&entries));
351f4bdf6c4SBarry Smith   ordering = ex->dofs_order;  /* ordering= 0   nodal ordering
352f4bdf6c4SBarry Smith                                            1   variable ordering */
35361710fbeSStefano Zampini   /* stencil entries are ordered by variables: var0_stencil0, var0_stencil1, ..., var0_stencil6, var1_stencil0, var1_stencil1, ...  */
354f4bdf6c4SBarry Smith   if (!ordering) {
355f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
356f4bdf6c4SBarry Smith       grid_rank= irow[i]/nvars;
357f4bdf6c4SBarry Smith       var_type = (irow[i] % nvars);
358f4bdf6c4SBarry Smith 
359f4bdf6c4SBarry Smith       for (j=0; j<ncol; j++) {
360f4bdf6c4SBarry Smith         to_grid_rank= icol[j]/nvars;
361f4bdf6c4SBarry Smith         to_var_type = (icol[j] % nvars);
362f4bdf6c4SBarry Smith 
363f4bdf6c4SBarry Smith         to_var_entry= to_var_entry*7;
364f4bdf6c4SBarry Smith         entries[j]  = to_var_entry;
365f4bdf6c4SBarry Smith 
366f4bdf6c4SBarry Smith         stencil = to_grid_rank-grid_rank;
367f4bdf6c4SBarry Smith         if (!stencil) {
368f4bdf6c4SBarry Smith           entries[j] += 3;
369f4bdf6c4SBarry Smith         } else if (stencil == -1) {
370f4bdf6c4SBarry Smith           entries[j] += 2;
371f4bdf6c4SBarry Smith         } else if (stencil == 1) {
372f4bdf6c4SBarry Smith           entries[j] += 4;
373f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnx) {
374f4bdf6c4SBarry Smith           entries[j] += 1;
375f4bdf6c4SBarry Smith         } else if (stencil == ex->gnx) {
376f4bdf6c4SBarry Smith           entries[j] += 5;
377f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnxgny) {
378f4bdf6c4SBarry Smith           entries[j] += 0;
379f4bdf6c4SBarry Smith         } else if (stencil == ex->gnxgny) {
380f4bdf6c4SBarry Smith           entries[j] += 6;
38163a3b9bcSJacob Faibussowitsch         } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row %" PetscInt_FMT " local column %" PetscInt_FMT " have bad stencil %" PetscInt_FMT,irow[i],icol[j],stencil);
382f4bdf6c4SBarry Smith       }
383f4bdf6c4SBarry Smith 
384f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
3852cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
3862cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
3872cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
388f4bdf6c4SBarry Smith 
389792fecdfSBarry Smith       if (addv == ADD_VALUES) PetscCallExternal(HYPRE_SStructMatrixAddToValues,ex->ss_mat,part,index,var_type,ncol,entries,values);
390792fecdfSBarry Smith       else PetscCallExternal(HYPRE_SStructMatrixSetValues,ex->ss_mat,part,index,var_type,ncol,entries,values);
391f4bdf6c4SBarry Smith       values += ncol;
392f4bdf6c4SBarry Smith     }
393f4bdf6c4SBarry Smith   } else {
394f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
395f4bdf6c4SBarry Smith       var_type = irow[i]/(ex->gnxgnygnz);
396f4bdf6c4SBarry Smith       grid_rank= irow[i] - var_type*(ex->gnxgnygnz);
397f4bdf6c4SBarry Smith 
398f4bdf6c4SBarry Smith       for (j=0; j<ncol; j++) {
399f4bdf6c4SBarry Smith         to_var_type = icol[j]/(ex->gnxgnygnz);
400f4bdf6c4SBarry Smith         to_grid_rank= icol[j] - to_var_type*(ex->gnxgnygnz);
401f4bdf6c4SBarry Smith 
402f4bdf6c4SBarry Smith         to_var_entry= to_var_entry*7;
403f4bdf6c4SBarry Smith         entries[j]  = to_var_entry;
404f4bdf6c4SBarry Smith 
405f4bdf6c4SBarry Smith         stencil = to_grid_rank-grid_rank;
406f4bdf6c4SBarry Smith         if (!stencil) {
407f4bdf6c4SBarry Smith           entries[j] += 3;
408f4bdf6c4SBarry Smith         } else if (stencil == -1) {
409f4bdf6c4SBarry Smith           entries[j] += 2;
410f4bdf6c4SBarry Smith         } else if (stencil == 1) {
411f4bdf6c4SBarry Smith           entries[j] += 4;
412f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnx) {
413f4bdf6c4SBarry Smith           entries[j] += 1;
414f4bdf6c4SBarry Smith         } else if (stencil == ex->gnx) {
415f4bdf6c4SBarry Smith           entries[j] += 5;
416f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnxgny) {
417f4bdf6c4SBarry Smith           entries[j] += 0;
418f4bdf6c4SBarry Smith         } else if (stencil == ex->gnxgny) {
419f4bdf6c4SBarry Smith           entries[j] += 6;
42063a3b9bcSJacob Faibussowitsch         } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row %" PetscInt_FMT " local column %" PetscInt_FMT " have bad stencil %" PetscInt_FMT,irow[i],icol[j],stencil);
421f4bdf6c4SBarry Smith       }
422f4bdf6c4SBarry Smith 
423f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
4242cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
4252cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
4262cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
427f4bdf6c4SBarry Smith 
428792fecdfSBarry Smith       if (addv == ADD_VALUES) PetscCallExternal(HYPRE_SStructMatrixAddToValues,ex->ss_mat,part,index,var_type,ncol,entries,values);
429792fecdfSBarry Smith       else PetscCallExternal(HYPRE_SStructMatrixSetValues,ex->ss_mat,part,index,var_type,ncol,entries,values);
430f4bdf6c4SBarry Smith       values += ncol;
431f4bdf6c4SBarry Smith     }
432f4bdf6c4SBarry Smith   }
4339566063dSJacob Faibussowitsch   PetscCall(PetscFree(entries));
434f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
435f4bdf6c4SBarry Smith }
436f4bdf6c4SBarry Smith 
437f4bdf6c4SBarry Smith PetscErrorCode  MatZeroRowsLocal_HYPRESStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscScalar d,Vec x,Vec b)
438f4bdf6c4SBarry Smith {
4392cf14000SStefano Zampini   HYPRE_Int        index[3],*entries;
4402cf14000SStefano Zampini   PetscInt         i;
44139accc25SStefano Zampini   HYPRE_Complex    **values;
442f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data;
443f4bdf6c4SBarry Smith 
4444ddd07fcSJed Brown   PetscInt         part     = 0;      /* Petsc sstruct interface only allows 1 part */
4454ddd07fcSJed Brown   PetscInt         ordering = ex->dofs_order;
4464ddd07fcSJed Brown   PetscInt         grid_rank;
4474ddd07fcSJed Brown   PetscInt         var_type;
4484ddd07fcSJed Brown   PetscInt         nvars= ex->nvars;
4492cf14000SStefano Zampini   PetscInt         row;
450f4bdf6c4SBarry Smith 
451f4bdf6c4SBarry Smith   PetscFunctionBegin;
45208401ef6SPierre Jolivet   PetscCheck(!x || !b,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"No support");
4539566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(7*nvars,&entries));
454f4bdf6c4SBarry Smith 
4559566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nvars,&values));
4569566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(7*nvars*nvars,&values[0]));
457f4bdf6c4SBarry Smith   for (i=1; i<nvars; i++) {
458f4bdf6c4SBarry Smith     values[i] = values[i-1] + nvars*7;
459f4bdf6c4SBarry Smith   }
460f4bdf6c4SBarry Smith 
461f4bdf6c4SBarry Smith   for (i=0; i< nvars; i++) {
4629566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(values[i],nvars*7*sizeof(HYPRE_Complex)));
4639566063dSJacob Faibussowitsch     PetscCall(PetscHYPREScalarCast(d,values[i]+3));
464f4bdf6c4SBarry Smith   }
465f4bdf6c4SBarry Smith 
4668865f1eaSKarl Rupp   for (i=0; i< nvars*7; i++) entries[i] = i;
467f4bdf6c4SBarry Smith 
468f4bdf6c4SBarry Smith   if (!ordering) {
469f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
470f4bdf6c4SBarry Smith       grid_rank = irow[i] / nvars;
471f4bdf6c4SBarry Smith       var_type  = (irow[i] % nvars);
472f4bdf6c4SBarry Smith 
473f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
4742cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
4752cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
4762cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
477792fecdfSBarry Smith       PetscCallExternal(HYPRE_SStructMatrixSetValues,ex->ss_mat,part,index,var_type,7*nvars,entries,values[var_type]);
478f4bdf6c4SBarry Smith     }
479f4bdf6c4SBarry Smith   } else {
480f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
481f4bdf6c4SBarry Smith       var_type = irow[i]/(ex->gnxgnygnz);
482f4bdf6c4SBarry Smith       grid_rank= irow[i] - var_type*(ex->gnxgnygnz);
483f4bdf6c4SBarry Smith 
484f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
4852cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
4862cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
4872cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
488792fecdfSBarry Smith       PetscCallExternal(HYPRE_SStructMatrixSetValues,ex->ss_mat,part,index,var_type,7*nvars,entries,values[var_type]);
489f4bdf6c4SBarry Smith     }
490f4bdf6c4SBarry Smith   }
491792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructMatrixAssemble,ex->ss_mat);
4929566063dSJacob Faibussowitsch   PetscCall(PetscFree(values[0]));
4939566063dSJacob Faibussowitsch   PetscCall(PetscFree(values));
4949566063dSJacob Faibussowitsch   PetscCall(PetscFree(entries));
495f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
496f4bdf6c4SBarry Smith }
497f4bdf6c4SBarry Smith 
498f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPRESStruct_3d(Mat mat)
499f4bdf6c4SBarry Smith {
500f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex  = (Mat_HYPRESStruct*) mat->data;
5014ddd07fcSJed Brown   PetscInt         nvars= ex->nvars;
5024ddd07fcSJed Brown   PetscInt         size;
5034ddd07fcSJed Brown   PetscInt         part= 0;   /* only one part */
504f4bdf6c4SBarry Smith 
505f4bdf6c4SBarry Smith   PetscFunctionBegin;
506f4bdf6c4SBarry 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);
507f4bdf6c4SBarry Smith   {
5082cf14000SStefano Zampini     HYPRE_Int     i,*entries,iupper[3],ilower[3];
50939accc25SStefano Zampini     HYPRE_Complex *values;
5104ddd07fcSJed Brown 
511f4bdf6c4SBarry Smith     for (i= 0; i< 3; i++) {
512f4bdf6c4SBarry Smith       ilower[i] = ex->hbox.imin[i];
513f4bdf6c4SBarry Smith       iupper[i] = ex->hbox.imax[i];
514f4bdf6c4SBarry Smith     }
515f4bdf6c4SBarry Smith 
5169566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nvars*7,&entries,nvars*7*size,&values));
5178865f1eaSKarl Rupp     for (i= 0; i< nvars*7; i++) entries[i] = i;
5189566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(values,nvars*7*size));
519f4bdf6c4SBarry Smith 
520f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
521792fecdfSBarry Smith       PetscCallExternal(HYPRE_SStructMatrixSetBoxValues,ex->ss_mat,part,ilower,iupper,i,nvars*7,entries,values);
522f4bdf6c4SBarry Smith     }
5239566063dSJacob Faibussowitsch     PetscCall(PetscFree2(entries,values));
524f4bdf6c4SBarry Smith   }
525792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructMatrixAssemble,ex->ss_mat);
526f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
527f4bdf6c4SBarry Smith }
528f4bdf6c4SBarry Smith 
52959cb773eSBarry Smith static PetscErrorCode  MatSetUp_HYPRESStruct(Mat mat)
530f4bdf6c4SBarry Smith {
531f4bdf6c4SBarry Smith   Mat_HYPRESStruct       *ex = (Mat_HYPRESStruct*) mat->data;
532f4bdf6c4SBarry Smith   PetscInt               dim,dof,sw[3],nx,ny,nz;
5334ddd07fcSJed Brown   PetscInt               ilower[3],iupper[3],ssize,i;
534bff4a2f0SMatthew G. Knepley   DMBoundaryType         px,py,pz;
535f4bdf6c4SBarry Smith   DMDAStencilType        st;
5364ddd07fcSJed Brown   PetscInt               nparts= 1;  /* assuming only one part */
5374ddd07fcSJed Brown   PetscInt               part  = 0;
538565245c5SBarry Smith   ISLocalToGlobalMapping ltog;
53959cb773eSBarry Smith   DM                     da;
540b026d285SBarry Smith 
541f4bdf6c4SBarry Smith   PetscFunctionBegin;
5429566063dSJacob Faibussowitsch   PetscCall(MatGetDM(mat,(DM*)&da));
543f4bdf6c4SBarry Smith   ex->da = da;
5449566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)da));
545f4bdf6c4SBarry Smith 
5469566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(ex->da,&dim,0,0,0,0,0,0,&dof,&sw[0],&px,&py,&pz,&st));
5479566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]));
548f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
549f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
550f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
551f4bdf6c4SBarry Smith   /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
552f4bdf6c4SBarry Smith   ex->hbox.imin[0] = ilower[0];
553f4bdf6c4SBarry Smith   ex->hbox.imin[1] = ilower[1];
554f4bdf6c4SBarry Smith   ex->hbox.imin[2] = ilower[2];
555f4bdf6c4SBarry Smith   ex->hbox.imax[0] = iupper[0];
556f4bdf6c4SBarry Smith   ex->hbox.imax[1] = iupper[1];
557f4bdf6c4SBarry Smith   ex->hbox.imax[2] = iupper[2];
558f4bdf6c4SBarry Smith 
559f4bdf6c4SBarry Smith   ex->dofs_order = 0;
560f4bdf6c4SBarry Smith 
561f4bdf6c4SBarry Smith   /* assuming that the same number of dofs on each gridpoint. Also assume all cell-centred based */
562f4bdf6c4SBarry Smith   ex->nvars= dof;
563f4bdf6c4SBarry Smith 
564f4bdf6c4SBarry Smith   /* create the hypre grid object and set its information */
5651dca8a05SBarry Smith   PetscCheck(!px && !py && !pz,PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add periodic support by calling HYPRE_SStructGridSetPeriodic()");
566792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGridCreate,ex->hcomm,dim,nparts,&ex->ss_grid);
567792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGridSetExtents,ex->ss_grid,part,ex->hbox.imin,ex->hbox.imax);
568f4bdf6c4SBarry Smith   {
569f4bdf6c4SBarry Smith     HYPRE_SStructVariable *vartypes;
5709566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(ex->nvars,&vartypes));
5718865f1eaSKarl Rupp     for (i= 0; i< ex->nvars; i++) vartypes[i]= HYPRE_SSTRUCT_VARIABLE_CELL;
572792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructGridSetVariables,ex->ss_grid, part, ex->nvars,vartypes);
5739566063dSJacob Faibussowitsch     PetscCall(PetscFree(vartypes));
574f4bdf6c4SBarry Smith   }
575792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGridAssemble,ex->ss_grid);
576f4bdf6c4SBarry Smith 
577f4bdf6c4SBarry Smith   sw[1] = sw[0];
578f4bdf6c4SBarry Smith   sw[2] = sw[1];
579792fecdfSBarry Smith   /* PetscCallExternal(HYPRE_SStructGridSetNumGhost,ex->ss_grid,sw); */
580f4bdf6c4SBarry Smith 
581f4bdf6c4SBarry Smith   /* create the hypre stencil object and set its information */
58208401ef6SPierre Jolivet   PetscCheck(sw[0] <= 1,PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for wider stencils");
58308401ef6SPierre Jolivet   PetscCheck(st != DMDA_STENCIL_BOX,PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for box stencils");
584f4bdf6c4SBarry Smith 
585f4bdf6c4SBarry Smith   if (dim == 1) {
5862cf14000SStefano Zampini     HYPRE_Int offsets[3][1] = {{-1},{0},{1}};
5874ddd07fcSJed Brown     PetscInt  j, cnt;
588f4bdf6c4SBarry Smith 
589f4bdf6c4SBarry Smith     ssize = 3*(ex->nvars);
590792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructStencilCreate,dim,ssize,&ex->ss_stencil);
591f4bdf6c4SBarry Smith     cnt= 0;
592f4bdf6c4SBarry Smith     for (i = 0; i < (ex->nvars); i++) {
593f4bdf6c4SBarry Smith       for (j = 0; j < 3; j++) {
594792fecdfSBarry Smith         PetscCallExternal(HYPRE_SStructStencilSetEntry,ex->ss_stencil, cnt, offsets[j], i);
595f4bdf6c4SBarry Smith         cnt++;
596f4bdf6c4SBarry Smith       }
597f4bdf6c4SBarry Smith     }
598f4bdf6c4SBarry Smith   } else if (dim == 2) {
5992cf14000SStefano Zampini     HYPRE_Int offsets[5][2] = {{0,-1},{-1,0},{0,0},{1,0},{0,1}};
6004ddd07fcSJed Brown     PetscInt  j, cnt;
601f4bdf6c4SBarry Smith 
602f4bdf6c4SBarry Smith     ssize = 5*(ex->nvars);
603792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructStencilCreate,dim,ssize,&ex->ss_stencil);
604f4bdf6c4SBarry Smith     cnt= 0;
605f4bdf6c4SBarry Smith     for (i= 0; i< (ex->nvars); i++) {
606f4bdf6c4SBarry Smith       for (j= 0; j< 5; j++) {
607792fecdfSBarry Smith         PetscCallExternal(HYPRE_SStructStencilSetEntry,ex->ss_stencil, cnt, offsets[j], i);
608f4bdf6c4SBarry Smith         cnt++;
609f4bdf6c4SBarry Smith       }
610f4bdf6c4SBarry Smith     }
611f4bdf6c4SBarry Smith   } else if (dim == 3) {
6122cf14000SStefano 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}};
6134ddd07fcSJed Brown     PetscInt  j, cnt;
614f4bdf6c4SBarry Smith 
615f4bdf6c4SBarry Smith     ssize = 7*(ex->nvars);
616792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructStencilCreate,dim,ssize,&ex->ss_stencil);
617f4bdf6c4SBarry Smith     cnt= 0;
618f4bdf6c4SBarry Smith     for (i= 0; i< (ex->nvars); i++) {
619f4bdf6c4SBarry Smith       for (j= 0; j< 7; j++) {
620792fecdfSBarry Smith         PetscCallExternal(HYPRE_SStructStencilSetEntry,ex->ss_stencil, cnt, offsets[j], i);
621f4bdf6c4SBarry Smith         cnt++;
622f4bdf6c4SBarry Smith       }
623f4bdf6c4SBarry Smith     }
624f4bdf6c4SBarry Smith   }
625f4bdf6c4SBarry Smith 
626f4bdf6c4SBarry Smith   /* create the HYPRE graph */
627792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGraphCreate,ex->hcomm, ex->ss_grid, &(ex->ss_graph));
628f4bdf6c4SBarry Smith 
629f4bdf6c4SBarry Smith   /* set the stencil graph. Note that each variable has the same graph. This means that each
630f4bdf6c4SBarry Smith      variable couples to all the other variable and with the same stencil pattern. */
631f4bdf6c4SBarry Smith   for (i= 0; i< (ex->nvars); i++) {
632792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructGraphSetStencil,ex->ss_graph,part,i,ex->ss_stencil);
633f4bdf6c4SBarry Smith   }
634792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGraphAssemble,ex->ss_graph);
635f4bdf6c4SBarry Smith 
636f4bdf6c4SBarry Smith   /* create the HYPRE sstruct vectors for rhs and solution */
637792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorCreate,ex->hcomm,ex->ss_grid,&ex->ss_b);
638792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorCreate,ex->hcomm,ex->ss_grid,&ex->ss_x);
639792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorInitialize,ex->ss_b);
640792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorInitialize,ex->ss_x);
641792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorAssemble,ex->ss_b);
642792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorAssemble,ex->ss_x);
643f4bdf6c4SBarry Smith 
644f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
645792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructMatrixCreate,ex->hcomm,ex->ss_graph,&ex->ss_mat);
646792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGridDestroy,ex->ss_grid);
647792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructStencilDestroy,ex->ss_stencil);
648f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
649792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixInitialize,ex->ss_mat);
650f4bdf6c4SBarry Smith     ex->needsinitialization = PETSC_FALSE;
651f4bdf6c4SBarry Smith   }
652f4bdf6c4SBarry Smith 
653f4bdf6c4SBarry Smith   /* set the global and local sizes of the matrix */
6549566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da,0,0,0,&nx,&ny,&nz));
6559566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat,dof*nx*ny*nz,dof*nx*ny*nz,PETSC_DECIDE,PETSC_DECIDE));
6569566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->rmap,dof));
6579566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->cmap,dof));
6589566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->rmap));
6599566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->cmap));
66061710fbeSStefano Zampini   mat->preallocated = PETSC_TRUE;
661f4bdf6c4SBarry Smith 
662f4bdf6c4SBarry Smith   if (dim == 3) {
663f4bdf6c4SBarry Smith     mat->ops->setvalueslocal = MatSetValuesLocal_HYPRESStruct_3d;
664f4bdf6c4SBarry Smith     mat->ops->zerorowslocal  = MatZeroRowsLocal_HYPRESStruct_3d;
665f4bdf6c4SBarry Smith     mat->ops->zeroentries    = MatZeroEntries_HYPRESStruct_3d;
6668865f1eaSKarl Rupp 
6679566063dSJacob Faibussowitsch     /* PetscCall(MatZeroEntries_HYPRESStruct_3d(mat)); */
668ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Only support for 3d DMDA currently");
669f4bdf6c4SBarry Smith 
670f4bdf6c4SBarry Smith   /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
6719566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(mat,&ex->rstart,NULL));
6729566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(ex->da,&ltog));
6739566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **) &ex->gindices));
6749566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(ex->da,0,0,0,&ex->gnx,&ex->gnxgny,&ex->gnxgnygnz));
6758865f1eaSKarl Rupp 
676f4bdf6c4SBarry Smith   ex->gnxgny    *= ex->gnx;
677f4bdf6c4SBarry Smith   ex->gnxgnygnz *= ex->gnxgny;
6788865f1eaSKarl Rupp 
6799566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da,&ex->xs,&ex->ys,&ex->zs,&ex->nx,&ex->ny,&ex->nz));
6808865f1eaSKarl Rupp 
681f4bdf6c4SBarry Smith   ex->nxny   = ex->nx*ex->ny;
682f4bdf6c4SBarry Smith   ex->nxnynz = ex->nz*ex->nxny;
683f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
684f4bdf6c4SBarry Smith }
685f4bdf6c4SBarry Smith 
686f4bdf6c4SBarry Smith PetscErrorCode MatMult_HYPRESStruct(Mat A,Vec x,Vec y)
687f4bdf6c4SBarry Smith {
688b026d285SBarry Smith   const PetscScalar *xx;
689b026d285SBarry Smith   PetscScalar       *yy;
6902cf14000SStefano Zampini   HYPRE_Int         hlower[3],hupper[3];
6914ddd07fcSJed Brown   PetscInt          ilower[3],iupper[3];
692f4bdf6c4SBarry Smith   Mat_HYPRESStruct  *mx     = (Mat_HYPRESStruct*)(A->data);
6934ddd07fcSJed Brown   PetscInt          ordering= mx->dofs_order;
6944ddd07fcSJed Brown   PetscInt          nvars   = mx->nvars;
6954ddd07fcSJed Brown   PetscInt          part    = 0;
6964ddd07fcSJed Brown   PetscInt          size;
6974ddd07fcSJed Brown   PetscInt          i;
698f4bdf6c4SBarry Smith 
699f4bdf6c4SBarry Smith   PetscFunctionBegin;
7009566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]));
7012cf14000SStefano Zampini 
7022cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
703f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
704f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
705f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
7062cf14000SStefano Zampini   hlower[0]  = (HYPRE_Int)ilower[0];
7072cf14000SStefano Zampini   hlower[1]  = (HYPRE_Int)ilower[1];
7082cf14000SStefano Zampini   hlower[2]  = (HYPRE_Int)ilower[2];
7092cf14000SStefano Zampini   hupper[0]  = (HYPRE_Int)iupper[0];
7102cf14000SStefano Zampini   hupper[1]  = (HYPRE_Int)iupper[1];
7112cf14000SStefano Zampini   hupper[2]  = (HYPRE_Int)iupper[2];
712f4bdf6c4SBarry Smith 
713f4bdf6c4SBarry Smith   size= 1;
7148865f1eaSKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i]-ilower[i]+1);
715f4bdf6c4SBarry Smith 
716f4bdf6c4SBarry Smith   /* copy x values over to hypre for variable ordering */
717f4bdf6c4SBarry Smith   if (ordering) {
718792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues,mx->ss_b,0.0);
7199566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x,&xx));
720f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
721792fecdfSBarry Smith       PetscCallExternal(HYPRE_SStructVectorSetBoxValues,mx->ss_b,part,hlower,hupper,i,(HYPRE_Complex*)(xx+(size*i)));
722f4bdf6c4SBarry Smith     }
7239566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x,&xx));
724792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble,mx->ss_b);
725792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixMatvec,1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x);
726f4bdf6c4SBarry Smith 
727f4bdf6c4SBarry Smith     /* copy solution values back to PETSc */
7289566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y,&yy));
729f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
730792fecdfSBarry Smith       PetscCallExternal(HYPRE_SStructVectorGetBoxValues,mx->ss_x,part,hlower,hupper,i,(HYPRE_Complex*)(yy+(size*i)));
731f4bdf6c4SBarry Smith     }
7329566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y,&yy));
733f4bdf6c4SBarry Smith   } else {      /* nodal ordering must be mapped to variable ordering for sys_pfmg */
734f4bdf6c4SBarry Smith     PetscScalar *z;
7354ddd07fcSJed Brown     PetscInt    j, k;
736f4bdf6c4SBarry Smith 
7379566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nvars*size,&z));
738792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues,mx->ss_b,0.0);
7399566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x,&xx));
740f4bdf6c4SBarry Smith 
741f4bdf6c4SBarry Smith     /* transform nodal to hypre's variable ordering for sys_pfmg */
742f4bdf6c4SBarry Smith     for (i= 0; i< size; i++) {
743f4bdf6c4SBarry Smith       k= i*nvars;
7448865f1eaSKarl Rupp       for (j= 0; j< nvars; j++) z[j*size+i]= xx[k+j];
745f4bdf6c4SBarry Smith     }
746f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
747792fecdfSBarry Smith       PetscCallExternal(HYPRE_SStructVectorSetBoxValues,mx->ss_b,part,hlower,hupper,i,(HYPRE_Complex*)(z+(size*i)));
748f4bdf6c4SBarry Smith     }
7499566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x,&xx));
750792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble,mx->ss_b);
751792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixMatvec,1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x);
752f4bdf6c4SBarry Smith 
753f4bdf6c4SBarry Smith     /* copy solution values back to PETSc */
7549566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y,&yy));
755f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
756792fecdfSBarry Smith       PetscCallExternal(HYPRE_SStructVectorGetBoxValues,mx->ss_x,part,hlower,hupper,i,(HYPRE_Complex*)(z+(size*i)));
757f4bdf6c4SBarry Smith     }
758f4bdf6c4SBarry Smith     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
759f4bdf6c4SBarry Smith     for (i= 0; i< size; i++) {
760f4bdf6c4SBarry Smith       k= i*nvars;
7618865f1eaSKarl Rupp       for (j= 0; j< nvars; j++) yy[k+j]= z[j*size+i];
762f4bdf6c4SBarry Smith     }
7639566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y,&yy));
7649566063dSJacob Faibussowitsch     PetscCall(PetscFree(z));
765f4bdf6c4SBarry Smith   }
766f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
767f4bdf6c4SBarry Smith }
768f4bdf6c4SBarry Smith 
769f4bdf6c4SBarry Smith PetscErrorCode MatAssemblyEnd_HYPRESStruct(Mat mat,MatAssemblyType mode)
770f4bdf6c4SBarry Smith {
771f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data;
772f4bdf6c4SBarry Smith 
773f4bdf6c4SBarry Smith   PetscFunctionBegin;
774792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructMatrixAssemble,ex->ss_mat);
775f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
776f4bdf6c4SBarry Smith }
777f4bdf6c4SBarry Smith 
778f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPRESStruct(Mat mat)
779f4bdf6c4SBarry Smith {
780f4bdf6c4SBarry Smith   PetscFunctionBegin;
781f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
782f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
783f4bdf6c4SBarry Smith }
784f4bdf6c4SBarry Smith 
785f4bdf6c4SBarry Smith PetscErrorCode MatDestroy_HYPRESStruct(Mat mat)
786f4bdf6c4SBarry Smith {
787f4bdf6c4SBarry Smith   Mat_HYPRESStruct       *ex = (Mat_HYPRESStruct*) mat->data;
788d94fc0b6SBarry Smith   ISLocalToGlobalMapping ltog;
789f4bdf6c4SBarry Smith 
790f4bdf6c4SBarry Smith   PetscFunctionBegin;
7919566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(ex->da,&ltog));
7929566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreIndices(ltog, (const PetscInt **) &ex->gindices));
793792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGraphDestroy,ex->ss_graph);
794792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructMatrixDestroy,ex->ss_mat);
795792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorDestroy,ex->ss_x);
796792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorDestroy,ex->ss_b);
7979566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)ex->da));
7989566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&(ex->hcomm)));
7999566063dSJacob Faibussowitsch   PetscCall(PetscFree(ex));
800f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
801f4bdf6c4SBarry Smith }
802f4bdf6c4SBarry Smith 
8038cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_HYPRESStruct(Mat B)
804f4bdf6c4SBarry Smith {
805f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex;
806f4bdf6c4SBarry Smith 
807f4bdf6c4SBarry Smith   PetscFunctionBegin;
8089566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(B,&ex));
809f4bdf6c4SBarry Smith   B->data      = (void*)ex;
810f4bdf6c4SBarry Smith   B->rmap->bs  = 1;
811f4bdf6c4SBarry Smith   B->assembled = PETSC_FALSE;
812f4bdf6c4SBarry Smith 
813f4bdf6c4SBarry Smith   B->insertmode = NOT_SET_VALUES;
814f4bdf6c4SBarry Smith 
815f4bdf6c4SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_HYPRESStruct;
816f4bdf6c4SBarry Smith   B->ops->mult        = MatMult_HYPRESStruct;
817f4bdf6c4SBarry Smith   B->ops->zeroentries = MatZeroEntries_HYPRESStruct;
818f4bdf6c4SBarry Smith   B->ops->destroy     = MatDestroy_HYPRESStruct;
81959cb773eSBarry Smith   B->ops->setup       = MatSetUp_HYPRESStruct;
820f4bdf6c4SBarry Smith 
821f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
822f4bdf6c4SBarry Smith 
8239566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_dup(PetscObjectComm((PetscObject)B),&(ex->hcomm)));
8249566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B,MATHYPRESSTRUCT));
825f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
826f4bdf6c4SBarry Smith }
827