xref: /petsc/src/dm/impls/da/hypre/mhyp.c (revision 4dfa11a44d5adf2389f1d3acbc8f3c1116dc6c3a)
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 
289371c9d4SSatish Balay PetscErrorCode MatSetValuesLocal_HYPREStruct_3d(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) {
2976a007c6Sftrigaux   HYPRE_Int        index[3], entries[9];
302cf14000SStefano Zampini   PetscInt         i, j, stencil, row;
3139accc25SStefano Zampini   HYPRE_Complex   *values = (HYPRE_Complex *)y;
32f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex     = (Mat_HYPREStruct *)mat->data;
33f4bdf6c4SBarry Smith 
34f4bdf6c4SBarry Smith   PetscFunctionBegin;
3576a007c6Sftrigaux   PetscCheck(ncol <= 9, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "ncol %" PetscInt_FMT " > 9 too large", ncol);
36f4bdf6c4SBarry Smith   for (i = 0; i < nrow; i++) {
37f4bdf6c4SBarry Smith     for (j = 0; j < ncol; j++) {
38f4bdf6c4SBarry Smith       stencil = icol[j] - irow[i];
39f4bdf6c4SBarry Smith       if (!stencil) {
40f4bdf6c4SBarry Smith         entries[j] = 3;
41f4bdf6c4SBarry Smith       } else if (stencil == -1) {
42f4bdf6c4SBarry Smith         entries[j] = 2;
43f4bdf6c4SBarry Smith       } else if (stencil == 1) {
44f4bdf6c4SBarry Smith         entries[j] = 4;
45f4bdf6c4SBarry Smith       } else if (stencil == -ex->gnx) {
46f4bdf6c4SBarry Smith         entries[j] = 1;
47f4bdf6c4SBarry Smith       } else if (stencil == ex->gnx) {
48f4bdf6c4SBarry Smith         entries[j] = 5;
49f4bdf6c4SBarry Smith       } else if (stencil == -ex->gnxgny) {
50f4bdf6c4SBarry Smith         entries[j] = 0;
51f4bdf6c4SBarry Smith       } else if (stencil == ex->gnxgny) {
52f4bdf6c4SBarry Smith         entries[j] = 6;
5363a3b9bcSJacob 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);
54f4bdf6c4SBarry Smith     }
55f4bdf6c4SBarry Smith     row      = ex->gindices[irow[i]] - ex->rstart;
562cf14000SStefano Zampini     index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
572cf14000SStefano Zampini     index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny));
582cf14000SStefano Zampini     index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny)));
59792fecdfSBarry Smith     if (addv == ADD_VALUES) PetscCallExternal(HYPRE_StructMatrixAddToValues, ex->hmat, index, ncol, entries, values);
60792fecdfSBarry Smith     else PetscCallExternal(HYPRE_StructMatrixSetValues, ex->hmat, index, ncol, entries, values);
61f4bdf6c4SBarry Smith     values += ncol;
62f4bdf6c4SBarry Smith   }
63f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
64f4bdf6c4SBarry Smith }
65f4bdf6c4SBarry Smith 
669371c9d4SSatish Balay PetscErrorCode MatZeroRowsLocal_HYPREStruct_3d(Mat mat, PetscInt nrow, const PetscInt irow[], PetscScalar d, Vec x, Vec b) {
672cf14000SStefano Zampini   HYPRE_Int        index[3], entries[7] = {0, 1, 2, 3, 4, 5, 6};
682cf14000SStefano Zampini   PetscInt         row, i;
6939accc25SStefano Zampini   HYPRE_Complex    values[7];
70f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct *)mat->data;
71f4bdf6c4SBarry Smith 
72f4bdf6c4SBarry Smith   PetscFunctionBegin;
7308401ef6SPierre Jolivet   PetscCheck(!x || !b, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "No support");
749566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(values, 7));
759566063dSJacob Faibussowitsch   PetscCall(PetscHYPREScalarCast(d, &values[3]));
76f4bdf6c4SBarry Smith   for (i = 0; i < nrow; i++) {
77f4bdf6c4SBarry Smith     row      = ex->gindices[irow[i]] - ex->rstart;
782cf14000SStefano Zampini     index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
792cf14000SStefano Zampini     index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny));
802cf14000SStefano Zampini     index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny)));
81792fecdfSBarry Smith     PetscCallExternal(HYPRE_StructMatrixSetValues, ex->hmat, index, 7, entries, values);
82f4bdf6c4SBarry Smith   }
83792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixAssemble, ex->hmat);
84f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
85f4bdf6c4SBarry Smith }
86f4bdf6c4SBarry Smith 
879371c9d4SSatish Balay PetscErrorCode MatZeroEntries_HYPREStruct_3d(Mat mat) {
882cf14000SStefano Zampini   HYPRE_Int        indices[7] = {0, 1, 2, 3, 4, 5, 6};
89f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex         = (Mat_HYPREStruct *)mat->data;
90f4bdf6c4SBarry Smith 
91f4bdf6c4SBarry Smith   PetscFunctionBegin;
92f4bdf6c4SBarry Smith   /* hypre has no public interface to do this */
93792fecdfSBarry Smith   PetscCallExternal(hypre_StructMatrixClearBoxValues, ex->hmat, &ex->hbox, 7, indices, 0, 1);
94792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixAssemble, ex->hmat);
95f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
96f4bdf6c4SBarry Smith }
97f4bdf6c4SBarry Smith 
989371c9d4SSatish Balay static PetscErrorCode MatSetUp_HYPREStruct(Mat mat) {
99f4bdf6c4SBarry Smith   Mat_HYPREStruct       *ex = (Mat_HYPREStruct *)mat->data;
1002cf14000SStefano Zampini   HYPRE_Int              sw[6];
101e33d7e95Sftrigaux   HYPRE_Int              hlower[3], hupper[3], period[3] = {0, 0, 0};
102e33d7e95Sftrigaux   PetscInt               dim, dof, psw, Nx, Ny, Nz, nx, ny, nz, ilower[3], iupper[3], ssize, i;
103bff4a2f0SMatthew G. Knepley   DMBoundaryType         px, py, pz;
104f4bdf6c4SBarry Smith   DMDAStencilType        st;
105565245c5SBarry Smith   ISLocalToGlobalMapping ltog;
10659cb773eSBarry Smith   DM                     da;
107f4bdf6c4SBarry Smith 
108f4bdf6c4SBarry Smith   PetscFunctionBegin;
1099566063dSJacob Faibussowitsch   PetscCall(MatGetDM(mat, (DM *)&da));
110f4bdf6c4SBarry Smith   ex->da = da;
1119566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)da));
112f4bdf6c4SBarry Smith 
113e33d7e95Sftrigaux   PetscCall(DMDAGetInfo(ex->da, &dim, &Nx, &Ny, &Nz, 0, 0, 0, &dof, &psw, &px, &py, &pz, &st));
1149566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
1152cf14000SStefano Zampini 
1162cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
117f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
118f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
119f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
1202cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
1212cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
1222cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
1232cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
1242cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
1252cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
126f4bdf6c4SBarry Smith 
127f4bdf6c4SBarry Smith   /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
1282cf14000SStefano Zampini   ex->hbox.imin[0] = hlower[0];
1292cf14000SStefano Zampini   ex->hbox.imin[1] = hlower[1];
1302cf14000SStefano Zampini   ex->hbox.imin[2] = hlower[2];
1312cf14000SStefano Zampini   ex->hbox.imax[0] = hupper[0];
1322cf14000SStefano Zampini   ex->hbox.imax[1] = hupper[1];
1332cf14000SStefano Zampini   ex->hbox.imax[2] = hupper[2];
134f4bdf6c4SBarry Smith 
135f4bdf6c4SBarry Smith   /* create the hypre grid object and set its information */
13608401ef6SPierre Jolivet   PetscCheck(dof <= 1, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Currently only support for scalar problems");
137e33d7e95Sftrigaux   if (px || py || pz) {
138e33d7e95Sftrigaux     if (px == DM_BOUNDARY_PERIODIC) period[0] = (HYPRE_Int)Nx;
139e33d7e95Sftrigaux     if (py == DM_BOUNDARY_PERIODIC) period[1] = (HYPRE_Int)Ny;
140e33d7e95Sftrigaux     if (pz == DM_BOUNDARY_PERIODIC) period[2] = (HYPRE_Int)Nz;
141e33d7e95Sftrigaux   }
142792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructGridCreate, ex->hcomm, dim, &ex->hgrid);
143792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructGridSetExtents, ex->hgrid, hlower, hupper);
144e33d7e95Sftrigaux   PetscCallExternal(HYPRE_StructGridSetPeriodic, ex->hgrid, period);
145792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructGridAssemble, ex->hgrid);
146f4bdf6c4SBarry Smith 
1472cf14000SStefano Zampini   sw[5] = sw[4] = sw[3] = sw[2] = sw[1] = sw[0] = psw;
148792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructGridSetNumGhost, ex->hgrid, sw);
149f4bdf6c4SBarry Smith 
150f4bdf6c4SBarry Smith   /* create the hypre stencil object and set its information */
15108401ef6SPierre Jolivet   PetscCheck(sw[0] <= 1, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add support for wider stencils");
15208401ef6SPierre Jolivet   PetscCheck(st != DMDA_STENCIL_BOX, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add support for box stencils");
153f4bdf6c4SBarry Smith   if (dim == 1) {
1542cf14000SStefano Zampini     HYPRE_Int offsets[3][1] = {{-1}, {0}, {1}};
155f4bdf6c4SBarry Smith     ssize                   = 3;
156792fecdfSBarry Smith     PetscCallExternal(HYPRE_StructStencilCreate, dim, ssize, &ex->hstencil);
15748a46eb9SPierre Jolivet     for (i = 0; i < ssize; i++) PetscCallExternal(HYPRE_StructStencilSetElement, ex->hstencil, i, offsets[i]);
158f4bdf6c4SBarry Smith   } else if (dim == 2) {
1599371c9d4SSatish Balay     HYPRE_Int offsets[5][2] = {
1609371c9d4SSatish Balay       {0,  -1},
1619371c9d4SSatish Balay       {-1, 0 },
1629371c9d4SSatish Balay       {0,  0 },
1639371c9d4SSatish Balay       {1,  0 },
1649371c9d4SSatish Balay       {0,  1 }
1659371c9d4SSatish Balay     };
166f4bdf6c4SBarry Smith     ssize = 5;
167792fecdfSBarry Smith     PetscCallExternal(HYPRE_StructStencilCreate, dim, ssize, &ex->hstencil);
16848a46eb9SPierre Jolivet     for (i = 0; i < ssize; i++) PetscCallExternal(HYPRE_StructStencilSetElement, ex->hstencil, i, offsets[i]);
169f4bdf6c4SBarry Smith   } else if (dim == 3) {
1709371c9d4SSatish Balay     HYPRE_Int offsets[7][3] = {
1719371c9d4SSatish Balay       {0,  0,  -1},
1729371c9d4SSatish Balay       {0,  -1, 0 },
1739371c9d4SSatish Balay       {-1, 0,  0 },
1749371c9d4SSatish Balay       {0,  0,  0 },
1759371c9d4SSatish Balay       {1,  0,  0 },
1769371c9d4SSatish Balay       {0,  1,  0 },
1779371c9d4SSatish Balay       {0,  0,  1 }
1789371c9d4SSatish Balay     };
179f4bdf6c4SBarry Smith     ssize = 7;
180792fecdfSBarry Smith     PetscCallExternal(HYPRE_StructStencilCreate, dim, ssize, &ex->hstencil);
18148a46eb9SPierre Jolivet     for (i = 0; i < ssize; i++) PetscCallExternal(HYPRE_StructStencilSetElement, ex->hstencil, i, offsets[i]);
182f4bdf6c4SBarry Smith   }
183f4bdf6c4SBarry Smith 
184f4bdf6c4SBarry Smith   /* create the HYPRE vector for rhs and solution */
185792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorCreate, ex->hcomm, ex->hgrid, &ex->hb);
186792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorCreate, ex->hcomm, ex->hgrid, &ex->hx);
187792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorInitialize, ex->hb);
188792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorInitialize, ex->hx);
189792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble, ex->hb);
190792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble, ex->hx);
191f4bdf6c4SBarry Smith 
192f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
193792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixCreate, ex->hcomm, ex->hgrid, ex->hstencil, &ex->hmat);
194792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructGridDestroy, ex->hgrid);
195792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructStencilDestroy, ex->hstencil);
196f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
197792fecdfSBarry Smith     PetscCallExternal(HYPRE_StructMatrixInitialize, ex->hmat);
198f4bdf6c4SBarry Smith     ex->needsinitialization = PETSC_FALSE;
199f4bdf6c4SBarry Smith   }
200f4bdf6c4SBarry Smith 
201f4bdf6c4SBarry Smith   /* set the global and local sizes of the matrix */
2029566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, 0, 0, 0, &nx, &ny, &nz));
2039566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat, dof * nx * ny * nz, dof * nx * ny * nz, PETSC_DECIDE, PETSC_DECIDE));
2049566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->rmap, 1));
2059566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->cmap, 1));
2069566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->rmap));
2079566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->cmap));
20859cb773eSBarry Smith   mat->preallocated = PETSC_TRUE;
209f4bdf6c4SBarry Smith 
210f4bdf6c4SBarry Smith   if (dim == 3) {
211f4bdf6c4SBarry Smith     mat->ops->setvalueslocal = MatSetValuesLocal_HYPREStruct_3d;
212f4bdf6c4SBarry Smith     mat->ops->zerorowslocal  = MatZeroRowsLocal_HYPREStruct_3d;
213f4bdf6c4SBarry Smith     mat->ops->zeroentries    = MatZeroEntries_HYPREStruct_3d;
2148865f1eaSKarl Rupp 
2159566063dSJacob Faibussowitsch     /*        PetscCall(MatZeroEntries_HYPREStruct_3d(mat)); */
216ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Only support for 3d DMDA currently");
217f4bdf6c4SBarry Smith 
218f4bdf6c4SBarry Smith   /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
2199566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(mat, &ex->rstart, NULL));
2209566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(ex->da, &ltog));
2219566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **)&ex->gindices));
2229566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(ex->da, 0, 0, 0, &ex->gnx, &ex->gnxgny, 0));
223f4bdf6c4SBarry Smith   ex->gnxgny *= ex->gnx;
2249566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da, &ex->xs, &ex->ys, &ex->zs, &ex->nx, &ex->ny, 0));
225f4bdf6c4SBarry Smith   ex->nxny = ex->nx * ex->ny;
226f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
227f4bdf6c4SBarry Smith }
228f4bdf6c4SBarry Smith 
2299371c9d4SSatish Balay PetscErrorCode MatMult_HYPREStruct(Mat A, Vec x, Vec y) {
230b026d285SBarry Smith   const PetscScalar *xx;
231b026d285SBarry Smith   PetscScalar       *yy;
2324ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
2332cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
234f4bdf6c4SBarry Smith   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)(A->data);
235f4bdf6c4SBarry Smith 
236f4bdf6c4SBarry Smith   PetscFunctionBegin;
2379566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
2382cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
239f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
240f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
241f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
2422cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
2432cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
2442cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
2452cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
2462cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
2472cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
248f4bdf6c4SBarry Smith 
249f4bdf6c4SBarry Smith   /* copy x values over to hypre */
250792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
2519566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
252792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
2539566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
254792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
255792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixMatvec, 1.0, mx->hmat, mx->hb, 0.0, mx->hx);
256f4bdf6c4SBarry Smith 
257f4bdf6c4SBarry Smith   /* copy solution values back to PETSc */
2589566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
259792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
2609566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
261f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
262f4bdf6c4SBarry Smith }
263f4bdf6c4SBarry Smith 
2649371c9d4SSatish Balay PetscErrorCode MatAssemblyEnd_HYPREStruct(Mat mat, MatAssemblyType mode) {
265f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct *)mat->data;
266f4bdf6c4SBarry Smith 
267f4bdf6c4SBarry Smith   PetscFunctionBegin;
268792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixAssemble, ex->hmat);
269792fecdfSBarry Smith   /* PetscCallExternal(HYPRE_StructMatrixPrint,"dummy",ex->hmat,0); */
270f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
271f4bdf6c4SBarry Smith }
272f4bdf6c4SBarry Smith 
2739371c9d4SSatish Balay PetscErrorCode MatZeroEntries_HYPREStruct(Mat mat) {
274f4bdf6c4SBarry Smith   PetscFunctionBegin;
275f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
276f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
277f4bdf6c4SBarry Smith }
278f4bdf6c4SBarry Smith 
2799371c9d4SSatish Balay PetscErrorCode MatDestroy_HYPREStruct(Mat mat) {
280f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct *)mat->data;
281f4bdf6c4SBarry Smith 
282f4bdf6c4SBarry Smith   PetscFunctionBegin;
283792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixDestroy, ex->hmat);
284792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorDestroy, ex->hx);
285792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorDestroy, ex->hb);
2869566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)ex->da));
2879566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&(ex->hcomm)));
2889566063dSJacob Faibussowitsch   PetscCall(PetscFree(ex));
289f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
290f4bdf6c4SBarry Smith }
291f4bdf6c4SBarry Smith 
2929371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatCreate_HYPREStruct(Mat B) {
293f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex;
294f4bdf6c4SBarry Smith 
295f4bdf6c4SBarry Smith   PetscFunctionBegin;
296*4dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&ex));
297f4bdf6c4SBarry Smith   B->data      = (void *)ex;
298f4bdf6c4SBarry Smith   B->rmap->bs  = 1;
299f4bdf6c4SBarry Smith   B->assembled = PETSC_FALSE;
300f4bdf6c4SBarry Smith 
301f4bdf6c4SBarry Smith   B->insertmode = NOT_SET_VALUES;
302f4bdf6c4SBarry Smith 
303f4bdf6c4SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_HYPREStruct;
304f4bdf6c4SBarry Smith   B->ops->mult        = MatMult_HYPREStruct;
305f4bdf6c4SBarry Smith   B->ops->zeroentries = MatZeroEntries_HYPREStruct;
306f4bdf6c4SBarry Smith   B->ops->destroy     = MatDestroy_HYPREStruct;
30759cb773eSBarry Smith   B->ops->setup       = MatSetUp_HYPREStruct;
308f4bdf6c4SBarry Smith 
309f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
310f4bdf6c4SBarry Smith 
3119566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_dup(PetscObjectComm((PetscObject)B), &(ex->hcomm)));
3129566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRESTRUCT));
313f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
314f4bdf6c4SBarry Smith }
315f4bdf6c4SBarry Smith 
316f4bdf6c4SBarry Smith /*MC
317f4bdf6c4SBarry Smith    MATHYPRESSTRUCT - MATHYPRESSTRUCT = "hypresstruct" - A matrix type to be used for parallel sparse matrices
318f4bdf6c4SBarry Smith           based on the hypre HYPRE_SStructMatrix.
319f4bdf6c4SBarry Smith 
320f4bdf6c4SBarry Smith    Level: intermediate
321f4bdf6c4SBarry Smith 
32295452b02SPatrick Sanan    Notes:
32395452b02SPatrick Sanan     Unlike hypre's general semi-struct object consisting of a collection of structured-grid objects and unstructured
324b026d285SBarry Smith           grid objects, we restrict the semi-struct objects to consist of only structured-grid components.
325f4bdf6c4SBarry Smith 
326f4bdf6c4SBarry 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
327f4bdf6c4SBarry Smith           be defined by a DMDA.
328f4bdf6c4SBarry Smith 
32959cb773eSBarry Smith           The matrix needs a DMDA associated with it by either a call to MatSetDM() or if the matrix is obtained from DMCreateMatrix()
330f4bdf6c4SBarry Smith 
331f4bdf6c4SBarry Smith M*/
332f4bdf6c4SBarry Smith 
3339371c9d4SSatish Balay PetscErrorCode MatSetValuesLocal_HYPRESStruct_3d(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) {
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;
37963a3b9bcSJacob 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);
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 
387792fecdfSBarry Smith       if (addv == ADD_VALUES) PetscCallExternal(HYPRE_SStructMatrixAddToValues, ex->ss_mat, part, index, var_type, ncol, entries, values);
388792fecdfSBarry Smith       else PetscCallExternal(HYPRE_SStructMatrixSetValues, ex->ss_mat, part, index, var_type, ncol, entries, values);
389f4bdf6c4SBarry Smith       values += ncol;
390f4bdf6c4SBarry Smith     }
391f4bdf6c4SBarry Smith   } else {
392f4bdf6c4SBarry Smith     for (i = 0; i < nrow; i++) {
393f4bdf6c4SBarry Smith       var_type  = irow[i] / (ex->gnxgnygnz);
394f4bdf6c4SBarry Smith       grid_rank = irow[i] - var_type * (ex->gnxgnygnz);
395f4bdf6c4SBarry Smith 
396f4bdf6c4SBarry Smith       for (j = 0; j < ncol; j++) {
397f4bdf6c4SBarry Smith         to_var_type  = icol[j] / (ex->gnxgnygnz);
398f4bdf6c4SBarry Smith         to_grid_rank = icol[j] - to_var_type * (ex->gnxgnygnz);
399f4bdf6c4SBarry Smith 
400f4bdf6c4SBarry Smith         to_var_entry = to_var_entry * 7;
401f4bdf6c4SBarry Smith         entries[j]   = to_var_entry;
402f4bdf6c4SBarry Smith 
403f4bdf6c4SBarry Smith         stencil = to_grid_rank - grid_rank;
404f4bdf6c4SBarry Smith         if (!stencil) {
405f4bdf6c4SBarry Smith           entries[j] += 3;
406f4bdf6c4SBarry Smith         } else if (stencil == -1) {
407f4bdf6c4SBarry Smith           entries[j] += 2;
408f4bdf6c4SBarry Smith         } else if (stencil == 1) {
409f4bdf6c4SBarry Smith           entries[j] += 4;
410f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnx) {
411f4bdf6c4SBarry Smith           entries[j] += 1;
412f4bdf6c4SBarry Smith         } else if (stencil == ex->gnx) {
413f4bdf6c4SBarry Smith           entries[j] += 5;
414f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnxgny) {
415f4bdf6c4SBarry Smith           entries[j] += 0;
416f4bdf6c4SBarry Smith         } else if (stencil == ex->gnxgny) {
417f4bdf6c4SBarry Smith           entries[j] += 6;
41863a3b9bcSJacob 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);
419f4bdf6c4SBarry Smith       }
420f4bdf6c4SBarry Smith 
421f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
4222cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
4232cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny));
4242cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny)));
425f4bdf6c4SBarry Smith 
426792fecdfSBarry Smith       if (addv == ADD_VALUES) PetscCallExternal(HYPRE_SStructMatrixAddToValues, ex->ss_mat, part, index, var_type, ncol, entries, values);
427792fecdfSBarry Smith       else PetscCallExternal(HYPRE_SStructMatrixSetValues, ex->ss_mat, part, index, var_type, ncol, entries, values);
428f4bdf6c4SBarry Smith       values += ncol;
429f4bdf6c4SBarry Smith     }
430f4bdf6c4SBarry Smith   }
4319566063dSJacob Faibussowitsch   PetscCall(PetscFree(entries));
432f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
433f4bdf6c4SBarry Smith }
434f4bdf6c4SBarry Smith 
4359371c9d4SSatish Balay PetscErrorCode MatZeroRowsLocal_HYPRESStruct_3d(Mat mat, PetscInt nrow, const PetscInt irow[], PetscScalar d, Vec x, Vec b) {
4362cf14000SStefano Zampini   HYPRE_Int         index[3], *entries;
4372cf14000SStefano Zampini   PetscInt          i;
43839accc25SStefano Zampini   HYPRE_Complex   **values;
439f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct *)mat->data;
440f4bdf6c4SBarry Smith 
4414ddd07fcSJed Brown   PetscInt part     = 0; /* Petsc sstruct interface only allows 1 part */
4424ddd07fcSJed Brown   PetscInt ordering = ex->dofs_order;
4434ddd07fcSJed Brown   PetscInt grid_rank;
4444ddd07fcSJed Brown   PetscInt var_type;
4454ddd07fcSJed Brown   PetscInt nvars = ex->nvars;
4462cf14000SStefano Zampini   PetscInt row;
447f4bdf6c4SBarry Smith 
448f4bdf6c4SBarry Smith   PetscFunctionBegin;
44908401ef6SPierre Jolivet   PetscCheck(!x || !b, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "No support");
4509566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(7 * nvars, &entries));
451f4bdf6c4SBarry Smith 
4529566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nvars, &values));
4539566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(7 * nvars * nvars, &values[0]));
454ad540459SPierre Jolivet   for (i = 1; i < nvars; i++) values[i] = values[i - 1] + nvars * 7;
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)));
472792fecdfSBarry 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)));
483792fecdfSBarry Smith       PetscCallExternal(HYPRE_SStructMatrixSetValues, ex->ss_mat, part, index, var_type, 7 * nvars, entries, values[var_type]);
484f4bdf6c4SBarry Smith     }
485f4bdf6c4SBarry Smith   }
486792fecdfSBarry 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 
4939371c9d4SSatish Balay PetscErrorCode MatZeroEntries_HYPRESStruct_3d(Mat mat) {
494f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex    = (Mat_HYPRESStruct *)mat->data;
4954ddd07fcSJed Brown   PetscInt          nvars = ex->nvars;
4964ddd07fcSJed Brown   PetscInt          size;
4974ddd07fcSJed Brown   PetscInt          part = 0; /* only one part */
498f4bdf6c4SBarry Smith 
499f4bdf6c4SBarry Smith   PetscFunctionBegin;
500f4bdf6c4SBarry 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);
501f4bdf6c4SBarry Smith   {
5022cf14000SStefano Zampini     HYPRE_Int      i, *entries, iupper[3], ilower[3];
50339accc25SStefano Zampini     HYPRE_Complex *values;
5044ddd07fcSJed Brown 
505f4bdf6c4SBarry Smith     for (i = 0; i < 3; i++) {
506f4bdf6c4SBarry Smith       ilower[i] = ex->hbox.imin[i];
507f4bdf6c4SBarry Smith       iupper[i] = ex->hbox.imax[i];
508f4bdf6c4SBarry Smith     }
509f4bdf6c4SBarry Smith 
5109566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nvars * 7, &entries, nvars * 7 * size, &values));
5118865f1eaSKarl Rupp     for (i = 0; i < nvars * 7; i++) entries[i] = i;
5129566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(values, nvars * 7 * size));
513f4bdf6c4SBarry Smith 
51448a46eb9SPierre Jolivet     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructMatrixSetBoxValues, ex->ss_mat, part, ilower, iupper, i, nvars * 7, entries, values);
5159566063dSJacob Faibussowitsch     PetscCall(PetscFree2(entries, values));
516f4bdf6c4SBarry Smith   }
517792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructMatrixAssemble, ex->ss_mat);
518f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
519f4bdf6c4SBarry Smith }
520f4bdf6c4SBarry Smith 
5219371c9d4SSatish Balay static PetscErrorCode MatSetUp_HYPRESStruct(Mat mat) {
522f4bdf6c4SBarry Smith   Mat_HYPRESStruct      *ex = (Mat_HYPRESStruct *)mat->data;
523f4bdf6c4SBarry Smith   PetscInt               dim, dof, sw[3], nx, ny, nz;
5244ddd07fcSJed Brown   PetscInt               ilower[3], iupper[3], ssize, i;
525bff4a2f0SMatthew G. Knepley   DMBoundaryType         px, py, pz;
526f4bdf6c4SBarry Smith   DMDAStencilType        st;
5274ddd07fcSJed Brown   PetscInt               nparts = 1; /* assuming only one part */
5284ddd07fcSJed Brown   PetscInt               part   = 0;
529565245c5SBarry Smith   ISLocalToGlobalMapping ltog;
53059cb773eSBarry Smith   DM                     da;
531b026d285SBarry Smith 
532f4bdf6c4SBarry Smith   PetscFunctionBegin;
5339566063dSJacob Faibussowitsch   PetscCall(MatGetDM(mat, (DM *)&da));
534f4bdf6c4SBarry Smith   ex->da = da;
5359566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)da));
536f4bdf6c4SBarry Smith 
5379566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(ex->da, &dim, 0, 0, 0, 0, 0, 0, &dof, &sw[0], &px, &py, &pz, &st));
5389566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
539f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
540f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
541f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
542f4bdf6c4SBarry Smith   /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
543f4bdf6c4SBarry Smith   ex->hbox.imin[0] = ilower[0];
544f4bdf6c4SBarry Smith   ex->hbox.imin[1] = ilower[1];
545f4bdf6c4SBarry Smith   ex->hbox.imin[2] = ilower[2];
546f4bdf6c4SBarry Smith   ex->hbox.imax[0] = iupper[0];
547f4bdf6c4SBarry Smith   ex->hbox.imax[1] = iupper[1];
548f4bdf6c4SBarry Smith   ex->hbox.imax[2] = iupper[2];
549f4bdf6c4SBarry Smith 
550f4bdf6c4SBarry Smith   ex->dofs_order = 0;
551f4bdf6c4SBarry Smith 
552f4bdf6c4SBarry Smith   /* assuming that the same number of dofs on each gridpoint. Also assume all cell-centred based */
553f4bdf6c4SBarry Smith   ex->nvars = dof;
554f4bdf6c4SBarry Smith 
555f4bdf6c4SBarry Smith   /* create the hypre grid object and set its information */
5561dca8a05SBarry Smith   PetscCheck(!px && !py && !pz, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add periodic support by calling HYPRE_SStructGridSetPeriodic()");
557792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGridCreate, ex->hcomm, dim, nparts, &ex->ss_grid);
558792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGridSetExtents, ex->ss_grid, part, ex->hbox.imin, ex->hbox.imax);
559f4bdf6c4SBarry Smith   {
560f4bdf6c4SBarry Smith     HYPRE_SStructVariable *vartypes;
5619566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(ex->nvars, &vartypes));
5628865f1eaSKarl Rupp     for (i = 0; i < ex->nvars; i++) vartypes[i] = HYPRE_SSTRUCT_VARIABLE_CELL;
563792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructGridSetVariables, ex->ss_grid, part, ex->nvars, vartypes);
5649566063dSJacob Faibussowitsch     PetscCall(PetscFree(vartypes));
565f4bdf6c4SBarry Smith   }
566792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGridAssemble, ex->ss_grid);
567f4bdf6c4SBarry Smith 
568f4bdf6c4SBarry Smith   sw[1] = sw[0];
569f4bdf6c4SBarry Smith   sw[2] = sw[1];
570792fecdfSBarry Smith   /* PetscCallExternal(HYPRE_SStructGridSetNumGhost,ex->ss_grid,sw); */
571f4bdf6c4SBarry Smith 
572f4bdf6c4SBarry Smith   /* create the hypre stencil object and set its information */
57308401ef6SPierre Jolivet   PetscCheck(sw[0] <= 1, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add support for wider stencils");
57408401ef6SPierre Jolivet   PetscCheck(st != DMDA_STENCIL_BOX, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add support for box stencils");
575f4bdf6c4SBarry Smith 
576f4bdf6c4SBarry Smith   if (dim == 1) {
5772cf14000SStefano Zampini     HYPRE_Int offsets[3][1] = {{-1}, {0}, {1}};
5784ddd07fcSJed Brown     PetscInt  j, cnt;
579f4bdf6c4SBarry Smith 
580f4bdf6c4SBarry Smith     ssize = 3 * (ex->nvars);
581792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructStencilCreate, dim, ssize, &ex->ss_stencil);
582f4bdf6c4SBarry Smith     cnt = 0;
583f4bdf6c4SBarry Smith     for (i = 0; i < (ex->nvars); i++) {
584f4bdf6c4SBarry Smith       for (j = 0; j < 3; j++) {
585792fecdfSBarry Smith         PetscCallExternal(HYPRE_SStructStencilSetEntry, ex->ss_stencil, cnt, offsets[j], i);
586f4bdf6c4SBarry Smith         cnt++;
587f4bdf6c4SBarry Smith       }
588f4bdf6c4SBarry Smith     }
589f4bdf6c4SBarry Smith   } else if (dim == 2) {
5909371c9d4SSatish Balay     HYPRE_Int offsets[5][2] = {
5919371c9d4SSatish Balay       {0,  -1},
5929371c9d4SSatish Balay       {-1, 0 },
5939371c9d4SSatish Balay       {0,  0 },
5949371c9d4SSatish Balay       {1,  0 },
5959371c9d4SSatish Balay       {0,  1 }
5969371c9d4SSatish Balay     };
5974ddd07fcSJed Brown     PetscInt j, cnt;
598f4bdf6c4SBarry Smith 
599f4bdf6c4SBarry Smith     ssize = 5 * (ex->nvars);
600792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructStencilCreate, dim, ssize, &ex->ss_stencil);
601f4bdf6c4SBarry Smith     cnt = 0;
602f4bdf6c4SBarry Smith     for (i = 0; i < (ex->nvars); i++) {
603f4bdf6c4SBarry Smith       for (j = 0; j < 5; j++) {
604792fecdfSBarry Smith         PetscCallExternal(HYPRE_SStructStencilSetEntry, ex->ss_stencil, cnt, offsets[j], i);
605f4bdf6c4SBarry Smith         cnt++;
606f4bdf6c4SBarry Smith       }
607f4bdf6c4SBarry Smith     }
608f4bdf6c4SBarry Smith   } else if (dim == 3) {
6099371c9d4SSatish Balay     HYPRE_Int offsets[7][3] = {
6109371c9d4SSatish Balay       {0,  0,  -1},
6119371c9d4SSatish Balay       {0,  -1, 0 },
6129371c9d4SSatish Balay       {-1, 0,  0 },
6139371c9d4SSatish Balay       {0,  0,  0 },
6149371c9d4SSatish Balay       {1,  0,  0 },
6159371c9d4SSatish Balay       {0,  1,  0 },
6169371c9d4SSatish Balay       {0,  0,  1 }
6179371c9d4SSatish Balay     };
6184ddd07fcSJed Brown     PetscInt j, cnt;
619f4bdf6c4SBarry Smith 
620f4bdf6c4SBarry Smith     ssize = 7 * (ex->nvars);
621792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructStencilCreate, dim, ssize, &ex->ss_stencil);
622f4bdf6c4SBarry Smith     cnt = 0;
623f4bdf6c4SBarry Smith     for (i = 0; i < (ex->nvars); i++) {
624f4bdf6c4SBarry Smith       for (j = 0; j < 7; j++) {
625792fecdfSBarry Smith         PetscCallExternal(HYPRE_SStructStencilSetEntry, ex->ss_stencil, cnt, offsets[j], i);
626f4bdf6c4SBarry Smith         cnt++;
627f4bdf6c4SBarry Smith       }
628f4bdf6c4SBarry Smith     }
629f4bdf6c4SBarry Smith   }
630f4bdf6c4SBarry Smith 
631f4bdf6c4SBarry Smith   /* create the HYPRE graph */
632792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGraphCreate, ex->hcomm, ex->ss_grid, &(ex->ss_graph));
633f4bdf6c4SBarry Smith 
634f4bdf6c4SBarry Smith   /* set the stencil graph. Note that each variable has the same graph. This means that each
635f4bdf6c4SBarry Smith      variable couples to all the other variable and with the same stencil pattern. */
63648a46eb9SPierre Jolivet   for (i = 0; i < (ex->nvars); i++) PetscCallExternal(HYPRE_SStructGraphSetStencil, ex->ss_graph, part, i, ex->ss_stencil);
637792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGraphAssemble, ex->ss_graph);
638f4bdf6c4SBarry Smith 
639f4bdf6c4SBarry Smith   /* create the HYPRE sstruct vectors for rhs and solution */
640792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorCreate, ex->hcomm, ex->ss_grid, &ex->ss_b);
641792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorCreate, ex->hcomm, ex->ss_grid, &ex->ss_x);
642792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorInitialize, ex->ss_b);
643792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorInitialize, ex->ss_x);
644792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorAssemble, ex->ss_b);
645792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorAssemble, ex->ss_x);
646f4bdf6c4SBarry Smith 
647f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
648792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructMatrixCreate, ex->hcomm, ex->ss_graph, &ex->ss_mat);
649792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGridDestroy, ex->ss_grid);
650792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructStencilDestroy, ex->ss_stencil);
651f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
652792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixInitialize, ex->ss_mat);
653f4bdf6c4SBarry Smith     ex->needsinitialization = PETSC_FALSE;
654f4bdf6c4SBarry Smith   }
655f4bdf6c4SBarry Smith 
656f4bdf6c4SBarry Smith   /* set the global and local sizes of the matrix */
6579566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, 0, 0, 0, &nx, &ny, &nz));
6589566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat, dof * nx * ny * nz, dof * nx * ny * nz, PETSC_DECIDE, PETSC_DECIDE));
6599566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->rmap, dof));
6609566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->cmap, dof));
6619566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->rmap));
6629566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->cmap));
66361710fbeSStefano Zampini   mat->preallocated = PETSC_TRUE;
664f4bdf6c4SBarry Smith 
665f4bdf6c4SBarry Smith   if (dim == 3) {
666f4bdf6c4SBarry Smith     mat->ops->setvalueslocal = MatSetValuesLocal_HYPRESStruct_3d;
667f4bdf6c4SBarry Smith     mat->ops->zerorowslocal  = MatZeroRowsLocal_HYPRESStruct_3d;
668f4bdf6c4SBarry Smith     mat->ops->zeroentries    = MatZeroEntries_HYPRESStruct_3d;
6698865f1eaSKarl Rupp 
6709566063dSJacob Faibussowitsch     /* PetscCall(MatZeroEntries_HYPRESStruct_3d(mat)); */
671ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Only support for 3d DMDA currently");
672f4bdf6c4SBarry Smith 
673f4bdf6c4SBarry Smith   /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
6749566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(mat, &ex->rstart, NULL));
6759566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(ex->da, &ltog));
6769566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **)&ex->gindices));
6779566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(ex->da, 0, 0, 0, &ex->gnx, &ex->gnxgny, &ex->gnxgnygnz));
6788865f1eaSKarl Rupp 
679f4bdf6c4SBarry Smith   ex->gnxgny *= ex->gnx;
680f4bdf6c4SBarry Smith   ex->gnxgnygnz *= ex->gnxgny;
6818865f1eaSKarl Rupp 
6829566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da, &ex->xs, &ex->ys, &ex->zs, &ex->nx, &ex->ny, &ex->nz));
6838865f1eaSKarl Rupp 
684f4bdf6c4SBarry Smith   ex->nxny   = ex->nx * ex->ny;
685f4bdf6c4SBarry Smith   ex->nxnynz = ex->nz * ex->nxny;
686f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
687f4bdf6c4SBarry Smith }
688f4bdf6c4SBarry Smith 
6899371c9d4SSatish Balay PetscErrorCode MatMult_HYPRESStruct(Mat A, Vec x, Vec y) {
690b026d285SBarry Smith   const PetscScalar *xx;
691b026d285SBarry Smith   PetscScalar       *yy;
6922cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
6934ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
694f4bdf6c4SBarry Smith   Mat_HYPRESStruct  *mx       = (Mat_HYPRESStruct *)(A->data);
6954ddd07fcSJed Brown   PetscInt           ordering = mx->dofs_order;
6964ddd07fcSJed Brown   PetscInt           nvars    = mx->nvars;
6974ddd07fcSJed Brown   PetscInt           part     = 0;
6984ddd07fcSJed Brown   PetscInt           size;
6994ddd07fcSJed Brown   PetscInt           i;
700f4bdf6c4SBarry Smith 
701f4bdf6c4SBarry Smith   PetscFunctionBegin;
7029566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
7032cf14000SStefano Zampini 
7042cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
705f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
706f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
707f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
7082cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
7092cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
7102cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
7112cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
7122cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
7132cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
714f4bdf6c4SBarry Smith 
715f4bdf6c4SBarry Smith   size = 1;
7168865f1eaSKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i] - ilower[i] + 1);
717f4bdf6c4SBarry Smith 
718f4bdf6c4SBarry Smith   /* copy x values over to hypre for variable ordering */
719f4bdf6c4SBarry Smith   if (ordering) {
720792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
7219566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
72248a46eb9SPierre Jolivet     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(xx + (size * i)));
7239566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
724792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
725792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixMatvec, 1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x);
726f4bdf6c4SBarry Smith 
727f4bdf6c4SBarry Smith     /* copy solution values back to PETSc */
7289566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
72948a46eb9SPierre Jolivet     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(yy + (size * i)));
7309566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
731f4bdf6c4SBarry Smith   } else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */
732f4bdf6c4SBarry Smith     PetscScalar *z;
7334ddd07fcSJed Brown     PetscInt     j, k;
734f4bdf6c4SBarry Smith 
7359566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nvars * size, &z));
736792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
7379566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
738f4bdf6c4SBarry Smith 
739f4bdf6c4SBarry Smith     /* transform nodal to hypre's variable ordering for sys_pfmg */
740f4bdf6c4SBarry Smith     for (i = 0; i < size; i++) {
741f4bdf6c4SBarry Smith       k = i * nvars;
7428865f1eaSKarl Rupp       for (j = 0; j < nvars; j++) z[j * size + i] = xx[k + j];
743f4bdf6c4SBarry Smith     }
74448a46eb9SPierre Jolivet     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
7459566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
746792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
747792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixMatvec, 1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x);
748f4bdf6c4SBarry Smith 
749f4bdf6c4SBarry Smith     /* copy solution values back to PETSc */
7509566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
75148a46eb9SPierre Jolivet     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
752f4bdf6c4SBarry Smith     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
753f4bdf6c4SBarry Smith     for (i = 0; i < size; i++) {
754f4bdf6c4SBarry Smith       k = i * nvars;
7558865f1eaSKarl Rupp       for (j = 0; j < nvars; j++) yy[k + j] = z[j * size + i];
756f4bdf6c4SBarry Smith     }
7579566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
7589566063dSJacob Faibussowitsch     PetscCall(PetscFree(z));
759f4bdf6c4SBarry Smith   }
760f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
761f4bdf6c4SBarry Smith }
762f4bdf6c4SBarry Smith 
7639371c9d4SSatish Balay PetscErrorCode MatAssemblyEnd_HYPRESStruct(Mat mat, MatAssemblyType mode) {
764f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct *)mat->data;
765f4bdf6c4SBarry Smith 
766f4bdf6c4SBarry Smith   PetscFunctionBegin;
767792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructMatrixAssemble, ex->ss_mat);
768f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
769f4bdf6c4SBarry Smith }
770f4bdf6c4SBarry Smith 
7719371c9d4SSatish Balay PetscErrorCode MatZeroEntries_HYPRESStruct(Mat mat) {
772f4bdf6c4SBarry Smith   PetscFunctionBegin;
773f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
774f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
775f4bdf6c4SBarry Smith }
776f4bdf6c4SBarry Smith 
7779371c9d4SSatish Balay PetscErrorCode MatDestroy_HYPRESStruct(Mat mat) {
778f4bdf6c4SBarry Smith   Mat_HYPRESStruct      *ex = (Mat_HYPRESStruct *)mat->data;
779d94fc0b6SBarry Smith   ISLocalToGlobalMapping ltog;
780f4bdf6c4SBarry Smith 
781f4bdf6c4SBarry Smith   PetscFunctionBegin;
7829566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(ex->da, &ltog));
7839566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreIndices(ltog, (const PetscInt **)&ex->gindices));
784792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGraphDestroy, ex->ss_graph);
785792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructMatrixDestroy, ex->ss_mat);
786792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorDestroy, ex->ss_x);
787792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorDestroy, ex->ss_b);
7889566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)ex->da));
7899566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&(ex->hcomm)));
7909566063dSJacob Faibussowitsch   PetscCall(PetscFree(ex));
791f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
792f4bdf6c4SBarry Smith }
793f4bdf6c4SBarry Smith 
7949371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatCreate_HYPRESStruct(Mat B) {
795f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex;
796f4bdf6c4SBarry Smith 
797f4bdf6c4SBarry Smith   PetscFunctionBegin;
798*4dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&ex));
799f4bdf6c4SBarry Smith   B->data      = (void *)ex;
800f4bdf6c4SBarry Smith   B->rmap->bs  = 1;
801f4bdf6c4SBarry Smith   B->assembled = PETSC_FALSE;
802f4bdf6c4SBarry Smith 
803f4bdf6c4SBarry Smith   B->insertmode = NOT_SET_VALUES;
804f4bdf6c4SBarry Smith 
805f4bdf6c4SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_HYPRESStruct;
806f4bdf6c4SBarry Smith   B->ops->mult        = MatMult_HYPRESStruct;
807f4bdf6c4SBarry Smith   B->ops->zeroentries = MatZeroEntries_HYPRESStruct;
808f4bdf6c4SBarry Smith   B->ops->destroy     = MatDestroy_HYPRESStruct;
80959cb773eSBarry Smith   B->ops->setup       = MatSetUp_HYPRESStruct;
810f4bdf6c4SBarry Smith 
811f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
812f4bdf6c4SBarry Smith 
8139566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_dup(PetscObjectComm((PetscObject)B), &(ex->hcomm)));
8149566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRESSTRUCT));
815f4bdf6c4SBarry Smith   PetscFunctionReturn(0);
816f4bdf6c4SBarry Smith }
817