Actual source code: plexgenerate.c
1: #include <petsc/private/dmpleximpl.h>
3: /*@
4: DMPlexInvertCell - Flips cell orientations since `DMPLEX` stores some of them internally with outward normals.
6: Input Parameters:
7: + cellType - The cell type
8: - cone - The incoming cone
10: Output Parameter:
11: . cone - The inverted cone (in-place)
13: Level: developer
15: .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeType`, `DMPlexGenerate()`
16: @*/
17: PetscErrorCode DMPlexInvertCell(DMPolytopeType cellType, PetscInt cone[])
18: {
19: #define SWAPCONE(cone, i, j) \
20: do { \
21: PetscInt _cone_tmp; \
22: _cone_tmp = (cone)[i]; \
23: (cone)[i] = (cone)[j]; \
24: (cone)[j] = _cone_tmp; \
25: } while (0)
27: PetscFunctionBegin;
28: switch (cellType) {
29: case DM_POLYTOPE_POINT:
30: break;
31: case DM_POLYTOPE_SEGMENT:
32: break;
33: case DM_POLYTOPE_POINT_PRISM_TENSOR:
34: break;
35: case DM_POLYTOPE_TRIANGLE:
36: break;
37: case DM_POLYTOPE_QUADRILATERAL:
38: break;
39: case DM_POLYTOPE_SEG_PRISM_TENSOR:
40: SWAPCONE(cone, 2, 3);
41: break;
42: case DM_POLYTOPE_TETRAHEDRON:
43: SWAPCONE(cone, 0, 1);
44: break;
45: case DM_POLYTOPE_HEXAHEDRON:
46: SWAPCONE(cone, 1, 3);
47: break;
48: case DM_POLYTOPE_TRI_PRISM:
49: SWAPCONE(cone, 1, 2);
50: break;
51: case DM_POLYTOPE_TRI_PRISM_TENSOR:
52: break;
53: case DM_POLYTOPE_QUAD_PRISM_TENSOR:
54: break;
55: case DM_POLYTOPE_PYRAMID:
56: SWAPCONE(cone, 1, 3);
57: break;
58: default:
59: break;
60: }
61: PetscFunctionReturn(PETSC_SUCCESS);
62: #undef SWAPCONE
63: }
65: /*@
66: DMPlexReorderCell - Flips cell orientations since `DMPLEX` stores some of them internally with outward normals.
68: Input Parameters:
69: + dm - The `DMPLEX` object
70: . cell - The cell
71: - cone - The incoming cone
73: Output Parameter:
74: . cone - The reordered cone (in-place)
76: Level: developer
78: .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeType`, `DMPlexGenerate()`
79: @*/
80: PetscErrorCode DMPlexReorderCell(DM dm, PetscInt cell, PetscInt cone[])
81: {
82: DMPolytopeType cellType;
84: PetscFunctionBegin;
85: PetscCall(DMPlexGetCellType(dm, cell, &cellType));
86: PetscCall(DMPlexInvertCell(cellType, cone));
87: PetscFunctionReturn(PETSC_SUCCESS);
88: }
90: /*@
91: DMPlexTriangleSetAngleBound - Set the minimum angle bound for the Triangle mesh generator
93: Logically Collective
95: Input Parameters:
96: + dm - The `DMPLEX` object
97: - ang - The minimum angle for a triangle
99: Level: developer
101: .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTriangleGetAngleBound()`, `DMPlexTetgenSetOptions()`, `DMPlexGenerate()`
102: @*/
103: PetscErrorCode DMPlexTriangleSetAngleBound(DM dm, PetscReal ang)
104: {
105: DM_Plex *mesh = (DM_Plex *)dm->data;
107: PetscFunctionBegin;
109: mesh->triangleAngBound = ang;
110: PetscFunctionReturn(PETSC_SUCCESS);
111: }
113: /*@
114: DMPlexTriangleGetAngleBound - Get the minimum angle bound for the Triangle mesh generator
116: Not Collective
118: Input Parameter:
119: . dm - The `DMPLEX` object
121: Output Parameter:
122: . ang - The minimum angle for a triangle
124: Level: developer
126: .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTriangleSetAngleBound()`, `DMPlexTetgenSetOptions()`, `DMPlexGenerate()`
127: @*/
128: PetscErrorCode DMPlexTriangleGetAngleBound(DM dm, PetscReal *ang)
129: {
130: DM_Plex *mesh = (DM_Plex *)dm->data;
132: PetscFunctionBegin;
134: PetscAssertPointer(ang, 2);
135: *ang = mesh->triangleAngBound;
136: PetscFunctionReturn(PETSC_SUCCESS);
137: }
139: /*@
140: DMPlexTriangleSetOptions - Set the options used for the Triangle mesh generator
142: Logically Collective
144: Input Parameters:
145: + dm - The `DMPLEX` object
146: - opts - The command line options
148: Level: developer
150: .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTetgenSetOptions()`, `DMPlexGenerate()`
151: @*/
152: PetscErrorCode DMPlexTriangleSetOptions(DM dm, const char *opts)
153: {
154: DM_Plex *mesh = (DM_Plex *)dm->data;
156: PetscFunctionBegin;
158: PetscAssertPointer(opts, 2);
159: PetscCall(PetscFree(mesh->triangleOpts));
160: PetscCall(PetscStrallocpy(opts, &mesh->triangleOpts));
161: PetscFunctionReturn(PETSC_SUCCESS);
162: }
164: /*@
165: DMPlexTetgenSetRadiusEdgeBound - Set the maximum radius-edge ratio bound for the Tetgen mesh generator
167: Logically Collective
169: Input Parameters:
170: + dm - The `DMPLEX` object
171: - ratio - The maximum radius-edge ratio for a tetrahedron
173: Level: developer
175: .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTetgenGetRadiusEdgeBound()`, `DMPlexTriangleSetOptions()`, `DMPlexGenerate()`
176: @*/
177: PetscErrorCode DMPlexTetgenSetRadiusEdgeBound(DM dm, PetscReal ratio)
178: {
179: DM_Plex *mesh = (DM_Plex *)dm->data;
181: PetscFunctionBegin;
183: mesh->tetgenRadiusEdgeBound = ratio;
184: PetscFunctionReturn(PETSC_SUCCESS);
185: }
187: /*@
188: DMPlexTetgenGetRadiusEdgeBound - Get the maximum radius-edge ratio for the Tetgen mesh generator
190: Not Collective
192: Input Parameter:
193: . dm - The `DMPLEX` object
195: Output Parameter:
196: . ratio - The maximum radius-edge ratio for a tetrahedron
198: Level: developer
200: .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTetgenSetRadiusEdgeBound()`, `DMPlexTriangleSetOptions()`, `DMPlexGenerate()`
201: @*/
202: PetscErrorCode DMPlexTetgenGetRadiusEdgeBound(DM dm, PetscReal *ratio)
203: {
204: DM_Plex *mesh = (DM_Plex *)dm->data;
206: PetscFunctionBegin;
208: PetscAssertPointer(ratio, 2);
209: *ratio = mesh->tetgenRadiusEdgeBound;
210: PetscFunctionReturn(PETSC_SUCCESS);
211: }
213: /*@
214: DMPlexTetgenSetDihedralBound - Set the minimum dihedral angle bound for the Tetgen mesh generator
216: Logically Collective
218: Input Parameters:
219: + dm - The `DMPLEX` object
220: - ang - The minimum dihedral angle for a tetrahedron
222: Level: developer
224: .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTetgenGetDihedralBound()`, `DMPlexTriangleSetOptions()`, `DMPlexGenerate()`
225: @*/
226: PetscErrorCode DMPlexTetgenSetDihedralBound(DM dm, PetscReal ang)
227: {
228: DM_Plex *mesh = (DM_Plex *)dm->data;
230: PetscFunctionBegin;
232: mesh->tetgenDihedralBound = ang;
233: PetscFunctionReturn(PETSC_SUCCESS);
234: }
236: /*@
237: DMPlexTetgenGetDihedralBound - Get the minimum dihedral angle bound for the Tetgen mesh generator
239: Not Collective
241: Input Parameter:
242: . dm - The `DMPLEX` object
244: Output Parameter:
245: . ang - The minimum dihedral angle for a tetrahedron
247: Level: developer
249: .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTetgenSetDihedralBound()`, `DMPlexTriangleSetOptions()`, `DMPlexGenerate()`
250: @*/
251: PetscErrorCode DMPlexTetgenGetDihedralBound(DM dm, PetscReal *ang)
252: {
253: DM_Plex *mesh = (DM_Plex *)dm->data;
255: PetscFunctionBegin;
257: PetscAssertPointer(ang, 2);
258: *ang = mesh->tetgenDihedralBound;
259: PetscFunctionReturn(PETSC_SUCCESS);
260: }
262: /*@
263: DMPlexTetgenSetOptions - Set the options used for the Tetgen mesh generator
265: Logically Collective
267: Input Parameters:
268: + dm - The `DMPLEX` object
269: - opts - The command line options
271: Level: developer
273: .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTetgenSetRadiusEdgeBound()`, `DMPlexTetgenSetDihedralBound()`, `DMPlexTriangleSetOptions()`, `DMPlexGenerate()`
274: @*/
275: PetscErrorCode DMPlexTetgenSetOptions(DM dm, const char *opts)
276: {
277: DM_Plex *mesh = (DM_Plex *)dm->data;
279: PetscFunctionBegin;
281: PetscAssertPointer(opts, 2);
282: PetscCall(PetscFree(mesh->tetgenOpts));
283: PetscCall(PetscStrallocpy(opts, &mesh->tetgenOpts));
284: PetscFunctionReturn(PETSC_SUCCESS);
285: }
287: /*@
288: DMPlexGenerate - Generates a mesh.
290: Not Collective
292: Input Parameters:
293: + boundary - The `DMPLEX` boundary object
294: . name - The mesh generation package name
295: - interpolate - Flag to create intermediate mesh elements
297: Output Parameter:
298: . mesh - The `DMPLEX` object
300: Options Database Keys:
301: + -dm_plex_generate name - package to generate mesh, for example, triangle, ctetgen or tetgen
302: - -dm_generator name - package to generate mesh, for example, triangle, ctetgen or tetgen
304: Level: intermediate
306: .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMRefine()`
307: @*/
308: PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh)
309: {
310: DMGeneratorFunctionList fl;
311: char genname[PETSC_MAX_PATH_LEN];
312: const char *suggestions;
313: PetscInt dim;
314: PetscBool flg;
316: PetscFunctionBegin;
319: PetscCall(DMGetDimension(boundary, &dim));
320: PetscCall(PetscOptionsGetString(((PetscObject)boundary)->options, ((PetscObject)boundary)->prefix, "-dm_generator", genname, sizeof(genname), &flg));
321: if (flg) name = genname;
322: else {
323: PetscCall(PetscOptionsGetString(((PetscObject)boundary)->options, ((PetscObject)boundary)->prefix, "-dm_plex_generate", genname, sizeof(genname), &flg));
324: if (flg) name = genname;
325: }
327: fl = DMGenerateList;
328: if (name) {
329: while (fl) {
330: PetscCall(PetscStrcmp(fl->name, name, &flg));
331: if (flg) {
332: PetscCall((*fl->generate)(boundary, interpolate, mesh));
333: PetscFunctionReturn(PETSC_SUCCESS);
334: }
335: fl = fl->next;
336: }
337: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Grid generator %s not registered; you may need to add --download-%s to your ./configure options", name, name);
338: } else {
339: while (fl) {
340: if (boundary->dim == fl->dim) {
341: PetscCall((*fl->generate)(boundary, interpolate, mesh));
342: PetscFunctionReturn(PETSC_SUCCESS);
343: }
344: fl = fl->next;
345: }
346: suggestions = "";
347: if (boundary->dim + 1 == 2) suggestions = " You may need to add --download-triangle to your ./configure options";
348: else if (boundary->dim + 1 == 3) suggestions = " You may need to add --download-ctetgen or --download-tetgen in your ./configure options";
349: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No grid generator of dimension %" PetscInt_FMT " registered%s", boundary->dim + 1, suggestions);
350: }
351: }