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
ProcessOptions(MPI_Comm comm,AppCtx * options)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
CreateHybridMesh(MPI_Comm comm,PetscBool interpolate,DM * dm)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 */
CreateReverseHybridMesh(MPI_Comm comm,PetscBool interpolate,DM * dm)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
OrderHybridMesh(DM * dm)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
CreateMesh(MPI_Comm comm,AppCtx * user,DM * dm)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
main(int argc,char ** argv)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