Actual source code: trigenerate.c
petsc-master 2020-08-25
1: #include <petsc/private/dmpleximpl.h>
3: #if !defined(ANSI_DECLARATORS)
4: #define ANSI_DECLARATORS
5: #endif
6: #include <triangle.h>
8: static PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx)
9: {
11: inputCtx->numberofpoints = 0;
12: inputCtx->numberofpointattributes = 0;
13: inputCtx->pointlist = NULL;
14: inputCtx->pointattributelist = NULL;
15: inputCtx->pointmarkerlist = NULL;
16: inputCtx->numberofsegments = 0;
17: inputCtx->segmentlist = NULL;
18: inputCtx->segmentmarkerlist = NULL;
19: inputCtx->numberoftriangleattributes = 0;
20: inputCtx->trianglelist = NULL;
21: inputCtx->numberofholes = 0;
22: inputCtx->holelist = NULL;
23: inputCtx->numberofregions = 0;
24: inputCtx->regionlist = NULL;
25: return(0);
26: }
28: static PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx)
29: {
31: outputCtx->numberofpoints = 0;
32: outputCtx->pointlist = NULL;
33: outputCtx->pointattributelist = NULL;
34: outputCtx->pointmarkerlist = NULL;
35: outputCtx->numberoftriangles = 0;
36: outputCtx->trianglelist = NULL;
37: outputCtx->triangleattributelist = NULL;
38: outputCtx->neighborlist = NULL;
39: outputCtx->segmentlist = NULL;
40: outputCtx->segmentmarkerlist = NULL;
41: outputCtx->numberofedges = 0;
42: outputCtx->edgelist = NULL;
43: outputCtx->edgemarkerlist = NULL;
44: return(0);
45: }
47: static PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx)
48: {
50: free(outputCtx->pointlist);
51: free(outputCtx->pointmarkerlist);
52: free(outputCtx->segmentlist);
53: free(outputCtx->segmentmarkerlist);
54: free(outputCtx->edgelist);
55: free(outputCtx->edgemarkerlist);
56: free(outputCtx->trianglelist);
57: free(outputCtx->neighborlist);
58: return(0);
59: }
61: PETSC_EXTERN PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm)
62: {
63: MPI_Comm comm;
64: DM_Plex *mesh = (DM_Plex *) boundary->data;
65: PetscInt dim = 2;
66: const PetscBool createConvexHull = PETSC_FALSE;
67: const PetscBool constrained = PETSC_FALSE;
68: const char *labelName = "marker";
69: const char *labelName2 = "Face Sets";
70: struct triangulateio in;
71: struct triangulateio out;
72: DMLabel label, label2;
73: PetscInt vStart, vEnd, v, eStart, eEnd, e;
74: PetscMPIInt rank;
75: PetscErrorCode ierr;
78: PetscObjectGetComm((PetscObject)boundary,&comm);
79: MPI_Comm_rank(comm, &rank);
80: InitInput_Triangle(&in);
81: InitOutput_Triangle(&out);
82: DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);
83: DMGetLabel(boundary, labelName, &label);
84: DMGetLabel(boundary, labelName2, &label2);
86: in.numberofpoints = vEnd - vStart;
87: if (in.numberofpoints > 0) {
88: PetscSection coordSection;
89: Vec coordinates;
90: PetscScalar *array;
92: PetscMalloc1(in.numberofpoints*dim, &in.pointlist);
93: PetscMalloc1(in.numberofpoints, &in.pointmarkerlist);
94: DMGetCoordinatesLocal(boundary, &coordinates);
95: DMGetCoordinateSection(boundary, &coordSection);
96: VecGetArray(coordinates, &array);
97: for (v = vStart; v < vEnd; ++v) {
98: const PetscInt idx = v - vStart;
99: PetscInt val, off, d;
101: PetscSectionGetOffset(coordSection, v, &off);
102: for (d = 0; d < dim; ++d) {
103: in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]);
104: }
105: if (label) {
106: DMLabelGetValue(label, v, &val);
107: in.pointmarkerlist[idx] = val;
108: }
109: }
110: VecRestoreArray(coordinates, &array);
111: }
112: DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);
113: in.numberofsegments = eEnd - eStart;
114: if (in.numberofsegments > 0) {
115: PetscMalloc1(in.numberofsegments*2, &in.segmentlist);
116: PetscMalloc1(in.numberofsegments, &in.segmentmarkerlist);
117: for (e = eStart; e < eEnd; ++e) {
118: const PetscInt idx = e - eStart;
119: const PetscInt *cone;
120: PetscInt val;
122: DMPlexGetCone(boundary, e, &cone);
124: in.segmentlist[idx*2+0] = cone[0] - vStart;
125: in.segmentlist[idx*2+1] = cone[1] - vStart;
127: if (label) {
128: DMLabelGetValue(label, e, &val);
129: in.segmentmarkerlist[idx] = val;
130: }
131: }
132: }
133: #if 0 /* Do not currently support holes */
134: PetscReal *holeCoords;
135: PetscInt h, d;
137: DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);
138: if (in.numberofholes > 0) {
139: PetscMalloc1(in.numberofholes*dim, &in.holelist);
140: for (h = 0; h < in.numberofholes; ++h) {
141: for (d = 0; d < dim; ++d) {
142: in.holelist[h*dim+d] = holeCoords[h*dim+d];
143: }
144: }
145: }
146: #endif
147: if (!rank) {
148: char args[32];
150: /* Take away 'Q' for verbose output */
151: PetscStrcpy(args, "pqezQ");
152: if (createConvexHull) {PetscStrcat(args, "c");}
153: if (constrained) {PetscStrcpy(args, "zepDQ");}
154: if (mesh->triangleOpts) {triangulate(mesh->triangleOpts, &in, &out, NULL);}
155: else {triangulate(args, &in, &out, NULL);}
156: }
157: PetscFree(in.pointlist);
158: PetscFree(in.pointmarkerlist);
159: PetscFree(in.segmentlist);
160: PetscFree(in.segmentmarkerlist);
161: PetscFree(in.holelist);
163: {
164: DMLabel glabel = NULL;
165: DMLabel glabel2 = NULL;
166: const PetscInt numCorners = 3;
167: const PetscInt numCells = out.numberoftriangles;
168: const PetscInt numVertices = out.numberofpoints;
169: PetscInt *cells;
170: PetscReal *meshCoords;
172: if (sizeof (PetscReal) == sizeof (out.pointlist[0])) {
173: meshCoords = (PetscReal *) out.pointlist;
174: } else {
175: PetscInt i;
177: PetscMalloc1(dim * numVertices,&meshCoords);
178: for (i = 0; i < dim * numVertices; i++) {
179: meshCoords[i] = (PetscReal) out.pointlist[i];
180: }
181: }
182: if (sizeof (PetscInt) == sizeof (out.trianglelist[0])) {
183: cells = (PetscInt *) out.trianglelist;
184: } else {
185: PetscInt i;
187: PetscMalloc1(numCells * numCorners, &cells);
188: for (i = 0; i < numCells * numCorners; i++) {
189: cells[i] = (PetscInt) out.trianglelist[i];
190: }
191: }
192: DMPlexCreateFromCellListPetsc(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);
193: if (sizeof (PetscReal) != sizeof (out.pointlist[0])) {
194: PetscFree(meshCoords);
195: }
196: if (sizeof (PetscInt) != sizeof (out.trianglelist[0])) {
197: PetscFree(cells);
198: }
199: if (label) {
200: DMCreateLabel(*dm, labelName);
201: DMGetLabel(*dm, labelName, &glabel);
202: }
203: if (label2) {
204: DMCreateLabel(*dm, labelName2);
205: DMGetLabel(*dm, labelName2, &glabel2);
206: }
207: /* Set labels */
208: for (v = 0; v < numVertices; ++v) {
209: if (out.pointmarkerlist[v]) {
210: if (glabel) {DMLabelSetValue(glabel, v+numCells, out.pointmarkerlist[v]);}
211: }
212: }
213: if (interpolate) {
214: for (e = 0; e < out.numberofedges; e++) {
215: if (out.edgemarkerlist[e]) {
216: const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells};
217: const PetscInt *edges;
218: PetscInt numEdges;
220: DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);
221: if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges);
222: if (glabel) {DMLabelSetValue(glabel, edges[0], out.edgemarkerlist[e]);}
223: if (glabel2) {DMLabelSetValue(glabel2, edges[0], out.edgemarkerlist[e]);}
224: DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);
225: }
226: }
227: }
228: DMPlexSetRefinementUniform(*dm, PETSC_FALSE);
229: }
230: #if 0 /* Do not currently support holes */
231: DMPlexCopyHoles(*dm, boundary);
232: #endif
233: FiniOutput_Triangle(&out);
234: return(0);
235: }
237: PETSC_EXTERN PetscErrorCode DMPlexRefine_Triangle(DM dm, PetscReal *inmaxVolumes, DM *dmRefined)
238: {
239: MPI_Comm comm;
240: PetscInt dim = 2;
241: const char *labelName = "marker";
242: struct triangulateio in;
243: struct triangulateio out;
244: DMLabel label;
245: PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal;
246: PetscMPIInt rank;
247: PetscErrorCode ierr;
248: double *maxVolumes;
251: PetscObjectGetComm((PetscObject)dm,&comm);
252: MPI_Comm_rank(comm, &rank);
253: InitInput_Triangle(&in);
254: InitOutput_Triangle(&out);
255: DMPlexGetDepth(dm, &depth);
256: MPIU_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);
257: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
258: DMGetLabel(dm, labelName, &label);
260: in.numberofpoints = vEnd - vStart;
261: if (in.numberofpoints > 0) {
262: PetscSection coordSection;
263: Vec coordinates;
264: PetscScalar *array;
266: PetscMalloc1(in.numberofpoints*dim, &in.pointlist);
267: PetscMalloc1(in.numberofpoints, &in.pointmarkerlist);
268: DMGetCoordinatesLocal(dm, &coordinates);
269: DMGetCoordinateSection(dm, &coordSection);
270: VecGetArray(coordinates, &array);
271: for (v = vStart; v < vEnd; ++v) {
272: const PetscInt idx = v - vStart;
273: PetscInt off, d, val;
275: PetscSectionGetOffset(coordSection, v, &off);
276: for (d = 0; d < dim; ++d) {
277: in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]);
278: }
279: if (label) {
280: DMLabelGetValue(label, v, &val);
281: in.pointmarkerlist[idx] = val;
282: }
283: }
284: VecRestoreArray(coordinates, &array);
285: }
286: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
288: in.numberofcorners = 3;
289: in.numberoftriangles = cEnd - cStart;
291: #if !defined(PETSC_USE_REAL_DOUBLE)
292: PetscMalloc1(cEnd - cStart,&maxVolumes);
293: for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = (double)inmaxVolumes[c];
294: #else
295: maxVolumes = inmaxVolumes;
296: #endif
298: in.trianglearealist = (double*) maxVolumes;
299: if (in.numberoftriangles > 0) {
300: PetscMalloc1(in.numberoftriangles*in.numberofcorners, &in.trianglelist);
301: for (c = cStart; c < cEnd; ++c) {
302: const PetscInt idx = c - cStart;
303: PetscInt *closure = NULL;
304: PetscInt closureSize;
306: DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
307: if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize);
308: for (v = 0; v < 3; ++v) {
309: in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart;
310: }
311: DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);
312: }
313: }
314: /* TODO: Segment markers are missing on input */
315: #if 0 /* Do not currently support holes */
316: PetscReal *holeCoords;
317: PetscInt h, d;
319: DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);
320: if (in.numberofholes > 0) {
321: PetscMalloc1(in.numberofholes*dim, &in.holelist);
322: for (h = 0; h < in.numberofholes; ++h) {
323: for (d = 0; d < dim; ++d) {
324: in.holelist[h*dim+d] = holeCoords[h*dim+d];
325: }
326: }
327: }
328: #endif
329: if (!rank) {
330: char args[32];
332: /* Take away 'Q' for verbose output */
333: PetscStrcpy(args, "pqezQra");
334: triangulate(args, &in, &out, NULL);
335: }
336: PetscFree(in.pointlist);
337: PetscFree(in.pointmarkerlist);
338: PetscFree(in.segmentlist);
339: PetscFree(in.segmentmarkerlist);
340: PetscFree(in.trianglelist);
342: {
343: DMLabel rlabel = NULL;
344: const PetscInt numCorners = 3;
345: const PetscInt numCells = out.numberoftriangles;
346: const PetscInt numVertices = out.numberofpoints;
347: PetscInt *cells;
348: PetscReal *meshCoords;
349: PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE;
351: if (sizeof (PetscReal) == sizeof (out.pointlist[0])) {
352: meshCoords = (PetscReal *) out.pointlist;
353: } else {
354: PetscInt i;
356: PetscMalloc1(dim * numVertices,&meshCoords);
357: for (i = 0; i < dim * numVertices; i++) {
358: meshCoords[i] = (PetscReal) out.pointlist[i];
359: }
360: }
361: if (sizeof (PetscInt) == sizeof (out.trianglelist[0])) {
362: cells = (PetscInt *) out.trianglelist;
363: } else {
364: PetscInt i;
366: PetscMalloc1(numCells * numCorners, &cells);
367: for (i = 0; i < numCells * numCorners; i++) {
368: cells[i] = (PetscInt) out.trianglelist[i];
369: }
370: }
372: DMPlexCreateFromCellListPetsc(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);
373: if (label) {
374: DMCreateLabel(*dmRefined, labelName);
375: DMGetLabel(*dmRefined, labelName, &rlabel);
376: }
377: if (sizeof (PetscReal) != sizeof (out.pointlist[0])) {
378: PetscFree(meshCoords);
379: }
380: if (sizeof (PetscInt) != sizeof (out.trianglelist[0])) {
381: PetscFree(cells);
382: }
383: /* Set labels */
384: for (v = 0; v < numVertices; ++v) {
385: if (out.pointmarkerlist[v]) {
386: if (rlabel) {DMLabelSetValue(rlabel, v+numCells, out.pointmarkerlist[v]);}
387: }
388: }
389: if (interpolate) {
390: PetscInt e;
392: for (e = 0; e < out.numberofedges; e++) {
393: if (out.edgemarkerlist[e]) {
394: const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells};
395: const PetscInt *edges;
396: PetscInt numEdges;
398: DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);
399: if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges);
400: if (rlabel) {DMLabelSetValue(rlabel, edges[0], out.edgemarkerlist[e]);}
401: DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);
402: }
403: }
404: }
405: DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);
406: }
407: #if 0 /* Do not currently support holes */
408: DMPlexCopyHoles(*dm, boundary);
409: #endif
410: FiniOutput_Triangle(&out);
411: #if !defined(PETSC_USE_REAL_DOUBLE)
412: PetscFree(maxVolumes);
413: #endif
414: return(0);
415: }