Actual source code: plexcreate.c

petsc-dev 2014-02-02
Report Typos and Errors
  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: }