Actual source code: plexcreate.c
petsc-dev 2014-02-02
1: #define PETSCDM_DLL
2: #include <petsc-private/dmpleximpl.h> /*I "petscdmplex.h" I*/
3: #include <petscdmda.h>
4: #include <petscsf.h>
8: PetscErrorCode DMSetFromOptions_Plex(DM dm)
9: {
10: DM_Plex *mesh = (DM_Plex*) dm->data;
15: PetscOptionsHead("DMPlex Options");
16: /* Handle DMPlex refinement */
17: /* Handle associated vectors */
18: /* Handle viewing */
19: PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMView", PETSC_FALSE, &mesh->printSetValues, NULL);
20: PetscOptionsInt("-dm_plex_print_fem", "Debug output level all fem computations", "DMView", 0, &mesh->printFEM, NULL);
21: PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMView", PETSC_FALSE, &mesh->printTol, NULL);
22: PetscOptionsTail();
23: return(0);
24: }
28: /*@
29: DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement.
31: Collective on MPI_Comm
33: Input Parameters:
34: + comm - The communicator for the DM object
35: . dim - The spatial dimension
36: . simplex - Flag for simplicial cells, otherwise they are tensor product cells
37: . interpolate - Flag to create intermediate mesh pieces (edges, faces)
38: . refinementUniform - Flag for uniform parallel refinement
39: - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell
41: Output Parameter:
42: . dm - The DM object
44: Level: beginner
46: .keywords: DM, create
47: .seealso: DMSetType(), DMCreate()
48: @*/
49: PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscBool refinementUniform, PetscReal refinementLimit, DM *newdm)
50: {
51: DM dm;
52: PetscInt p;
53: PetscMPIInt rank;
57: DMCreate(comm, &dm);
58: DMSetType(dm, DMPLEX);
59: DMPlexSetDimension(dm, dim);
60: MPI_Comm_rank(comm, &rank);
61: switch (dim) {
62: case 2:
63: if (simplex) {PetscObjectSetName((PetscObject) dm, "triangular");}
64: else {PetscObjectSetName((PetscObject) dm, "quadrilateral");}
65: break;
66: case 3:
67: if (simplex) {PetscObjectSetName((PetscObject) dm, "tetrahedral");}
68: else {PetscObjectSetName((PetscObject) dm, "hexahedral");}
69: break;
70: default:
71: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %d", dim);
72: }
73: if (rank) {
74: PetscInt numPoints[2] = {0, 0};
75: DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL);
76: } else {
77: switch (dim) {
78: case 2:
79: if (simplex) {
80: PetscInt numPoints[2] = {4, 2};
81: PetscInt coneSize[6] = {3, 3, 0, 0, 0, 0};
82: PetscInt cones[6] = {2, 3, 4, 5, 4, 3};
83: PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0};
84: PetscScalar vertexCoords[8] = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5};
85: PetscInt markerPoints[8] = {2, 1, 3, 1, 4, 1, 5, 1};
87: DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);
88: for (p = 0; p < 4; ++p) {DMPlexSetLabelValue(dm, "marker", markerPoints[p*2], markerPoints[p*2+1]);}
89: } else {
90: PetscInt numPoints[2] = {6, 2};
91: PetscInt coneSize[8] = {4, 4, 0, 0, 0, 0, 0, 0};
92: PetscInt cones[8] = {2, 3, 4, 5, 3, 6, 7, 4};
93: PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
94: PetscScalar vertexCoords[12] = {-1.0, -0.5, 0.0, -0.5, 0.0, 0.5, -1.0, 0.5, 1.0, -0.5, 1.0, 0.5};
96: DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);
97: }
98: break;
99: case 3:
100: if (simplex) {
101: PetscInt numPoints[2] = {5, 2};
102: PetscInt coneSize[7] = {4, 4, 0, 0, 0, 0, 0};
103: PetscInt cones[8] = {4, 3, 5, 2, 5, 3, 4, 6};
104: PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
105: PetscScalar vertexCoords[15] = {-1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0};
106: PetscInt markerPoints[10] = {2, 1, 3, 1, 4, 1, 5, 1, 6, 1};
108: DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);
109: for (p = 0; p < 5; ++p) {DMPlexSetLabelValue(dm, "marker", markerPoints[p*2], markerPoints[p*2+1]);}
110: } else {
111: PetscInt numPoints[2] = {12, 2};
112: PetscInt coneSize[14] = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
113: PetscInt cones[16] = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8};
114: PetscInt coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
115: PetscScalar vertexCoords[36] = {-1.0, -0.5, -0.5, -1.0, 0.5, -0.5, 0.0, 0.5, -0.5, 0.0, -0.5, -0.5,
116: -1.0, -0.5, 0.5, 0.0, -0.5, 0.5, 0.0, 0.5, 0.5, -1.0, 0.5, 0.5,
117: 1.0, 0.5, -0.5, 1.0, -0.5, -0.5, 1.0, -0.5, 0.5, 1.0, 0.5, 0.5};
119: DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);
120: }
121: break;
122: default:
123: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %d", dim);
124: }
125: }
126: *newdm = dm;
127: if (refinementLimit > 0.0) {
128: DM rdm;
129: const char *name;
131: DMPlexSetRefinementUniform(*newdm, PETSC_FALSE);
132: DMPlexSetRefinementLimit(*newdm, refinementLimit);
133: DMRefine(*newdm, comm, &rdm);
134: PetscObjectGetName((PetscObject) *newdm, &name);
135: PetscObjectSetName((PetscObject) rdm, name);
136: DMDestroy(newdm);
137: *newdm = rdm;
138: }
139: if (interpolate) {
140: DM idm;
141: const char *name;
143: DMPlexInterpolate(*newdm, &idm);
144: PetscObjectGetName((PetscObject) *newdm, &name);
145: PetscObjectSetName((PetscObject) idm, name);
146: DMPlexCopyCoordinates(*newdm, idm);
147: DMPlexCopyLabels(*newdm, idm);
148: DMDestroy(newdm);
149: *newdm = idm;
150: }
151: {
152: DM refinedMesh = NULL;
153: DM distributedMesh = NULL;
155: /* Distribute mesh over processes */
156: DMPlexDistribute(*newdm, NULL, 0, NULL, &distributedMesh);
157: if (distributedMesh) {
158: DMDestroy(newdm);
159: *newdm = distributedMesh;
160: }
161: if (refinementUniform) {
162: DMPlexSetRefinementUniform(*newdm, refinementUniform);
163: DMRefine(*newdm, comm, &refinedMesh);
164: if (refinedMesh) {
165: DMDestroy(newdm);
166: *newdm = refinedMesh;
167: }
168: }
169: }
170: return(0);
171: }
175: /*
176: Simple square boundary:
178: 18--5-17--4--16
179: | | |
180: 6 10 3
181: | | |
182: 19-11-20--9--15
183: | | |
184: 7 8 2
185: | | |
186: 12--0-13--1--14
187: */
188: PetscErrorCode DMPlexCreateSquareBoundary(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[])
189: {
190: PetscInt numVertices = (edges[0]+1)*(edges[1]+1);
191: PetscInt numEdges = edges[0]*(edges[1]+1) + (edges[0]+1)*edges[1];
192: PetscInt markerTop = 1;
193: PetscInt markerBottom = 1;
194: PetscInt markerRight = 1;
195: PetscInt markerLeft = 1;
196: PetscBool markerSeparate = PETSC_FALSE;
197: Vec coordinates;
198: PetscSection coordSection;
199: PetscScalar *coords;
200: PetscInt coordSize;
201: PetscMPIInt rank;
202: PetscInt v, vx, vy;
206: PetscOptionsGetBool(((PetscObject) dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL);
207: if (markerSeparate) {
208: markerTop = 1;
209: markerBottom = 0;
210: markerRight = 0;
211: markerLeft = 0;
212: }
213: MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);
214: if (!rank) {
215: PetscInt e, ex, ey;
217: DMPlexSetChart(dm, 0, numEdges+numVertices);
218: for (e = 0; e < numEdges; ++e) {
219: DMPlexSetConeSize(dm, e, 2);
220: }
221: DMSetUp(dm); /* Allocate space for cones */
222: for (vx = 0; vx <= edges[0]; vx++) {
223: for (ey = 0; ey < edges[1]; ey++) {
224: PetscInt edge = vx*edges[1] + ey + edges[0]*(edges[1]+1);
225: PetscInt vertex = ey*(edges[0]+1) + vx + numEdges;
226: PetscInt cone[2];
228: cone[0] = vertex; cone[1] = vertex+edges[0]+1;
229: DMPlexSetCone(dm, edge, cone);
230: if (vx == edges[0]) {
231: DMPlexSetLabelValue(dm, "marker", edge, markerRight);
232: DMPlexSetLabelValue(dm, "marker", cone[0], markerRight);
233: if (ey == edges[1]-1) {
234: DMPlexSetLabelValue(dm, "marker", cone[1], markerRight);
235: }
236: } else if (vx == 0) {
237: DMPlexSetLabelValue(dm, "marker", edge, markerLeft);
238: DMPlexSetLabelValue(dm, "marker", cone[0], markerLeft);
239: if (ey == edges[1]-1) {
240: DMPlexSetLabelValue(dm, "marker", cone[1], markerLeft);
241: }
242: }
243: }
244: }
245: for (vy = 0; vy <= edges[1]; vy++) {
246: for (ex = 0; ex < edges[0]; ex++) {
247: PetscInt edge = vy*edges[0] + ex;
248: PetscInt vertex = vy*(edges[0]+1) + ex + numEdges;
249: PetscInt cone[2];
251: cone[0] = vertex; cone[1] = vertex+1;
252: DMPlexSetCone(dm, edge, cone);
253: if (vy == edges[1]) {
254: DMPlexSetLabelValue(dm, "marker", edge, markerTop);
255: DMPlexSetLabelValue(dm, "marker", cone[0], markerTop);
256: if (ex == edges[0]-1) {
257: DMPlexSetLabelValue(dm, "marker", cone[1], markerTop);
258: }
259: } else if (vy == 0) {
260: DMPlexSetLabelValue(dm, "marker", edge, markerBottom);
261: DMPlexSetLabelValue(dm, "marker", cone[0], markerBottom);
262: if (ex == edges[0]-1) {
263: DMPlexSetLabelValue(dm, "marker", cone[1], markerBottom);
264: }
265: }
266: }
267: }
268: }
269: DMPlexSymmetrize(dm);
270: DMPlexStratify(dm);
271: /* Build coordinates */
272: DMGetCoordinateSection(dm, &coordSection);
273: PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices);
274: for (v = numEdges; v < numEdges+numVertices; ++v) {
275: PetscSectionSetDof(coordSection, v, 2);
276: }
277: PetscSectionSetUp(coordSection);
278: PetscSectionGetStorageSize(coordSection, &coordSize);
279: VecCreate(PetscObjectComm((PetscObject)dm), &coordinates);
280: VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);
281: VecSetType(coordinates,VECSTANDARD);
282: VecGetArray(coordinates, &coords);
283: for (vy = 0; vy <= edges[1]; ++vy) {
284: for (vx = 0; vx <= edges[0]; ++vx) {
285: coords[(vy*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/edges[0])*vx;
286: coords[(vy*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/edges[1])*vy;
287: }
288: }
289: VecRestoreArray(coordinates, &coords);
290: DMSetCoordinatesLocal(dm, coordinates);
291: VecDestroy(&coordinates);
292: return(0);
293: }
297: /*
298: Simple cubic boundary:
300: 2-------3
301: /| /|
302: 6-------7 |
303: | | | |
304: | 0-----|-1
305: |/ |/
306: 4-------5
307: */
308: PetscErrorCode DMPlexCreateCubeBoundary(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[])
309: {
310: PetscInt numVertices = (faces[0]+1)*(faces[1]+1)*(faces[2]+1);
311: PetscInt numFaces = 6;
312: Vec coordinates;
313: PetscSection coordSection;
314: PetscScalar *coords;
315: PetscInt coordSize;
316: PetscMPIInt rank;
317: PetscInt v, vx, vy, vz;
321: if ((faces[0] < 1) || (faces[1] < 1) || (faces[2] < 1)) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Must have at least 1 face per side");
322: if ((faces[0] > 1) || (faces[1] > 1) || (faces[2] > 1)) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Currently can't handle more than 1 face per side");
323: MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);
324: if (!rank) {
325: PetscInt f;
327: DMPlexSetChart(dm, 0, numFaces+numVertices);
328: for (f = 0; f < numFaces; ++f) {
329: DMPlexSetConeSize(dm, f, 4);
330: }
331: DMSetUp(dm); /* Allocate space for cones */
332: for (v = 0; v < numFaces+numVertices; ++v) {
333: DMPlexSetLabelValue(dm, "marker", v, 1);
334: }
335: { /* Side 0 (Front) */
336: PetscInt cone[4];
337: cone[0] = numFaces+4; cone[1] = numFaces+5; cone[2] = numFaces+7; cone[3] = numFaces+6;
338: DMPlexSetCone(dm, 0, cone);
339: }
340: { /* Side 1 (Back) */
341: PetscInt cone[4];
342: cone[0] = numFaces+1; cone[1] = numFaces+0; cone[2] = numFaces+2; cone[3] = numFaces+3;
343: DMPlexSetCone(dm, 1, cone);
344: }
345: { /* Side 2 (Bottom) */
346: PetscInt cone[4];
347: cone[0] = numFaces+0; cone[1] = numFaces+1; cone[2] = numFaces+5; cone[3] = numFaces+4;
348: DMPlexSetCone(dm, 2, cone);
349: }
350: { /* Side 3 (Top) */
351: PetscInt cone[4];
352: cone[0] = numFaces+6; cone[1] = numFaces+7; cone[2] = numFaces+3; cone[3] = numFaces+2;
353: DMPlexSetCone(dm, 3, cone);
354: }
355: { /* Side 4 (Left) */
356: PetscInt cone[4];
357: cone[0] = numFaces+0; cone[1] = numFaces+4; cone[2] = numFaces+6; cone[3] = numFaces+2;
358: DMPlexSetCone(dm, 4, cone);
359: }
360: { /* Side 5 (Right) */
361: PetscInt cone[4];
362: cone[0] = numFaces+5; cone[1] = numFaces+1; cone[2] = numFaces+3; cone[3] = numFaces+7;
363: DMPlexSetCone(dm, 5, cone);
364: }
365: }
366: DMPlexSymmetrize(dm);
367: DMPlexStratify(dm);
368: /* Build coordinates */
369: DMGetCoordinateSection(dm, &coordSection);
370: PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices);
371: for (v = numFaces; v < numFaces+numVertices; ++v) {
372: PetscSectionSetDof(coordSection, v, 3);
373: }
374: PetscSectionSetUp(coordSection);
375: PetscSectionGetStorageSize(coordSection, &coordSize);
376: VecCreate(PetscObjectComm((PetscObject)dm), &coordinates);
377: PetscObjectSetName((PetscObject) coordinates, "coordinates");
378: VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);
379: VecSetType(coordinates,VECSTANDARD);
380: VecGetArray(coordinates, &coords);
381: for (vz = 0; vz <= faces[2]; ++vz) {
382: for (vy = 0; vy <= faces[1]; ++vy) {
383: for (vx = 0; vx <= faces[0]; ++vx) {
384: coords[((vz*(faces[1]+1)+vy)*(faces[0]+1)+vx)*3+0] = lower[0] + ((upper[0] - lower[0])/faces[0])*vx;
385: coords[((vz*(faces[1]+1)+vy)*(faces[0]+1)+vx)*3+1] = lower[1] + ((upper[1] - lower[1])/faces[1])*vy;
386: coords[((vz*(faces[1]+1)+vy)*(faces[0]+1)+vx)*3+2] = lower[2] + ((upper[2] - lower[2])/faces[2])*vz;
387: }
388: }
389: }
390: VecRestoreArray(coordinates, &coords);
391: DMSetCoordinatesLocal(dm, coordinates);
392: VecDestroy(&coordinates);
393: return(0);
394: }
398: /*
399: Simple square mesh:
401: 22--8-23--9--24
402: | | |
403: 13 2 14 3 15
404: | | |
405: 19--6-20--7--21
406: | | |
407: 10 0 11 1 12
408: | | |
409: 16--4-17--5--18
410: */
411: PetscErrorCode DMPlexCreateSquareMesh(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[])
412: {
413: PetscInt markerTop = 1;
414: PetscInt markerBottom = 1;
415: PetscInt markerRight = 1;
416: PetscInt markerLeft = 1;
417: PetscBool markerSeparate = PETSC_FALSE;
418: PetscMPIInt rank;
422: MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);
423: PetscOptionsGetBool(((PetscObject) dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL);
424: if (markerSeparate) {
425: markerTop = 3;
426: markerBottom = 1;
427: markerRight = 2;
428: markerLeft = 4;
429: }
430: {
431: const PetscInt numXEdges = !rank ? edges[0] : 0;
432: const PetscInt numYEdges = !rank ? edges[1] : 0;
433: const PetscInt numXVertices = !rank ? edges[0]+1 : 0;
434: const PetscInt numYVertices = !rank ? edges[1]+1 : 0;
435: const PetscInt numTotXEdges = numXEdges*numYVertices;
436: const PetscInt numTotYEdges = numYEdges*numXVertices;
437: const PetscInt numVertices = numXVertices*numYVertices;
438: const PetscInt numEdges = numTotXEdges + numTotYEdges;
439: const PetscInt numFaces = numXEdges*numYEdges;
440: const PetscInt firstVertex = numFaces;
441: const PetscInt firstXEdge = numFaces + numVertices;
442: const PetscInt firstYEdge = numFaces + numVertices + numTotXEdges;
443: Vec coordinates;
444: PetscSection coordSection;
445: PetscScalar *coords;
446: PetscInt coordSize;
447: PetscInt v, vx, vy;
448: PetscInt f, fx, fy, e, ex, ey;
450: DMPlexSetChart(dm, 0, numFaces+numEdges+numVertices);
451: for (f = 0; f < numFaces; ++f) {
452: DMPlexSetConeSize(dm, f, 4);
453: }
454: for (e = firstXEdge; e < firstXEdge+numEdges; ++e) {
455: DMPlexSetConeSize(dm, e, 2);
456: }
457: DMSetUp(dm); /* Allocate space for cones */
458: /* Build faces */
459: for (fy = 0; fy < numYEdges; fy++) {
460: for (fx = 0; fx < numXEdges; fx++) {
461: const PetscInt face = fy*numXEdges + fx;
462: const PetscInt edgeL = firstYEdge + fx*numYEdges + fy;
463: const PetscInt edgeB = firstXEdge + fy*numXEdges + fx;
464: const PetscInt ornt[4] = {0, 0, -2, -2};
465: PetscInt cone[4];
467: cone[0] = edgeB; cone[1] = edgeL+numYEdges; cone[2] = edgeB+numXEdges; cone[3] = edgeL;
468: DMPlexSetCone(dm, face, cone);
469: DMPlexSetConeOrientation(dm, face, ornt);
470: }
471: }
472: /* Build Y edges*/
473: for (vx = 0; vx < numXVertices; vx++) {
474: for (ey = 0; ey < numYEdges; ey++) {
475: const PetscInt edge = firstYEdge + vx*numYEdges + ey;
476: const PetscInt vertex = firstVertex + ey*numXVertices + vx;
477: PetscInt cone[2];
479: cone[0] = vertex; cone[1] = vertex+numXVertices;
480: DMPlexSetCone(dm, edge, cone);
481: if (vx == numXVertices-1) {
482: DMPlexSetLabelValue(dm, "marker", edge, markerRight);
483: DMPlexSetLabelValue(dm, "marker", cone[0], markerRight);
484: if (ey == numYEdges-1) {
485: DMPlexSetLabelValue(dm, "marker", cone[1], markerRight);
486: }
487: } else if (vx == 0) {
488: DMPlexSetLabelValue(dm, "marker", edge, markerLeft);
489: DMPlexSetLabelValue(dm, "marker", cone[0], markerLeft);
490: if (ey == numYEdges-1) {
491: DMPlexSetLabelValue(dm, "marker", cone[1], markerLeft);
492: }
493: }
494: }
495: }
496: /* Build X edges*/
497: for (vy = 0; vy < numYVertices; vy++) {
498: for (ex = 0; ex < numXEdges; ex++) {
499: const PetscInt edge = firstXEdge + vy*numXEdges + ex;
500: const PetscInt vertex = firstVertex + vy*numXVertices + ex;
501: PetscInt cone[2];
503: cone[0] = vertex; cone[1] = vertex+1;
504: DMPlexSetCone(dm, edge, cone);
505: if (vy == numYVertices-1) {
506: DMPlexSetLabelValue(dm, "marker", edge, markerTop);
507: DMPlexSetLabelValue(dm, "marker", cone[0], markerTop);
508: if (ex == numXEdges-1) {
509: DMPlexSetLabelValue(dm, "marker", cone[1], markerTop);
510: }
511: } else if (vy == 0) {
512: DMPlexSetLabelValue(dm, "marker", edge, markerBottom);
513: DMPlexSetLabelValue(dm, "marker", cone[0], markerBottom);
514: if (ex == numXEdges-1) {
515: DMPlexSetLabelValue(dm, "marker", cone[1], markerBottom);
516: }
517: }
518: }
519: }
520: DMPlexSymmetrize(dm);
521: DMPlexStratify(dm);
522: /* Build coordinates */
523: DMGetCoordinateSection(dm, &coordSection);
524: PetscSectionSetChart(coordSection, firstVertex, firstVertex+numVertices);
525: for (v = firstVertex; v < firstVertex+numVertices; ++v) {
526: PetscSectionSetDof(coordSection, v, 2);
527: }
528: PetscSectionSetUp(coordSection);
529: PetscSectionGetStorageSize(coordSection, &coordSize);
530: VecCreate(PetscObjectComm((PetscObject)dm), &coordinates);
531: VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);
532: VecSetType(coordinates,VECSTANDARD);
533: VecGetArray(coordinates, &coords);
534: for (vy = 0; vy < numYVertices; ++vy) {
535: for (vx = 0; vx < numXVertices; ++vx) {
536: coords[(vy*numXVertices+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/numXEdges)*vx;
537: coords[(vy*numXVertices+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/numYEdges)*vy;
538: }
539: }
540: VecRestoreArray(coordinates, &coords);
541: DMSetCoordinatesLocal(dm, coordinates);
542: VecDestroy(&coordinates);
543: }
544: return(0);
545: }
549: /*@
550: DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box).
552: Collective on MPI_Comm
554: Input Parameters:
555: + comm - The communicator for the DM object
556: . dim - The spatial dimension
557: - interpolate - Flag to create intermediate mesh pieces (edges, faces)
559: Output Parameter:
560: . dm - The DM object
562: Level: beginner
564: .keywords: DM, create
565: .seealso: DMSetType(), DMCreate()
566: @*/
567: PetscErrorCode DMPlexCreateBoxMesh(MPI_Comm comm, PetscInt dim, PetscBool interpolate, DM *dm)
568: {
569: DM boundary;
574: DMCreate(comm, &boundary);
576: DMSetType(boundary, DMPLEX);
577: DMPlexSetDimension(boundary, dim-1);
578: switch (dim) {
579: case 2:
580: {
581: PetscReal lower[2] = {0.0, 0.0};
582: PetscReal upper[2] = {1.0, 1.0};
583: PetscInt edges[2] = {2, 2};
585: DMPlexCreateSquareBoundary(boundary, lower, upper, edges);
586: break;
587: }
588: case 3:
589: {
590: PetscReal lower[3] = {0.0, 0.0, 0.0};
591: PetscReal upper[3] = {1.0, 1.0, 1.0};
592: PetscInt faces[3] = {1, 1, 1};
594: DMPlexCreateCubeBoundary(boundary, lower, upper, faces);
595: break;
596: }
597: default:
598: SETERRQ1(comm, PETSC_ERR_SUP, "Dimension not supported: %d", dim);
599: }
600: DMPlexGenerate(boundary, NULL, interpolate, dm);
601: DMDestroy(&boundary);
602: return(0);
603: }
607: PetscErrorCode DMPlexCreateHexBoxMesh(MPI_Comm comm, PetscInt dim, const PetscInt cells[], DM *dm)
608: {
613: DMCreate(comm, dm);
615: DMSetType(*dm, DMPLEX);
616: DMPlexSetDimension(*dm, dim);
617: switch (dim) {
618: case 2:
619: {
620: PetscReal lower[2] = {0.0, 0.0};
621: PetscReal upper[2] = {1.0, 1.0};
623: DMPlexCreateSquareMesh(*dm, lower, upper, cells);
624: break;
625: }
626: #if 0
627: case 3:
628: {
629: PetscReal lower[3] = {0.0, 0.0, 0.0};
630: PetscReal upper[3] = {1.0, 1.0, 1.0};
632: DMPlexCreateCubeMesh(boundary, lower, upper, cells);
633: break;
634: }
635: #endif
636: default:
637: SETERRQ1(comm, PETSC_ERR_SUP, "Dimension not supported: %d", dim);
638: }
639: return(0);
640: }
642: /* External function declarations here */
643: extern PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling);
644: extern PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J);
645: extern PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm);
646: extern PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined);
647: extern PetscErrorCode DMClone_Plex(DM dm, DM *newdm);
648: extern PetscErrorCode DMSetUp_Plex(DM dm);
649: extern PetscErrorCode DMDestroy_Plex(DM dm);
650: extern PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer);
651: extern PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm);
652: extern PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS);
656: static PetscErrorCode DMCreateGlobalVector_Plex(DM dm,Vec *vec)
657: {
661: DMCreateGlobalVector_Section_Private(dm,vec);
662: /* VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM); */
663: VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex);
664: return(0);
665: }
669: static PetscErrorCode DMCreateLocalVector_Plex(DM dm,Vec *vec)
670: {
674: DMCreateLocalVector_Section_Private(dm,vec);
675: VecSetOperation(*vec, VECOP_VIEW, (void(*)(void)) VecView_Plex_Local);
676: return(0);
677: }
681: PetscErrorCode DMInitialize_Plex(DM dm)
682: {
684: dm->ops->view = DMView_Plex;
685: dm->ops->setfromoptions = DMSetFromOptions_Plex;
686: dm->ops->clone = DMClone_Plex;
687: dm->ops->setup = DMSetUp_Plex;
688: dm->ops->createglobalvector = DMCreateGlobalVector_Plex;
689: dm->ops->createlocalvector = DMCreateLocalVector_Plex;
690: dm->ops->getlocaltoglobalmapping = NULL;
691: dm->ops->getlocaltoglobalmappingblock = NULL;
692: dm->ops->createfieldis = NULL;
693: dm->ops->createcoordinatedm = DMCreateCoordinateDM_Plex;
694: dm->ops->getcoloring = 0;
695: dm->ops->creatematrix = DMCreateMatrix_Plex;
696: dm->ops->createinterpolation = 0;
697: dm->ops->getaggregates = 0;
698: dm->ops->getinjection = 0;
699: dm->ops->refine = DMRefine_Plex;
700: dm->ops->coarsen = 0;
701: dm->ops->refinehierarchy = 0;
702: dm->ops->coarsenhierarchy = 0;
703: dm->ops->globaltolocalbegin = NULL;
704: dm->ops->globaltolocalend = NULL;
705: dm->ops->localtoglobalbegin = NULL;
706: dm->ops->localtoglobalend = NULL;
707: dm->ops->destroy = DMDestroy_Plex;
708: dm->ops->createsubdm = DMCreateSubDM_Plex;
709: dm->ops->locatepoints = DMLocatePoints_Plex;
710: return(0);
711: }
715: PetscErrorCode DMClone_Plex(DM dm, DM *newdm)
716: {
717: DM_Plex *mesh = (DM_Plex *) dm->data;
721: mesh->refct++;
722: (*newdm)->data = mesh;
723: PetscObjectChangeTypeName((PetscObject) *newdm, DMPLEX);
724: DMInitialize_Plex(*newdm);
725: return(0);
726: }
728: /*MC
729: DMPLEX = "plex" - A DM object that encapsulates an unstructured mesh, or CW Complex, which can be expressed using a Hasse Diagram.
730: In the local representation, Vecs contain all unknowns in the interior and shared boundary. This is
731: specified by a PetscSection object. Ownership in the global representation is determined by
732: ownership of the underlying DMPlex points. This is specified by another PetscSection object.
734: Level: intermediate
736: .seealso: DMType, DMPlexCreate(), DMCreate(), DMSetType()
737: M*/
741: PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm)
742: {
743: DM_Plex *mesh;
744: PetscInt unit, d;
749: PetscNewLog(dm,&mesh);
750: dm->data = mesh;
752: mesh->refct = 1;
753: mesh->dim = 0;
754: PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection);
755: mesh->maxConeSize = 0;
756: mesh->cones = NULL;
757: mesh->coneOrientations = NULL;
758: PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection);
759: mesh->maxSupportSize = 0;
760: mesh->supports = NULL;
761: mesh->refinementUniform = PETSC_TRUE;
762: mesh->refinementLimit = -1.0;
764: mesh->facesTmp = NULL;
766: mesh->subpointMap = NULL;
768: for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0;
770: mesh->labels = NULL;
771: mesh->depthLabel = NULL;
772: mesh->globalVertexNumbers = NULL;
773: mesh->globalCellNumbers = NULL;
774: for (d = 0; d < 8; ++d) mesh->hybridPointMax[d] = PETSC_DETERMINE;
775: mesh->vtkCellHeight = 0;
776: mesh->preallocCenterDim = -1;
778: mesh->printSetValues = PETSC_FALSE;
779: mesh->printFEM = 0;
780: mesh->printTol = 1.0e-10;
782: DMInitialize_Plex(dm);
783: return(0);
784: }
788: /*@
789: DMPlexCreate - Creates a DMPlex object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram.
791: Collective on MPI_Comm
793: Input Parameter:
794: . comm - The communicator for the DMPlex object
796: Output Parameter:
797: . mesh - The DMPlex object
799: Level: beginner
801: .keywords: DMPlex, create
802: @*/
803: PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh)
804: {
809: DMCreate(comm, mesh);
810: DMSetType(*mesh, DMPLEX);
811: return(0);
812: }
816: /*
817: This takes as input the common mesh generator output, a list of the vertices for each cell
818: */
819: PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[])
820: {
821: PetscInt *cone, c, p;
825: DMPlexSetChart(dm, 0, numCells+numVertices);
826: for (c = 0; c < numCells; ++c) {
827: DMPlexSetConeSize(dm, c, numCorners);
828: }
829: DMSetUp(dm);
830: DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);
831: for (c = 0; c < numCells; ++c) {
832: for (p = 0; p < numCorners; ++p) {
833: cone[p] = cells[c*numCorners+p]+numCells;
834: }
835: DMPlexSetCone(dm, c, cone);
836: }
837: DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);
838: DMPlexSymmetrize(dm);
839: DMPlexStratify(dm);
840: return(0);
841: }
845: /*
846: This takes as input the coordinates for each vertex
847: */
848: PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[])
849: {
850: PetscSection coordSection;
851: Vec coordinates;
852: PetscScalar *coords;
853: PetscInt coordSize, v, d;
857: DMGetCoordinateSection(dm, &coordSection);
858: PetscSectionSetNumFields(coordSection, 1);
859: PetscSectionSetFieldComponents(coordSection, 0, spaceDim);
860: PetscSectionSetChart(coordSection, numCells, numCells + numVertices);
861: for (v = numCells; v < numCells+numVertices; ++v) {
862: PetscSectionSetDof(coordSection, v, spaceDim);
863: PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);
864: }
865: PetscSectionSetUp(coordSection);
866: PetscSectionGetStorageSize(coordSection, &coordSize);
867: VecCreate(PetscObjectComm((PetscObject)dm), &coordinates);
868: PetscObjectSetName((PetscObject) coordinates, "coordinates");
869: VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);
870: VecSetType(coordinates,VECSTANDARD);
871: VecGetArray(coordinates, &coords);
872: for (v = 0; v < numVertices; ++v) {
873: for (d = 0; d < spaceDim; ++d) {
874: coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d];
875: }
876: }
877: VecRestoreArray(coordinates, &coords);
878: DMSetCoordinatesLocal(dm, coordinates);
879: VecDestroy(&coordinates);
880: return(0);
881: }
885: /*@C
886: DMPlexCreateFromCellList - This takes as input common mesh generator output, a list of the vertices for each cell, and produces a DM
888: Input Parameters:
889: + comm - The communicator
890: . dim - The topological dimension of the mesh
891: . numCells - The number of cells
892: . numVertices - The number of vertices
893: . numCorners - The number of vertices for each cell
894: . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
895: . cells - An array of numCells*numCorners numbers, the vertices for each cell
896: . spaceDim - The spatial dimension used for coordinates
897: - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
899: Output Parameter:
900: . dm - The DM
902: Note: Two triangles sharing a face
903: $
904: $ 2
905: $ / | \
906: $ / | \
907: $ / | \
908: $ 0 0 | 1 3
909: $ \ | /
910: $ \ | /
911: $ \ | /
912: $ 1
913: would have input
914: $ numCells = 2, numVertices = 4
915: $ cells = [0 1 2 1 3 2]
916: $
917: which would result in the DMPlex
918: $
919: $ 4
920: $ / | \
921: $ / | \
922: $ / | \
923: $ 2 0 | 1 5
924: $ \ | /
925: $ \ | /
926: $ \ | /
927: $ 3
929: Level: beginner
931: .seealso: DMPlexCreateFromDAG(), DMPlexCreate()
932: @*/
933: PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], PetscInt spaceDim, const double vertexCoords[], DM *dm)
934: {
938: DMCreate(comm, dm);
939: DMSetType(*dm, DMPLEX);
940: DMPlexSetDimension(*dm, dim);
941: DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);
942: if (interpolate) {
943: DM idm;
945: DMPlexInterpolate(*dm, &idm);
946: DMDestroy(dm);
947: *dm = idm;
948: }
949: DMPlexBuildCoordinates_Private(*dm, spaceDim, numCells, numVertices, vertexCoords);
950: return(0);
951: }
955: /*@
956: DMPlexCreateFromDAG - This takes as input the adjacency-list representation of the Directed Acyclic Graph (Hasse Diagram) encoding a mesh, and produces a DM
958: Input Parameters:
959: + dm - The empty DM object, usually from DMCreate() and DMPlexSetDimension()
960: . depth - The depth of the DAG
961: . numPoints - The number of points at each depth
962: . coneSize - The cone size of each point
963: . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point
964: . coneOrientations - The orientation of each cone point
965: - vertexCoords - An array of numVertices*dim numbers, the coordinates of each vertex
967: Output Parameter:
968: . dm - The DM
970: Note: Two triangles sharing a face would have input
971: $ depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0]
972: $ cones = [2 3 4 3 5 4], coneOrientations = [0 0 0 0 0 0]
973: $ vertexCoords = [-1.0 0.0 0.0 -1.0 0.0 1.0 1.0 0.0]
974: $
975: which would result in the DMPlex
976: $
977: $ 4
978: $ / | \
979: $ / | \
980: $ / | \
981: $ 2 0 | 1 5
982: $ \ | /
983: $ \ | /
984: $ \ | /
985: $ 3
986: $
987: $ Notice that all points are numbered consecutively, unlikely DMPlexCreateFromCellList()
989: Level: advanced
991: .seealso: DMPlexCreateFromCellList(), DMPlexCreate()
992: @*/
993: PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[])
994: {
995: Vec coordinates;
996: PetscSection coordSection;
997: PetscScalar *coords;
998: PetscInt coordSize, firstVertex = numPoints[depth], pStart = 0, pEnd = 0, p, v, dim, d, off;
1002: DMPlexGetDimension(dm, &dim);
1003: for (d = 0; d <= depth; ++d) pEnd += numPoints[d];
1004: DMPlexSetChart(dm, pStart, pEnd);
1005: for (p = pStart; p < pEnd; ++p) {
1006: DMPlexSetConeSize(dm, p, coneSize[p-pStart]);
1007: }
1008: DMSetUp(dm); /* Allocate space for cones */
1009: for (p = pStart, off = 0; p < pEnd; off += coneSize[p-pStart], ++p) {
1010: DMPlexSetCone(dm, p, &cones[off]);
1011: DMPlexSetConeOrientation(dm, p, &coneOrientations[off]);
1012: }
1013: DMPlexSymmetrize(dm);
1014: DMPlexStratify(dm);
1015: /* Build coordinates */
1016: DMGetCoordinateSection(dm, &coordSection);
1017: PetscSectionSetNumFields(coordSection, 1);
1018: PetscSectionSetFieldComponents(coordSection, 0, dim);
1019: PetscSectionSetChart(coordSection, firstVertex, firstVertex+numPoints[0]);
1020: for (v = firstVertex; v < firstVertex+numPoints[0]; ++v) {
1021: PetscSectionSetDof(coordSection, v, dim);
1022: PetscSectionSetFieldDof(coordSection, v, 0, dim);
1023: }
1024: PetscSectionSetUp(coordSection);
1025: PetscSectionGetStorageSize(coordSection, &coordSize);
1026: VecCreate(PetscObjectComm((PetscObject)dm), &coordinates);
1027: PetscObjectSetName((PetscObject) coordinates, "coordinates");
1028: VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);
1029: VecSetType(coordinates,VECSTANDARD);
1030: VecGetArray(coordinates, &coords);
1031: for (v = 0; v < numPoints[0]; ++v) {
1032: PetscInt off;
1034: PetscSectionGetOffset(coordSection, v+firstVertex, &off);
1035: for (d = 0; d < dim; ++d) {
1036: coords[off+d] = vertexCoords[v*dim+d];
1037: }
1038: }
1039: VecRestoreArray(coordinates, &coords);
1040: DMSetCoordinatesLocal(dm, coordinates);
1041: VecDestroy(&coordinates);
1042: return(0);
1043: }