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: }