xref: /petsc/src/dm/impls/da/hypre/mhyp.c (revision ea9ee2c1d69c9e3cf6d2b3c8a205b9880d3dba39)
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
21dce8aebaSBarry Smith           be defined by a `DMDA`.
22f4bdf6c4SBarry Smith 
23dce8aebaSBarry 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 
28d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValuesLocal_HYPREStruct_3d(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
29d71ae5a4SJacob Faibussowitsch {
3076a007c6Sftrigaux   HYPRE_Int        index[3], entries[9];
312cf14000SStefano Zampini   PetscInt         i, j, stencil, row;
3239accc25SStefano Zampini   HYPRE_Complex   *values = (HYPRE_Complex *)y;
33f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex     = (Mat_HYPREStruct *)mat->data;
34f4bdf6c4SBarry Smith 
35f4bdf6c4SBarry Smith   PetscFunctionBegin;
3676a007c6Sftrigaux   PetscCheck(ncol <= 9, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "ncol %" PetscInt_FMT " > 9 too large", ncol);
37f4bdf6c4SBarry Smith   for (i = 0; i < nrow; i++) {
38f4bdf6c4SBarry Smith     for (j = 0; j < ncol; j++) {
39f4bdf6c4SBarry Smith       stencil = icol[j] - irow[i];
40f4bdf6c4SBarry Smith       if (!stencil) {
41f4bdf6c4SBarry Smith         entries[j] = 3;
42f4bdf6c4SBarry Smith       } else if (stencil == -1) {
43f4bdf6c4SBarry Smith         entries[j] = 2;
44f4bdf6c4SBarry Smith       } else if (stencil == 1) {
45f4bdf6c4SBarry Smith         entries[j] = 4;
46f4bdf6c4SBarry Smith       } else if (stencil == -ex->gnx) {
47f4bdf6c4SBarry Smith         entries[j] = 1;
48f4bdf6c4SBarry Smith       } else if (stencil == ex->gnx) {
49f4bdf6c4SBarry Smith         entries[j] = 5;
50f4bdf6c4SBarry Smith       } else if (stencil == -ex->gnxgny) {
51f4bdf6c4SBarry Smith         entries[j] = 0;
52f4bdf6c4SBarry Smith       } else if (stencil == ex->gnxgny) {
53f4bdf6c4SBarry Smith         entries[j] = 6;
5463a3b9bcSJacob Faibussowitsch       } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Local row %" PetscInt_FMT " local column %" PetscInt_FMT " have bad stencil %" PetscInt_FMT, irow[i], icol[j], stencil);
55f4bdf6c4SBarry Smith     }
56f4bdf6c4SBarry Smith     row      = ex->gindices[irow[i]] - ex->rstart;
572cf14000SStefano Zampini     index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
582cf14000SStefano Zampini     index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny));
592cf14000SStefano Zampini     index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny)));
60792fecdfSBarry Smith     if (addv == ADD_VALUES) PetscCallExternal(HYPRE_StructMatrixAddToValues, ex->hmat, index, ncol, entries, values);
61792fecdfSBarry Smith     else PetscCallExternal(HYPRE_StructMatrixSetValues, ex->hmat, index, ncol, entries, values);
62f4bdf6c4SBarry Smith     values += ncol;
63f4bdf6c4SBarry Smith   }
643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
65f4bdf6c4SBarry Smith }
66f4bdf6c4SBarry Smith 
67d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroRowsLocal_HYPREStruct_3d(Mat mat, PetscInt nrow, const PetscInt irow[], PetscScalar d, Vec x, Vec b)
68d71ae5a4SJacob Faibussowitsch {
692cf14000SStefano Zampini   HYPRE_Int        index[3], entries[7] = {0, 1, 2, 3, 4, 5, 6};
702cf14000SStefano Zampini   PetscInt         row, i;
7139accc25SStefano Zampini   HYPRE_Complex    values[7];
72f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct *)mat->data;
73f4bdf6c4SBarry Smith 
74f4bdf6c4SBarry Smith   PetscFunctionBegin;
7508401ef6SPierre Jolivet   PetscCheck(!x || !b, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "No support");
769566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(values, 7));
779566063dSJacob Faibussowitsch   PetscCall(PetscHYPREScalarCast(d, &values[3]));
78f4bdf6c4SBarry Smith   for (i = 0; i < nrow; i++) {
79f4bdf6c4SBarry Smith     row      = ex->gindices[irow[i]] - ex->rstart;
802cf14000SStefano Zampini     index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
812cf14000SStefano Zampini     index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny));
822cf14000SStefano Zampini     index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny)));
83792fecdfSBarry Smith     PetscCallExternal(HYPRE_StructMatrixSetValues, ex->hmat, index, 7, entries, values);
84f4bdf6c4SBarry Smith   }
85792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixAssemble, ex->hmat);
863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
87f4bdf6c4SBarry Smith }
88f4bdf6c4SBarry Smith 
89d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroEntries_HYPREStruct_3d(Mat mat)
90d71ae5a4SJacob Faibussowitsch {
912cf14000SStefano Zampini   HYPRE_Int        indices[7] = {0, 1, 2, 3, 4, 5, 6};
92f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex         = (Mat_HYPREStruct *)mat->data;
93f4bdf6c4SBarry Smith 
94f4bdf6c4SBarry Smith   PetscFunctionBegin;
95f4bdf6c4SBarry Smith   /* hypre has no public interface to do this */
96792fecdfSBarry Smith   PetscCallExternal(hypre_StructMatrixClearBoxValues, ex->hmat, &ex->hbox, 7, indices, 0, 1);
97792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixAssemble, ex->hmat);
983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
99f4bdf6c4SBarry Smith }
100f4bdf6c4SBarry Smith 
101d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetUp_HYPREStruct(Mat mat)
102d71ae5a4SJacob Faibussowitsch {
103f4bdf6c4SBarry Smith   Mat_HYPREStruct       *ex = (Mat_HYPREStruct *)mat->data;
1042cf14000SStefano Zampini   HYPRE_Int              sw[6];
105e33d7e95Sftrigaux   HYPRE_Int              hlower[3], hupper[3], period[3] = {0, 0, 0};
106e33d7e95Sftrigaux   PetscInt               dim, dof, psw, Nx, Ny, Nz, nx, ny, nz, ilower[3], iupper[3], ssize, i;
107bff4a2f0SMatthew G. Knepley   DMBoundaryType         px, py, pz;
108f4bdf6c4SBarry Smith   DMDAStencilType        st;
109565245c5SBarry Smith   ISLocalToGlobalMapping ltog;
11059cb773eSBarry Smith   DM                     da;
111f4bdf6c4SBarry Smith 
112f4bdf6c4SBarry Smith   PetscFunctionBegin;
1139566063dSJacob Faibussowitsch   PetscCall(MatGetDM(mat, (DM *)&da));
114f4bdf6c4SBarry Smith   ex->da = da;
1159566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)da));
116f4bdf6c4SBarry Smith 
117e33d7e95Sftrigaux   PetscCall(DMDAGetInfo(ex->da, &dim, &Nx, &Ny, &Nz, 0, 0, 0, &dof, &psw, &px, &py, &pz, &st));
1189566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
1192cf14000SStefano Zampini 
1202cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
121f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
122f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
123f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
1242cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
1252cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
1262cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
1272cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
1282cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
1292cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
130f4bdf6c4SBarry Smith 
131f4bdf6c4SBarry Smith   /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
1322cf14000SStefano Zampini   ex->hbox.imin[0] = hlower[0];
1332cf14000SStefano Zampini   ex->hbox.imin[1] = hlower[1];
1342cf14000SStefano Zampini   ex->hbox.imin[2] = hlower[2];
1352cf14000SStefano Zampini   ex->hbox.imax[0] = hupper[0];
1362cf14000SStefano Zampini   ex->hbox.imax[1] = hupper[1];
1372cf14000SStefano Zampini   ex->hbox.imax[2] = hupper[2];
138f4bdf6c4SBarry Smith 
139f4bdf6c4SBarry Smith   /* create the hypre grid object and set its information */
14008401ef6SPierre Jolivet   PetscCheck(dof <= 1, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Currently only support for scalar problems");
141e33d7e95Sftrigaux   if (px || py || pz) {
142e33d7e95Sftrigaux     if (px == DM_BOUNDARY_PERIODIC) period[0] = (HYPRE_Int)Nx;
143e33d7e95Sftrigaux     if (py == DM_BOUNDARY_PERIODIC) period[1] = (HYPRE_Int)Ny;
144e33d7e95Sftrigaux     if (pz == DM_BOUNDARY_PERIODIC) period[2] = (HYPRE_Int)Nz;
145e33d7e95Sftrigaux   }
146792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructGridCreate, ex->hcomm, dim, &ex->hgrid);
147792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructGridSetExtents, ex->hgrid, hlower, hupper);
148e33d7e95Sftrigaux   PetscCallExternal(HYPRE_StructGridSetPeriodic, ex->hgrid, period);
149792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructGridAssemble, ex->hgrid);
150f4bdf6c4SBarry Smith 
1512cf14000SStefano Zampini   sw[5] = sw[4] = sw[3] = sw[2] = sw[1] = sw[0] = psw;
152792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructGridSetNumGhost, ex->hgrid, sw);
153f4bdf6c4SBarry Smith 
154f4bdf6c4SBarry Smith   /* create the hypre stencil object and set its information */
15508401ef6SPierre Jolivet   PetscCheck(sw[0] <= 1, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add support for wider stencils");
15608401ef6SPierre Jolivet   PetscCheck(st != DMDA_STENCIL_BOX, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add support for box stencils");
157f4bdf6c4SBarry Smith   if (dim == 1) {
1582cf14000SStefano Zampini     HYPRE_Int offsets[3][1] = {{-1}, {0}, {1}};
159f4bdf6c4SBarry Smith     ssize                   = 3;
160792fecdfSBarry Smith     PetscCallExternal(HYPRE_StructStencilCreate, dim, ssize, &ex->hstencil);
16148a46eb9SPierre Jolivet     for (i = 0; i < ssize; i++) PetscCallExternal(HYPRE_StructStencilSetElement, ex->hstencil, i, offsets[i]);
162f4bdf6c4SBarry Smith   } else if (dim == 2) {
1639371c9d4SSatish Balay     HYPRE_Int offsets[5][2] = {
1649371c9d4SSatish Balay       {0,  -1},
1659371c9d4SSatish Balay       {-1, 0 },
1669371c9d4SSatish Balay       {0,  0 },
1679371c9d4SSatish Balay       {1,  0 },
1689371c9d4SSatish Balay       {0,  1 }
1699371c9d4SSatish Balay     };
170f4bdf6c4SBarry Smith     ssize = 5;
171792fecdfSBarry Smith     PetscCallExternal(HYPRE_StructStencilCreate, dim, ssize, &ex->hstencil);
17248a46eb9SPierre Jolivet     for (i = 0; i < ssize; i++) PetscCallExternal(HYPRE_StructStencilSetElement, ex->hstencil, i, offsets[i]);
173f4bdf6c4SBarry Smith   } else if (dim == 3) {
1749371c9d4SSatish Balay     HYPRE_Int offsets[7][3] = {
1759371c9d4SSatish Balay       {0,  0,  -1},
1769371c9d4SSatish Balay       {0,  -1, 0 },
1779371c9d4SSatish Balay       {-1, 0,  0 },
1789371c9d4SSatish Balay       {0,  0,  0 },
1799371c9d4SSatish Balay       {1,  0,  0 },
1809371c9d4SSatish Balay       {0,  1,  0 },
1819371c9d4SSatish Balay       {0,  0,  1 }
1829371c9d4SSatish Balay     };
183f4bdf6c4SBarry Smith     ssize = 7;
184792fecdfSBarry Smith     PetscCallExternal(HYPRE_StructStencilCreate, dim, ssize, &ex->hstencil);
18548a46eb9SPierre Jolivet     for (i = 0; i < ssize; i++) PetscCallExternal(HYPRE_StructStencilSetElement, ex->hstencil, i, offsets[i]);
186f4bdf6c4SBarry Smith   }
187f4bdf6c4SBarry Smith 
188f4bdf6c4SBarry Smith   /* create the HYPRE vector for rhs and solution */
189792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorCreate, ex->hcomm, ex->hgrid, &ex->hb);
190792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorCreate, ex->hcomm, ex->hgrid, &ex->hx);
191792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorInitialize, ex->hb);
192792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorInitialize, ex->hx);
193792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble, ex->hb);
194792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble, ex->hx);
195f4bdf6c4SBarry Smith 
196f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
197792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixCreate, ex->hcomm, ex->hgrid, ex->hstencil, &ex->hmat);
198792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructGridDestroy, ex->hgrid);
199792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructStencilDestroy, ex->hstencil);
200f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
201792fecdfSBarry Smith     PetscCallExternal(HYPRE_StructMatrixInitialize, ex->hmat);
202f4bdf6c4SBarry Smith     ex->needsinitialization = PETSC_FALSE;
203f4bdf6c4SBarry Smith   }
204f4bdf6c4SBarry Smith 
205f4bdf6c4SBarry Smith   /* set the global and local sizes of the matrix */
2069566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, 0, 0, 0, &nx, &ny, &nz));
2079566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat, dof * nx * ny * nz, dof * nx * ny * nz, PETSC_DECIDE, PETSC_DECIDE));
2089566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->rmap, 1));
2099566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->cmap, 1));
2109566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->rmap));
2119566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->cmap));
21259cb773eSBarry Smith   mat->preallocated = PETSC_TRUE;
213f4bdf6c4SBarry Smith 
214f4bdf6c4SBarry Smith   if (dim == 3) {
215f4bdf6c4SBarry Smith     mat->ops->setvalueslocal = MatSetValuesLocal_HYPREStruct_3d;
216f4bdf6c4SBarry Smith     mat->ops->zerorowslocal  = MatZeroRowsLocal_HYPREStruct_3d;
217f4bdf6c4SBarry Smith     mat->ops->zeroentries    = MatZeroEntries_HYPREStruct_3d;
2188865f1eaSKarl Rupp 
2199566063dSJacob Faibussowitsch     /*        PetscCall(MatZeroEntries_HYPREStruct_3d(mat)); */
220ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Only support for 3d DMDA currently");
221f4bdf6c4SBarry Smith 
222f4bdf6c4SBarry Smith   /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
2239566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(mat, &ex->rstart, NULL));
2249566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(ex->da, &ltog));
2259566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **)&ex->gindices));
2269566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(ex->da, 0, 0, 0, &ex->gnx, &ex->gnxgny, 0));
227f4bdf6c4SBarry Smith   ex->gnxgny *= ex->gnx;
2289566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da, &ex->xs, &ex->ys, &ex->zs, &ex->nx, &ex->ny, 0));
229f4bdf6c4SBarry Smith   ex->nxny = ex->nx * ex->ny;
2303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
231f4bdf6c4SBarry Smith }
232f4bdf6c4SBarry Smith 
233d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMult_HYPREStruct(Mat A, Vec x, Vec y)
234d71ae5a4SJacob Faibussowitsch {
235b026d285SBarry Smith   const PetscScalar *xx;
236b026d285SBarry Smith   PetscScalar       *yy;
2374ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
2382cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
239f4bdf6c4SBarry Smith   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)(A->data);
240f4bdf6c4SBarry Smith 
241f4bdf6c4SBarry Smith   PetscFunctionBegin;
2429566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
2432cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
244f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
245f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
246f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
2472cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
2482cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
2492cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
2502cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
2512cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
2522cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
253f4bdf6c4SBarry Smith 
254f4bdf6c4SBarry Smith   /* copy x values over to hypre */
255792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0);
2569566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
257792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx);
2589566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
259792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb);
260792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixMatvec, 1.0, mx->hmat, mx->hb, 0.0, mx->hx);
261f4bdf6c4SBarry Smith 
262f4bdf6c4SBarry Smith   /* copy solution values back to PETSc */
2639566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
264792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy);
2659566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
2663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
267f4bdf6c4SBarry Smith }
268f4bdf6c4SBarry Smith 
269d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAssemblyEnd_HYPREStruct(Mat mat, MatAssemblyType mode)
270d71ae5a4SJacob Faibussowitsch {
271f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct *)mat->data;
272f4bdf6c4SBarry Smith 
273f4bdf6c4SBarry Smith   PetscFunctionBegin;
274792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixAssemble, ex->hmat);
275792fecdfSBarry Smith   /* PetscCallExternal(HYPRE_StructMatrixPrint,"dummy",ex->hmat,0); */
2763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
277f4bdf6c4SBarry Smith }
278f4bdf6c4SBarry Smith 
279d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroEntries_HYPREStruct(Mat mat)
280d71ae5a4SJacob Faibussowitsch {
281f4bdf6c4SBarry Smith   PetscFunctionBegin;
282f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
2833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
284f4bdf6c4SBarry Smith }
285f4bdf6c4SBarry Smith 
286d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_HYPREStruct(Mat mat)
287d71ae5a4SJacob Faibussowitsch {
288f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct *)mat->data;
289f4bdf6c4SBarry Smith 
290f4bdf6c4SBarry Smith   PetscFunctionBegin;
291792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructMatrixDestroy, ex->hmat);
292792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorDestroy, ex->hx);
293792fecdfSBarry Smith   PetscCallExternal(HYPRE_StructVectorDestroy, ex->hb);
2949566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)ex->da));
2959566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&(ex->hcomm)));
2969566063dSJacob Faibussowitsch   PetscCall(PetscFree(ex));
2973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
298f4bdf6c4SBarry Smith }
299f4bdf6c4SBarry Smith 
300d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_HYPREStruct(Mat B)
301d71ae5a4SJacob Faibussowitsch {
302f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex;
303f4bdf6c4SBarry Smith 
304f4bdf6c4SBarry Smith   PetscFunctionBegin;
3054dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&ex));
306f4bdf6c4SBarry Smith   B->data      = (void *)ex;
307f4bdf6c4SBarry Smith   B->rmap->bs  = 1;
308f4bdf6c4SBarry Smith   B->assembled = PETSC_FALSE;
309f4bdf6c4SBarry Smith 
310f4bdf6c4SBarry Smith   B->insertmode = NOT_SET_VALUES;
311f4bdf6c4SBarry Smith 
312f4bdf6c4SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_HYPREStruct;
313f4bdf6c4SBarry Smith   B->ops->mult        = MatMult_HYPREStruct;
314f4bdf6c4SBarry Smith   B->ops->zeroentries = MatZeroEntries_HYPREStruct;
315f4bdf6c4SBarry Smith   B->ops->destroy     = MatDestroy_HYPREStruct;
31659cb773eSBarry Smith   B->ops->setup       = MatSetUp_HYPREStruct;
317f4bdf6c4SBarry Smith 
318f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
319f4bdf6c4SBarry Smith 
3209566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_dup(PetscObjectComm((PetscObject)B), &(ex->hcomm)));
3219566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRESTRUCT));
322*ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
3233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
324f4bdf6c4SBarry Smith }
325f4bdf6c4SBarry Smith 
326f4bdf6c4SBarry Smith /*MC
327f4bdf6c4SBarry Smith    MATHYPRESSTRUCT - MATHYPRESSTRUCT = "hypresstruct" - A matrix type to be used for parallel sparse matrices
328f4bdf6c4SBarry Smith           based on the hypre HYPRE_SStructMatrix.
329f4bdf6c4SBarry Smith 
330f4bdf6c4SBarry Smith    Level: intermediate
331f4bdf6c4SBarry Smith 
33295452b02SPatrick Sanan    Notes:
33395452b02SPatrick Sanan     Unlike hypre's general semi-struct object consisting of a collection of structured-grid objects and unstructured
334b026d285SBarry Smith           grid objects, we restrict the semi-struct objects to consist of only structured-grid components.
335f4bdf6c4SBarry Smith 
336f4bdf6c4SBarry 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
337dce8aebaSBarry Smith           be defined by a `DMDA`.
338f4bdf6c4SBarry Smith 
33959cb773eSBarry Smith           The matrix needs a DMDA associated with it by either a call to MatSetDM() or if the matrix is obtained from DMCreateMatrix()
340f4bdf6c4SBarry Smith 
341dce8aebaSBarry Smith .seealso: `Mat`
342f4bdf6c4SBarry Smith M*/
343f4bdf6c4SBarry Smith 
344d71ae5a4SJacob Faibussowitsch PetscErrorCode MatSetValuesLocal_HYPRESStruct_3d(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
345d71ae5a4SJacob Faibussowitsch {
3462cf14000SStefano Zampini   HYPRE_Int         index[3], *entries;
3472cf14000SStefano Zampini   PetscInt          i, j, stencil;
34839accc25SStefano Zampini   HYPRE_Complex    *values = (HYPRE_Complex *)y;
349f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex     = (Mat_HYPRESStruct *)mat->data;
350f4bdf6c4SBarry Smith 
3514ddd07fcSJed Brown   PetscInt part = 0; /* Petsc sstruct interface only allows 1 part */
3524ddd07fcSJed Brown   PetscInt ordering;
3534ddd07fcSJed Brown   PetscInt grid_rank, to_grid_rank;
3544ddd07fcSJed Brown   PetscInt var_type, to_var_type;
3554ddd07fcSJed Brown   PetscInt to_var_entry = 0;
3564ddd07fcSJed Brown   PetscInt nvars        = ex->nvars;
3572cf14000SStefano Zampini   PetscInt row;
358f4bdf6c4SBarry Smith 
359f4bdf6c4SBarry Smith   PetscFunctionBegin;
3609566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(7 * nvars, &entries));
361f4bdf6c4SBarry Smith   ordering = ex->dofs_order; /* ordering= 0   nodal ordering
362f4bdf6c4SBarry Smith                                            1   variable ordering */
36361710fbeSStefano Zampini   /* stencil entries are ordered by variables: var0_stencil0, var0_stencil1, ..., var0_stencil6, var1_stencil0, var1_stencil1, ...  */
364f4bdf6c4SBarry Smith   if (!ordering) {
365f4bdf6c4SBarry Smith     for (i = 0; i < nrow; i++) {
366f4bdf6c4SBarry Smith       grid_rank = irow[i] / nvars;
367f4bdf6c4SBarry Smith       var_type  = (irow[i] % nvars);
368f4bdf6c4SBarry Smith 
369f4bdf6c4SBarry Smith       for (j = 0; j < ncol; j++) {
370f4bdf6c4SBarry Smith         to_grid_rank = icol[j] / nvars;
371f4bdf6c4SBarry Smith         to_var_type  = (icol[j] % nvars);
372f4bdf6c4SBarry Smith 
373f4bdf6c4SBarry Smith         to_var_entry = to_var_entry * 7;
374f4bdf6c4SBarry Smith         entries[j]   = to_var_entry;
375f4bdf6c4SBarry Smith 
376f4bdf6c4SBarry Smith         stencil = to_grid_rank - grid_rank;
377f4bdf6c4SBarry Smith         if (!stencil) {
378f4bdf6c4SBarry Smith           entries[j] += 3;
379f4bdf6c4SBarry Smith         } else if (stencil == -1) {
380f4bdf6c4SBarry Smith           entries[j] += 2;
381f4bdf6c4SBarry Smith         } else if (stencil == 1) {
382f4bdf6c4SBarry Smith           entries[j] += 4;
383f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnx) {
384f4bdf6c4SBarry Smith           entries[j] += 1;
385f4bdf6c4SBarry Smith         } else if (stencil == ex->gnx) {
386f4bdf6c4SBarry Smith           entries[j] += 5;
387f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnxgny) {
388f4bdf6c4SBarry Smith           entries[j] += 0;
389f4bdf6c4SBarry Smith         } else if (stencil == ex->gnxgny) {
390f4bdf6c4SBarry Smith           entries[j] += 6;
39163a3b9bcSJacob 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);
392f4bdf6c4SBarry Smith       }
393f4bdf6c4SBarry Smith 
394f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
3952cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
3962cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny));
3972cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny)));
398f4bdf6c4SBarry Smith 
399792fecdfSBarry Smith       if (addv == ADD_VALUES) PetscCallExternal(HYPRE_SStructMatrixAddToValues, ex->ss_mat, part, index, var_type, ncol, entries, values);
400792fecdfSBarry Smith       else PetscCallExternal(HYPRE_SStructMatrixSetValues, ex->ss_mat, part, index, var_type, ncol, entries, values);
401f4bdf6c4SBarry Smith       values += ncol;
402f4bdf6c4SBarry Smith     }
403f4bdf6c4SBarry Smith   } else {
404f4bdf6c4SBarry Smith     for (i = 0; i < nrow; i++) {
405f4bdf6c4SBarry Smith       var_type  = irow[i] / (ex->gnxgnygnz);
406f4bdf6c4SBarry Smith       grid_rank = irow[i] - var_type * (ex->gnxgnygnz);
407f4bdf6c4SBarry Smith 
408f4bdf6c4SBarry Smith       for (j = 0; j < ncol; j++) {
409f4bdf6c4SBarry Smith         to_var_type  = icol[j] / (ex->gnxgnygnz);
410f4bdf6c4SBarry Smith         to_grid_rank = icol[j] - to_var_type * (ex->gnxgnygnz);
411f4bdf6c4SBarry Smith 
412f4bdf6c4SBarry Smith         to_var_entry = to_var_entry * 7;
413f4bdf6c4SBarry Smith         entries[j]   = to_var_entry;
414f4bdf6c4SBarry Smith 
415f4bdf6c4SBarry Smith         stencil = to_grid_rank - grid_rank;
416f4bdf6c4SBarry Smith         if (!stencil) {
417f4bdf6c4SBarry Smith           entries[j] += 3;
418f4bdf6c4SBarry Smith         } else if (stencil == -1) {
419f4bdf6c4SBarry Smith           entries[j] += 2;
420f4bdf6c4SBarry Smith         } else if (stencil == 1) {
421f4bdf6c4SBarry Smith           entries[j] += 4;
422f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnx) {
423f4bdf6c4SBarry Smith           entries[j] += 1;
424f4bdf6c4SBarry Smith         } else if (stencil == ex->gnx) {
425f4bdf6c4SBarry Smith           entries[j] += 5;
426f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnxgny) {
427f4bdf6c4SBarry Smith           entries[j] += 0;
428f4bdf6c4SBarry Smith         } else if (stencil == ex->gnxgny) {
429f4bdf6c4SBarry Smith           entries[j] += 6;
43063a3b9bcSJacob 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);
431f4bdf6c4SBarry Smith       }
432f4bdf6c4SBarry Smith 
433f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
4342cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
4352cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny));
4362cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny)));
437f4bdf6c4SBarry Smith 
438792fecdfSBarry Smith       if (addv == ADD_VALUES) PetscCallExternal(HYPRE_SStructMatrixAddToValues, ex->ss_mat, part, index, var_type, ncol, entries, values);
439792fecdfSBarry Smith       else PetscCallExternal(HYPRE_SStructMatrixSetValues, ex->ss_mat, part, index, var_type, ncol, entries, values);
440f4bdf6c4SBarry Smith       values += ncol;
441f4bdf6c4SBarry Smith     }
442f4bdf6c4SBarry Smith   }
4439566063dSJacob Faibussowitsch   PetscCall(PetscFree(entries));
4443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
445f4bdf6c4SBarry Smith }
446f4bdf6c4SBarry Smith 
447d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroRowsLocal_HYPRESStruct_3d(Mat mat, PetscInt nrow, const PetscInt irow[], PetscScalar d, Vec x, Vec b)
448d71ae5a4SJacob Faibussowitsch {
4492cf14000SStefano Zampini   HYPRE_Int         index[3], *entries;
4502cf14000SStefano Zampini   PetscInt          i;
45139accc25SStefano Zampini   HYPRE_Complex   **values;
452f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct *)mat->data;
453f4bdf6c4SBarry Smith 
4544ddd07fcSJed Brown   PetscInt part     = 0; /* Petsc sstruct interface only allows 1 part */
4554ddd07fcSJed Brown   PetscInt ordering = ex->dofs_order;
4564ddd07fcSJed Brown   PetscInt grid_rank;
4574ddd07fcSJed Brown   PetscInt var_type;
4584ddd07fcSJed Brown   PetscInt nvars = ex->nvars;
4592cf14000SStefano Zampini   PetscInt row;
460f4bdf6c4SBarry Smith 
461f4bdf6c4SBarry Smith   PetscFunctionBegin;
46208401ef6SPierre Jolivet   PetscCheck(!x || !b, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "No support");
4639566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(7 * nvars, &entries));
464f4bdf6c4SBarry Smith 
4659566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nvars, &values));
4669566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(7 * nvars * nvars, &values[0]));
467ad540459SPierre Jolivet   for (i = 1; i < nvars; i++) values[i] = values[i - 1] + nvars * 7;
468f4bdf6c4SBarry Smith 
469f4bdf6c4SBarry Smith   for (i = 0; i < nvars; i++) {
4709566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(values[i], nvars * 7 * sizeof(HYPRE_Complex)));
4719566063dSJacob Faibussowitsch     PetscCall(PetscHYPREScalarCast(d, values[i] + 3));
472f4bdf6c4SBarry Smith   }
473f4bdf6c4SBarry Smith 
4748865f1eaSKarl Rupp   for (i = 0; i < nvars * 7; i++) entries[i] = i;
475f4bdf6c4SBarry Smith 
476f4bdf6c4SBarry Smith   if (!ordering) {
477f4bdf6c4SBarry Smith     for (i = 0; i < nrow; i++) {
478f4bdf6c4SBarry Smith       grid_rank = irow[i] / nvars;
479f4bdf6c4SBarry Smith       var_type  = (irow[i] % nvars);
480f4bdf6c4SBarry Smith 
481f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
4822cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
4832cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny));
4842cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny)));
485792fecdfSBarry Smith       PetscCallExternal(HYPRE_SStructMatrixSetValues, ex->ss_mat, part, index, var_type, 7 * nvars, entries, values[var_type]);
486f4bdf6c4SBarry Smith     }
487f4bdf6c4SBarry Smith   } else {
488f4bdf6c4SBarry Smith     for (i = 0; i < nrow; i++) {
489f4bdf6c4SBarry Smith       var_type  = irow[i] / (ex->gnxgnygnz);
490f4bdf6c4SBarry Smith       grid_rank = irow[i] - var_type * (ex->gnxgnygnz);
491f4bdf6c4SBarry Smith 
492f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
4932cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
4942cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny));
4952cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny)));
496792fecdfSBarry Smith       PetscCallExternal(HYPRE_SStructMatrixSetValues, ex->ss_mat, part, index, var_type, 7 * nvars, entries, values[var_type]);
497f4bdf6c4SBarry Smith     }
498f4bdf6c4SBarry Smith   }
499792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructMatrixAssemble, ex->ss_mat);
5009566063dSJacob Faibussowitsch   PetscCall(PetscFree(values[0]));
5019566063dSJacob Faibussowitsch   PetscCall(PetscFree(values));
5029566063dSJacob Faibussowitsch   PetscCall(PetscFree(entries));
5033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
504f4bdf6c4SBarry Smith }
505f4bdf6c4SBarry Smith 
506d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroEntries_HYPRESStruct_3d(Mat mat)
507d71ae5a4SJacob Faibussowitsch {
508f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex    = (Mat_HYPRESStruct *)mat->data;
5094ddd07fcSJed Brown   PetscInt          nvars = ex->nvars;
5104ddd07fcSJed Brown   PetscInt          size;
5114ddd07fcSJed Brown   PetscInt          part = 0; /* only one part */
512f4bdf6c4SBarry Smith 
513f4bdf6c4SBarry Smith   PetscFunctionBegin;
514f4bdf6c4SBarry 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);
515f4bdf6c4SBarry Smith   {
5162cf14000SStefano Zampini     HYPRE_Int      i, *entries, iupper[3], ilower[3];
51739accc25SStefano Zampini     HYPRE_Complex *values;
5184ddd07fcSJed Brown 
519f4bdf6c4SBarry Smith     for (i = 0; i < 3; i++) {
520f4bdf6c4SBarry Smith       ilower[i] = ex->hbox.imin[i];
521f4bdf6c4SBarry Smith       iupper[i] = ex->hbox.imax[i];
522f4bdf6c4SBarry Smith     }
523f4bdf6c4SBarry Smith 
5249566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nvars * 7, &entries, nvars * 7 * size, &values));
5258865f1eaSKarl Rupp     for (i = 0; i < nvars * 7; i++) entries[i] = i;
5269566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(values, nvars * 7 * size));
527f4bdf6c4SBarry Smith 
52848a46eb9SPierre Jolivet     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructMatrixSetBoxValues, ex->ss_mat, part, ilower, iupper, i, nvars * 7, entries, values);
5299566063dSJacob Faibussowitsch     PetscCall(PetscFree2(entries, values));
530f4bdf6c4SBarry Smith   }
531792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructMatrixAssemble, ex->ss_mat);
5323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
533f4bdf6c4SBarry Smith }
534f4bdf6c4SBarry Smith 
535d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetUp_HYPRESStruct(Mat mat)
536d71ae5a4SJacob Faibussowitsch {
537f4bdf6c4SBarry Smith   Mat_HYPRESStruct      *ex = (Mat_HYPRESStruct *)mat->data;
538f4bdf6c4SBarry Smith   PetscInt               dim, dof, sw[3], nx, ny, nz;
5394ddd07fcSJed Brown   PetscInt               ilower[3], iupper[3], ssize, i;
540bff4a2f0SMatthew G. Knepley   DMBoundaryType         px, py, pz;
541f4bdf6c4SBarry Smith   DMDAStencilType        st;
5424ddd07fcSJed Brown   PetscInt               nparts = 1; /* assuming only one part */
5434ddd07fcSJed Brown   PetscInt               part   = 0;
544565245c5SBarry Smith   ISLocalToGlobalMapping ltog;
54559cb773eSBarry Smith   DM                     da;
546b026d285SBarry Smith 
547f4bdf6c4SBarry Smith   PetscFunctionBegin;
5489566063dSJacob Faibussowitsch   PetscCall(MatGetDM(mat, (DM *)&da));
549f4bdf6c4SBarry Smith   ex->da = da;
5509566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)da));
551f4bdf6c4SBarry Smith 
5529566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(ex->da, &dim, 0, 0, 0, 0, 0, 0, &dof, &sw[0], &px, &py, &pz, &st));
5539566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
554f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
555f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
556f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
557f4bdf6c4SBarry Smith   /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
558f4bdf6c4SBarry Smith   ex->hbox.imin[0] = ilower[0];
559f4bdf6c4SBarry Smith   ex->hbox.imin[1] = ilower[1];
560f4bdf6c4SBarry Smith   ex->hbox.imin[2] = ilower[2];
561f4bdf6c4SBarry Smith   ex->hbox.imax[0] = iupper[0];
562f4bdf6c4SBarry Smith   ex->hbox.imax[1] = iupper[1];
563f4bdf6c4SBarry Smith   ex->hbox.imax[2] = iupper[2];
564f4bdf6c4SBarry Smith 
565f4bdf6c4SBarry Smith   ex->dofs_order = 0;
566f4bdf6c4SBarry Smith 
567f4bdf6c4SBarry Smith   /* assuming that the same number of dofs on each gridpoint. Also assume all cell-centred based */
568f4bdf6c4SBarry Smith   ex->nvars = dof;
569f4bdf6c4SBarry Smith 
570f4bdf6c4SBarry Smith   /* create the hypre grid object and set its information */
5711dca8a05SBarry Smith   PetscCheck(!px && !py && !pz, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add periodic support by calling HYPRE_SStructGridSetPeriodic()");
572792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGridCreate, ex->hcomm, dim, nparts, &ex->ss_grid);
573792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGridSetExtents, ex->ss_grid, part, ex->hbox.imin, ex->hbox.imax);
574f4bdf6c4SBarry Smith   {
575f4bdf6c4SBarry Smith     HYPRE_SStructVariable *vartypes;
5769566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(ex->nvars, &vartypes));
5778865f1eaSKarl Rupp     for (i = 0; i < ex->nvars; i++) vartypes[i] = HYPRE_SSTRUCT_VARIABLE_CELL;
578792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructGridSetVariables, ex->ss_grid, part, ex->nvars, vartypes);
5799566063dSJacob Faibussowitsch     PetscCall(PetscFree(vartypes));
580f4bdf6c4SBarry Smith   }
581792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGridAssemble, ex->ss_grid);
582f4bdf6c4SBarry Smith 
583f4bdf6c4SBarry Smith   sw[1] = sw[0];
584f4bdf6c4SBarry Smith   sw[2] = sw[1];
585792fecdfSBarry Smith   /* PetscCallExternal(HYPRE_SStructGridSetNumGhost,ex->ss_grid,sw); */
586f4bdf6c4SBarry Smith 
587f4bdf6c4SBarry Smith   /* create the hypre stencil object and set its information */
58808401ef6SPierre Jolivet   PetscCheck(sw[0] <= 1, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add support for wider stencils");
58908401ef6SPierre Jolivet   PetscCheck(st != DMDA_STENCIL_BOX, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add support for box stencils");
590f4bdf6c4SBarry Smith 
591f4bdf6c4SBarry Smith   if (dim == 1) {
5922cf14000SStefano Zampini     HYPRE_Int offsets[3][1] = {{-1}, {0}, {1}};
5934ddd07fcSJed Brown     PetscInt  j, cnt;
594f4bdf6c4SBarry Smith 
595f4bdf6c4SBarry Smith     ssize = 3 * (ex->nvars);
596792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructStencilCreate, dim, ssize, &ex->ss_stencil);
597f4bdf6c4SBarry Smith     cnt = 0;
598f4bdf6c4SBarry Smith     for (i = 0; i < (ex->nvars); i++) {
599f4bdf6c4SBarry Smith       for (j = 0; j < 3; j++) {
600792fecdfSBarry Smith         PetscCallExternal(HYPRE_SStructStencilSetEntry, ex->ss_stencil, cnt, offsets[j], i);
601f4bdf6c4SBarry Smith         cnt++;
602f4bdf6c4SBarry Smith       }
603f4bdf6c4SBarry Smith     }
604f4bdf6c4SBarry Smith   } else if (dim == 2) {
6059371c9d4SSatish Balay     HYPRE_Int offsets[5][2] = {
6069371c9d4SSatish Balay       {0,  -1},
6079371c9d4SSatish Balay       {-1, 0 },
6089371c9d4SSatish Balay       {0,  0 },
6099371c9d4SSatish Balay       {1,  0 },
6109371c9d4SSatish Balay       {0,  1 }
6119371c9d4SSatish Balay     };
6124ddd07fcSJed Brown     PetscInt j, cnt;
613f4bdf6c4SBarry Smith 
614f4bdf6c4SBarry Smith     ssize = 5 * (ex->nvars);
615792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructStencilCreate, dim, ssize, &ex->ss_stencil);
616f4bdf6c4SBarry Smith     cnt = 0;
617f4bdf6c4SBarry Smith     for (i = 0; i < (ex->nvars); i++) {
618f4bdf6c4SBarry Smith       for (j = 0; j < 5; j++) {
619792fecdfSBarry Smith         PetscCallExternal(HYPRE_SStructStencilSetEntry, ex->ss_stencil, cnt, offsets[j], i);
620f4bdf6c4SBarry Smith         cnt++;
621f4bdf6c4SBarry Smith       }
622f4bdf6c4SBarry Smith     }
623f4bdf6c4SBarry Smith   } else if (dim == 3) {
6249371c9d4SSatish Balay     HYPRE_Int offsets[7][3] = {
6259371c9d4SSatish Balay       {0,  0,  -1},
6269371c9d4SSatish Balay       {0,  -1, 0 },
6279371c9d4SSatish Balay       {-1, 0,  0 },
6289371c9d4SSatish Balay       {0,  0,  0 },
6299371c9d4SSatish Balay       {1,  0,  0 },
6309371c9d4SSatish Balay       {0,  1,  0 },
6319371c9d4SSatish Balay       {0,  0,  1 }
6329371c9d4SSatish Balay     };
6334ddd07fcSJed Brown     PetscInt j, cnt;
634f4bdf6c4SBarry Smith 
635f4bdf6c4SBarry Smith     ssize = 7 * (ex->nvars);
636792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructStencilCreate, dim, ssize, &ex->ss_stencil);
637f4bdf6c4SBarry Smith     cnt = 0;
638f4bdf6c4SBarry Smith     for (i = 0; i < (ex->nvars); i++) {
639f4bdf6c4SBarry Smith       for (j = 0; j < 7; j++) {
640792fecdfSBarry Smith         PetscCallExternal(HYPRE_SStructStencilSetEntry, ex->ss_stencil, cnt, offsets[j], i);
641f4bdf6c4SBarry Smith         cnt++;
642f4bdf6c4SBarry Smith       }
643f4bdf6c4SBarry Smith     }
644f4bdf6c4SBarry Smith   }
645f4bdf6c4SBarry Smith 
646f4bdf6c4SBarry Smith   /* create the HYPRE graph */
647792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGraphCreate, ex->hcomm, ex->ss_grid, &(ex->ss_graph));
648f4bdf6c4SBarry Smith 
649f4bdf6c4SBarry Smith   /* set the stencil graph. Note that each variable has the same graph. This means that each
650f4bdf6c4SBarry Smith      variable couples to all the other variable and with the same stencil pattern. */
65148a46eb9SPierre Jolivet   for (i = 0; i < (ex->nvars); i++) PetscCallExternal(HYPRE_SStructGraphSetStencil, ex->ss_graph, part, i, ex->ss_stencil);
652792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGraphAssemble, ex->ss_graph);
653f4bdf6c4SBarry Smith 
654f4bdf6c4SBarry Smith   /* create the HYPRE sstruct vectors for rhs and solution */
655792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorCreate, ex->hcomm, ex->ss_grid, &ex->ss_b);
656792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorCreate, ex->hcomm, ex->ss_grid, &ex->ss_x);
657792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorInitialize, ex->ss_b);
658792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorInitialize, ex->ss_x);
659792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorAssemble, ex->ss_b);
660792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorAssemble, ex->ss_x);
661f4bdf6c4SBarry Smith 
662f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
663792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructMatrixCreate, ex->hcomm, ex->ss_graph, &ex->ss_mat);
664792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGridDestroy, ex->ss_grid);
665792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructStencilDestroy, ex->ss_stencil);
666f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
667792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixInitialize, ex->ss_mat);
668f4bdf6c4SBarry Smith     ex->needsinitialization = PETSC_FALSE;
669f4bdf6c4SBarry Smith   }
670f4bdf6c4SBarry Smith 
671f4bdf6c4SBarry Smith   /* set the global and local sizes of the matrix */
6729566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, 0, 0, 0, &nx, &ny, &nz));
6739566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat, dof * nx * ny * nz, dof * nx * ny * nz, PETSC_DECIDE, PETSC_DECIDE));
6749566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->rmap, dof));
6759566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->cmap, dof));
6769566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->rmap));
6779566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->cmap));
67861710fbeSStefano Zampini   mat->preallocated = PETSC_TRUE;
679f4bdf6c4SBarry Smith 
680f4bdf6c4SBarry Smith   if (dim == 3) {
681f4bdf6c4SBarry Smith     mat->ops->setvalueslocal = MatSetValuesLocal_HYPRESStruct_3d;
682f4bdf6c4SBarry Smith     mat->ops->zerorowslocal  = MatZeroRowsLocal_HYPRESStruct_3d;
683f4bdf6c4SBarry Smith     mat->ops->zeroentries    = MatZeroEntries_HYPRESStruct_3d;
6848865f1eaSKarl Rupp 
6859566063dSJacob Faibussowitsch     /* PetscCall(MatZeroEntries_HYPRESStruct_3d(mat)); */
686ce94432eSBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Only support for 3d DMDA currently");
687f4bdf6c4SBarry Smith 
688f4bdf6c4SBarry Smith   /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
6899566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(mat, &ex->rstart, NULL));
6909566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(ex->da, &ltog));
6919566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **)&ex->gindices));
6929566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(ex->da, 0, 0, 0, &ex->gnx, &ex->gnxgny, &ex->gnxgnygnz));
6938865f1eaSKarl Rupp 
694f4bdf6c4SBarry Smith   ex->gnxgny *= ex->gnx;
695f4bdf6c4SBarry Smith   ex->gnxgnygnz *= ex->gnxgny;
6968865f1eaSKarl Rupp 
6979566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da, &ex->xs, &ex->ys, &ex->zs, &ex->nx, &ex->ny, &ex->nz));
6988865f1eaSKarl Rupp 
699f4bdf6c4SBarry Smith   ex->nxny   = ex->nx * ex->ny;
700f4bdf6c4SBarry Smith   ex->nxnynz = ex->nz * ex->nxny;
7013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
702f4bdf6c4SBarry Smith }
703f4bdf6c4SBarry Smith 
704d71ae5a4SJacob Faibussowitsch PetscErrorCode MatMult_HYPRESStruct(Mat A, Vec x, Vec y)
705d71ae5a4SJacob Faibussowitsch {
706b026d285SBarry Smith   const PetscScalar *xx;
707b026d285SBarry Smith   PetscScalar       *yy;
7082cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
7094ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
710f4bdf6c4SBarry Smith   Mat_HYPRESStruct  *mx       = (Mat_HYPRESStruct *)(A->data);
7114ddd07fcSJed Brown   PetscInt           ordering = mx->dofs_order;
7124ddd07fcSJed Brown   PetscInt           nvars    = mx->nvars;
7134ddd07fcSJed Brown   PetscInt           part     = 0;
7144ddd07fcSJed Brown   PetscInt           size;
7154ddd07fcSJed Brown   PetscInt           i;
716f4bdf6c4SBarry Smith 
717f4bdf6c4SBarry Smith   PetscFunctionBegin;
7189566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
7192cf14000SStefano Zampini 
7202cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
721f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
722f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
723f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
7242cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
7252cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
7262cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
7272cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
7282cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
7292cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
730f4bdf6c4SBarry Smith 
731f4bdf6c4SBarry Smith   size = 1;
7328865f1eaSKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i] - ilower[i] + 1);
733f4bdf6c4SBarry Smith 
734f4bdf6c4SBarry Smith   /* copy x values over to hypre for variable ordering */
735f4bdf6c4SBarry Smith   if (ordering) {
736792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
7379566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
73848a46eb9SPierre Jolivet     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(xx + (size * i)));
7399566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
740792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
741792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixMatvec, 1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x);
742f4bdf6c4SBarry Smith 
743f4bdf6c4SBarry Smith     /* copy solution values back to PETSc */
7449566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
74548a46eb9SPierre Jolivet     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(yy + (size * i)));
7469566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
747f4bdf6c4SBarry Smith   } else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */
748f4bdf6c4SBarry Smith     PetscScalar *z;
7494ddd07fcSJed Brown     PetscInt     j, k;
750f4bdf6c4SBarry Smith 
7519566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nvars * size, &z));
752792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0);
7539566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
754f4bdf6c4SBarry Smith 
755f4bdf6c4SBarry Smith     /* transform nodal to hypre's variable ordering for sys_pfmg */
756f4bdf6c4SBarry Smith     for (i = 0; i < size; i++) {
757f4bdf6c4SBarry Smith       k = i * nvars;
7588865f1eaSKarl Rupp       for (j = 0; j < nvars; j++) z[j * size + i] = xx[k + j];
759f4bdf6c4SBarry Smith     }
76048a46eb9SPierre Jolivet     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
7619566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
762792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b);
763792fecdfSBarry Smith     PetscCallExternal(HYPRE_SStructMatrixMatvec, 1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x);
764f4bdf6c4SBarry Smith 
765f4bdf6c4SBarry Smith     /* copy solution values back to PETSc */
7669566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
76748a46eb9SPierre Jolivet     for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i)));
768f4bdf6c4SBarry Smith     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
769f4bdf6c4SBarry Smith     for (i = 0; i < size; i++) {
770f4bdf6c4SBarry Smith       k = i * nvars;
7718865f1eaSKarl Rupp       for (j = 0; j < nvars; j++) yy[k + j] = z[j * size + i];
772f4bdf6c4SBarry Smith     }
7739566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
7749566063dSJacob Faibussowitsch     PetscCall(PetscFree(z));
775f4bdf6c4SBarry Smith   }
7763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
777f4bdf6c4SBarry Smith }
778f4bdf6c4SBarry Smith 
779d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAssemblyEnd_HYPRESStruct(Mat mat, MatAssemblyType mode)
780d71ae5a4SJacob Faibussowitsch {
781f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct *)mat->data;
782f4bdf6c4SBarry Smith 
783f4bdf6c4SBarry Smith   PetscFunctionBegin;
784792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructMatrixAssemble, ex->ss_mat);
7853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
786f4bdf6c4SBarry Smith }
787f4bdf6c4SBarry Smith 
788d71ae5a4SJacob Faibussowitsch PetscErrorCode MatZeroEntries_HYPRESStruct(Mat mat)
789d71ae5a4SJacob Faibussowitsch {
790f4bdf6c4SBarry Smith   PetscFunctionBegin;
791f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
7923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
793f4bdf6c4SBarry Smith }
794f4bdf6c4SBarry Smith 
795d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDestroy_HYPRESStruct(Mat mat)
796d71ae5a4SJacob Faibussowitsch {
797f4bdf6c4SBarry Smith   Mat_HYPRESStruct      *ex = (Mat_HYPRESStruct *)mat->data;
798d94fc0b6SBarry Smith   ISLocalToGlobalMapping ltog;
799f4bdf6c4SBarry Smith 
800f4bdf6c4SBarry Smith   PetscFunctionBegin;
8019566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(ex->da, &ltog));
8029566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreIndices(ltog, (const PetscInt **)&ex->gindices));
803792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructGraphDestroy, ex->ss_graph);
804792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructMatrixDestroy, ex->ss_mat);
805792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorDestroy, ex->ss_x);
806792fecdfSBarry Smith   PetscCallExternal(HYPRE_SStructVectorDestroy, ex->ss_b);
8079566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)ex->da));
8089566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&(ex->hcomm)));
8099566063dSJacob Faibussowitsch   PetscCall(PetscFree(ex));
8103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
811f4bdf6c4SBarry Smith }
812f4bdf6c4SBarry Smith 
813d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_HYPRESStruct(Mat B)
814d71ae5a4SJacob Faibussowitsch {
815f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex;
816f4bdf6c4SBarry Smith 
817f4bdf6c4SBarry Smith   PetscFunctionBegin;
8184dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&ex));
819f4bdf6c4SBarry Smith   B->data      = (void *)ex;
820f4bdf6c4SBarry Smith   B->rmap->bs  = 1;
821f4bdf6c4SBarry Smith   B->assembled = PETSC_FALSE;
822f4bdf6c4SBarry Smith 
823f4bdf6c4SBarry Smith   B->insertmode = NOT_SET_VALUES;
824f4bdf6c4SBarry Smith 
825f4bdf6c4SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_HYPRESStruct;
826f4bdf6c4SBarry Smith   B->ops->mult        = MatMult_HYPRESStruct;
827f4bdf6c4SBarry Smith   B->ops->zeroentries = MatZeroEntries_HYPRESStruct;
828f4bdf6c4SBarry Smith   B->ops->destroy     = MatDestroy_HYPRESStruct;
82959cb773eSBarry Smith   B->ops->setup       = MatSetUp_HYPRESStruct;
830f4bdf6c4SBarry Smith 
831f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
832f4bdf6c4SBarry Smith 
8339566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_dup(PetscObjectComm((PetscObject)B), &(ex->hcomm)));
8349566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRESSTRUCT));
835*ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
8363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
837f4bdf6c4SBarry Smith }
838