1f4bdf6c4SBarry Smith 2f4bdf6c4SBarry Smith /* 3f4bdf6c4SBarry Smith Creates hypre ijmatrix from PETSc matrix 4f4bdf6c4SBarry Smith */ 5c6db04a5SJed Brown #include <petscsys.h> 639accc25SStefano Zampini #include <petsc/private/petschypre.h> 7af0996ceSBarry Smith #include <petsc/private/matimpl.h> 8c6db04a5SJed Brown #include <petscdmda.h> /*I "petscdmda.h" I*/ 9c6db04a5SJed Brown #include <../src/dm/impls/da/hypre/mhyp.h> 10f4bdf6c4SBarry Smith 11f4bdf6c4SBarry Smith /* -----------------------------------------------------------------------------------------------------------------*/ 12f4bdf6c4SBarry Smith 13f4bdf6c4SBarry Smith /*MC 14f4bdf6c4SBarry Smith MATHYPRESTRUCT - MATHYPRESTRUCT = "hyprestruct" - A matrix type to be used for parallel sparse matrices 15f4bdf6c4SBarry Smith based on the hypre HYPRE_StructMatrix. 16f4bdf6c4SBarry Smith 17f4bdf6c4SBarry Smith Level: intermediate 18f4bdf6c4SBarry Smith 1995452b02SPatrick Sanan Notes: 2095452b02SPatrick Sanan Unlike the more general support for blocks in hypre this allows only one block per process and requires the block 21f4bdf6c4SBarry Smith be defined by a DMDA. 22f4bdf6c4SBarry Smith 2359cb773eSBarry Smith The matrix needs a DMDA associated with it by either a call to MatSetDM() or if the matrix is obtained from DMCreateMatrix() 24f4bdf6c4SBarry Smith 25db781477SPatrick Sanan .seealso: `MatCreate()`, `PCPFMG`, `MatSetDM()`, `DMCreateMatrix()` 26f4bdf6c4SBarry Smith M*/ 27f4bdf6c4SBarry Smith 289371c9d4SSatish Balay PetscErrorCode MatSetValuesLocal_HYPREStruct_3d(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) { 2976a007c6Sftrigaux HYPRE_Int index[3], entries[9]; 302cf14000SStefano Zampini PetscInt i, j, stencil, row; 3139accc25SStefano Zampini HYPRE_Complex *values = (HYPRE_Complex *)y; 32f4bdf6c4SBarry Smith Mat_HYPREStruct *ex = (Mat_HYPREStruct *)mat->data; 33f4bdf6c4SBarry Smith 34f4bdf6c4SBarry Smith PetscFunctionBegin; 3576a007c6Sftrigaux PetscCheck(ncol <= 9, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "ncol %" PetscInt_FMT " > 9 too large", ncol); 36f4bdf6c4SBarry Smith for (i = 0; i < nrow; i++) { 37f4bdf6c4SBarry Smith for (j = 0; j < ncol; j++) { 38f4bdf6c4SBarry Smith stencil = icol[j] - irow[i]; 39f4bdf6c4SBarry Smith if (!stencil) { 40f4bdf6c4SBarry Smith entries[j] = 3; 41f4bdf6c4SBarry Smith } else if (stencil == -1) { 42f4bdf6c4SBarry Smith entries[j] = 2; 43f4bdf6c4SBarry Smith } else if (stencil == 1) { 44f4bdf6c4SBarry Smith entries[j] = 4; 45f4bdf6c4SBarry Smith } else if (stencil == -ex->gnx) { 46f4bdf6c4SBarry Smith entries[j] = 1; 47f4bdf6c4SBarry Smith } else if (stencil == ex->gnx) { 48f4bdf6c4SBarry Smith entries[j] = 5; 49f4bdf6c4SBarry Smith } else if (stencil == -ex->gnxgny) { 50f4bdf6c4SBarry Smith entries[j] = 0; 51f4bdf6c4SBarry Smith } else if (stencil == ex->gnxgny) { 52f4bdf6c4SBarry Smith entries[j] = 6; 5363a3b9bcSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Local row %" PetscInt_FMT " local column %" PetscInt_FMT " have bad stencil %" PetscInt_FMT, irow[i], icol[j], stencil); 54f4bdf6c4SBarry Smith } 55f4bdf6c4SBarry Smith row = ex->gindices[irow[i]] - ex->rstart; 562cf14000SStefano Zampini index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx)); 572cf14000SStefano Zampini index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny)); 582cf14000SStefano Zampini index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny))); 59792fecdfSBarry Smith if (addv == ADD_VALUES) PetscCallExternal(HYPRE_StructMatrixAddToValues, ex->hmat, index, ncol, entries, values); 60792fecdfSBarry Smith else PetscCallExternal(HYPRE_StructMatrixSetValues, ex->hmat, index, ncol, entries, values); 61f4bdf6c4SBarry Smith values += ncol; 62f4bdf6c4SBarry Smith } 63f4bdf6c4SBarry Smith PetscFunctionReturn(0); 64f4bdf6c4SBarry Smith } 65f4bdf6c4SBarry Smith 669371c9d4SSatish Balay PetscErrorCode MatZeroRowsLocal_HYPREStruct_3d(Mat mat, PetscInt nrow, const PetscInt irow[], PetscScalar d, Vec x, Vec b) { 672cf14000SStefano Zampini HYPRE_Int index[3], entries[7] = {0, 1, 2, 3, 4, 5, 6}; 682cf14000SStefano Zampini PetscInt row, i; 6939accc25SStefano Zampini HYPRE_Complex values[7]; 70f4bdf6c4SBarry Smith Mat_HYPREStruct *ex = (Mat_HYPREStruct *)mat->data; 71f4bdf6c4SBarry Smith 72f4bdf6c4SBarry Smith PetscFunctionBegin; 7308401ef6SPierre Jolivet PetscCheck(!x || !b, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "No support"); 749566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(values, 7)); 759566063dSJacob Faibussowitsch PetscCall(PetscHYPREScalarCast(d, &values[3])); 76f4bdf6c4SBarry Smith for (i = 0; i < nrow; i++) { 77f4bdf6c4SBarry Smith row = ex->gindices[irow[i]] - ex->rstart; 782cf14000SStefano Zampini index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx)); 792cf14000SStefano Zampini index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny)); 802cf14000SStefano Zampini index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny))); 81792fecdfSBarry Smith PetscCallExternal(HYPRE_StructMatrixSetValues, ex->hmat, index, 7, entries, values); 82f4bdf6c4SBarry Smith } 83792fecdfSBarry Smith PetscCallExternal(HYPRE_StructMatrixAssemble, ex->hmat); 84f4bdf6c4SBarry Smith PetscFunctionReturn(0); 85f4bdf6c4SBarry Smith } 86f4bdf6c4SBarry Smith 879371c9d4SSatish Balay PetscErrorCode MatZeroEntries_HYPREStruct_3d(Mat mat) { 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 */ 93792fecdfSBarry Smith PetscCallExternal(hypre_StructMatrixClearBoxValues, ex->hmat, &ex->hbox, 7, indices, 0, 1); 94792fecdfSBarry Smith PetscCallExternal(HYPRE_StructMatrixAssemble, ex->hmat); 95f4bdf6c4SBarry Smith PetscFunctionReturn(0); 96f4bdf6c4SBarry Smith } 97f4bdf6c4SBarry Smith 989371c9d4SSatish Balay static PetscErrorCode MatSetUp_HYPREStruct(Mat mat) { 99f4bdf6c4SBarry Smith Mat_HYPREStruct *ex = (Mat_HYPREStruct *)mat->data; 1002cf14000SStefano Zampini HYPRE_Int sw[6]; 101e33d7e95Sftrigaux HYPRE_Int hlower[3], hupper[3], period[3] = {0, 0, 0}; 102e33d7e95Sftrigaux PetscInt dim, dof, psw, Nx, Ny, Nz, nx, ny, nz, ilower[3], iupper[3], ssize, i; 103bff4a2f0SMatthew G. Knepley DMBoundaryType px, py, pz; 104f4bdf6c4SBarry Smith DMDAStencilType st; 105565245c5SBarry Smith ISLocalToGlobalMapping ltog; 10659cb773eSBarry Smith DM da; 107f4bdf6c4SBarry Smith 108f4bdf6c4SBarry Smith PetscFunctionBegin; 1099566063dSJacob Faibussowitsch PetscCall(MatGetDM(mat, (DM *)&da)); 110f4bdf6c4SBarry Smith ex->da = da; 1119566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)da)); 112f4bdf6c4SBarry Smith 113e33d7e95Sftrigaux PetscCall(DMDAGetInfo(ex->da, &dim, &Nx, &Ny, &Nz, 0, 0, 0, &dof, &psw, &px, &py, &pz, &st)); 1149566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(ex->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2])); 1152cf14000SStefano Zampini 1162cf14000SStefano Zampini /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */ 117f4bdf6c4SBarry Smith iupper[0] += ilower[0] - 1; 118f4bdf6c4SBarry Smith iupper[1] += ilower[1] - 1; 119f4bdf6c4SBarry Smith iupper[2] += ilower[2] - 1; 1202cf14000SStefano Zampini hlower[0] = (HYPRE_Int)ilower[0]; 1212cf14000SStefano Zampini hlower[1] = (HYPRE_Int)ilower[1]; 1222cf14000SStefano Zampini hlower[2] = (HYPRE_Int)ilower[2]; 1232cf14000SStefano Zampini hupper[0] = (HYPRE_Int)iupper[0]; 1242cf14000SStefano Zampini hupper[1] = (HYPRE_Int)iupper[1]; 1252cf14000SStefano Zampini hupper[2] = (HYPRE_Int)iupper[2]; 126f4bdf6c4SBarry Smith 127f4bdf6c4SBarry Smith /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */ 1282cf14000SStefano Zampini ex->hbox.imin[0] = hlower[0]; 1292cf14000SStefano Zampini ex->hbox.imin[1] = hlower[1]; 1302cf14000SStefano Zampini ex->hbox.imin[2] = hlower[2]; 1312cf14000SStefano Zampini ex->hbox.imax[0] = hupper[0]; 1322cf14000SStefano Zampini ex->hbox.imax[1] = hupper[1]; 1332cf14000SStefano Zampini ex->hbox.imax[2] = hupper[2]; 134f4bdf6c4SBarry Smith 135f4bdf6c4SBarry Smith /* create the hypre grid object and set its information */ 13608401ef6SPierre Jolivet PetscCheck(dof <= 1, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Currently only support for scalar problems"); 137e33d7e95Sftrigaux if (px || py || pz) { 138e33d7e95Sftrigaux if (px == DM_BOUNDARY_PERIODIC) period[0] = (HYPRE_Int)Nx; 139e33d7e95Sftrigaux if (py == DM_BOUNDARY_PERIODIC) period[1] = (HYPRE_Int)Ny; 140e33d7e95Sftrigaux if (pz == DM_BOUNDARY_PERIODIC) period[2] = (HYPRE_Int)Nz; 141e33d7e95Sftrigaux } 142792fecdfSBarry Smith PetscCallExternal(HYPRE_StructGridCreate, ex->hcomm, dim, &ex->hgrid); 143792fecdfSBarry Smith PetscCallExternal(HYPRE_StructGridSetExtents, ex->hgrid, hlower, hupper); 144e33d7e95Sftrigaux PetscCallExternal(HYPRE_StructGridSetPeriodic, ex->hgrid, period); 145792fecdfSBarry Smith PetscCallExternal(HYPRE_StructGridAssemble, ex->hgrid); 146f4bdf6c4SBarry Smith 1472cf14000SStefano Zampini sw[5] = sw[4] = sw[3] = sw[2] = sw[1] = sw[0] = psw; 148792fecdfSBarry Smith PetscCallExternal(HYPRE_StructGridSetNumGhost, ex->hgrid, sw); 149f4bdf6c4SBarry Smith 150f4bdf6c4SBarry Smith /* create the hypre stencil object and set its information */ 15108401ef6SPierre Jolivet PetscCheck(sw[0] <= 1, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add support for wider stencils"); 15208401ef6SPierre Jolivet PetscCheck(st != DMDA_STENCIL_BOX, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add support for box stencils"); 153f4bdf6c4SBarry Smith if (dim == 1) { 1542cf14000SStefano Zampini HYPRE_Int offsets[3][1] = {{-1}, {0}, {1}}; 155f4bdf6c4SBarry Smith ssize = 3; 156792fecdfSBarry Smith PetscCallExternal(HYPRE_StructStencilCreate, dim, ssize, &ex->hstencil); 15748a46eb9SPierre Jolivet for (i = 0; i < ssize; i++) PetscCallExternal(HYPRE_StructStencilSetElement, ex->hstencil, i, offsets[i]); 158f4bdf6c4SBarry Smith } else if (dim == 2) { 1599371c9d4SSatish Balay HYPRE_Int offsets[5][2] = { 1609371c9d4SSatish Balay {0, -1}, 1619371c9d4SSatish Balay {-1, 0 }, 1629371c9d4SSatish Balay {0, 0 }, 1639371c9d4SSatish Balay {1, 0 }, 1649371c9d4SSatish Balay {0, 1 } 1659371c9d4SSatish Balay }; 166f4bdf6c4SBarry Smith ssize = 5; 167792fecdfSBarry Smith PetscCallExternal(HYPRE_StructStencilCreate, dim, ssize, &ex->hstencil); 16848a46eb9SPierre Jolivet for (i = 0; i < ssize; i++) PetscCallExternal(HYPRE_StructStencilSetElement, ex->hstencil, i, offsets[i]); 169f4bdf6c4SBarry Smith } else if (dim == 3) { 1709371c9d4SSatish Balay HYPRE_Int offsets[7][3] = { 1719371c9d4SSatish Balay {0, 0, -1}, 1729371c9d4SSatish Balay {0, -1, 0 }, 1739371c9d4SSatish Balay {-1, 0, 0 }, 1749371c9d4SSatish Balay {0, 0, 0 }, 1759371c9d4SSatish Balay {1, 0, 0 }, 1769371c9d4SSatish Balay {0, 1, 0 }, 1779371c9d4SSatish Balay {0, 0, 1 } 1789371c9d4SSatish Balay }; 179f4bdf6c4SBarry Smith ssize = 7; 180792fecdfSBarry Smith PetscCallExternal(HYPRE_StructStencilCreate, dim, ssize, &ex->hstencil); 18148a46eb9SPierre Jolivet for (i = 0; i < ssize; i++) PetscCallExternal(HYPRE_StructStencilSetElement, ex->hstencil, i, offsets[i]); 182f4bdf6c4SBarry Smith } 183f4bdf6c4SBarry Smith 184f4bdf6c4SBarry Smith /* create the HYPRE vector for rhs and solution */ 185792fecdfSBarry Smith PetscCallExternal(HYPRE_StructVectorCreate, ex->hcomm, ex->hgrid, &ex->hb); 186792fecdfSBarry Smith PetscCallExternal(HYPRE_StructVectorCreate, ex->hcomm, ex->hgrid, &ex->hx); 187792fecdfSBarry Smith PetscCallExternal(HYPRE_StructVectorInitialize, ex->hb); 188792fecdfSBarry Smith PetscCallExternal(HYPRE_StructVectorInitialize, ex->hx); 189792fecdfSBarry Smith PetscCallExternal(HYPRE_StructVectorAssemble, ex->hb); 190792fecdfSBarry Smith PetscCallExternal(HYPRE_StructVectorAssemble, ex->hx); 191f4bdf6c4SBarry Smith 192f4bdf6c4SBarry Smith /* create the hypre matrix object and set its information */ 193792fecdfSBarry Smith PetscCallExternal(HYPRE_StructMatrixCreate, ex->hcomm, ex->hgrid, ex->hstencil, &ex->hmat); 194792fecdfSBarry Smith PetscCallExternal(HYPRE_StructGridDestroy, ex->hgrid); 195792fecdfSBarry Smith PetscCallExternal(HYPRE_StructStencilDestroy, ex->hstencil); 196f4bdf6c4SBarry Smith if (ex->needsinitialization) { 197792fecdfSBarry Smith PetscCallExternal(HYPRE_StructMatrixInitialize, ex->hmat); 198f4bdf6c4SBarry Smith ex->needsinitialization = PETSC_FALSE; 199f4bdf6c4SBarry Smith } 200f4bdf6c4SBarry Smith 201f4bdf6c4SBarry Smith /* set the global and local sizes of the matrix */ 2029566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, 0, 0, 0, &nx, &ny, &nz)); 2039566063dSJacob Faibussowitsch PetscCall(MatSetSizes(mat, dof * nx * ny * nz, dof * nx * ny * nz, PETSC_DECIDE, PETSC_DECIDE)); 2049566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(mat->rmap, 1)); 2059566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(mat->cmap, 1)); 2069566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(mat->rmap)); 2079566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(mat->cmap)); 20859cb773eSBarry Smith mat->preallocated = PETSC_TRUE; 209f4bdf6c4SBarry Smith 210f4bdf6c4SBarry Smith if (dim == 3) { 211f4bdf6c4SBarry Smith mat->ops->setvalueslocal = MatSetValuesLocal_HYPREStruct_3d; 212f4bdf6c4SBarry Smith mat->ops->zerorowslocal = MatZeroRowsLocal_HYPREStruct_3d; 213f4bdf6c4SBarry Smith mat->ops->zeroentries = MatZeroEntries_HYPREStruct_3d; 2148865f1eaSKarl Rupp 2159566063dSJacob Faibussowitsch /* PetscCall(MatZeroEntries_HYPREStruct_3d(mat)); */ 216ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Only support for 3d DMDA currently"); 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; 226f4bdf6c4SBarry Smith PetscFunctionReturn(0); 227f4bdf6c4SBarry Smith } 228f4bdf6c4SBarry Smith 2299371c9d4SSatish Balay PetscErrorCode MatMult_HYPREStruct(Mat A, Vec x, Vec y) { 230b026d285SBarry Smith const PetscScalar *xx; 231b026d285SBarry Smith PetscScalar *yy; 2324ddd07fcSJed Brown PetscInt ilower[3], iupper[3]; 2332cf14000SStefano Zampini HYPRE_Int hlower[3], hupper[3]; 234f4bdf6c4SBarry Smith Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(A->data); 235f4bdf6c4SBarry Smith 236f4bdf6c4SBarry Smith PetscFunctionBegin; 2379566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2])); 2382cf14000SStefano Zampini /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */ 239f4bdf6c4SBarry Smith iupper[0] += ilower[0] - 1; 240f4bdf6c4SBarry Smith iupper[1] += ilower[1] - 1; 241f4bdf6c4SBarry Smith iupper[2] += ilower[2] - 1; 2422cf14000SStefano Zampini hlower[0] = (HYPRE_Int)ilower[0]; 2432cf14000SStefano Zampini hlower[1] = (HYPRE_Int)ilower[1]; 2442cf14000SStefano Zampini hlower[2] = (HYPRE_Int)ilower[2]; 2452cf14000SStefano Zampini hupper[0] = (HYPRE_Int)iupper[0]; 2462cf14000SStefano Zampini hupper[1] = (HYPRE_Int)iupper[1]; 2472cf14000SStefano Zampini hupper[2] = (HYPRE_Int)iupper[2]; 248f4bdf6c4SBarry Smith 249f4bdf6c4SBarry Smith /* copy x values over to hypre */ 250792fecdfSBarry Smith PetscCallExternal(HYPRE_StructVectorSetConstantValues, mx->hb, 0.0); 2519566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &xx)); 252792fecdfSBarry Smith PetscCallExternal(HYPRE_StructVectorSetBoxValues, mx->hb, hlower, hupper, (HYPRE_Complex *)xx); 2539566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &xx)); 254792fecdfSBarry Smith PetscCallExternal(HYPRE_StructVectorAssemble, mx->hb); 255792fecdfSBarry Smith PetscCallExternal(HYPRE_StructMatrixMatvec, 1.0, mx->hmat, mx->hb, 0.0, mx->hx); 256f4bdf6c4SBarry Smith 257f4bdf6c4SBarry Smith /* copy solution values back to PETSc */ 2589566063dSJacob Faibussowitsch PetscCall(VecGetArray(y, &yy)); 259792fecdfSBarry Smith PetscCallExternal(HYPRE_StructVectorGetBoxValues, mx->hx, hlower, hupper, (HYPRE_Complex *)yy); 2609566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(y, &yy)); 261f4bdf6c4SBarry Smith PetscFunctionReturn(0); 262f4bdf6c4SBarry Smith } 263f4bdf6c4SBarry Smith 2649371c9d4SSatish Balay PetscErrorCode MatAssemblyEnd_HYPREStruct(Mat mat, MatAssemblyType mode) { 265f4bdf6c4SBarry Smith Mat_HYPREStruct *ex = (Mat_HYPREStruct *)mat->data; 266f4bdf6c4SBarry Smith 267f4bdf6c4SBarry Smith PetscFunctionBegin; 268792fecdfSBarry Smith PetscCallExternal(HYPRE_StructMatrixAssemble, ex->hmat); 269792fecdfSBarry Smith /* PetscCallExternal(HYPRE_StructMatrixPrint,"dummy",ex->hmat,0); */ 270f4bdf6c4SBarry Smith PetscFunctionReturn(0); 271f4bdf6c4SBarry Smith } 272f4bdf6c4SBarry Smith 2739371c9d4SSatish Balay PetscErrorCode MatZeroEntries_HYPREStruct(Mat mat) { 274f4bdf6c4SBarry Smith PetscFunctionBegin; 275f4bdf6c4SBarry Smith /* before the DMDA is set to the matrix the zero doesn't need to do anything */ 276f4bdf6c4SBarry Smith PetscFunctionReturn(0); 277f4bdf6c4SBarry Smith } 278f4bdf6c4SBarry Smith 2799371c9d4SSatish Balay PetscErrorCode MatDestroy_HYPREStruct(Mat mat) { 280f4bdf6c4SBarry Smith Mat_HYPREStruct *ex = (Mat_HYPREStruct *)mat->data; 281f4bdf6c4SBarry Smith 282f4bdf6c4SBarry Smith PetscFunctionBegin; 283792fecdfSBarry Smith PetscCallExternal(HYPRE_StructMatrixDestroy, ex->hmat); 284792fecdfSBarry Smith PetscCallExternal(HYPRE_StructVectorDestroy, ex->hx); 285792fecdfSBarry Smith PetscCallExternal(HYPRE_StructVectorDestroy, ex->hb); 2869566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)ex->da)); 2879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free(&(ex->hcomm))); 2889566063dSJacob Faibussowitsch PetscCall(PetscFree(ex)); 289f4bdf6c4SBarry Smith PetscFunctionReturn(0); 290f4bdf6c4SBarry Smith } 291f4bdf6c4SBarry Smith 2929371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatCreate_HYPREStruct(Mat B) { 293f4bdf6c4SBarry Smith Mat_HYPREStruct *ex; 294f4bdf6c4SBarry Smith 295f4bdf6c4SBarry Smith PetscFunctionBegin; 296*4dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&ex)); 297f4bdf6c4SBarry Smith B->data = (void *)ex; 298f4bdf6c4SBarry Smith B->rmap->bs = 1; 299f4bdf6c4SBarry Smith B->assembled = PETSC_FALSE; 300f4bdf6c4SBarry Smith 301f4bdf6c4SBarry Smith B->insertmode = NOT_SET_VALUES; 302f4bdf6c4SBarry Smith 303f4bdf6c4SBarry Smith B->ops->assemblyend = MatAssemblyEnd_HYPREStruct; 304f4bdf6c4SBarry Smith B->ops->mult = MatMult_HYPREStruct; 305f4bdf6c4SBarry Smith B->ops->zeroentries = MatZeroEntries_HYPREStruct; 306f4bdf6c4SBarry Smith B->ops->destroy = MatDestroy_HYPREStruct; 30759cb773eSBarry Smith B->ops->setup = MatSetUp_HYPREStruct; 308f4bdf6c4SBarry Smith 309f4bdf6c4SBarry Smith ex->needsinitialization = PETSC_TRUE; 310f4bdf6c4SBarry Smith 3119566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_dup(PetscObjectComm((PetscObject)B), &(ex->hcomm))); 3129566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRESTRUCT)); 313f4bdf6c4SBarry Smith PetscFunctionReturn(0); 314f4bdf6c4SBarry Smith } 315f4bdf6c4SBarry Smith 316f4bdf6c4SBarry Smith /*MC 317f4bdf6c4SBarry Smith MATHYPRESSTRUCT - MATHYPRESSTRUCT = "hypresstruct" - A matrix type to be used for parallel sparse matrices 318f4bdf6c4SBarry Smith based on the hypre HYPRE_SStructMatrix. 319f4bdf6c4SBarry Smith 320f4bdf6c4SBarry Smith Level: intermediate 321f4bdf6c4SBarry Smith 32295452b02SPatrick Sanan Notes: 32395452b02SPatrick Sanan Unlike hypre's general semi-struct object consisting of a collection of structured-grid objects and unstructured 324b026d285SBarry Smith grid objects, we restrict the semi-struct objects to consist of only structured-grid components. 325f4bdf6c4SBarry Smith 326f4bdf6c4SBarry 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 327f4bdf6c4SBarry Smith be defined by a DMDA. 328f4bdf6c4SBarry Smith 32959cb773eSBarry Smith The matrix needs a DMDA associated with it by either a call to MatSetDM() or if the matrix is obtained from DMCreateMatrix() 330f4bdf6c4SBarry Smith 331f4bdf6c4SBarry Smith M*/ 332f4bdf6c4SBarry Smith 3339371c9d4SSatish Balay PetscErrorCode MatSetValuesLocal_HYPRESStruct_3d(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) { 3342cf14000SStefano Zampini HYPRE_Int index[3], *entries; 3352cf14000SStefano Zampini PetscInt i, j, stencil; 33639accc25SStefano Zampini HYPRE_Complex *values = (HYPRE_Complex *)y; 337f4bdf6c4SBarry Smith Mat_HYPRESStruct *ex = (Mat_HYPRESStruct *)mat->data; 338f4bdf6c4SBarry Smith 3394ddd07fcSJed Brown PetscInt part = 0; /* Petsc sstruct interface only allows 1 part */ 3404ddd07fcSJed Brown PetscInt ordering; 3414ddd07fcSJed Brown PetscInt grid_rank, to_grid_rank; 3424ddd07fcSJed Brown PetscInt var_type, to_var_type; 3434ddd07fcSJed Brown PetscInt to_var_entry = 0; 3444ddd07fcSJed Brown PetscInt nvars = ex->nvars; 3452cf14000SStefano Zampini PetscInt row; 346f4bdf6c4SBarry Smith 347f4bdf6c4SBarry Smith PetscFunctionBegin; 3489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(7 * nvars, &entries)); 349f4bdf6c4SBarry Smith ordering = ex->dofs_order; /* ordering= 0 nodal ordering 350f4bdf6c4SBarry Smith 1 variable ordering */ 35161710fbeSStefano Zampini /* stencil entries are ordered by variables: var0_stencil0, var0_stencil1, ..., var0_stencil6, var1_stencil0, var1_stencil1, ... */ 352f4bdf6c4SBarry Smith if (!ordering) { 353f4bdf6c4SBarry Smith for (i = 0; i < nrow; i++) { 354f4bdf6c4SBarry Smith grid_rank = irow[i] / nvars; 355f4bdf6c4SBarry Smith var_type = (irow[i] % nvars); 356f4bdf6c4SBarry Smith 357f4bdf6c4SBarry Smith for (j = 0; j < ncol; j++) { 358f4bdf6c4SBarry Smith to_grid_rank = icol[j] / nvars; 359f4bdf6c4SBarry Smith to_var_type = (icol[j] % nvars); 360f4bdf6c4SBarry Smith 361f4bdf6c4SBarry Smith to_var_entry = to_var_entry * 7; 362f4bdf6c4SBarry Smith entries[j] = to_var_entry; 363f4bdf6c4SBarry Smith 364f4bdf6c4SBarry Smith stencil = to_grid_rank - grid_rank; 365f4bdf6c4SBarry Smith if (!stencil) { 366f4bdf6c4SBarry Smith entries[j] += 3; 367f4bdf6c4SBarry Smith } else if (stencil == -1) { 368f4bdf6c4SBarry Smith entries[j] += 2; 369f4bdf6c4SBarry Smith } else if (stencil == 1) { 370f4bdf6c4SBarry Smith entries[j] += 4; 371f4bdf6c4SBarry Smith } else if (stencil == -ex->gnx) { 372f4bdf6c4SBarry Smith entries[j] += 1; 373f4bdf6c4SBarry Smith } else if (stencil == ex->gnx) { 374f4bdf6c4SBarry Smith entries[j] += 5; 375f4bdf6c4SBarry Smith } else if (stencil == -ex->gnxgny) { 376f4bdf6c4SBarry Smith entries[j] += 0; 377f4bdf6c4SBarry Smith } else if (stencil == ex->gnxgny) { 378f4bdf6c4SBarry Smith entries[j] += 6; 37963a3b9bcSJacob 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); 380f4bdf6c4SBarry Smith } 381f4bdf6c4SBarry Smith 382f4bdf6c4SBarry Smith row = ex->gindices[grid_rank] - ex->rstart; 3832cf14000SStefano Zampini index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx)); 3842cf14000SStefano Zampini index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny)); 3852cf14000SStefano Zampini index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny))); 386f4bdf6c4SBarry Smith 387792fecdfSBarry Smith if (addv == ADD_VALUES) PetscCallExternal(HYPRE_SStructMatrixAddToValues, ex->ss_mat, part, index, var_type, ncol, entries, values); 388792fecdfSBarry Smith else PetscCallExternal(HYPRE_SStructMatrixSetValues, ex->ss_mat, part, index, var_type, ncol, entries, values); 389f4bdf6c4SBarry Smith values += ncol; 390f4bdf6c4SBarry Smith } 391f4bdf6c4SBarry Smith } else { 392f4bdf6c4SBarry Smith for (i = 0; i < nrow; i++) { 393f4bdf6c4SBarry Smith var_type = irow[i] / (ex->gnxgnygnz); 394f4bdf6c4SBarry Smith grid_rank = irow[i] - var_type * (ex->gnxgnygnz); 395f4bdf6c4SBarry Smith 396f4bdf6c4SBarry Smith for (j = 0; j < ncol; j++) { 397f4bdf6c4SBarry Smith to_var_type = icol[j] / (ex->gnxgnygnz); 398f4bdf6c4SBarry Smith to_grid_rank = icol[j] - to_var_type * (ex->gnxgnygnz); 399f4bdf6c4SBarry Smith 400f4bdf6c4SBarry Smith to_var_entry = to_var_entry * 7; 401f4bdf6c4SBarry Smith entries[j] = to_var_entry; 402f4bdf6c4SBarry Smith 403f4bdf6c4SBarry Smith stencil = to_grid_rank - grid_rank; 404f4bdf6c4SBarry Smith if (!stencil) { 405f4bdf6c4SBarry Smith entries[j] += 3; 406f4bdf6c4SBarry Smith } else if (stencil == -1) { 407f4bdf6c4SBarry Smith entries[j] += 2; 408f4bdf6c4SBarry Smith } else if (stencil == 1) { 409f4bdf6c4SBarry Smith entries[j] += 4; 410f4bdf6c4SBarry Smith } else if (stencil == -ex->gnx) { 411f4bdf6c4SBarry Smith entries[j] += 1; 412f4bdf6c4SBarry Smith } else if (stencil == ex->gnx) { 413f4bdf6c4SBarry Smith entries[j] += 5; 414f4bdf6c4SBarry Smith } else if (stencil == -ex->gnxgny) { 415f4bdf6c4SBarry Smith entries[j] += 0; 416f4bdf6c4SBarry Smith } else if (stencil == ex->gnxgny) { 417f4bdf6c4SBarry Smith entries[j] += 6; 41863a3b9bcSJacob 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); 419f4bdf6c4SBarry Smith } 420f4bdf6c4SBarry Smith 421f4bdf6c4SBarry Smith row = ex->gindices[grid_rank] - ex->rstart; 4222cf14000SStefano Zampini index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx)); 4232cf14000SStefano Zampini index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny)); 4242cf14000SStefano Zampini index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny))); 425f4bdf6c4SBarry Smith 426792fecdfSBarry Smith if (addv == ADD_VALUES) PetscCallExternal(HYPRE_SStructMatrixAddToValues, ex->ss_mat, part, index, var_type, ncol, entries, values); 427792fecdfSBarry Smith else PetscCallExternal(HYPRE_SStructMatrixSetValues, ex->ss_mat, part, index, var_type, ncol, entries, values); 428f4bdf6c4SBarry Smith values += ncol; 429f4bdf6c4SBarry Smith } 430f4bdf6c4SBarry Smith } 4319566063dSJacob Faibussowitsch PetscCall(PetscFree(entries)); 432f4bdf6c4SBarry Smith PetscFunctionReturn(0); 433f4bdf6c4SBarry Smith } 434f4bdf6c4SBarry Smith 4359371c9d4SSatish Balay PetscErrorCode MatZeroRowsLocal_HYPRESStruct_3d(Mat mat, PetscInt nrow, const PetscInt irow[], PetscScalar d, Vec x, Vec b) { 4362cf14000SStefano Zampini HYPRE_Int index[3], *entries; 4372cf14000SStefano Zampini PetscInt i; 43839accc25SStefano Zampini HYPRE_Complex **values; 439f4bdf6c4SBarry Smith Mat_HYPRESStruct *ex = (Mat_HYPRESStruct *)mat->data; 440f4bdf6c4SBarry Smith 4414ddd07fcSJed Brown PetscInt part = 0; /* Petsc sstruct interface only allows 1 part */ 4424ddd07fcSJed Brown PetscInt ordering = ex->dofs_order; 4434ddd07fcSJed Brown PetscInt grid_rank; 4444ddd07fcSJed Brown PetscInt var_type; 4454ddd07fcSJed Brown PetscInt nvars = ex->nvars; 4462cf14000SStefano Zampini PetscInt row; 447f4bdf6c4SBarry Smith 448f4bdf6c4SBarry Smith PetscFunctionBegin; 44908401ef6SPierre Jolivet PetscCheck(!x || !b, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "No support"); 4509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(7 * nvars, &entries)); 451f4bdf6c4SBarry Smith 4529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nvars, &values)); 4539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(7 * nvars * nvars, &values[0])); 454ad540459SPierre Jolivet for (i = 1; i < nvars; i++) values[i] = values[i - 1] + nvars * 7; 455f4bdf6c4SBarry Smith 456f4bdf6c4SBarry Smith for (i = 0; i < nvars; i++) { 4579566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(values[i], nvars * 7 * sizeof(HYPRE_Complex))); 4589566063dSJacob Faibussowitsch PetscCall(PetscHYPREScalarCast(d, values[i] + 3)); 459f4bdf6c4SBarry Smith } 460f4bdf6c4SBarry Smith 4618865f1eaSKarl Rupp for (i = 0; i < nvars * 7; i++) entries[i] = i; 462f4bdf6c4SBarry Smith 463f4bdf6c4SBarry Smith if (!ordering) { 464f4bdf6c4SBarry Smith for (i = 0; i < nrow; i++) { 465f4bdf6c4SBarry Smith grid_rank = irow[i] / nvars; 466f4bdf6c4SBarry Smith var_type = (irow[i] % nvars); 467f4bdf6c4SBarry Smith 468f4bdf6c4SBarry Smith row = ex->gindices[grid_rank] - ex->rstart; 4692cf14000SStefano Zampini index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx)); 4702cf14000SStefano Zampini index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny)); 4712cf14000SStefano Zampini index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny))); 472792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructMatrixSetValues, ex->ss_mat, part, index, var_type, 7 * nvars, entries, values[var_type]); 473f4bdf6c4SBarry Smith } 474f4bdf6c4SBarry Smith } else { 475f4bdf6c4SBarry Smith for (i = 0; i < nrow; i++) { 476f4bdf6c4SBarry Smith var_type = irow[i] / (ex->gnxgnygnz); 477f4bdf6c4SBarry Smith grid_rank = irow[i] - var_type * (ex->gnxgnygnz); 478f4bdf6c4SBarry Smith 479f4bdf6c4SBarry Smith row = ex->gindices[grid_rank] - ex->rstart; 4802cf14000SStefano Zampini index[0] = (HYPRE_Int)(ex->xs + (row % ex->nx)); 4812cf14000SStefano Zampini index[1] = (HYPRE_Int)(ex->ys + ((row / ex->nx) % ex->ny)); 4822cf14000SStefano Zampini index[2] = (HYPRE_Int)(ex->zs + (row / (ex->nxny))); 483792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructMatrixSetValues, ex->ss_mat, part, index, var_type, 7 * nvars, entries, values[var_type]); 484f4bdf6c4SBarry Smith } 485f4bdf6c4SBarry Smith } 486792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructMatrixAssemble, ex->ss_mat); 4879566063dSJacob Faibussowitsch PetscCall(PetscFree(values[0])); 4889566063dSJacob Faibussowitsch PetscCall(PetscFree(values)); 4899566063dSJacob Faibussowitsch PetscCall(PetscFree(entries)); 490f4bdf6c4SBarry Smith PetscFunctionReturn(0); 491f4bdf6c4SBarry Smith } 492f4bdf6c4SBarry Smith 4939371c9d4SSatish Balay PetscErrorCode MatZeroEntries_HYPRESStruct_3d(Mat mat) { 494f4bdf6c4SBarry Smith Mat_HYPRESStruct *ex = (Mat_HYPRESStruct *)mat->data; 4954ddd07fcSJed Brown PetscInt nvars = ex->nvars; 4964ddd07fcSJed Brown PetscInt size; 4974ddd07fcSJed Brown PetscInt part = 0; /* only one part */ 498f4bdf6c4SBarry Smith 499f4bdf6c4SBarry Smith PetscFunctionBegin; 500f4bdf6c4SBarry Smith size = ((ex->hbox.imax[0]) - (ex->hbox.imin[0]) + 1) * ((ex->hbox.imax[1]) - (ex->hbox.imin[1]) + 1) * ((ex->hbox.imax[2]) - (ex->hbox.imin[2]) + 1); 501f4bdf6c4SBarry Smith { 5022cf14000SStefano Zampini HYPRE_Int i, *entries, iupper[3], ilower[3]; 50339accc25SStefano Zampini HYPRE_Complex *values; 5044ddd07fcSJed Brown 505f4bdf6c4SBarry Smith for (i = 0; i < 3; i++) { 506f4bdf6c4SBarry Smith ilower[i] = ex->hbox.imin[i]; 507f4bdf6c4SBarry Smith iupper[i] = ex->hbox.imax[i]; 508f4bdf6c4SBarry Smith } 509f4bdf6c4SBarry Smith 5109566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nvars * 7, &entries, nvars * 7 * size, &values)); 5118865f1eaSKarl Rupp for (i = 0; i < nvars * 7; i++) entries[i] = i; 5129566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(values, nvars * 7 * size)); 513f4bdf6c4SBarry Smith 51448a46eb9SPierre Jolivet for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructMatrixSetBoxValues, ex->ss_mat, part, ilower, iupper, i, nvars * 7, entries, values); 5159566063dSJacob Faibussowitsch PetscCall(PetscFree2(entries, values)); 516f4bdf6c4SBarry Smith } 517792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructMatrixAssemble, ex->ss_mat); 518f4bdf6c4SBarry Smith PetscFunctionReturn(0); 519f4bdf6c4SBarry Smith } 520f4bdf6c4SBarry Smith 5219371c9d4SSatish Balay static PetscErrorCode MatSetUp_HYPRESStruct(Mat mat) { 522f4bdf6c4SBarry Smith Mat_HYPRESStruct *ex = (Mat_HYPRESStruct *)mat->data; 523f4bdf6c4SBarry Smith PetscInt dim, dof, sw[3], nx, ny, nz; 5244ddd07fcSJed Brown PetscInt ilower[3], iupper[3], ssize, i; 525bff4a2f0SMatthew G. Knepley DMBoundaryType px, py, pz; 526f4bdf6c4SBarry Smith DMDAStencilType st; 5274ddd07fcSJed Brown PetscInt nparts = 1; /* assuming only one part */ 5284ddd07fcSJed Brown PetscInt part = 0; 529565245c5SBarry Smith ISLocalToGlobalMapping ltog; 53059cb773eSBarry Smith DM da; 531b026d285SBarry Smith 532f4bdf6c4SBarry Smith PetscFunctionBegin; 5339566063dSJacob Faibussowitsch PetscCall(MatGetDM(mat, (DM *)&da)); 534f4bdf6c4SBarry Smith ex->da = da; 5359566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)da)); 536f4bdf6c4SBarry Smith 5379566063dSJacob Faibussowitsch PetscCall(DMDAGetInfo(ex->da, &dim, 0, 0, 0, 0, 0, 0, &dof, &sw[0], &px, &py, &pz, &st)); 5389566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(ex->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2])); 539f4bdf6c4SBarry Smith iupper[0] += ilower[0] - 1; 540f4bdf6c4SBarry Smith iupper[1] += ilower[1] - 1; 541f4bdf6c4SBarry Smith iupper[2] += ilower[2] - 1; 542f4bdf6c4SBarry Smith /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */ 543f4bdf6c4SBarry Smith ex->hbox.imin[0] = ilower[0]; 544f4bdf6c4SBarry Smith ex->hbox.imin[1] = ilower[1]; 545f4bdf6c4SBarry Smith ex->hbox.imin[2] = ilower[2]; 546f4bdf6c4SBarry Smith ex->hbox.imax[0] = iupper[0]; 547f4bdf6c4SBarry Smith ex->hbox.imax[1] = iupper[1]; 548f4bdf6c4SBarry Smith ex->hbox.imax[2] = iupper[2]; 549f4bdf6c4SBarry Smith 550f4bdf6c4SBarry Smith ex->dofs_order = 0; 551f4bdf6c4SBarry Smith 552f4bdf6c4SBarry Smith /* assuming that the same number of dofs on each gridpoint. Also assume all cell-centred based */ 553f4bdf6c4SBarry Smith ex->nvars = dof; 554f4bdf6c4SBarry Smith 555f4bdf6c4SBarry Smith /* create the hypre grid object and set its information */ 5561dca8a05SBarry Smith PetscCheck(!px && !py && !pz, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add periodic support by calling HYPRE_SStructGridSetPeriodic()"); 557792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructGridCreate, ex->hcomm, dim, nparts, &ex->ss_grid); 558792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructGridSetExtents, ex->ss_grid, part, ex->hbox.imin, ex->hbox.imax); 559f4bdf6c4SBarry Smith { 560f4bdf6c4SBarry Smith HYPRE_SStructVariable *vartypes; 5619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(ex->nvars, &vartypes)); 5628865f1eaSKarl Rupp for (i = 0; i < ex->nvars; i++) vartypes[i] = HYPRE_SSTRUCT_VARIABLE_CELL; 563792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructGridSetVariables, ex->ss_grid, part, ex->nvars, vartypes); 5649566063dSJacob Faibussowitsch PetscCall(PetscFree(vartypes)); 565f4bdf6c4SBarry Smith } 566792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructGridAssemble, ex->ss_grid); 567f4bdf6c4SBarry Smith 568f4bdf6c4SBarry Smith sw[1] = sw[0]; 569f4bdf6c4SBarry Smith sw[2] = sw[1]; 570792fecdfSBarry Smith /* PetscCallExternal(HYPRE_SStructGridSetNumGhost,ex->ss_grid,sw); */ 571f4bdf6c4SBarry Smith 572f4bdf6c4SBarry Smith /* create the hypre stencil object and set its information */ 57308401ef6SPierre Jolivet PetscCheck(sw[0] <= 1, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add support for wider stencils"); 57408401ef6SPierre Jolivet PetscCheck(st != DMDA_STENCIL_BOX, PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Ask us to add support for box stencils"); 575f4bdf6c4SBarry Smith 576f4bdf6c4SBarry Smith if (dim == 1) { 5772cf14000SStefano Zampini HYPRE_Int offsets[3][1] = {{-1}, {0}, {1}}; 5784ddd07fcSJed Brown PetscInt j, cnt; 579f4bdf6c4SBarry Smith 580f4bdf6c4SBarry Smith ssize = 3 * (ex->nvars); 581792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructStencilCreate, dim, ssize, &ex->ss_stencil); 582f4bdf6c4SBarry Smith cnt = 0; 583f4bdf6c4SBarry Smith for (i = 0; i < (ex->nvars); i++) { 584f4bdf6c4SBarry Smith for (j = 0; j < 3; j++) { 585792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructStencilSetEntry, ex->ss_stencil, cnt, offsets[j], i); 586f4bdf6c4SBarry Smith cnt++; 587f4bdf6c4SBarry Smith } 588f4bdf6c4SBarry Smith } 589f4bdf6c4SBarry Smith } else if (dim == 2) { 5909371c9d4SSatish Balay HYPRE_Int offsets[5][2] = { 5919371c9d4SSatish Balay {0, -1}, 5929371c9d4SSatish Balay {-1, 0 }, 5939371c9d4SSatish Balay {0, 0 }, 5949371c9d4SSatish Balay {1, 0 }, 5959371c9d4SSatish Balay {0, 1 } 5969371c9d4SSatish Balay }; 5974ddd07fcSJed Brown PetscInt j, cnt; 598f4bdf6c4SBarry Smith 599f4bdf6c4SBarry Smith ssize = 5 * (ex->nvars); 600792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructStencilCreate, dim, ssize, &ex->ss_stencil); 601f4bdf6c4SBarry Smith cnt = 0; 602f4bdf6c4SBarry Smith for (i = 0; i < (ex->nvars); i++) { 603f4bdf6c4SBarry Smith for (j = 0; j < 5; j++) { 604792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructStencilSetEntry, ex->ss_stencil, cnt, offsets[j], i); 605f4bdf6c4SBarry Smith cnt++; 606f4bdf6c4SBarry Smith } 607f4bdf6c4SBarry Smith } 608f4bdf6c4SBarry Smith } else if (dim == 3) { 6099371c9d4SSatish Balay HYPRE_Int offsets[7][3] = { 6109371c9d4SSatish Balay {0, 0, -1}, 6119371c9d4SSatish Balay {0, -1, 0 }, 6129371c9d4SSatish Balay {-1, 0, 0 }, 6139371c9d4SSatish Balay {0, 0, 0 }, 6149371c9d4SSatish Balay {1, 0, 0 }, 6159371c9d4SSatish Balay {0, 1, 0 }, 6169371c9d4SSatish Balay {0, 0, 1 } 6179371c9d4SSatish Balay }; 6184ddd07fcSJed Brown PetscInt j, cnt; 619f4bdf6c4SBarry Smith 620f4bdf6c4SBarry Smith ssize = 7 * (ex->nvars); 621792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructStencilCreate, dim, ssize, &ex->ss_stencil); 622f4bdf6c4SBarry Smith cnt = 0; 623f4bdf6c4SBarry Smith for (i = 0; i < (ex->nvars); i++) { 624f4bdf6c4SBarry Smith for (j = 0; j < 7; j++) { 625792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructStencilSetEntry, ex->ss_stencil, cnt, offsets[j], i); 626f4bdf6c4SBarry Smith cnt++; 627f4bdf6c4SBarry Smith } 628f4bdf6c4SBarry Smith } 629f4bdf6c4SBarry Smith } 630f4bdf6c4SBarry Smith 631f4bdf6c4SBarry Smith /* create the HYPRE graph */ 632792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructGraphCreate, ex->hcomm, ex->ss_grid, &(ex->ss_graph)); 633f4bdf6c4SBarry Smith 634f4bdf6c4SBarry Smith /* set the stencil graph. Note that each variable has the same graph. This means that each 635f4bdf6c4SBarry Smith variable couples to all the other variable and with the same stencil pattern. */ 63648a46eb9SPierre Jolivet for (i = 0; i < (ex->nvars); i++) PetscCallExternal(HYPRE_SStructGraphSetStencil, ex->ss_graph, part, i, ex->ss_stencil); 637792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructGraphAssemble, ex->ss_graph); 638f4bdf6c4SBarry Smith 639f4bdf6c4SBarry Smith /* create the HYPRE sstruct vectors for rhs and solution */ 640792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructVectorCreate, ex->hcomm, ex->ss_grid, &ex->ss_b); 641792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructVectorCreate, ex->hcomm, ex->ss_grid, &ex->ss_x); 642792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructVectorInitialize, ex->ss_b); 643792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructVectorInitialize, ex->ss_x); 644792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructVectorAssemble, ex->ss_b); 645792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructVectorAssemble, ex->ss_x); 646f4bdf6c4SBarry Smith 647f4bdf6c4SBarry Smith /* create the hypre matrix object and set its information */ 648792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructMatrixCreate, ex->hcomm, ex->ss_graph, &ex->ss_mat); 649792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructGridDestroy, ex->ss_grid); 650792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructStencilDestroy, ex->ss_stencil); 651f4bdf6c4SBarry Smith if (ex->needsinitialization) { 652792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructMatrixInitialize, ex->ss_mat); 653f4bdf6c4SBarry Smith ex->needsinitialization = PETSC_FALSE; 654f4bdf6c4SBarry Smith } 655f4bdf6c4SBarry Smith 656f4bdf6c4SBarry Smith /* set the global and local sizes of the matrix */ 6579566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(da, 0, 0, 0, &nx, &ny, &nz)); 6589566063dSJacob Faibussowitsch PetscCall(MatSetSizes(mat, dof * nx * ny * nz, dof * nx * ny * nz, PETSC_DECIDE, PETSC_DECIDE)); 6599566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(mat->rmap, dof)); 6609566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(mat->cmap, dof)); 6619566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(mat->rmap)); 6629566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetUp(mat->cmap)); 66361710fbeSStefano Zampini mat->preallocated = PETSC_TRUE; 664f4bdf6c4SBarry Smith 665f4bdf6c4SBarry Smith if (dim == 3) { 666f4bdf6c4SBarry Smith mat->ops->setvalueslocal = MatSetValuesLocal_HYPRESStruct_3d; 667f4bdf6c4SBarry Smith mat->ops->zerorowslocal = MatZeroRowsLocal_HYPRESStruct_3d; 668f4bdf6c4SBarry Smith mat->ops->zeroentries = MatZeroEntries_HYPRESStruct_3d; 6698865f1eaSKarl Rupp 6709566063dSJacob Faibussowitsch /* PetscCall(MatZeroEntries_HYPRESStruct_3d(mat)); */ 671ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Only support for 3d DMDA currently"); 672f4bdf6c4SBarry Smith 673f4bdf6c4SBarry Smith /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */ 6749566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(mat, &ex->rstart, NULL)); 6759566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(ex->da, <og)); 6769566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **)&ex->gindices)); 6779566063dSJacob Faibussowitsch PetscCall(DMDAGetGhostCorners(ex->da, 0, 0, 0, &ex->gnx, &ex->gnxgny, &ex->gnxgnygnz)); 6788865f1eaSKarl Rupp 679f4bdf6c4SBarry Smith ex->gnxgny *= ex->gnx; 680f4bdf6c4SBarry Smith ex->gnxgnygnz *= ex->gnxgny; 6818865f1eaSKarl Rupp 6829566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(ex->da, &ex->xs, &ex->ys, &ex->zs, &ex->nx, &ex->ny, &ex->nz)); 6838865f1eaSKarl Rupp 684f4bdf6c4SBarry Smith ex->nxny = ex->nx * ex->ny; 685f4bdf6c4SBarry Smith ex->nxnynz = ex->nz * ex->nxny; 686f4bdf6c4SBarry Smith PetscFunctionReturn(0); 687f4bdf6c4SBarry Smith } 688f4bdf6c4SBarry Smith 6899371c9d4SSatish Balay PetscErrorCode MatMult_HYPRESStruct(Mat A, Vec x, Vec y) { 690b026d285SBarry Smith const PetscScalar *xx; 691b026d285SBarry Smith PetscScalar *yy; 6922cf14000SStefano Zampini HYPRE_Int hlower[3], hupper[3]; 6934ddd07fcSJed Brown PetscInt ilower[3], iupper[3]; 694f4bdf6c4SBarry Smith Mat_HYPRESStruct *mx = (Mat_HYPRESStruct *)(A->data); 6954ddd07fcSJed Brown PetscInt ordering = mx->dofs_order; 6964ddd07fcSJed Brown PetscInt nvars = mx->nvars; 6974ddd07fcSJed Brown PetscInt part = 0; 6984ddd07fcSJed Brown PetscInt size; 6994ddd07fcSJed Brown PetscInt i; 700f4bdf6c4SBarry Smith 701f4bdf6c4SBarry Smith PetscFunctionBegin; 7029566063dSJacob Faibussowitsch PetscCall(DMDAGetCorners(mx->da, &ilower[0], &ilower[1], &ilower[2], &iupper[0], &iupper[1], &iupper[2])); 7032cf14000SStefano Zampini 7042cf14000SStefano Zampini /* when HYPRE_MIXEDINT is defined, sizeof(HYPRE_Int) == 32 */ 705f4bdf6c4SBarry Smith iupper[0] += ilower[0] - 1; 706f4bdf6c4SBarry Smith iupper[1] += ilower[1] - 1; 707f4bdf6c4SBarry Smith iupper[2] += ilower[2] - 1; 7082cf14000SStefano Zampini hlower[0] = (HYPRE_Int)ilower[0]; 7092cf14000SStefano Zampini hlower[1] = (HYPRE_Int)ilower[1]; 7102cf14000SStefano Zampini hlower[2] = (HYPRE_Int)ilower[2]; 7112cf14000SStefano Zampini hupper[0] = (HYPRE_Int)iupper[0]; 7122cf14000SStefano Zampini hupper[1] = (HYPRE_Int)iupper[1]; 7132cf14000SStefano Zampini hupper[2] = (HYPRE_Int)iupper[2]; 714f4bdf6c4SBarry Smith 715f4bdf6c4SBarry Smith size = 1; 7168865f1eaSKarl Rupp for (i = 0; i < 3; i++) size *= (iupper[i] - ilower[i] + 1); 717f4bdf6c4SBarry Smith 718f4bdf6c4SBarry Smith /* copy x values over to hypre for variable ordering */ 719f4bdf6c4SBarry Smith if (ordering) { 720792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0); 7219566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &xx)); 72248a46eb9SPierre Jolivet for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(xx + (size * i))); 7239566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &xx)); 724792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b); 725792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructMatrixMatvec, 1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x); 726f4bdf6c4SBarry Smith 727f4bdf6c4SBarry Smith /* copy solution values back to PETSc */ 7289566063dSJacob Faibussowitsch PetscCall(VecGetArray(y, &yy)); 72948a46eb9SPierre Jolivet for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(yy + (size * i))); 7309566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(y, &yy)); 731f4bdf6c4SBarry Smith } else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */ 732f4bdf6c4SBarry Smith PetscScalar *z; 7334ddd07fcSJed Brown PetscInt j, k; 734f4bdf6c4SBarry Smith 7359566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nvars * size, &z)); 736792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructVectorSetConstantValues, mx->ss_b, 0.0); 7379566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(x, &xx)); 738f4bdf6c4SBarry Smith 739f4bdf6c4SBarry Smith /* transform nodal to hypre's variable ordering for sys_pfmg */ 740f4bdf6c4SBarry Smith for (i = 0; i < size; i++) { 741f4bdf6c4SBarry Smith k = i * nvars; 7428865f1eaSKarl Rupp for (j = 0; j < nvars; j++) z[j * size + i] = xx[k + j]; 743f4bdf6c4SBarry Smith } 74448a46eb9SPierre Jolivet for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorSetBoxValues, mx->ss_b, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i))); 7459566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(x, &xx)); 746792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructVectorAssemble, mx->ss_b); 747792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructMatrixMatvec, 1.0, mx->ss_mat, mx->ss_b, 0.0, mx->ss_x); 748f4bdf6c4SBarry Smith 749f4bdf6c4SBarry Smith /* copy solution values back to PETSc */ 7509566063dSJacob Faibussowitsch PetscCall(VecGetArray(y, &yy)); 75148a46eb9SPierre Jolivet for (i = 0; i < nvars; i++) PetscCallExternal(HYPRE_SStructVectorGetBoxValues, mx->ss_x, part, hlower, hupper, i, (HYPRE_Complex *)(z + (size * i))); 752f4bdf6c4SBarry Smith /* transform hypre's variable ordering for sys_pfmg to nodal ordering */ 753f4bdf6c4SBarry Smith for (i = 0; i < size; i++) { 754f4bdf6c4SBarry Smith k = i * nvars; 7558865f1eaSKarl Rupp for (j = 0; j < nvars; j++) yy[k + j] = z[j * size + i]; 756f4bdf6c4SBarry Smith } 7579566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(y, &yy)); 7589566063dSJacob Faibussowitsch PetscCall(PetscFree(z)); 759f4bdf6c4SBarry Smith } 760f4bdf6c4SBarry Smith PetscFunctionReturn(0); 761f4bdf6c4SBarry Smith } 762f4bdf6c4SBarry Smith 7639371c9d4SSatish Balay PetscErrorCode MatAssemblyEnd_HYPRESStruct(Mat mat, MatAssemblyType mode) { 764f4bdf6c4SBarry Smith Mat_HYPRESStruct *ex = (Mat_HYPRESStruct *)mat->data; 765f4bdf6c4SBarry Smith 766f4bdf6c4SBarry Smith PetscFunctionBegin; 767792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructMatrixAssemble, ex->ss_mat); 768f4bdf6c4SBarry Smith PetscFunctionReturn(0); 769f4bdf6c4SBarry Smith } 770f4bdf6c4SBarry Smith 7719371c9d4SSatish Balay PetscErrorCode MatZeroEntries_HYPRESStruct(Mat mat) { 772f4bdf6c4SBarry Smith PetscFunctionBegin; 773f4bdf6c4SBarry Smith /* before the DMDA is set to the matrix the zero doesn't need to do anything */ 774f4bdf6c4SBarry Smith PetscFunctionReturn(0); 775f4bdf6c4SBarry Smith } 776f4bdf6c4SBarry Smith 7779371c9d4SSatish Balay PetscErrorCode MatDestroy_HYPRESStruct(Mat mat) { 778f4bdf6c4SBarry Smith Mat_HYPRESStruct *ex = (Mat_HYPRESStruct *)mat->data; 779d94fc0b6SBarry Smith ISLocalToGlobalMapping ltog; 780f4bdf6c4SBarry Smith 781f4bdf6c4SBarry Smith PetscFunctionBegin; 7829566063dSJacob Faibussowitsch PetscCall(DMGetLocalToGlobalMapping(ex->da, <og)); 7839566063dSJacob Faibussowitsch PetscCall(ISLocalToGlobalMappingRestoreIndices(ltog, (const PetscInt **)&ex->gindices)); 784792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructGraphDestroy, ex->ss_graph); 785792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructMatrixDestroy, ex->ss_mat); 786792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructVectorDestroy, ex->ss_x); 787792fecdfSBarry Smith PetscCallExternal(HYPRE_SStructVectorDestroy, ex->ss_b); 7889566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)ex->da)); 7899566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free(&(ex->hcomm))); 7909566063dSJacob Faibussowitsch PetscCall(PetscFree(ex)); 791f4bdf6c4SBarry Smith PetscFunctionReturn(0); 792f4bdf6c4SBarry Smith } 793f4bdf6c4SBarry Smith 7949371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode MatCreate_HYPRESStruct(Mat B) { 795f4bdf6c4SBarry Smith Mat_HYPRESStruct *ex; 796f4bdf6c4SBarry Smith 797f4bdf6c4SBarry Smith PetscFunctionBegin; 798*4dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&ex)); 799f4bdf6c4SBarry Smith B->data = (void *)ex; 800f4bdf6c4SBarry Smith B->rmap->bs = 1; 801f4bdf6c4SBarry Smith B->assembled = PETSC_FALSE; 802f4bdf6c4SBarry Smith 803f4bdf6c4SBarry Smith B->insertmode = NOT_SET_VALUES; 804f4bdf6c4SBarry Smith 805f4bdf6c4SBarry Smith B->ops->assemblyend = MatAssemblyEnd_HYPRESStruct; 806f4bdf6c4SBarry Smith B->ops->mult = MatMult_HYPRESStruct; 807f4bdf6c4SBarry Smith B->ops->zeroentries = MatZeroEntries_HYPRESStruct; 808f4bdf6c4SBarry Smith B->ops->destroy = MatDestroy_HYPRESStruct; 80959cb773eSBarry Smith B->ops->setup = MatSetUp_HYPRESStruct; 810f4bdf6c4SBarry Smith 811f4bdf6c4SBarry Smith ex->needsinitialization = PETSC_TRUE; 812f4bdf6c4SBarry Smith 8139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_dup(PetscObjectComm((PetscObject)B), &(ex->hcomm))); 8149566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)B, MATHYPRESSTRUCT)); 815f4bdf6c4SBarry Smith PetscFunctionReturn(0); 816f4bdf6c4SBarry Smith } 817