xref: /petsc/src/dm/impls/da/hypre/mhyp.c (revision f2f41e485aa34be1ebd571fc6d0409440dab19e0)
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)));
59*f2f41e48SZach Atkins     if (addv == ADD_VALUES) PetscCallHYPRE(HYPRE_StructMatrixAddToValues(ex->hmat, index, (HYPRE_Int)ncol, entries, values));
60*f2f41e48SZach Atkins     else PetscCallHYPRE(HYPRE_StructMatrixSetValues(ex->hmat, index, (HYPRE_Int)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)));
82a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_StructMatrixSetValues(ex->hmat, index, 7, entries, values));
83f4bdf6c4SBarry Smith   }
84a333fa2bSZach Atkins   PetscCallHYPRE(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 */
95a333fa2bSZach Atkins   PetscCallHYPRE(hypre_StructMatrixClearBoxValues(ex->hmat, &ex->hbox, 7, indices, 0, 1));
96a333fa2bSZach Atkins   PetscCallHYPRE(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   }
145*f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_StructGridCreate(ex->hcomm, (HYPRE_Int)dim, &ex->hgrid));
146a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructGridSetExtents(ex->hgrid, hlower, hupper));
147a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructGridSetPeriodic(ex->hgrid, period));
148a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructGridAssemble(ex->hgrid));
149f4bdf6c4SBarry Smith 
150*f2f41e48SZach Atkins   sw[5] = sw[4] = sw[3] = sw[2] = sw[1] = sw[0] = (HYPRE_Int)psw;
151a333fa2bSZach Atkins   PetscCallHYPRE(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;
159*f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_StructStencilCreate((HYPRE_Int)dim, (HYPRE_Int)ssize, &ex->hstencil));
160*f2f41e48SZach Atkins     for (i = 0; i < ssize; i++) PetscCallHYPRE(HYPRE_StructStencilSetElement(ex->hstencil, (HYPRE_Int)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;
170*f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_StructStencilCreate((HYPRE_Int)dim, (HYPRE_Int)ssize, &ex->hstencil));
171*f2f41e48SZach Atkins     for (i = 0; i < ssize; i++) PetscCallHYPRE(HYPRE_StructStencilSetElement(ex->hstencil, (HYPRE_Int)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;
183*f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_StructStencilCreate((HYPRE_Int)dim, (HYPRE_Int)ssize, &ex->hstencil));
184*f2f41e48SZach Atkins     for (i = 0; i < ssize; i++) PetscCallHYPRE(HYPRE_StructStencilSetElement(ex->hstencil, (HYPRE_Int)i, offsets[i]));
185f4bdf6c4SBarry Smith   }
186f4bdf6c4SBarry Smith 
187f4bdf6c4SBarry Smith   /* create the HYPRE vector for rhs and solution */
188a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorCreate(ex->hcomm, ex->hgrid, &ex->hb));
189a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorCreate(ex->hcomm, ex->hgrid, &ex->hx));
190a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorInitialize(ex->hb));
191a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorInitialize(ex->hx));
192a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorAssemble(ex->hb));
193a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorAssemble(ex->hx));
194f4bdf6c4SBarry Smith 
195f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
196a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructMatrixCreate(ex->hcomm, ex->hgrid, ex->hstencil, &ex->hmat));
197a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructGridDestroy(ex->hgrid));
198a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructStencilDestroy(ex->hstencil));
199f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
200a333fa2bSZach Atkins     PetscCallHYPRE(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 
213966bd95aSPierre Jolivet   PetscCheck(dim == 3, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Only support for 3d DMDA currently");
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)); */
219f4bdf6c4SBarry Smith 
220f4bdf6c4SBarry Smith   /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
2219566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(mat, &ex->rstart, NULL));
2229566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(ex->da, &ltog));
2239566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **)&ex->gindices));
2249566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(ex->da, 0, 0, 0, &ex->gnx, &ex->gnxgny, 0));
225f4bdf6c4SBarry Smith   ex->gnxgny *= ex->gnx;
2269566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da, &ex->xs, &ex->ys, &ex->zs, &ex->nx, &ex->ny, 0));
227f4bdf6c4SBarry Smith   ex->nxny = ex->nx * ex->ny;
2283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
229f4bdf6c4SBarry Smith }
230f4bdf6c4SBarry Smith 
23166976f2fSJacob Faibussowitsch static PetscErrorCode MatMult_HYPREStruct(Mat A, Vec x, Vec y)
232d71ae5a4SJacob Faibussowitsch {
233b026d285SBarry Smith   const PetscScalar *xx;
234b026d285SBarry Smith   PetscScalar       *yy;
2354ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
2362cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
237f4f49eeaSPierre Jolivet   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)A->data;
238f4bdf6c4SBarry Smith 
239f4bdf6c4SBarry Smith   PetscFunctionBegin;
2409566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
2412cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
242f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
243f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
244f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
2452cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
2462cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
2472cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
2482cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
2492cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
2502cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
251f4bdf6c4SBarry Smith 
252f4bdf6c4SBarry Smith   /* copy x values over to hypre */
253a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorSetConstantValues(mx->hb, 0.0));
2549566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
255a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorSetBoxValues(mx->hb, hlower, hupper, (HYPRE_Complex *)xx));
2569566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
257a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorAssemble(mx->hb));
258a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructMatrixMatvec(1.0, mx->hmat, mx->hb, 0.0, mx->hx));
259f4bdf6c4SBarry Smith 
260f4bdf6c4SBarry Smith   /* copy solution values back to PETSc */
2619566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
262a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorGetBoxValues(mx->hx, hlower, hupper, (HYPRE_Complex *)yy));
2639566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
2643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
265f4bdf6c4SBarry Smith }
266f4bdf6c4SBarry Smith 
26766976f2fSJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_HYPREStruct(Mat mat, MatAssemblyType mode)
268d71ae5a4SJacob Faibussowitsch {
269f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct *)mat->data;
270f4bdf6c4SBarry Smith 
271f4bdf6c4SBarry Smith   PetscFunctionBegin;
272a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructMatrixAssemble(ex->hmat));
273a333fa2bSZach Atkins   /* PetscCallHYPRE(HYPRE_StructMatrixPrint("dummy",ex->hmat,0)); */
2743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
275f4bdf6c4SBarry Smith }
276f4bdf6c4SBarry Smith 
27766976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPREStruct(Mat mat)
278d71ae5a4SJacob Faibussowitsch {
279f4bdf6c4SBarry Smith   PetscFunctionBegin;
280f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
2813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
282f4bdf6c4SBarry Smith }
283f4bdf6c4SBarry Smith 
28466976f2fSJacob Faibussowitsch static PetscErrorCode MatDestroy_HYPREStruct(Mat mat)
285d71ae5a4SJacob Faibussowitsch {
286f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct *)mat->data;
287f4bdf6c4SBarry Smith 
288f4bdf6c4SBarry Smith   PetscFunctionBegin;
289a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructMatrixDestroy(ex->hmat));
290a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorDestroy(ex->hx));
291a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorDestroy(ex->hb));
2929566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)ex->da));
293f4f49eeaSPierre Jolivet   PetscCallMPI(MPI_Comm_free(&ex->hcomm));
2949566063dSJacob Faibussowitsch   PetscCall(PetscFree(ex));
2953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
296f4bdf6c4SBarry Smith }
297f4bdf6c4SBarry Smith 
298d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_HYPREStruct(Mat B)
299d71ae5a4SJacob Faibussowitsch {
300f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex;
301f4bdf6c4SBarry Smith 
302f4bdf6c4SBarry Smith   PetscFunctionBegin;
3034dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&ex));
304f4bdf6c4SBarry Smith   B->data      = (void *)ex;
305f4bdf6c4SBarry Smith   B->rmap->bs  = 1;
306f4bdf6c4SBarry Smith   B->assembled = PETSC_FALSE;
307f4bdf6c4SBarry Smith 
308f4bdf6c4SBarry Smith   B->insertmode = NOT_SET_VALUES;
309f4bdf6c4SBarry Smith 
310f4bdf6c4SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_HYPREStruct;
311f4bdf6c4SBarry Smith   B->ops->mult        = MatMult_HYPREStruct;
312f4bdf6c4SBarry Smith   B->ops->zeroentries = MatZeroEntries_HYPREStruct;
313f4bdf6c4SBarry Smith   B->ops->destroy     = MatDestroy_HYPREStruct;
31459cb773eSBarry Smith   B->ops->setup       = MatSetUp_HYPREStruct;
315f4bdf6c4SBarry Smith 
316f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
317f4bdf6c4SBarry Smith 
318f4f49eeaSPierre Jolivet   PetscCallMPI(MPI_Comm_dup(PetscObjectComm((PetscObject)B), &ex->hcomm));
3199566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRESTRUCT));
320ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
3213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
322f4bdf6c4SBarry Smith }
323f4bdf6c4SBarry Smith 
324f4bdf6c4SBarry Smith /*MC
325f4bdf6c4SBarry Smith    MATHYPRESSTRUCT - MATHYPRESSTRUCT = "hypresstruct" - A matrix type to be used for parallel sparse matrices
326f4bdf6c4SBarry Smith           based on the hypre HYPRE_SStructMatrix.
327f4bdf6c4SBarry Smith 
328f4bdf6c4SBarry Smith    Level: intermediate
329f4bdf6c4SBarry Smith 
33095452b02SPatrick Sanan    Notes:
33195452b02SPatrick Sanan     Unlike hypre's general semi-struct object consisting of a collection of structured-grid objects and unstructured
332b026d285SBarry Smith           grid objects, we restrict the semi-struct objects to consist of only structured-grid components.
333f4bdf6c4SBarry Smith 
334f4bdf6c4SBarry 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
335dce8aebaSBarry Smith           be defined by a `DMDA`.
336f4bdf6c4SBarry Smith 
33759cb773eSBarry Smith           The matrix needs a DMDA associated with it by either a call to MatSetDM() or if the matrix is obtained from DMCreateMatrix()
338f4bdf6c4SBarry Smith 
339dce8aebaSBarry Smith .seealso: `Mat`
340f4bdf6c4SBarry Smith M*/
341f4bdf6c4SBarry Smith 
34266976f2fSJacob Faibussowitsch static PetscErrorCode MatSetValuesLocal_HYPRESStruct_3d(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
343d71ae5a4SJacob Faibussowitsch {
3442cf14000SStefano Zampini   HYPRE_Int         index[3], *entries;
3452cf14000SStefano Zampini   PetscInt          i, j, stencil;
34639accc25SStefano Zampini   HYPRE_Complex    *values = (HYPRE_Complex *)y;
347f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex     = (Mat_HYPRESStruct *)mat->data;
348f4bdf6c4SBarry Smith 
349*f2f41e48SZach Atkins   HYPRE_Int part = 0; /* PETSc sstruct interface only allows 1 part */
3504ddd07fcSJed Brown   PetscInt  ordering;
3514ddd07fcSJed Brown   PetscInt  grid_rank, to_grid_rank;
3524ddd07fcSJed Brown   PetscInt  var_type, to_var_type;
3534ddd07fcSJed Brown   PetscInt  to_var_entry = 0;
3544ddd07fcSJed Brown   PetscInt  nvars        = ex->nvars;
3552cf14000SStefano Zampini   PetscInt  row;
356f4bdf6c4SBarry Smith 
357f4bdf6c4SBarry Smith   PetscFunctionBegin;
3589566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(7 * nvars, &entries));
359f4bdf6c4SBarry Smith   ordering = ex->dofs_order; /* ordering= 0   nodal ordering
360f4bdf6c4SBarry Smith                                            1   variable ordering */
36161710fbeSStefano Zampini   /* stencil entries are ordered by variables: var0_stencil0, var0_stencil1, ..., var0_stencil6, var1_stencil0, var1_stencil1, ...  */
362f4bdf6c4SBarry Smith   if (!ordering) {
363f4bdf6c4SBarry Smith     for (i = 0; i < nrow; i++) {
364f4bdf6c4SBarry Smith       grid_rank = irow[i] / nvars;
365f4bdf6c4SBarry Smith       var_type  = (irow[i] % nvars);
366f4bdf6c4SBarry Smith 
367f4bdf6c4SBarry Smith       for (j = 0; j < ncol; j++) {
368f4bdf6c4SBarry Smith         to_grid_rank = icol[j] / nvars;
369f4bdf6c4SBarry Smith         to_var_type  = (icol[j] % nvars);
370f4bdf6c4SBarry Smith 
371f4bdf6c4SBarry Smith         to_var_entry = to_var_entry * 7;
372*f2f41e48SZach Atkins         entries[j]   = (HYPRE_Int)to_var_entry;
373f4bdf6c4SBarry Smith 
374f4bdf6c4SBarry Smith         stencil = to_grid_rank - grid_rank;
375f4bdf6c4SBarry Smith         if (!stencil) {
376f4bdf6c4SBarry Smith           entries[j] += 3;
377f4bdf6c4SBarry Smith         } else if (stencil == -1) {
378f4bdf6c4SBarry Smith           entries[j] += 2;
379f4bdf6c4SBarry Smith         } else if (stencil == 1) {
380f4bdf6c4SBarry Smith           entries[j] += 4;
381f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnx) {
382f4bdf6c4SBarry Smith           entries[j] += 1;
383f4bdf6c4SBarry Smith         } else if (stencil == ex->gnx) {
384f4bdf6c4SBarry Smith           entries[j] += 5;
385f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnxgny) {
386f4bdf6c4SBarry Smith           entries[j] += 0;
387f4bdf6c4SBarry Smith         } else if (stencil == ex->gnxgny) {
388f4bdf6c4SBarry Smith           entries[j] += 6;
38963a3b9bcSJacob 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);
390f4bdf6c4SBarry Smith       }
391f4bdf6c4SBarry Smith 
392f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
3932cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
3942cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny));
3952cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny)));
396f4bdf6c4SBarry Smith 
397*f2f41e48SZach Atkins       if (addv == ADD_VALUES) PetscCallHYPRE(HYPRE_SStructMatrixAddToValues(ex->ss_mat, part, index, (HYPRE_Int)var_type, (HYPRE_Int)ncol, entries, values));
398*f2f41e48SZach Atkins       else PetscCallHYPRE(HYPRE_SStructMatrixSetValues(ex->ss_mat, part, index, (HYPRE_Int)var_type, (HYPRE_Int)ncol, entries, values));
399f4bdf6c4SBarry Smith       values += ncol;
400f4bdf6c4SBarry Smith     }
401f4bdf6c4SBarry Smith   } else {
402f4bdf6c4SBarry Smith     for (i = 0; i < nrow; i++) {
403f4bdf6c4SBarry Smith       var_type  = irow[i] / (ex->gnxgnygnz);
404f4bdf6c4SBarry Smith       grid_rank = irow[i] - var_type * (ex->gnxgnygnz);
405f4bdf6c4SBarry Smith 
406f4bdf6c4SBarry Smith       for (j = 0; j < ncol; j++) {
407f4bdf6c4SBarry Smith         to_var_type  = icol[j] / (ex->gnxgnygnz);
408f4bdf6c4SBarry Smith         to_grid_rank = icol[j] - to_var_type * (ex->gnxgnygnz);
409f4bdf6c4SBarry Smith 
410f4bdf6c4SBarry Smith         to_var_entry = to_var_entry * 7;
411*f2f41e48SZach Atkins         entries[j]   = (HYPRE_Int)to_var_entry;
412f4bdf6c4SBarry Smith 
413f4bdf6c4SBarry Smith         stencil = to_grid_rank - grid_rank;
414f4bdf6c4SBarry Smith         if (!stencil) {
415f4bdf6c4SBarry Smith           entries[j] += 3;
416f4bdf6c4SBarry Smith         } else if (stencil == -1) {
417f4bdf6c4SBarry Smith           entries[j] += 2;
418f4bdf6c4SBarry Smith         } else if (stencil == 1) {
419f4bdf6c4SBarry Smith           entries[j] += 4;
420f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnx) {
421f4bdf6c4SBarry Smith           entries[j] += 1;
422f4bdf6c4SBarry Smith         } else if (stencil == ex->gnx) {
423f4bdf6c4SBarry Smith           entries[j] += 5;
424f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnxgny) {
425f4bdf6c4SBarry Smith           entries[j] += 0;
426f4bdf6c4SBarry Smith         } else if (stencil == ex->gnxgny) {
427f4bdf6c4SBarry Smith           entries[j] += 6;
42863a3b9bcSJacob 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);
429f4bdf6c4SBarry Smith       }
430f4bdf6c4SBarry Smith 
431f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
4322cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
4332cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny));
4342cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny)));
435f4bdf6c4SBarry Smith 
436*f2f41e48SZach Atkins       if (addv == ADD_VALUES) PetscCallHYPRE(HYPRE_SStructMatrixAddToValues(ex->ss_mat, part, index, (HYPRE_Int)var_type, (HYPRE_Int)ncol, entries, values));
437*f2f41e48SZach Atkins       else PetscCallHYPRE(HYPRE_SStructMatrixSetValues(ex->ss_mat, part, index, (HYPRE_Int)var_type, (HYPRE_Int)ncol, entries, values));
438f4bdf6c4SBarry Smith       values += ncol;
439f4bdf6c4SBarry Smith     }
440f4bdf6c4SBarry Smith   }
4419566063dSJacob Faibussowitsch   PetscCall(PetscFree(entries));
4423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
443f4bdf6c4SBarry Smith }
444f4bdf6c4SBarry Smith 
44566976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroRowsLocal_HYPRESStruct_3d(Mat mat, PetscInt nrow, const PetscInt irow[], PetscScalar d, Vec x, Vec b)
446d71ae5a4SJacob Faibussowitsch {
4472cf14000SStefano Zampini   HYPRE_Int         index[3], *entries;
4482cf14000SStefano Zampini   PetscInt          i;
44939accc25SStefano Zampini   HYPRE_Complex   **values;
450f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct *)mat->data;
451f4bdf6c4SBarry Smith 
452*f2f41e48SZach Atkins   HYPRE_Int part     = 0; /* PETSc sstruct interface only allows 1 part */
4534ddd07fcSJed Brown   PetscInt  ordering = ex->dofs_order;
4544ddd07fcSJed Brown   PetscInt  grid_rank;
4554ddd07fcSJed Brown   PetscInt  var_type;
4564ddd07fcSJed Brown   PetscInt  nvars = ex->nvars;
4572cf14000SStefano Zampini   PetscInt  row;
458f4bdf6c4SBarry Smith 
459f4bdf6c4SBarry Smith   PetscFunctionBegin;
46008401ef6SPierre Jolivet   PetscCheck(!x || !b, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "No support");
4619566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(7 * nvars, &entries));
462f4bdf6c4SBarry Smith 
4639566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nvars, &values));
4649566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(7 * nvars * nvars, &values[0]));
465ad540459SPierre Jolivet   for (i = 1; i < nvars; i++) values[i] = values[i - 1] + nvars * 7;
466f4bdf6c4SBarry Smith 
467f4bdf6c4SBarry Smith   for (i = 0; i < nvars; i++) {
4689566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(values[i], nvars * 7 * sizeof(HYPRE_Complex)));
4699566063dSJacob Faibussowitsch     PetscCall(PetscHYPREScalarCast(d, values[i] + 3));
470f4bdf6c4SBarry Smith   }
471f4bdf6c4SBarry Smith 
472*f2f41e48SZach Atkins   for (i = 0; i < nvars * 7; i++) entries[i] = (HYPRE_Int)i;
473f4bdf6c4SBarry Smith 
474f4bdf6c4SBarry Smith   if (!ordering) {
475f4bdf6c4SBarry Smith     for (i = 0; i < nrow; i++) {
476f4bdf6c4SBarry Smith       grid_rank = irow[i] / nvars;
477f4bdf6c4SBarry Smith       var_type  = (irow[i] % nvars);
478f4bdf6c4SBarry Smith 
479f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
4802cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
4812cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny));
4822cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny)));
483*f2f41e48SZach Atkins       PetscCallHYPRE(HYPRE_SStructMatrixSetValues(ex->ss_mat, part, index, (HYPRE_Int)var_type, 7 * (HYPRE_Int)nvars, entries, values[var_type]));
484f4bdf6c4SBarry Smith     }
485f4bdf6c4SBarry Smith   } else {
486f4bdf6c4SBarry Smith     for (i = 0; i < nrow; i++) {
487f4bdf6c4SBarry Smith       var_type  = irow[i] / (ex->gnxgnygnz);
488f4bdf6c4SBarry Smith       grid_rank = irow[i] - var_type * (ex->gnxgnygnz);
489f4bdf6c4SBarry Smith 
490f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
4912cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
4922cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny));
4932cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny)));
494*f2f41e48SZach Atkins       PetscCallHYPRE(HYPRE_SStructMatrixSetValues(ex->ss_mat, part, index, (HYPRE_Int)var_type, 7 * (HYPRE_Int)nvars, entries, values[var_type]));
495f4bdf6c4SBarry Smith     }
496f4bdf6c4SBarry Smith   }
497a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructMatrixAssemble(ex->ss_mat));
4989566063dSJacob Faibussowitsch   PetscCall(PetscFree(values[0]));
4999566063dSJacob Faibussowitsch   PetscCall(PetscFree(values));
5009566063dSJacob Faibussowitsch   PetscCall(PetscFree(entries));
5013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
502f4bdf6c4SBarry Smith }
503f4bdf6c4SBarry Smith 
50466976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPRESStruct_3d(Mat mat)
505d71ae5a4SJacob Faibussowitsch {
506f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex    = (Mat_HYPRESStruct *)mat->data;
5074ddd07fcSJed Brown   PetscInt          nvars = ex->nvars;
5084ddd07fcSJed Brown   PetscInt          size;
509*f2f41e48SZach Atkins   HYPRE_Int         part = 0; /* only one part */
510f4bdf6c4SBarry Smith 
511f4bdf6c4SBarry Smith   PetscFunctionBegin;
5124ad8454bSPierre 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);
513f4bdf6c4SBarry Smith   {
5142cf14000SStefano Zampini     HYPRE_Int      i, *entries, iupper[3], ilower[3];
51539accc25SStefano Zampini     HYPRE_Complex *values;
5164ddd07fcSJed Brown 
517f4bdf6c4SBarry Smith     for (i = 0; i < 3; i++) {
518*f2f41e48SZach Atkins       ilower[i] = (HYPRE_Int)ex->hbox.imin[i];
519*f2f41e48SZach Atkins       iupper[i] = (HYPRE_Int)ex->hbox.imax[i];
520f4bdf6c4SBarry Smith     }
521f4bdf6c4SBarry Smith 
5229566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nvars * 7, &entries, nvars * 7 * size, &values));
5238865f1eaSKarl Rupp     for (i = 0; i < nvars * 7; i++) entries[i] = i;
5249566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(values, nvars * 7 * size));
525f4bdf6c4SBarry Smith 
526*f2f41e48SZach Atkins     for (i = 0; i < nvars; i++) PetscCallHYPRE(HYPRE_SStructMatrixSetBoxValues(ex->ss_mat, part, ilower, iupper, (HYPRE_Int)i, (HYPRE_Int)nvars * 7, entries, values));
5279566063dSJacob Faibussowitsch     PetscCall(PetscFree2(entries, values));
528f4bdf6c4SBarry Smith   }
529a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructMatrixAssemble(ex->ss_mat));
5303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
531f4bdf6c4SBarry Smith }
532f4bdf6c4SBarry Smith 
533d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetUp_HYPRESStruct(Mat mat)
534d71ae5a4SJacob Faibussowitsch {
535f4bdf6c4SBarry Smith   Mat_HYPRESStruct      *ex = (Mat_HYPRESStruct *)mat->data;
536f4bdf6c4SBarry Smith   PetscInt               dim, dof, sw[3], nx, ny, nz;
5374ddd07fcSJed Brown   PetscInt               ilower[3], iupper[3], ssize, i;
538bff4a2f0SMatthew G. Knepley   DMBoundaryType         px, py, pz;
539f4bdf6c4SBarry Smith   DMDAStencilType        st;
5404ddd07fcSJed Brown   PetscInt               nparts = 1; /* assuming only one part */
541*f2f41e48SZach Atkins   HYPRE_Int              part   = 0;
542565245c5SBarry Smith   ISLocalToGlobalMapping ltog;
54359cb773eSBarry Smith   DM                     da;
544b026d285SBarry Smith 
545f4bdf6c4SBarry Smith   PetscFunctionBegin;
5469566063dSJacob Faibussowitsch   PetscCall(MatGetDM(mat, (DM *)&da));
547f4bdf6c4SBarry Smith   ex->da = da;
5489566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)da));
549f4bdf6c4SBarry Smith 
5509566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(ex->da, &dim, 0, 0, 0, 0, 0, 0, &dof, &sw[0], &px, &py, &pz, &st));
5519566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
552f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
553f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
554f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
555f4bdf6c4SBarry Smith   /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
556*f2f41e48SZach Atkins   ex->hbox.imin[0] = (HYPRE_Int)ilower[0];
557*f2f41e48SZach Atkins   ex->hbox.imin[1] = (HYPRE_Int)ilower[1];
558*f2f41e48SZach Atkins   ex->hbox.imin[2] = (HYPRE_Int)ilower[2];
559*f2f41e48SZach Atkins   ex->hbox.imax[0] = (HYPRE_Int)iupper[0];
560*f2f41e48SZach Atkins   ex->hbox.imax[1] = (HYPRE_Int)iupper[1];
561*f2f41e48SZach Atkins   ex->hbox.imax[2] = (HYPRE_Int)iupper[2];
562f4bdf6c4SBarry Smith 
563f4bdf6c4SBarry Smith   ex->dofs_order = 0;
564f4bdf6c4SBarry Smith 
565f4bdf6c4SBarry Smith   /* assuming that the same number of dofs on each gridpoint. Also assume all cell-centred based */
5669ad2cedaSPierre Jolivet   ex->nvars = (int)dof;
567f4bdf6c4SBarry Smith 
568f4bdf6c4SBarry Smith   /* create the hypre grid object and set its information */
5691dca8a05SBarry Smith   PetscCheck(!px && !py && !pz, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add periodic support by calling HYPRE_SStructGridSetPeriodic()");
570*f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_SStructGridCreate(ex->hcomm, (HYPRE_Int)dim, (HYPRE_Int)nparts, &ex->ss_grid));
571a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructGridSetExtents(ex->ss_grid, part, ex->hbox.imin, ex->hbox.imax));
572f4bdf6c4SBarry Smith   {
573f4bdf6c4SBarry Smith     HYPRE_SStructVariable *vartypes;
5749566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(ex->nvars, &vartypes));
5758865f1eaSKarl Rupp     for (i = 0; i < ex->nvars; i++) vartypes[i] = HYPRE_SSTRUCT_VARIABLE_CELL;
576*f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_SStructGridSetVariables(ex->ss_grid, part, (HYPRE_Int)ex->nvars, vartypes));
5779566063dSJacob Faibussowitsch     PetscCall(PetscFree(vartypes));
578f4bdf6c4SBarry Smith   }
579a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructGridAssemble(ex->ss_grid));
580f4bdf6c4SBarry Smith 
581f4bdf6c4SBarry Smith   sw[1] = sw[0];
582f4bdf6c4SBarry Smith   sw[2] = sw[1];
583a333fa2bSZach Atkins   /* PetscCallHYPRE(HYPRE_SStructGridSetNumGhost(ex->ss_grid,sw)); */
584f4bdf6c4SBarry Smith 
585f4bdf6c4SBarry Smith   /* create the hypre stencil object and set its information */
58608401ef6SPierre Jolivet   PetscCheck(sw[0] <= 1, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add support for wider stencils");
58708401ef6SPierre Jolivet   PetscCheck(st != DMDA_STENCIL_BOX, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add support for box stencils");
588f4bdf6c4SBarry Smith 
589f4bdf6c4SBarry Smith   if (dim == 1) {
5902cf14000SStefano Zampini     HYPRE_Int offsets[3][1] = {{-1}, {0}, {1}};
5914ddd07fcSJed Brown     PetscInt  j, cnt;
592f4bdf6c4SBarry Smith 
593f4bdf6c4SBarry Smith     ssize = 3 * (ex->nvars);
594*f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_SStructStencilCreate((HYPRE_Int)dim, (HYPRE_Int)ssize, &ex->ss_stencil));
595f4bdf6c4SBarry Smith     cnt = 0;
596f4bdf6c4SBarry Smith     for (i = 0; i < (ex->nvars); i++) {
597f4bdf6c4SBarry Smith       for (j = 0; j < 3; j++) {
598*f2f41e48SZach Atkins         PetscCallHYPRE(HYPRE_SStructStencilSetEntry(ex->ss_stencil, (HYPRE_Int)cnt, offsets[j], (HYPRE_Int)i));
599f4bdf6c4SBarry Smith         cnt++;
600f4bdf6c4SBarry Smith       }
601f4bdf6c4SBarry Smith     }
602f4bdf6c4SBarry Smith   } else if (dim == 2) {
6039371c9d4SSatish Balay     HYPRE_Int offsets[5][2] = {
6049371c9d4SSatish Balay       {0,  -1},
6059371c9d4SSatish Balay       {-1, 0 },
6069371c9d4SSatish Balay       {0,  0 },
6079371c9d4SSatish Balay       {1,  0 },
6089371c9d4SSatish Balay       {0,  1 }
6099371c9d4SSatish Balay     };
6104ddd07fcSJed Brown     PetscInt j, cnt;
611f4bdf6c4SBarry Smith 
612f4bdf6c4SBarry Smith     ssize = 5 * (ex->nvars);
613*f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_SStructStencilCreate((HYPRE_Int)dim, (HYPRE_Int)ssize, &ex->ss_stencil));
614f4bdf6c4SBarry Smith     cnt = 0;
615f4bdf6c4SBarry Smith     for (i = 0; i < (ex->nvars); i++) {
616f4bdf6c4SBarry Smith       for (j = 0; j < 5; j++) {
617*f2f41e48SZach Atkins         PetscCallHYPRE(HYPRE_SStructStencilSetEntry(ex->ss_stencil, (HYPRE_Int)cnt, offsets[j], (HYPRE_Int)i));
618f4bdf6c4SBarry Smith         cnt++;
619f4bdf6c4SBarry Smith       }
620f4bdf6c4SBarry Smith     }
621f4bdf6c4SBarry Smith   } else if (dim == 3) {
6229371c9d4SSatish Balay     HYPRE_Int offsets[7][3] = {
6239371c9d4SSatish Balay       {0,  0,  -1},
6249371c9d4SSatish Balay       {0,  -1, 0 },
6259371c9d4SSatish Balay       {-1, 0,  0 },
6269371c9d4SSatish Balay       {0,  0,  0 },
6279371c9d4SSatish Balay       {1,  0,  0 },
6289371c9d4SSatish Balay       {0,  1,  0 },
6299371c9d4SSatish Balay       {0,  0,  1 }
6309371c9d4SSatish Balay     };
6314ddd07fcSJed Brown     PetscInt j, cnt;
632f4bdf6c4SBarry Smith 
633f4bdf6c4SBarry Smith     ssize = 7 * (ex->nvars);
634*f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_SStructStencilCreate((HYPRE_Int)dim, (HYPRE_Int)ssize, &ex->ss_stencil));
635f4bdf6c4SBarry Smith     cnt = 0;
636f4bdf6c4SBarry Smith     for (i = 0; i < (ex->nvars); i++) {
637f4bdf6c4SBarry Smith       for (j = 0; j < 7; j++) {
638*f2f41e48SZach Atkins         PetscCallHYPRE(HYPRE_SStructStencilSetEntry(ex->ss_stencil, (HYPRE_Int)cnt, offsets[j], (HYPRE_Int)i));
639f4bdf6c4SBarry Smith         cnt++;
640f4bdf6c4SBarry Smith       }
641f4bdf6c4SBarry Smith     }
642f4bdf6c4SBarry Smith   }
643f4bdf6c4SBarry Smith 
644f4bdf6c4SBarry Smith   /* create the HYPRE graph */
645a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructGraphCreate(ex->hcomm, ex->ss_grid, &ex->ss_graph));
646f4bdf6c4SBarry Smith 
647f4bdf6c4SBarry Smith   /* set the stencil graph. Note that each variable has the same graph. This means that each
648f4bdf6c4SBarry Smith      variable couples to all the other variable and with the same stencil pattern. */
649*f2f41e48SZach Atkins   for (i = 0; i < (ex->nvars); i++) PetscCallHYPRE(HYPRE_SStructGraphSetStencil(ex->ss_graph, part, (HYPRE_Int)i, ex->ss_stencil));
650a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructGraphAssemble(ex->ss_graph));
651f4bdf6c4SBarry Smith 
652f4bdf6c4SBarry Smith   /* create the HYPRE sstruct vectors for rhs and solution */
653a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructVectorCreate(ex->hcomm, ex->ss_grid, &ex->ss_b));
654a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructVectorCreate(ex->hcomm, ex->ss_grid, &ex->ss_x));
655a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructVectorInitialize(ex->ss_b));
656a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructVectorInitialize(ex->ss_x));
657a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructVectorAssemble(ex->ss_b));
658a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructVectorAssemble(ex->ss_x));
659f4bdf6c4SBarry Smith 
660f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
661a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructMatrixCreate(ex->hcomm, ex->ss_graph, &ex->ss_mat));
662a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructGridDestroy(ex->ss_grid));
663a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructStencilDestroy(ex->ss_stencil));
664f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
665a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_SStructMatrixInitialize(ex->ss_mat));
666f4bdf6c4SBarry Smith     ex->needsinitialization = PETSC_FALSE;
667f4bdf6c4SBarry Smith   }
668f4bdf6c4SBarry Smith 
669f4bdf6c4SBarry Smith   /* set the global and local sizes of the matrix */
6709566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, 0, 0, 0, &nx, &ny, &nz));
6719566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat, dof * nx * ny * nz, dof * nx * ny * nz, PETSC_DECIDE, PETSC_DECIDE));
6729566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->rmap, dof));
6739566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->cmap, dof));
6749566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->rmap));
6759566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->cmap));
67661710fbeSStefano Zampini   mat->preallocated = PETSC_TRUE;
677f4bdf6c4SBarry Smith 
678966bd95aSPierre Jolivet   PetscCheck(dim == 3, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Only support for 3d DMDA currently");
679f4bdf6c4SBarry Smith   mat->ops->setvalueslocal = MatSetValuesLocal_HYPRESStruct_3d;
680f4bdf6c4SBarry Smith   mat->ops->zerorowslocal  = MatZeroRowsLocal_HYPRESStruct_3d;
681f4bdf6c4SBarry Smith   mat->ops->zeroentries    = MatZeroEntries_HYPRESStruct_3d;
6828865f1eaSKarl Rupp 
6839566063dSJacob Faibussowitsch   /* PetscCall(MatZeroEntries_HYPRESStruct_3d(mat)); */
684f4bdf6c4SBarry Smith 
685f4bdf6c4SBarry Smith   /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
6869566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(mat, &ex->rstart, NULL));
6879566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(ex->da, &ltog));
6889566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **)&ex->gindices));
6899566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(ex->da, 0, 0, 0, &ex->gnx, &ex->gnxgny, &ex->gnxgnygnz));
6908865f1eaSKarl Rupp 
691f4bdf6c4SBarry Smith   ex->gnxgny *= ex->gnx;
692f4bdf6c4SBarry Smith   ex->gnxgnygnz *= ex->gnxgny;
6938865f1eaSKarl Rupp 
6949566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da, &ex->xs, &ex->ys, &ex->zs, &ex->nx, &ex->ny, &ex->nz));
6958865f1eaSKarl Rupp 
696f4bdf6c4SBarry Smith   ex->nxny   = ex->nx * ex->ny;
697f4bdf6c4SBarry Smith   ex->nxnynz = ex->nz * ex->nxny;
6983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
699f4bdf6c4SBarry Smith }
700f4bdf6c4SBarry Smith 
70166976f2fSJacob Faibussowitsch static PetscErrorCode MatMult_HYPRESStruct(Mat A, Vec x, Vec y)
702d71ae5a4SJacob Faibussowitsch {
703b026d285SBarry Smith   const PetscScalar *xx;
704b026d285SBarry Smith   PetscScalar       *yy;
7052cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
7064ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
707f4f49eeaSPierre Jolivet   Mat_HYPRESStruct  *mx       = (Mat_HYPRESStruct *)A->data;
7084ddd07fcSJed Brown   PetscInt           ordering = mx->dofs_order;
7094ddd07fcSJed Brown   PetscInt           nvars    = mx->nvars;
710*f2f41e48SZach Atkins   HYPRE_Int          part     = 0;
7114ddd07fcSJed Brown   PetscInt           size;
7124ddd07fcSJed Brown   PetscInt           i;
713f4bdf6c4SBarry Smith 
714f4bdf6c4SBarry Smith   PetscFunctionBegin;
7159566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
7162cf14000SStefano Zampini 
7172cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
718f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
719f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
720f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
7212cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
7222cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
7232cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
7242cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
7252cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
7262cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
727f4bdf6c4SBarry Smith 
728f4bdf6c4SBarry Smith   size = 1;
7298865f1eaSKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i] - ilower[i] + 1);
730f4bdf6c4SBarry Smith 
731f4bdf6c4SBarry Smith   /* copy x values over to hypre for variable ordering */
732f4bdf6c4SBarry Smith   if (ordering) {
733a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_SStructVectorSetConstantValues(mx->ss_b, 0.0));
7349566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
735*f2f41e48SZach Atkins     for (i = 0; i < nvars; i++) PetscCallHYPRE(HYPRE_SStructVectorSetBoxValues(mx->ss_b, part, hlower, hupper, (HYPRE_Int)i, (HYPRE_Complex *)(xx + (size * i))));
7369566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
737a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_SStructVectorAssemble(mx->ss_b));
738a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_SStructMatrixMatvec(1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x));
739f4bdf6c4SBarry Smith 
740f4bdf6c4SBarry Smith     /* copy solution values back to PETSc */
7419566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
742*f2f41e48SZach Atkins     for (i = 0; i < nvars; i++) PetscCallHYPRE(HYPRE_SStructVectorGetBoxValues(mx->ss_x, part, hlower, hupper, (HYPRE_Int)i, (HYPRE_Complex *)(yy + (size * i))));
7439566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
744f4bdf6c4SBarry Smith   } else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */
745f4bdf6c4SBarry Smith     PetscScalar *z;
7464ddd07fcSJed Brown     PetscInt     j, k;
747f4bdf6c4SBarry Smith 
7489566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nvars * size, &z));
749a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_SStructVectorSetConstantValues(mx->ss_b, 0.0));
7509566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
751f4bdf6c4SBarry Smith 
752f4bdf6c4SBarry Smith     /* transform nodal to hypre's variable ordering for sys_pfmg */
753f4bdf6c4SBarry Smith     for (i = 0; i < size; i++) {
754f4bdf6c4SBarry Smith       k = i * nvars;
7558865f1eaSKarl Rupp       for (j = 0; j < nvars; j++) z[j * size + i] = xx[k + j];
756f4bdf6c4SBarry Smith     }
757*f2f41e48SZach Atkins     for (i = 0; i < nvars; i++) PetscCallHYPRE(HYPRE_SStructVectorSetBoxValues(mx->ss_b, part, hlower, hupper, (HYPRE_Int)i, (HYPRE_Complex *)(z + (size * i))));
7589566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
759a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_SStructVectorAssemble(mx->ss_b));
760a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_SStructMatrixMatvec(1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x));
761f4bdf6c4SBarry Smith 
762f4bdf6c4SBarry Smith     /* copy solution values back to PETSc */
7639566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
764*f2f41e48SZach Atkins     for (i = 0; i < nvars; i++) PetscCallHYPRE(HYPRE_SStructVectorGetBoxValues(mx->ss_x, part, hlower, hupper, (HYPRE_Int)i, (HYPRE_Complex *)(z + (size * i))));
765f4bdf6c4SBarry Smith     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
766f4bdf6c4SBarry Smith     for (i = 0; i < size; i++) {
767f4bdf6c4SBarry Smith       k = i * nvars;
7688865f1eaSKarl Rupp       for (j = 0; j < nvars; j++) yy[k + j] = z[j * size + i];
769f4bdf6c4SBarry Smith     }
7709566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
7719566063dSJacob Faibussowitsch     PetscCall(PetscFree(z));
772f4bdf6c4SBarry Smith   }
7733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
774f4bdf6c4SBarry Smith }
775f4bdf6c4SBarry Smith 
77666976f2fSJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_HYPRESStruct(Mat mat, MatAssemblyType mode)
777d71ae5a4SJacob Faibussowitsch {
778f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct *)mat->data;
779f4bdf6c4SBarry Smith 
780f4bdf6c4SBarry Smith   PetscFunctionBegin;
781a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructMatrixAssemble(ex->ss_mat));
7823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
783f4bdf6c4SBarry Smith }
784f4bdf6c4SBarry Smith 
78566976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPRESStruct(Mat mat)
786d71ae5a4SJacob Faibussowitsch {
787f4bdf6c4SBarry Smith   PetscFunctionBegin;
788f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
7893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
790f4bdf6c4SBarry Smith }
791f4bdf6c4SBarry Smith 
79266976f2fSJacob Faibussowitsch static PetscErrorCode MatDestroy_HYPRESStruct(Mat mat)
793d71ae5a4SJacob Faibussowitsch {
794f4bdf6c4SBarry Smith   Mat_HYPRESStruct      *ex = (Mat_HYPRESStruct *)mat->data;
795d94fc0b6SBarry Smith   ISLocalToGlobalMapping ltog;
796f4bdf6c4SBarry Smith 
797f4bdf6c4SBarry Smith   PetscFunctionBegin;
7989566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(ex->da, &ltog));
7999566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreIndices(ltog, (const PetscInt **)&ex->gindices));
800a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructGraphDestroy(ex->ss_graph));
801a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructMatrixDestroy(ex->ss_mat));
802a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructVectorDestroy(ex->ss_x));
803a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructVectorDestroy(ex->ss_b));
8049566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)ex->da));
805f4f49eeaSPierre Jolivet   PetscCallMPI(MPI_Comm_free(&ex->hcomm));
8069566063dSJacob Faibussowitsch   PetscCall(PetscFree(ex));
8073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
808f4bdf6c4SBarry Smith }
809f4bdf6c4SBarry Smith 
810d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_HYPRESStruct(Mat B)
811d71ae5a4SJacob Faibussowitsch {
812f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex;
813f4bdf6c4SBarry Smith 
814f4bdf6c4SBarry Smith   PetscFunctionBegin;
8154dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&ex));
816f4bdf6c4SBarry Smith   B->data      = (void *)ex;
817f4bdf6c4SBarry Smith   B->rmap->bs  = 1;
818f4bdf6c4SBarry Smith   B->assembled = PETSC_FALSE;
819f4bdf6c4SBarry Smith 
820f4bdf6c4SBarry Smith   B->insertmode = NOT_SET_VALUES;
821f4bdf6c4SBarry Smith 
822f4bdf6c4SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_HYPRESStruct;
823f4bdf6c4SBarry Smith   B->ops->mult        = MatMult_HYPRESStruct;
824f4bdf6c4SBarry Smith   B->ops->zeroentries = MatZeroEntries_HYPRESStruct;
825f4bdf6c4SBarry Smith   B->ops->destroy     = MatDestroy_HYPRESStruct;
82659cb773eSBarry Smith   B->ops->setup       = MatSetUp_HYPRESStruct;
827f4bdf6c4SBarry Smith 
828f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
829f4bdf6c4SBarry Smith 
830f4f49eeaSPierre Jolivet   PetscCallMPI(MPI_Comm_dup(PetscObjectComm((PetscObject)B), &ex->hcomm));
8319566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRESSTRUCT));
832ea9ee2c1SPierre Jolivet   PetscHYPREInitialize();
8333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
834f4bdf6c4SBarry Smith }
835