xref: /petsc/src/dm/impls/da/hypre/mhyp.c (revision 792fecdfe9134cce4d631112660ddd34f063bc17)
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 {
302cf14000SStefano Zampini   HYPRE_Int       index[3],entries[7];
312cf14000SStefano Zampini   PetscInt        i,j,stencil,row;
3239accc25SStefano Zampini   HYPRE_Complex   *values = (HYPRE_Complex*)y;
33f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex     = (Mat_HYPREStruct*) mat->data;
34f4bdf6c4SBarry Smith 
35f4bdf6c4SBarry Smith   PetscFunctionBegin;
3663a3b9bcSJacob Faibussowitsch   PetscCheck(ncol <= 7,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"ncol %" PetscInt_FMT " > 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;
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)));
60*792fecdfSBarry Smith     if (addv == ADD_VALUES) PetscCallExternal(HYPRE_StructMatrixAddToValues,ex->hmat,index,ncol,entries,values);
61*792fecdfSBarry 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)));
83*792fecdfSBarry Smith     PetscCallExternal(HYPRE_StructMatrixSetValues,ex->hmat,index,7,entries,values);
84f4bdf6c4SBarry Smith   }
85*792fecdfSBarry 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 */
96*792fecdfSBarry Smith   PetscCallExternal(hypre_StructMatrixClearBoxValues,ex->hmat,&ex->hbox,7,indices,0,1);
97*792fecdfSBarry 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];
1052cf14000SStefano Zampini   HYPRE_Int              hlower[3],hupper[3];
1062cf14000SStefano Zampini   PetscInt               dim,dof,psw,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 
1179566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(ex->da,&dim,0,0,0,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");
1411dca8a05SBarry Smith   PetscCheck(!px && !py && !pz,PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add periodic support by calling HYPRE_StructGridSetPeriodic()");
142*792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructGridCreate,ex->hcomm,dim,&ex->hgrid);
143*792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructGridSetExtents,ex->hgrid,hlower,hupper);
144*792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructGridAssemble,ex->hgrid);
145f4bdf6c4SBarry Smith 
1462cf14000SStefano Zampini   sw[5] = sw[4] = sw[3] = sw[2] = sw[1] = sw[0] = psw;
147*792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructGridSetNumGhost,ex->hgrid,sw);
148f4bdf6c4SBarry Smith 
149f4bdf6c4SBarry Smith   /* create the hypre stencil object and set its information */
15008401ef6SPierre Jolivet   PetscCheck(sw[0] <= 1,PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for wider stencils");
15108401ef6SPierre Jolivet   PetscCheck(st != DMDA_STENCIL_BOX,PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for box stencils");
152f4bdf6c4SBarry Smith   if (dim == 1) {
1532cf14000SStefano Zampini     HYPRE_Int offsets[3][1] = {{-1},{0},{1}};
154f4bdf6c4SBarry Smith     ssize = 3;
155*792fecdfSBarry Smith     PetscCallExternal(HYPRE_StructStencilCreate,dim,ssize,&ex->hstencil);
156f4bdf6c4SBarry Smith     for (i=0; i<ssize; i++) {
157*792fecdfSBarry Smith       PetscCallExternal(HYPRE_StructStencilSetElement,ex->hstencil,i,offsets[i]);
158f4bdf6c4SBarry Smith     }
159f4bdf6c4SBarry Smith   } else if (dim == 2) {
1602cf14000SStefano Zampini     HYPRE_Int offsets[5][2] = {{0,-1},{-1,0},{0,0},{1,0},{0,1}};
161f4bdf6c4SBarry Smith     ssize = 5;
162*792fecdfSBarry Smith     PetscCallExternal(HYPRE_StructStencilCreate,dim,ssize,&ex->hstencil);
163f4bdf6c4SBarry Smith     for (i=0; i<ssize; i++) {
164*792fecdfSBarry Smith       PetscCallExternal(HYPRE_StructStencilSetElement,ex->hstencil,i,offsets[i]);
165f4bdf6c4SBarry Smith     }
166f4bdf6c4SBarry Smith   } else if (dim == 3) {
1672cf14000SStefano 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}};
168f4bdf6c4SBarry Smith     ssize = 7;
169*792fecdfSBarry Smith     PetscCallExternal(HYPRE_StructStencilCreate,dim,ssize,&ex->hstencil);
170f4bdf6c4SBarry Smith     for (i=0; i<ssize; i++) {
171*792fecdfSBarry Smith       PetscCallExternal(HYPRE_StructStencilSetElement,ex->hstencil,i,offsets[i]);
172f4bdf6c4SBarry Smith     }
173f4bdf6c4SBarry Smith   }
174f4bdf6c4SBarry Smith 
175f4bdf6c4SBarry Smith   /* create the HYPRE vector for rhs and solution */
176*792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorCreate,ex->hcomm,ex->hgrid,&ex->hb);
177*792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorCreate,ex->hcomm,ex->hgrid,&ex->hx);
178*792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorInitialize,ex->hb);
179*792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorInitialize,ex->hx);
180*792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble,ex->hb);
181*792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble,ex->hx);
182f4bdf6c4SBarry Smith 
183f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
184*792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixCreate,ex->hcomm,ex->hgrid,ex->hstencil,&ex->hmat);
185*792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructGridDestroy,ex->hgrid);
186*792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructStencilDestroy,ex->hstencil);
187f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
188*792fecdfSBarry Smith     PetscCallExternal(HYPRE_StructMatrixInitialize,ex->hmat);
189f4bdf6c4SBarry Smith     ex->needsinitialization = PETSC_FALSE;
190f4bdf6c4SBarry Smith   }
191f4bdf6c4SBarry Smith 
192f4bdf6c4SBarry Smith   /* set the global and local sizes of the matrix */
1939566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da,0,0,0,&nx,&ny,&nz));
1949566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat,dof*nx*ny*nz,dof*nx*ny*nz,PETSC_DECIDE,PETSC_DECIDE));
1959566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->rmap,1));
1969566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->cmap,1));
1979566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->rmap));
1989566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->cmap));
19959cb773eSBarry Smith   mat->preallocated = PETSC_TRUE;
200f4bdf6c4SBarry Smith 
201f4bdf6c4SBarry Smith   if (dim == 3) {
202f4bdf6c4SBarry Smith     mat->ops->setvalueslocal = MatSetValuesLocal_HYPREStruct_3d;
203f4bdf6c4SBarry Smith     mat->ops->zerorowslocal  = MatZeroRowsLocal_HYPREStruct_3d;
204f4bdf6c4SBarry Smith     mat->ops->zeroentries    = MatZeroEntries_HYPREStruct_3d;
2058865f1eaSKarl Rupp 
2069566063dSJacob Faibussowitsch     /*        PetscCall(MatZeroEntries_HYPREStruct_3d(mat)); */
207ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Only support for 3d DMDA currently");
208f4bdf6c4SBarry Smith 
209f4bdf6c4SBarry Smith   /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
2109566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(mat,&ex->rstart,NULL));
2119566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(ex->da,&ltog));
2129566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **) &ex->gindices));
2139566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(ex->da,0,0,0,&ex->gnx,&ex->gnxgny,0));
214f4bdf6c4SBarry Smith   ex->gnxgny *= ex->gnx;
2159566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da,&ex->xs,&ex->ys,&ex->zs,&ex->nx,&ex->ny,0));
216f4bdf6c4SBarry Smith   ex->nxny    = ex->nx*ex->ny;
217f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
218f4bdf6c4SBarry Smith }
219f4bdf6c4SBarry Smith 
220f4bdf6c4SBarry Smith PetscErrorCode MatMult_HYPREStruct(Mat A,Vec x,Vec y)
221f4bdf6c4SBarry Smith {
222b026d285SBarry Smith   const PetscScalar *xx;
223b026d285SBarry Smith   PetscScalar       *yy;
2244ddd07fcSJed Brown   PetscInt          ilower[3],iupper[3];
2252cf14000SStefano Zampini   HYPRE_Int         hlower[3],hupper[3];
226f4bdf6c4SBarry Smith   Mat_HYPREStruct   *mx = (Mat_HYPREStruct*)(A->data);
227f4bdf6c4SBarry Smith 
228f4bdf6c4SBarry Smith   PetscFunctionBegin;
2299566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]));
2302cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
231f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
232f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
233f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
2342cf14000SStefano Zampini   hlower[0]  = (HYPRE_Int)ilower[0];
2352cf14000SStefano Zampini   hlower[1]  = (HYPRE_Int)ilower[1];
2362cf14000SStefano Zampini   hlower[2]  = (HYPRE_Int)ilower[2];
2372cf14000SStefano Zampini   hupper[0]  = (HYPRE_Int)iupper[0];
2382cf14000SStefano Zampini   hupper[1]  = (HYPRE_Int)iupper[1];
2392cf14000SStefano Zampini   hupper[2]  = (HYPRE_Int)iupper[2];
240f4bdf6c4SBarry Smith 
241f4bdf6c4SBarry Smith   /* copy x values over to hypre */
242*792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetConstantValues,mx->hb,0.0);
2439566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x,&xx));
244*792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetBoxValues,mx->hb,hlower,hupper,(HYPRE_Complex*)xx);
2459566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x,&xx));
246*792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble,mx->hb);
247*792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixMatvec,1.0,mx->hmat,mx->hb,0.0,mx->hx);
248f4bdf6c4SBarry Smith 
249f4bdf6c4SBarry Smith   /* copy solution values back to PETSc */
2509566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y,&yy));
251*792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorGetBoxValues,mx->hx,hlower,hupper,(HYPRE_Complex*)yy);
2529566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y,&yy));
253f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
254f4bdf6c4SBarry Smith }
255f4bdf6c4SBarry Smith 
256f4bdf6c4SBarry Smith PetscErrorCode MatAssemblyEnd_HYPREStruct(Mat mat,MatAssemblyType mode)
257f4bdf6c4SBarry Smith {
258f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
259f4bdf6c4SBarry Smith 
260f4bdf6c4SBarry Smith   PetscFunctionBegin;
261*792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixAssemble,ex->hmat);
262*792fecdfSBarry Smith   /* PetscCallExternal(HYPRE_StructMatrixPrint,"dummy",ex->hmat,0); */
263f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
264f4bdf6c4SBarry Smith }
265f4bdf6c4SBarry Smith 
266f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPREStruct(Mat mat)
267f4bdf6c4SBarry Smith {
268f4bdf6c4SBarry Smith   PetscFunctionBegin;
269f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
270f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
271f4bdf6c4SBarry Smith }
272f4bdf6c4SBarry Smith 
273f4bdf6c4SBarry Smith PetscErrorCode MatDestroy_HYPREStruct(Mat mat)
274f4bdf6c4SBarry Smith {
275f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
276f4bdf6c4SBarry Smith 
277f4bdf6c4SBarry Smith   PetscFunctionBegin;
278*792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixDestroy,ex->hmat);
279*792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorDestroy,ex->hx);
280*792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorDestroy,ex->hb);
2819566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)ex->da));
2829566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&(ex->hcomm)));
2839566063dSJacob Faibussowitsch   PetscCall(PetscFree(ex));
284f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
285f4bdf6c4SBarry Smith }
286f4bdf6c4SBarry Smith 
2878cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_HYPREStruct(Mat B)
288f4bdf6c4SBarry Smith {
289f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex;
290f4bdf6c4SBarry Smith 
291f4bdf6c4SBarry Smith   PetscFunctionBegin;
2929566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(B,&ex));
293f4bdf6c4SBarry Smith   B->data      = (void*)ex;
294f4bdf6c4SBarry Smith   B->rmap->bs  = 1;
295f4bdf6c4SBarry Smith   B->assembled = PETSC_FALSE;
296f4bdf6c4SBarry Smith 
297f4bdf6c4SBarry Smith   B->insertmode = NOT_SET_VALUES;
298f4bdf6c4SBarry Smith 
299f4bdf6c4SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_HYPREStruct;
300f4bdf6c4SBarry Smith   B->ops->mult        = MatMult_HYPREStruct;
301f4bdf6c4SBarry Smith   B->ops->zeroentries = MatZeroEntries_HYPREStruct;
302f4bdf6c4SBarry Smith   B->ops->destroy     = MatDestroy_HYPREStruct;
30359cb773eSBarry Smith   B->ops->setup       = MatSetUp_HYPREStruct;
304f4bdf6c4SBarry Smith 
305f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
306f4bdf6c4SBarry Smith 
3079566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_dup(PetscObjectComm((PetscObject)B),&(ex->hcomm)));
3089566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B,MATHYPRESTRUCT));
309f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
310f4bdf6c4SBarry Smith }
311f4bdf6c4SBarry Smith 
312f4bdf6c4SBarry Smith /*MC
313f4bdf6c4SBarry Smith    MATHYPRESSTRUCT - MATHYPRESSTRUCT = "hypresstruct" - A matrix type to be used for parallel sparse matrices
314f4bdf6c4SBarry Smith           based on the hypre HYPRE_SStructMatrix.
315f4bdf6c4SBarry Smith 
316f4bdf6c4SBarry Smith    Level: intermediate
317f4bdf6c4SBarry Smith 
31895452b02SPatrick Sanan    Notes:
31995452b02SPatrick Sanan     Unlike hypre's general semi-struct object consisting of a collection of structured-grid objects and unstructured
320b026d285SBarry Smith           grid objects, we restrict the semi-struct objects to consist of only structured-grid components.
321f4bdf6c4SBarry Smith 
322f4bdf6c4SBarry 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
323f4bdf6c4SBarry Smith           be defined by a DMDA.
324f4bdf6c4SBarry Smith 
32559cb773eSBarry Smith           The matrix needs a DMDA associated with it by either a call to MatSetDM() or if the matrix is obtained from DMCreateMatrix()
326f4bdf6c4SBarry Smith 
327f4bdf6c4SBarry Smith M*/
328f4bdf6c4SBarry Smith 
329f4bdf6c4SBarry Smith PetscErrorCode  MatSetValuesLocal_HYPRESStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
330f4bdf6c4SBarry Smith {
3312cf14000SStefano Zampini   HYPRE_Int         index[3],*entries;
3322cf14000SStefano Zampini   PetscInt          i,j,stencil;
33339accc25SStefano Zampini   HYPRE_Complex     *values = (HYPRE_Complex*)y;
334f4bdf6c4SBarry Smith   Mat_HYPRESStruct  *ex     = (Mat_HYPRESStruct*) mat->data;
335f4bdf6c4SBarry Smith 
3364ddd07fcSJed Brown   PetscInt          part = 0;          /* Petsc sstruct interface only allows 1 part */
3374ddd07fcSJed Brown   PetscInt          ordering;
3384ddd07fcSJed Brown   PetscInt          grid_rank, to_grid_rank;
3394ddd07fcSJed Brown   PetscInt          var_type, to_var_type;
3404ddd07fcSJed Brown   PetscInt          to_var_entry = 0;
3414ddd07fcSJed Brown   PetscInt          nvars= ex->nvars;
3422cf14000SStefano Zampini   PetscInt          row;
343f4bdf6c4SBarry Smith 
344f4bdf6c4SBarry Smith   PetscFunctionBegin;
3459566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(7*nvars,&entries));
346f4bdf6c4SBarry Smith   ordering = ex->dofs_order;  /* ordering= 0   nodal ordering
347f4bdf6c4SBarry Smith                                            1   variable ordering */
34861710fbeSStefano Zampini   /* stencil entries are ordered by variables: var0_stencil0, var0_stencil1, ..., var0_stencil6, var1_stencil0, var1_stencil1, ...  */
349f4bdf6c4SBarry Smith   if (!ordering) {
350f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
351f4bdf6c4SBarry Smith       grid_rank= irow[i]/nvars;
352f4bdf6c4SBarry Smith       var_type = (irow[i] % nvars);
353f4bdf6c4SBarry Smith 
354f4bdf6c4SBarry Smith       for (j=0; j<ncol; j++) {
355f4bdf6c4SBarry Smith         to_grid_rank= icol[j]/nvars;
356f4bdf6c4SBarry Smith         to_var_type = (icol[j] % nvars);
357f4bdf6c4SBarry Smith 
358f4bdf6c4SBarry Smith         to_var_entry= to_var_entry*7;
359f4bdf6c4SBarry Smith         entries[j]  = to_var_entry;
360f4bdf6c4SBarry Smith 
361f4bdf6c4SBarry Smith         stencil = to_grid_rank-grid_rank;
362f4bdf6c4SBarry Smith         if (!stencil) {
363f4bdf6c4SBarry Smith           entries[j] += 3;
364f4bdf6c4SBarry Smith         } else if (stencil == -1) {
365f4bdf6c4SBarry Smith           entries[j] += 2;
366f4bdf6c4SBarry Smith         } else if (stencil == 1) {
367f4bdf6c4SBarry Smith           entries[j] += 4;
368f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnx) {
369f4bdf6c4SBarry Smith           entries[j] += 1;
370f4bdf6c4SBarry Smith         } else if (stencil == ex->gnx) {
371f4bdf6c4SBarry Smith           entries[j] += 5;
372f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnxgny) {
373f4bdf6c4SBarry Smith           entries[j] += 0;
374f4bdf6c4SBarry Smith         } else if (stencil == ex->gnxgny) {
375f4bdf6c4SBarry Smith           entries[j] += 6;
37663a3b9bcSJacob 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);
377f4bdf6c4SBarry Smith       }
378f4bdf6c4SBarry Smith 
379f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
3802cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
3812cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
3822cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
383f4bdf6c4SBarry Smith 
384*792fecdfSBarry Smith       if (addv == ADD_VALUES) PetscCallExternal(HYPRE_SStructMatrixAddToValues,ex->ss_mat,part,index,var_type,ncol,entries,values);
385*792fecdfSBarry Smith       else PetscCallExternal(HYPRE_SStructMatrixSetValues,ex->ss_mat,part,index,var_type,ncol,entries,values);
386f4bdf6c4SBarry Smith       values += ncol;
387f4bdf6c4SBarry Smith     }
388f4bdf6c4SBarry Smith   } else {
389f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
390f4bdf6c4SBarry Smith       var_type = irow[i]/(ex->gnxgnygnz);
391f4bdf6c4SBarry Smith       grid_rank= irow[i] - var_type*(ex->gnxgnygnz);
392f4bdf6c4SBarry Smith 
393f4bdf6c4SBarry Smith       for (j=0; j<ncol; j++) {
394f4bdf6c4SBarry Smith         to_var_type = icol[j]/(ex->gnxgnygnz);
395f4bdf6c4SBarry Smith         to_grid_rank= icol[j] - to_var_type*(ex->gnxgnygnz);
396f4bdf6c4SBarry Smith 
397f4bdf6c4SBarry Smith         to_var_entry= to_var_entry*7;
398f4bdf6c4SBarry Smith         entries[j]  = to_var_entry;
399f4bdf6c4SBarry Smith 
400f4bdf6c4SBarry Smith         stencil = to_grid_rank-grid_rank;
401f4bdf6c4SBarry Smith         if (!stencil) {
402f4bdf6c4SBarry Smith           entries[j] += 3;
403f4bdf6c4SBarry Smith         } else if (stencil == -1) {
404f4bdf6c4SBarry Smith           entries[j] += 2;
405f4bdf6c4SBarry Smith         } else if (stencil == 1) {
406f4bdf6c4SBarry Smith           entries[j] += 4;
407f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnx) {
408f4bdf6c4SBarry Smith           entries[j] += 1;
409f4bdf6c4SBarry Smith         } else if (stencil == ex->gnx) {
410f4bdf6c4SBarry Smith           entries[j] += 5;
411f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnxgny) {
412f4bdf6c4SBarry Smith           entries[j] += 0;
413f4bdf6c4SBarry Smith         } else if (stencil == ex->gnxgny) {
414f4bdf6c4SBarry Smith           entries[j] += 6;
41563a3b9bcSJacob 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);
416f4bdf6c4SBarry Smith       }
417f4bdf6c4SBarry Smith 
418f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
4192cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
4202cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
4212cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
422f4bdf6c4SBarry Smith 
423*792fecdfSBarry Smith       if (addv == ADD_VALUES) PetscCallExternal(HYPRE_SStructMatrixAddToValues,ex->ss_mat,part,index,var_type,ncol,entries,values);
424*792fecdfSBarry Smith       else PetscCallExternal(HYPRE_SStructMatrixSetValues,ex->ss_mat,part,index,var_type,ncol,entries,values);
425f4bdf6c4SBarry Smith       values += ncol;
426f4bdf6c4SBarry Smith     }
427f4bdf6c4SBarry Smith   }
4289566063dSJacob Faibussowitsch   PetscCall(PetscFree(entries));
429f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
430f4bdf6c4SBarry Smith }
431f4bdf6c4SBarry Smith 
432f4bdf6c4SBarry Smith PetscErrorCode  MatZeroRowsLocal_HYPRESStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscScalar d,Vec x,Vec b)
433f4bdf6c4SBarry Smith {
4342cf14000SStefano Zampini   HYPRE_Int        index[3],*entries;
4352cf14000SStefano Zampini   PetscInt         i;
43639accc25SStefano Zampini   HYPRE_Complex    **values;
437f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data;
438f4bdf6c4SBarry Smith 
4394ddd07fcSJed Brown   PetscInt         part     = 0;      /* Petsc sstruct interface only allows 1 part */
4404ddd07fcSJed Brown   PetscInt         ordering = ex->dofs_order;
4414ddd07fcSJed Brown   PetscInt         grid_rank;
4424ddd07fcSJed Brown   PetscInt         var_type;
4434ddd07fcSJed Brown   PetscInt         nvars= ex->nvars;
4442cf14000SStefano Zampini   PetscInt         row;
445f4bdf6c4SBarry Smith 
446f4bdf6c4SBarry Smith   PetscFunctionBegin;
44708401ef6SPierre Jolivet   PetscCheck(!x || !b,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"No support");
4489566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(7*nvars,&entries));
449f4bdf6c4SBarry Smith 
4509566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nvars,&values));
4519566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(7*nvars*nvars,&values[0]));
452f4bdf6c4SBarry Smith   for (i=1; i<nvars; i++) {
453f4bdf6c4SBarry Smith     values[i] = values[i-1] + nvars*7;
454f4bdf6c4SBarry Smith   }
455f4bdf6c4SBarry Smith 
456f4bdf6c4SBarry Smith   for (i=0; i< nvars; i++) {
4579566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(values[i],nvars*7*sizeof(HYPRE_Complex)));
4589566063dSJacob Faibussowitsch     PetscCall(PetscHYPREScalarCast(d,values[i]+3));
459f4bdf6c4SBarry Smith   }
460f4bdf6c4SBarry Smith 
4618865f1eaSKarl Rupp   for (i=0; i< nvars*7; i++) entries[i] = i;
462f4bdf6c4SBarry Smith 
463f4bdf6c4SBarry Smith   if (!ordering) {
464f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
465f4bdf6c4SBarry Smith       grid_rank = irow[i] / nvars;
466f4bdf6c4SBarry Smith       var_type  = (irow[i] % nvars);
467f4bdf6c4SBarry Smith 
468f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
4692cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
4702cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
4712cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
472*792fecdfSBarry Smith       PetscCallExternal(HYPRE_SStructMatrixSetValues,ex->ss_mat,part,index,var_type,7*nvars,entries,values[var_type]);
473f4bdf6c4SBarry Smith     }
474f4bdf6c4SBarry Smith   } else {
475f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
476f4bdf6c4SBarry Smith       var_type = irow[i]/(ex->gnxgnygnz);
477f4bdf6c4SBarry Smith       grid_rank= irow[i] - var_type*(ex->gnxgnygnz);
478f4bdf6c4SBarry Smith 
479f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
4802cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
4812cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
4822cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
483*792fecdfSBarry Smith       PetscCallExternal(HYPRE_SStructMatrixSetValues,ex->ss_mat,part,index,var_type,7*nvars,entries,values[var_type]);
484f4bdf6c4SBarry Smith     }
485f4bdf6c4SBarry Smith   }
486*792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructMatrixAssemble,ex->ss_mat);
4879566063dSJacob Faibussowitsch   PetscCall(PetscFree(values[0]));
4889566063dSJacob Faibussowitsch   PetscCall(PetscFree(values));
4899566063dSJacob Faibussowitsch   PetscCall(PetscFree(entries));
490f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
491f4bdf6c4SBarry Smith }
492f4bdf6c4SBarry Smith 
493f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPRESStruct_3d(Mat mat)
494f4bdf6c4SBarry Smith {
495f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex  = (Mat_HYPRESStruct*) mat->data;
4964ddd07fcSJed Brown   PetscInt         nvars= ex->nvars;
4974ddd07fcSJed Brown   PetscInt         size;
4984ddd07fcSJed Brown   PetscInt         part= 0;   /* only one part */
499f4bdf6c4SBarry Smith 
500f4bdf6c4SBarry Smith   PetscFunctionBegin;
501f4bdf6c4SBarry Smith   size = ((ex->hbox.imax[0])-(ex->hbox.imin[0])+1)*((ex->hbox.imax[1])-(ex->hbox.imin[1])+1)*((ex->hbox.imax[2])-(ex->hbox.imin[2])+1);
502f4bdf6c4SBarry Smith   {
5032cf14000SStefano Zampini     HYPRE_Int     i,*entries,iupper[3],ilower[3];
50439accc25SStefano Zampini     HYPRE_Complex *values;
5054ddd07fcSJed Brown 
506f4bdf6c4SBarry Smith     for (i= 0; i< 3; i++) {
507f4bdf6c4SBarry Smith       ilower[i] = ex->hbox.imin[i];
508f4bdf6c4SBarry Smith       iupper[i] = ex->hbox.imax[i];
509f4bdf6c4SBarry Smith     }
510f4bdf6c4SBarry Smith 
5119566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nvars*7,&entries,nvars*7*size,&values));
5128865f1eaSKarl Rupp     for (i= 0; i< nvars*7; i++) entries[i] = i;
5139566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(values,nvars*7*size));
514f4bdf6c4SBarry Smith 
515f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
516*792fecdfSBarry Smith       PetscCallExternal(HYPRE_SStructMatrixSetBoxValues,ex->ss_mat,part,ilower,iupper,i,nvars*7,entries,values);
517f4bdf6c4SBarry Smith     }
5189566063dSJacob Faibussowitsch     PetscCall(PetscFree2(entries,values));
519f4bdf6c4SBarry Smith   }
520*792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructMatrixAssemble,ex->ss_mat);
521f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
522f4bdf6c4SBarry Smith }
523f4bdf6c4SBarry Smith 
52459cb773eSBarry Smith static PetscErrorCode  MatSetUp_HYPRESStruct(Mat mat)
525f4bdf6c4SBarry Smith {
526f4bdf6c4SBarry Smith   Mat_HYPRESStruct       *ex = (Mat_HYPRESStruct*) mat->data;
527f4bdf6c4SBarry Smith   PetscInt               dim,dof,sw[3],nx,ny,nz;
5284ddd07fcSJed Brown   PetscInt               ilower[3],iupper[3],ssize,i;
529bff4a2f0SMatthew G. Knepley   DMBoundaryType         px,py,pz;
530f4bdf6c4SBarry Smith   DMDAStencilType        st;
5314ddd07fcSJed Brown   PetscInt               nparts= 1;  /* assuming only one part */
5324ddd07fcSJed Brown   PetscInt               part  = 0;
533565245c5SBarry Smith   ISLocalToGlobalMapping ltog;
53459cb773eSBarry Smith   DM                     da;
535b026d285SBarry Smith 
536f4bdf6c4SBarry Smith   PetscFunctionBegin;
5379566063dSJacob Faibussowitsch   PetscCall(MatGetDM(mat,(DM*)&da));
538f4bdf6c4SBarry Smith   ex->da = da;
5399566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)da));
540f4bdf6c4SBarry Smith 
5419566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(ex->da,&dim,0,0,0,0,0,0,&dof,&sw[0],&px,&py,&pz,&st));
5429566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]));
543f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
544f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
545f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
546f4bdf6c4SBarry Smith   /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
547f4bdf6c4SBarry Smith   ex->hbox.imin[0] = ilower[0];
548f4bdf6c4SBarry Smith   ex->hbox.imin[1] = ilower[1];
549f4bdf6c4SBarry Smith   ex->hbox.imin[2] = ilower[2];
550f4bdf6c4SBarry Smith   ex->hbox.imax[0] = iupper[0];
551f4bdf6c4SBarry Smith   ex->hbox.imax[1] = iupper[1];
552f4bdf6c4SBarry Smith   ex->hbox.imax[2] = iupper[2];
553f4bdf6c4SBarry Smith 
554f4bdf6c4SBarry Smith   ex->dofs_order = 0;
555f4bdf6c4SBarry Smith 
556f4bdf6c4SBarry Smith   /* assuming that the same number of dofs on each gridpoint. Also assume all cell-centred based */
557f4bdf6c4SBarry Smith   ex->nvars= dof;
558f4bdf6c4SBarry Smith 
559f4bdf6c4SBarry Smith   /* create the hypre grid object and set its information */
5601dca8a05SBarry Smith   PetscCheck(!px && !py && !pz,PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add periodic support by calling HYPRE_SStructGridSetPeriodic()");
561*792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGridCreate,ex->hcomm,dim,nparts,&ex->ss_grid);
562*792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGridSetExtents,ex->ss_grid,part,ex->hbox.imin,ex->hbox.imax);
563f4bdf6c4SBarry Smith   {
564f4bdf6c4SBarry Smith     HYPRE_SStructVariable *vartypes;
5659566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(ex->nvars,&vartypes));
5668865f1eaSKarl Rupp     for (i= 0; i< ex->nvars; i++) vartypes[i]= HYPRE_SSTRUCT_VARIABLE_CELL;
567*792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructGridSetVariables,ex->ss_grid, part, ex->nvars,vartypes);
5689566063dSJacob Faibussowitsch     PetscCall(PetscFree(vartypes));
569f4bdf6c4SBarry Smith   }
570*792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGridAssemble,ex->ss_grid);
571f4bdf6c4SBarry Smith 
572f4bdf6c4SBarry Smith   sw[1] = sw[0];
573f4bdf6c4SBarry Smith   sw[2] = sw[1];
574*792fecdfSBarry Smith   /* PetscCallExternal(HYPRE_SStructGridSetNumGhost,ex->ss_grid,sw); */
575f4bdf6c4SBarry Smith 
576f4bdf6c4SBarry Smith   /* create the hypre stencil object and set its information */
57708401ef6SPierre Jolivet   PetscCheck(sw[0] <= 1,PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for wider stencils");
57808401ef6SPierre Jolivet   PetscCheck(st != DMDA_STENCIL_BOX,PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for box stencils");
579f4bdf6c4SBarry Smith 
580f4bdf6c4SBarry Smith   if (dim == 1) {
5812cf14000SStefano Zampini     HYPRE_Int offsets[3][1] = {{-1},{0},{1}};
5824ddd07fcSJed Brown     PetscInt  j, cnt;
583f4bdf6c4SBarry Smith 
584f4bdf6c4SBarry Smith     ssize = 3*(ex->nvars);
585*792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructStencilCreate,dim,ssize,&ex->ss_stencil);
586f4bdf6c4SBarry Smith     cnt= 0;
587f4bdf6c4SBarry Smith     for (i = 0; i < (ex->nvars); i++) {
588f4bdf6c4SBarry Smith       for (j = 0; j < 3; j++) {
589*792fecdfSBarry Smith         PetscCallExternal(HYPRE_SStructStencilSetEntry,ex->ss_stencil, cnt, offsets[j], i);
590f4bdf6c4SBarry Smith         cnt++;
591f4bdf6c4SBarry Smith       }
592f4bdf6c4SBarry Smith     }
593f4bdf6c4SBarry Smith   } else if (dim == 2) {
5942cf14000SStefano Zampini     HYPRE_Int offsets[5][2] = {{0,-1},{-1,0},{0,0},{1,0},{0,1}};
5954ddd07fcSJed Brown     PetscInt  j, cnt;
596f4bdf6c4SBarry Smith 
597f4bdf6c4SBarry Smith     ssize = 5*(ex->nvars);
598*792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructStencilCreate,dim,ssize,&ex->ss_stencil);
599f4bdf6c4SBarry Smith     cnt= 0;
600f4bdf6c4SBarry Smith     for (i= 0; i< (ex->nvars); i++) {
601f4bdf6c4SBarry Smith       for (j= 0; j< 5; j++) {
602*792fecdfSBarry Smith         PetscCallExternal(HYPRE_SStructStencilSetEntry,ex->ss_stencil, cnt, offsets[j], i);
603f4bdf6c4SBarry Smith         cnt++;
604f4bdf6c4SBarry Smith       }
605f4bdf6c4SBarry Smith     }
606f4bdf6c4SBarry Smith   } else if (dim == 3) {
6072cf14000SStefano 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}};
6084ddd07fcSJed Brown     PetscInt  j, cnt;
609f4bdf6c4SBarry Smith 
610f4bdf6c4SBarry Smith     ssize = 7*(ex->nvars);
611*792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructStencilCreate,dim,ssize,&ex->ss_stencil);
612f4bdf6c4SBarry Smith     cnt= 0;
613f4bdf6c4SBarry Smith     for (i= 0; i< (ex->nvars); i++) {
614f4bdf6c4SBarry Smith       for (j= 0; j< 7; j++) {
615*792fecdfSBarry Smith         PetscCallExternal(HYPRE_SStructStencilSetEntry,ex->ss_stencil, cnt, offsets[j], i);
616f4bdf6c4SBarry Smith         cnt++;
617f4bdf6c4SBarry Smith       }
618f4bdf6c4SBarry Smith     }
619f4bdf6c4SBarry Smith   }
620f4bdf6c4SBarry Smith 
621f4bdf6c4SBarry Smith   /* create the HYPRE graph */
622*792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGraphCreate,ex->hcomm, ex->ss_grid, &(ex->ss_graph));
623f4bdf6c4SBarry Smith 
624f4bdf6c4SBarry Smith   /* set the stencil graph. Note that each variable has the same graph. This means that each
625f4bdf6c4SBarry Smith      variable couples to all the other variable and with the same stencil pattern. */
626f4bdf6c4SBarry Smith   for (i= 0; i< (ex->nvars); i++) {
627*792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructGraphSetStencil,ex->ss_graph,part,i,ex->ss_stencil);
628f4bdf6c4SBarry Smith   }
629*792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGraphAssemble,ex->ss_graph);
630f4bdf6c4SBarry Smith 
631f4bdf6c4SBarry Smith   /* create the HYPRE sstruct vectors for rhs and solution */
632*792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorCreate,ex->hcomm,ex->ss_grid,&ex->ss_b);
633*792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorCreate,ex->hcomm,ex->ss_grid,&ex->ss_x);
634*792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorInitialize,ex->ss_b);
635*792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorInitialize,ex->ss_x);
636*792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorAssemble,ex->ss_b);
637*792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorAssemble,ex->ss_x);
638f4bdf6c4SBarry Smith 
639f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
640*792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructMatrixCreate,ex->hcomm,ex->ss_graph,&ex->ss_mat);
641*792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGridDestroy,ex->ss_grid);
642*792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructStencilDestroy,ex->ss_stencil);
643f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
644*792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixInitialize,ex->ss_mat);
645f4bdf6c4SBarry Smith     ex->needsinitialization = PETSC_FALSE;
646f4bdf6c4SBarry Smith   }
647f4bdf6c4SBarry Smith 
648f4bdf6c4SBarry Smith   /* set the global and local sizes of the matrix */
6499566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da,0,0,0,&nx,&ny,&nz));
6509566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat,dof*nx*ny*nz,dof*nx*ny*nz,PETSC_DECIDE,PETSC_DECIDE));
6519566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->rmap,dof));
6529566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->cmap,dof));
6539566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->rmap));
6549566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->cmap));
65561710fbeSStefano Zampini   mat->preallocated = PETSC_TRUE;
656f4bdf6c4SBarry Smith 
657f4bdf6c4SBarry Smith   if (dim == 3) {
658f4bdf6c4SBarry Smith     mat->ops->setvalueslocal = MatSetValuesLocal_HYPRESStruct_3d;
659f4bdf6c4SBarry Smith     mat->ops->zerorowslocal  = MatZeroRowsLocal_HYPRESStruct_3d;
660f4bdf6c4SBarry Smith     mat->ops->zeroentries    = MatZeroEntries_HYPRESStruct_3d;
6618865f1eaSKarl Rupp 
6629566063dSJacob Faibussowitsch     /* PetscCall(MatZeroEntries_HYPRESStruct_3d(mat)); */
663ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Only support for 3d DMDA currently");
664f4bdf6c4SBarry Smith 
665f4bdf6c4SBarry Smith   /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
6669566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(mat,&ex->rstart,NULL));
6679566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(ex->da,&ltog));
6689566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **) &ex->gindices));
6699566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(ex->da,0,0,0,&ex->gnx,&ex->gnxgny,&ex->gnxgnygnz));
6708865f1eaSKarl Rupp 
671f4bdf6c4SBarry Smith   ex->gnxgny    *= ex->gnx;
672f4bdf6c4SBarry Smith   ex->gnxgnygnz *= ex->gnxgny;
6738865f1eaSKarl Rupp 
6749566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da,&ex->xs,&ex->ys,&ex->zs,&ex->nx,&ex->ny,&ex->nz));
6758865f1eaSKarl Rupp 
676f4bdf6c4SBarry Smith   ex->nxny   = ex->nx*ex->ny;
677f4bdf6c4SBarry Smith   ex->nxnynz = ex->nz*ex->nxny;
678f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
679f4bdf6c4SBarry Smith }
680f4bdf6c4SBarry Smith 
681f4bdf6c4SBarry Smith PetscErrorCode MatMult_HYPRESStruct(Mat A,Vec x,Vec y)
682f4bdf6c4SBarry Smith {
683b026d285SBarry Smith   const PetscScalar *xx;
684b026d285SBarry Smith   PetscScalar       *yy;
6852cf14000SStefano Zampini   HYPRE_Int         hlower[3],hupper[3];
6864ddd07fcSJed Brown   PetscInt          ilower[3],iupper[3];
687f4bdf6c4SBarry Smith   Mat_HYPRESStruct  *mx     = (Mat_HYPRESStruct*)(A->data);
6884ddd07fcSJed Brown   PetscInt          ordering= mx->dofs_order;
6894ddd07fcSJed Brown   PetscInt          nvars   = mx->nvars;
6904ddd07fcSJed Brown   PetscInt          part    = 0;
6914ddd07fcSJed Brown   PetscInt          size;
6924ddd07fcSJed Brown   PetscInt          i;
693f4bdf6c4SBarry Smith 
694f4bdf6c4SBarry Smith   PetscFunctionBegin;
6959566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]));
6962cf14000SStefano Zampini 
6972cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
698f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
699f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
700f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
7012cf14000SStefano Zampini   hlower[0]  = (HYPRE_Int)ilower[0];
7022cf14000SStefano Zampini   hlower[1]  = (HYPRE_Int)ilower[1];
7032cf14000SStefano Zampini   hlower[2]  = (HYPRE_Int)ilower[2];
7042cf14000SStefano Zampini   hupper[0]  = (HYPRE_Int)iupper[0];
7052cf14000SStefano Zampini   hupper[1]  = (HYPRE_Int)iupper[1];
7062cf14000SStefano Zampini   hupper[2]  = (HYPRE_Int)iupper[2];
707f4bdf6c4SBarry Smith 
708f4bdf6c4SBarry Smith   size= 1;
7098865f1eaSKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i]-ilower[i]+1);
710f4bdf6c4SBarry Smith 
711f4bdf6c4SBarry Smith   /* copy x values over to hypre for variable ordering */
712f4bdf6c4SBarry Smith   if (ordering) {
713*792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues,mx->ss_b,0.0);
7149566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x,&xx));
715f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
716*792fecdfSBarry Smith       PetscCallExternal(HYPRE_SStructVectorSetBoxValues,mx->ss_b,part,hlower,hupper,i,(HYPRE_Complex*)(xx+(size*i)));
717f4bdf6c4SBarry Smith     }
7189566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x,&xx));
719*792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble,mx->ss_b);
720*792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixMatvec,1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x);
721f4bdf6c4SBarry Smith 
722f4bdf6c4SBarry Smith     /* copy solution values back to PETSc */
7239566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y,&yy));
724f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
725*792fecdfSBarry Smith       PetscCallExternal(HYPRE_SStructVectorGetBoxValues,mx->ss_x,part,hlower,hupper,i,(HYPRE_Complex*)(yy+(size*i)));
726f4bdf6c4SBarry Smith     }
7279566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y,&yy));
728f4bdf6c4SBarry Smith   } else {      /* nodal ordering must be mapped to variable ordering for sys_pfmg */
729f4bdf6c4SBarry Smith     PetscScalar *z;
7304ddd07fcSJed Brown     PetscInt    j, k;
731f4bdf6c4SBarry Smith 
7329566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nvars*size,&z));
733*792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues,mx->ss_b,0.0);
7349566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x,&xx));
735f4bdf6c4SBarry Smith 
736f4bdf6c4SBarry Smith     /* transform nodal to hypre's variable ordering for sys_pfmg */
737f4bdf6c4SBarry Smith     for (i= 0; i< size; i++) {
738f4bdf6c4SBarry Smith       k= i*nvars;
7398865f1eaSKarl Rupp       for (j= 0; j< nvars; j++) z[j*size+i]= xx[k+j];
740f4bdf6c4SBarry Smith     }
741f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
742*792fecdfSBarry Smith       PetscCallExternal(HYPRE_SStructVectorSetBoxValues,mx->ss_b,part,hlower,hupper,i,(HYPRE_Complex*)(z+(size*i)));
743f4bdf6c4SBarry Smith     }
7449566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x,&xx));
745*792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble,mx->ss_b);
746*792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixMatvec,1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x);
747f4bdf6c4SBarry Smith 
748f4bdf6c4SBarry Smith     /* copy solution values back to PETSc */
7499566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y,&yy));
750f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
751*792fecdfSBarry Smith       PetscCallExternal(HYPRE_SStructVectorGetBoxValues,mx->ss_x,part,hlower,hupper,i,(HYPRE_Complex*)(z+(size*i)));
752f4bdf6c4SBarry Smith     }
753f4bdf6c4SBarry Smith     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
754f4bdf6c4SBarry Smith     for (i= 0; i< size; i++) {
755f4bdf6c4SBarry Smith       k= i*nvars;
7568865f1eaSKarl Rupp       for (j= 0; j< nvars; j++) yy[k+j]= z[j*size+i];
757f4bdf6c4SBarry Smith     }
7589566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y,&yy));
7599566063dSJacob Faibussowitsch     PetscCall(PetscFree(z));
760f4bdf6c4SBarry Smith   }
761f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
762f4bdf6c4SBarry Smith }
763f4bdf6c4SBarry Smith 
764f4bdf6c4SBarry Smith PetscErrorCode MatAssemblyEnd_HYPRESStruct(Mat mat,MatAssemblyType mode)
765f4bdf6c4SBarry Smith {
766f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data;
767f4bdf6c4SBarry Smith 
768f4bdf6c4SBarry Smith   PetscFunctionBegin;
769*792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructMatrixAssemble,ex->ss_mat);
770f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
771f4bdf6c4SBarry Smith }
772f4bdf6c4SBarry Smith 
773f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPRESStruct(Mat mat)
774f4bdf6c4SBarry Smith {
775f4bdf6c4SBarry Smith   PetscFunctionBegin;
776f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
777f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
778f4bdf6c4SBarry Smith }
779f4bdf6c4SBarry Smith 
780f4bdf6c4SBarry Smith PetscErrorCode MatDestroy_HYPRESStruct(Mat mat)
781f4bdf6c4SBarry Smith {
782f4bdf6c4SBarry Smith   Mat_HYPRESStruct       *ex = (Mat_HYPRESStruct*) mat->data;
783d94fc0b6SBarry Smith   ISLocalToGlobalMapping ltog;
784f4bdf6c4SBarry Smith 
785f4bdf6c4SBarry Smith   PetscFunctionBegin;
7869566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(ex->da,&ltog));
7879566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreIndices(ltog, (const PetscInt **) &ex->gindices));
788*792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGraphDestroy,ex->ss_graph);
789*792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructMatrixDestroy,ex->ss_mat);
790*792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorDestroy,ex->ss_x);
791*792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorDestroy,ex->ss_b);
7929566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)ex->da));
7939566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&(ex->hcomm)));
7949566063dSJacob Faibussowitsch   PetscCall(PetscFree(ex));
795f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
796f4bdf6c4SBarry Smith }
797f4bdf6c4SBarry Smith 
7988cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_HYPRESStruct(Mat B)
799f4bdf6c4SBarry Smith {
800f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex;
801f4bdf6c4SBarry Smith 
802f4bdf6c4SBarry Smith   PetscFunctionBegin;
8039566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(B,&ex));
804f4bdf6c4SBarry Smith   B->data      = (void*)ex;
805f4bdf6c4SBarry Smith   B->rmap->bs  = 1;
806f4bdf6c4SBarry Smith   B->assembled = PETSC_FALSE;
807f4bdf6c4SBarry Smith 
808f4bdf6c4SBarry Smith   B->insertmode = NOT_SET_VALUES;
809f4bdf6c4SBarry Smith 
810f4bdf6c4SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_HYPRESStruct;
811f4bdf6c4SBarry Smith   B->ops->mult        = MatMult_HYPRESStruct;
812f4bdf6c4SBarry Smith   B->ops->zeroentries = MatZeroEntries_HYPRESStruct;
813f4bdf6c4SBarry Smith   B->ops->destroy     = MatDestroy_HYPRESStruct;
81459cb773eSBarry Smith   B->ops->setup       = MatSetUp_HYPRESStruct;
815f4bdf6c4SBarry Smith 
816f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
817f4bdf6c4SBarry Smith 
8189566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_dup(PetscObjectComm((PetscObject)B),&(ex->hcomm)));
8199566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B,MATHYPRESSTRUCT));
820f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
821f4bdf6c4SBarry Smith }
822