1*c4762a1bSJed Brown static char help[] = "Tests interpolation and output of hybrid meshes\n\n"; 2*c4762a1bSJed Brown 3*c4762a1bSJed Brown #include <petscdmplex.h> 4*c4762a1bSJed Brown 5*c4762a1bSJed Brown typedef struct { 6*c4762a1bSJed Brown char filename[PETSC_MAX_PATH_LEN]; /* Import mesh from file */ 7*c4762a1bSJed Brown PetscBool interpolate; /* Interpolate the mesh */ 8*c4762a1bSJed Brown PetscInt meshNum; /* Which mesh we should construct */ 9*c4762a1bSJed Brown } AppCtx; 10*c4762a1bSJed Brown 11*c4762a1bSJed Brown static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options) 12*c4762a1bSJed Brown { 13*c4762a1bSJed Brown PetscErrorCode ierr; 14*c4762a1bSJed Brown 15*c4762a1bSJed Brown PetscFunctionBeginUser; 16*c4762a1bSJed Brown options->filename[0] = '\0'; 17*c4762a1bSJed Brown options->interpolate = PETSC_FALSE; 18*c4762a1bSJed Brown options->meshNum = 0; 19*c4762a1bSJed Brown 20*c4762a1bSJed Brown ierr = PetscOptionsBegin(comm, "", "Hybrid Output Test Options", "DMPLEX");CHKERRQ(ierr); 21*c4762a1bSJed Brown ierr = PetscOptionsString("-filename", "The mesh file", "ex8.c", options->filename, options->filename, PETSC_MAX_PATH_LEN, NULL);CHKERRQ(ierr); 22*c4762a1bSJed Brown ierr = PetscOptionsBool("-interpolate", "Interpolate the mesh", "ex8.c", options->interpolate, &options->interpolate, NULL);CHKERRQ(ierr); 23*c4762a1bSJed Brown ierr = PetscOptionsBoundedInt("-mesh_num", "The mesh we should construct", "ex8.c", options->meshNum, &options->meshNum, NULL,0);CHKERRQ(ierr); 24*c4762a1bSJed Brown ierr = PetscOptionsEnd(); 25*c4762a1bSJed Brown 26*c4762a1bSJed Brown PetscFunctionReturn(0); 27*c4762a1bSJed Brown } 28*c4762a1bSJed Brown 29*c4762a1bSJed Brown static PetscErrorCode CreateHybridMesh(MPI_Comm comm, PetscBool interpolate, DM *dm) 30*c4762a1bSJed Brown { 31*c4762a1bSJed Brown PetscInt dim; 32*c4762a1bSJed Brown PetscErrorCode ierr; 33*c4762a1bSJed Brown 34*c4762a1bSJed Brown PetscFunctionBegin; 35*c4762a1bSJed Brown dim = 3; 36*c4762a1bSJed Brown ierr = DMCreate(comm, dm);CHKERRQ(ierr); 37*c4762a1bSJed Brown ierr = PetscObjectSetName((PetscObject) *dm, "Simple Hybrid Mesh");CHKERRQ(ierr); 38*c4762a1bSJed Brown ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 39*c4762a1bSJed Brown ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); 40*c4762a1bSJed Brown { 41*c4762a1bSJed Brown /* Simple mesh with 2 tets and 1 wedge */ 42*c4762a1bSJed Brown PetscInt numPoints[2] = {8, 3}; 43*c4762a1bSJed Brown PetscInt coneSize[11] = {4, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0}; 44*c4762a1bSJed Brown PetscInt cones[14] = {4, 5, 6, 3, 7, 9, 8, 10, 4, 5, 6, 7, 8, 9}; 45*c4762a1bSJed Brown PetscInt coneOrientations[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 46*c4762a1bSJed Brown PetscScalar vertexCoords[48] = {-1.0, 1.0, 0.0, 47*c4762a1bSJed Brown 0.0, 0.0, 0.0, 0.0, 1.0, -1.0, 0.0, 1.0, 1.0, 48*c4762a1bSJed Brown 1.0, 0.0, 0.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 49*c4762a1bSJed Brown 2.0, 1.0, 0.0}; 50*c4762a1bSJed Brown 51*c4762a1bSJed Brown ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 52*c4762a1bSJed Brown ierr = DMPlexSetHybridBounds(*dm, 2, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 53*c4762a1bSJed Brown if (interpolate) { 54*c4762a1bSJed Brown DM idm; 55*c4762a1bSJed Brown 56*c4762a1bSJed Brown ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 57*c4762a1bSJed Brown ierr = DMDestroy(dm);CHKERRQ(ierr); 58*c4762a1bSJed Brown *dm = idm; 59*c4762a1bSJed Brown } 60*c4762a1bSJed Brown ierr = DMViewFromOptions(*dm, NULL, "-dm_view");CHKERRQ(ierr); 61*c4762a1bSJed Brown } 62*c4762a1bSJed Brown PetscFunctionReturn(0); 63*c4762a1bSJed Brown } 64*c4762a1bSJed Brown 65*c4762a1bSJed Brown /* TODO Need to extend interpolation to work when regular cells join to hybrid faces, rather than end faces */ 66*c4762a1bSJed Brown static PetscErrorCode CreateReverseHybridMesh(MPI_Comm comm, PetscBool interpolate, DM *dm) 67*c4762a1bSJed Brown { 68*c4762a1bSJed Brown PetscInt dim; 69*c4762a1bSJed Brown PetscErrorCode ierr; 70*c4762a1bSJed Brown 71*c4762a1bSJed Brown PetscFunctionBegin; 72*c4762a1bSJed Brown dim = 3; 73*c4762a1bSJed Brown ierr = DMCreate(comm, dm);CHKERRQ(ierr); 74*c4762a1bSJed Brown ierr = PetscObjectSetName((PetscObject) *dm, "Reverse Hybrid Mesh");CHKERRQ(ierr); 75*c4762a1bSJed Brown ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 76*c4762a1bSJed Brown ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); 77*c4762a1bSJed Brown { 78*c4762a1bSJed Brown /* Simple mesh with 2 hexes and 3 wedges */ 79*c4762a1bSJed Brown PetscInt numPoints[2] = {16, 5}; 80*c4762a1bSJed Brown PetscInt coneSize[21] = {8, 8, 6, 6, 6, 81*c4762a1bSJed Brown 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 82*c4762a1bSJed Brown PetscInt cones[34] = { 5, 6, 12, 11, 8, 14, 15, 9, 83*c4762a1bSJed Brown 6, 7, 13, 12, 9, 15, 16, 10, 84*c4762a1bSJed Brown 11, 17, 12, 14, 19, 15, 85*c4762a1bSJed Brown 12, 18, 13, 15, 20, 16, 86*c4762a1bSJed Brown 12, 17, 18, 15, 19, 20}; 87*c4762a1bSJed Brown PetscInt coneOrientations[34] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88*c4762a1bSJed Brown 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 89*c4762a1bSJed Brown PetscScalar vertexCoords[48] = {-1.0, -1.0, 0.0, -1.0, 0.0, 0.0, -1.0, 1.0, 0.0, 90*c4762a1bSJed Brown -1.0, -1.0, 1.0, -1.0, 0.0, 1.0, -1.0, 1.0, 1.0, 91*c4762a1bSJed Brown 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 92*c4762a1bSJed Brown 0.0, -1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 93*c4762a1bSJed Brown 1.0, -1.0, 0.0, 1.0, 1.0, 0.0, 94*c4762a1bSJed Brown 1.0, -1.0, 1.0, 1.0, 1.0, 1.0}; 95*c4762a1bSJed Brown 96*c4762a1bSJed Brown ierr = DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 97*c4762a1bSJed Brown ierr = DMPlexSetHybridBounds(*dm, 2, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 98*c4762a1bSJed Brown if (interpolate) { 99*c4762a1bSJed Brown DM idm; 100*c4762a1bSJed Brown 101*c4762a1bSJed Brown ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 102*c4762a1bSJed Brown ierr = DMDestroy(dm);CHKERRQ(ierr); 103*c4762a1bSJed Brown *dm = idm; 104*c4762a1bSJed Brown } 105*c4762a1bSJed Brown ierr = DMViewFromOptions(*dm, NULL, "-dm_view");CHKERRQ(ierr); 106*c4762a1bSJed Brown } 107*c4762a1bSJed Brown PetscFunctionReturn(0); 108*c4762a1bSJed Brown } 109*c4762a1bSJed Brown 110*c4762a1bSJed Brown static PetscErrorCode OrderHybridMesh(DM *dm) 111*c4762a1bSJed Brown { 112*c4762a1bSJed Brown DM pdm; 113*c4762a1bSJed Brown IS perm; 114*c4762a1bSJed Brown PetscInt *ind; 115*c4762a1bSJed Brown PetscInt dim, pStart, pEnd, p, cStart, cEnd, c, Nhyb = 0, off[2]; 116*c4762a1bSJed Brown PetscErrorCode ierr; 117*c4762a1bSJed Brown 118*c4762a1bSJed Brown PetscFunctionBegin; 119*c4762a1bSJed Brown ierr = DMGetDimension(*dm, &dim);CHKERRQ(ierr); 120*c4762a1bSJed Brown if (dim != 3) SETERRQ1(PetscObjectComm((PetscObject) *dm), PETSC_ERR_SUP, "No support for dimension %D", dim); 121*c4762a1bSJed Brown ierr = DMPlexGetChart(*dm, &pStart, &pEnd);CHKERRQ(ierr); 122*c4762a1bSJed Brown ierr = PetscMalloc1(pEnd-pStart, &ind);CHKERRQ(ierr); 123*c4762a1bSJed Brown for (p = 0; p < pEnd-pStart; ++p) ind[p] = p; 124*c4762a1bSJed Brown ierr = DMPlexGetHeightStratum(*dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 125*c4762a1bSJed Brown for (c = cStart; c < cEnd; ++c) { 126*c4762a1bSJed Brown PetscInt coneSize; 127*c4762a1bSJed Brown 128*c4762a1bSJed Brown ierr = DMPlexGetConeSize(*dm, c, &coneSize);CHKERRQ(ierr); 129*c4762a1bSJed Brown if (coneSize == 6) ++Nhyb; 130*c4762a1bSJed Brown } 131*c4762a1bSJed Brown off[0] = 0; 132*c4762a1bSJed Brown off[1] = cEnd - Nhyb; 133*c4762a1bSJed Brown for (c = cStart; c < cEnd; ++c) { 134*c4762a1bSJed Brown PetscInt coneSize; 135*c4762a1bSJed Brown 136*c4762a1bSJed Brown ierr = DMPlexGetConeSize(*dm, c, &coneSize);CHKERRQ(ierr); 137*c4762a1bSJed Brown if (coneSize == 6) ind[c] = off[1]++; 138*c4762a1bSJed Brown else ind[c] = off[0]++; 139*c4762a1bSJed Brown } 140*c4762a1bSJed Brown if (off[0] != cEnd - Nhyb) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of normal cells %D should be %D", off[0], cEnd - Nhyb); 141*c4762a1bSJed Brown if (off[1] != cEnd) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of hybrid cells %D should be %D", off[1] - off[0], Nhyb); 142*c4762a1bSJed Brown ierr = ISCreateGeneral(PETSC_COMM_SELF, pEnd-pStart, ind, PETSC_OWN_POINTER, &perm);CHKERRQ(ierr); 143*c4762a1bSJed Brown ierr = DMPlexPermute(*dm, perm, &pdm);CHKERRQ(ierr); 144*c4762a1bSJed Brown ierr = DMPlexSetHybridBounds(pdm, cEnd-Nhyb, PETSC_DETERMINE, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 145*c4762a1bSJed Brown ierr = ISDestroy(&perm);CHKERRQ(ierr); 146*c4762a1bSJed Brown ierr = DMDestroy(dm);CHKERRQ(ierr); 147*c4762a1bSJed Brown *dm = pdm; 148*c4762a1bSJed Brown PetscFunctionReturn(0); 149*c4762a1bSJed Brown } 150*c4762a1bSJed Brown 151*c4762a1bSJed Brown static PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *dm) 152*c4762a1bSJed Brown { 153*c4762a1bSJed Brown const char *filename = user->filename; 154*c4762a1bSJed Brown PetscBool interpolate = user->interpolate; 155*c4762a1bSJed Brown PetscInt meshNum = user->meshNum; 156*c4762a1bSJed Brown size_t len; 157*c4762a1bSJed Brown PetscErrorCode ierr; 158*c4762a1bSJed Brown 159*c4762a1bSJed Brown PetscFunctionBegin; 160*c4762a1bSJed Brown ierr = PetscStrlen(filename, &len);CHKERRQ(ierr); 161*c4762a1bSJed Brown if (len) { 162*c4762a1bSJed Brown ierr = DMPlexCreateFromFile(comm, filename, PETSC_FALSE, dm);CHKERRQ(ierr); 163*c4762a1bSJed Brown ierr = OrderHybridMesh(dm);CHKERRQ(ierr); 164*c4762a1bSJed Brown if (interpolate) { 165*c4762a1bSJed Brown DM idm; 166*c4762a1bSJed Brown 167*c4762a1bSJed Brown ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 168*c4762a1bSJed Brown ierr = DMDestroy(dm);CHKERRQ(ierr); 169*c4762a1bSJed Brown *dm = idm; 170*c4762a1bSJed Brown } 171*c4762a1bSJed Brown ierr = PetscObjectSetName((PetscObject) *dm, "Input Mesh");CHKERRQ(ierr); 172*c4762a1bSJed Brown ierr = DMViewFromOptions(*dm, NULL, "-dm_view");CHKERRQ(ierr); 173*c4762a1bSJed Brown } else { 174*c4762a1bSJed Brown switch (meshNum) { 175*c4762a1bSJed Brown case 0: 176*c4762a1bSJed Brown ierr = CreateHybridMesh(comm, interpolate, dm);CHKERRQ(ierr);break; 177*c4762a1bSJed Brown case 1: 178*c4762a1bSJed Brown ierr = CreateReverseHybridMesh(comm, interpolate, dm);CHKERRQ(ierr);break; 179*c4762a1bSJed Brown default: SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Unknown mesh number %D", user->meshNum); 180*c4762a1bSJed Brown } 181*c4762a1bSJed Brown } 182*c4762a1bSJed Brown PetscFunctionReturn(0); 183*c4762a1bSJed Brown } 184*c4762a1bSJed Brown 185*c4762a1bSJed Brown int main(int argc, char **argv) 186*c4762a1bSJed Brown { 187*c4762a1bSJed Brown DM dm; 188*c4762a1bSJed Brown AppCtx user; 189*c4762a1bSJed Brown PetscErrorCode ierr; 190*c4762a1bSJed Brown 191*c4762a1bSJed Brown ierr = PetscInitialize(&argc, &argv, NULL,help);if (ierr) return ierr; 192*c4762a1bSJed Brown ierr = ProcessOptions(PETSC_COMM_WORLD, &user);CHKERRQ(ierr); 193*c4762a1bSJed Brown ierr = CreateMesh(PETSC_COMM_WORLD, &user, &dm);CHKERRQ(ierr); 194*c4762a1bSJed Brown ierr = DMDestroy(&dm);CHKERRQ(ierr); 195*c4762a1bSJed Brown ierr = PetscFinalize(); 196*c4762a1bSJed Brown return ierr; 197*c4762a1bSJed Brown } 198*c4762a1bSJed Brown 199*c4762a1bSJed Brown /*TEST 200*c4762a1bSJed Brown 201*c4762a1bSJed Brown test: 202*c4762a1bSJed Brown suffix: 0 203*c4762a1bSJed Brown args: -interpolate -dm_view ascii::ascii_info_detail 204*c4762a1bSJed Brown 205*c4762a1bSJed Brown test: 206*c4762a1bSJed Brown suffix: 1 207*c4762a1bSJed Brown args: -mesh_num 1 -interpolate -dm_view ascii::ascii_info_detail 208*c4762a1bSJed Brown 209*c4762a1bSJed Brown TEST*/ 210