1c4762a1bSJed Brown static char help[] = "Tests interpolation and output of hybrid meshes\n\n"; 2c4762a1bSJed Brown 3c4762a1bSJed Brown #include <petscdmplex.h> 4c4762a1bSJed Brown 5c4762a1bSJed Brown typedef struct { 6c4762a1bSJed Brown char filename[PETSC_MAX_PATH_LEN]; /* Import mesh from file */ 7c4762a1bSJed Brown PetscBool interpolate; /* Interpolate the mesh */ 8c4762a1bSJed Brown PetscInt meshNum; /* Which mesh we should construct */ 9c4762a1bSJed Brown } AppCtx; 10c4762a1bSJed Brown 11d71ae5a4SJacob Faibussowitsch static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options) 12d71ae5a4SJacob Faibussowitsch { 13c4762a1bSJed Brown PetscFunctionBeginUser; 14c4762a1bSJed Brown options->filename[0] = '\0'; 15c4762a1bSJed Brown options->interpolate = PETSC_FALSE; 16c4762a1bSJed Brown options->meshNum = 0; 17c4762a1bSJed Brown 18d0609cedSBarry Smith PetscOptionsBegin(comm, "", "Hybrid Output Test Options", "DMPLEX"); 199566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-filename", "The mesh file", "ex8.c", options->filename, options->filename, sizeof(options->filename), NULL)); 209566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-interpolate", "Interpolate the mesh", "ex8.c", options->interpolate, &options->interpolate, NULL)); 219566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-mesh_num", "The mesh we should construct", "ex8.c", options->meshNum, &options->meshNum, NULL, 0)); 22d0609cedSBarry Smith PetscOptionsEnd(); 233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 24c4762a1bSJed Brown } 25c4762a1bSJed Brown 26d71ae5a4SJacob Faibussowitsch static PetscErrorCode CreateHybridMesh(MPI_Comm comm, PetscBool interpolate, DM *dm) 27d71ae5a4SJacob Faibussowitsch { 28c4762a1bSJed Brown PetscInt dim; 29c4762a1bSJed Brown 30c4762a1bSJed Brown PetscFunctionBegin; 31c4762a1bSJed Brown dim = 3; 329566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 339566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*dm, "Simple Hybrid Mesh")); 349566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 359566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 36c4762a1bSJed Brown { 37c4762a1bSJed Brown /* Simple mesh with 2 tets and 1 wedge */ 38c4762a1bSJed Brown PetscInt numPoints[2] = {8, 3}; 39c4762a1bSJed Brown PetscInt coneSize[11] = {4, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0}; 40c4762a1bSJed Brown PetscInt cones[14] = {4, 5, 6, 3, 7, 9, 8, 10, 4, 5, 6, 7, 8, 9}; 41c4762a1bSJed Brown PetscInt coneOrientations[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 429371c9d4SSatish Balay PetscScalar vertexCoords[48] = {-1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, -1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 2.0, 1.0, 0.0}; 43c4762a1bSJed Brown 449566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45c4762a1bSJed Brown if (interpolate) { 46c4762a1bSJed Brown DM idm; 47c4762a1bSJed Brown 489566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 499566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 50c4762a1bSJed Brown *dm = idm; 51c4762a1bSJed Brown } 529566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(*dm, NULL, "-dm_view")); 53c4762a1bSJed Brown } 543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 55c4762a1bSJed Brown } 56c4762a1bSJed Brown 57b5a892a1SMatthew G. Knepley /* 58b5a892a1SMatthew G. Knepley This is not a valid mesh. We need to either change to tensor quad prisms or regular triangular prisms. 59b5a892a1SMatthew G. Knepley 60b5a892a1SMatthew G. Knepley 10-------16--------20 61b5a892a1SMatthew G. Knepley /| | 62b5a892a1SMatthew G. Knepley / | | 63b5a892a1SMatthew G. Knepley / | | 64b5a892a1SMatthew G. Knepley 9---|---15 | 65b5a892a1SMatthew G. Knepley /| 7 | 13--------18 66b5a892a1SMatthew G. Knepley / | / | / ____/ 67b5a892a1SMatthew G. Knepley / | / | /____/ 68b5a892a1SMatthew G. Knepley 8 |/ 14---|//---19 69b5a892a1SMatthew G. Knepley | 6 | 12 70b5a892a1SMatthew G. Knepley | / | / \ 71b5a892a1SMatthew G. Knepley | / | / \__ 72b5a892a1SMatthew G. Knepley |/ |/ \ 73b5a892a1SMatthew G. Knepley 5--------11--------17 74b5a892a1SMatthew G. Knepley */ 75d71ae5a4SJacob Faibussowitsch static PetscErrorCode CreateReverseHybridMesh(MPI_Comm comm, PetscBool interpolate, DM *dm) 76d71ae5a4SJacob Faibussowitsch { 77c4762a1bSJed Brown PetscInt dim; 78c4762a1bSJed Brown 79c4762a1bSJed Brown PetscFunctionBegin; 80c4762a1bSJed Brown dim = 3; 819566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 829566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*dm, "Reverse Hybrid Mesh")); 839566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 849566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 85c4762a1bSJed Brown { 86c4762a1bSJed Brown /* Simple mesh with 2 hexes and 3 wedges */ 87c4762a1bSJed Brown PetscInt numPoints[2] = {16, 5}; 889371c9d4SSatish Balay PetscInt coneSize[21] = {8, 8, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 899371c9d4SSatish Balay PetscInt cones[34] = {5, 6, 12, 11, 8, 14, 15, 9, 6, 7, 13, 12, 9, 15, 16, 10, 11, 17, 12, 14, 19, 15, 12, 18, 13, 15, 20, 16, 12, 17, 18, 15, 19, 20}; 909371c9d4SSatish Balay PetscInt coneOrientations[34] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 919371c9d4SSatish Balay PetscScalar vertexCoords[48] = {-1.0, -1.0, 0.0, -1.0, 0.0, 0.0, -1.0, 1.0, 0.0, -1.0, -1.0, 1.0, -1.0, 0.0, 1.0, -1.0, 1.0, 1.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, 929371c9d4SSatish Balay 0.0, 1.0, 0.0, 0.0, -1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0}; 93c4762a1bSJed Brown 949566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 95c4762a1bSJed Brown if (interpolate) { 96c4762a1bSJed Brown DM idm; 97c4762a1bSJed Brown 989566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 999566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 100c4762a1bSJed Brown *dm = idm; 101c4762a1bSJed Brown } 1029566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(*dm, NULL, "-dm_view")); 103c4762a1bSJed Brown } 1043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 105c4762a1bSJed Brown } 106c4762a1bSJed Brown 107d71ae5a4SJacob Faibussowitsch static PetscErrorCode OrderHybridMesh(DM *dm) 108d71ae5a4SJacob Faibussowitsch { 109c4762a1bSJed Brown DM pdm; 110c4762a1bSJed Brown IS perm; 111c4762a1bSJed Brown PetscInt *ind; 112c4762a1bSJed Brown PetscInt dim, pStart, pEnd, p, cStart, cEnd, c, Nhyb = 0, off[2]; 113c4762a1bSJed Brown 114c4762a1bSJed Brown PetscFunctionBegin; 1159566063dSJacob Faibussowitsch PetscCall(DMGetDimension(*dm, &dim)); 11663a3b9bcSJacob Faibussowitsch PetscCheck(dim == 3, PetscObjectComm((PetscObject)*dm), PETSC_ERR_SUP, "No support for dimension %" PetscInt_FMT, dim); 1179566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(*dm, &pStart, &pEnd)); 1189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd - pStart, &ind)); 119c4762a1bSJed Brown for (p = 0; p < pEnd - pStart; ++p) ind[p] = p; 1209566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(*dm, 0, &cStart, &cEnd)); 121c4762a1bSJed Brown for (c = cStart; c < cEnd; ++c) { 122c4762a1bSJed Brown PetscInt coneSize; 123c4762a1bSJed Brown 1249566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(*dm, c, &coneSize)); 125c4762a1bSJed Brown if (coneSize == 6) ++Nhyb; 126c4762a1bSJed Brown } 127c4762a1bSJed Brown off[0] = 0; 128c4762a1bSJed Brown off[1] = cEnd - Nhyb; 129c4762a1bSJed Brown for (c = cStart; c < cEnd; ++c) { 130c4762a1bSJed Brown PetscInt coneSize; 131c4762a1bSJed Brown 1329566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(*dm, c, &coneSize)); 133c4762a1bSJed Brown if (coneSize == 6) ind[c] = off[1]++; 134c4762a1bSJed Brown else ind[c] = off[0]++; 135c4762a1bSJed Brown } 1361dca8a05SBarry Smith PetscCheck(off[0] == cEnd - Nhyb, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of normal cells %" PetscInt_FMT " should be %" PetscInt_FMT, off[0], cEnd - Nhyb); 13763a3b9bcSJacob Faibussowitsch PetscCheck(off[1] == cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of hybrid cells %" PetscInt_FMT " should be %" PetscInt_FMT, off[1] - off[0], Nhyb); 1389566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, pEnd - pStart, ind, PETSC_OWN_POINTER, &perm)); 1399566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(*dm, perm, &pdm)); 1409566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 1419566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 142c4762a1bSJed Brown *dm = pdm; 1433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 144c4762a1bSJed Brown } 145c4762a1bSJed Brown 146d71ae5a4SJacob Faibussowitsch static PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *dm) 147d71ae5a4SJacob Faibussowitsch { 148c4762a1bSJed Brown const char *filename = user->filename; 149c4762a1bSJed Brown PetscBool interpolate = user->interpolate; 150c4762a1bSJed Brown PetscInt meshNum = user->meshNum; 151c4762a1bSJed Brown size_t len; 152c4762a1bSJed Brown 153c4762a1bSJed Brown PetscFunctionBegin; 1549566063dSJacob Faibussowitsch PetscCall(PetscStrlen(filename, &len)); 155c4762a1bSJed Brown if (len) { 1569566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromFile(comm, filename, "ex34_plex", PETSC_FALSE, dm)); 1579566063dSJacob Faibussowitsch PetscCall(OrderHybridMesh(dm)); 158c4762a1bSJed Brown if (interpolate) { 159c4762a1bSJed Brown DM idm; 160c4762a1bSJed Brown 1619566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 1629566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 163c4762a1bSJed Brown *dm = idm; 164c4762a1bSJed Brown } 1659566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)*dm, "Input Mesh")); 1669566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(*dm, NULL, "-dm_view")); 167c4762a1bSJed Brown } else { 168c4762a1bSJed Brown switch (meshNum) { 169d71ae5a4SJacob Faibussowitsch case 0: 170d71ae5a4SJacob Faibussowitsch PetscCall(CreateHybridMesh(comm, interpolate, dm)); 171d71ae5a4SJacob Faibussowitsch break; 172d71ae5a4SJacob Faibussowitsch case 1: 173d71ae5a4SJacob Faibussowitsch PetscCall(CreateReverseHybridMesh(comm, interpolate, dm)); 174d71ae5a4SJacob Faibussowitsch break; 175d71ae5a4SJacob Faibussowitsch default: 176d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unknown mesh number %" PetscInt_FMT, user->meshNum); 177c4762a1bSJed Brown } 178c4762a1bSJed Brown } 1793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 180c4762a1bSJed Brown } 181c4762a1bSJed Brown 182d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv) 183d71ae5a4SJacob Faibussowitsch { 184c4762a1bSJed Brown DM dm; 185c4762a1bSJed Brown AppCtx user; 186c4762a1bSJed Brown 187327415f7SBarry Smith PetscFunctionBeginUser; 1889566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc, &argv, NULL, help)); 1899566063dSJacob Faibussowitsch PetscCall(ProcessOptions(PETSC_COMM_WORLD, &user)); 1909566063dSJacob Faibussowitsch PetscCall(CreateMesh(PETSC_COMM_WORLD, &user, &dm)); 1919566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dm)); 1929566063dSJacob Faibussowitsch PetscCall(PetscFinalize()); 193b122ec5aSJacob Faibussowitsch return 0; 194c4762a1bSJed Brown } 195c4762a1bSJed Brown 196c4762a1bSJed Brown /*TEST 197c4762a1bSJed Brown 198c4762a1bSJed Brown test: 199c4762a1bSJed Brown suffix: 0 200c4762a1bSJed Brown args: -interpolate -dm_view ascii::ascii_info_detail 201c4762a1bSJed Brown 202b5a892a1SMatthew G. Knepley # Test needs to be reworked 203c4762a1bSJed Brown test: 204*0338c944SBarry Smith TODO: broken 205c4762a1bSJed Brown suffix: 1 206c4762a1bSJed Brown args: -mesh_num 1 -interpolate -dm_view ascii::ascii_info_detail 207c4762a1bSJed Brown 208c4762a1bSJed Brown TEST*/ 209