xref: /petsc/src/dm/impls/da/hypre/mhyp.c (revision f4f49eeac7efa77fffa46b7ff95a3ed169f659ed)
1f4bdf6c4SBarry Smith /*
2f4bdf6c4SBarry Smith     Creates hypre ijmatrix from PETSc matrix
3f4bdf6c4SBarry Smith */
4c6db04a5SJed Brown #include <petscsys.h>
539accc25SStefano Zampini #include <petsc/private/petschypre.h>
6af0996ceSBarry Smith #include <petsc/private/matimpl.h>
7c6db04a5SJed Brown #include <petscdmda.h> /*I "petscdmda.h" I*/
8c6db04a5SJed Brown #include <../src/dm/impls/da/hypre/mhyp.h>
9f4bdf6c4SBarry Smith 
10f4bdf6c4SBarry Smith /* -----------------------------------------------------------------------------------------------------------------*/
11f4bdf6c4SBarry Smith 
12f4bdf6c4SBarry Smith /*MC
13f4bdf6c4SBarry Smith    MATHYPRESTRUCT - MATHYPRESTRUCT = "hyprestruct" - A matrix type to be used for parallel sparse matrices
14f4bdf6c4SBarry Smith           based on the hypre HYPRE_StructMatrix.
15f4bdf6c4SBarry Smith 
16f4bdf6c4SBarry Smith    Level: intermediate
17f4bdf6c4SBarry Smith 
1895452b02SPatrick Sanan    Notes:
1995452b02SPatrick Sanan     Unlike the more general support for blocks in hypre this allows only one block per process and requires the block
20dce8aebaSBarry Smith           be defined by a `DMDA`.
21f4bdf6c4SBarry Smith 
22dce8aebaSBarry Smith           The matrix needs a `DMDA` associated with it by either a call to `MatSetDM()` or if the matrix is obtained from `DMCreateMatrix()`
23f4bdf6c4SBarry Smith 
24db781477SPatrick Sanan .seealso: `MatCreate()`, `PCPFMG`, `MatSetDM()`, `DMCreateMatrix()`
25f4bdf6c4SBarry Smith M*/
26f4bdf6c4SBarry Smith 
2766976f2fSJacob Faibussowitsch static PetscErrorCode MatSetValuesLocal_HYPREStruct_3d(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
28d71ae5a4SJacob Faibussowitsch {
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   }
633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
64f4bdf6c4SBarry Smith }
65f4bdf6c4SBarry Smith 
6666976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroRowsLocal_HYPREStruct_3d(Mat mat, PetscInt nrow, const PetscInt irow[], PetscScalar d, Vec x, Vec b)
67d71ae5a4SJacob Faibussowitsch {
682cf14000SStefano Zampini   HYPRE_Int        index[3], entries[7] = {0, 1, 2, 3, 4, 5, 6};
692cf14000SStefano Zampini   PetscInt         row, i;
7039accc25SStefano Zampini   HYPRE_Complex    values[7];
71f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct *)mat->data;
72f4bdf6c4SBarry Smith 
73f4bdf6c4SBarry Smith   PetscFunctionBegin;
7408401ef6SPierre Jolivet   PetscCheck(!x || !b, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "No support");
759566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(values, 7));
769566063dSJacob Faibussowitsch   PetscCall(PetscHYPREScalarCast(d, &values[3]));
77f4bdf6c4SBarry Smith   for (i = 0; i < nrow; i++) {
78f4bdf6c4SBarry Smith     row      = ex->gindices[irow[i]] - ex->rstart;
792cf14000SStefano Zampini     index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
802cf14000SStefano Zampini     index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny));
812cf14000SStefano Zampini     index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny)));
82792fecdfSBarry Smith     PetscCallExternal(HYPRE_StructMatrixSetValues, ex->hmat, index, 7, entries, values);
83f4bdf6c4SBarry Smith   }
84792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixAssemble, ex->hmat);
853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
86f4bdf6c4SBarry Smith }
87f4bdf6c4SBarry Smith 
8866976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPREStruct_3d(Mat mat)
89d71ae5a4SJacob Faibussowitsch {
902cf14000SStefano Zampini   HYPRE_Int        indices[7] = {0, 1, 2, 3, 4, 5, 6};
91f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex         = (Mat_HYPREStruct *)mat->data;
92f4bdf6c4SBarry Smith 
93f4bdf6c4SBarry Smith   PetscFunctionBegin;
94f4bdf6c4SBarry Smith   /* hypre has no public interface to do this */
95792fecdfSBarry Smith   PetscCallExternal(hypre_StructMatrixClearBoxValues, ex->hmat, &ex->hbox, 7, indices, 0, 1);
96792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixAssemble, ex->hmat);
973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
98f4bdf6c4SBarry Smith }
99f4bdf6c4SBarry Smith 
100d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetUp_HYPREStruct(Mat mat)
101d71ae5a4SJacob Faibussowitsch {
102f4bdf6c4SBarry Smith   Mat_HYPREStruct       *ex = (Mat_HYPREStruct *)mat->data;
1032cf14000SStefano Zampini   HYPRE_Int              sw[6];
104e33d7e95Sftrigaux   HYPRE_Int              hlower[3], hupper[3], period[3] = {0, 0, 0};
105e33d7e95Sftrigaux   PetscInt               dim, dof, psw, Nx, Ny, Nz, nx, ny, nz, ilower[3], iupper[3], ssize, i;
106bff4a2f0SMatthew G. Knepley   DMBoundaryType         px, py, pz;
107f4bdf6c4SBarry Smith   DMDAStencilType        st;
108565245c5SBarry Smith   ISLocalToGlobalMapping ltog;
10959cb773eSBarry Smith   DM                     da;
110f4bdf6c4SBarry Smith 
111f4bdf6c4SBarry Smith   PetscFunctionBegin;
1129566063dSJacob Faibussowitsch   PetscCall(MatGetDM(mat, (DM *)&da));
113f4bdf6c4SBarry Smith   ex->da = da;
1149566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)da));
115f4bdf6c4SBarry Smith 
116e33d7e95Sftrigaux   PetscCall(DMDAGetInfo(ex->da, &dim, &Nx, &Ny, &Nz, 0, 0, 0, &dof, &psw, &px, &py, &pz, &st));
1179566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
1182cf14000SStefano Zampini 
1192cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
120f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
121f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
122f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
1232cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
1242cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
1252cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
1262cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
1272cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
1282cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
129f4bdf6c4SBarry Smith 
130f4bdf6c4SBarry Smith   /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
1312cf14000SStefano Zampini   ex->hbox.imin[0] = hlower[0];
1322cf14000SStefano Zampini   ex->hbox.imin[1] = hlower[1];
1332cf14000SStefano Zampini   ex->hbox.imin[2] = hlower[2];
1342cf14000SStefano Zampini   ex->hbox.imax[0] = hupper[0];
1352cf14000SStefano Zampini   ex->hbox.imax[1] = hupper[1];
1362cf14000SStefano Zampini   ex->hbox.imax[2] = hupper[2];
137f4bdf6c4SBarry Smith 
138f4bdf6c4SBarry Smith   /* create the hypre grid object and set its information */
13908401ef6SPierre Jolivet   PetscCheck(dof <= 1, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Currently only support for scalar problems");
140e33d7e95Sftrigaux   if (px || py || pz) {
141e33d7e95Sftrigaux     if (px == DM_BOUNDARY_PERIODIC) period[0] = (HYPRE_Int)Nx;
142e33d7e95Sftrigaux     if (py == DM_BOUNDARY_PERIODIC) period[1] = (HYPRE_Int)Ny;
143e33d7e95Sftrigaux     if (pz == DM_BOUNDARY_PERIODIC) period[2] = (HYPRE_Int)Nz;
144e33d7e95Sftrigaux   }
145792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructGridCreate, ex->hcomm, dim, &ex->hgrid);
146792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructGridSetExtents, ex->hgrid, hlower, hupper);
147e33d7e95Sftrigaux   PetscCallExternal(HYPRE_StructGridSetPeriodic, ex->hgrid, period);
148792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructGridAssemble, ex->hgrid);
149f4bdf6c4SBarry Smith 
1502cf14000SStefano Zampini   sw[5] = sw[4] = sw[3] = sw[2] = sw[1] = sw[0] = psw;
151792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructGridSetNumGhost, ex->hgrid, sw);
152f4bdf6c4SBarry Smith 
153f4bdf6c4SBarry Smith   /* create the hypre stencil object and set its information */
15408401ef6SPierre Jolivet   PetscCheck(sw[0] <= 1, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add support for wider stencils");
15508401ef6SPierre Jolivet   PetscCheck(st != DMDA_STENCIL_BOX, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add support for box stencils");
156f4bdf6c4SBarry Smith   if (dim == 1) {
1572cf14000SStefano Zampini     HYPRE_Int offsets[3][1] = {{-1}, {0}, {1}};
158f4bdf6c4SBarry Smith     ssize                   = 3;
159792fecdfSBarry Smith     PetscCallExternal(HYPRE_StructStencilCreate, dim, ssize, &ex->hstencil);
16048a46eb9SPierre Jolivet     for (i = 0; i < ssize; i++) PetscCallExternal(HYPRE_StructStencilSetElement, ex->hstencil, i, offsets[i]);
161f4bdf6c4SBarry Smith   } else if (dim == 2) {
1629371c9d4SSatish Balay     HYPRE_Int offsets[5][2] = {
1639371c9d4SSatish Balay       {0,  -1},
1649371c9d4SSatish Balay       {-1, 0 },
1659371c9d4SSatish Balay       {0,  0 },
1669371c9d4SSatish Balay       {1,  0 },
1679371c9d4SSatish Balay       {0,  1 }
1689371c9d4SSatish Balay     };
169f4bdf6c4SBarry Smith     ssize = 5;
170792fecdfSBarry Smith     PetscCallExternal(HYPRE_StructStencilCreate, dim, ssize, &ex->hstencil);
17148a46eb9SPierre Jolivet     for (i = 0; i < ssize; i++) PetscCallExternal(HYPRE_StructStencilSetElement, ex->hstencil, i, offsets[i]);
172f4bdf6c4SBarry Smith   } else if (dim == 3) {
1739371c9d4SSatish Balay     HYPRE_Int offsets[7][3] = {
1749371c9d4SSatish Balay       {0,  0,  -1},
1759371c9d4SSatish Balay       {0,  -1, 0 },
1769371c9d4SSatish Balay       {-1, 0,  0 },
1779371c9d4SSatish Balay       {0,  0,  0 },
1789371c9d4SSatish Balay       {1,  0,  0 },
1799371c9d4SSatish Balay       {0,  1,  0 },
1809371c9d4SSatish Balay       {0,  0,  1 }
1819371c9d4SSatish Balay     };
182f4bdf6c4SBarry Smith     ssize = 7;
183792fecdfSBarry Smith     PetscCallExternal(HYPRE_StructStencilCreate, dim, ssize, &ex->hstencil);
18448a46eb9SPierre Jolivet     for (i = 0; i < ssize; i++) PetscCallExternal(HYPRE_StructStencilSetElement, ex->hstencil, i, offsets[i]);
185f4bdf6c4SBarry Smith   }
186f4bdf6c4SBarry Smith 
187f4bdf6c4SBarry Smith   /* create the HYPRE vector for rhs and solution */
188792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorCreate, ex->hcomm, ex->hgrid, &ex->hb);
189792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorCreate, ex->hcomm, ex->hgrid, &ex->hx);
190792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorInitialize, ex->hb);
191792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorInitialize, ex->hx);
192792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble, ex->hb);
193792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble, ex->hx);
194f4bdf6c4SBarry Smith 
195f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
196792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixCreate, ex->hcomm, ex->hgrid, ex->hstencil, &ex->hmat);
197792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructGridDestroy, ex->hgrid);
198792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructStencilDestroy, ex->hstencil);
199f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
200792fecdfSBarry Smith     PetscCallExternal(HYPRE_StructMatrixInitialize, ex->hmat);
201f4bdf6c4SBarry Smith     ex->needsinitialization = PETSC_FALSE;
202f4bdf6c4SBarry Smith   }
203f4bdf6c4SBarry Smith 
204f4bdf6c4SBarry Smith   /* set the global and local sizes of the matrix */
2059566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, 0, 0, 0, &nx, &ny, &nz));
2069566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat, dof * nx * ny * nz, dof * nx * ny * nz, PETSC_DECIDE, PETSC_DECIDE));
2079566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->rmap, 1));
2089566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->cmap, 1));
2099566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->rmap));
2109566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->cmap));
21159cb773eSBarry Smith   mat->preallocated = PETSC_TRUE;
212f4bdf6c4SBarry Smith 
213f4bdf6c4SBarry Smith   if (dim == 3) {
214f4bdf6c4SBarry Smith     mat->ops->setvalueslocal = MatSetValuesLocal_HYPREStruct_3d;
215f4bdf6c4SBarry Smith     mat->ops->zerorowslocal  = MatZeroRowsLocal_HYPREStruct_3d;
216f4bdf6c4SBarry Smith     mat->ops->zeroentries    = MatZeroEntries_HYPREStruct_3d;
2178865f1eaSKarl Rupp 
2189566063dSJacob Faibussowitsch     /*        PetscCall(MatZeroEntries_HYPREStruct_3d(mat)); */
219ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Only support for 3d DMDA currently");
220f4bdf6c4SBarry Smith 
221f4bdf6c4SBarry Smith   /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
2229566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(mat, &ex->rstart, NULL));
2239566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(ex->da, &ltog));
2249566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **)&ex->gindices));
2259566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(ex->da, 0, 0, 0, &ex->gnx, &ex->gnxgny, 0));
226f4bdf6c4SBarry Smith   ex->gnxgny *= ex->gnx;
2279566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da, &ex->xs, &ex->ys, &ex->zs, &ex->nx, &ex->ny, 0));
228f4bdf6c4SBarry Smith   ex->nxny = ex->nx * ex->ny;
2293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
230f4bdf6c4SBarry Smith }
231f4bdf6c4SBarry Smith 
23266976f2fSJacob Faibussowitsch static PetscErrorCode MatMult_HYPREStruct(Mat A, Vec x, Vec y)
233d71ae5a4SJacob Faibussowitsch {
234b026d285SBarry Smith   const PetscScalar *xx;
235b026d285SBarry Smith   PetscScalar       *yy;
2364ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
2372cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
238*f4f49eeaSPierre Jolivet   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)A->data;
239f4bdf6c4SBarry Smith 
240f4bdf6c4SBarry Smith   PetscFunctionBegin;
2419566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
2422cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
243f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
244f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
245f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
2462cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
2472cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
2482cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
2492cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
2502cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
2512cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
252f4bdf6c4SBarry Smith 
253f4bdf6c4SBarry Smith   /* copy x values over to hypre */
254792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
2559566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
256792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
2579566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
258792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
259792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixMatvec, 1.0, mx->hmat, mx->hb, 0.0, mx->hx);
260f4bdf6c4SBarry Smith 
261f4bdf6c4SBarry Smith   /* copy solution values back to PETSc */
2629566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
263792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
2649566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
2653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
266f4bdf6c4SBarry Smith }
267f4bdf6c4SBarry Smith 
26866976f2fSJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_HYPREStruct(Mat mat, MatAssemblyType mode)
269d71ae5a4SJacob Faibussowitsch {
270f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct *)mat->data;
271f4bdf6c4SBarry Smith 
272f4bdf6c4SBarry Smith   PetscFunctionBegin;
273792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixAssemble, ex->hmat);
274792fecdfSBarry Smith   /* PetscCallExternal(HYPRE_StructMatrixPrint,"dummy",ex->hmat,0); */
2753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
276f4bdf6c4SBarry Smith }
277f4bdf6c4SBarry Smith 
27866976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPREStruct(Mat mat)
279d71ae5a4SJacob Faibussowitsch {
280f4bdf6c4SBarry Smith   PetscFunctionBegin;
281f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
2823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
283f4bdf6c4SBarry Smith }
284f4bdf6c4SBarry Smith 
28566976f2fSJacob Faibussowitsch static PetscErrorCode MatDestroy_HYPREStruct(Mat mat)
286d71ae5a4SJacob Faibussowitsch {
287f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct *)mat->data;
288f4bdf6c4SBarry Smith 
289f4bdf6c4SBarry Smith   PetscFunctionBegin;
290792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixDestroy, ex->hmat);
291792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorDestroy, ex->hx);
292792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorDestroy, ex->hb);
2939566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)ex->da));
294*f4f49eeaSPierre Jolivet   PetscCallMPI(MPI_Comm_free(&ex->hcomm));
2959566063dSJacob Faibussowitsch   PetscCall(PetscFree(ex));
2963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
297f4bdf6c4SBarry Smith }
298f4bdf6c4SBarry Smith 
299d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_HYPREStruct(Mat B)
300d71ae5a4SJacob Faibussowitsch {
301f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex;
302f4bdf6c4SBarry Smith 
303f4bdf6c4SBarry Smith   PetscFunctionBegin;
3044dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&ex));
305f4bdf6c4SBarry Smith   B->data      = (void *)ex;
306f4bdf6c4SBarry Smith   B->rmap->bs  = 1;
307f4bdf6c4SBarry Smith   B->assembled = PETSC_FALSE;
308f4bdf6c4SBarry Smith 
309f4bdf6c4SBarry Smith   B->insertmode = NOT_SET_VALUES;
310f4bdf6c4SBarry Smith 
311f4bdf6c4SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_HYPREStruct;
312f4bdf6c4SBarry Smith   B->ops->mult        = MatMult_HYPREStruct;
313f4bdf6c4SBarry Smith   B->ops->zeroentries = MatZeroEntries_HYPREStruct;
314f4bdf6c4SBarry Smith   B->ops->destroy     = MatDestroy_HYPREStruct;
31559cb773eSBarry Smith   B->ops->setup       = MatSetUp_HYPREStruct;
316f4bdf6c4SBarry Smith 
317f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
318f4bdf6c4SBarry Smith 
319*f4f49eeaSPierre Jolivet   PetscCallMPI(MPI_Comm_dup(PetscObjectComm((PetscObject)B), &ex->hcomm));
3209566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRESTRUCT));
321ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
3223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
323f4bdf6c4SBarry Smith }
324f4bdf6c4SBarry Smith 
325f4bdf6c4SBarry Smith /*MC
326f4bdf6c4SBarry Smith    MATHYPRESSTRUCT - MATHYPRESSTRUCT = "hypresstruct" - A matrix type to be used for parallel sparse matrices
327f4bdf6c4SBarry Smith           based on the hypre HYPRE_SStructMatrix.
328f4bdf6c4SBarry Smith 
329f4bdf6c4SBarry Smith    Level: intermediate
330f4bdf6c4SBarry Smith 
33195452b02SPatrick Sanan    Notes:
33295452b02SPatrick Sanan     Unlike hypre's general semi-struct object consisting of a collection of structured-grid objects and unstructured
333b026d285SBarry Smith           grid objects, we restrict the semi-struct objects to consist of only structured-grid components.
334f4bdf6c4SBarry Smith 
335f4bdf6c4SBarry 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
336dce8aebaSBarry Smith           be defined by a `DMDA`.
337f4bdf6c4SBarry Smith 
33859cb773eSBarry Smith           The matrix needs a DMDA associated with it by either a call to MatSetDM() or if the matrix is obtained from DMCreateMatrix()
339f4bdf6c4SBarry Smith 
340dce8aebaSBarry Smith .seealso: `Mat`
341f4bdf6c4SBarry Smith M*/
342f4bdf6c4SBarry Smith 
34366976f2fSJacob Faibussowitsch static PetscErrorCode MatSetValuesLocal_HYPRESStruct_3d(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
344d71ae5a4SJacob Faibussowitsch {
3452cf14000SStefano Zampini   HYPRE_Int         index[3], *entries;
3462cf14000SStefano Zampini   PetscInt          i, j, stencil;
34739accc25SStefano Zampini   HYPRE_Complex    *values = (HYPRE_Complex *)y;
348f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex     = (Mat_HYPRESStruct *)mat->data;
349f4bdf6c4SBarry Smith 
3504ddd07fcSJed Brown   PetscInt part = 0; /* Petsc sstruct interface only allows 1 part */
3514ddd07fcSJed Brown   PetscInt ordering;
3524ddd07fcSJed Brown   PetscInt grid_rank, to_grid_rank;
3534ddd07fcSJed Brown   PetscInt var_type, to_var_type;
3544ddd07fcSJed Brown   PetscInt to_var_entry = 0;
3554ddd07fcSJed Brown   PetscInt nvars        = ex->nvars;
3562cf14000SStefano Zampini   PetscInt row;
357f4bdf6c4SBarry Smith 
358f4bdf6c4SBarry Smith   PetscFunctionBegin;
3599566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(7 * nvars, &entries));
360f4bdf6c4SBarry Smith   ordering = ex->dofs_order; /* ordering= 0   nodal ordering
361f4bdf6c4SBarry Smith                                            1   variable ordering */
36261710fbeSStefano Zampini   /* stencil entries are ordered by variables: var0_stencil0, var0_stencil1, ..., var0_stencil6, var1_stencil0, var1_stencil1, ...  */
363f4bdf6c4SBarry Smith   if (!ordering) {
364f4bdf6c4SBarry Smith     for (i = 0; i < nrow; i++) {
365f4bdf6c4SBarry Smith       grid_rank = irow[i] / nvars;
366f4bdf6c4SBarry Smith       var_type  = (irow[i] % nvars);
367f4bdf6c4SBarry Smith 
368f4bdf6c4SBarry Smith       for (j = 0; j < ncol; j++) {
369f4bdf6c4SBarry Smith         to_grid_rank = icol[j] / nvars;
370f4bdf6c4SBarry Smith         to_var_type  = (icol[j] % nvars);
371f4bdf6c4SBarry Smith 
372f4bdf6c4SBarry Smith         to_var_entry = to_var_entry * 7;
373f4bdf6c4SBarry Smith         entries[j]   = to_var_entry;
374f4bdf6c4SBarry Smith 
375f4bdf6c4SBarry Smith         stencil = to_grid_rank - grid_rank;
376f4bdf6c4SBarry Smith         if (!stencil) {
377f4bdf6c4SBarry Smith           entries[j] += 3;
378f4bdf6c4SBarry Smith         } else if (stencil == -1) {
379f4bdf6c4SBarry Smith           entries[j] += 2;
380f4bdf6c4SBarry Smith         } else if (stencil == 1) {
381f4bdf6c4SBarry Smith           entries[j] += 4;
382f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnx) {
383f4bdf6c4SBarry Smith           entries[j] += 1;
384f4bdf6c4SBarry Smith         } else if (stencil == ex->gnx) {
385f4bdf6c4SBarry Smith           entries[j] += 5;
386f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnxgny) {
387f4bdf6c4SBarry Smith           entries[j] += 0;
388f4bdf6c4SBarry Smith         } else if (stencil == ex->gnxgny) {
389f4bdf6c4SBarry Smith           entries[j] += 6;
39063a3b9bcSJacob 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);
391f4bdf6c4SBarry Smith       }
392f4bdf6c4SBarry Smith 
393f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
3942cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
3952cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny));
3962cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny)));
397f4bdf6c4SBarry Smith 
398792fecdfSBarry Smith       if (addv == ADD_VALUES) PetscCallExternal(HYPRE_SStructMatrixAddToValues, ex->ss_mat, part, index, var_type, ncol, entries, values);
399792fecdfSBarry Smith       else PetscCallExternal(HYPRE_SStructMatrixSetValues, ex->ss_mat, part, index, var_type, ncol, entries, values);
400f4bdf6c4SBarry Smith       values += ncol;
401f4bdf6c4SBarry Smith     }
402f4bdf6c4SBarry Smith   } else {
403f4bdf6c4SBarry Smith     for (i = 0; i < nrow; i++) {
404f4bdf6c4SBarry Smith       var_type  = irow[i] / (ex->gnxgnygnz);
405f4bdf6c4SBarry Smith       grid_rank = irow[i] - var_type * (ex->gnxgnygnz);
406f4bdf6c4SBarry Smith 
407f4bdf6c4SBarry Smith       for (j = 0; j < ncol; j++) {
408f4bdf6c4SBarry Smith         to_var_type  = icol[j] / (ex->gnxgnygnz);
409f4bdf6c4SBarry Smith         to_grid_rank = icol[j] - to_var_type * (ex->gnxgnygnz);
410f4bdf6c4SBarry Smith 
411f4bdf6c4SBarry Smith         to_var_entry = to_var_entry * 7;
412f4bdf6c4SBarry Smith         entries[j]   = to_var_entry;
413f4bdf6c4SBarry Smith 
414f4bdf6c4SBarry Smith         stencil = to_grid_rank - grid_rank;
415f4bdf6c4SBarry Smith         if (!stencil) {
416f4bdf6c4SBarry Smith           entries[j] += 3;
417f4bdf6c4SBarry Smith         } else if (stencil == -1) {
418f4bdf6c4SBarry Smith           entries[j] += 2;
419f4bdf6c4SBarry Smith         } else if (stencil == 1) {
420f4bdf6c4SBarry Smith           entries[j] += 4;
421f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnx) {
422f4bdf6c4SBarry Smith           entries[j] += 1;
423f4bdf6c4SBarry Smith         } else if (stencil == ex->gnx) {
424f4bdf6c4SBarry Smith           entries[j] += 5;
425f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnxgny) {
426f4bdf6c4SBarry Smith           entries[j] += 0;
427f4bdf6c4SBarry Smith         } else if (stencil == ex->gnxgny) {
428f4bdf6c4SBarry Smith           entries[j] += 6;
42963a3b9bcSJacob 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);
430f4bdf6c4SBarry Smith       }
431f4bdf6c4SBarry Smith 
432f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
4332cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
4342cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny));
4352cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny)));
436f4bdf6c4SBarry Smith 
437792fecdfSBarry Smith       if (addv == ADD_VALUES) PetscCallExternal(HYPRE_SStructMatrixAddToValues, ex->ss_mat, part, index, var_type, ncol, entries, values);
438792fecdfSBarry Smith       else PetscCallExternal(HYPRE_SStructMatrixSetValues, ex->ss_mat, part, index, var_type, ncol, entries, values);
439f4bdf6c4SBarry Smith       values += ncol;
440f4bdf6c4SBarry Smith     }
441f4bdf6c4SBarry Smith   }
4429566063dSJacob Faibussowitsch   PetscCall(PetscFree(entries));
4433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
444f4bdf6c4SBarry Smith }
445f4bdf6c4SBarry Smith 
44666976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroRowsLocal_HYPRESStruct_3d(Mat mat, PetscInt nrow, const PetscInt irow[], PetscScalar d, Vec x, Vec b)
447d71ae5a4SJacob Faibussowitsch {
4482cf14000SStefano Zampini   HYPRE_Int         index[3], *entries;
4492cf14000SStefano Zampini   PetscInt          i;
45039accc25SStefano Zampini   HYPRE_Complex   **values;
451f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct *)mat->data;
452f4bdf6c4SBarry Smith 
4534ddd07fcSJed Brown   PetscInt part     = 0; /* Petsc sstruct interface only allows 1 part */
4544ddd07fcSJed Brown   PetscInt ordering = ex->dofs_order;
4554ddd07fcSJed Brown   PetscInt grid_rank;
4564ddd07fcSJed Brown   PetscInt var_type;
4574ddd07fcSJed Brown   PetscInt nvars = ex->nvars;
4582cf14000SStefano Zampini   PetscInt row;
459f4bdf6c4SBarry Smith 
460f4bdf6c4SBarry Smith   PetscFunctionBegin;
46108401ef6SPierre Jolivet   PetscCheck(!x || !b, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "No support");
4629566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(7 * nvars, &entries));
463f4bdf6c4SBarry Smith 
4649566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nvars, &values));
4659566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(7 * nvars * nvars, &values[0]));
466ad540459SPierre Jolivet   for (i = 1; i < nvars; i++) values[i] = values[i - 1] + nvars * 7;
467f4bdf6c4SBarry Smith 
468f4bdf6c4SBarry Smith   for (i = 0; i < nvars; i++) {
4699566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(values[i], nvars * 7 * sizeof(HYPRE_Complex)));
4709566063dSJacob Faibussowitsch     PetscCall(PetscHYPREScalarCast(d, values[i] + 3));
471f4bdf6c4SBarry Smith   }
472f4bdf6c4SBarry Smith 
4738865f1eaSKarl Rupp   for (i = 0; i < nvars * 7; i++) entries[i] = i;
474f4bdf6c4SBarry Smith 
475f4bdf6c4SBarry Smith   if (!ordering) {
476f4bdf6c4SBarry Smith     for (i = 0; i < nrow; i++) {
477f4bdf6c4SBarry Smith       grid_rank = irow[i] / nvars;
478f4bdf6c4SBarry Smith       var_type  = (irow[i] % nvars);
479f4bdf6c4SBarry Smith 
480f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
4812cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
4822cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny));
4832cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny)));
484792fecdfSBarry Smith       PetscCallExternal(HYPRE_SStructMatrixSetValues, ex->ss_mat, part, index, var_type, 7 * nvars, entries, values[var_type]);
485f4bdf6c4SBarry Smith     }
486f4bdf6c4SBarry Smith   } else {
487f4bdf6c4SBarry Smith     for (i = 0; i < nrow; i++) {
488f4bdf6c4SBarry Smith       var_type  = irow[i] / (ex->gnxgnygnz);
489f4bdf6c4SBarry Smith       grid_rank = irow[i] - var_type * (ex->gnxgnygnz);
490f4bdf6c4SBarry Smith 
491f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
4922cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
4932cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny));
4942cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny)));
495792fecdfSBarry Smith       PetscCallExternal(HYPRE_SStructMatrixSetValues, ex->ss_mat, part, index, var_type, 7 * nvars, entries, values[var_type]);
496f4bdf6c4SBarry Smith     }
497f4bdf6c4SBarry Smith   }
498792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructMatrixAssemble, ex->ss_mat);
4999566063dSJacob Faibussowitsch   PetscCall(PetscFree(values[0]));
5009566063dSJacob Faibussowitsch   PetscCall(PetscFree(values));
5019566063dSJacob Faibussowitsch   PetscCall(PetscFree(entries));
5023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
503f4bdf6c4SBarry Smith }
504f4bdf6c4SBarry Smith 
50566976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPRESStruct_3d(Mat mat)
506d71ae5a4SJacob Faibussowitsch {
507f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex    = (Mat_HYPRESStruct *)mat->data;
5084ddd07fcSJed Brown   PetscInt          nvars = ex->nvars;
5094ddd07fcSJed Brown   PetscInt          size;
5104ddd07fcSJed Brown   PetscInt          part = 0; /* only one part */
511f4bdf6c4SBarry Smith 
512f4bdf6c4SBarry Smith   PetscFunctionBegin;
513*f4f49eeaSPierre Jolivet   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);
514f4bdf6c4SBarry Smith   {
5152cf14000SStefano Zampini     HYPRE_Int      i, *entries, iupper[3], ilower[3];
51639accc25SStefano Zampini     HYPRE_Complex *values;
5174ddd07fcSJed Brown 
518f4bdf6c4SBarry Smith     for (i = 0; i < 3; i++) {
519f4bdf6c4SBarry Smith       ilower[i] = ex->hbox.imin[i];
520f4bdf6c4SBarry Smith       iupper[i] = ex->hbox.imax[i];
521f4bdf6c4SBarry Smith     }
522f4bdf6c4SBarry Smith 
5239566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nvars * 7, &entries, nvars * 7 * size, &values));
5248865f1eaSKarl Rupp     for (i = 0; i < nvars * 7; i++) entries[i] = i;
5259566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(values, nvars * 7 * size));
526f4bdf6c4SBarry Smith 
52748a46eb9SPierre Jolivet     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructMatrixSetBoxValues, ex->ss_mat, part, ilower, iupper, i, nvars * 7, entries, values);
5289566063dSJacob Faibussowitsch     PetscCall(PetscFree2(entries, values));
529f4bdf6c4SBarry Smith   }
530792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructMatrixAssemble, ex->ss_mat);
5313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
532f4bdf6c4SBarry Smith }
533f4bdf6c4SBarry Smith 
534d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetUp_HYPRESStruct(Mat mat)
535d71ae5a4SJacob Faibussowitsch {
536f4bdf6c4SBarry Smith   Mat_HYPRESStruct      *ex = (Mat_HYPRESStruct *)mat->data;
537f4bdf6c4SBarry Smith   PetscInt               dim, dof, sw[3], nx, ny, nz;
5384ddd07fcSJed Brown   PetscInt               ilower[3], iupper[3], ssize, i;
539bff4a2f0SMatthew G. Knepley   DMBoundaryType         px, py, pz;
540f4bdf6c4SBarry Smith   DMDAStencilType        st;
5414ddd07fcSJed Brown   PetscInt               nparts = 1; /* assuming only one part */
5424ddd07fcSJed Brown   PetscInt               part   = 0;
543565245c5SBarry Smith   ISLocalToGlobalMapping ltog;
54459cb773eSBarry Smith   DM                     da;
545b026d285SBarry Smith 
546f4bdf6c4SBarry Smith   PetscFunctionBegin;
5479566063dSJacob Faibussowitsch   PetscCall(MatGetDM(mat, (DM *)&da));
548f4bdf6c4SBarry Smith   ex->da = da;
5499566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)da));
550f4bdf6c4SBarry Smith 
5519566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(ex->da, &dim, 0, 0, 0, 0, 0, 0, &dof, &sw[0], &px, &py, &pz, &st));
5529566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
553f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
554f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
555f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
556f4bdf6c4SBarry Smith   /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
557f4bdf6c4SBarry Smith   ex->hbox.imin[0] = ilower[0];
558f4bdf6c4SBarry Smith   ex->hbox.imin[1] = ilower[1];
559f4bdf6c4SBarry Smith   ex->hbox.imin[2] = ilower[2];
560f4bdf6c4SBarry Smith   ex->hbox.imax[0] = iupper[0];
561f4bdf6c4SBarry Smith   ex->hbox.imax[1] = iupper[1];
562f4bdf6c4SBarry Smith   ex->hbox.imax[2] = iupper[2];
563f4bdf6c4SBarry Smith 
564f4bdf6c4SBarry Smith   ex->dofs_order = 0;
565f4bdf6c4SBarry Smith 
566f4bdf6c4SBarry Smith   /* assuming that the same number of dofs on each gridpoint. Also assume all cell-centred based */
567f4bdf6c4SBarry Smith   ex->nvars = dof;
568f4bdf6c4SBarry Smith 
569f4bdf6c4SBarry Smith   /* create the hypre grid object and set its information */
5701dca8a05SBarry Smith   PetscCheck(!px && !py && !pz, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add periodic support by calling HYPRE_SStructGridSetPeriodic()");
571792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGridCreate, ex->hcomm, dim, nparts, &ex->ss_grid);
572792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGridSetExtents, ex->ss_grid, part, ex->hbox.imin, ex->hbox.imax);
573f4bdf6c4SBarry Smith   {
574f4bdf6c4SBarry Smith     HYPRE_SStructVariable *vartypes;
5759566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(ex->nvars, &vartypes));
5768865f1eaSKarl Rupp     for (i = 0; i < ex->nvars; i++) vartypes[i] = HYPRE_SSTRUCT_VARIABLE_CELL;
577792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructGridSetVariables, ex->ss_grid, part, ex->nvars, vartypes);
5789566063dSJacob Faibussowitsch     PetscCall(PetscFree(vartypes));
579f4bdf6c4SBarry Smith   }
580792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGridAssemble, ex->ss_grid);
581f4bdf6c4SBarry Smith 
582f4bdf6c4SBarry Smith   sw[1] = sw[0];
583f4bdf6c4SBarry Smith   sw[2] = sw[1];
584792fecdfSBarry Smith   /* PetscCallExternal(HYPRE_SStructGridSetNumGhost,ex->ss_grid,sw); */
585f4bdf6c4SBarry Smith 
586f4bdf6c4SBarry Smith   /* create the hypre stencil object and set its information */
58708401ef6SPierre Jolivet   PetscCheck(sw[0] <= 1, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add support for wider stencils");
58808401ef6SPierre Jolivet   PetscCheck(st != DMDA_STENCIL_BOX, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add support for box stencils");
589f4bdf6c4SBarry Smith 
590f4bdf6c4SBarry Smith   if (dim == 1) {
5912cf14000SStefano Zampini     HYPRE_Int offsets[3][1] = {{-1}, {0}, {1}};
5924ddd07fcSJed Brown     PetscInt  j, cnt;
593f4bdf6c4SBarry Smith 
594f4bdf6c4SBarry Smith     ssize = 3 * (ex->nvars);
595792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructStencilCreate, dim, ssize, &ex->ss_stencil);
596f4bdf6c4SBarry Smith     cnt = 0;
597f4bdf6c4SBarry Smith     for (i = 0; i < (ex->nvars); i++) {
598f4bdf6c4SBarry Smith       for (j = 0; j < 3; j++) {
599792fecdfSBarry Smith         PetscCallExternal(HYPRE_SStructStencilSetEntry, ex->ss_stencil, cnt, offsets[j], i);
600f4bdf6c4SBarry Smith         cnt++;
601f4bdf6c4SBarry Smith       }
602f4bdf6c4SBarry Smith     }
603f4bdf6c4SBarry Smith   } else if (dim == 2) {
6049371c9d4SSatish Balay     HYPRE_Int offsets[5][2] = {
6059371c9d4SSatish Balay       {0,  -1},
6069371c9d4SSatish Balay       {-1, 0 },
6079371c9d4SSatish Balay       {0,  0 },
6089371c9d4SSatish Balay       {1,  0 },
6099371c9d4SSatish Balay       {0,  1 }
6109371c9d4SSatish Balay     };
6114ddd07fcSJed Brown     PetscInt j, cnt;
612f4bdf6c4SBarry Smith 
613f4bdf6c4SBarry Smith     ssize = 5 * (ex->nvars);
614792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructStencilCreate, dim, ssize, &ex->ss_stencil);
615f4bdf6c4SBarry Smith     cnt = 0;
616f4bdf6c4SBarry Smith     for (i = 0; i < (ex->nvars); i++) {
617f4bdf6c4SBarry Smith       for (j = 0; j < 5; j++) {
618792fecdfSBarry Smith         PetscCallExternal(HYPRE_SStructStencilSetEntry, ex->ss_stencil, cnt, offsets[j], i);
619f4bdf6c4SBarry Smith         cnt++;
620f4bdf6c4SBarry Smith       }
621f4bdf6c4SBarry Smith     }
622f4bdf6c4SBarry Smith   } else if (dim == 3) {
6239371c9d4SSatish Balay     HYPRE_Int offsets[7][3] = {
6249371c9d4SSatish Balay       {0,  0,  -1},
6259371c9d4SSatish Balay       {0,  -1, 0 },
6269371c9d4SSatish Balay       {-1, 0,  0 },
6279371c9d4SSatish Balay       {0,  0,  0 },
6289371c9d4SSatish Balay       {1,  0,  0 },
6299371c9d4SSatish Balay       {0,  1,  0 },
6309371c9d4SSatish Balay       {0,  0,  1 }
6319371c9d4SSatish Balay     };
6324ddd07fcSJed Brown     PetscInt j, cnt;
633f4bdf6c4SBarry Smith 
634f4bdf6c4SBarry Smith     ssize = 7 * (ex->nvars);
635792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructStencilCreate, dim, ssize, &ex->ss_stencil);
636f4bdf6c4SBarry Smith     cnt = 0;
637f4bdf6c4SBarry Smith     for (i = 0; i < (ex->nvars); i++) {
638f4bdf6c4SBarry Smith       for (j = 0; j < 7; j++) {
639792fecdfSBarry Smith         PetscCallExternal(HYPRE_SStructStencilSetEntry, ex->ss_stencil, cnt, offsets[j], i);
640f4bdf6c4SBarry Smith         cnt++;
641f4bdf6c4SBarry Smith       }
642f4bdf6c4SBarry Smith     }
643f4bdf6c4SBarry Smith   }
644f4bdf6c4SBarry Smith 
645f4bdf6c4SBarry Smith   /* create the HYPRE graph */
646*f4f49eeaSPierre Jolivet   PetscCallExternal(HYPRE_SStructGraphCreate, ex->hcomm, ex->ss_grid, &ex->ss_graph);
647f4bdf6c4SBarry Smith 
648f4bdf6c4SBarry Smith   /* set the stencil graph. Note that each variable has the same graph. This means that each
649f4bdf6c4SBarry Smith      variable couples to all the other variable and with the same stencil pattern. */
65048a46eb9SPierre Jolivet   for (i = 0; i < (ex->nvars); i++) PetscCallExternal(HYPRE_SStructGraphSetStencil, ex->ss_graph, part, i, ex->ss_stencil);
651792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGraphAssemble, ex->ss_graph);
652f4bdf6c4SBarry Smith 
653f4bdf6c4SBarry Smith   /* create the HYPRE sstruct vectors for rhs and solution */
654792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorCreate, ex->hcomm, ex->ss_grid, &ex->ss_b);
655792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorCreate, ex->hcomm, ex->ss_grid, &ex->ss_x);
656792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorInitialize, ex->ss_b);
657792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorInitialize, ex->ss_x);
658792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorAssemble, ex->ss_b);
659792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorAssemble, ex->ss_x);
660f4bdf6c4SBarry Smith 
661f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
662792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructMatrixCreate, ex->hcomm, ex->ss_graph, &ex->ss_mat);
663792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGridDestroy, ex->ss_grid);
664792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructStencilDestroy, ex->ss_stencil);
665f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
666792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixInitialize, ex->ss_mat);
667f4bdf6c4SBarry Smith     ex->needsinitialization = PETSC_FALSE;
668f4bdf6c4SBarry Smith   }
669f4bdf6c4SBarry Smith 
670f4bdf6c4SBarry Smith   /* set the global and local sizes of the matrix */
6719566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, 0, 0, 0, &nx, &ny, &nz));
6729566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat, dof * nx * ny * nz, dof * nx * ny * nz, PETSC_DECIDE, PETSC_DECIDE));
6739566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->rmap, dof));
6749566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->cmap, dof));
6759566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->rmap));
6769566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->cmap));
67761710fbeSStefano Zampini   mat->preallocated = PETSC_TRUE;
678f4bdf6c4SBarry Smith 
679f4bdf6c4SBarry Smith   if (dim == 3) {
680f4bdf6c4SBarry Smith     mat->ops->setvalueslocal = MatSetValuesLocal_HYPRESStruct_3d;
681f4bdf6c4SBarry Smith     mat->ops->zerorowslocal  = MatZeroRowsLocal_HYPRESStruct_3d;
682f4bdf6c4SBarry Smith     mat->ops->zeroentries    = MatZeroEntries_HYPRESStruct_3d;
6838865f1eaSKarl Rupp 
6849566063dSJacob Faibussowitsch     /* PetscCall(MatZeroEntries_HYPRESStruct_3d(mat)); */
685ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Only support for 3d DMDA currently");
686f4bdf6c4SBarry Smith 
687f4bdf6c4SBarry Smith   /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
6889566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(mat, &ex->rstart, NULL));
6899566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(ex->da, &ltog));
6909566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **)&ex->gindices));
6919566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(ex->da, 0, 0, 0, &ex->gnx, &ex->gnxgny, &ex->gnxgnygnz));
6928865f1eaSKarl Rupp 
693f4bdf6c4SBarry Smith   ex->gnxgny *= ex->gnx;
694f4bdf6c4SBarry Smith   ex->gnxgnygnz *= ex->gnxgny;
6958865f1eaSKarl Rupp 
6969566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da, &ex->xs, &ex->ys, &ex->zs, &ex->nx, &ex->ny, &ex->nz));
6978865f1eaSKarl Rupp 
698f4bdf6c4SBarry Smith   ex->nxny   = ex->nx * ex->ny;
699f4bdf6c4SBarry Smith   ex->nxnynz = ex->nz * ex->nxny;
7003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
701f4bdf6c4SBarry Smith }
702f4bdf6c4SBarry Smith 
70366976f2fSJacob Faibussowitsch static PetscErrorCode MatMult_HYPRESStruct(Mat A, Vec x, Vec y)
704d71ae5a4SJacob Faibussowitsch {
705b026d285SBarry Smith   const PetscScalar *xx;
706b026d285SBarry Smith   PetscScalar       *yy;
7072cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
7084ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
709*f4f49eeaSPierre Jolivet   Mat_HYPRESStruct  *mx       = (Mat_HYPRESStruct *)A->data;
7104ddd07fcSJed Brown   PetscInt           ordering = mx->dofs_order;
7114ddd07fcSJed Brown   PetscInt           nvars    = mx->nvars;
7124ddd07fcSJed Brown   PetscInt           part     = 0;
7134ddd07fcSJed Brown   PetscInt           size;
7144ddd07fcSJed Brown   PetscInt           i;
715f4bdf6c4SBarry Smith 
716f4bdf6c4SBarry Smith   PetscFunctionBegin;
7179566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
7182cf14000SStefano Zampini 
7192cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
720f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
721f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
722f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
7232cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
7242cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
7252cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
7262cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
7272cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
7282cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
729f4bdf6c4SBarry Smith 
730f4bdf6c4SBarry Smith   size = 1;
7318865f1eaSKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i] - ilower[i] + 1);
732f4bdf6c4SBarry Smith 
733f4bdf6c4SBarry Smith   /* copy x values over to hypre for variable ordering */
734f4bdf6c4SBarry Smith   if (ordering) {
735792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
7369566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
73748a46eb9SPierre Jolivet     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(xx + (size * i)));
7389566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
739792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
740792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixMatvec, 1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x);
741f4bdf6c4SBarry Smith 
742f4bdf6c4SBarry Smith     /* copy solution values back to PETSc */
7439566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
74448a46eb9SPierre Jolivet     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(yy + (size * i)));
7459566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
746f4bdf6c4SBarry Smith   } else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */
747f4bdf6c4SBarry Smith     PetscScalar *z;
7484ddd07fcSJed Brown     PetscInt     j, k;
749f4bdf6c4SBarry Smith 
7509566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nvars * size, &z));
751792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
7529566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
753f4bdf6c4SBarry Smith 
754f4bdf6c4SBarry Smith     /* transform nodal to hypre's variable ordering for sys_pfmg */
755f4bdf6c4SBarry Smith     for (i = 0; i < size; i++) {
756f4bdf6c4SBarry Smith       k = i * nvars;
7578865f1eaSKarl Rupp       for (j = 0; j < nvars; j++) z[j * size + i] = xx[k + j];
758f4bdf6c4SBarry Smith     }
75948a46eb9SPierre Jolivet     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
7609566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
761792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
762792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixMatvec, 1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x);
763f4bdf6c4SBarry Smith 
764f4bdf6c4SBarry Smith     /* copy solution values back to PETSc */
7659566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
76648a46eb9SPierre Jolivet     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
767f4bdf6c4SBarry Smith     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
768f4bdf6c4SBarry Smith     for (i = 0; i < size; i++) {
769f4bdf6c4SBarry Smith       k = i * nvars;
7708865f1eaSKarl Rupp       for (j = 0; j < nvars; j++) yy[k + j] = z[j * size + i];
771f4bdf6c4SBarry Smith     }
7729566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
7739566063dSJacob Faibussowitsch     PetscCall(PetscFree(z));
774f4bdf6c4SBarry Smith   }
7753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
776f4bdf6c4SBarry Smith }
777f4bdf6c4SBarry Smith 
77866976f2fSJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_HYPRESStruct(Mat mat, MatAssemblyType mode)
779d71ae5a4SJacob Faibussowitsch {
780f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct *)mat->data;
781f4bdf6c4SBarry Smith 
782f4bdf6c4SBarry Smith   PetscFunctionBegin;
783792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructMatrixAssemble, ex->ss_mat);
7843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
785f4bdf6c4SBarry Smith }
786f4bdf6c4SBarry Smith 
78766976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPRESStruct(Mat mat)
788d71ae5a4SJacob Faibussowitsch {
789f4bdf6c4SBarry Smith   PetscFunctionBegin;
790f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
7913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
792f4bdf6c4SBarry Smith }
793f4bdf6c4SBarry Smith 
79466976f2fSJacob Faibussowitsch static PetscErrorCode MatDestroy_HYPRESStruct(Mat mat)
795d71ae5a4SJacob Faibussowitsch {
796f4bdf6c4SBarry Smith   Mat_HYPRESStruct      *ex = (Mat_HYPRESStruct *)mat->data;
797d94fc0b6SBarry Smith   ISLocalToGlobalMapping ltog;
798f4bdf6c4SBarry Smith 
799f4bdf6c4SBarry Smith   PetscFunctionBegin;
8009566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(ex->da, &ltog));
8019566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreIndices(ltog, (const PetscInt **)&ex->gindices));
802792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGraphDestroy, ex->ss_graph);
803792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructMatrixDestroy, ex->ss_mat);
804792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorDestroy, ex->ss_x);
805792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorDestroy, ex->ss_b);
8069566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)ex->da));
807*f4f49eeaSPierre Jolivet   PetscCallMPI(MPI_Comm_free(&ex->hcomm));
8089566063dSJacob Faibussowitsch   PetscCall(PetscFree(ex));
8093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
810f4bdf6c4SBarry Smith }
811f4bdf6c4SBarry Smith 
812d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_HYPRESStruct(Mat B)
813d71ae5a4SJacob Faibussowitsch {
814f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex;
815f4bdf6c4SBarry Smith 
816f4bdf6c4SBarry Smith   PetscFunctionBegin;
8174dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&ex));
818f4bdf6c4SBarry Smith   B->data      = (void *)ex;
819f4bdf6c4SBarry Smith   B->rmap->bs  = 1;
820f4bdf6c4SBarry Smith   B->assembled = PETSC_FALSE;
821f4bdf6c4SBarry Smith 
822f4bdf6c4SBarry Smith   B->insertmode = NOT_SET_VALUES;
823f4bdf6c4SBarry Smith 
824f4bdf6c4SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_HYPRESStruct;
825f4bdf6c4SBarry Smith   B->ops->mult        = MatMult_HYPRESStruct;
826f4bdf6c4SBarry Smith   B->ops->zeroentries = MatZeroEntries_HYPRESStruct;
827f4bdf6c4SBarry Smith   B->ops->destroy     = MatDestroy_HYPRESStruct;
82859cb773eSBarry Smith   B->ops->setup       = MatSetUp_HYPRESStruct;
829f4bdf6c4SBarry Smith 
830f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
831f4bdf6c4SBarry Smith 
832*f4f49eeaSPierre Jolivet   PetscCallMPI(MPI_Comm_dup(PetscObjectComm((PetscObject)B), &ex->hcomm));
8339566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRESSTRUCT));
834ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
8353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
836f4bdf6c4SBarry Smith }
837