xref: /petsc/src/dm/impls/da/hypre/mhyp.c (revision 47c84c5acc69ca2c78267fc7dfb4d7203bd055c8)
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 /*MC
11f4bdf6c4SBarry Smith    MATHYPRESTRUCT - MATHYPRESTRUCT = "hyprestruct" - A matrix type to be used for parallel sparse matrices
12f4bdf6c4SBarry Smith           based on the hypre HYPRE_StructMatrix.
13f4bdf6c4SBarry Smith 
14f4bdf6c4SBarry Smith    Level: intermediate
15f4bdf6c4SBarry Smith 
1695452b02SPatrick Sanan    Notes:
1795452b02SPatrick Sanan     Unlike the more general support for blocks in hypre this allows only one block per process and requires the block
18dce8aebaSBarry Smith           be defined by a `DMDA`.
19f4bdf6c4SBarry Smith 
20dce8aebaSBarry Smith           The matrix needs a `DMDA` associated with it by either a call to `MatSetDM()` or if the matrix is obtained from `DMCreateMatrix()`
21f4bdf6c4SBarry Smith 
22db781477SPatrick Sanan .seealso: `MatCreate()`, `PCPFMG`, `MatSetDM()`, `DMCreateMatrix()`
23f4bdf6c4SBarry Smith M*/
24f4bdf6c4SBarry Smith 
MatSetValuesLocal_HYPREStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)2566976f2fSJacob Faibussowitsch static PetscErrorCode MatSetValuesLocal_HYPREStruct_3d(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
26d71ae5a4SJacob Faibussowitsch {
2776a007c6Sftrigaux   HYPRE_Int        index[3], entries[9];
282cf14000SStefano Zampini   PetscInt         i, j, stencil, row;
2939accc25SStefano Zampini   HYPRE_Complex   *values = (HYPRE_Complex *)y;
30f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex     = (Mat_HYPREStruct *)mat->data;
31f4bdf6c4SBarry Smith 
32f4bdf6c4SBarry Smith   PetscFunctionBegin;
3376a007c6Sftrigaux   PetscCheck(ncol <= 9, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "ncol %" PetscInt_FMT " > 9 too large", ncol);
34f4bdf6c4SBarry Smith   for (i = 0; i < nrow; i++) {
35f4bdf6c4SBarry Smith     for (j = 0; j < ncol; j++) {
36f4bdf6c4SBarry Smith       stencil = icol[j] - irow[i];
37f4bdf6c4SBarry Smith       if (!stencil) {
38f4bdf6c4SBarry Smith         entries[j] = 3;
39f4bdf6c4SBarry Smith       } else if (stencil == -1) {
40f4bdf6c4SBarry Smith         entries[j] = 2;
41f4bdf6c4SBarry Smith       } else if (stencil == 1) {
42f4bdf6c4SBarry Smith         entries[j] = 4;
43f4bdf6c4SBarry Smith       } else if (stencil == -ex->gnx) {
44f4bdf6c4SBarry Smith         entries[j] = 1;
45f4bdf6c4SBarry Smith       } else if (stencil == ex->gnx) {
46f4bdf6c4SBarry Smith         entries[j] = 5;
47f4bdf6c4SBarry Smith       } else if (stencil == -ex->gnxgny) {
48f4bdf6c4SBarry Smith         entries[j] = 0;
49f4bdf6c4SBarry Smith       } else if (stencil == ex->gnxgny) {
50f4bdf6c4SBarry Smith         entries[j] = 6;
5163a3b9bcSJacob 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);
52f4bdf6c4SBarry Smith     }
53f4bdf6c4SBarry Smith     row      = ex->gindices[irow[i]] - ex->rstart;
542cf14000SStefano Zampini     index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
552cf14000SStefano Zampini     index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny));
562cf14000SStefano Zampini     index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny)));
57f2f41e48SZach Atkins     if (addv == ADD_VALUES) PetscCallHYPRE(HYPRE_StructMatrixAddToValues(ex->hmat, index, (HYPRE_Int)ncol, entries, values));
58f2f41e48SZach Atkins     else PetscCallHYPRE(HYPRE_StructMatrixSetValues(ex->hmat, index, (HYPRE_Int)ncol, entries, values));
59f4bdf6c4SBarry Smith     values += ncol;
60f4bdf6c4SBarry Smith   }
613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
62f4bdf6c4SBarry Smith }
63f4bdf6c4SBarry Smith 
MatZeroRowsLocal_HYPREStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscScalar d,Vec x,Vec b)6466976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroRowsLocal_HYPREStruct_3d(Mat mat, PetscInt nrow, const PetscInt irow[], PetscScalar d, Vec x, Vec b)
65d71ae5a4SJacob Faibussowitsch {
662cf14000SStefano Zampini   HYPRE_Int        index[3], entries[7] = {0, 1, 2, 3, 4, 5, 6};
672cf14000SStefano Zampini   PetscInt         row, i;
6839accc25SStefano Zampini   HYPRE_Complex    values[7];
69f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct *)mat->data;
70f4bdf6c4SBarry Smith 
71f4bdf6c4SBarry Smith   PetscFunctionBegin;
7208401ef6SPierre Jolivet   PetscCheck(!x || !b, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "No support");
739566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(values, 7));
749566063dSJacob Faibussowitsch   PetscCall(PetscHYPREScalarCast(d, &values[3]));
75f4bdf6c4SBarry Smith   for (i = 0; i < nrow; i++) {
76f4bdf6c4SBarry Smith     row      = ex->gindices[irow[i]] - ex->rstart;
772cf14000SStefano Zampini     index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
782cf14000SStefano Zampini     index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny));
792cf14000SStefano Zampini     index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny)));
80a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_StructMatrixSetValues(ex->hmat, index, 7, entries, values));
81f4bdf6c4SBarry Smith   }
82a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructMatrixAssemble(ex->hmat));
833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
84f4bdf6c4SBarry Smith }
85f4bdf6c4SBarry Smith 
MatZeroEntries_HYPREStruct_3d(Mat mat)8666976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPREStruct_3d(Mat mat)
87d71ae5a4SJacob Faibussowitsch {
882cf14000SStefano Zampini   HYPRE_Int        indices[7] = {0, 1, 2, 3, 4, 5, 6};
89f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex         = (Mat_HYPREStruct *)mat->data;
90f4bdf6c4SBarry Smith 
91f4bdf6c4SBarry Smith   PetscFunctionBegin;
92f4bdf6c4SBarry Smith   /* hypre has no public interface to do this */
93a333fa2bSZach Atkins   PetscCallHYPRE(hypre_StructMatrixClearBoxValues(ex->hmat, &ex->hbox, 7, indices, 0, 1));
94a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructMatrixAssemble(ex->hmat));
953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
96f4bdf6c4SBarry Smith }
97f4bdf6c4SBarry Smith 
MatSetUp_HYPREStruct(Mat mat)98d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetUp_HYPREStruct(Mat mat)
99d71ae5a4SJacob Faibussowitsch {
100f4bdf6c4SBarry Smith   Mat_HYPREStruct       *ex = (Mat_HYPREStruct *)mat->data;
1012cf14000SStefano Zampini   HYPRE_Int              sw[6];
102e33d7e95Sftrigaux   HYPRE_Int              hlower[3], hupper[3], period[3] = {0, 0, 0};
103e33d7e95Sftrigaux   PetscInt               dim, dof, psw, Nx, Ny, Nz, nx, ny, nz, ilower[3], iupper[3], ssize, i;
104bff4a2f0SMatthew G. Knepley   DMBoundaryType         px, py, pz;
105f4bdf6c4SBarry Smith   DMDAStencilType        st;
106565245c5SBarry Smith   ISLocalToGlobalMapping ltog;
10759cb773eSBarry Smith   DM                     da;
108f4bdf6c4SBarry Smith 
109f4bdf6c4SBarry Smith   PetscFunctionBegin;
1109566063dSJacob Faibussowitsch   PetscCall(MatGetDM(mat, (DM *)&da));
111f4bdf6c4SBarry Smith   ex->da = da;
1129566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)da));
113f4bdf6c4SBarry Smith 
114e33d7e95Sftrigaux   PetscCall(DMDAGetInfo(ex->da, &dim, &Nx, &Ny, &Nz, 0, 0, 0, &dof, &psw, &px, &py, &pz, &st));
1159566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
1162cf14000SStefano Zampini 
1172cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
118f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
119f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
120f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
1212cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
1222cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
1232cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
1242cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
1252cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
1262cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
127f4bdf6c4SBarry Smith 
128f4bdf6c4SBarry Smith   /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
1292cf14000SStefano Zampini   ex->hbox.imin[0] = hlower[0];
1302cf14000SStefano Zampini   ex->hbox.imin[1] = hlower[1];
1312cf14000SStefano Zampini   ex->hbox.imin[2] = hlower[2];
1322cf14000SStefano Zampini   ex->hbox.imax[0] = hupper[0];
1332cf14000SStefano Zampini   ex->hbox.imax[1] = hupper[1];
1342cf14000SStefano Zampini   ex->hbox.imax[2] = hupper[2];
135f4bdf6c4SBarry Smith 
136f4bdf6c4SBarry Smith   /* create the hypre grid object and set its information */
13708401ef6SPierre Jolivet   PetscCheck(dof <= 1, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Currently only support for scalar problems");
138e33d7e95Sftrigaux   if (px || py || pz) {
139e33d7e95Sftrigaux     if (px == DM_BOUNDARY_PERIODIC) period[0] = (HYPRE_Int)Nx;
140e33d7e95Sftrigaux     if (py == DM_BOUNDARY_PERIODIC) period[1] = (HYPRE_Int)Ny;
141e33d7e95Sftrigaux     if (pz == DM_BOUNDARY_PERIODIC) period[2] = (HYPRE_Int)Nz;
142e33d7e95Sftrigaux   }
143f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_StructGridCreate(ex->hcomm, (HYPRE_Int)dim, &ex->hgrid));
144a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructGridSetExtents(ex->hgrid, hlower, hupper));
145a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructGridSetPeriodic(ex->hgrid, period));
146a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructGridAssemble(ex->hgrid));
147f4bdf6c4SBarry Smith 
148f2f41e48SZach Atkins   sw[5] = sw[4] = sw[3] = sw[2] = sw[1] = sw[0] = (HYPRE_Int)psw;
149a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructGridSetNumGhost(ex->hgrid, sw));
150f4bdf6c4SBarry Smith 
151f4bdf6c4SBarry Smith   /* create the hypre stencil object and set its information */
15208401ef6SPierre Jolivet   PetscCheck(sw[0] <= 1, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add support for wider stencils");
15308401ef6SPierre Jolivet   PetscCheck(st != DMDA_STENCIL_BOX, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add support for box stencils");
154f4bdf6c4SBarry Smith   if (dim == 1) {
1552cf14000SStefano Zampini     HYPRE_Int offsets[3][1] = {{-1}, {0}, {1}};
156f4bdf6c4SBarry Smith     ssize                   = 3;
157f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_StructStencilCreate((HYPRE_Int)dim, (HYPRE_Int)ssize, &ex->hstencil));
158f2f41e48SZach Atkins     for (i = 0; i < ssize; i++) PetscCallHYPRE(HYPRE_StructStencilSetElement(ex->hstencil, (HYPRE_Int)i, offsets[i]));
159f4bdf6c4SBarry Smith   } else if (dim == 2) {
1609371c9d4SSatish Balay     HYPRE_Int offsets[5][2] = {
1619371c9d4SSatish Balay       {0,  -1},
1629371c9d4SSatish Balay       {-1, 0 },
1639371c9d4SSatish Balay       {0,  0 },
1649371c9d4SSatish Balay       {1,  0 },
1659371c9d4SSatish Balay       {0,  1 }
1669371c9d4SSatish Balay     };
167f4bdf6c4SBarry Smith     ssize = 5;
168f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_StructStencilCreate((HYPRE_Int)dim, (HYPRE_Int)ssize, &ex->hstencil));
169f2f41e48SZach Atkins     for (i = 0; i < ssize; i++) PetscCallHYPRE(HYPRE_StructStencilSetElement(ex->hstencil, (HYPRE_Int)i, offsets[i]));
170f4bdf6c4SBarry Smith   } else if (dim == 3) {
1719371c9d4SSatish Balay     HYPRE_Int offsets[7][3] = {
1729371c9d4SSatish Balay       {0,  0,  -1},
1739371c9d4SSatish Balay       {0,  -1, 0 },
1749371c9d4SSatish Balay       {-1, 0,  0 },
1759371c9d4SSatish Balay       {0,  0,  0 },
1769371c9d4SSatish Balay       {1,  0,  0 },
1779371c9d4SSatish Balay       {0,  1,  0 },
1789371c9d4SSatish Balay       {0,  0,  1 }
1799371c9d4SSatish Balay     };
180f4bdf6c4SBarry Smith     ssize = 7;
181f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_StructStencilCreate((HYPRE_Int)dim, (HYPRE_Int)ssize, &ex->hstencil));
182f2f41e48SZach Atkins     for (i = 0; i < ssize; i++) PetscCallHYPRE(HYPRE_StructStencilSetElement(ex->hstencil, (HYPRE_Int)i, offsets[i]));
183f4bdf6c4SBarry Smith   }
184f4bdf6c4SBarry Smith 
185f4bdf6c4SBarry Smith   /* create the HYPRE vector for rhs and solution */
186a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorCreate(ex->hcomm, ex->hgrid, &ex->hb));
187a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorCreate(ex->hcomm, ex->hgrid, &ex->hx));
188a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorInitialize(ex->hb));
189a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorInitialize(ex->hx));
190a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorAssemble(ex->hb));
191a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorAssemble(ex->hx));
192f4bdf6c4SBarry Smith 
193f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
194a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructMatrixCreate(ex->hcomm, ex->hgrid, ex->hstencil, &ex->hmat));
195a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructGridDestroy(ex->hgrid));
196a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructStencilDestroy(ex->hstencil));
197f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
198a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_StructMatrixInitialize(ex->hmat));
199f4bdf6c4SBarry Smith     ex->needsinitialization = PETSC_FALSE;
200f4bdf6c4SBarry Smith   }
201f4bdf6c4SBarry Smith 
202f4bdf6c4SBarry Smith   /* set the global and local sizes of the matrix */
2039566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, 0, 0, 0, &nx, &ny, &nz));
2049566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat, dof * nx * ny * nz, dof * nx * ny * nz, PETSC_DECIDE, PETSC_DECIDE));
2059566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->rmap, 1));
2069566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->cmap, 1));
2079566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->rmap));
2089566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->cmap));
20959cb773eSBarry Smith   mat->preallocated = PETSC_TRUE;
210f4bdf6c4SBarry Smith 
211966bd95aSPierre Jolivet   PetscCheck(dim == 3, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Only support for 3d DMDA currently");
212f4bdf6c4SBarry Smith   mat->ops->setvalueslocal = MatSetValuesLocal_HYPREStruct_3d;
213f4bdf6c4SBarry Smith   mat->ops->zerorowslocal  = MatZeroRowsLocal_HYPREStruct_3d;
214f4bdf6c4SBarry Smith   mat->ops->zeroentries    = MatZeroEntries_HYPREStruct_3d;
2158865f1eaSKarl Rupp 
2169566063dSJacob Faibussowitsch   /*        PetscCall(MatZeroEntries_HYPREStruct_3d(mat)); */
217f4bdf6c4SBarry Smith 
218f4bdf6c4SBarry Smith   /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
2199566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(mat, &ex->rstart, NULL));
2209566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(ex->da, &ltog));
2219566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **)&ex->gindices));
2229566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(ex->da, 0, 0, 0, &ex->gnx, &ex->gnxgny, 0));
223f4bdf6c4SBarry Smith   ex->gnxgny *= ex->gnx;
2249566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da, &ex->xs, &ex->ys, &ex->zs, &ex->nx, &ex->ny, 0));
225f4bdf6c4SBarry Smith   ex->nxny = ex->nx * ex->ny;
2263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
227f4bdf6c4SBarry Smith }
228f4bdf6c4SBarry Smith 
MatMult_HYPREStruct(Mat A,Vec x,Vec y)22966976f2fSJacob Faibussowitsch static PetscErrorCode MatMult_HYPREStruct(Mat A, Vec x, Vec y)
230d71ae5a4SJacob Faibussowitsch {
231b026d285SBarry Smith   const PetscScalar *xx;
232b026d285SBarry Smith   PetscScalar       *yy;
2334ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
2342cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
235f4f49eeaSPierre Jolivet   Mat_HYPREStruct   *mx = (Mat_HYPREStruct *)A->data;
236f4bdf6c4SBarry Smith 
237f4bdf6c4SBarry Smith   PetscFunctionBegin;
2389566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
2392cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
240f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
241f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
242f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
2432cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
2442cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
2452cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
2462cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
2472cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
2482cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
249f4bdf6c4SBarry Smith 
250f4bdf6c4SBarry Smith   /* copy x values over to hypre */
251a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorSetConstantValues(mx->hb, 0.0));
2529566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(x, &xx));
253a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorSetBoxValues(mx->hb, hlower, hupper, (HYPRE_Complex *)xx));
2549566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(x, &xx));
255a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorAssemble(mx->hb));
256a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructMatrixMatvec(1.0, mx->hmat, mx->hb, 0.0, mx->hx));
257f4bdf6c4SBarry Smith 
258f4bdf6c4SBarry Smith   /* copy solution values back to PETSc */
2599566063dSJacob Faibussowitsch   PetscCall(VecGetArray(y, &yy));
260a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorGetBoxValues(mx->hx, hlower, hupper, (HYPRE_Complex *)yy));
2619566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(y, &yy));
2623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
263f4bdf6c4SBarry Smith }
264f4bdf6c4SBarry Smith 
MatAssemblyEnd_HYPREStruct(Mat mat,MatAssemblyType mode)26566976f2fSJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_HYPREStruct(Mat mat, MatAssemblyType mode)
266d71ae5a4SJacob Faibussowitsch {
267f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct *)mat->data;
268f4bdf6c4SBarry Smith 
269f4bdf6c4SBarry Smith   PetscFunctionBegin;
270a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructMatrixAssemble(ex->hmat));
2713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
272f4bdf6c4SBarry Smith }
273f4bdf6c4SBarry Smith 
MatZeroEntries_HYPREStruct(Mat mat)27466976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPREStruct(Mat mat)
275d71ae5a4SJacob Faibussowitsch {
276f4bdf6c4SBarry Smith   PetscFunctionBegin;
277f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
2783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
279f4bdf6c4SBarry Smith }
280f4bdf6c4SBarry Smith 
MatDestroy_HYPREStruct(Mat mat)28166976f2fSJacob Faibussowitsch static PetscErrorCode MatDestroy_HYPREStruct(Mat mat)
282d71ae5a4SJacob Faibussowitsch {
283f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex = (Mat_HYPREStruct *)mat->data;
284f4bdf6c4SBarry Smith 
285f4bdf6c4SBarry Smith   PetscFunctionBegin;
286a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructMatrixDestroy(ex->hmat));
287a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorDestroy(ex->hx));
288a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_StructVectorDestroy(ex->hb));
2899566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)ex->da));
290f4f49eeaSPierre Jolivet   PetscCallMPI(MPI_Comm_free(&ex->hcomm));
2919566063dSJacob Faibussowitsch   PetscCall(PetscFree(ex));
2923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
293f4bdf6c4SBarry Smith }
294f4bdf6c4SBarry Smith 
MatCreate_HYPREStruct(Mat B)295d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_HYPREStruct(Mat B)
296d71ae5a4SJacob Faibussowitsch {
297f4bdf6c4SBarry Smith   Mat_HYPREStruct *ex;
298f4bdf6c4SBarry Smith 
299f4bdf6c4SBarry Smith   PetscFunctionBegin;
3004dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&ex));
301f4bdf6c4SBarry Smith   B->data      = (void *)ex;
302f4bdf6c4SBarry Smith   B->rmap->bs  = 1;
303f4bdf6c4SBarry Smith   B->assembled = PETSC_FALSE;
304f4bdf6c4SBarry Smith 
305f4bdf6c4SBarry Smith   B->insertmode = NOT_SET_VALUES;
306f4bdf6c4SBarry Smith 
307f4bdf6c4SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_HYPREStruct;
308f4bdf6c4SBarry Smith   B->ops->mult        = MatMult_HYPREStruct;
309f4bdf6c4SBarry Smith   B->ops->zeroentries = MatZeroEntries_HYPREStruct;
310f4bdf6c4SBarry Smith   B->ops->destroy     = MatDestroy_HYPREStruct;
31159cb773eSBarry Smith   B->ops->setup       = MatSetUp_HYPREStruct;
312f4bdf6c4SBarry Smith 
313f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
314f4bdf6c4SBarry Smith 
315f4f49eeaSPierre Jolivet   PetscCallMPI(MPI_Comm_dup(PetscObjectComm((PetscObject)B), &ex->hcomm));
3169566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRESTRUCT));
317*5482091fSJunchao Zhang   PetscCall(PetscHYPREInitialize());
3183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
319f4bdf6c4SBarry Smith }
320f4bdf6c4SBarry Smith 
321f4bdf6c4SBarry Smith /*MC
322f4bdf6c4SBarry Smith    MATHYPRESSTRUCT - MATHYPRESSTRUCT = "hypresstruct" - A matrix type to be used for parallel sparse matrices
323f4bdf6c4SBarry Smith           based on the hypre HYPRE_SStructMatrix.
324f4bdf6c4SBarry Smith 
325f4bdf6c4SBarry Smith    Level: intermediate
326f4bdf6c4SBarry Smith 
32795452b02SPatrick Sanan    Notes:
32895452b02SPatrick Sanan     Unlike hypre's general semi-struct object consisting of a collection of structured-grid objects and unstructured
329b026d285SBarry Smith           grid objects, we restrict the semi-struct objects to consist of only structured-grid components.
330f4bdf6c4SBarry Smith 
331f4bdf6c4SBarry 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
332dce8aebaSBarry Smith           be defined by a `DMDA`.
333f4bdf6c4SBarry Smith 
33459cb773eSBarry Smith           The matrix needs a DMDA associated with it by either a call to MatSetDM() or if the matrix is obtained from DMCreateMatrix()
335f4bdf6c4SBarry Smith 
336dce8aebaSBarry Smith .seealso: `Mat`
337f4bdf6c4SBarry Smith M*/
338f4bdf6c4SBarry Smith 
MatSetValuesLocal_HYPRESStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv)33966976f2fSJacob Faibussowitsch static PetscErrorCode MatSetValuesLocal_HYPRESStruct_3d(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
340d71ae5a4SJacob Faibussowitsch {
3412cf14000SStefano Zampini   HYPRE_Int         index[3], *entries;
3422cf14000SStefano Zampini   PetscInt          i, j, stencil;
34339accc25SStefano Zampini   HYPRE_Complex    *values = (HYPRE_Complex *)y;
344f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex     = (Mat_HYPRESStruct *)mat->data;
345f4bdf6c4SBarry Smith 
346f2f41e48SZach Atkins   HYPRE_Int part = 0; /* PETSc sstruct interface only allows 1 part */
3474ddd07fcSJed Brown   PetscInt  ordering;
3484ddd07fcSJed Brown   PetscInt  grid_rank, to_grid_rank;
3494ddd07fcSJed Brown   PetscInt  var_type, to_var_type;
3504ddd07fcSJed Brown   PetscInt  to_var_entry = 0;
3514ddd07fcSJed Brown   PetscInt  nvars        = ex->nvars;
3522cf14000SStefano Zampini   PetscInt  row;
353f4bdf6c4SBarry Smith 
354f4bdf6c4SBarry Smith   PetscFunctionBegin;
3559566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(7 * nvars, &entries));
356f4bdf6c4SBarry Smith   ordering = ex->dofs_order; /* ordering= 0   nodal ordering
357f4bdf6c4SBarry Smith                                            1   variable ordering */
35861710fbeSStefano Zampini   /* stencil entries are ordered by variables: var0_stencil0, var0_stencil1, ..., var0_stencil6, var1_stencil0, var1_stencil1, ...  */
359f4bdf6c4SBarry Smith   if (!ordering) {
360f4bdf6c4SBarry Smith     for (i = 0; i < nrow; i++) {
361f4bdf6c4SBarry Smith       grid_rank = irow[i] / nvars;
362f4bdf6c4SBarry Smith       var_type  = (irow[i] % nvars);
363f4bdf6c4SBarry Smith 
364f4bdf6c4SBarry Smith       for (j = 0; j < ncol; j++) {
365f4bdf6c4SBarry Smith         to_grid_rank = icol[j] / nvars;
366f4bdf6c4SBarry Smith         to_var_type  = (icol[j] % nvars);
367f4bdf6c4SBarry Smith 
368f4bdf6c4SBarry Smith         to_var_entry = to_var_entry * 7;
369f2f41e48SZach Atkins         entries[j]   = (HYPRE_Int)to_var_entry;
370f4bdf6c4SBarry Smith 
371f4bdf6c4SBarry Smith         stencil = to_grid_rank - grid_rank;
372f4bdf6c4SBarry Smith         if (!stencil) {
373f4bdf6c4SBarry Smith           entries[j] += 3;
374f4bdf6c4SBarry Smith         } else if (stencil == -1) {
375f4bdf6c4SBarry Smith           entries[j] += 2;
376f4bdf6c4SBarry Smith         } else if (stencil == 1) {
377f4bdf6c4SBarry Smith           entries[j] += 4;
378f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnx) {
379f4bdf6c4SBarry Smith           entries[j] += 1;
380f4bdf6c4SBarry Smith         } else if (stencil == ex->gnx) {
381f4bdf6c4SBarry Smith           entries[j] += 5;
382f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnxgny) {
383f4bdf6c4SBarry Smith           entries[j] += 0;
384f4bdf6c4SBarry Smith         } else if (stencil == ex->gnxgny) {
385f4bdf6c4SBarry Smith           entries[j] += 6;
38663a3b9bcSJacob 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);
387f4bdf6c4SBarry Smith       }
388f4bdf6c4SBarry Smith 
389f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
3902cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
3912cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny));
3922cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny)));
393f4bdf6c4SBarry Smith 
394f2f41e48SZach Atkins       if (addv == ADD_VALUES) PetscCallHYPRE(HYPRE_SStructMatrixAddToValues(ex->ss_mat, part, index, (HYPRE_Int)var_type, (HYPRE_Int)ncol, entries, values));
395f2f41e48SZach Atkins       else PetscCallHYPRE(HYPRE_SStructMatrixSetValues(ex->ss_mat, part, index, (HYPRE_Int)var_type, (HYPRE_Int)ncol, entries, values));
396f4bdf6c4SBarry Smith       values += ncol;
397f4bdf6c4SBarry Smith     }
398f4bdf6c4SBarry Smith   } else {
399f4bdf6c4SBarry Smith     for (i = 0; i < nrow; i++) {
400f4bdf6c4SBarry Smith       var_type  = irow[i] / (ex->gnxgnygnz);
401f4bdf6c4SBarry Smith       grid_rank = irow[i] - var_type * (ex->gnxgnygnz);
402f4bdf6c4SBarry Smith 
403f4bdf6c4SBarry Smith       for (j = 0; j < ncol; j++) {
404f4bdf6c4SBarry Smith         to_var_type  = icol[j] / (ex->gnxgnygnz);
405f4bdf6c4SBarry Smith         to_grid_rank = icol[j] - to_var_type * (ex->gnxgnygnz);
406f4bdf6c4SBarry Smith 
407f4bdf6c4SBarry Smith         to_var_entry = to_var_entry * 7;
408f2f41e48SZach Atkins         entries[j]   = (HYPRE_Int)to_var_entry;
409f4bdf6c4SBarry Smith 
410f4bdf6c4SBarry Smith         stencil = to_grid_rank - grid_rank;
411f4bdf6c4SBarry Smith         if (!stencil) {
412f4bdf6c4SBarry Smith           entries[j] += 3;
413f4bdf6c4SBarry Smith         } else if (stencil == -1) {
414f4bdf6c4SBarry Smith           entries[j] += 2;
415f4bdf6c4SBarry Smith         } else if (stencil == 1) {
416f4bdf6c4SBarry Smith           entries[j] += 4;
417f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnx) {
418f4bdf6c4SBarry Smith           entries[j] += 1;
419f4bdf6c4SBarry Smith         } else if (stencil == ex->gnx) {
420f4bdf6c4SBarry Smith           entries[j] += 5;
421f4bdf6c4SBarry Smith         } else if (stencil == -ex->gnxgny) {
422f4bdf6c4SBarry Smith           entries[j] += 0;
423f4bdf6c4SBarry Smith         } else if (stencil == ex->gnxgny) {
424f4bdf6c4SBarry Smith           entries[j] += 6;
42563a3b9bcSJacob 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);
426f4bdf6c4SBarry Smith       }
427f4bdf6c4SBarry Smith 
428f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
4292cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
4302cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny));
4312cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny)));
432f4bdf6c4SBarry Smith 
433f2f41e48SZach Atkins       if (addv == ADD_VALUES) PetscCallHYPRE(HYPRE_SStructMatrixAddToValues(ex->ss_mat, part, index, (HYPRE_Int)var_type, (HYPRE_Int)ncol, entries, values));
434f2f41e48SZach Atkins       else PetscCallHYPRE(HYPRE_SStructMatrixSetValues(ex->ss_mat, part, index, (HYPRE_Int)var_type, (HYPRE_Int)ncol, entries, values));
435f4bdf6c4SBarry Smith       values += ncol;
436f4bdf6c4SBarry Smith     }
437f4bdf6c4SBarry Smith   }
4389566063dSJacob Faibussowitsch   PetscCall(PetscFree(entries));
4393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
440f4bdf6c4SBarry Smith }
441f4bdf6c4SBarry Smith 
MatZeroRowsLocal_HYPRESStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscScalar d,Vec x,Vec b)44266976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroRowsLocal_HYPRESStruct_3d(Mat mat, PetscInt nrow, const PetscInt irow[], PetscScalar d, Vec x, Vec b)
443d71ae5a4SJacob Faibussowitsch {
4442cf14000SStefano Zampini   HYPRE_Int         index[3], *entries;
4452cf14000SStefano Zampini   PetscInt          i;
44639accc25SStefano Zampini   HYPRE_Complex   **values;
447f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct *)mat->data;
448f4bdf6c4SBarry Smith 
449f2f41e48SZach Atkins   HYPRE_Int part     = 0; /* PETSc sstruct interface only allows 1 part */
4504ddd07fcSJed Brown   PetscInt  ordering = ex->dofs_order;
4514ddd07fcSJed Brown   PetscInt  grid_rank;
4524ddd07fcSJed Brown   PetscInt  var_type;
4534ddd07fcSJed Brown   PetscInt  nvars = ex->nvars;
4542cf14000SStefano Zampini   PetscInt  row;
455f4bdf6c4SBarry Smith 
456f4bdf6c4SBarry Smith   PetscFunctionBegin;
45708401ef6SPierre Jolivet   PetscCheck(!x || !b, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "No support");
4589566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(7 * nvars, &entries));
459f4bdf6c4SBarry Smith 
4609566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nvars, &values));
4619566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(7 * nvars * nvars, &values[0]));
462ad540459SPierre Jolivet   for (i = 1; i < nvars; i++) values[i] = values[i - 1] + nvars * 7;
463f4bdf6c4SBarry Smith 
464f4bdf6c4SBarry Smith   for (i = 0; i < nvars; i++) {
4659566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(values[i], nvars * 7 * sizeof(HYPRE_Complex)));
4669566063dSJacob Faibussowitsch     PetscCall(PetscHYPREScalarCast(d, values[i] + 3));
467f4bdf6c4SBarry Smith   }
468f4bdf6c4SBarry Smith 
469f2f41e48SZach Atkins   for (i = 0; i < nvars * 7; i++) entries[i] = (HYPRE_Int)i;
470f4bdf6c4SBarry Smith 
471f4bdf6c4SBarry Smith   if (!ordering) {
472f4bdf6c4SBarry Smith     for (i = 0; i < nrow; i++) {
473f4bdf6c4SBarry Smith       grid_rank = irow[i] / nvars;
474f4bdf6c4SBarry Smith       var_type  = (irow[i] % nvars);
475f4bdf6c4SBarry Smith 
476f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
4772cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
4782cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny));
4792cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny)));
480f2f41e48SZach Atkins       PetscCallHYPRE(HYPRE_SStructMatrixSetValues(ex->ss_mat, part, index, (HYPRE_Int)var_type, 7 * (HYPRE_Int)nvars, entries, values[var_type]));
481f4bdf6c4SBarry Smith     }
482f4bdf6c4SBarry Smith   } else {
483f4bdf6c4SBarry Smith     for (i = 0; i < nrow; i++) {
484f4bdf6c4SBarry Smith       var_type  = irow[i] / (ex->gnxgnygnz);
485f4bdf6c4SBarry Smith       grid_rank = irow[i] - var_type * (ex->gnxgnygnz);
486f4bdf6c4SBarry Smith 
487f4bdf6c4SBarry Smith       row      = ex->gindices[grid_rank] - ex->rstart;
4882cf14000SStefano Zampini       index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx));
4892cf14000SStefano Zampini       index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny));
4902cf14000SStefano Zampini       index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny)));
491f2f41e48SZach Atkins       PetscCallHYPRE(HYPRE_SStructMatrixSetValues(ex->ss_mat, part, index, (HYPRE_Int)var_type, 7 * (HYPRE_Int)nvars, entries, values[var_type]));
492f4bdf6c4SBarry Smith     }
493f4bdf6c4SBarry Smith   }
494a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructMatrixAssemble(ex->ss_mat));
4959566063dSJacob Faibussowitsch   PetscCall(PetscFree(values[0]));
4969566063dSJacob Faibussowitsch   PetscCall(PetscFree(values));
4979566063dSJacob Faibussowitsch   PetscCall(PetscFree(entries));
4983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
499f4bdf6c4SBarry Smith }
500f4bdf6c4SBarry Smith 
MatZeroEntries_HYPRESStruct_3d(Mat mat)50166976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPRESStruct_3d(Mat mat)
502d71ae5a4SJacob Faibussowitsch {
503f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex    = (Mat_HYPRESStruct *)mat->data;
5044ddd07fcSJed Brown   PetscInt          nvars = ex->nvars;
5054ddd07fcSJed Brown   PetscInt          size;
506f2f41e48SZach Atkins   HYPRE_Int         part = 0; /* only one part */
507f4bdf6c4SBarry Smith 
508f4bdf6c4SBarry Smith   PetscFunctionBegin;
5094ad8454bSPierre 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);
510f4bdf6c4SBarry Smith   {
5112cf14000SStefano Zampini     HYPRE_Int      i, *entries, iupper[3], ilower[3];
51239accc25SStefano Zampini     HYPRE_Complex *values;
5134ddd07fcSJed Brown 
514f4bdf6c4SBarry Smith     for (i = 0; i < 3; i++) {
515f2f41e48SZach Atkins       ilower[i] = (HYPRE_Int)ex->hbox.imin[i];
516f2f41e48SZach Atkins       iupper[i] = (HYPRE_Int)ex->hbox.imax[i];
517f4bdf6c4SBarry Smith     }
518f4bdf6c4SBarry Smith 
5199566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(nvars * 7, &entries, nvars * 7 * size, &values));
5208865f1eaSKarl Rupp     for (i = 0; i < nvars * 7; i++) entries[i] = i;
5219566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(values, nvars * 7 * size));
522f4bdf6c4SBarry Smith 
523f2f41e48SZach 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));
5249566063dSJacob Faibussowitsch     PetscCall(PetscFree2(entries, values));
525f4bdf6c4SBarry Smith   }
526a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructMatrixAssemble(ex->ss_mat));
5273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
528f4bdf6c4SBarry Smith }
529f4bdf6c4SBarry Smith 
MatSetUp_HYPRESStruct(Mat mat)530d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatSetUp_HYPRESStruct(Mat mat)
531d71ae5a4SJacob Faibussowitsch {
532f4bdf6c4SBarry Smith   Mat_HYPRESStruct      *ex = (Mat_HYPRESStruct *)mat->data;
533f4bdf6c4SBarry Smith   PetscInt               dim, dof, sw[3], nx, ny, nz;
5344ddd07fcSJed Brown   PetscInt               ilower[3], iupper[3], ssize, i;
535bff4a2f0SMatthew G. Knepley   DMBoundaryType         px, py, pz;
536f4bdf6c4SBarry Smith   DMDAStencilType        st;
5374ddd07fcSJed Brown   PetscInt               nparts = 1; /* assuming only one part */
538f2f41e48SZach Atkins   HYPRE_Int              part   = 0;
539565245c5SBarry Smith   ISLocalToGlobalMapping ltog;
54059cb773eSBarry Smith   DM                     da;
541b026d285SBarry Smith 
542f4bdf6c4SBarry Smith   PetscFunctionBegin;
5439566063dSJacob Faibussowitsch   PetscCall(MatGetDM(mat, (DM *)&da));
544f4bdf6c4SBarry Smith   ex->da = da;
5459566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)da));
546f4bdf6c4SBarry Smith 
5479566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(ex->da, &dim, 0, 0, 0, 0, 0, 0, &dof, &sw[0], &px, &py, &pz, &st));
5489566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
549f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
550f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
551f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
552f4bdf6c4SBarry Smith   /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */
553f2f41e48SZach Atkins   ex->hbox.imin[0] = (HYPRE_Int)ilower[0];
554f2f41e48SZach Atkins   ex->hbox.imin[1] = (HYPRE_Int)ilower[1];
555f2f41e48SZach Atkins   ex->hbox.imin[2] = (HYPRE_Int)ilower[2];
556f2f41e48SZach Atkins   ex->hbox.imax[0] = (HYPRE_Int)iupper[0];
557f2f41e48SZach Atkins   ex->hbox.imax[1] = (HYPRE_Int)iupper[1];
558f2f41e48SZach Atkins   ex->hbox.imax[2] = (HYPRE_Int)iupper[2];
559f4bdf6c4SBarry Smith 
560f4bdf6c4SBarry Smith   ex->dofs_order = 0;
561f4bdf6c4SBarry Smith 
562f4bdf6c4SBarry Smith   /* assuming that the same number of dofs on each gridpoint. Also assume all cell-centred based */
5639ad2cedaSPierre Jolivet   ex->nvars = (int)dof;
564f4bdf6c4SBarry Smith 
565f4bdf6c4SBarry Smith   /* create the hypre grid object and set its information */
5661dca8a05SBarry Smith   PetscCheck(!px && !py && !pz, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add periodic support by calling HYPRE_SStructGridSetPeriodic()");
567f2f41e48SZach Atkins   PetscCallHYPRE(HYPRE_SStructGridCreate(ex->hcomm, (HYPRE_Int)dim, (HYPRE_Int)nparts, &ex->ss_grid));
568a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructGridSetExtents(ex->ss_grid, part, ex->hbox.imin, ex->hbox.imax));
569f4bdf6c4SBarry Smith   {
570f4bdf6c4SBarry Smith     HYPRE_SStructVariable *vartypes;
5719566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(ex->nvars, &vartypes));
5728865f1eaSKarl Rupp     for (i = 0; i < ex->nvars; i++) vartypes[i] = HYPRE_SSTRUCT_VARIABLE_CELL;
573f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_SStructGridSetVariables(ex->ss_grid, part, (HYPRE_Int)ex->nvars, vartypes));
5749566063dSJacob Faibussowitsch     PetscCall(PetscFree(vartypes));
575f4bdf6c4SBarry Smith   }
576a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructGridAssemble(ex->ss_grid));
577f4bdf6c4SBarry Smith 
578f4bdf6c4SBarry Smith   sw[1] = sw[0];
579f4bdf6c4SBarry Smith   sw[2] = sw[1];
580a333fa2bSZach Atkins   /* PetscCallHYPRE(HYPRE_SStructGridSetNumGhost(ex->ss_grid,sw)); */
581f4bdf6c4SBarry Smith 
582f4bdf6c4SBarry Smith   /* create the hypre stencil object and set its information */
58308401ef6SPierre Jolivet   PetscCheck(sw[0] <= 1, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add support for wider stencils");
58408401ef6SPierre Jolivet   PetscCheck(st != DMDA_STENCIL_BOX, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add support for box stencils");
585f4bdf6c4SBarry Smith 
586f4bdf6c4SBarry Smith   if (dim == 1) {
5872cf14000SStefano Zampini     HYPRE_Int offsets[3][1] = {{-1}, {0}, {1}};
5884ddd07fcSJed Brown     PetscInt  j, cnt;
589f4bdf6c4SBarry Smith 
590f4bdf6c4SBarry Smith     ssize = 3 * (ex->nvars);
591f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_SStructStencilCreate((HYPRE_Int)dim, (HYPRE_Int)ssize, &ex->ss_stencil));
592f4bdf6c4SBarry Smith     cnt = 0;
593f4bdf6c4SBarry Smith     for (i = 0; i < (ex->nvars); i++) {
594f4bdf6c4SBarry Smith       for (j = 0; j < 3; j++) {
595f2f41e48SZach Atkins         PetscCallHYPRE(HYPRE_SStructStencilSetEntry(ex->ss_stencil, (HYPRE_Int)cnt, offsets[j], (HYPRE_Int)i));
596f4bdf6c4SBarry Smith         cnt++;
597f4bdf6c4SBarry Smith       }
598f4bdf6c4SBarry Smith     }
599f4bdf6c4SBarry Smith   } else if (dim == 2) {
6009371c9d4SSatish Balay     HYPRE_Int offsets[5][2] = {
6019371c9d4SSatish Balay       {0,  -1},
6029371c9d4SSatish Balay       {-1, 0 },
6039371c9d4SSatish Balay       {0,  0 },
6049371c9d4SSatish Balay       {1,  0 },
6059371c9d4SSatish Balay       {0,  1 }
6069371c9d4SSatish Balay     };
6074ddd07fcSJed Brown     PetscInt j, cnt;
608f4bdf6c4SBarry Smith 
609f4bdf6c4SBarry Smith     ssize = 5 * (ex->nvars);
610f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_SStructStencilCreate((HYPRE_Int)dim, (HYPRE_Int)ssize, &ex->ss_stencil));
611f4bdf6c4SBarry Smith     cnt = 0;
612f4bdf6c4SBarry Smith     for (i = 0; i < (ex->nvars); i++) {
613f4bdf6c4SBarry Smith       for (j = 0; j < 5; j++) {
614f2f41e48SZach Atkins         PetscCallHYPRE(HYPRE_SStructStencilSetEntry(ex->ss_stencil, (HYPRE_Int)cnt, offsets[j], (HYPRE_Int)i));
615f4bdf6c4SBarry Smith         cnt++;
616f4bdf6c4SBarry Smith       }
617f4bdf6c4SBarry Smith     }
618f4bdf6c4SBarry Smith   } else if (dim == 3) {
6199371c9d4SSatish Balay     HYPRE_Int offsets[7][3] = {
6209371c9d4SSatish Balay       {0,  0,  -1},
6219371c9d4SSatish Balay       {0,  -1, 0 },
6229371c9d4SSatish Balay       {-1, 0,  0 },
6239371c9d4SSatish Balay       {0,  0,  0 },
6249371c9d4SSatish Balay       {1,  0,  0 },
6259371c9d4SSatish Balay       {0,  1,  0 },
6269371c9d4SSatish Balay       {0,  0,  1 }
6279371c9d4SSatish Balay     };
6284ddd07fcSJed Brown     PetscInt j, cnt;
629f4bdf6c4SBarry Smith 
630f4bdf6c4SBarry Smith     ssize = 7 * (ex->nvars);
631f2f41e48SZach Atkins     PetscCallHYPRE(HYPRE_SStructStencilCreate((HYPRE_Int)dim, (HYPRE_Int)ssize, &ex->ss_stencil));
632f4bdf6c4SBarry Smith     cnt = 0;
633f4bdf6c4SBarry Smith     for (i = 0; i < (ex->nvars); i++) {
634f4bdf6c4SBarry Smith       for (j = 0; j < 7; j++) {
635f2f41e48SZach Atkins         PetscCallHYPRE(HYPRE_SStructStencilSetEntry(ex->ss_stencil, (HYPRE_Int)cnt, offsets[j], (HYPRE_Int)i));
636f4bdf6c4SBarry Smith         cnt++;
637f4bdf6c4SBarry Smith       }
638f4bdf6c4SBarry Smith     }
639f4bdf6c4SBarry Smith   }
640f4bdf6c4SBarry Smith 
641f4bdf6c4SBarry Smith   /* create the HYPRE graph */
642a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructGraphCreate(ex->hcomm, ex->ss_grid, &ex->ss_graph));
643f4bdf6c4SBarry Smith 
644f4bdf6c4SBarry Smith   /* set the stencil graph. Note that each variable has the same graph. This means that each
645f4bdf6c4SBarry Smith      variable couples to all the other variable and with the same stencil pattern. */
646f2f41e48SZach Atkins   for (i = 0; i < (ex->nvars); i++) PetscCallHYPRE(HYPRE_SStructGraphSetStencil(ex->ss_graph, part, (HYPRE_Int)i, ex->ss_stencil));
647a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructGraphAssemble(ex->ss_graph));
648f4bdf6c4SBarry Smith 
649f4bdf6c4SBarry Smith   /* create the HYPRE sstruct vectors for rhs and solution */
650a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructVectorCreate(ex->hcomm, ex->ss_grid, &ex->ss_b));
651a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructVectorCreate(ex->hcomm, ex->ss_grid, &ex->ss_x));
652a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructVectorInitialize(ex->ss_b));
653a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructVectorInitialize(ex->ss_x));
654a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructVectorAssemble(ex->ss_b));
655a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructVectorAssemble(ex->ss_x));
656f4bdf6c4SBarry Smith 
657f4bdf6c4SBarry Smith   /* create the hypre matrix object and set its information */
658a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructMatrixCreate(ex->hcomm, ex->ss_graph, &ex->ss_mat));
659a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructGridDestroy(ex->ss_grid));
660a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructStencilDestroy(ex->ss_stencil));
661f4bdf6c4SBarry Smith   if (ex->needsinitialization) {
662a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_SStructMatrixInitialize(ex->ss_mat));
663f4bdf6c4SBarry Smith     ex->needsinitialization = PETSC_FALSE;
664f4bdf6c4SBarry Smith   }
665f4bdf6c4SBarry Smith 
666f4bdf6c4SBarry Smith   /* set the global and local sizes of the matrix */
6679566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(da, 0, 0, 0, &nx, &ny, &nz));
6689566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(mat, dof * nx * ny * nz, dof * nx * ny * nz, PETSC_DECIDE, PETSC_DECIDE));
6699566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->rmap, dof));
6709566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(mat->cmap, dof));
6719566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->rmap));
6729566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetUp(mat->cmap));
67361710fbeSStefano Zampini   mat->preallocated = PETSC_TRUE;
674f4bdf6c4SBarry Smith 
675966bd95aSPierre Jolivet   PetscCheck(dim == 3, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Only support for 3d DMDA currently");
676f4bdf6c4SBarry Smith   mat->ops->setvalueslocal = MatSetValuesLocal_HYPRESStruct_3d;
677f4bdf6c4SBarry Smith   mat->ops->zerorowslocal  = MatZeroRowsLocal_HYPRESStruct_3d;
678f4bdf6c4SBarry Smith   mat->ops->zeroentries    = MatZeroEntries_HYPRESStruct_3d;
6798865f1eaSKarl Rupp 
6809566063dSJacob Faibussowitsch   /* PetscCall(MatZeroEntries_HYPRESStruct_3d(mat)); */
681f4bdf6c4SBarry Smith 
682f4bdf6c4SBarry Smith   /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */
6839566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(mat, &ex->rstart, NULL));
6849566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(ex->da, &ltog));
6859566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **)&ex->gindices));
6869566063dSJacob Faibussowitsch   PetscCall(DMDAGetGhostCorners(ex->da, 0, 0, 0, &ex->gnx, &ex->gnxgny, &ex->gnxgnygnz));
6878865f1eaSKarl Rupp 
688f4bdf6c4SBarry Smith   ex->gnxgny *= ex->gnx;
689f4bdf6c4SBarry Smith   ex->gnxgnygnz *= ex->gnxgny;
6908865f1eaSKarl Rupp 
6919566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(ex->da, &ex->xs, &ex->ys, &ex->zs, &ex->nx, &ex->ny, &ex->nz));
6928865f1eaSKarl Rupp 
693f4bdf6c4SBarry Smith   ex->nxny   = ex->nx * ex->ny;
694f4bdf6c4SBarry Smith   ex->nxnynz = ex->nz * ex->nxny;
6953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
696f4bdf6c4SBarry Smith }
697f4bdf6c4SBarry Smith 
MatMult_HYPRESStruct(Mat A,Vec x,Vec y)69866976f2fSJacob Faibussowitsch static PetscErrorCode MatMult_HYPRESStruct(Mat A, Vec x, Vec y)
699d71ae5a4SJacob Faibussowitsch {
700b026d285SBarry Smith   const PetscScalar *xx;
701b026d285SBarry Smith   PetscScalar       *yy;
7022cf14000SStefano Zampini   HYPRE_Int          hlower[3], hupper[3];
7034ddd07fcSJed Brown   PetscInt           ilower[3], iupper[3];
704f4f49eeaSPierre Jolivet   Mat_HYPRESStruct  *mx       = (Mat_HYPRESStruct *)A->data;
7054ddd07fcSJed Brown   PetscInt           ordering = mx->dofs_order;
7064ddd07fcSJed Brown   PetscInt           nvars    = mx->nvars;
707f2f41e48SZach Atkins   HYPRE_Int          part     = 0;
7084ddd07fcSJed Brown   PetscInt           size;
7094ddd07fcSJed Brown   PetscInt           i;
710f4bdf6c4SBarry Smith 
711f4bdf6c4SBarry Smith   PetscFunctionBegin;
7129566063dSJacob Faibussowitsch   PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2]));
7132cf14000SStefano Zampini 
7142cf14000SStefano Zampini   /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */
715f4bdf6c4SBarry Smith   iupper[0] += ilower[0] - 1;
716f4bdf6c4SBarry Smith   iupper[1] += ilower[1] - 1;
717f4bdf6c4SBarry Smith   iupper[2] += ilower[2] - 1;
7182cf14000SStefano Zampini   hlower[0] = (HYPRE_Int)ilower[0];
7192cf14000SStefano Zampini   hlower[1] = (HYPRE_Int)ilower[1];
7202cf14000SStefano Zampini   hlower[2] = (HYPRE_Int)ilower[2];
7212cf14000SStefano Zampini   hupper[0] = (HYPRE_Int)iupper[0];
7222cf14000SStefano Zampini   hupper[1] = (HYPRE_Int)iupper[1];
7232cf14000SStefano Zampini   hupper[2] = (HYPRE_Int)iupper[2];
724f4bdf6c4SBarry Smith 
725f4bdf6c4SBarry Smith   size = 1;
7268865f1eaSKarl Rupp   for (i = 0; i < 3; i++) size *= (iupper[i] - ilower[i] + 1);
727f4bdf6c4SBarry Smith 
728f4bdf6c4SBarry Smith   /* copy x values over to hypre for variable ordering */
729f4bdf6c4SBarry Smith   if (ordering) {
730a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_SStructVectorSetConstantValues(mx->ss_b, 0.0));
7319566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
732f2f41e48SZach Atkins     for (i = 0; i < nvars; i++) PetscCallHYPRE(HYPRE_SStructVectorSetBoxValues(mx->ss_b, part, hlower, hupper, (HYPRE_Int)i, (HYPRE_Complex *)(xx + (size * i))));
7339566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
734a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_SStructVectorAssemble(mx->ss_b));
735a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_SStructMatrixMatvec(1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x));
736f4bdf6c4SBarry Smith 
737f4bdf6c4SBarry Smith     /* copy solution values back to PETSc */
7389566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
739f2f41e48SZach Atkins     for (i = 0; i < nvars; i++) PetscCallHYPRE(HYPRE_SStructVectorGetBoxValues(mx->ss_x, part, hlower, hupper, (HYPRE_Int)i, (HYPRE_Complex *)(yy + (size * i))));
7409566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
741f4bdf6c4SBarry Smith   } else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */
742f4bdf6c4SBarry Smith     PetscScalar *z;
7434ddd07fcSJed Brown     PetscInt     j, k;
744f4bdf6c4SBarry Smith 
7459566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nvars * size, &z));
746a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_SStructVectorSetConstantValues(mx->ss_b, 0.0));
7479566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(x, &xx));
748f4bdf6c4SBarry Smith 
749f4bdf6c4SBarry Smith     /* transform nodal to hypre's variable ordering for sys_pfmg */
750f4bdf6c4SBarry Smith     for (i = 0; i < size; i++) {
751f4bdf6c4SBarry Smith       k = i * nvars;
7528865f1eaSKarl Rupp       for (j = 0; j < nvars; j++) z[j * size + i] = xx[k + j];
753f4bdf6c4SBarry Smith     }
754f2f41e48SZach Atkins     for (i = 0; i < nvars; i++) PetscCallHYPRE(HYPRE_SStructVectorSetBoxValues(mx->ss_b, part, hlower, hupper, (HYPRE_Int)i, (HYPRE_Complex *)(z + (size * i))));
7559566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(x, &xx));
756a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_SStructVectorAssemble(mx->ss_b));
757a333fa2bSZach Atkins     PetscCallHYPRE(HYPRE_SStructMatrixMatvec(1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x));
758f4bdf6c4SBarry Smith 
759f4bdf6c4SBarry Smith     /* copy solution values back to PETSc */
7609566063dSJacob Faibussowitsch     PetscCall(VecGetArray(y, &yy));
761f2f41e48SZach Atkins     for (i = 0; i < nvars; i++) PetscCallHYPRE(HYPRE_SStructVectorGetBoxValues(mx->ss_x, part, hlower, hupper, (HYPRE_Int)i, (HYPRE_Complex *)(z + (size * i))));
762f4bdf6c4SBarry Smith     /* transform hypre's variable ordering for sys_pfmg to nodal ordering */
763f4bdf6c4SBarry Smith     for (i = 0; i < size; i++) {
764f4bdf6c4SBarry Smith       k = i * nvars;
7658865f1eaSKarl Rupp       for (j = 0; j < nvars; j++) yy[k + j] = z[j * size + i];
766f4bdf6c4SBarry Smith     }
7679566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(y, &yy));
7689566063dSJacob Faibussowitsch     PetscCall(PetscFree(z));
769f4bdf6c4SBarry Smith   }
7703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
771f4bdf6c4SBarry Smith }
772f4bdf6c4SBarry Smith 
MatAssemblyEnd_HYPRESStruct(Mat mat,MatAssemblyType mode)77366976f2fSJacob Faibussowitsch static PetscErrorCode MatAssemblyEnd_HYPRESStruct(Mat mat, MatAssemblyType mode)
774d71ae5a4SJacob Faibussowitsch {
775f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex = (Mat_HYPRESStruct *)mat->data;
776f4bdf6c4SBarry Smith 
777f4bdf6c4SBarry Smith   PetscFunctionBegin;
778a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructMatrixAssemble(ex->ss_mat));
7793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
780f4bdf6c4SBarry Smith }
781f4bdf6c4SBarry Smith 
MatZeroEntries_HYPRESStruct(Mat mat)78266976f2fSJacob Faibussowitsch static PetscErrorCode MatZeroEntries_HYPRESStruct(Mat mat)
783d71ae5a4SJacob Faibussowitsch {
784f4bdf6c4SBarry Smith   PetscFunctionBegin;
785f4bdf6c4SBarry Smith   /* before the DMDA is set to the matrix the zero doesn't need to do anything */
7863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
787f4bdf6c4SBarry Smith }
788f4bdf6c4SBarry Smith 
MatDestroy_HYPRESStruct(Mat mat)78966976f2fSJacob Faibussowitsch static PetscErrorCode MatDestroy_HYPRESStruct(Mat mat)
790d71ae5a4SJacob Faibussowitsch {
791f4bdf6c4SBarry Smith   Mat_HYPRESStruct      *ex = (Mat_HYPRESStruct *)mat->data;
792d94fc0b6SBarry Smith   ISLocalToGlobalMapping ltog;
793f4bdf6c4SBarry Smith 
794f4bdf6c4SBarry Smith   PetscFunctionBegin;
7959566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(ex->da, &ltog));
7969566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingRestoreIndices(ltog, (const PetscInt **)&ex->gindices));
797a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructGraphDestroy(ex->ss_graph));
798a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructMatrixDestroy(ex->ss_mat));
799a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructVectorDestroy(ex->ss_x));
800a333fa2bSZach Atkins   PetscCallHYPRE(HYPRE_SStructVectorDestroy(ex->ss_b));
8019566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)ex->da));
802f4f49eeaSPierre Jolivet   PetscCallMPI(MPI_Comm_free(&ex->hcomm));
8039566063dSJacob Faibussowitsch   PetscCall(PetscFree(ex));
8043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
805f4bdf6c4SBarry Smith }
806f4bdf6c4SBarry Smith 
MatCreate_HYPRESStruct(Mat B)807d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode MatCreate_HYPRESStruct(Mat B)
808d71ae5a4SJacob Faibussowitsch {
809f4bdf6c4SBarry Smith   Mat_HYPRESStruct *ex;
810f4bdf6c4SBarry Smith 
811f4bdf6c4SBarry Smith   PetscFunctionBegin;
8124dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&ex));
813f4bdf6c4SBarry Smith   B->data      = (void *)ex;
814f4bdf6c4SBarry Smith   B->rmap->bs  = 1;
815f4bdf6c4SBarry Smith   B->assembled = PETSC_FALSE;
816f4bdf6c4SBarry Smith 
817f4bdf6c4SBarry Smith   B->insertmode = NOT_SET_VALUES;
818f4bdf6c4SBarry Smith 
819f4bdf6c4SBarry Smith   B->ops->assemblyend = MatAssemblyEnd_HYPRESStruct;
820f4bdf6c4SBarry Smith   B->ops->mult        = MatMult_HYPRESStruct;
821f4bdf6c4SBarry Smith   B->ops->zeroentries = MatZeroEntries_HYPRESStruct;
822f4bdf6c4SBarry Smith   B->ops->destroy     = MatDestroy_HYPRESStruct;
82359cb773eSBarry Smith   B->ops->setup       = MatSetUp_HYPRESStruct;
824f4bdf6c4SBarry Smith 
825f4bdf6c4SBarry Smith   ex->needsinitialization = PETSC_TRUE;
826f4bdf6c4SBarry Smith 
827f4f49eeaSPierre Jolivet   PetscCallMPI(MPI_Comm_dup(PetscObjectComm((PetscObject)B), &ex->hcomm));
8289566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRESSTRUCT));
829*5482091fSJunchao Zhang   PetscCall(PetscHYPREInitialize());
8303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
831f4bdf6c4SBarry Smith }
832