xref: /petsc/src/dm/impls/da/hypre/mhyp.c (revision 08401ef684002a709c6d3db98a0c9f54a8bcf1ec)
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 
2559cb773eSBarry Smith .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;
36*08401ef6SPierre Jolivet   PetscCheck(ncol <= 7,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"ncol %D > 7 too large",ncol);
37f4bdf6c4SBarry Smith   for (i=0; i<nrow; i++) {
38f4bdf6c4SBarry Smith     for (j=0; j<ncol; j++) {
39f4bdf6c4SBarry Smith       stencil = icol[j] - irow[i];
40f4bdf6c4SBarry Smith       if (!stencil) {
41f4bdf6c4SBarry Smith         entries[j] = 3;
42f4bdf6c4SBarry Smith       } else if (stencil == -1) {
43f4bdf6c4SBarry Smith         entries[j] = 2;
44f4bdf6c4SBarry Smith       } else if (stencil == 1) {
45f4bdf6c4SBarry Smith         entries[j] = 4;
46f4bdf6c4SBarry Smith       } else if (stencil == -ex->gnx) {
47f4bdf6c4SBarry Smith         entries[j] = 1;
48f4bdf6c4SBarry Smith       } else if (stencil == ex->gnx) {
49f4bdf6c4SBarry Smith         entries[j] = 5;
50f4bdf6c4SBarry Smith       } else if (stencil == -ex->gnxgny) {
51f4bdf6c4SBarry Smith         entries[j] = 0;
52f4bdf6c4SBarry Smith       } else if (stencil == ex->gnxgny) {
53f4bdf6c4SBarry Smith         entries[j] = 6;
5498921bdaSJacob Faibussowitsch       } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row %D local column %D have bad stencil %D",irow[i],icol[j],stencil);
55f4bdf6c4SBarry Smith     }
56f4bdf6c4SBarry Smith     row      = ex->gindices[irow[i]] - ex->rstart;
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)));
60f4bdf6c4SBarry Smith     if (addv == ADD_VALUES) {
61a74df02fSJacob Faibussowitsch       PetscStackCallStandard(HYPRE_StructMatrixAddToValues,ex->hmat,index,ncol,entries,values);
62f4bdf6c4SBarry Smith     } else {
63a74df02fSJacob Faibussowitsch       PetscStackCallStandard(HYPRE_StructMatrixSetValues,ex->hmat,index,ncol,entries,values);
64f4bdf6c4SBarry Smith     }
65f4bdf6c4SBarry Smith     values += ncol;
66f4bdf6c4SBarry Smith   }
67f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
68f4bdf6c4SBarry Smith }
69f4bdf6c4SBarry Smith 
70f4bdf6c4SBarry Smith PetscErrorCode  MatZeroRowsLocal_HYPREStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscScalar d,Vec x,Vec b)
71f4bdf6c4SBarry Smith {
722cf14000SStefano Zampini   HYPRE_Int       index[3],entries[7] = {0,1,2,3,4,5,6};
732cf14000SStefano Zampini   PetscInt        row,i;
7439accc25SStefano Zampini   HYPRE_Complex   values[7];
75f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
76f4bdf6c4SBarry Smith 
77f4bdf6c4SBarry Smith   PetscFunctionBegin;
78*08401ef6SPierre Jolivet   PetscCheck(!x || !b,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"No support");
799566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(values,7));
809566063dSJacob Faibussowitsch   PetscCall(PetscHYPREScalarCast(d,&values[3]));
81f4bdf6c4SBarry Smith   for (i=0; i<nrow; i++) {
82f4bdf6c4SBarry Smith     row      = ex->gindices[irow[i]] - ex->rstart;
832cf14000SStefano Zampini     index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
842cf14000SStefano Zampini     index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
852cf14000SStefano Zampini     index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
86a74df02fSJacob Faibussowitsch     PetscStackCallStandard(HYPRE_StructMatrixSetValues,ex->hmat,index,7,entries,values);
87f4bdf6c4SBarry Smith   }
88a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_StructMatrixAssemble,ex->hmat);
89f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
90f4bdf6c4SBarry Smith }
91f4bdf6c4SBarry Smith 
92f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPREStruct_3d(Mat mat)
93f4bdf6c4SBarry Smith {
942cf14000SStefano Zampini   HYPRE_Int       indices[7] = {0,1,2,3,4,5,6};
95f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex        = (Mat_HYPREStruct*) mat->data;
96f4bdf6c4SBarry Smith 
97f4bdf6c4SBarry Smith   PetscFunctionBegin;
98f4bdf6c4SBarry Smith   /* hypre has no public interface to do this */
99a74df02fSJacob Faibussowitsch   PetscStackCallStandard(hypre_StructMatrixClearBoxValues,ex->hmat,&ex->hbox,7,indices,0,1);
100a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_StructMatrixAssemble,ex->hmat);
101f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
102f4bdf6c4SBarry Smith }
103f4bdf6c4SBarry Smith 
10459cb773eSBarry Smith static PetscErrorCode  MatSetUp_HYPREStruct(Mat mat)
105f4bdf6c4SBarry Smith {
106f4bdf6c4SBarry Smith   Mat_HYPREStruct        *ex = (Mat_HYPREStruct*) mat->data;
1072cf14000SStefano Zampini   HYPRE_Int              sw[6];
1082cf14000SStefano Zampini   HYPRE_Int              hlower[3],hupper[3];
1092cf14000SStefano Zampini   PetscInt               dim,dof,psw,nx,ny,nz,ilower[3],iupper[3],ssize,i;
110bff4a2f0SMatthew G. Knepley   DMBoundaryType         px,py,pz;
111f4bdf6c4SBarry Smith   DMDAStencilType        st;
112565245c5SBarry Smith   ISLocalToGlobalMapping ltog;
11359cb773eSBarry Smith   DM                     da;
114f4bdf6c4SBarry Smith 
115f4bdf6c4SBarry Smith   PetscFunctionBegin;
1169566063dSJacob Faibussowitsch   PetscCall(MatGetDM(mat,(DM*)&da));
117f4bdf6c4SBarry Smith   ex->da = da;
1189566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)da));
119f4bdf6c4SBarry Smith 
1209566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(ex->da,&dim,0,0,0,0,0,0,&dof,&psw,&px,&py,&pz,&st));
1219566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]));
1222cf14000SStefano Zampini 
1232cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
124f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
125f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
126f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
1272cf14000SStefano Zampini   hlower[0]  = (HYPRE_Int)ilower[0];
1282cf14000SStefano Zampini   hlower[1]  = (HYPRE_Int)ilower[1];
1292cf14000SStefano Zampini   hlower[2]  = (HYPRE_Int)ilower[2];
1302cf14000SStefano Zampini   hupper[0]  = (HYPRE_Int)iupper[0];
1312cf14000SStefano Zampini   hupper[1]  = (HYPRE_Int)iupper[1];
1322cf14000SStefano Zampini   hupper[2]  = (HYPRE_Int)iupper[2];
133f4bdf6c4SBarry Smith 
134f4bdf6c4SBarry Smith   /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
1352cf14000SStefano Zampini   ex->hbox.imin[0] = hlower[0];
1362cf14000SStefano Zampini   ex->hbox.imin[1] = hlower[1];
1372cf14000SStefano Zampini   ex->hbox.imin[2] = hlower[2];
1382cf14000SStefano Zampini   ex->hbox.imax[0] = hupper[0];
1392cf14000SStefano Zampini   ex->hbox.imax[1] = hupper[1];
1402cf14000SStefano Zampini   ex->hbox.imax[2] = hupper[2];
141f4bdf6c4SBarry Smith 
142f4bdf6c4SBarry Smith   /* create the hypre grid object and set its information */
143*08401ef6SPierre Jolivet   PetscCheck(dof <= 1,PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Currently only support for scalar problems");
1442c71b3e2SJacob Faibussowitsch   PetscCheckFalse(px || py || pz,PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add periodic support by calling HYPRE_StructGridSetPeriodic()");
145a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_StructGridCreate,ex->hcomm,dim,&ex->hgrid);
146a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_StructGridSetExtents,ex->hgrid,hlower,hupper);
147a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_StructGridAssemble,ex->hgrid);
148f4bdf6c4SBarry Smith 
1492cf14000SStefano Zampini   sw[5] = sw[4] = sw[3] = sw[2] = sw[1] = sw[0] = psw;
150a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_StructGridSetNumGhost,ex->hgrid,sw);
151f4bdf6c4SBarry Smith 
152f4bdf6c4SBarry Smith   /* create the hypre stencil object and set its information */
153*08401ef6SPierre Jolivet   PetscCheck(sw[0] <= 1,PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for wider stencils");
154*08401ef6SPierre Jolivet   PetscCheck(st != DMDA_STENCIL_BOX,PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for box stencils");
155f4bdf6c4SBarry Smith   if (dim == 1) {
1562cf14000SStefano Zampini     HYPRE_Int offsets[3][1] = {{-1},{0},{1}};
157f4bdf6c4SBarry Smith     ssize = 3;
158a74df02fSJacob Faibussowitsch     PetscStackCallStandard(HYPRE_StructStencilCreate,dim,ssize,&ex->hstencil);
159f4bdf6c4SBarry Smith     for (i=0; i<ssize; i++) {
160a74df02fSJacob Faibussowitsch       PetscStackCallStandard(HYPRE_StructStencilSetElement,ex->hstencil,i,offsets[i]);
161f4bdf6c4SBarry Smith     }
162f4bdf6c4SBarry Smith   } else if (dim == 2) {
1632cf14000SStefano Zampini     HYPRE_Int offsets[5][2] = {{0,-1},{-1,0},{0,0},{1,0},{0,1}};
164f4bdf6c4SBarry Smith     ssize = 5;
165a74df02fSJacob Faibussowitsch     PetscStackCallStandard(HYPRE_StructStencilCreate,dim,ssize,&ex->hstencil);
166f4bdf6c4SBarry Smith     for (i=0; i<ssize; i++) {
167a74df02fSJacob Faibussowitsch       PetscStackCallStandard(HYPRE_StructStencilSetElement,ex->hstencil,i,offsets[i]);
168f4bdf6c4SBarry Smith     }
169f4bdf6c4SBarry Smith   } else if (dim == 3) {
1702cf14000SStefano 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}};
171f4bdf6c4SBarry Smith     ssize = 7;
172a74df02fSJacob Faibussowitsch     PetscStackCallStandard(HYPRE_StructStencilCreate,dim,ssize,&ex->hstencil);
173f4bdf6c4SBarry Smith     for (i=0; i<ssize; i++) {
174a74df02fSJacob Faibussowitsch       PetscStackCallStandard(HYPRE_StructStencilSetElement,ex->hstencil,i,offsets[i]);
175f4bdf6c4SBarry Smith     }
176f4bdf6c4SBarry Smith   }
177f4bdf6c4SBarry Smith 
178f4bdf6c4SBarry Smith   /* create the HYPRE vector for rhs and solution */
179a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_StructVectorCreate,ex->hcomm,ex->hgrid,&ex->hb);
180a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_StructVectorCreate,ex->hcomm,ex->hgrid,&ex->hx);
181a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_StructVectorInitialize,ex->hb);
182a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_StructVectorInitialize,ex->hx);
183a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_StructVectorAssemble,ex->hb);
184a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_StructVectorAssemble,ex->hx);
185f4bdf6c4SBarry Smith 
186f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
187a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_StructMatrixCreate,ex->hcomm,ex->hgrid,ex->hstencil,&ex->hmat);
188a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_StructGridDestroy,ex->hgrid);
189a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_StructStencilDestroy,ex->hstencil);
190f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
191a74df02fSJacob Faibussowitsch     PetscStackCallStandard(HYPRE_StructMatrixInitialize,ex->hmat);
192f4bdf6c4SBarry Smith     ex->needsinitialization = PETSC_FALSE;
193f4bdf6c4SBarry Smith   }
194f4bdf6c4SBarry Smith 
195f4bdf6c4SBarry Smith   /* set the global and local sizes of the matrix */
1969566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da,0,0,0,&nx,&ny,&nz));
1979566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat,dof*nx*ny*nz,dof*nx*ny*nz,PETSC_DECIDE,PETSC_DECIDE));
1989566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->rmap,1));
1999566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->cmap,1));
2009566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->rmap));
2019566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->cmap));
20259cb773eSBarry Smith   mat->preallocated = PETSC_TRUE;
203f4bdf6c4SBarry Smith 
204f4bdf6c4SBarry Smith   if (dim == 3) {
205f4bdf6c4SBarry Smith     mat->ops->setvalueslocal = MatSetValuesLocal_HYPREStruct_3d;
206f4bdf6c4SBarry Smith     mat->ops->zerorowslocal  = MatZeroRowsLocal_HYPREStruct_3d;
207f4bdf6c4SBarry Smith     mat->ops->zeroentries    = MatZeroEntries_HYPREStruct_3d;
2088865f1eaSKarl Rupp 
2099566063dSJacob Faibussowitsch     /*        PetscCall(MatZeroEntries_HYPREStruct_3d(mat)); */
210ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Only support for 3d DMDA currently");
211f4bdf6c4SBarry Smith 
212f4bdf6c4SBarry Smith   /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
2139566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(mat,&ex->rstart,NULL));
2149566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(ex->da,&ltog));
2159566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **) &ex->gindices));
2169566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(ex->da,0,0,0,&ex->gnx,&ex->gnxgny,0));
217f4bdf6c4SBarry Smith   ex->gnxgny *= ex->gnx;
2189566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da,&ex->xs,&ex->ys,&ex->zs,&ex->nx,&ex->ny,0));
219f4bdf6c4SBarry Smith   ex->nxny    = ex->nx*ex->ny;
220f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
221f4bdf6c4SBarry Smith }
222f4bdf6c4SBarry Smith 
223f4bdf6c4SBarry Smith PetscErrorCode MatMult_HYPREStruct(Mat A,Vec x,Vec y)
224f4bdf6c4SBarry Smith {
225b026d285SBarry Smith   const PetscScalar *xx;
226b026d285SBarry Smith   PetscScalar       *yy;
2274ddd07fcSJed Brown   PetscInt          ilower[3],iupper[3];
2282cf14000SStefano Zampini   HYPRE_Int         hlower[3],hupper[3];
229f4bdf6c4SBarry Smith   Mat_HYPREStruct   *mx = (Mat_HYPREStruct*)(A->data);
230f4bdf6c4SBarry Smith 
231f4bdf6c4SBarry Smith   PetscFunctionBegin;
2329566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]));
2332cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
234f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
235f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
236f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
2372cf14000SStefano Zampini   hlower[0]  = (HYPRE_Int)ilower[0];
2382cf14000SStefano Zampini   hlower[1]  = (HYPRE_Int)ilower[1];
2392cf14000SStefano Zampini   hlower[2]  = (HYPRE_Int)ilower[2];
2402cf14000SStefano Zampini   hupper[0]  = (HYPRE_Int)iupper[0];
2412cf14000SStefano Zampini   hupper[1]  = (HYPRE_Int)iupper[1];
2422cf14000SStefano Zampini   hupper[2]  = (HYPRE_Int)iupper[2];
243f4bdf6c4SBarry Smith 
244f4bdf6c4SBarry Smith   /* copy x values over to hypre */
245a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_StructVectorSetConstantValues,mx->hb,0.0);
2469566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x,&xx));
247a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_StructVectorSetBoxValues,mx->hb,hlower,hupper,(HYPRE_Complex*)xx);
2489566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x,&xx));
249a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_StructVectorAssemble,mx->hb);
250a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_StructMatrixMatvec,1.0,mx->hmat,mx->hb,0.0,mx->hx);
251f4bdf6c4SBarry Smith 
252f4bdf6c4SBarry Smith   /* copy solution values back to PETSc */
2539566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y,&yy));
254a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_StructVectorGetBoxValues,mx->hx,hlower,hupper,(HYPRE_Complex*)yy);
2559566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y,&yy));
256f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
257f4bdf6c4SBarry Smith }
258f4bdf6c4SBarry Smith 
259f4bdf6c4SBarry Smith PetscErrorCode MatAssemblyEnd_HYPREStruct(Mat mat,MatAssemblyType mode)
260f4bdf6c4SBarry Smith {
261f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
262f4bdf6c4SBarry Smith 
263f4bdf6c4SBarry Smith   PetscFunctionBegin;
264a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_StructMatrixAssemble,ex->hmat);
265a74df02fSJacob Faibussowitsch   /* PetscStackCallStandard(HYPRE_StructMatrixPrint,"dummy",ex->hmat,0); */
266f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
267f4bdf6c4SBarry Smith }
268f4bdf6c4SBarry Smith 
269f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPREStruct(Mat mat)
270f4bdf6c4SBarry Smith {
271f4bdf6c4SBarry Smith   PetscFunctionBegin;
272f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
273f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
274f4bdf6c4SBarry Smith }
275f4bdf6c4SBarry Smith 
276f4bdf6c4SBarry Smith PetscErrorCode MatDestroy_HYPREStruct(Mat mat)
277f4bdf6c4SBarry Smith {
278f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data;
279f4bdf6c4SBarry Smith 
280f4bdf6c4SBarry Smith   PetscFunctionBegin;
281a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_StructMatrixDestroy,ex->hmat);
282a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_StructVectorDestroy,ex->hx);
283a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_StructVectorDestroy,ex->hb);
2849566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)ex->da));
2859566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&(ex->hcomm)));
2869566063dSJacob Faibussowitsch   PetscCall(PetscFree(ex));
287f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
288f4bdf6c4SBarry Smith }
289f4bdf6c4SBarry Smith 
2908cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_HYPREStruct(Mat B)
291f4bdf6c4SBarry Smith {
292f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex;
293f4bdf6c4SBarry Smith 
294f4bdf6c4SBarry Smith   PetscFunctionBegin;
2959566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(B,&ex));
296f4bdf6c4SBarry Smith   B->data      = (void*)ex;
297f4bdf6c4SBarry Smith   B->rmap->bs  = 1;
298f4bdf6c4SBarry Smith   B->assembled = PETSC_FALSE;
299f4bdf6c4SBarry Smith 
300f4bdf6c4SBarry Smith   B->insertmode = NOT_SET_VALUES;
301f4bdf6c4SBarry Smith 
302f4bdf6c4SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_HYPREStruct;
303f4bdf6c4SBarry Smith   B->ops->mult        = MatMult_HYPREStruct;
304f4bdf6c4SBarry Smith   B->ops->zeroentries = MatZeroEntries_HYPREStruct;
305f4bdf6c4SBarry Smith   B->ops->destroy     = MatDestroy_HYPREStruct;
30659cb773eSBarry Smith   B->ops->setup       = MatSetUp_HYPREStruct;
307f4bdf6c4SBarry Smith 
308f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
309f4bdf6c4SBarry Smith 
3109566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_dup(PetscObjectComm((PetscObject)B),&(ex->hcomm)));
3119566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B,MATHYPRESTRUCT));
312f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
313f4bdf6c4SBarry Smith }
314f4bdf6c4SBarry Smith 
315f4bdf6c4SBarry Smith /*MC
316f4bdf6c4SBarry Smith    MATHYPRESSTRUCT - MATHYPRESSTRUCT = "hypresstruct" - A matrix type to be used for parallel sparse matrices
317f4bdf6c4SBarry Smith           based on the hypre HYPRE_SStructMatrix.
318f4bdf6c4SBarry Smith 
319f4bdf6c4SBarry Smith    Level: intermediate
320f4bdf6c4SBarry Smith 
32195452b02SPatrick Sanan    Notes:
32295452b02SPatrick Sanan     Unlike hypre's general semi-struct object consisting of a collection of structured-grid objects and unstructured
323b026d285SBarry Smith           grid objects, we restrict the semi-struct objects to consist of only structured-grid components.
324f4bdf6c4SBarry Smith 
325f4bdf6c4SBarry 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
326f4bdf6c4SBarry Smith           be defined by a DMDA.
327f4bdf6c4SBarry Smith 
32859cb773eSBarry Smith           The matrix needs a DMDA associated with it by either a call to MatSetDM() or if the matrix is obtained from DMCreateMatrix()
329f4bdf6c4SBarry Smith 
330f4bdf6c4SBarry Smith M*/
331f4bdf6c4SBarry Smith 
332f4bdf6c4SBarry Smith PetscErrorCode  MatSetValuesLocal_HYPRESStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)
333f4bdf6c4SBarry Smith {
3342cf14000SStefano Zampini   HYPRE_Int         index[3],*entries;
3352cf14000SStefano Zampini   PetscInt          i,j,stencil;
33639accc25SStefano Zampini   HYPRE_Complex     *values = (HYPRE_Complex*)y;
337f4bdf6c4SBarry Smith   Mat_HYPRESStruct  *ex     = (Mat_HYPRESStruct*) mat->data;
338f4bdf6c4SBarry Smith 
3394ddd07fcSJed Brown   PetscInt          part = 0;          /* Petsc sstruct interface only allows 1 part */
3404ddd07fcSJed Brown   PetscInt          ordering;
3414ddd07fcSJed Brown   PetscInt          grid_rank, to_grid_rank;
3424ddd07fcSJed Brown   PetscInt          var_type, to_var_type;
3434ddd07fcSJed Brown   PetscInt          to_var_entry = 0;
3444ddd07fcSJed Brown   PetscInt          nvars= ex->nvars;
3452cf14000SStefano Zampini   PetscInt          row;
346f4bdf6c4SBarry Smith 
347f4bdf6c4SBarry Smith   PetscFunctionBegin;
3489566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(7*nvars,&entries));
349f4bdf6c4SBarry Smith   ordering = ex->dofs_order;  /* ordering= 0   nodal ordering
350f4bdf6c4SBarry Smith                                            1   variable ordering */
35161710fbeSStefano Zampini   /* stencil entries are ordered by variables: var0_stencil0, var0_stencil1, ..., var0_stencil6, var1_stencil0, var1_stencil1, ...  */
352f4bdf6c4SBarry Smith   if (!ordering) {
353f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
354f4bdf6c4SBarry Smith       grid_rank= irow[i]/nvars;
355f4bdf6c4SBarry Smith       var_type = (irow[i] % nvars);
356f4bdf6c4SBarry Smith 
357f4bdf6c4SBarry Smith       for (j=0; j<ncol; j++) {
358f4bdf6c4SBarry Smith         to_grid_rank= icol[j]/nvars;
359f4bdf6c4SBarry Smith         to_var_type = (icol[j] % nvars);
360f4bdf6c4SBarry Smith 
361f4bdf6c4SBarry Smith         to_var_entry= to_var_entry*7;
362f4bdf6c4SBarry Smith         entries[j]  = to_var_entry;
363f4bdf6c4SBarry Smith 
364f4bdf6c4SBarry Smith         stencil = to_grid_rank-grid_rank;
365f4bdf6c4SBarry Smith         if (!stencil) {
366f4bdf6c4SBarry Smith           entries[j] += 3;
367f4bdf6c4SBarry Smith         } else if (stencil == -1) {
368f4bdf6c4SBarry Smith           entries[j] += 2;
369f4bdf6c4SBarry Smith         } else if (stencil == 1) {
370f4bdf6c4SBarry Smith           entries[j] += 4;
371f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnx) {
372f4bdf6c4SBarry Smith           entries[j] += 1;
373f4bdf6c4SBarry Smith         } else if (stencil == ex->gnx) {
374f4bdf6c4SBarry Smith           entries[j] += 5;
375f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnxgny) {
376f4bdf6c4SBarry Smith           entries[j] += 0;
377f4bdf6c4SBarry Smith         } else if (stencil == ex->gnxgny) {
378f4bdf6c4SBarry Smith           entries[j] += 6;
37998921bdaSJacob Faibussowitsch         } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row %D local column %D have bad stencil %D",irow[i],icol[j],stencil);
380f4bdf6c4SBarry Smith       }
381f4bdf6c4SBarry Smith 
382f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
3832cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
3842cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
3852cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
386f4bdf6c4SBarry Smith 
387f4bdf6c4SBarry Smith       if (addv == ADD_VALUES) {
388a74df02fSJacob Faibussowitsch         PetscStackCallStandard(HYPRE_SStructMatrixAddToValues,ex->ss_mat,part,index,var_type,ncol,entries,values);
389f4bdf6c4SBarry Smith       } else {
390a74df02fSJacob Faibussowitsch         PetscStackCallStandard(HYPRE_SStructMatrixSetValues,ex->ss_mat,part,index,var_type,ncol,entries,values);
391f4bdf6c4SBarry Smith       }
392f4bdf6c4SBarry Smith       values += ncol;
393f4bdf6c4SBarry Smith     }
394f4bdf6c4SBarry Smith   } else {
395f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
396f4bdf6c4SBarry Smith       var_type = irow[i]/(ex->gnxgnygnz);
397f4bdf6c4SBarry Smith       grid_rank= irow[i] - var_type*(ex->gnxgnygnz);
398f4bdf6c4SBarry Smith 
399f4bdf6c4SBarry Smith       for (j=0; j<ncol; j++) {
400f4bdf6c4SBarry Smith         to_var_type = icol[j]/(ex->gnxgnygnz);
401f4bdf6c4SBarry Smith         to_grid_rank= icol[j] - to_var_type*(ex->gnxgnygnz);
402f4bdf6c4SBarry Smith 
403f4bdf6c4SBarry Smith         to_var_entry= to_var_entry*7;
404f4bdf6c4SBarry Smith         entries[j]  = to_var_entry;
405f4bdf6c4SBarry Smith 
406f4bdf6c4SBarry Smith         stencil = to_grid_rank-grid_rank;
407f4bdf6c4SBarry Smith         if (!stencil) {
408f4bdf6c4SBarry Smith           entries[j] += 3;
409f4bdf6c4SBarry Smith         } else if (stencil == -1) {
410f4bdf6c4SBarry Smith           entries[j] += 2;
411f4bdf6c4SBarry Smith         } else if (stencil == 1) {
412f4bdf6c4SBarry Smith           entries[j] += 4;
413f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnx) {
414f4bdf6c4SBarry Smith           entries[j] += 1;
415f4bdf6c4SBarry Smith         } else if (stencil == ex->gnx) {
416f4bdf6c4SBarry Smith           entries[j] += 5;
417f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnxgny) {
418f4bdf6c4SBarry Smith           entries[j] += 0;
419f4bdf6c4SBarry Smith         } else if (stencil == ex->gnxgny) {
420f4bdf6c4SBarry Smith           entries[j] += 6;
42198921bdaSJacob Faibussowitsch         } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row %D local column %D have bad stencil %D",irow[i],icol[j],stencil);
422f4bdf6c4SBarry Smith       }
423f4bdf6c4SBarry Smith 
424f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
4252cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
4262cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
4272cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
428f4bdf6c4SBarry Smith 
429f4bdf6c4SBarry Smith       if (addv == ADD_VALUES) {
430a74df02fSJacob Faibussowitsch         PetscStackCallStandard(HYPRE_SStructMatrixAddToValues,ex->ss_mat,part,index,var_type,ncol,entries,values);
431f4bdf6c4SBarry Smith       } else {
432a74df02fSJacob Faibussowitsch         PetscStackCallStandard(HYPRE_SStructMatrixSetValues,ex->ss_mat,part,index,var_type,ncol,entries,values);
433f4bdf6c4SBarry Smith       }
434f4bdf6c4SBarry Smith       values += ncol;
435f4bdf6c4SBarry Smith     }
436f4bdf6c4SBarry Smith   }
4379566063dSJacob Faibussowitsch   PetscCall(PetscFree(entries));
438f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
439f4bdf6c4SBarry Smith }
440f4bdf6c4SBarry Smith 
441f4bdf6c4SBarry Smith PetscErrorCode  MatZeroRowsLocal_HYPRESStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscScalar d,Vec x,Vec b)
442f4bdf6c4SBarry Smith {
4432cf14000SStefano Zampini   HYPRE_Int        index[3],*entries;
4442cf14000SStefano Zampini   PetscInt         i;
44539accc25SStefano Zampini   HYPRE_Complex    **values;
446f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data;
447f4bdf6c4SBarry Smith 
4484ddd07fcSJed Brown   PetscInt         part     = 0;      /* Petsc sstruct interface only allows 1 part */
4494ddd07fcSJed Brown   PetscInt         ordering = ex->dofs_order;
4504ddd07fcSJed Brown   PetscInt         grid_rank;
4514ddd07fcSJed Brown   PetscInt         var_type;
4524ddd07fcSJed Brown   PetscInt         nvars= ex->nvars;
4532cf14000SStefano Zampini   PetscInt         row;
454f4bdf6c4SBarry Smith 
455f4bdf6c4SBarry Smith   PetscFunctionBegin;
456*08401ef6SPierre Jolivet   PetscCheck(!x || !b,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"No support");
4579566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(7*nvars,&entries));
458f4bdf6c4SBarry Smith 
4599566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nvars,&values));
4609566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(7*nvars*nvars,&values[0]));
461f4bdf6c4SBarry Smith   for (i=1; i<nvars; i++) {
462f4bdf6c4SBarry Smith     values[i] = values[i-1] + nvars*7;
463f4bdf6c4SBarry Smith   }
464f4bdf6c4SBarry Smith 
465f4bdf6c4SBarry Smith   for (i=0; i< nvars; i++) {
4669566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(values[i],nvars*7*sizeof(HYPRE_Complex)));
4679566063dSJacob Faibussowitsch     PetscCall(PetscHYPREScalarCast(d,values[i]+3));
468f4bdf6c4SBarry Smith   }
469f4bdf6c4SBarry Smith 
4708865f1eaSKarl Rupp   for (i=0; i< nvars*7; i++) entries[i] = i;
471f4bdf6c4SBarry Smith 
472f4bdf6c4SBarry Smith   if (!ordering) {
473f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
474f4bdf6c4SBarry Smith       grid_rank = irow[i] / nvars;
475f4bdf6c4SBarry Smith       var_type  = (irow[i] % nvars);
476f4bdf6c4SBarry Smith 
477f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
4782cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
4792cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
4802cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
481a74df02fSJacob Faibussowitsch       PetscStackCallStandard(HYPRE_SStructMatrixSetValues,ex->ss_mat,part,index,var_type,7*nvars,entries,values[var_type]);
482f4bdf6c4SBarry Smith     }
483f4bdf6c4SBarry Smith   } else {
484f4bdf6c4SBarry Smith     for (i=0; i<nrow; i++) {
485f4bdf6c4SBarry Smith       var_type = irow[i]/(ex->gnxgnygnz);
486f4bdf6c4SBarry Smith       grid_rank= irow[i] - var_type*(ex->gnxgnygnz);
487f4bdf6c4SBarry Smith 
488f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
4892cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
4902cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row/ex->nx) % ex->ny));
4912cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row/(ex->nxny)));
492a74df02fSJacob Faibussowitsch       PetscStackCallStandard(HYPRE_SStructMatrixSetValues,ex->ss_mat,part,index,var_type,7*nvars,entries,values[var_type]);
493f4bdf6c4SBarry Smith     }
494f4bdf6c4SBarry Smith   }
495a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_SStructMatrixAssemble,ex->ss_mat);
4969566063dSJacob Faibussowitsch   PetscCall(PetscFree(values[0]));
4979566063dSJacob Faibussowitsch   PetscCall(PetscFree(values));
4989566063dSJacob Faibussowitsch   PetscCall(PetscFree(entries));
499f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
500f4bdf6c4SBarry Smith }
501f4bdf6c4SBarry Smith 
502f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPRESStruct_3d(Mat mat)
503f4bdf6c4SBarry Smith {
504f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex  = (Mat_HYPRESStruct*) mat->data;
5054ddd07fcSJed Brown   PetscInt         nvars= ex->nvars;
5064ddd07fcSJed Brown   PetscInt         size;
5074ddd07fcSJed Brown   PetscInt         part= 0;   /* only one part */
508f4bdf6c4SBarry Smith 
509f4bdf6c4SBarry Smith   PetscFunctionBegin;
510f4bdf6c4SBarry 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);
511f4bdf6c4SBarry Smith   {
5122cf14000SStefano Zampini     HYPRE_Int     i,*entries,iupper[3],ilower[3];
51339accc25SStefano Zampini     HYPRE_Complex *values;
5144ddd07fcSJed Brown 
515f4bdf6c4SBarry Smith     for (i= 0; i< 3; i++) {
516f4bdf6c4SBarry Smith       ilower[i] = ex->hbox.imin[i];
517f4bdf6c4SBarry Smith       iupper[i] = ex->hbox.imax[i];
518f4bdf6c4SBarry Smith     }
519f4bdf6c4SBarry Smith 
5209566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nvars*7,&entries,nvars*7*size,&values));
5218865f1eaSKarl Rupp     for (i= 0; i< nvars*7; i++) entries[i] = i;
5229566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(values,nvars*7*size));
523f4bdf6c4SBarry Smith 
524f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
525a74df02fSJacob Faibussowitsch       PetscStackCallStandard(HYPRE_SStructMatrixSetBoxValues,ex->ss_mat,part,ilower,iupper,i,nvars*7,entries,values);
526f4bdf6c4SBarry Smith     }
5279566063dSJacob Faibussowitsch     PetscCall(PetscFree2(entries,values));
528f4bdf6c4SBarry Smith   }
529a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_SStructMatrixAssemble,ex->ss_mat);
530f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
531f4bdf6c4SBarry Smith }
532f4bdf6c4SBarry Smith 
53359cb773eSBarry Smith static PetscErrorCode  MatSetUp_HYPRESStruct(Mat mat)
534f4bdf6c4SBarry Smith {
535f4bdf6c4SBarry Smith   Mat_HYPRESStruct       *ex = (Mat_HYPRESStruct*) mat->data;
536f4bdf6c4SBarry Smith   PetscInt               dim,dof,sw[3],nx,ny,nz;
5374ddd07fcSJed Brown   PetscInt               ilower[3],iupper[3],ssize,i;
538bff4a2f0SMatthew G. Knepley   DMBoundaryType         px,py,pz;
539f4bdf6c4SBarry Smith   DMDAStencilType        st;
5404ddd07fcSJed Brown   PetscInt               nparts= 1;  /* assuming only one part */
5414ddd07fcSJed Brown   PetscInt               part  = 0;
542565245c5SBarry Smith   ISLocalToGlobalMapping ltog;
54359cb773eSBarry Smith   DM                     da;
544b026d285SBarry Smith 
545f4bdf6c4SBarry Smith   PetscFunctionBegin;
5469566063dSJacob Faibussowitsch   PetscCall(MatGetDM(mat,(DM*)&da));
547f4bdf6c4SBarry Smith   ex->da = da;
5489566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)da));
549f4bdf6c4SBarry Smith 
5509566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(ex->da,&dim,0,0,0,0,0,0,&dof,&sw[0],&px,&py,&pz,&st));
5519566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]));
552f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
553f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
554f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
555f4bdf6c4SBarry Smith   /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
556f4bdf6c4SBarry Smith   ex->hbox.imin[0] = ilower[0];
557f4bdf6c4SBarry Smith   ex->hbox.imin[1] = ilower[1];
558f4bdf6c4SBarry Smith   ex->hbox.imin[2] = ilower[2];
559f4bdf6c4SBarry Smith   ex->hbox.imax[0] = iupper[0];
560f4bdf6c4SBarry Smith   ex->hbox.imax[1] = iupper[1];
561f4bdf6c4SBarry Smith   ex->hbox.imax[2] = iupper[2];
562f4bdf6c4SBarry Smith 
563f4bdf6c4SBarry Smith   ex->dofs_order = 0;
564f4bdf6c4SBarry Smith 
565f4bdf6c4SBarry Smith   /* assuming that the same number of dofs on each gridpoint. Also assume all cell-centred based */
566f4bdf6c4SBarry Smith   ex->nvars= dof;
567f4bdf6c4SBarry Smith 
568f4bdf6c4SBarry Smith   /* create the hypre grid object and set its information */
5692c71b3e2SJacob Faibussowitsch   PetscCheckFalse(px || py || pz,PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add periodic support by calling HYPRE_SStructGridSetPeriodic()");
570a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_SStructGridCreate,ex->hcomm,dim,nparts,&ex->ss_grid);
571a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_SStructGridSetExtents,ex->ss_grid,part,ex->hbox.imin,ex->hbox.imax);
572f4bdf6c4SBarry Smith   {
573f4bdf6c4SBarry Smith     HYPRE_SStructVariable *vartypes;
5749566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(ex->nvars,&vartypes));
5758865f1eaSKarl Rupp     for (i= 0; i< ex->nvars; i++) vartypes[i]= HYPRE_SSTRUCT_VARIABLE_CELL;
576a74df02fSJacob Faibussowitsch     PetscStackCallStandard(HYPRE_SStructGridSetVariables,ex->ss_grid, part, ex->nvars,vartypes);
5779566063dSJacob Faibussowitsch     PetscCall(PetscFree(vartypes));
578f4bdf6c4SBarry Smith   }
579a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_SStructGridAssemble,ex->ss_grid);
580f4bdf6c4SBarry Smith 
581f4bdf6c4SBarry Smith   sw[1] = sw[0];
582f4bdf6c4SBarry Smith   sw[2] = sw[1];
583a74df02fSJacob Faibussowitsch   /* PetscStackCallStandard(HYPRE_SStructGridSetNumGhost,ex->ss_grid,sw); */
584f4bdf6c4SBarry Smith 
585f4bdf6c4SBarry Smith   /* create the hypre stencil object and set its information */
586*08401ef6SPierre Jolivet   PetscCheck(sw[0] <= 1,PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for wider stencils");
587*08401ef6SPierre Jolivet   PetscCheck(st != DMDA_STENCIL_BOX,PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for box stencils");
588f4bdf6c4SBarry Smith 
589f4bdf6c4SBarry Smith   if (dim == 1) {
5902cf14000SStefano Zampini     HYPRE_Int offsets[3][1] = {{-1},{0},{1}};
5914ddd07fcSJed Brown     PetscInt  j, cnt;
592f4bdf6c4SBarry Smith 
593f4bdf6c4SBarry Smith     ssize = 3*(ex->nvars);
594a74df02fSJacob Faibussowitsch     PetscStackCallStandard(HYPRE_SStructStencilCreate,dim,ssize,&ex->ss_stencil);
595f4bdf6c4SBarry Smith     cnt= 0;
596f4bdf6c4SBarry Smith     for (i = 0; i < (ex->nvars); i++) {
597f4bdf6c4SBarry Smith       for (j = 0; j < 3; j++) {
598a74df02fSJacob Faibussowitsch         PetscStackCallStandard(HYPRE_SStructStencilSetEntry,ex->ss_stencil, cnt, offsets[j], i);
599f4bdf6c4SBarry Smith         cnt++;
600f4bdf6c4SBarry Smith       }
601f4bdf6c4SBarry Smith     }
602f4bdf6c4SBarry Smith   } else if (dim == 2) {
6032cf14000SStefano Zampini     HYPRE_Int offsets[5][2] = {{0,-1},{-1,0},{0,0},{1,0},{0,1}};
6044ddd07fcSJed Brown     PetscInt  j, cnt;
605f4bdf6c4SBarry Smith 
606f4bdf6c4SBarry Smith     ssize = 5*(ex->nvars);
607a74df02fSJacob Faibussowitsch     PetscStackCallStandard(HYPRE_SStructStencilCreate,dim,ssize,&ex->ss_stencil);
608f4bdf6c4SBarry Smith     cnt= 0;
609f4bdf6c4SBarry Smith     for (i= 0; i< (ex->nvars); i++) {
610f4bdf6c4SBarry Smith       for (j= 0; j< 5; j++) {
611a74df02fSJacob Faibussowitsch         PetscStackCallStandard(HYPRE_SStructStencilSetEntry,ex->ss_stencil, cnt, offsets[j], i);
612f4bdf6c4SBarry Smith         cnt++;
613f4bdf6c4SBarry Smith       }
614f4bdf6c4SBarry Smith     }
615f4bdf6c4SBarry Smith   } else if (dim == 3) {
6162cf14000SStefano 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}};
6174ddd07fcSJed Brown     PetscInt  j, cnt;
618f4bdf6c4SBarry Smith 
619f4bdf6c4SBarry Smith     ssize = 7*(ex->nvars);
620a74df02fSJacob Faibussowitsch     PetscStackCallStandard(HYPRE_SStructStencilCreate,dim,ssize,&ex->ss_stencil);
621f4bdf6c4SBarry Smith     cnt= 0;
622f4bdf6c4SBarry Smith     for (i= 0; i< (ex->nvars); i++) {
623f4bdf6c4SBarry Smith       for (j= 0; j< 7; j++) {
624a74df02fSJacob Faibussowitsch         PetscStackCallStandard(HYPRE_SStructStencilSetEntry,ex->ss_stencil, cnt, offsets[j], i);
625f4bdf6c4SBarry Smith         cnt++;
626f4bdf6c4SBarry Smith       }
627f4bdf6c4SBarry Smith     }
628f4bdf6c4SBarry Smith   }
629f4bdf6c4SBarry Smith 
630f4bdf6c4SBarry Smith   /* create the HYPRE graph */
631a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_SStructGraphCreate,ex->hcomm, ex->ss_grid, &(ex->ss_graph));
632f4bdf6c4SBarry Smith 
633f4bdf6c4SBarry Smith   /* set the stencil graph. Note that each variable has the same graph. This means that each
634f4bdf6c4SBarry Smith      variable couples to all the other variable and with the same stencil pattern. */
635f4bdf6c4SBarry Smith   for (i= 0; i< (ex->nvars); i++) {
636a74df02fSJacob Faibussowitsch     PetscStackCallStandard(HYPRE_SStructGraphSetStencil,ex->ss_graph,part,i,ex->ss_stencil);
637f4bdf6c4SBarry Smith   }
638a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_SStructGraphAssemble,ex->ss_graph);
639f4bdf6c4SBarry Smith 
640f4bdf6c4SBarry Smith   /* create the HYPRE sstruct vectors for rhs and solution */
641a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_SStructVectorCreate,ex->hcomm,ex->ss_grid,&ex->ss_b);
642a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_SStructVectorCreate,ex->hcomm,ex->ss_grid,&ex->ss_x);
643a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_SStructVectorInitialize,ex->ss_b);
644a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_SStructVectorInitialize,ex->ss_x);
645a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_SStructVectorAssemble,ex->ss_b);
646a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_SStructVectorAssemble,ex->ss_x);
647f4bdf6c4SBarry Smith 
648f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
649a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_SStructMatrixCreate,ex->hcomm,ex->ss_graph,&ex->ss_mat);
650a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_SStructGridDestroy,ex->ss_grid);
651a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_SStructStencilDestroy,ex->ss_stencil);
652f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
653a74df02fSJacob Faibussowitsch     PetscStackCallStandard(HYPRE_SStructMatrixInitialize,ex->ss_mat);
654f4bdf6c4SBarry Smith     ex->needsinitialization = PETSC_FALSE;
655f4bdf6c4SBarry Smith   }
656f4bdf6c4SBarry Smith 
657f4bdf6c4SBarry Smith   /* set the global and local sizes of the matrix */
6589566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da,0,0,0,&nx,&ny,&nz));
6599566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat,dof*nx*ny*nz,dof*nx*ny*nz,PETSC_DECIDE,PETSC_DECIDE));
6609566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->rmap,dof));
6619566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->cmap,dof));
6629566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->rmap));
6639566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->cmap));
66461710fbeSStefano Zampini   mat->preallocated = PETSC_TRUE;
665f4bdf6c4SBarry Smith 
666f4bdf6c4SBarry Smith   if (dim == 3) {
667f4bdf6c4SBarry Smith     mat->ops->setvalueslocal = MatSetValuesLocal_HYPRESStruct_3d;
668f4bdf6c4SBarry Smith     mat->ops->zerorowslocal  = MatZeroRowsLocal_HYPRESStruct_3d;
669f4bdf6c4SBarry Smith     mat->ops->zeroentries    = MatZeroEntries_HYPRESStruct_3d;
6708865f1eaSKarl Rupp 
6719566063dSJacob Faibussowitsch     /* PetscCall(MatZeroEntries_HYPRESStruct_3d(mat)); */
672ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Only support for 3d DMDA currently");
673f4bdf6c4SBarry Smith 
674f4bdf6c4SBarry Smith   /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
6759566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(mat,&ex->rstart,NULL));
6769566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(ex->da,&ltog));
6779566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **) &ex->gindices));
6789566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(ex->da,0,0,0,&ex->gnx,&ex->gnxgny,&ex->gnxgnygnz));
6798865f1eaSKarl Rupp 
680f4bdf6c4SBarry Smith   ex->gnxgny    *= ex->gnx;
681f4bdf6c4SBarry Smith   ex->gnxgnygnz *= ex->gnxgny;
6828865f1eaSKarl Rupp 
6839566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da,&ex->xs,&ex->ys,&ex->zs,&ex->nx,&ex->ny,&ex->nz));
6848865f1eaSKarl Rupp 
685f4bdf6c4SBarry Smith   ex->nxny   = ex->nx*ex->ny;
686f4bdf6c4SBarry Smith   ex->nxnynz = ex->nz*ex->nxny;
687f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
688f4bdf6c4SBarry Smith }
689f4bdf6c4SBarry Smith 
690f4bdf6c4SBarry Smith PetscErrorCode MatMult_HYPRESStruct(Mat A,Vec x,Vec y)
691f4bdf6c4SBarry Smith {
692b026d285SBarry Smith   const PetscScalar *xx;
693b026d285SBarry Smith   PetscScalar       *yy;
6942cf14000SStefano Zampini   HYPRE_Int         hlower[3],hupper[3];
6954ddd07fcSJed Brown   PetscInt          ilower[3],iupper[3];
696f4bdf6c4SBarry Smith   Mat_HYPRESStruct  *mx     = (Mat_HYPRESStruct*)(A->data);
6974ddd07fcSJed Brown   PetscInt          ordering= mx->dofs_order;
6984ddd07fcSJed Brown   PetscInt          nvars   = mx->nvars;
6994ddd07fcSJed Brown   PetscInt          part    = 0;
7004ddd07fcSJed Brown   PetscInt          size;
7014ddd07fcSJed Brown   PetscInt          i;
702f4bdf6c4SBarry Smith 
703f4bdf6c4SBarry Smith   PetscFunctionBegin;
7049566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]));
7052cf14000SStefano Zampini 
7062cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
707f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
708f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
709f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
7102cf14000SStefano Zampini   hlower[0]  = (HYPRE_Int)ilower[0];
7112cf14000SStefano Zampini   hlower[1]  = (HYPRE_Int)ilower[1];
7122cf14000SStefano Zampini   hlower[2]  = (HYPRE_Int)ilower[2];
7132cf14000SStefano Zampini   hupper[0]  = (HYPRE_Int)iupper[0];
7142cf14000SStefano Zampini   hupper[1]  = (HYPRE_Int)iupper[1];
7152cf14000SStefano Zampini   hupper[2]  = (HYPRE_Int)iupper[2];
716f4bdf6c4SBarry Smith 
717f4bdf6c4SBarry Smith   size= 1;
7188865f1eaSKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i]-ilower[i]+1);
719f4bdf6c4SBarry Smith 
720f4bdf6c4SBarry Smith   /* copy x values over to hypre for variable ordering */
721f4bdf6c4SBarry Smith   if (ordering) {
722a74df02fSJacob Faibussowitsch     PetscStackCallStandard(HYPRE_SStructVectorSetConstantValues,mx->ss_b,0.0);
7239566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x,&xx));
724f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
725a74df02fSJacob Faibussowitsch       PetscStackCallStandard(HYPRE_SStructVectorSetBoxValues,mx->ss_b,part,hlower,hupper,i,(HYPRE_Complex*)(xx+(size*i)));
726f4bdf6c4SBarry Smith     }
7279566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x,&xx));
728a74df02fSJacob Faibussowitsch     PetscStackCallStandard(HYPRE_SStructVectorAssemble,mx->ss_b);
729a74df02fSJacob Faibussowitsch     PetscStackCallStandard(HYPRE_SStructMatrixMatvec,1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x);
730f4bdf6c4SBarry Smith 
731f4bdf6c4SBarry Smith     /* copy solution values back to PETSc */
7329566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y,&yy));
733f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
734a74df02fSJacob Faibussowitsch       PetscStackCallStandard(HYPRE_SStructVectorGetBoxValues,mx->ss_x,part,hlower,hupper,i,(HYPRE_Complex*)(yy+(size*i)));
735f4bdf6c4SBarry Smith     }
7369566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y,&yy));
737f4bdf6c4SBarry Smith   } else {      /* nodal ordering must be mapped to variable ordering for sys_pfmg */
738f4bdf6c4SBarry Smith     PetscScalar *z;
7394ddd07fcSJed Brown     PetscInt    j, k;
740f4bdf6c4SBarry Smith 
7419566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nvars*size,&z));
742a74df02fSJacob Faibussowitsch     PetscStackCallStandard(HYPRE_SStructVectorSetConstantValues,mx->ss_b,0.0);
7439566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x,&xx));
744f4bdf6c4SBarry Smith 
745f4bdf6c4SBarry Smith     /* transform nodal to hypre's variable ordering for sys_pfmg */
746f4bdf6c4SBarry Smith     for (i= 0; i< size; i++) {
747f4bdf6c4SBarry Smith       k= i*nvars;
7488865f1eaSKarl Rupp       for (j= 0; j< nvars; j++) z[j*size+i]= xx[k+j];
749f4bdf6c4SBarry Smith     }
750f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
751a74df02fSJacob Faibussowitsch       PetscStackCallStandard(HYPRE_SStructVectorSetBoxValues,mx->ss_b,part,hlower,hupper,i,(HYPRE_Complex*)(z+(size*i)));
752f4bdf6c4SBarry Smith     }
7539566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x,&xx));
754a74df02fSJacob Faibussowitsch     PetscStackCallStandard(HYPRE_SStructVectorAssemble,mx->ss_b);
755a74df02fSJacob Faibussowitsch     PetscStackCallStandard(HYPRE_SStructMatrixMatvec,1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x);
756f4bdf6c4SBarry Smith 
757f4bdf6c4SBarry Smith     /* copy solution values back to PETSc */
7589566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y,&yy));
759f4bdf6c4SBarry Smith     for (i= 0; i< nvars; i++) {
760a74df02fSJacob Faibussowitsch       PetscStackCallStandard(HYPRE_SStructVectorGetBoxValues,mx->ss_x,part,hlower,hupper,i,(HYPRE_Complex*)(z+(size*i)));
761f4bdf6c4SBarry Smith     }
762f4bdf6c4SBarry Smith     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
763f4bdf6c4SBarry Smith     for (i= 0; i< size; i++) {
764f4bdf6c4SBarry Smith       k= i*nvars;
7658865f1eaSKarl Rupp       for (j= 0; j< nvars; j++) yy[k+j]= z[j*size+i];
766f4bdf6c4SBarry Smith     }
7679566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y,&yy));
7689566063dSJacob Faibussowitsch     PetscCall(PetscFree(z));
769f4bdf6c4SBarry Smith   }
770f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
771f4bdf6c4SBarry Smith }
772f4bdf6c4SBarry Smith 
773f4bdf6c4SBarry Smith PetscErrorCode MatAssemblyEnd_HYPRESStruct(Mat mat,MatAssemblyType mode)
774f4bdf6c4SBarry Smith {
775f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data;
776f4bdf6c4SBarry Smith 
777f4bdf6c4SBarry Smith   PetscFunctionBegin;
778a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_SStructMatrixAssemble,ex->ss_mat);
779f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
780f4bdf6c4SBarry Smith }
781f4bdf6c4SBarry Smith 
782f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPRESStruct(Mat mat)
783f4bdf6c4SBarry Smith {
784f4bdf6c4SBarry Smith   PetscFunctionBegin;
785f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
786f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
787f4bdf6c4SBarry Smith }
788f4bdf6c4SBarry Smith 
789f4bdf6c4SBarry Smith PetscErrorCode MatDestroy_HYPRESStruct(Mat mat)
790f4bdf6c4SBarry Smith {
791f4bdf6c4SBarry Smith   Mat_HYPRESStruct       *ex = (Mat_HYPRESStruct*) mat->data;
792d94fc0b6SBarry Smith   ISLocalToGlobalMapping ltog;
793f4bdf6c4SBarry Smith 
794f4bdf6c4SBarry Smith   PetscFunctionBegin;
7959566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(ex->da,&ltog));
7969566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreIndices(ltog, (const PetscInt **) &ex->gindices));
797a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_SStructGraphDestroy,ex->ss_graph);
798a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_SStructMatrixDestroy,ex->ss_mat);
799a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_SStructVectorDestroy,ex->ss_x);
800a74df02fSJacob Faibussowitsch   PetscStackCallStandard(HYPRE_SStructVectorDestroy,ex->ss_b);
8019566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)ex->da));
8029566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&(ex->hcomm)));
8039566063dSJacob Faibussowitsch   PetscCall(PetscFree(ex));
804f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
805f4bdf6c4SBarry Smith }
806f4bdf6c4SBarry Smith 
8078cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_HYPRESStruct(Mat B)
808f4bdf6c4SBarry Smith {
809f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex;
810f4bdf6c4SBarry Smith 
811f4bdf6c4SBarry Smith   PetscFunctionBegin;
8129566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(B,&ex));
813f4bdf6c4SBarry Smith   B->data      = (void*)ex;
814f4bdf6c4SBarry Smith   B->rmap->bs  = 1;
815f4bdf6c4SBarry Smith   B->assembled = PETSC_FALSE;
816f4bdf6c4SBarry Smith 
817f4bdf6c4SBarry Smith   B->insertmode = NOT_SET_VALUES;
818f4bdf6c4SBarry Smith 
819f4bdf6c4SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_HYPRESStruct;
820f4bdf6c4SBarry Smith   B->ops->mult        = MatMult_HYPRESStruct;
821f4bdf6c4SBarry Smith   B->ops->zeroentries = MatZeroEntries_HYPRESStruct;
822f4bdf6c4SBarry Smith   B->ops->destroy     = MatDestroy_HYPRESStruct;
82359cb773eSBarry Smith   B->ops->setup       = MatSetUp_HYPRESStruct;
824f4bdf6c4SBarry Smith 
825f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
826f4bdf6c4SBarry Smith 
8279566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_dup(PetscObjectComm((PetscObject)B),&(ex->hcomm)));
8289566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B,MATHYPRESSTRUCT));
829f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
830f4bdf6c4SBarry Smith }
831