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, <og));
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, <og));
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, <og));
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