Actual source code: plexgenerate.c
petsc-3.14.6 2021-03-30
1: #include <petsc/private/dmpleximpl.h>
3: /*@C
4: DMPlexInvertCell - Flips cell orientations since Plex 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: 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)
28: switch (cellType) {
29: case DM_POLYTOPE_POINT: break;
30: case DM_POLYTOPE_SEGMENT: break;
31: case DM_POLYTOPE_POINT_PRISM_TENSOR: break;
32: case DM_POLYTOPE_TRIANGLE: break;
33: case DM_POLYTOPE_QUADRILATERAL: break;
34: case DM_POLYTOPE_SEG_PRISM_TENSOR: SWAPCONE(cone,2,3); break;
35: case DM_POLYTOPE_TETRAHEDRON: SWAPCONE(cone,0,1); break;
36: case DM_POLYTOPE_HEXAHEDRON: SWAPCONE(cone,1,3); break;
37: case DM_POLYTOPE_TRI_PRISM: SWAPCONE(cone,1,2); break;
38: case DM_POLYTOPE_TRI_PRISM_TENSOR: break;
39: case DM_POLYTOPE_QUAD_PRISM_TENSOR: break;
40: default: break;
41: }
42: return(0);
43: #undef SWAPCONE
44: }
46: /*@C
47: DMPlexReorderCell - Flips cell orientations since Plex stores some of them internally with outward normals.
49: Input Parameters:
50: + dm - The DMPlex object
51: . cell - The cell
52: - cone - The incoming cone
54: Output Parameter:
55: . cone - The reordered cone (in-place)
57: Level: developer
59: .seealso: DMPlexGenerate()
60: @*/
61: PetscErrorCode DMPlexReorderCell(DM dm, PetscInt cell, PetscInt cone[])
62: {
63: DMPolytopeType cellType;
67: DMPlexGetCellType(dm, cell, &cellType);
68: DMPlexInvertCell(cellType, cone);
69: return(0);
70: }
73: /*@C
74: DMPlexTriangleSetOptions - Set the options used for the Triangle mesh generator
76: Not Collective
78: Inputs Parameters:
79: + dm - The DMPlex object
80: - opts - The command line options
82: Level: developer
84: .seealso: DMPlexTetgenSetOptions(), DMPlexGenerate()
85: @*/
86: PetscErrorCode DMPlexTriangleSetOptions(DM dm, const char *opts)
87: {
88: DM_Plex *mesh = (DM_Plex*) dm->data;
94: PetscFree(mesh->triangleOpts);
95: PetscStrallocpy(opts, &mesh->triangleOpts);
96: return(0);
97: }
99: /*@C
100: DMPlexTetgenSetOptions - Set the options used for the Tetgen mesh generator
102: Not Collective
104: Inputs Parameters:
105: + dm - The DMPlex object
106: - opts - The command line options
108: Level: developer
110: .seealso: DMPlexTriangleSetOptions(), DMPlexGenerate()
111: @*/
112: PetscErrorCode DMPlexTetgenSetOptions(DM dm, const char *opts)
113: {
114: DM_Plex *mesh = (DM_Plex*) dm->data;
120: PetscFree(mesh->tetgenOpts);
121: PetscStrallocpy(opts, &mesh->tetgenOpts);
122: return(0);
123: }
125: /*
126: Contains the list of registered DMPlexGenerators routines
127: */
128: PetscFunctionList DMPlexGenerateList = NULL;
130: struct _n_PetscFunctionList {
131: PetscErrorCode (*generate)(DM, PetscBool, DM*);
132: PetscErrorCode (*refine)(DM,double*, DM*);
133: char *name; /* string to identify routine */
134: PetscInt dim;
135: PetscFunctionList next; /* next pointer */
136: };
138: /*@C
139: DMPlexGenerate - Generates a mesh.
141: Not Collective
143: Input Parameters:
144: + boundary - The DMPlex boundary object
145: . name - The mesh generation package name
146: - interpolate - Flag to create intermediate mesh elements
148: Output Parameter:
149: . mesh - The DMPlex object
151: Options Database:
152: + -dm_plex_generate <name> - package to generate mesh, for example, triangle, ctetgen or tetgen
153: - -dm_plex_generator <name> - package to generate mesh, for example, triangle, ctetgen or tetgen (deprecated)
155: Level: intermediate
157: .seealso: DMPlexCreate(), DMRefine()
158: @*/
159: PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh)
160: {
161: PetscInt dim;
162: char genname[1024];
163: PetscBool flg;
164: PetscErrorCode ierr;
165: PetscFunctionList fl;
166: const char* suggestions;
171: DMGetDimension(boundary, &dim);
172: PetscOptionsGetString(((PetscObject) boundary)->options,((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, sizeof(genname), &flg);
173: if (flg) name = genname;
174: else {
175: PetscOptionsGetString(((PetscObject) boundary)->options,((PetscObject) boundary)->prefix, "-dm_plex_generate", genname, sizeof(genname), &flg);
176: if (flg) name = genname;
177: }
179: fl = DMPlexGenerateList;
180: if (name) {
181: while (fl) {
182: PetscStrcmp(fl->name,name,&flg);
183: if (flg) {
184: (*fl->generate)(boundary,interpolate,mesh);
185: return(0);
186: }
187: fl = fl->next;
188: }
189: SETERRQ2(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);
190: } else {
191: while (fl) {
192: if (boundary->dim == fl->dim) {
193: (*fl->generate)(boundary,interpolate,mesh);
194: return(0);
195: }
196: fl = fl->next;
197: }
198: suggestions = "";
199: if (boundary->dim+1 == 2) suggestions = " You may need to add --download-triangle to your ./configure options";
200: else if (boundary->dim+1 == 3) suggestions = " You may need to add --download-ctetgen or --download-tetgen in your ./configure options";
201: SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"No grid generator of dimension %D registered%s",boundary->dim+1,suggestions);
202: }
203: }
205: /*@C
206: DMPlexGenerateRegister - Adds a grid generator to DMPlex
208: Not Collective
210: Input Parameters:
211: + name_solver - name of a new user-defined grid generator
212: . fnc - generator function
213: . rfnc - refinement function
214: - dim - dimension of boundary of domain
216: Notes:
217: DMPlexGenerateRegister() may be called multiple times to add several user-defined solvers.
219: Sample usage:
220: .vb
221: DMPlexGenerateRegister("my_generator",MyGeneratorCreate,MyGeneratorRefiner,dim);
222: .ve
224: Then, your generator can be chosen with the procedural interface via
225: $ DMPlexGenerate(dm,"my_generator",...)
226: or at runtime via the option
227: $ -dm_plex_generator my_generator
229: Level: advanced
231: .seealso: DMPlexGenerateRegisterAll(), DMPlexGenerate(), DMPlexGenerateRegisterDestroy()
233: @*/
234: PetscErrorCode DMPlexGenerateRegister(const char sname[],PetscErrorCode (*fnc)(DM, PetscBool,DM*), PetscErrorCode (*rfnc)(DM, double*,DM*),PetscInt dim)
235: {
236: PetscErrorCode ierr;
237: PetscFunctionList entry;
240: PetscNew(&entry);
241: PetscStrallocpy(sname,&entry->name);
242: entry->generate = fnc;
243: entry->refine = rfnc;
244: entry->dim = dim;
245: entry->next = NULL;
246: if (!DMPlexGenerateList) DMPlexGenerateList = entry;
247: else {
248: PetscFunctionList fl = DMPlexGenerateList;
249: while (fl->next) fl = fl->next;
250: fl->next = entry;
251: }
252: return(0);
253: }
255: extern PetscBool DMPlexGenerateRegisterAllCalled;
257: PetscErrorCode DMPlexGenerateRegisterDestroy(void)
258: {
259: PetscFunctionList next,fl;
260: PetscErrorCode ierr;
263: next = fl = DMPlexGenerateList;
264: while (next) {
265: next = fl ? fl->next : NULL;
266: if (fl) {PetscFree(fl->name);}
267: PetscFree(fl);
268: fl = next;
269: }
270: DMPlexGenerateList = NULL;
271: DMPlexGenerateRegisterAllCalled = PETSC_FALSE;
272: return(0);
273: }