1f4bdf6c4SBarry Smith 2f4bdf6c4SBarry Smith /* 3f4bdf6c4SBarry Smith Creates hypre ijmatrix from PETSc matrix 4f4bdf6c4SBarry Smith */ 5c6db04a5SJed Brown #include <petscsys.h> 6af0996ceSBarry Smith #include <petsc/private/matimpl.h> 7c6db04a5SJed Brown #include <petscdmda.h> /*I "petscdmda.h" I*/ 8c6db04a5SJed Brown #include <../src/dm/impls/da/hypre/mhyp.h> 9f4bdf6c4SBarry Smith 10f4bdf6c4SBarry Smith /* -----------------------------------------------------------------------------------------------------------------*/ 11f4bdf6c4SBarry Smith 12f4bdf6c4SBarry Smith /*MC 13f4bdf6c4SBarry Smith MATHYPRESTRUCT - MATHYPRESTRUCT = "hyprestruct" - A matrix type to be used for parallel sparse matrices 14f4bdf6c4SBarry Smith based on the hypre HYPRE_StructMatrix. 15f4bdf6c4SBarry Smith 16f4bdf6c4SBarry Smith Level: intermediate 17f4bdf6c4SBarry Smith 18f4bdf6c4SBarry Smith Notes: Unlike the more general support for blocks in hypre this allows only one block per process and requires the block 19f4bdf6c4SBarry Smith be defined by a DMDA. 20f4bdf6c4SBarry Smith 21*59cb773eSBarry Smith The matrix needs a DMDA associated with it by either a call to MatSetDM() or if the matrix is obtained from DMCreateMatrix() 22f4bdf6c4SBarry Smith 23*59cb773eSBarry Smith .seealso: MatCreate(), PCPFMG, MatSetDM(), DMCreateMatrix() 24f4bdf6c4SBarry Smith M*/ 25f4bdf6c4SBarry Smith 26f4bdf6c4SBarry Smith 27f4bdf6c4SBarry Smith PetscErrorCode MatSetValuesLocal_HYPREStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv) 28f4bdf6c4SBarry Smith { 29f4bdf6c4SBarry Smith PetscErrorCode ierr; 30f4bdf6c4SBarry Smith PetscInt i,j,stencil,index[3],row,entries[7]; 31f4bdf6c4SBarry Smith const PetscScalar *values = y; 32f4bdf6c4SBarry Smith Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data; 33f4bdf6c4SBarry Smith 34f4bdf6c4SBarry Smith PetscFunctionBegin; 35*59cb773eSBarry Smith if (PetscUnlikely(ncol > 7)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"ncol %D > 7 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; 53f4bdf6c4SBarry Smith } else SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row %D local column %D have bad stencil %D",irow[i],icol[j],stencil); 54f4bdf6c4SBarry Smith } 55f4bdf6c4SBarry Smith row = ex->gindices[irow[i]] - ex->rstart; 56f4bdf6c4SBarry Smith index[0] = ex->xs + (row % ex->nx); 57f4bdf6c4SBarry Smith index[1] = ex->ys + ((row/ex->nx) % ex->ny); 58f4bdf6c4SBarry Smith index[2] = ex->zs + (row/(ex->nxny)); 59f4bdf6c4SBarry Smith if (addv == ADD_VALUES) { 608b1f7689SBarry Smith PetscStackCallStandard(HYPRE_StructMatrixAddToValues,(ex->hmat,(HYPRE_Int *)index,ncol,(HYPRE_Int *)entries,(PetscScalar*)values)); 61f4bdf6c4SBarry Smith } else { 628b1f7689SBarry Smith PetscStackCallStandard(HYPRE_StructMatrixSetValues,(ex->hmat,(HYPRE_Int *)index,ncol,(HYPRE_Int *)entries,(PetscScalar*)values)); 63f4bdf6c4SBarry Smith } 64f4bdf6c4SBarry Smith values += ncol; 65f4bdf6c4SBarry Smith } 66f4bdf6c4SBarry Smith PetscFunctionReturn(0); 67f4bdf6c4SBarry Smith } 68f4bdf6c4SBarry Smith 69f4bdf6c4SBarry Smith PetscErrorCode MatZeroRowsLocal_HYPREStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscScalar d,Vec x,Vec b) 70f4bdf6c4SBarry Smith { 71f4bdf6c4SBarry Smith PetscErrorCode ierr; 72f4bdf6c4SBarry Smith PetscInt i,index[3],row,entries[7] = {0,1,2,3,4,5,6}; 73f4bdf6c4SBarry Smith PetscScalar values[7]; 74f4bdf6c4SBarry Smith Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data; 75f4bdf6c4SBarry Smith 76f4bdf6c4SBarry Smith PetscFunctionBegin; 77ce94432eSBarry Smith if (x && b) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"No support"); 78f4bdf6c4SBarry Smith ierr = PetscMemzero(values,7*sizeof(PetscScalar));CHKERRQ(ierr); 79f4bdf6c4SBarry Smith values[3] = d; 80f4bdf6c4SBarry Smith for (i=0; i<nrow; i++) { 81f4bdf6c4SBarry Smith row = ex->gindices[irow[i]] - ex->rstart; 82f4bdf6c4SBarry Smith index[0] = ex->xs + (row % ex->nx); 83f4bdf6c4SBarry Smith index[1] = ex->ys + ((row/ex->nx) % ex->ny); 84f4bdf6c4SBarry Smith index[2] = ex->zs + (row/(ex->nxny)); 858b1f7689SBarry Smith PetscStackCallStandard(HYPRE_StructMatrixSetValues,(ex->hmat,(HYPRE_Int *)index,7,(HYPRE_Int *)entries,values)); 86f4bdf6c4SBarry Smith } 87fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_StructMatrixAssemble,(ex->hmat)); 88f4bdf6c4SBarry Smith PetscFunctionReturn(0); 89f4bdf6c4SBarry Smith } 90f4bdf6c4SBarry Smith 91f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPREStruct_3d(Mat mat) 92f4bdf6c4SBarry Smith { 93f4bdf6c4SBarry Smith PetscErrorCode ierr; 94f4bdf6c4SBarry Smith PetscInt indices[7] = {0,1,2,3,4,5,6}; 95f4bdf6c4SBarry Smith Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data; 96f4bdf6c4SBarry Smith 97f4bdf6c4SBarry Smith PetscFunctionBegin; 98f4bdf6c4SBarry Smith /* hypre has no public interface to do this */ 998b1f7689SBarry Smith PetscStackCallStandard(hypre_StructMatrixClearBoxValues,(ex->hmat,&ex->hbox,7,(HYPRE_Int *)indices,0,1)); 100fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_StructMatrixAssemble,(ex->hmat)); 101f4bdf6c4SBarry Smith PetscFunctionReturn(0); 102f4bdf6c4SBarry Smith } 103f4bdf6c4SBarry Smith 104*59cb773eSBarry Smith static PetscErrorCode MatSetUp_HYPREStruct(Mat mat) 105f4bdf6c4SBarry Smith { 106f4bdf6c4SBarry Smith PetscErrorCode ierr; 107f4bdf6c4SBarry Smith Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data; 108*59cb773eSBarry Smith PetscInt dim,dof,sw[6],nx,ny,nz,ilower[3],iupper[3],ssize,i; 109bff4a2f0SMatthew G. Knepley DMBoundaryType px,py,pz; 110f4bdf6c4SBarry Smith DMDAStencilType st; 111565245c5SBarry Smith ISLocalToGlobalMapping ltog; 112*59cb773eSBarry Smith DM da; 113f4bdf6c4SBarry Smith 114f4bdf6c4SBarry Smith PetscFunctionBegin; 115*59cb773eSBarry Smith ierr = MatGetDM(mat,(DM*)&da);CHKERRQ(ierr); 116f4bdf6c4SBarry Smith ex->da = da; 117f4bdf6c4SBarry Smith ierr = PetscObjectReference((PetscObject)da);CHKERRQ(ierr); 118f4bdf6c4SBarry Smith 1197ab44359SJed Brown ierr = DMDAGetInfo(ex->da,&dim,0,0,0,0,0,0,&dof,&sw[0],&px,&py,&pz,&st);CHKERRQ(ierr); 120f4bdf6c4SBarry Smith ierr = DMDAGetCorners(ex->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr); 121f4bdf6c4SBarry Smith iupper[0] += ilower[0] - 1; 122f4bdf6c4SBarry Smith iupper[1] += ilower[1] - 1; 123f4bdf6c4SBarry Smith iupper[2] += ilower[2] - 1; 124f4bdf6c4SBarry Smith 125f4bdf6c4SBarry Smith /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */ 126f4bdf6c4SBarry Smith ex->hbox.imin[0] = ilower[0]; 127f4bdf6c4SBarry Smith ex->hbox.imin[1] = ilower[1]; 128f4bdf6c4SBarry Smith ex->hbox.imin[2] = ilower[2]; 129f4bdf6c4SBarry Smith ex->hbox.imax[0] = iupper[0]; 130f4bdf6c4SBarry Smith ex->hbox.imax[1] = iupper[1]; 131f4bdf6c4SBarry Smith ex->hbox.imax[2] = iupper[2]; 132f4bdf6c4SBarry Smith 133f4bdf6c4SBarry Smith /* create the hypre grid object and set its information */ 134ce94432eSBarry Smith if (dof > 1) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Currently only support for scalar problems"); 135ce94432eSBarry Smith if (px || py || pz) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add periodic support by calling HYPRE_StructGridSetPeriodic()"); 136fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_StructGridCreate,(ex->hcomm,dim,&ex->hgrid)); 1378b1f7689SBarry Smith PetscStackCallStandard(HYPRE_StructGridSetExtents,(ex->hgrid,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper)); 138fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_StructGridAssemble,(ex->hgrid)); 139f4bdf6c4SBarry Smith 140*59cb773eSBarry Smith sw[5] = sw[4] = sw[3] = sw[2] = sw[1] = sw[0]; 1418b1f7689SBarry Smith PetscStackCallStandard(HYPRE_StructGridSetNumGhost,(ex->hgrid,(HYPRE_Int *)sw)); 142f4bdf6c4SBarry Smith 143f4bdf6c4SBarry Smith /* create the hypre stencil object and set its information */ 144ce94432eSBarry Smith if (sw[0] > 1) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for wider stencils"); 145ce94432eSBarry Smith if (st == DMDA_STENCIL_BOX) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for box stencils"); 146f4bdf6c4SBarry Smith if (dim == 1) { 1474ddd07fcSJed Brown PetscInt offsets[3][1] = {{-1},{0},{1}}; 148f4bdf6c4SBarry Smith ssize = 3; 149fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_StructStencilCreate,(dim,ssize,&ex->hstencil)); 150f4bdf6c4SBarry Smith for (i=0; i<ssize; i++) { 1518b1f7689SBarry Smith PetscStackCallStandard(HYPRE_StructStencilSetElement,(ex->hstencil,i,(HYPRE_Int *)offsets[i])); 152f4bdf6c4SBarry Smith } 153f4bdf6c4SBarry Smith } else if (dim == 2) { 1544ddd07fcSJed Brown PetscInt offsets[5][2] = {{0,-1},{-1,0},{0,0},{1,0},{0,1}}; 155f4bdf6c4SBarry Smith ssize = 5; 156fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_StructStencilCreate,(dim,ssize,&ex->hstencil)); 157f4bdf6c4SBarry Smith for (i=0; i<ssize; i++) { 1588b1f7689SBarry Smith PetscStackCallStandard(HYPRE_StructStencilSetElement,(ex->hstencil,i,(HYPRE_Int *)offsets[i])); 159f4bdf6c4SBarry Smith } 160f4bdf6c4SBarry Smith } else if (dim == 3) { 1614ddd07fcSJed Brown PetscInt offsets[7][3] = {{0,0,-1},{0,-1,0},{-1,0,0},{0,0,0},{1,0,0},{0,1,0},{0,0,1}}; 162f4bdf6c4SBarry Smith ssize = 7; 163fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_StructStencilCreate,(dim,ssize,&ex->hstencil)); 164f4bdf6c4SBarry Smith for (i=0; i<ssize; i++) { 1658b1f7689SBarry Smith PetscStackCallStandard(HYPRE_StructStencilSetElement,(ex->hstencil,i,(HYPRE_Int *)offsets[i])); 166f4bdf6c4SBarry Smith } 167f4bdf6c4SBarry Smith } 168f4bdf6c4SBarry Smith 169f4bdf6c4SBarry Smith /* create the HYPRE vector for rhs and solution */ 170fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_StructVectorCreate,(ex->hcomm,ex->hgrid,&ex->hb)); 171fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_StructVectorCreate,(ex->hcomm,ex->hgrid,&ex->hx)); 172fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_StructVectorInitialize,(ex->hb)); 173fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_StructVectorInitialize,(ex->hx)); 174fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_StructVectorAssemble,(ex->hb)); 175fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_StructVectorAssemble,(ex->hx)); 176f4bdf6c4SBarry Smith 177f4bdf6c4SBarry Smith /* create the hypre matrix object and set its information */ 178fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_StructMatrixCreate,(ex->hcomm,ex->hgrid,ex->hstencil,&ex->hmat)); 179fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_StructGridDestroy,(ex->hgrid)); 180fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_StructStencilDestroy,(ex->hstencil)); 181f4bdf6c4SBarry Smith if (ex->needsinitialization) { 182fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_StructMatrixInitialize,(ex->hmat)); 183f4bdf6c4SBarry Smith ex->needsinitialization = PETSC_FALSE; 184f4bdf6c4SBarry Smith } 185f4bdf6c4SBarry Smith 186f4bdf6c4SBarry Smith /* set the global and local sizes of the matrix */ 187f4bdf6c4SBarry Smith ierr = DMDAGetCorners(da,0,0,0,&nx,&ny,&nz);CHKERRQ(ierr); 188f4bdf6c4SBarry Smith ierr = MatSetSizes(mat,dof*nx*ny*nz,dof*nx*ny*nz,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 189f4bdf6c4SBarry Smith ierr = PetscLayoutSetBlockSize(mat->rmap,1);CHKERRQ(ierr); 190f4bdf6c4SBarry Smith ierr = PetscLayoutSetBlockSize(mat->cmap,1);CHKERRQ(ierr); 191f4bdf6c4SBarry Smith ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr); 192f4bdf6c4SBarry Smith ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr); 193*59cb773eSBarry Smith mat->preallocated = PETSC_TRUE; 194f4bdf6c4SBarry Smith 195f4bdf6c4SBarry Smith if (dim == 3) { 196f4bdf6c4SBarry Smith mat->ops->setvalueslocal = MatSetValuesLocal_HYPREStruct_3d; 197f4bdf6c4SBarry Smith mat->ops->zerorowslocal = MatZeroRowsLocal_HYPREStruct_3d; 198f4bdf6c4SBarry Smith mat->ops->zeroentries = MatZeroEntries_HYPREStruct_3d; 1998865f1eaSKarl Rupp 200*59cb773eSBarry Smith /* ierr = MatZeroEntries_HYPREStruct_3d(mat);CHKERRQ(ierr); */ 201ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Only support for 3d DMDA currently"); 202f4bdf6c4SBarry Smith 203f4bdf6c4SBarry Smith /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */ 2040298fd71SBarry Smith ierr = MatGetOwnershipRange(mat,&ex->rstart,NULL);CHKERRQ(ierr); 205565245c5SBarry Smith ierr = DMGetLocalToGlobalMapping(ex->da,<og);CHKERRQ(ierr); 206565245c5SBarry Smith ierr = ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **) &ex->gindices);CHKERRQ(ierr); 207f4bdf6c4SBarry Smith ierr = DMDAGetGhostCorners(ex->da,0,0,0,&ex->gnx,&ex->gnxgny,0);CHKERRQ(ierr); 208f4bdf6c4SBarry Smith ex->gnxgny *= ex->gnx; 209f4bdf6c4SBarry Smith ierr = DMDAGetCorners(ex->da,&ex->xs,&ex->ys,&ex->zs,&ex->nx,&ex->ny,0);CHKERRQ(ierr); 210f4bdf6c4SBarry Smith ex->nxny = ex->nx*ex->ny; 211f4bdf6c4SBarry Smith PetscFunctionReturn(0); 212f4bdf6c4SBarry Smith } 213f4bdf6c4SBarry Smith 214f4bdf6c4SBarry Smith PetscErrorCode MatMult_HYPREStruct(Mat A,Vec x,Vec y) 215f4bdf6c4SBarry Smith { 216f4bdf6c4SBarry Smith PetscErrorCode ierr; 217b026d285SBarry Smith const PetscScalar *xx; 218b026d285SBarry Smith PetscScalar *yy; 2194ddd07fcSJed Brown PetscInt ilower[3],iupper[3]; 220f4bdf6c4SBarry Smith Mat_HYPREStruct *mx = (Mat_HYPREStruct*)(A->data); 221f4bdf6c4SBarry Smith 222f4bdf6c4SBarry Smith PetscFunctionBegin; 223f4bdf6c4SBarry Smith ierr = DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr); 2248865f1eaSKarl Rupp 225f4bdf6c4SBarry Smith iupper[0] += ilower[0] - 1; 226f4bdf6c4SBarry Smith iupper[1] += ilower[1] - 1; 227f4bdf6c4SBarry Smith iupper[2] += ilower[2] - 1; 228f4bdf6c4SBarry Smith 229f4bdf6c4SBarry Smith /* copy x values over to hypre */ 230fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_StructVectorSetConstantValues,(mx->hb,0.0)); 231b026d285SBarry Smith ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr); 232b026d285SBarry Smith PetscStackCallStandard(HYPRE_StructVectorSetBoxValues,(mx->hb,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,(PetscScalar*)xx)); 233b026d285SBarry Smith ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr); 234fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_StructVectorAssemble,(mx->hb)); 235fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_StructMatrixMatvec,(1.0,mx->hmat,mx->hb,0.0,mx->hx)); 236f4bdf6c4SBarry Smith 237f4bdf6c4SBarry Smith /* copy solution values back to PETSc */ 238f4bdf6c4SBarry Smith ierr = VecGetArray(y,&yy);CHKERRQ(ierr); 2398b1f7689SBarry Smith PetscStackCallStandard(HYPRE_StructVectorGetBoxValues,(mx->hx,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,yy)); 240f4bdf6c4SBarry Smith ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr); 241f4bdf6c4SBarry Smith PetscFunctionReturn(0); 242f4bdf6c4SBarry Smith } 243f4bdf6c4SBarry Smith 244f4bdf6c4SBarry Smith PetscErrorCode MatAssemblyEnd_HYPREStruct(Mat mat,MatAssemblyType mode) 245f4bdf6c4SBarry Smith { 246f4bdf6c4SBarry Smith Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data; 247f4bdf6c4SBarry Smith PetscErrorCode ierr; 248f4bdf6c4SBarry Smith 249f4bdf6c4SBarry Smith PetscFunctionBegin; 250fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_StructMatrixAssemble,(ex->hmat)); 251fd3f9acdSBarry Smith /* PetscStackCallStandard(HYPRE_StructMatrixPrint,("dummy",ex->hmat,0)); */ 252f4bdf6c4SBarry Smith PetscFunctionReturn(0); 253f4bdf6c4SBarry Smith } 254f4bdf6c4SBarry Smith 255f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPREStruct(Mat mat) 256f4bdf6c4SBarry Smith { 257f4bdf6c4SBarry Smith PetscFunctionBegin; 258f4bdf6c4SBarry Smith /* before the DMDA is set to the matrix the zero doesn't need to do anything */ 259f4bdf6c4SBarry Smith PetscFunctionReturn(0); 260f4bdf6c4SBarry Smith } 261f4bdf6c4SBarry Smith 262f4bdf6c4SBarry Smith PetscErrorCode MatDestroy_HYPREStruct(Mat mat) 263f4bdf6c4SBarry Smith { 264f4bdf6c4SBarry Smith Mat_HYPREStruct *ex = (Mat_HYPREStruct*) mat->data; 265f4bdf6c4SBarry Smith PetscErrorCode ierr; 266f4bdf6c4SBarry Smith 267f4bdf6c4SBarry Smith PetscFunctionBegin; 268fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_StructMatrixDestroy,(ex->hmat)); 269fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_StructVectorDestroy,(ex->hx)); 270fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_StructVectorDestroy,(ex->hb)); 271*59cb773eSBarry Smith ierr = PetscObjectDereference((PetscObject)ex->da);CHKERRQ(ierr); 272*59cb773eSBarry Smith ierr = MPI_Comm_free(&(ex->hcomm));CHKERRQ(ierr); 273*59cb773eSBarry Smith ierr = PetscFree(ex);CHKERRQ(ierr); 274f4bdf6c4SBarry Smith PetscFunctionReturn(0); 275f4bdf6c4SBarry Smith } 276f4bdf6c4SBarry Smith 2778cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_HYPREStruct(Mat B) 278f4bdf6c4SBarry Smith { 279f4bdf6c4SBarry Smith Mat_HYPREStruct *ex; 280f4bdf6c4SBarry Smith PetscErrorCode ierr; 281f4bdf6c4SBarry Smith 282f4bdf6c4SBarry Smith PetscFunctionBegin; 283b00a9115SJed Brown ierr = PetscNewLog(B,&ex);CHKERRQ(ierr); 284f4bdf6c4SBarry Smith B->data = (void*)ex; 285f4bdf6c4SBarry Smith B->rmap->bs = 1; 286f4bdf6c4SBarry Smith B->assembled = PETSC_FALSE; 287f4bdf6c4SBarry Smith 288f4bdf6c4SBarry Smith B->insertmode = NOT_SET_VALUES; 289f4bdf6c4SBarry Smith 290f4bdf6c4SBarry Smith B->ops->assemblyend = MatAssemblyEnd_HYPREStruct; 291f4bdf6c4SBarry Smith B->ops->mult = MatMult_HYPREStruct; 292f4bdf6c4SBarry Smith B->ops->zeroentries = MatZeroEntries_HYPREStruct; 293f4bdf6c4SBarry Smith B->ops->destroy = MatDestroy_HYPREStruct; 294*59cb773eSBarry Smith B->ops->setup = MatSetUp_HYPREStruct; 295f4bdf6c4SBarry Smith 296f4bdf6c4SBarry Smith ex->needsinitialization = PETSC_TRUE; 297f4bdf6c4SBarry Smith 298ce94432eSBarry Smith ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)B),&(ex->hcomm));CHKERRQ(ierr); 299f4bdf6c4SBarry Smith ierr = PetscObjectChangeTypeName((PetscObject)B,MATHYPRESTRUCT);CHKERRQ(ierr); 300f4bdf6c4SBarry Smith PetscFunctionReturn(0); 301f4bdf6c4SBarry Smith } 302f4bdf6c4SBarry Smith 303f4bdf6c4SBarry Smith /*MC 304f4bdf6c4SBarry Smith MATHYPRESSTRUCT - MATHYPRESSTRUCT = "hypresstruct" - A matrix type to be used for parallel sparse matrices 305f4bdf6c4SBarry Smith based on the hypre HYPRE_SStructMatrix. 306f4bdf6c4SBarry Smith 307f4bdf6c4SBarry Smith 308f4bdf6c4SBarry Smith Level: intermediate 309f4bdf6c4SBarry Smith 310f4bdf6c4SBarry Smith Notes: Unlike hypre's general semi-struct object consisting of a collection of structured-grid objects and unstructured 311b026d285SBarry Smith grid objects, we restrict the semi-struct objects to consist of only structured-grid components. 312f4bdf6c4SBarry Smith 313f4bdf6c4SBarry 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 314f4bdf6c4SBarry Smith be defined by a DMDA. 315f4bdf6c4SBarry Smith 316*59cb773eSBarry Smith The matrix needs a DMDA associated with it by either a call to MatSetDM() or if the matrix is obtained from DMCreateMatrix() 317f4bdf6c4SBarry Smith 318f4bdf6c4SBarry Smith M*/ 319f4bdf6c4SBarry Smith 320f4bdf6c4SBarry Smith PetscErrorCode MatSetValuesLocal_HYPRESStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscInt ncol,const PetscInt icol[],const PetscScalar y[],InsertMode addv) 321f4bdf6c4SBarry Smith { 322f4bdf6c4SBarry Smith PetscErrorCode ierr; 323f4bdf6c4SBarry Smith PetscInt i,j,stencil,index[3]; 324f4bdf6c4SBarry Smith const PetscScalar *values = y; 325f4bdf6c4SBarry Smith Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data; 326f4bdf6c4SBarry Smith 3274ddd07fcSJed Brown PetscInt part = 0; /* Petsc sstruct interface only allows 1 part */ 3284ddd07fcSJed Brown PetscInt ordering; 3294ddd07fcSJed Brown PetscInt grid_rank, to_grid_rank; 3304ddd07fcSJed Brown PetscInt var_type, to_var_type; 3314ddd07fcSJed Brown PetscInt to_var_entry = 0; 3324ddd07fcSJed Brown PetscInt nvars= ex->nvars; 333f4bdf6c4SBarry Smith PetscInt row,*entries; 334f4bdf6c4SBarry Smith 335f4bdf6c4SBarry Smith PetscFunctionBegin; 336785e854fSJed Brown ierr = PetscMalloc1(7*nvars,&entries);CHKERRQ(ierr); 337f4bdf6c4SBarry Smith ordering = ex->dofs_order; /* ordering= 0 nodal ordering 338f4bdf6c4SBarry Smith 1 variable ordering */ 339f4bdf6c4SBarry Smith /* stencil entries are orderer by variables: var0_stencil0, var0_stencil1, ..., var0_stencil6, var1_stencil0, var1_stencil1, ... */ 340f4bdf6c4SBarry Smith 341f4bdf6c4SBarry Smith if (!ordering) { 342f4bdf6c4SBarry Smith for (i=0; i<nrow; i++) { 343f4bdf6c4SBarry Smith grid_rank= irow[i]/nvars; 344f4bdf6c4SBarry Smith var_type = (irow[i] % nvars); 345f4bdf6c4SBarry Smith 346f4bdf6c4SBarry Smith for (j=0; j<ncol; j++) { 347f4bdf6c4SBarry Smith to_grid_rank= icol[j]/nvars; 348f4bdf6c4SBarry Smith to_var_type = (icol[j] % nvars); 349f4bdf6c4SBarry Smith 350f4bdf6c4SBarry Smith to_var_entry= to_var_entry*7; 351f4bdf6c4SBarry Smith entries[j] = to_var_entry; 352f4bdf6c4SBarry Smith 353f4bdf6c4SBarry Smith stencil = to_grid_rank-grid_rank; 354f4bdf6c4SBarry Smith if (!stencil) { 355f4bdf6c4SBarry Smith entries[j] += 3; 356f4bdf6c4SBarry Smith } else if (stencil == -1) { 357f4bdf6c4SBarry Smith entries[j] += 2; 358f4bdf6c4SBarry Smith } else if (stencil == 1) { 359f4bdf6c4SBarry Smith entries[j] += 4; 360f4bdf6c4SBarry Smith } else if (stencil == -ex->gnx) { 361f4bdf6c4SBarry Smith entries[j] += 1; 362f4bdf6c4SBarry Smith } else if (stencil == ex->gnx) { 363f4bdf6c4SBarry Smith entries[j] += 5; 364f4bdf6c4SBarry Smith } else if (stencil == -ex->gnxgny) { 365f4bdf6c4SBarry Smith entries[j] += 0; 366f4bdf6c4SBarry Smith } else if (stencil == ex->gnxgny) { 367f4bdf6c4SBarry Smith entries[j] += 6; 368f4bdf6c4SBarry Smith } else SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row %D local column %D have bad stencil %D",irow[i],icol[j],stencil); 369f4bdf6c4SBarry Smith } 370f4bdf6c4SBarry Smith 371f4bdf6c4SBarry Smith row = ex->gindices[grid_rank] - ex->rstart; 372f4bdf6c4SBarry Smith index[0] = ex->xs + (row % ex->nx); 373f4bdf6c4SBarry Smith index[1] = ex->ys + ((row/ex->nx) % ex->ny); 374f4bdf6c4SBarry Smith index[2] = ex->zs + (row/(ex->nxny)); 375f4bdf6c4SBarry Smith 376f4bdf6c4SBarry Smith if (addv == ADD_VALUES) { 3778b1f7689SBarry Smith PetscStackCallStandard(HYPRE_SStructMatrixAddToValues,(ex->ss_mat,part,(HYPRE_Int *)index,var_type,ncol,(HYPRE_Int *)entries,(PetscScalar*)values)); 378f4bdf6c4SBarry Smith } else { 3798b1f7689SBarry Smith PetscStackCallStandard(HYPRE_SStructMatrixSetValues,(ex->ss_mat,part,(HYPRE_Int *)index,var_type,ncol,(HYPRE_Int *)entries,(PetscScalar*)values)); 380f4bdf6c4SBarry Smith } 381f4bdf6c4SBarry Smith values += ncol; 382f4bdf6c4SBarry Smith } 383f4bdf6c4SBarry Smith } else { 384f4bdf6c4SBarry Smith for (i=0; i<nrow; i++) { 385f4bdf6c4SBarry Smith var_type = irow[i]/(ex->gnxgnygnz); 386f4bdf6c4SBarry Smith grid_rank= irow[i] - var_type*(ex->gnxgnygnz); 387f4bdf6c4SBarry Smith 388f4bdf6c4SBarry Smith for (j=0; j<ncol; j++) { 389f4bdf6c4SBarry Smith to_var_type = icol[j]/(ex->gnxgnygnz); 390f4bdf6c4SBarry Smith to_grid_rank= icol[j] - to_var_type*(ex->gnxgnygnz); 391f4bdf6c4SBarry Smith 392f4bdf6c4SBarry Smith to_var_entry= to_var_entry*7; 393f4bdf6c4SBarry Smith entries[j] = to_var_entry; 394f4bdf6c4SBarry Smith 395f4bdf6c4SBarry Smith stencil = to_grid_rank-grid_rank; 396f4bdf6c4SBarry Smith if (!stencil) { 397f4bdf6c4SBarry Smith entries[j] += 3; 398f4bdf6c4SBarry Smith } else if (stencil == -1) { 399f4bdf6c4SBarry Smith entries[j] += 2; 400f4bdf6c4SBarry Smith } else if (stencil == 1) { 401f4bdf6c4SBarry Smith entries[j] += 4; 402f4bdf6c4SBarry Smith } else if (stencil == -ex->gnx) { 403f4bdf6c4SBarry Smith entries[j] += 1; 404f4bdf6c4SBarry Smith } else if (stencil == ex->gnx) { 405f4bdf6c4SBarry Smith entries[j] += 5; 406f4bdf6c4SBarry Smith } else if (stencil == -ex->gnxgny) { 407f4bdf6c4SBarry Smith entries[j] += 0; 408f4bdf6c4SBarry Smith } else if (stencil == ex->gnxgny) { 409f4bdf6c4SBarry Smith entries[j] += 6; 410f4bdf6c4SBarry Smith } else SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row %D local column %D have bad stencil %D",irow[i],icol[j],stencil); 411f4bdf6c4SBarry Smith } 412f4bdf6c4SBarry Smith 413f4bdf6c4SBarry Smith row = ex->gindices[grid_rank] - ex->rstart; 414f4bdf6c4SBarry Smith index[0] = ex->xs + (row % ex->nx); 415f4bdf6c4SBarry Smith index[1] = ex->ys + ((row/ex->nx) % ex->ny); 416f4bdf6c4SBarry Smith index[2] = ex->zs + (row/(ex->nxny)); 417f4bdf6c4SBarry Smith 418f4bdf6c4SBarry Smith if (addv == ADD_VALUES) { 4198b1f7689SBarry Smith PetscStackCallStandard(HYPRE_SStructMatrixAddToValues,(ex->ss_mat,part,(HYPRE_Int *)index,var_type,ncol,(HYPRE_Int *)entries,(PetscScalar*)values)); 420f4bdf6c4SBarry Smith } else { 4218b1f7689SBarry Smith PetscStackCallStandard(HYPRE_SStructMatrixSetValues,(ex->ss_mat,part,(HYPRE_Int *)index,var_type,ncol,(HYPRE_Int *)entries,(PetscScalar*)values)); 422f4bdf6c4SBarry Smith } 423f4bdf6c4SBarry Smith values += ncol; 424f4bdf6c4SBarry Smith } 425f4bdf6c4SBarry Smith } 426f4bdf6c4SBarry Smith ierr = PetscFree(entries);CHKERRQ(ierr); 427f4bdf6c4SBarry Smith PetscFunctionReturn(0); 428f4bdf6c4SBarry Smith } 429f4bdf6c4SBarry Smith 430f4bdf6c4SBarry Smith PetscErrorCode MatZeroRowsLocal_HYPRESStruct_3d(Mat mat,PetscInt nrow,const PetscInt irow[],PetscScalar d,Vec x,Vec b) 431f4bdf6c4SBarry Smith { 432f4bdf6c4SBarry Smith PetscErrorCode ierr; 433f4bdf6c4SBarry Smith PetscInt i,index[3]; 434f4bdf6c4SBarry Smith PetscScalar **values; 435f4bdf6c4SBarry Smith Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data; 436f4bdf6c4SBarry Smith 4374ddd07fcSJed Brown PetscInt part = 0; /* Petsc sstruct interface only allows 1 part */ 4384ddd07fcSJed Brown PetscInt ordering = ex->dofs_order; 4394ddd07fcSJed Brown PetscInt grid_rank; 4404ddd07fcSJed Brown PetscInt var_type; 4414ddd07fcSJed Brown PetscInt nvars= ex->nvars; 442f4bdf6c4SBarry Smith PetscInt row,*entries; 443f4bdf6c4SBarry Smith 444f4bdf6c4SBarry Smith PetscFunctionBegin; 445ce94432eSBarry Smith if (x && b) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"No support"); 446785e854fSJed Brown ierr = PetscMalloc1(7*nvars,&entries);CHKERRQ(ierr); 447f4bdf6c4SBarry Smith 448785e854fSJed Brown ierr = PetscMalloc1(nvars,&values);CHKERRQ(ierr); 449785e854fSJed Brown ierr = PetscMalloc1(7*nvars*nvars,&values[0]);CHKERRQ(ierr); 450f4bdf6c4SBarry Smith for (i=1; i<nvars; i++) { 451f4bdf6c4SBarry Smith values[i] = values[i-1] + nvars*7; 452f4bdf6c4SBarry Smith } 453f4bdf6c4SBarry Smith 454f4bdf6c4SBarry Smith for (i=0; i< nvars; i++) { 455f4bdf6c4SBarry Smith ierr = PetscMemzero(values[i],nvars*7*sizeof(PetscScalar));CHKERRQ(ierr); 456f4bdf6c4SBarry Smith *(values[i]+3) = d; 457f4bdf6c4SBarry Smith } 458f4bdf6c4SBarry Smith 4598865f1eaSKarl Rupp for (i= 0; i< nvars*7; i++) entries[i] = i; 460f4bdf6c4SBarry Smith 461f4bdf6c4SBarry Smith if (!ordering) { 462f4bdf6c4SBarry Smith for (i=0; i<nrow; i++) { 463f4bdf6c4SBarry Smith grid_rank = irow[i] / nvars; 464f4bdf6c4SBarry Smith var_type =(irow[i] % nvars); 465f4bdf6c4SBarry Smith 466f4bdf6c4SBarry Smith row = ex->gindices[grid_rank] - ex->rstart; 467f4bdf6c4SBarry Smith index[0] = ex->xs + (row % ex->nx); 468f4bdf6c4SBarry Smith index[1] = ex->ys + ((row/ex->nx) % ex->ny); 469f4bdf6c4SBarry Smith index[2] = ex->zs + (row/(ex->nxny)); 4708b1f7689SBarry Smith PetscStackCallStandard(HYPRE_SStructMatrixSetValues,(ex->ss_mat,part,(HYPRE_Int *)index,var_type,7*nvars,(HYPRE_Int *)entries,values[var_type])); 471f4bdf6c4SBarry Smith } 472f4bdf6c4SBarry Smith } else { 473f4bdf6c4SBarry Smith for (i=0; i<nrow; i++) { 474f4bdf6c4SBarry Smith var_type = irow[i]/(ex->gnxgnygnz); 475f4bdf6c4SBarry Smith grid_rank= irow[i] - var_type*(ex->gnxgnygnz); 476f4bdf6c4SBarry Smith 477f4bdf6c4SBarry Smith row = ex->gindices[grid_rank] - ex->rstart; 478f4bdf6c4SBarry Smith index[0] = ex->xs + (row % ex->nx); 479f4bdf6c4SBarry Smith index[1] = ex->ys + ((row/ex->nx) % ex->ny); 480f4bdf6c4SBarry Smith index[2] = ex->zs + (row/(ex->nxny)); 4818b1f7689SBarry Smith PetscStackCallStandard(HYPRE_SStructMatrixSetValues,(ex->ss_mat,part,(HYPRE_Int *)index,var_type,7*nvars,(HYPRE_Int *)entries,values[var_type])); 482f4bdf6c4SBarry Smith } 483f4bdf6c4SBarry Smith } 484fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructMatrixAssemble,(ex->ss_mat)); 485f4bdf6c4SBarry Smith ierr = PetscFree(values[0]);CHKERRQ(ierr); 486f4bdf6c4SBarry Smith ierr = PetscFree(values);CHKERRQ(ierr); 487f4bdf6c4SBarry Smith ierr = PetscFree(entries);CHKERRQ(ierr); 488f4bdf6c4SBarry Smith PetscFunctionReturn(0); 489f4bdf6c4SBarry Smith } 490f4bdf6c4SBarry Smith 491f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPRESStruct_3d(Mat mat) 492f4bdf6c4SBarry Smith { 493f4bdf6c4SBarry Smith PetscErrorCode ierr; 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 { 5024ddd07fcSJed Brown PetscInt i,*entries,iupper[3],ilower[3]; 503f4bdf6c4SBarry Smith PetscScalar *values; 5044ddd07fcSJed Brown 505f4bdf6c4SBarry Smith 506f4bdf6c4SBarry Smith for (i= 0; i< 3; i++) { 507f4bdf6c4SBarry Smith ilower[i]= ex->hbox.imin[i]; 508f4bdf6c4SBarry Smith iupper[i]= ex->hbox.imax[i]; 509f4bdf6c4SBarry Smith } 510f4bdf6c4SBarry Smith 511dcca6d9dSJed Brown ierr = PetscMalloc2(nvars*7,&entries,nvars*7*size,&values);CHKERRQ(ierr); 5128865f1eaSKarl Rupp for (i= 0; i< nvars*7; i++) entries[i]= i; 513f4bdf6c4SBarry Smith ierr = PetscMemzero(values,nvars*7*size*sizeof(PetscScalar));CHKERRQ(ierr); 514f4bdf6c4SBarry Smith 515f4bdf6c4SBarry Smith for (i= 0; i< nvars; i++) { 5168b1f7689SBarry Smith PetscStackCallStandard(HYPRE_SStructMatrixSetBoxValues,(ex->ss_mat,part,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,i,nvars*7,(HYPRE_Int *)entries,values)); 517f4bdf6c4SBarry Smith } 518f4bdf6c4SBarry Smith ierr = PetscFree2(entries,values);CHKERRQ(ierr); 519f4bdf6c4SBarry Smith } 520fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructMatrixAssemble,(ex->ss_mat)); 521f4bdf6c4SBarry Smith PetscFunctionReturn(0); 522f4bdf6c4SBarry Smith } 523f4bdf6c4SBarry Smith 524f4bdf6c4SBarry Smith 525*59cb773eSBarry Smith static PetscErrorCode MatSetUp_HYPRESStruct(Mat mat) 526f4bdf6c4SBarry Smith { 527f4bdf6c4SBarry Smith PetscErrorCode ierr; 528f4bdf6c4SBarry Smith Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data; 529f4bdf6c4SBarry Smith PetscInt dim,dof,sw[3],nx,ny,nz; 5304ddd07fcSJed Brown PetscInt ilower[3],iupper[3],ssize,i; 531bff4a2f0SMatthew G. Knepley DMBoundaryType px,py,pz; 532f4bdf6c4SBarry Smith DMDAStencilType st; 5334ddd07fcSJed Brown PetscInt nparts= 1; /* assuming only one part */ 5344ddd07fcSJed Brown PetscInt part = 0; 535565245c5SBarry Smith ISLocalToGlobalMapping ltog; 536*59cb773eSBarry Smith DM da; 537b026d285SBarry Smith 538f4bdf6c4SBarry Smith PetscFunctionBegin; 539*59cb773eSBarry Smith ierr = MatGetDM(mat,(DM*)&da);CHKERRQ(ierr); 540f4bdf6c4SBarry Smith ex->da = da; 541f4bdf6c4SBarry Smith ierr = PetscObjectReference((PetscObject)da);CHKERRQ(ierr); 542f4bdf6c4SBarry Smith 5437ab44359SJed Brown ierr = DMDAGetInfo(ex->da,&dim,0,0,0,0,0,0,&dof,&sw[0],&px,&py,&pz,&st);CHKERRQ(ierr); 544f4bdf6c4SBarry Smith ierr = DMDAGetCorners(ex->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr); 545f4bdf6c4SBarry Smith iupper[0] += ilower[0] - 1; 546f4bdf6c4SBarry Smith iupper[1] += ilower[1] - 1; 547f4bdf6c4SBarry Smith iupper[2] += ilower[2] - 1; 548f4bdf6c4SBarry Smith /* the hypre_Box is used to zero out the matrix entries in MatZeroValues() */ 549f4bdf6c4SBarry Smith ex->hbox.imin[0] = ilower[0]; 550f4bdf6c4SBarry Smith ex->hbox.imin[1] = ilower[1]; 551f4bdf6c4SBarry Smith ex->hbox.imin[2] = ilower[2]; 552f4bdf6c4SBarry Smith ex->hbox.imax[0] = iupper[0]; 553f4bdf6c4SBarry Smith ex->hbox.imax[1] = iupper[1]; 554f4bdf6c4SBarry Smith ex->hbox.imax[2] = iupper[2]; 555f4bdf6c4SBarry Smith 556f4bdf6c4SBarry Smith ex->dofs_order = 0; 557f4bdf6c4SBarry Smith 558f4bdf6c4SBarry Smith /* assuming that the same number of dofs on each gridpoint. Also assume all cell-centred based */ 559f4bdf6c4SBarry Smith ex->nvars= dof; 560f4bdf6c4SBarry Smith 561f4bdf6c4SBarry Smith /* create the hypre grid object and set its information */ 562ce94432eSBarry Smith if (px || py || pz) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add periodic support by calling HYPRE_SStructGridSetPeriodic()"); 563fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructGridCreate,(ex->hcomm,dim,nparts,&ex->ss_grid)); 564fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructGridSetExtents,(ex->ss_grid,part,ex->hbox.imin,ex->hbox.imax)); 565f4bdf6c4SBarry Smith { 566f4bdf6c4SBarry Smith HYPRE_SStructVariable *vartypes; 567785e854fSJed Brown ierr = PetscMalloc1(ex->nvars,&vartypes);CHKERRQ(ierr); 5688865f1eaSKarl Rupp for (i= 0; i< ex->nvars; i++) vartypes[i]= HYPRE_SSTRUCT_VARIABLE_CELL; 569fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructGridSetVariables,(ex->ss_grid, part, ex->nvars,vartypes)); 570f4bdf6c4SBarry Smith ierr = PetscFree(vartypes);CHKERRQ(ierr); 571f4bdf6c4SBarry Smith } 572fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructGridAssemble,(ex->ss_grid)); 573f4bdf6c4SBarry Smith 574f4bdf6c4SBarry Smith sw[1] = sw[0]; 575f4bdf6c4SBarry Smith sw[2] = sw[1]; 576fd3f9acdSBarry Smith /* PetscStackCallStandard(HYPRE_SStructGridSetNumGhost,(ex->ss_grid,sw)); */ 577f4bdf6c4SBarry Smith 578f4bdf6c4SBarry Smith /* create the hypre stencil object and set its information */ 579ce94432eSBarry Smith if (sw[0] > 1) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for wider stencils"); 580ce94432eSBarry Smith if (st == DMDA_STENCIL_BOX) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Ask us to add support for box stencils"); 581f4bdf6c4SBarry Smith 582f4bdf6c4SBarry Smith if (dim == 1) { 5834ddd07fcSJed Brown PetscInt offsets[3][1] = {{-1},{0},{1}}; 5844ddd07fcSJed Brown PetscInt j, cnt; 585f4bdf6c4SBarry Smith 586f4bdf6c4SBarry Smith ssize = 3*(ex->nvars); 587fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructStencilCreate,(dim,ssize,&ex->ss_stencil)); 588f4bdf6c4SBarry Smith cnt= 0; 589f4bdf6c4SBarry Smith for (i = 0; i < (ex->nvars); i++) { 590f4bdf6c4SBarry Smith for (j = 0; j < 3; j++) { 5918b1f7689SBarry Smith PetscStackCallStandard(HYPRE_SStructStencilSetEntry,(ex->ss_stencil, cnt, (HYPRE_Int *)offsets[j], i)); 592f4bdf6c4SBarry Smith cnt++; 593f4bdf6c4SBarry Smith } 594f4bdf6c4SBarry Smith } 595f4bdf6c4SBarry Smith } else if (dim == 2) { 5964ddd07fcSJed Brown PetscInt offsets[5][2] = {{0,-1},{-1,0},{0,0},{1,0},{0,1}}; 5974ddd07fcSJed Brown PetscInt j, cnt; 598f4bdf6c4SBarry Smith 599f4bdf6c4SBarry Smith ssize = 5*(ex->nvars); 600fd3f9acdSBarry Smith PetscStackCallStandard(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++) { 6048b1f7689SBarry Smith PetscStackCallStandard(HYPRE_SStructStencilSetEntry,(ex->ss_stencil, cnt, (HYPRE_Int *)offsets[j], i)); 605f4bdf6c4SBarry Smith cnt++; 606f4bdf6c4SBarry Smith } 607f4bdf6c4SBarry Smith } 608f4bdf6c4SBarry Smith } else if (dim == 3) { 6094ddd07fcSJed Brown PetscInt offsets[7][3] = {{0,0,-1},{0,-1,0},{-1,0,0},{0,0,0},{1,0,0},{0,1,0},{0,0,1}}; 6104ddd07fcSJed Brown PetscInt j, cnt; 611f4bdf6c4SBarry Smith 612f4bdf6c4SBarry Smith ssize = 7*(ex->nvars); 613fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructStencilCreate,(dim,ssize,&ex->ss_stencil)); 614f4bdf6c4SBarry Smith cnt= 0; 615f4bdf6c4SBarry Smith for (i= 0; i< (ex->nvars); i++) { 616f4bdf6c4SBarry Smith for (j= 0; j< 7; j++) { 6178b1f7689SBarry Smith PetscStackCallStandard(HYPRE_SStructStencilSetEntry,(ex->ss_stencil, cnt, (HYPRE_Int *)offsets[j], i)); 618f4bdf6c4SBarry Smith cnt++; 619f4bdf6c4SBarry Smith } 620f4bdf6c4SBarry Smith } 621f4bdf6c4SBarry Smith } 622f4bdf6c4SBarry Smith 623f4bdf6c4SBarry Smith /* create the HYPRE graph */ 624fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructGraphCreate,(ex->hcomm, ex->ss_grid, &(ex->ss_graph))); 625f4bdf6c4SBarry Smith 626f4bdf6c4SBarry Smith /* set the stencil graph. Note that each variable has the same graph. This means that each 627f4bdf6c4SBarry Smith variable couples to all the other variable and with the same stencil pattern. */ 628f4bdf6c4SBarry Smith for (i= 0; i< (ex->nvars); i++) { 629fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructGraphSetStencil,(ex->ss_graph,part,i,ex->ss_stencil)); 630f4bdf6c4SBarry Smith } 631fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructGraphAssemble,(ex->ss_graph)); 632f4bdf6c4SBarry Smith 633f4bdf6c4SBarry Smith /* create the HYPRE sstruct vectors for rhs and solution */ 634fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructVectorCreate,(ex->hcomm,ex->ss_grid,&ex->ss_b)); 635fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructVectorCreate,(ex->hcomm,ex->ss_grid,&ex->ss_x)); 636fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructVectorInitialize,(ex->ss_b)); 637fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructVectorInitialize,(ex->ss_x)); 638fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructVectorAssemble,(ex->ss_b)); 639fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructVectorAssemble,(ex->ss_x)); 640f4bdf6c4SBarry Smith 641f4bdf6c4SBarry Smith /* create the hypre matrix object and set its information */ 642fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructMatrixCreate,(ex->hcomm,ex->ss_graph,&ex->ss_mat)); 643fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructGridDestroy,(ex->ss_grid)); 644fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructStencilDestroy,(ex->ss_stencil)); 645f4bdf6c4SBarry Smith if (ex->needsinitialization) { 646fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructMatrixInitialize,(ex->ss_mat)); 647f4bdf6c4SBarry Smith ex->needsinitialization = PETSC_FALSE; 648f4bdf6c4SBarry Smith } 649f4bdf6c4SBarry Smith 650f4bdf6c4SBarry Smith /* set the global and local sizes of the matrix */ 651f4bdf6c4SBarry Smith ierr = DMDAGetCorners(da,0,0,0,&nx,&ny,&nz);CHKERRQ(ierr); 652f4bdf6c4SBarry Smith ierr = MatSetSizes(mat,dof*nx*ny*nz,dof*nx*ny*nz,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 653f4bdf6c4SBarry Smith ierr = PetscLayoutSetBlockSize(mat->rmap,1);CHKERRQ(ierr); 654f4bdf6c4SBarry Smith ierr = PetscLayoutSetBlockSize(mat->cmap,1);CHKERRQ(ierr); 655f4bdf6c4SBarry Smith ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr); 656f4bdf6c4SBarry Smith ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr); 657f4bdf6c4SBarry Smith 658f4bdf6c4SBarry Smith if (dim == 3) { 659f4bdf6c4SBarry Smith mat->ops->setvalueslocal = MatSetValuesLocal_HYPRESStruct_3d; 660f4bdf6c4SBarry Smith mat->ops->zerorowslocal = MatZeroRowsLocal_HYPRESStruct_3d; 661f4bdf6c4SBarry Smith mat->ops->zeroentries = MatZeroEntries_HYPRESStruct_3d; 6628865f1eaSKarl Rupp 663f4bdf6c4SBarry Smith ierr = MatZeroEntries_HYPRESStruct_3d(mat);CHKERRQ(ierr); 664ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Only support for 3d DMDA currently"); 665f4bdf6c4SBarry Smith 666f4bdf6c4SBarry Smith /* get values that will be used repeatedly in MatSetValuesLocal() and MatZeroRowsLocal() repeatedly */ 6670298fd71SBarry Smith ierr = MatGetOwnershipRange(mat,&ex->rstart,NULL);CHKERRQ(ierr); 668565245c5SBarry Smith ierr = DMGetLocalToGlobalMapping(ex->da,<og);CHKERRQ(ierr); 669565245c5SBarry Smith ierr = ISLocalToGlobalMappingGetIndices(ltog, (const PetscInt **) &ex->gindices);CHKERRQ(ierr); 670f4bdf6c4SBarry Smith ierr = DMDAGetGhostCorners(ex->da,0,0,0,&ex->gnx,&ex->gnxgny,&ex->gnxgnygnz);CHKERRQ(ierr); 6718865f1eaSKarl Rupp 672f4bdf6c4SBarry Smith ex->gnxgny *= ex->gnx; 673f4bdf6c4SBarry Smith ex->gnxgnygnz *= ex->gnxgny; 6748865f1eaSKarl Rupp 675f4bdf6c4SBarry Smith ierr = DMDAGetCorners(ex->da,&ex->xs,&ex->ys,&ex->zs,&ex->nx,&ex->ny,&ex->nz);CHKERRQ(ierr); 6768865f1eaSKarl Rupp 677f4bdf6c4SBarry Smith ex->nxny = ex->nx*ex->ny; 678f4bdf6c4SBarry Smith ex->nxnynz = ex->nz*ex->nxny; 679f4bdf6c4SBarry Smith PetscFunctionReturn(0); 680f4bdf6c4SBarry Smith } 681f4bdf6c4SBarry Smith 682f4bdf6c4SBarry Smith PetscErrorCode MatMult_HYPRESStruct(Mat A,Vec x,Vec y) 683f4bdf6c4SBarry Smith { 684f4bdf6c4SBarry Smith PetscErrorCode ierr; 685b026d285SBarry Smith const PetscScalar *xx; 686b026d285SBarry Smith PetscScalar *yy; 6874ddd07fcSJed Brown PetscInt ilower[3],iupper[3]; 688f4bdf6c4SBarry Smith Mat_HYPRESStruct *mx = (Mat_HYPRESStruct*)(A->data); 6894ddd07fcSJed Brown PetscInt ordering= mx->dofs_order; 6904ddd07fcSJed Brown PetscInt nvars = mx->nvars; 6914ddd07fcSJed Brown PetscInt part = 0; 6924ddd07fcSJed Brown PetscInt size; 6934ddd07fcSJed Brown PetscInt i; 694f4bdf6c4SBarry Smith 695f4bdf6c4SBarry Smith PetscFunctionBegin; 696f4bdf6c4SBarry Smith ierr = DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr); 697f4bdf6c4SBarry Smith iupper[0] += ilower[0] - 1; 698f4bdf6c4SBarry Smith iupper[1] += ilower[1] - 1; 699f4bdf6c4SBarry Smith iupper[2] += ilower[2] - 1; 700f4bdf6c4SBarry Smith 701f4bdf6c4SBarry Smith size= 1; 7028865f1eaSKarl Rupp for (i = 0; i < 3; i++) size *= (iupper[i]-ilower[i]+1); 703f4bdf6c4SBarry Smith 704f4bdf6c4SBarry Smith /* copy x values over to hypre for variable ordering */ 705f4bdf6c4SBarry Smith if (ordering) { 706fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructVectorSetConstantValues,(mx->ss_b,0.0)); 707b026d285SBarry Smith ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr); 708f4bdf6c4SBarry Smith for (i= 0; i< nvars; i++) { 709b026d285SBarry Smith PetscStackCallStandard(HYPRE_SStructVectorSetBoxValues,(mx->ss_b,part,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,i,(PetscScalar*)xx+(size*i))); 710f4bdf6c4SBarry Smith } 711b026d285SBarry Smith ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr); 712fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructVectorAssemble,(mx->ss_b)); 713fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructMatrixMatvec,(1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x)); 714f4bdf6c4SBarry Smith 715f4bdf6c4SBarry Smith /* copy solution values back to PETSc */ 716f4bdf6c4SBarry Smith ierr = VecGetArray(y,&yy);CHKERRQ(ierr); 717f4bdf6c4SBarry Smith for (i= 0; i< nvars; i++) { 7188b1f7689SBarry Smith PetscStackCallStandard(HYPRE_SStructVectorGetBoxValues,(mx->ss_x,part,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,i,yy+(size*i))); 719f4bdf6c4SBarry Smith } 720f4bdf6c4SBarry Smith ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr); 721f4bdf6c4SBarry Smith } else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */ 722f4bdf6c4SBarry Smith PetscScalar *z; 7234ddd07fcSJed Brown PetscInt j, k; 724f4bdf6c4SBarry Smith 725785e854fSJed Brown ierr = PetscMalloc1(nvars*size,&z);CHKERRQ(ierr); 726fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructVectorSetConstantValues,(mx->ss_b,0.0)); 727b026d285SBarry Smith ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr); 728f4bdf6c4SBarry Smith 729f4bdf6c4SBarry Smith /* transform nodal to hypre's variable ordering for sys_pfmg */ 730f4bdf6c4SBarry Smith for (i= 0; i< size; i++) { 731f4bdf6c4SBarry Smith k= i*nvars; 7328865f1eaSKarl Rupp for (j= 0; j< nvars; j++) z[j*size+i]= xx[k+j]; 733f4bdf6c4SBarry Smith } 734f4bdf6c4SBarry Smith for (i= 0; i< nvars; i++) { 7358b1f7689SBarry Smith PetscStackCallStandard(HYPRE_SStructVectorSetBoxValues,(mx->ss_b,part,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,i,z+(size*i))); 736f4bdf6c4SBarry Smith } 737b026d285SBarry Smith ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr); 738fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructVectorAssemble,(mx->ss_b)); 739fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructMatrixMatvec,(1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x)); 740f4bdf6c4SBarry Smith 741f4bdf6c4SBarry Smith /* copy solution values back to PETSc */ 742f4bdf6c4SBarry Smith ierr = VecGetArray(y,&yy);CHKERRQ(ierr); 743f4bdf6c4SBarry Smith for (i= 0; i< nvars; i++) { 7448b1f7689SBarry Smith PetscStackCallStandard(HYPRE_SStructVectorGetBoxValues,(mx->ss_x,part,(HYPRE_Int *)ilower,(HYPRE_Int *)iupper,i,z+(size*i))); 745f4bdf6c4SBarry Smith } 746f4bdf6c4SBarry Smith /* transform hypre's variable ordering for sys_pfmg to nodal ordering */ 747f4bdf6c4SBarry Smith for (i= 0; i< size; i++) { 748f4bdf6c4SBarry Smith k= i*nvars; 7498865f1eaSKarl Rupp for (j= 0; j< nvars; j++) yy[k+j]= z[j*size+i]; 750f4bdf6c4SBarry Smith } 751f4bdf6c4SBarry Smith ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr); 752f4bdf6c4SBarry Smith ierr = PetscFree(z);CHKERRQ(ierr); 753f4bdf6c4SBarry Smith } 754f4bdf6c4SBarry Smith PetscFunctionReturn(0); 755f4bdf6c4SBarry Smith } 756f4bdf6c4SBarry Smith 757f4bdf6c4SBarry Smith PetscErrorCode MatAssemblyEnd_HYPRESStruct(Mat mat,MatAssemblyType mode) 758f4bdf6c4SBarry Smith { 759f4bdf6c4SBarry Smith Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data; 760f4bdf6c4SBarry Smith PetscErrorCode ierr; 761f4bdf6c4SBarry Smith 762f4bdf6c4SBarry Smith PetscFunctionBegin; 763fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructMatrixAssemble,(ex->ss_mat)); 764f4bdf6c4SBarry Smith PetscFunctionReturn(0); 765f4bdf6c4SBarry Smith } 766f4bdf6c4SBarry Smith 767f4bdf6c4SBarry Smith PetscErrorCode MatZeroEntries_HYPRESStruct(Mat mat) 768f4bdf6c4SBarry Smith { 769f4bdf6c4SBarry Smith PetscFunctionBegin; 770f4bdf6c4SBarry Smith /* before the DMDA is set to the matrix the zero doesn't need to do anything */ 771f4bdf6c4SBarry Smith PetscFunctionReturn(0); 772f4bdf6c4SBarry Smith } 773f4bdf6c4SBarry Smith 774f4bdf6c4SBarry Smith PetscErrorCode MatDestroy_HYPRESStruct(Mat mat) 775f4bdf6c4SBarry Smith { 776f4bdf6c4SBarry Smith Mat_HYPRESStruct *ex = (Mat_HYPRESStruct*) mat->data; 777f4bdf6c4SBarry Smith PetscErrorCode ierr; 778f4bdf6c4SBarry Smith 779f4bdf6c4SBarry Smith PetscFunctionBegin; 780fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructGraphDestroy,(ex->ss_graph)); 781fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructMatrixDestroy,(ex->ss_mat)); 782fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructVectorDestroy,(ex->ss_x)); 783fd3f9acdSBarry Smith PetscStackCallStandard(HYPRE_SStructVectorDestroy,(ex->ss_b)); 784*59cb773eSBarry Smith ierr = PetscObjectDereference((PetscObject)ex->da);CHKERRQ(ierr); 785*59cb773eSBarry Smith ierr = MPI_Comm_free(&(ex->hcomm));CHKERRQ(ierr); 786*59cb773eSBarry Smith ierr = PetscFree(ex);CHKERRQ(ierr); 787f4bdf6c4SBarry Smith PetscFunctionReturn(0); 788f4bdf6c4SBarry Smith } 789f4bdf6c4SBarry Smith 7908cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_HYPRESStruct(Mat B) 791f4bdf6c4SBarry Smith { 792f4bdf6c4SBarry Smith Mat_HYPRESStruct *ex; 793f4bdf6c4SBarry Smith PetscErrorCode ierr; 794f4bdf6c4SBarry Smith 795f4bdf6c4SBarry Smith PetscFunctionBegin; 796b00a9115SJed Brown ierr = PetscNewLog(B,&ex);CHKERRQ(ierr); 797f4bdf6c4SBarry Smith B->data = (void*)ex; 798f4bdf6c4SBarry Smith B->rmap->bs = 1; 799f4bdf6c4SBarry Smith B->assembled = PETSC_FALSE; 800f4bdf6c4SBarry Smith 801f4bdf6c4SBarry Smith B->insertmode = NOT_SET_VALUES; 802f4bdf6c4SBarry Smith 803f4bdf6c4SBarry Smith B->ops->assemblyend = MatAssemblyEnd_HYPRESStruct; 804f4bdf6c4SBarry Smith B->ops->mult = MatMult_HYPRESStruct; 805f4bdf6c4SBarry Smith B->ops->zeroentries = MatZeroEntries_HYPRESStruct; 806f4bdf6c4SBarry Smith B->ops->destroy = MatDestroy_HYPRESStruct; 807*59cb773eSBarry Smith B->ops->setup = MatSetUp_HYPRESStruct; 808f4bdf6c4SBarry Smith 809f4bdf6c4SBarry Smith ex->needsinitialization = PETSC_TRUE; 810f4bdf6c4SBarry Smith 811ce94432eSBarry Smith ierr = MPI_Comm_dup(PetscObjectComm((PetscObject)B),&(ex->hcomm));CHKERRQ(ierr); 812f4bdf6c4SBarry Smith ierr = PetscObjectChangeTypeName((PetscObject)B,MATHYPRESSTRUCT);CHKERRQ(ierr); 813f4bdf6c4SBarry Smith PetscFunctionReturn(0); 814f4bdf6c4SBarry Smith } 815f4bdf6c4SBarry Smith 816f4bdf6c4SBarry Smith 817f4bdf6c4SBarry Smith 818