Actual source code: plexsubmesh.c
petsc-dev 2014-02-02
1: #include <petsc-private/dmpleximpl.h> /*I "petscdmplex.h" I*/
2: #include <petscsf.h>
6: /*@
7: DMPlexMarkBoundaryFaces - Mark all faces on the boundary
9: Not Collective
11: Input Parameter:
12: . dm - The original DM
14: Output Parameter:
15: . label - The DMLabel marking boundary faces with value 1
17: Level: developer
19: .seealso: DMLabelCreate(), DMPlexCreateLabel()
20: @*/
21: PetscErrorCode DMPlexMarkBoundaryFaces(DM dm, DMLabel label)
22: {
23: PetscInt fStart, fEnd, f;
28: DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
29: for (f = fStart; f < fEnd; ++f) {
30: PetscInt supportSize;
32: DMPlexGetSupportSize(dm, f, &supportSize);
33: if (supportSize == 1) {
34: DMLabelSetValue(label, f, 1);
35: }
36: }
37: return(0);
38: }
42: /*@
43: DMPlexLabelComplete - Starting with a label marking points on a surface, we add the transitive closure to the surface
45: Input Parameters:
46: + dm - The DM
47: - label - A DMLabel marking the surface points
49: Output Parameter:
50: . label - A DMLabel marking all surface points in the transitive closure
52: Level: developer
54: .seealso: DMPlexLabelCohesiveComplete()
55: @*/
56: PetscErrorCode DMPlexLabelComplete(DM dm, DMLabel label)
57: {
58: IS valueIS;
59: const PetscInt *values;
60: PetscInt numValues, v;
61: PetscErrorCode ierr;
64: DMLabelGetNumValues(label, &numValues);
65: DMLabelGetValueIS(label, &valueIS);
66: ISGetIndices(valueIS, &values);
67: for (v = 0; v < numValues; ++v) {
68: IS pointIS;
69: const PetscInt *points;
70: PetscInt numPoints, p;
72: DMLabelGetStratumSize(label, values[v], &numPoints);
73: DMLabelGetStratumIS(label, values[v], &pointIS);
74: ISGetIndices(pointIS, &points);
75: for (p = 0; p < numPoints; ++p) {
76: PetscInt *closure = NULL;
77: PetscInt closureSize, c;
79: DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure);
80: for (c = 0; c < closureSize*2; c += 2) {
81: DMLabelSetValue(label, closure[c], values[v]);
82: }
83: DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure);
84: }
85: ISRestoreIndices(pointIS, &points);
86: ISDestroy(&pointIS);
87: }
88: ISRestoreIndices(valueIS, &values);
89: ISDestroy(&valueIS);
90: return(0);
91: }
95: PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Internal(PetscInt p, PetscInt depth, PetscInt depthMax[], PetscInt depthEnd[], PetscInt depthShift[])
96: {
97: if (depth < 0) return p;
98: /* Normal Cells */ if (p < depthMax[depth]) return p;
99: /* Hybrid Cells+Normal Vertices */ if (p < depthMax[0]) return p + depthShift[depth];
100: /* Hybrid Vertices+Normal Faces */ if (depth < 2 || p < depthMax[depth-1]) return p + depthShift[depth] + depthShift[0];
101: /* Hybrid Faces+Normal Edges */ if (depth < 3 || p < depthMax[depth-2]) return p + depthShift[depth] + depthShift[0] + depthShift[depth-1];
102: /* Hybrid Edges */ return p + depthShift[depth] + depthShift[0] + depthShift[depth-1] + depthShift[depth-2];
103: }
107: static PetscErrorCode DMPlexShiftSizes_Internal(DM dm, PetscInt depthShift[], DM dmNew)
108: {
109: PetscInt *depthMax, *depthEnd;
110: PetscInt depth = 0, d, pStart, pEnd, p;
114: DMPlexGetDepth(dm, &depth);
115: if (depth < 0) return(0);
116: PetscMalloc2(depth+1,&depthMax,depth+1,&depthEnd);
117: /* Step 1: Expand chart */
118: DMPlexGetChart(dm, &pStart, &pEnd);
119: DMPlexGetHybridBounds(dm, &depthMax[depth], depth > 0 ? &depthMax[depth-1] : NULL, &depthMax[1], &depthMax[0]);
120: for (d = 0; d <= depth; ++d) {
121: pEnd += depthShift[d];
122: DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);
123: depthMax[d] = depthMax[d] < 0 ? depthEnd[d] : depthMax[d];
124: }
125: DMPlexSetChart(dmNew, pStart, pEnd);
126: /* Step 2: Set cone and support sizes */
127: for (d = 0; d <= depth; ++d) {
128: DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);
129: for (p = pStart; p < pEnd; ++p) {
130: PetscInt newp = DMPlexShiftPoint_Internal(p, depth, depthMax, depthEnd, depthShift);
131: PetscInt size;
133: DMPlexGetConeSize(dm, p, &size);
134: DMPlexSetConeSize(dmNew, newp, size);
135: DMPlexGetSupportSize(dm, p, &size);
136: DMPlexSetSupportSize(dmNew, newp, size);
137: }
138: }
139: PetscFree2(depthMax,depthEnd);
140: return(0);
141: }
145: static PetscErrorCode DMPlexShiftPoints_Internal(DM dm, PetscInt depthShift[], DM dmNew)
146: {
147: PetscInt *depthEnd, *depthMax, *newpoints;
148: PetscInt depth = 0, d, maxConeSize, maxSupportSize, maxConeSizeNew, maxSupportSizeNew, pStart, pEnd, p;
152: DMPlexGetDepth(dm, &depth);
153: if (depth < 0) return(0);
154: DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);
155: DMPlexGetMaxSizes(dmNew, &maxConeSizeNew, &maxSupportSizeNew);
156: PetscMalloc3(depth+1,&depthEnd,depth+1,&depthMax,PetscMax(PetscMax(maxConeSize, maxSupportSize), PetscMax(maxConeSizeNew, maxSupportSizeNew)),&newpoints);
157: DMPlexGetHybridBounds(dm, &depthMax[depth], depth > 0 ? &depthMax[depth-1] : NULL, &depthMax[1], &depthMax[0]);
158: for (d = 0; d <= depth; ++d) {
159: DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);
160: depthMax[d] = depthMax[d] < 0 ? depthEnd[d] : depthMax[d];
161: }
162: /* Step 5: Set cones and supports */
163: DMPlexGetChart(dm, &pStart, &pEnd);
164: for (p = pStart; p < pEnd; ++p) {
165: const PetscInt *points = NULL, *orientations = NULL;
166: PetscInt size,sizeNew, i, newp = DMPlexShiftPoint_Internal(p, depth, depthMax, depthEnd, depthShift);
168: DMPlexGetConeSize(dm, p, &size);
169: DMPlexGetCone(dm, p, &points);
170: DMPlexGetConeOrientation(dm, p, &orientations);
171: for (i = 0; i < size; ++i) {
172: newpoints[i] = DMPlexShiftPoint_Internal(points[i], depth, depthMax, depthEnd, depthShift);
173: }
174: DMPlexSetCone(dmNew, newp, newpoints);
175: DMPlexSetConeOrientation(dmNew, newp, orientations);
176: DMPlexGetSupportSize(dm, p, &size);
177: DMPlexGetSupportSize(dmNew, newp, &sizeNew);
178: DMPlexGetSupport(dm, p, &points);
179: for (i = 0; i < size; ++i) {
180: newpoints[i] = DMPlexShiftPoint_Internal(points[i], depth, depthMax, depthEnd, depthShift);
181: }
182: for (i = size; i < sizeNew; ++i) newpoints[i] = 0;
183: DMPlexSetSupport(dmNew, newp, newpoints);
184: }
185: PetscFree3(depthEnd,depthMax,newpoints);
186: return(0);
187: }
191: static PetscErrorCode DMPlexShiftCoordinates_Internal(DM dm, PetscInt depthShift[], DM dmNew)
192: {
193: PetscSection coordSection, newCoordSection;
194: Vec coordinates, newCoordinates;
195: PetscScalar *coords, *newCoords;
196: PetscInt *depthEnd, coordSize;
197: PetscInt dim, depth = 0, d, vStart, vEnd, vStartNew, vEndNew, v;
201: DMPlexGetDimension(dm, &dim);
202: DMPlexGetDepth(dm, &depth);
203: PetscMalloc1((depth+1), &depthEnd);
204: for (d = 0; d <= depth; ++d) {
205: DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);
206: }
207: /* Step 8: Convert coordinates */
208: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
209: DMPlexGetDepthStratum(dmNew, 0, &vStartNew, &vEndNew);
210: DMGetCoordinateSection(dm, &coordSection);
211: PetscSectionCreate(PetscObjectComm((PetscObject)dm), &newCoordSection);
212: PetscSectionSetNumFields(newCoordSection, 1);
213: PetscSectionSetFieldComponents(newCoordSection, 0, dim);
214: PetscSectionSetChart(newCoordSection, vStartNew, vEndNew);
215: for (v = vStartNew; v < vEndNew; ++v) {
216: PetscSectionSetDof(newCoordSection, v, dim);
217: PetscSectionSetFieldDof(newCoordSection, v, 0, dim);
218: }
219: PetscSectionSetUp(newCoordSection);
220: DMSetCoordinateSection(dmNew, newCoordSection);
221: PetscSectionGetStorageSize(newCoordSection, &coordSize);
222: VecCreate(PetscObjectComm((PetscObject)dm), &newCoordinates);
223: PetscObjectSetName((PetscObject) newCoordinates, "coordinates");
224: VecSetSizes(newCoordinates, coordSize, PETSC_DETERMINE);
225: VecSetType(newCoordinates,VECSTANDARD);
226: DMSetCoordinatesLocal(dmNew, newCoordinates);
227: DMGetCoordinatesLocal(dm, &coordinates);
228: VecGetArray(coordinates, &coords);
229: VecGetArray(newCoordinates, &newCoords);
230: for (v = vStart; v < vEnd; ++v) {
231: PetscInt dof, off, noff, d;
233: PetscSectionGetDof(coordSection, v, &dof);
234: PetscSectionGetOffset(coordSection, v, &off);
235: PetscSectionGetOffset(newCoordSection, DMPlexShiftPoint_Internal(v, depth, depthEnd, depthEnd, depthShift), &noff);
236: for (d = 0; d < dof; ++d) {
237: newCoords[noff+d] = coords[off+d];
238: }
239: }
240: VecRestoreArray(coordinates, &coords);
241: VecRestoreArray(newCoordinates, &newCoords);
242: VecDestroy(&newCoordinates);
243: PetscSectionDestroy(&newCoordSection);
244: PetscFree(depthEnd);
245: return(0);
246: }
250: static PetscErrorCode DMPlexShiftSF_Internal(DM dm, PetscInt depthShift[], DM dmNew)
251: {
252: PetscInt *depthMax, *depthEnd;
253: PetscInt depth = 0, d;
254: PetscSF sfPoint, sfPointNew;
255: const PetscSFNode *remotePoints;
256: PetscSFNode *gremotePoints;
257: const PetscInt *localPoints;
258: PetscInt *glocalPoints, *newLocation, *newRemoteLocation;
259: PetscInt numRoots, numLeaves, l, pStart, pEnd, totShift = 0;
260: PetscErrorCode ierr;
263: DMPlexGetDepth(dm, &depth);
264: PetscMalloc2(depth+1,&depthMax,depth+1,&depthEnd);
265: DMPlexGetHybridBounds(dm, depth >= 0 ? &depthMax[depth] : NULL, depth>1 ? &depthMax[depth-1] : NULL, depth>2 ? &depthMax[1] : NULL, depth >= 0 ? &depthMax[0] : NULL);
266: for (d = 0; d <= depth; ++d) {
267: totShift += depthShift[d];
268: DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);
269: depthMax[d] = depthMax[d] < 0 ? depthEnd[d] : depthMax[d];
270: }
271: /* Step 9: Convert pointSF */
272: DMGetPointSF(dm, &sfPoint);
273: DMGetPointSF(dmNew, &sfPointNew);
274: DMPlexGetChart(dm, &pStart, &pEnd);
275: PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);
276: if (numRoots >= 0) {
277: PetscMalloc2(numRoots,&newLocation,pEnd-pStart,&newRemoteLocation);
278: for (l=0; l<numRoots; l++) newLocation[l] = DMPlexShiftPoint_Internal(l, depth, depthMax, depthEnd, depthShift);
279: PetscSFBcastBegin(sfPoint, MPIU_INT, newLocation, newRemoteLocation);
280: PetscSFBcastEnd(sfPoint, MPIU_INT, newLocation, newRemoteLocation);
281: PetscMalloc1(numLeaves, &glocalPoints);
282: PetscMalloc1(numLeaves, &gremotePoints);
283: for (l = 0; l < numLeaves; ++l) {
284: glocalPoints[l] = DMPlexShiftPoint_Internal(localPoints[l], depth, depthMax, depthEnd, depthShift);
285: gremotePoints[l].rank = remotePoints[l].rank;
286: gremotePoints[l].index = newRemoteLocation[localPoints[l]];
287: }
288: PetscFree2(newLocation,newRemoteLocation);
289: PetscSFSetGraph(sfPointNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER);
290: }
291: PetscFree2(depthMax,depthEnd);
292: return(0);
293: }
297: static PetscErrorCode DMPlexShiftLabels_Internal(DM dm, PetscInt depthShift[], DM dmNew)
298: {
299: PetscSF sfPoint;
300: DMLabel vtkLabel, ghostLabel;
301: PetscInt *depthMax, *depthEnd;
302: const PetscSFNode *leafRemote;
303: const PetscInt *leafLocal;
304: PetscInt depth = 0, d, numLeaves, numLabels, l, cStart, cEnd, c, fStart, fEnd, f;
305: PetscMPIInt rank;
306: PetscErrorCode ierr;
309: DMPlexGetDepth(dm, &depth);
310: PetscMalloc2(depth+1,&depthMax,depth+1,&depthEnd);
311: DMPlexGetHybridBounds(dm, depth >= 0 ? &depthMax[depth] : NULL, depth>1 ? &depthMax[depth-1] : NULL, depth>2 ? &depthMax[1] : NULL, depth >= 0 ? &depthMax[0] : NULL);
312: for (d = 0; d <= depth; ++d) {
313: DMPlexGetDepthStratum(dm, d, NULL, &depthEnd[d]);
314: depthMax[d] = depthMax[d] < 0 ? depthEnd[d] : depthMax[d];
315: }
316: /* Step 10: Convert labels */
317: DMPlexGetNumLabels(dm, &numLabels);
318: for (l = 0; l < numLabels; ++l) {
319: DMLabel label, newlabel;
320: const char *lname;
321: PetscBool isDepth;
322: IS valueIS;
323: const PetscInt *values;
324: PetscInt numValues, val;
326: DMPlexGetLabelName(dm, l, &lname);
327: PetscStrcmp(lname, "depth", &isDepth);
328: if (isDepth) continue;
329: DMPlexCreateLabel(dmNew, lname);
330: DMPlexGetLabel(dm, lname, &label);
331: DMPlexGetLabel(dmNew, lname, &newlabel);
332: DMLabelGetValueIS(label, &valueIS);
333: ISGetLocalSize(valueIS, &numValues);
334: ISGetIndices(valueIS, &values);
335: for (val = 0; val < numValues; ++val) {
336: IS pointIS;
337: const PetscInt *points;
338: PetscInt numPoints, p;
340: DMLabelGetStratumIS(label, values[val], &pointIS);
341: ISGetLocalSize(pointIS, &numPoints);
342: ISGetIndices(pointIS, &points);
343: for (p = 0; p < numPoints; ++p) {
344: const PetscInt newpoint = DMPlexShiftPoint_Internal(points[p], depth, depthMax, depthEnd, depthShift);
346: DMLabelSetValue(newlabel, newpoint, values[val]);
347: }
348: ISRestoreIndices(pointIS, &points);
349: ISDestroy(&pointIS);
350: }
351: ISRestoreIndices(valueIS, &values);
352: ISDestroy(&valueIS);
353: }
354: PetscFree2(depthMax,depthEnd);
355: /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */
356: MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);
357: DMGetPointSF(dm, &sfPoint);
358: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
359: PetscSFGetGraph(sfPoint, NULL, &numLeaves, &leafLocal, &leafRemote);
360: DMPlexCreateLabel(dmNew, "vtk");
361: DMPlexCreateLabel(dmNew, "ghost");
362: DMPlexGetLabel(dmNew, "vtk", &vtkLabel);
363: DMPlexGetLabel(dmNew, "ghost", &ghostLabel);
364: for (l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) {
365: for (; c < leafLocal[l] && c < cEnd; ++c) {
366: DMLabelSetValue(vtkLabel, c, 1);
367: }
368: if (leafLocal[l] >= cEnd) break;
369: if (leafRemote[l].rank == rank) {
370: DMLabelSetValue(vtkLabel, c, 1);
371: } else {
372: DMLabelSetValue(ghostLabel, c, 2);
373: }
374: }
375: for (; c < cEnd; ++c) {
376: DMLabelSetValue(vtkLabel, c, 1);
377: }
378: if (0) {
379: PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);
380: DMLabelView(vtkLabel, PETSC_VIEWER_STDOUT_WORLD);
381: PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);
382: }
383: DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd);
384: for (f = fStart; f < fEnd; ++f) {
385: PetscInt numCells;
387: DMPlexGetSupportSize(dmNew, f, &numCells);
388: if (numCells < 2) {
389: DMLabelSetValue(ghostLabel, f, 1);
390: } else {
391: const PetscInt *cells = NULL;
392: PetscInt vA, vB;
394: DMPlexGetSupport(dmNew, f, &cells);
395: DMLabelGetValue(vtkLabel, cells[0], &vA);
396: DMLabelGetValue(vtkLabel, cells[1], &vB);
397: if (!vA && !vB) {DMLabelSetValue(ghostLabel, f, 1);}
398: }
399: }
400: if (0) {
401: PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);
402: DMLabelView(ghostLabel, PETSC_VIEWER_STDOUT_WORLD);
403: PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);
404: }
405: return(0);
406: }
410: static PetscErrorCode DMPlexConstructGhostCells_Internal(DM dm, DMLabel label, PetscInt *numGhostCells, DM gdm)
411: {
412: IS valueIS;
413: const PetscInt *values;
414: PetscInt *depthShift;
415: PetscInt depth = 0, numFS, fs, fStart, fEnd, ghostCell, cEnd, c;
416: PetscErrorCode ierr;
419: DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
420: /* Count ghost cells */
421: DMLabelGetValueIS(label, &valueIS);
422: ISGetLocalSize(valueIS, &numFS);
423: ISGetIndices(valueIS, &values);
424: *numGhostCells = 0;
425: for (fs = 0; fs < numFS; ++fs) {
426: IS faceIS;
427: const PetscInt *faces;
428: PetscInt numFaces, f, numBdFaces = 0;
430: DMLabelGetStratumIS(label, values[fs], &faceIS);
431: ISGetLocalSize(faceIS, &numFaces);
432: ISGetIndices(faceIS, &faces);
433: for (f = 0; f < numFaces; ++f) {
434: if ((faces[f] >= fStart) && (faces[f] < fEnd)) ++numBdFaces;
435: }
436: *numGhostCells += numBdFaces;
437: ISDestroy(&faceIS);
438: }
439: DMPlexGetDepth(dm, &depth);
440: PetscMalloc1((depth+1), &depthShift);
441: PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));
442: if (depth >= 0) depthShift[depth] = *numGhostCells;
443: DMPlexShiftSizes_Internal(dm, depthShift, gdm);
444: /* Step 3: Set cone/support sizes for new points */
445: DMPlexGetHeightStratum(dm, 0, NULL, &cEnd);
446: for (c = cEnd; c < cEnd + *numGhostCells; ++c) {
447: DMPlexSetConeSize(gdm, c, 1);
448: }
449: for (fs = 0; fs < numFS; ++fs) {
450: IS faceIS;
451: const PetscInt *faces;
452: PetscInt numFaces, f;
454: DMLabelGetStratumIS(label, values[fs], &faceIS);
455: ISGetLocalSize(faceIS, &numFaces);
456: ISGetIndices(faceIS, &faces);
457: for (f = 0; f < numFaces; ++f) {
458: PetscInt size;
460: if ((faces[f] < fStart) || (faces[f] >= fEnd)) continue;
461: DMPlexGetSupportSize(dm, faces[f], &size);
462: if (size != 1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "DM has boundary face %d with %d support cells", faces[f], size);
463: DMPlexSetSupportSize(gdm, faces[f] + *numGhostCells, 2);
464: }
465: ISRestoreIndices(faceIS, &faces);
466: ISDestroy(&faceIS);
467: }
468: /* Step 4: Setup ghosted DM */
469: DMSetUp(gdm);
470: DMPlexShiftPoints_Internal(dm, depthShift, gdm);
471: /* Step 6: Set cones and supports for new points */
472: ghostCell = cEnd;
473: for (fs = 0; fs < numFS; ++fs) {
474: IS faceIS;
475: const PetscInt *faces;
476: PetscInt numFaces, f;
478: DMLabelGetStratumIS(label, values[fs], &faceIS);
479: ISGetLocalSize(faceIS, &numFaces);
480: ISGetIndices(faceIS, &faces);
481: for (f = 0; f < numFaces; ++f) {
482: PetscInt newFace = faces[f] + *numGhostCells;
484: if ((faces[f] < fStart) || (faces[f] >= fEnd)) continue;
485: DMPlexSetCone(gdm, ghostCell, &newFace);
486: DMPlexInsertSupport(gdm, newFace, 1, ghostCell);
487: ++ghostCell;
488: }
489: ISRestoreIndices(faceIS, &faces);
490: ISDestroy(&faceIS);
491: }
492: ISRestoreIndices(valueIS, &values);
493: ISDestroy(&valueIS);
494: /* Step 7: Stratify */
495: DMPlexStratify(gdm);
496: DMPlexShiftCoordinates_Internal(dm, depthShift, gdm);
497: DMPlexShiftSF_Internal(dm, depthShift, gdm);
498: DMPlexShiftLabels_Internal(dm, depthShift, gdm);
499: PetscFree(depthShift);
500: return(0);
501: }
505: /*@C
506: DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face
508: Collective on dm
510: Input Parameters:
511: + dm - The original DM
512: - labelName - The label specifying the boundary faces, or "Face Sets" if this is NULL
514: Output Parameters:
515: + numGhostCells - The number of ghost cells added to the DM
516: - dmGhosted - The new DM
518: Note: If no label exists of that name, one will be created marking all boundary faces
520: Level: developer
522: .seealso: DMCreate()
523: @*/
524: PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted)
525: {
526: DM gdm;
527: DMLabel label;
528: const char *name = labelName ? labelName : "Face Sets";
529: PetscInt dim;
536: DMCreate(PetscObjectComm((PetscObject)dm), &gdm);
537: DMSetType(gdm, DMPLEX);
538: DMPlexGetDimension(dm, &dim);
539: DMPlexSetDimension(gdm, dim);
540: DMPlexGetLabel(dm, name, &label);
541: if (!label) {
542: /* Get label for boundary faces */
543: DMPlexCreateLabel(dm, name);
544: DMPlexGetLabel(dm, name, &label);
545: DMPlexMarkBoundaryFaces(dm, label);
546: }
547: DMPlexConstructGhostCells_Internal(dm, label, numGhostCells, gdm);
548: DMSetFromOptions(gdm);
549: *dmGhosted = gdm;
550: return(0);
551: }
555: /*
556: We are adding three kinds of points here:
557: Replicated: Copies of points which exist in the mesh, such as vertices identified across a fault
558: Non-replicated: Points which exist on the fault, but are not replicated
559: Hybrid: Entirely new points, such as cohesive cells
561: When creating subsequent cohesive cells, we shift the old hybrid cells to the end of the numbering at
562: each depth so that the new split/hybrid points can be inserted as a block.
563: */
564: static PetscErrorCode DMPlexConstructCohesiveCells_Internal(DM dm, DMLabel label, DM sdm)
565: {
566: MPI_Comm comm;
567: IS valueIS;
568: PetscInt numSP = 0; /* The number of depths for which we have replicated points */
569: const PetscInt *values; /* List of depths for which we have replicated points */
570: IS *splitIS;
571: IS *unsplitIS;
572: PetscInt *numSplitPoints; /* The number of replicated points at each depth */
573: PetscInt *numUnsplitPoints; /* The number of non-replicated points at each depth which still give rise to hybrid points */
574: PetscInt *numHybridPoints; /* The number of new hybrid points at each depth */
575: PetscInt *numHybridPointsOld; /* The number of existing hybrid points at each depth */
576: const PetscInt **splitPoints; /* Replicated points for each depth */
577: const PetscInt **unsplitPoints; /* Non-replicated points for each depth */
578: PetscSection coordSection;
579: Vec coordinates;
580: PetscScalar *coords;
581: PetscInt depths[4]; /* Depths in the order that plex points are numbered */
582: PetscInt *depthMax; /* The first hybrid point at each depth in the original mesh */
583: PetscInt *depthEnd; /* The point limit at each depth in the original mesh */
584: PetscInt *depthShift; /* Number of replicated+hybrid points at each depth */
585: PetscInt *depthOffset; /* Prefix sums of depthShift */
586: PetscInt *pMaxNew; /* The first replicated point at each depth in the new mesh, hybrids come after this */
587: PetscInt *coneNew, *coneONew, *supportNew;
588: PetscInt shift = 100, shift2 = 200, depth = 0, dep, dim, d, sp, maxConeSize, maxSupportSize, maxConeSizeNew, maxSupportSizeNew, numLabels, vStart, vEnd, pEnd, p, v;
589: PetscErrorCode ierr;
592: PetscObjectGetComm((PetscObject)dm,&comm);
593: DMPlexGetDimension(dm, &dim);
594: DMPlexGetDepth(dm, &depth);
595: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
596: depths[0] = depth;
597: depths[1] = 0;
598: depths[2] = depth-1;
599: depths[3] = 1;
600: /* Count split points and add cohesive cells */
601: DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);
602: PetscMalloc6(depth+1,&depthMax,depth+1,&depthEnd,depth+1,&depthShift,depth+1,&depthOffset,depth+1,&pMaxNew,depth+1,&numHybridPointsOld);
603: PetscMalloc7(depth+1,&splitIS,depth+1,&unsplitIS,depth+1,&numSplitPoints,depth+1,&numUnsplitPoints,depth+1,&numHybridPoints,depth+1,&splitPoints,depth+1,&unsplitPoints);
604: PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));
605: PetscMemzero(depthOffset, (depth+1) * sizeof(PetscInt));
606: DMPlexGetHybridBounds(dm, depth >= 0 ? &depthMax[depth] : NULL, depth>1 ? &depthMax[depth-1] : NULL, depth>2 ? &depthMax[1] : NULL, depth >= 0 ? &depthMax[0] : NULL);
607: for (d = 0; d <= depth; ++d) {
608: DMPlexGetDepthStratum(dm, d, NULL, &pMaxNew[d]);
609: depthEnd[d] = pMaxNew[d];
610: depthMax[d] = depthMax[d] < 0 ? depthEnd[d] : depthMax[d];
611: numSplitPoints[d] = 0;
612: numUnsplitPoints[d] = 0;
613: numHybridPoints[d] = 0;
614: numHybridPointsOld[d] = depthMax[d] < 0 ? 0 : depthEnd[d] - depthMax[d];
615: splitPoints[d] = NULL;
616: unsplitPoints[d] = NULL;
617: splitIS[d] = NULL;
618: unsplitIS[d] = NULL;
619: }
620: if (label) {
621: DMLabelGetValueIS(label, &valueIS);
622: ISGetLocalSize(valueIS, &numSP);
623: ISGetIndices(valueIS, &values);
624: }
625: for (sp = 0; sp < numSP; ++sp) {
626: const PetscInt dep = values[sp];
628: if ((dep < 0) || (dep > depth)) continue;
629: DMLabelGetStratumIS(label, dep, &splitIS[dep]);
630: if (splitIS[dep]) {
631: ISGetLocalSize(splitIS[dep], &numSplitPoints[dep]);
632: ISGetIndices(splitIS[dep], &splitPoints[dep]);
633: }
634: DMLabelGetStratumIS(label, shift2+dep, &unsplitIS[dep]);
635: if (unsplitIS[dep]) {
636: ISGetLocalSize(unsplitIS[dep], &numUnsplitPoints[dep]);
637: ISGetIndices(unsplitIS[dep], &unsplitPoints[dep]);
638: }
639: }
640: /* Calculate number of hybrid points */
641: for (d = 1; d <= depth; ++d) numHybridPoints[d] = numSplitPoints[d-1] + numUnsplitPoints[d-1]; /* There is a hybrid cell/face/edge for every split face/edge/vertex */
642: for (d = 0; d <= depth; ++d) depthShift[d] = numSplitPoints[d] + numHybridPoints[d];
643: for (d = 1; d <= depth; ++d) depthOffset[depths[d]] = depthOffset[depths[d-1]] + depthShift[depths[d-1]];
644: for (d = 0; d <= depth; ++d) pMaxNew[d] += depthOffset[d] - numHybridPointsOld[d];
645: DMPlexShiftSizes_Internal(dm, depthShift, sdm);
646: /* Step 3: Set cone/support sizes for new points */
647: for (dep = 0; dep <= depth; ++dep) {
648: for (p = 0; p < numSplitPoints[dep]; ++p) {
649: const PetscInt oldp = splitPoints[dep][p];
650: const PetscInt newp = DMPlexShiftPoint_Internal(oldp, depth, depthMax, depthEnd, depthShift) /*oldp + depthOffset[dep]*/;
651: const PetscInt splitp = p + pMaxNew[dep];
652: const PetscInt *support;
653: PetscInt coneSize, supportSize, qf, qn, qp, e;
655: DMPlexGetConeSize(dm, oldp, &coneSize);
656: DMPlexSetConeSize(sdm, splitp, coneSize);
657: DMPlexGetSupportSize(dm, oldp, &supportSize);
658: DMPlexSetSupportSize(sdm, splitp, supportSize);
659: if (dep == depth-1) {
660: const PetscInt hybcell = p + pMaxNew[dep+1] + numSplitPoints[dep+1];
662: /* Add cohesive cells, they are prisms */
663: DMPlexSetConeSize(sdm, hybcell, 2 + coneSize);
664: } else if (dep == 0) {
665: const PetscInt hybedge = p + pMaxNew[dep+1] + numSplitPoints[dep+1];
667: DMPlexGetSupport(dm, oldp, &support);
668: for (e = 0, qn = 0, qp = 0, qf = 0; e < supportSize; ++e) {
669: PetscInt val;
671: DMLabelGetValue(label, support[e], &val);
672: if (val == 1) ++qf;
673: if ((val == 1) || (val == (shift + 1))) ++qn;
674: if ((val == 1) || (val == -(shift + 1))) ++qp;
675: }
676: /* Split old vertex: Edges into original vertex and new cohesive edge */
677: DMPlexSetSupportSize(sdm, newp, qn+1);
678: /* Split new vertex: Edges into split vertex and new cohesive edge */
679: DMPlexSetSupportSize(sdm, splitp, qp+1);
680: /* Add hybrid edge */
681: DMPlexSetConeSize(sdm, hybedge, 2);
682: DMPlexSetSupportSize(sdm, hybedge, qf);
683: } else if (dep == dim-2) {
684: const PetscInt hybface = p + pMaxNew[dep+1] + numSplitPoints[dep+1];
686: DMPlexGetSupport(dm, oldp, &support);
687: for (e = 0, qn = 0, qp = 0, qf = 0; e < supportSize; ++e) {
688: PetscInt val;
690: DMLabelGetValue(label, support[e], &val);
691: if (val == dim-1) ++qf;
692: if ((val == dim-1) || (val == (shift + dim-1))) ++qn;
693: if ((val == dim-1) || (val == -(shift + dim-1))) ++qp;
694: }
695: /* Split old edge: Faces into original edge and cohesive face (positive side?) */
696: DMPlexSetSupportSize(sdm, newp, qn+1);
697: /* Split new edge: Faces into split edge and cohesive face (negative side?) */
698: DMPlexSetSupportSize(sdm, splitp, qp+1);
699: /* Add hybrid face */
700: DMPlexSetConeSize(sdm, hybface, 4);
701: DMPlexSetSupportSize(sdm, hybface, qf);
702: }
703: }
704: }
705: for (dep = 0; dep <= depth; ++dep) {
706: for (p = 0; p < numUnsplitPoints[dep]; ++p) {
707: const PetscInt oldp = unsplitPoints[dep][p];
708: const PetscInt newp = DMPlexShiftPoint_Internal(oldp, depth, depthMax, depthEnd, depthShift) /*oldp + depthOffset[dep]*/;
709: const PetscInt *support;
710: PetscInt coneSize, supportSize, qf, qn, qp, e;
712: DMPlexGetConeSize(dm, oldp, &coneSize);
713: DMPlexGetSupportSize(dm, oldp, &supportSize);
714: if (dep == 0) {
715: const PetscInt hybedge = p + pMaxNew[dep+1] + numSplitPoints[dep+1] + numSplitPoints[dep];
717: /* Unsplit vertex: Edges into original vertex, split edge, and new cohesive edge twice */
718: DMPlexSetSupportSize(sdm, newp, supportSize+3);
719: /* Add hybrid edge */
720: DMPlexSetConeSize(sdm, hybedge, 2);
721: DMPlexGetSupport(dm, oldp, &support);
722: for (e = 0, qf = 0; e < supportSize; ++e) {
723: PetscInt val;
725: DMLabelGetValue(label, support[e], &val);
726: /* Split and unsplit edges produce hybrid faces */
727: if ((val == 1) || (val == (shift2 + 1))) ++qf;
728: }
729: DMPlexSetSupportSize(sdm, hybedge, qf);
730: } else if (dep == dim-2) {
731: const PetscInt hybface = p + pMaxNew[dep+1] + numSplitPoints[dep+1] + numSplitPoints[dep];
733: DMPlexGetSupport(dm, oldp, &support);
734: for (e = 0, qn = 0, qp = 0, qf = 0; e < supportSize; ++e) {
735: PetscInt val;
737: DMLabelGetValue(label, support[e], &val);
738: if (val == dim-1) ++qf;
739: if ((val == dim-1) || (val == (shift + dim-1))) ++qn;
740: if ((val == dim-1) || (val == -(shift + dim-1))) ++qp;
741: }
742: /* Unsplit edge: Faces into original edge, split face, and cohesive face twice */
743: DMPlexSetSupportSize(sdm, newp, supportSize+3);
744: /* Add hybrid face */
745: DMPlexSetConeSize(sdm, hybface, 4);
746: /* TODO: Here we should check for neighboring faults for which this is unsplit */
747: DMPlexSetSupportSize(sdm, hybface, 1);
748: }
749: }
750: }
751: /* Step 4: Setup split DM */
752: DMSetUp(sdm);
753: DMPlexShiftPoints_Internal(dm, depthShift, sdm);
754: DMPlexGetMaxSizes(sdm, &maxConeSizeNew, &maxSupportSizeNew);
755: PetscMalloc3(PetscMax(maxConeSize, maxConeSizeNew)*3,&coneNew,PetscMax(maxConeSize, maxConeSizeNew)*3,&coneONew,PetscMax(maxSupportSize, maxSupportSizeNew),&supportNew);
756: /* Step 6: Set cones and supports for new points */
757: for (dep = 0; dep <= depth; ++dep) {
758: for (p = 0; p < numSplitPoints[dep]; ++p) {
759: const PetscInt oldp = splitPoints[dep][p];
760: const PetscInt newp = DMPlexShiftPoint_Internal(oldp, depth, depthMax, depthEnd, depthShift) /*oldp + depthOffset[dep]*/;
761: const PetscInt splitp = p + pMaxNew[dep];
762: const PetscInt *cone, *support, *ornt;
763: PetscInt coneSize, supportSize, q, qf, qn, qp, v, e, s;
765: DMPlexGetConeSize(dm, oldp, &coneSize);
766: DMPlexGetCone(dm, oldp, &cone);
767: DMPlexGetConeOrientation(dm, oldp, &ornt);
768: DMPlexGetSupportSize(dm, oldp, &supportSize);
769: DMPlexGetSupport(dm, oldp, &support);
770: if (dep == depth-1) {
771: const PetscInt hybcell = p + pMaxNew[dep+1] + numSplitPoints[dep+1];
772: const PetscInt *supportF;
774: /* Split face: copy in old face to new face to start */
775: DMPlexGetSupport(sdm, newp, &supportF);
776: DMPlexSetSupport(sdm, splitp, supportF);
777: /* Split old face: old vertices/edges in cone so no change */
778: /* Split new face: new vertices/edges in cone */
779: for (q = 0; q < coneSize; ++q) {
780: PetscFindInt(cone[q], numSplitPoints[dep-1], splitPoints[dep-1], &v);
781: if (v < 0) {
782: PetscFindInt(cone[q], numUnsplitPoints[dep-1], unsplitPoints[dep-1], &v);
783: if (v < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not locate point %d in split or unsplit points of depth %d", cone[q], dep-1);
784: coneNew[2+q] = DMPlexShiftPoint_Internal(cone[q], depth, depthMax, depthEnd, depthShift) /*cone[q] + depthOffset[dep-1]*/;
785: } else {
786: coneNew[2+q] = v + pMaxNew[dep-1];
787: }
788: }
789: DMPlexSetCone(sdm, splitp, &coneNew[2]);
790: DMPlexSetConeOrientation(sdm, splitp, ornt);
791: /* Face support */
792: for (s = 0; s < supportSize; ++s) {
793: PetscInt val;
795: DMLabelGetValue(label, support[s], &val);
796: if (val < 0) {
797: /* Split old face: Replace negative side cell with cohesive cell */
798: DMPlexInsertSupport(sdm, newp, s, hybcell);
799: } else {
800: /* Split new face: Replace positive side cell with cohesive cell */
801: DMPlexInsertSupport(sdm, splitp, s, hybcell);
802: /* Get orientation for cohesive face */
803: {
804: const PetscInt *ncone, *nconeO;
805: PetscInt nconeSize, nc;
807: DMPlexGetConeSize(dm, support[s], &nconeSize);
808: DMPlexGetCone(dm, support[s], &ncone);
809: DMPlexGetConeOrientation(dm, support[s], &nconeO);
810: for (nc = 0; nc < nconeSize; ++nc) {
811: if (ncone[nc] == oldp) {
812: coneONew[0] = nconeO[nc];
813: break;
814: }
815: }
816: if (nc >= nconeSize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not locate face %d in neighboring cell %d", oldp, support[s]);
817: }
818: }
819: }
820: /* Cohesive cell: Old and new split face, then new cohesive faces */
821: coneNew[0] = newp; /* Extracted negative side orientation above */
822: coneNew[1] = splitp;
823: coneONew[1] = coneONew[0];
824: for (q = 0; q < coneSize; ++q) {
825: PetscFindInt(cone[q], numSplitPoints[dep-1], splitPoints[dep-1], &v);
826: if (v < 0) {
827: PetscFindInt(cone[q], numUnsplitPoints[dep-1], unsplitPoints[dep-1], &v);
828: coneNew[2+q] = v + pMaxNew[dep] + numSplitPoints[dep] + numSplitPoints[dep-1];
829: coneONew[2+q] = 0;
830: } else {
831: coneNew[2+q] = v + pMaxNew[dep] + numSplitPoints[dep];
832: }
833: coneONew[2+q] = 0;
834: }
835: DMPlexSetCone(sdm, hybcell, coneNew);
836: DMPlexSetConeOrientation(sdm, hybcell, coneONew);
837: } else if (dep == 0) {
838: const PetscInt hybedge = p + pMaxNew[dep+1] + numSplitPoints[dep+1];
840: /* Split old vertex: Edges in old split faces and new cohesive edge */
841: for (e = 0, qn = 0; e < supportSize; ++e) {
842: PetscInt val;
844: DMLabelGetValue(label, support[e], &val);
845: if ((val == 1) || (val == (shift + 1))) {
846: supportNew[qn++] = DMPlexShiftPoint_Internal(support[e], depth, depthMax, depthEnd, depthShift) /*support[e] + depthOffset[dep+1]*/;
847: }
848: }
849: supportNew[qn] = hybedge;
850: DMPlexSetSupport(sdm, newp, supportNew);
851: /* Split new vertex: Edges in new split faces and new cohesive edge */
852: for (e = 0, qp = 0; e < supportSize; ++e) {
853: PetscInt val, edge;
855: DMLabelGetValue(label, support[e], &val);
856: if (val == 1) {
857: PetscFindInt(support[e], numSplitPoints[dep+1], splitPoints[dep+1], &edge);
858: if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a split edge", support[e]);
859: supportNew[qp++] = edge + pMaxNew[dep+1];
860: } else if (val == -(shift + 1)) {
861: supportNew[qp++] = DMPlexShiftPoint_Internal(support[e], depth, depthMax, depthEnd, depthShift) /*support[e] + depthOffset[dep+1]*/;
862: }
863: }
864: supportNew[qp] = hybedge;
865: DMPlexSetSupport(sdm, splitp, supportNew);
866: /* Hybrid edge: Old and new split vertex */
867: coneNew[0] = newp;
868: coneNew[1] = splitp;
869: DMPlexSetCone(sdm, hybedge, coneNew);
870: for (e = 0, qf = 0; e < supportSize; ++e) {
871: PetscInt val, edge;
873: DMLabelGetValue(label, support[e], &val);
874: if (val == 1) {
875: PetscFindInt(support[e], numSplitPoints[dep+1], splitPoints[dep+1], &edge);
876: if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a split edge", support[e]);
877: supportNew[qf++] = edge + pMaxNew[dep+2] + numSplitPoints[dep+2];
878: }
879: }
880: DMPlexSetSupport(sdm, hybedge, supportNew);
881: } else if (dep == dim-2) {
882: const PetscInt hybface = p + pMaxNew[dep+1] + numSplitPoints[dep+1];
884: /* Split old edge: old vertices in cone so no change */
885: /* Split new edge: new vertices in cone */
886: for (q = 0; q < coneSize; ++q) {
887: PetscFindInt(cone[q], numSplitPoints[dep-1], splitPoints[dep-1], &v);
888: if (v < 0) {
889: PetscFindInt(cone[q], numUnsplitPoints[dep-1], unsplitPoints[dep-1], &v);
890: if (v < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not locate point %d in split or unsplit points of depth %d", cone[q], dep-1);
891: coneNew[q] = DMPlexShiftPoint_Internal(cone[q], depth, depthMax, depthEnd, depthShift) /*cone[q] + depthOffset[dep-1]*/;
892: } else {
893: coneNew[q] = v + pMaxNew[dep-1];
894: }
895: }
896: DMPlexSetCone(sdm, splitp, coneNew);
897: /* Split old edge: Faces in positive side cells and old split faces */
898: for (e = 0, q = 0; e < supportSize; ++e) {
899: PetscInt val;
901: DMLabelGetValue(label, support[e], &val);
902: if (val == dim-1) {
903: supportNew[q++] = DMPlexShiftPoint_Internal(support[e], depth, depthMax, depthEnd, depthShift) /*support[e] + depthOffset[dep+1]*/;
904: } else if (val == (shift + dim-1)) {
905: supportNew[q++] = DMPlexShiftPoint_Internal(support[e], depth, depthMax, depthEnd, depthShift) /*support[e] + depthOffset[dep+1]*/;
906: }
907: }
908: supportNew[q++] = p + pMaxNew[dep+1] + numSplitPoints[dep+1];
909: DMPlexSetSupport(sdm, newp, supportNew);
910: /* Split new edge: Faces in negative side cells and new split faces */
911: for (e = 0, q = 0; e < supportSize; ++e) {
912: PetscInt val, face;
914: DMLabelGetValue(label, support[e], &val);
915: if (val == dim-1) {
916: PetscFindInt(support[e], numSplitPoints[dep+1], splitPoints[dep+1], &face);
917: if (face < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Face %d is not a split face", support[e]);
918: supportNew[q++] = face + pMaxNew[dep+1];
919: } else if (val == -(shift + dim-1)) {
920: supportNew[q++] = DMPlexShiftPoint_Internal(support[e], depth, depthMax, depthEnd, depthShift) /*support[e] + depthOffset[dep+1]*/;
921: }
922: }
923: supportNew[q++] = p + pMaxNew[dep+1] + numSplitPoints[dep+1];
924: DMPlexSetSupport(sdm, splitp, supportNew);
925: /* Hybrid face */
926: coneNew[0] = newp;
927: coneNew[1] = splitp;
928: for (v = 0; v < coneSize; ++v) {
929: PetscInt vertex;
930: PetscFindInt(cone[v], numSplitPoints[dep-1], splitPoints[dep-1], &vertex);
931: if (vertex < 0) {
932: PetscFindInt(cone[v], numUnsplitPoints[dep-1], unsplitPoints[dep-1], &vertex);
933: if (vertex < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not locate point %d in split or unsplit points of depth %d", cone[v], dep-1);
934: coneNew[2+v] = vertex + pMaxNew[dep] + numSplitPoints[dep] + numSplitPoints[dep-1];
935: } else {
936: coneNew[2+v] = vertex + pMaxNew[dep] + numSplitPoints[dep];
937: }
938: }
939: DMPlexSetCone(sdm, hybface, coneNew);
940: for (e = 0, qf = 0; e < supportSize; ++e) {
941: PetscInt val, face;
943: DMLabelGetValue(label, support[e], &val);
944: if (val == dim-1) {
945: PetscFindInt(support[e], numSplitPoints[dep+1], splitPoints[dep+1], &face);
946: if (face < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Face %d is not a split face", support[e]);
947: supportNew[qf++] = face + pMaxNew[dep+2] + numSplitPoints[dep+2];
948: }
949: }
950: DMPlexSetSupport(sdm, hybface, supportNew);
951: }
952: }
953: }
954: for (dep = 0; dep <= depth; ++dep) {
955: for (p = 0; p < numUnsplitPoints[dep]; ++p) {
956: const PetscInt oldp = unsplitPoints[dep][p];
957: const PetscInt newp = DMPlexShiftPoint_Internal(oldp, depth, depthMax, depthEnd, depthShift) /*oldp + depthOffset[dep]*/;
958: const PetscInt *cone, *support, *ornt;
959: PetscInt coneSize, supportSize, supportSizeNew, q, qf, e, f, s;
961: DMPlexGetConeSize(dm, oldp, &coneSize);
962: DMPlexGetCone(dm, oldp, &cone);
963: DMPlexGetConeOrientation(dm, oldp, &ornt);
964: DMPlexGetSupportSize(dm, oldp, &supportSize);
965: DMPlexGetSupport(dm, oldp, &support);
966: if (dep == 0) {
967: const PetscInt hybedge = p + pMaxNew[dep+1] + numSplitPoints[dep+1] + numSplitPoints[dep];
969: /* Unsplit vertex */
970: DMPlexGetSupportSize(sdm, newp, &supportSizeNew);
971: for (s = 0, q = 0; s < supportSize; ++s) {
972: supportNew[q++] = DMPlexShiftPoint_Internal(support[s], depth, depthMax, depthEnd, depthShift) /*support[s] + depthOffset[dep+1]*/;
973: PetscFindInt(support[s], numSplitPoints[dep+1], splitPoints[dep+1], &e);
974: if (e >= 0) {
975: supportNew[q++] = e + pMaxNew[dep+1];
976: }
977: }
978: supportNew[q++] = hybedge;
979: supportNew[q++] = hybedge;
980: if (q != supportSizeNew) SETERRQ3(comm, PETSC_ERR_ARG_WRONG, "Support size %d != %d for vertex %d", q, supportSizeNew, newp);
981: DMPlexSetSupport(sdm, newp, supportNew);
982: /* Hybrid edge */
983: coneNew[0] = newp;
984: coneNew[1] = newp;
985: DMPlexSetCone(sdm, hybedge, coneNew);
986: for (e = 0, qf = 0; e < supportSize; ++e) {
987: PetscInt val, edge;
989: DMLabelGetValue(label, support[e], &val);
990: if (val == 1) {
991: PetscFindInt(support[e], numSplitPoints[dep+1], splitPoints[dep+1], &edge);
992: if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a split edge", support[e]);
993: supportNew[qf++] = edge + pMaxNew[dep+2] + numSplitPoints[dep+2];
994: } else if (val == (shift2 + 1)) {
995: PetscFindInt(support[e], numUnsplitPoints[dep+1], unsplitPoints[dep+1], &edge);
996: if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a unsplit edge", support[e]);
997: supportNew[qf++] = edge + pMaxNew[dep+2] + numSplitPoints[dep+2] + numSplitPoints[dep+1];
998: }
999: }
1000: DMPlexSetSupport(sdm, hybedge, supportNew);
1001: } else if (dep == dim-2) {
1002: const PetscInt hybface = p + pMaxNew[dep+1] + numSplitPoints[dep+1] + numSplitPoints[dep];
1003: PetscInt hybcell = -1;
1005: /* Unsplit edge: Faces into original edge, split face, and cohesive face twice */
1006: for (f = 0, qf = 0; f < supportSize; ++f) {
1007: PetscInt val, face;
1009: DMLabelGetValue(label, support[f], &val);
1010: if (val == dim-1) {
1011: PetscFindInt(support[f], numSplitPoints[dep+1], splitPoints[dep+1], &face);
1012: if (face < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Face %d is not a split face", support[f]);
1013: supportNew[qf++] = DMPlexShiftPoint_Internal(support[f], depth, depthMax, depthEnd, depthShift) /*support[f] + depthOffset[dep+1]*/;
1014: supportNew[qf++] = face + pMaxNew[dep+1];
1015: hybcell = face + pMaxNew[dep+2] + numSplitPoints[dep+2];
1016: } else {
1017: supportNew[qf++] = DMPlexShiftPoint_Internal(support[f], depth, depthMax, depthEnd, depthShift) /*support[f] + depthOffset[dep+1]*/;
1018: }
1019: }
1020: supportNew[qf++] = hybface;
1021: supportNew[qf++] = hybface;
1022: DMPlexSetSupport(sdm, newp, supportNew);
1023: /* Add hybrid face */
1024: coneNew[0] = newp;
1025: PetscFindInt(cone[0], numUnsplitPoints[dep-1], unsplitPoints[dep-1], &v);
1026: if (v < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Vertex %d is not an unsplit vertex", cone[0]);
1027: coneNew[1] = v + pMaxNew[dep] + numSplitPoints[dep] + numSplitPoints[dep-1];
1028: coneNew[2] = newp;
1029: PetscFindInt(cone[1], numUnsplitPoints[dep-1], unsplitPoints[dep-1], &v);
1030: if (v < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Vertex %d is not an unsplit vertex", cone[1]);
1031: coneNew[3] = v + pMaxNew[dep] + numSplitPoints[dep] + numSplitPoints[dep-1];
1032: DMPlexSetCone(sdm, hybface, coneNew);
1033: supportNew[0] = hybcell;
1034: DMPlexSetSupport(sdm, hybface, supportNew);
1035: }
1036: }
1037: }
1038: /* Step 6b: Replace split points in negative side cones */
1039: for (sp = 0; sp < numSP; ++sp) {
1040: PetscInt dep = values[sp];
1041: IS pIS;
1042: PetscInt numPoints;
1043: const PetscInt *points;
1045: if (dep >= 0) continue;
1046: DMLabelGetStratumIS(label, dep, &pIS);
1047: if (!pIS) continue;
1048: dep = -dep - shift;
1049: ISGetLocalSize(pIS, &numPoints);
1050: ISGetIndices(pIS, &points);
1051: for (p = 0; p < numPoints; ++p) {
1052: const PetscInt oldp = points[p];
1053: const PetscInt newp = DMPlexShiftPoint_Internal(oldp, depth, depthMax, depthEnd, depthShift) /*depthOffset[dep] + oldp*/;
1054: const PetscInt *cone;
1055: PetscInt coneSize, c;
1056: /* PetscBool replaced = PETSC_FALSE; */
1058: /* Negative edge: replace split vertex */
1059: /* Negative cell: replace split face */
1060: DMPlexGetConeSize(sdm, newp, &coneSize);
1061: DMPlexGetCone(sdm, newp, &cone);
1062: for (c = 0; c < coneSize; ++c) {
1063: const PetscInt coldp = cone[c] - depthOffset[dep-1];
1064: PetscInt csplitp, cp, val;
1066: DMLabelGetValue(label, coldp, &val);
1067: if (val == dep-1) {
1068: PetscFindInt(coldp, numSplitPoints[dep-1], splitPoints[dep-1], &cp);
1069: if (cp < 0) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "Point %d is not a split point of dimension %d", oldp, dep-1);
1070: csplitp = pMaxNew[dep-1] + cp;
1071: DMPlexInsertCone(sdm, newp, c, csplitp);
1072: /* replaced = PETSC_TRUE; */
1073: }
1074: }
1075: /* Cells with only a vertex or edge on the submesh have no replacement */
1076: /* if (!replaced) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "The cone of point %d does not contain split points", oldp); */
1077: }
1078: ISRestoreIndices(pIS, &points);
1079: ISDestroy(&pIS);
1080: }
1081: /* Step 7: Stratify */
1082: DMPlexStratify(sdm);
1083: /* Step 8: Coordinates */
1084: DMPlexShiftCoordinates_Internal(dm, depthShift, sdm);
1085: DMGetCoordinateSection(sdm, &coordSection);
1086: DMGetCoordinatesLocal(sdm, &coordinates);
1087: VecGetArray(coordinates, &coords);
1088: for (v = 0; v < (numSplitPoints ? numSplitPoints[0] : 0); ++v) {
1089: const PetscInt newp = DMPlexShiftPoint_Internal(splitPoints[0][v], depth, depthMax, depthEnd, depthShift) /*depthOffset[0] + splitPoints[0][v]*/;
1090: const PetscInt splitp = pMaxNew[0] + v;
1091: PetscInt dof, off, soff, d;
1093: PetscSectionGetDof(coordSection, newp, &dof);
1094: PetscSectionGetOffset(coordSection, newp, &off);
1095: PetscSectionGetOffset(coordSection, splitp, &soff);
1096: for (d = 0; d < dof; ++d) coords[soff+d] = coords[off+d];
1097: }
1098: VecRestoreArray(coordinates, &coords);
1099: /* Step 9: SF, if I can figure this out we can split the mesh in parallel */
1100: DMPlexShiftSF_Internal(dm, depthShift, sdm);
1101: /* Step 10: Labels */
1102: DMPlexShiftLabels_Internal(dm, depthShift, sdm);
1103: DMPlexGetNumLabels(sdm, &numLabels);
1104: for (dep = 0; dep <= depth; ++dep) {
1105: for (p = 0; p < numSplitPoints[dep]; ++p) {
1106: const PetscInt newp = DMPlexShiftPoint_Internal(splitPoints[dep][p], depth, depthMax, depthEnd, depthShift) /*depthOffset[dep] + splitPoints[dep][p]*/;
1107: const PetscInt splitp = pMaxNew[dep] + p;
1108: PetscInt l;
1110: for (l = 0; l < numLabels; ++l) {
1111: DMLabel mlabel;
1112: const char *lname;
1113: PetscInt val;
1114: PetscBool isDepth;
1116: DMPlexGetLabelName(sdm, l, &lname);
1117: PetscStrcmp(lname, "depth", &isDepth);
1118: if (isDepth) continue;
1119: DMPlexGetLabel(sdm, lname, &mlabel);
1120: DMLabelGetValue(mlabel, newp, &val);
1121: if (val >= 0) {
1122: DMLabelSetValue(mlabel, splitp, val);
1123: #if 0
1124: /* Do not put cohesive edges into the label */
1125: if (dep == 0) {
1126: const PetscInt cedge = p + pMaxNew[dep+1] + numSplitPoints[dep+1];
1127: DMLabelSetValue(mlabel, cedge, val);
1128: } else if (dep == dim-2) {
1129: const PetscInt cface = p + pMaxNew[dep+1] + numSplitPoints[dep+1];
1130: DMLabelSetValue(mlabel, cface, val);
1131: }
1132: /* Do not put cohesive faces into the label */
1133: #endif
1134: }
1135: }
1136: }
1137: }
1138: for (sp = 0; sp < numSP; ++sp) {
1139: const PetscInt dep = values[sp];
1141: if ((dep < 0) || (dep > depth)) continue;
1142: if (splitIS[dep]) {ISRestoreIndices(splitIS[dep], &splitPoints[dep]);}
1143: ISDestroy(&splitIS[dep]);
1144: if (unsplitIS[dep]) {ISRestoreIndices(unsplitIS[dep], &unsplitPoints[dep]);}
1145: ISDestroy(&unsplitIS[dep]);
1146: }
1147: if (label) {
1148: ISRestoreIndices(valueIS, &values);
1149: ISDestroy(&valueIS);
1150: }
1151: for (d = 0; d <= depth; ++d) {
1152: DMPlexGetDepthStratum(sdm, d, NULL, &pEnd);
1153: pMaxNew[d] = pEnd - numHybridPoints[d] - numHybridPointsOld[d];
1154: }
1155: DMPlexSetHybridBounds(sdm, depth >= 0 ? pMaxNew[depth] : PETSC_DETERMINE, depth>1 ? pMaxNew[depth-1] : PETSC_DETERMINE, depth>2 ? pMaxNew[1] : PETSC_DETERMINE, depth >= 0 ? pMaxNew[0] : PETSC_DETERMINE);
1156: PetscFree3(coneNew, coneONew, supportNew);
1157: PetscFree6(depthMax, depthEnd, depthShift, depthOffset, pMaxNew, numHybridPointsOld);
1158: PetscFree7(splitIS, unsplitIS, numSplitPoints, numUnsplitPoints, numHybridPoints, splitPoints, unsplitPoints);
1159: return(0);
1160: }
1164: /*@C
1165: DMPlexConstructCohesiveCells - Construct cohesive cells which split the face along an internal interface
1167: Collective on dm
1169: Input Parameters:
1170: + dm - The original DM
1171: - label - The label specifying the boundary faces (this could be auto-generated)
1173: Output Parameters:
1174: - dmSplit - The new DM
1176: Level: developer
1178: .seealso: DMCreate(), DMPlexLabelCohesiveComplete()
1179: @*/
1180: PetscErrorCode DMPlexConstructCohesiveCells(DM dm, DMLabel label, DM *dmSplit)
1181: {
1182: DM sdm;
1183: PetscInt dim;
1189: DMCreate(PetscObjectComm((PetscObject)dm), &sdm);
1190: DMSetType(sdm, DMPLEX);
1191: DMPlexGetDimension(dm, &dim);
1192: DMPlexSetDimension(sdm, dim);
1193: switch (dim) {
1194: case 2:
1195: case 3:
1196: DMPlexConstructCohesiveCells_Internal(dm, label, sdm);
1197: break;
1198: default:
1199: SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct cohesive cells for dimension %d", dim);
1200: }
1201: *dmSplit = sdm;
1202: return(0);
1203: }
1207: /*@
1208: DMPlexLabelCohesiveComplete - Starting with a label marking vertices on an internal surface, we add all other mesh pieces
1209: to complete the surface
1211: Input Parameters:
1212: + dm - The DM
1213: . label - A DMLabel marking the surface vertices
1214: . flip - Flag to flip the submesh normal and replace points on the other side
1215: - subdm - The subDM associated with the label, or NULL
1217: Output Parameter:
1218: . label - A DMLabel marking all surface points
1220: Level: developer
1222: .seealso: DMPlexConstructCohesiveCells(), DMPlexLabelComplete()
1223: @*/
1224: PetscErrorCode DMPlexLabelCohesiveComplete(DM dm, DMLabel label, PetscBool flip, DM subdm)
1225: {
1226: DMLabel depthLabel;
1227: IS dimIS, subpointIS, facePosIS, faceNegIS;
1228: const PetscInt *points, *subpoints;
1229: const PetscInt rev = flip ? -1 : 1;
1230: PetscInt shift = 100, shift2 = 200, dim, dep, cStart, cEnd, numPoints, numSubpoints, p, val;
1231: PetscErrorCode ierr;
1234: DMPlexGetDepthLabel(dm, &depthLabel);
1235: DMPlexGetDimension(dm, &dim);
1236: if (subdm) {
1237: DMPlexCreateSubpointIS(subdm, &subpointIS);
1238: if (subpointIS) {
1239: ISGetLocalSize(subpointIS, &numSubpoints);
1240: ISGetIndices(subpointIS, &subpoints);
1241: }
1242: }
1243: /* Mark cell on the fault, and its faces which touch the fault: cell orientation for face gives the side of the fault */
1244: DMLabelGetStratumIS(label, dim-1, &dimIS);
1245: if (!dimIS) return(0);
1246: ISGetLocalSize(dimIS, &numPoints);
1247: ISGetIndices(dimIS, &points);
1248: for (p = 0; p < numPoints; ++p) { /* Loop over fault faces */
1249: const PetscInt *support;
1250: PetscInt supportSize, s;
1252: DMPlexGetSupportSize(dm, points[p], &supportSize);
1253: if (supportSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Split face %d has %d != 2 supports", points[p], supportSize);
1254: DMPlexGetSupport(dm, points[p], &support);
1255: for (s = 0; s < supportSize; ++s) {
1256: const PetscInt *cone, *ornt;
1257: PetscInt coneSize, c;
1258: PetscBool pos = PETSC_TRUE;
1260: DMPlexGetConeSize(dm, support[s], &coneSize);
1261: DMPlexGetCone(dm, support[s], &cone);
1262: DMPlexGetConeOrientation(dm, support[s], &ornt);
1263: for (c = 0; c < coneSize; ++c) {
1264: if (cone[c] == points[p]) {
1265: PetscInt o = ornt[c];
1267: if (subdm) {
1268: const PetscInt *subcone, *subornt;
1269: PetscInt subpoint, subface, subconeSize, sc;
1271: PetscFindInt(support[s], numSubpoints, subpoints, &subpoint);
1272: PetscFindInt(points[p], numSubpoints, subpoints, &subface);
1273: DMPlexGetConeSize(subdm, subpoint, &subconeSize);
1274: DMPlexGetCone(subdm, subpoint, &subcone);
1275: DMPlexGetConeOrientation(subdm, subpoint, &subornt);
1276: for (sc = 0; sc < subconeSize; ++sc) {
1277: if (subcone[sc] == subface) {
1278: o = subornt[0];
1279: break;
1280: }
1281: }
1282: if (sc >= subconeSize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find point %d in cone for subpoint %d", points[p], subpoint);
1283: }
1284: if (o >= 0) {
1285: DMLabelSetValue(label, support[s], rev*(shift+dim));
1286: pos = rev > 0 ? PETSC_TRUE : PETSC_FALSE;
1287: } else {
1288: DMLabelSetValue(label, support[s], -rev*(shift+dim));
1289: pos = rev > 0 ? PETSC_FALSE : PETSC_TRUE;
1290: }
1291: break;
1292: }
1293: }
1294: if (c == coneSize) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cell split face %d support does not have it in the cone", points[p]);
1295: /* Put faces touching the fault in the label */
1296: for (c = 0; c < coneSize; ++c) {
1297: const PetscInt point = cone[c];
1299: DMLabelGetValue(label, point, &val);
1300: if (val == -1) {
1301: PetscInt *closure = NULL;
1302: PetscInt closureSize, cl;
1304: DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);
1305: for (cl = 0; cl < closureSize*2; cl += 2) {
1306: const PetscInt clp = closure[cl];
1308: DMLabelGetValue(label, clp, &val);
1309: if ((val >= 0) && (val < dim-1)) {
1310: DMLabelSetValue(label, point, pos == PETSC_TRUE ? shift+dim-1 : -(shift+dim-1));
1311: break;
1312: }
1313: }
1314: DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);
1315: }
1316: }
1317: }
1318: }
1319: if (subdm) {
1320: if (subpointIS) {ISRestoreIndices(subpointIS, &subpoints);}
1321: ISDestroy(&subpointIS);
1322: }
1323: ISRestoreIndices(dimIS, &points);
1324: ISDestroy(&dimIS);
1325: /* Search for other cells/faces/edges connected to the fault by a vertex */
1326: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
1327: DMLabelGetStratumIS(label, 0, &dimIS);
1328: if (!dimIS) return(0);
1329: ISGetLocalSize(dimIS, &numPoints);
1330: ISGetIndices(dimIS, &points);
1331: for (p = 0; p < numPoints; ++p) { /* Loop over fault vertices */
1332: PetscInt *star = NULL;
1333: PetscInt starSize, s;
1334: PetscInt again = 1; /* 0: Finished 1: Keep iterating after a change 2: No change */
1336: /* All points connected to the fault are inside a cell, so at the top level we will only check cells */
1337: DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);
1338: while (again) {
1339: if (again > 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Could not classify all cells connected to the fault");
1340: again = 0;
1341: for (s = 0; s < starSize*2; s += 2) {
1342: const PetscInt point = star[s];
1343: const PetscInt *cone;
1344: PetscInt coneSize, c;
1346: if ((point < cStart) || (point >= cEnd)) continue;
1347: DMLabelGetValue(label, point, &val);
1348: if (val != -1) continue;
1349: again = again == 1 ? 1 : 2;
1350: DMPlexGetConeSize(dm, point, &coneSize);
1351: DMPlexGetCone(dm, point, &cone);
1352: for (c = 0; c < coneSize; ++c) {
1353: DMLabelGetValue(label, cone[c], &val);
1354: if (val != -1) {
1355: const PetscInt *ccone;
1356: PetscInt cconeSize, cc, side;
1358: if (abs(val) < shift) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Face %d on cell %d has an invalid label %d", cone[c], point, val);
1359: if (val > 0) side = 1;
1360: else side = -1;
1361: DMLabelSetValue(label, point, side*(shift+dim));
1362: /* Mark cell faces which touch the fault */
1363: DMPlexGetConeSize(dm, point, &cconeSize);
1364: DMPlexGetCone(dm, point, &ccone);
1365: for (cc = 0; cc < cconeSize; ++cc) {
1366: PetscInt *closure = NULL;
1367: PetscInt closureSize, cl;
1369: DMLabelGetValue(label, ccone[cc], &val);
1370: if (val != -1) continue;
1371: DMPlexGetTransitiveClosure(dm, ccone[cc], PETSC_TRUE, &closureSize, &closure);
1372: for (cl = 0; cl < closureSize*2; cl += 2) {
1373: const PetscInt clp = closure[cl];
1375: DMLabelGetValue(label, clp, &val);
1376: if (val == -1) continue;
1377: DMLabelSetValue(label, ccone[cc], side*(shift+dim-1));
1378: break;
1379: }
1380: DMPlexRestoreTransitiveClosure(dm, ccone[cc], PETSC_TRUE, &closureSize, &closure);
1381: }
1382: again = 1;
1383: break;
1384: }
1385: }
1386: }
1387: }
1388: /* Classify the rest by cell membership */
1389: for (s = 0; s < starSize*2; s += 2) {
1390: const PetscInt point = star[s];
1392: DMLabelGetValue(label, point, &val);
1393: if (val == -1) {
1394: PetscInt *sstar = NULL;
1395: PetscInt sstarSize, ss;
1396: PetscBool marked = PETSC_FALSE;
1398: DMPlexGetTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);
1399: for (ss = 0; ss < sstarSize*2; ss += 2) {
1400: const PetscInt spoint = sstar[ss];
1402: if ((spoint < cStart) || (spoint >= cEnd)) continue;
1403: DMLabelGetValue(label, spoint, &val);
1404: if (val == -1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Cell %d in star of %d does not have a valid label", spoint, point);
1405: DMLabelGetValue(depthLabel, point, &dep);
1406: if (val > 0) {
1407: DMLabelSetValue(label, point, shift+dep);
1408: } else {
1409: DMLabelSetValue(label, point, -(shift+dep));
1410: }
1411: marked = PETSC_TRUE;
1412: break;
1413: }
1414: DMPlexRestoreTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);
1415: if (!marked) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d could not be classified", point);
1416: }
1417: }
1418: DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);
1419: }
1420: ISRestoreIndices(dimIS, &points);
1421: ISDestroy(&dimIS);
1422: /* If any faces touching the fault divide cells on either side, split them */
1423: DMLabelGetStratumIS(label, shift+dim-1, &facePosIS);
1424: DMLabelGetStratumIS(label, -(shift+dim-1), &faceNegIS);
1425: ISExpand(facePosIS, faceNegIS, &dimIS);
1426: ISDestroy(&facePosIS);
1427: ISDestroy(&faceNegIS);
1428: ISGetLocalSize(dimIS, &numPoints);
1429: ISGetIndices(dimIS, &points);
1430: for (p = 0; p < numPoints; ++p) {
1431: const PetscInt point = points[p];
1432: const PetscInt *support;
1433: PetscInt supportSize, valA, valB;
1435: DMPlexGetSupportSize(dm, point, &supportSize);
1436: if (supportSize != 2) continue;
1437: DMPlexGetSupport(dm, point, &support);
1438: DMLabelGetValue(label, support[0], &valA);
1439: DMLabelGetValue(label, support[1], &valB);
1440: if ((valA == -1) || (valB == -1)) continue;
1441: if (valA*valB > 0) continue;
1442: /* Split the face */
1443: DMLabelGetValue(label, point, &valA);
1444: DMLabelClearValue(label, point, valA);
1445: DMLabelSetValue(label, point, dim-1);
1446: /* Label its closure:
1447: unmarked: label as unsplit
1448: incident: relabel as split
1449: split: do nothing
1450: */
1451: {
1452: PetscInt *closure = NULL;
1453: PetscInt closureSize, cl;
1455: DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);
1456: for (cl = 0; cl < closureSize*2; cl += 2) {
1457: DMLabelGetValue(label, closure[cl], &valA);
1458: if (valA < 0) { /* Mark as unsplit */
1459: DMLabelGetValue(depthLabel, closure[cl], &dep);
1460: DMLabelSetValue(label, closure[cl], shift2+dep);
1461: } else if (valA >= shift) {
1462: DMLabelGetValue(depthLabel, closure[cl], &dep);
1463: DMLabelClearValue(label, closure[cl], valA);
1464: DMLabelSetValue(label, closure[cl], dep);
1465: }
1466: }
1467: DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);
1468: }
1469: }
1470: ISRestoreIndices(dimIS, &points);
1471: ISDestroy(&dimIS);
1472: return(0);
1473: }
1477: /*@C
1478: DMPlexCreateHybridMesh - Create a mesh with hybrid cells along an internal interface
1480: Collective on dm
1482: Input Parameters:
1483: + dm - The original DM
1484: - labelName - The label specifying the interface vertices
1486: Output Parameters:
1487: + hybridLabel - The label fully marking the interface
1488: - dmHybrid - The new DM
1490: Level: developer
1492: .seealso: DMPlexConstructCohesiveCells(), DMPlexLabelCohesiveComplete(), DMCreate()
1493: @*/
1494: PetscErrorCode DMPlexCreateHybridMesh(DM dm, DMLabel label, DMLabel *hybridLabel, DM *dmHybrid)
1495: {
1496: DM idm;
1497: DMLabel subpointMap, hlabel;
1498: PetscInt dim;
1505: DMPlexGetDimension(dm, &dim);
1506: DMPlexCreateSubmesh(dm, label, 1, &idm);
1507: DMPlexOrient(idm);
1508: DMPlexGetSubpointMap(idm, &subpointMap);
1509: DMLabelDuplicate(subpointMap, &hlabel);
1510: DMLabelClearStratum(hlabel, dim);
1511: DMPlexLabelCohesiveComplete(dm, hlabel, PETSC_FALSE, idm);
1512: DMDestroy(&idm);
1513: DMPlexConstructCohesiveCells(dm, hlabel, dmHybrid);
1514: if (hybridLabel) *hybridLabel = hlabel;
1515: else {DMLabelDestroy(&hlabel);}
1516: return(0);
1517: }
1521: /* Here we need the explicit assumption that:
1523: For any marked cell, the marked vertices constitute a single face
1524: */
1525: static PetscErrorCode DMPlexMarkSubmesh_Uninterpolated(DM dm, DMLabel vertexLabel, PetscInt value, DMLabel subpointMap, PetscInt *numFaces, PetscInt *nFV, DM subdm)
1526: {
1527: IS subvertexIS = NULL;
1528: const PetscInt *subvertices;
1529: PetscInt *pStart, *pEnd, *pMax, pSize;
1530: PetscInt depth, dim, d, numSubVerticesInitial = 0, v;
1531: PetscErrorCode ierr;
1534: *numFaces = 0;
1535: *nFV = 0;
1536: DMPlexGetDepth(dm, &depth);
1537: DMPlexGetDimension(dm, &dim);
1538: pSize = PetscMax(depth, dim) + 1;
1539: PetscMalloc3(pSize,&pStart,pSize,&pEnd,pSize,&pMax);
1540: DMPlexGetHybridBounds(dm, depth >= 0 ? &pMax[depth] : NULL, depth>1 ? &pMax[depth-1] : NULL, depth>2 ? &pMax[1] : NULL, &pMax[0]);
1541: for (d = 0; d <= depth; ++d) {
1542: DMPlexGetDepthStratum(dm, d, &pStart[d], &pEnd[d]);
1543: if (pMax[d] >= 0) pEnd[d] = PetscMin(pEnd[d], pMax[d]);
1544: }
1545: /* Loop over initial vertices and mark all faces in the collective star() */
1546: if (vertexLabel) {DMLabelGetStratumIS(vertexLabel, value, &subvertexIS);}
1547: if (subvertexIS) {
1548: ISGetSize(subvertexIS, &numSubVerticesInitial);
1549: ISGetIndices(subvertexIS, &subvertices);
1550: }
1551: for (v = 0; v < numSubVerticesInitial; ++v) {
1552: const PetscInt vertex = subvertices[v];
1553: PetscInt *star = NULL;
1554: PetscInt starSize, s, numCells = 0, c;
1556: DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);
1557: for (s = 0; s < starSize*2; s += 2) {
1558: const PetscInt point = star[s];
1559: if ((point >= pStart[depth]) && (point < pEnd[depth])) star[numCells++] = point;
1560: }
1561: for (c = 0; c < numCells; ++c) {
1562: const PetscInt cell = star[c];
1563: PetscInt *closure = NULL;
1564: PetscInt closureSize, cl;
1565: PetscInt cellLoc, numCorners = 0, faceSize = 0;
1567: DMLabelGetValue(subpointMap, cell, &cellLoc);
1568: if (cellLoc == 2) continue;
1569: if (cellLoc >= 0) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Cell %d has dimension %d in the surface label", cell, cellLoc);
1570: DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);
1571: for (cl = 0; cl < closureSize*2; cl += 2) {
1572: const PetscInt point = closure[cl];
1573: PetscInt vertexLoc;
1575: if ((point >= pStart[0]) && (point < pEnd[0])) {
1576: ++numCorners;
1577: DMLabelGetValue(vertexLabel, point, &vertexLoc);
1578: if (vertexLoc == value) closure[faceSize++] = point;
1579: }
1580: }
1581: if (!(*nFV)) {DMPlexGetNumFaceVertices(dm, dim, numCorners, nFV);}
1582: if (faceSize > *nFV) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize);
1583: if (faceSize == *nFV) {
1584: const PetscInt *cells = NULL;
1585: PetscInt numCells, nc;
1587: ++(*numFaces);
1588: for (cl = 0; cl < faceSize; ++cl) {
1589: DMLabelSetValue(subpointMap, closure[cl], 0);
1590: }
1591: DMPlexGetJoin(dm, faceSize, closure, &numCells, &cells);
1592: for (nc = 0; nc < numCells; ++nc) {
1593: DMLabelSetValue(subpointMap, cells[nc], 2);
1594: }
1595: DMPlexRestoreJoin(dm, faceSize, closure, &numCells, &cells);
1596: }
1597: DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);
1598: }
1599: DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);
1600: }
1601: if (subvertexIS) {
1602: ISRestoreIndices(subvertexIS, &subvertices);
1603: }
1604: ISDestroy(&subvertexIS);
1605: PetscFree3(pStart,pEnd,pMax);
1606: return(0);
1607: }
1611: static PetscErrorCode DMPlexMarkSubmesh_Interpolated(DM dm, DMLabel vertexLabel, PetscInt value, DMLabel subpointMap, DM subdm)
1612: {
1613: IS subvertexIS;
1614: const PetscInt *subvertices;
1615: PetscInt *pStart, *pEnd, *pMax;
1616: PetscInt dim, d, numSubVerticesInitial = 0, v;
1617: PetscErrorCode ierr;
1620: DMPlexGetDimension(dm, &dim);
1621: PetscMalloc3(dim+1,&pStart,dim+1,&pEnd,dim+1,&pMax);
1622: DMPlexGetHybridBounds(dm, &pMax[dim], dim>1 ? &pMax[dim-1] : NULL, dim > 2 ? &pMax[1] : NULL, &pMax[0]);
1623: for (d = 0; d <= dim; ++d) {
1624: DMPlexGetDepthStratum(dm, d, &pStart[d], &pEnd[d]);
1625: if (pMax[d] >= 0) pEnd[d] = PetscMin(pEnd[d], pMax[d]);
1626: }
1627: /* Loop over initial vertices and mark all faces in the collective star() */
1628: DMLabelGetStratumIS(vertexLabel, value, &subvertexIS);
1629: if (subvertexIS) {
1630: ISGetSize(subvertexIS, &numSubVerticesInitial);
1631: ISGetIndices(subvertexIS, &subvertices);
1632: }
1633: for (v = 0; v < numSubVerticesInitial; ++v) {
1634: const PetscInt vertex = subvertices[v];
1635: PetscInt *star = NULL;
1636: PetscInt starSize, s, numFaces = 0, f;
1638: DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);
1639: for (s = 0; s < starSize*2; s += 2) {
1640: const PetscInt point = star[s];
1641: if ((point >= pStart[dim-1]) && (point < pEnd[dim-1])) star[numFaces++] = point;
1642: }
1643: for (f = 0; f < numFaces; ++f) {
1644: const PetscInt face = star[f];
1645: PetscInt *closure = NULL;
1646: PetscInt closureSize, c;
1647: PetscInt faceLoc;
1649: DMLabelGetValue(subpointMap, face, &faceLoc);
1650: if (faceLoc == dim-1) continue;
1651: if (faceLoc >= 0) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Face %d has dimension %d in the surface label", face, faceLoc);
1652: DMPlexGetTransitiveClosure(dm, face, PETSC_TRUE, &closureSize, &closure);
1653: for (c = 0; c < closureSize*2; c += 2) {
1654: const PetscInt point = closure[c];
1655: PetscInt vertexLoc;
1657: if ((point >= pStart[0]) && (point < pEnd[0])) {
1658: DMLabelGetValue(vertexLabel, point, &vertexLoc);
1659: if (vertexLoc != value) break;
1660: }
1661: }
1662: if (c == closureSize*2) {
1663: const PetscInt *support;
1664: PetscInt supportSize, s;
1666: for (c = 0; c < closureSize*2; c += 2) {
1667: const PetscInt point = closure[c];
1669: for (d = 0; d < dim; ++d) {
1670: if ((point >= pStart[d]) && (point < pEnd[d])) {
1671: DMLabelSetValue(subpointMap, point, d);
1672: break;
1673: }
1674: }
1675: }
1676: DMPlexGetSupportSize(dm, face, &supportSize);
1677: DMPlexGetSupport(dm, face, &support);
1678: for (s = 0; s < supportSize; ++s) {
1679: DMLabelSetValue(subpointMap, support[s], dim);
1680: }
1681: }
1682: DMPlexRestoreTransitiveClosure(dm, face, PETSC_TRUE, &closureSize, &closure);
1683: }
1684: DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);
1685: }
1686: if (subvertexIS) {
1687: ISRestoreIndices(subvertexIS, &subvertices);
1688: }
1689: ISDestroy(&subvertexIS);
1690: PetscFree3(pStart,pEnd,pMax);
1691: return(0);
1692: }
1696: static PetscErrorCode DMPlexMarkCohesiveSubmesh_Uninterpolated(DM dm, PetscBool hasLagrange, const char labelname[], PetscInt value, DMLabel subpointMap, PetscInt *numFaces, PetscInt *nFV, PetscInt *subCells[], DM subdm)
1697: {
1698: DMLabel label = NULL;
1699: const PetscInt *cone;
1700: PetscInt dim, cMax, cEnd, c, subc = 0, p, coneSize;
1701: PetscErrorCode ierr;
1704: *numFaces = 0;
1705: *nFV = 0;
1706: if (labelname) {DMPlexGetLabel(dm, labelname, &label);}
1707: *subCells = NULL;
1708: DMPlexGetDimension(dm, &dim);
1709: DMPlexGetHeightStratum(dm, 0, NULL, &cEnd);
1710: DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);
1711: if (cMax < 0) return(0);
1712: if (label) {
1713: for (c = cMax; c < cEnd; ++c) {
1714: PetscInt val;
1716: DMLabelGetValue(label, c, &val);
1717: if (val == value) {
1718: ++(*numFaces);
1719: DMPlexGetConeSize(dm, c, &coneSize);
1720: }
1721: }
1722: } else {
1723: *numFaces = cEnd - cMax;
1724: DMPlexGetConeSize(dm, cMax, &coneSize);
1725: }
1726: *nFV = hasLagrange ? coneSize/3 : coneSize/2;
1727: PetscMalloc1(*numFaces *2, subCells);
1728: for (c = cMax; c < cEnd; ++c) {
1729: const PetscInt *cells;
1730: PetscInt numCells;
1732: if (label) {
1733: PetscInt val;
1735: DMLabelGetValue(label, c, &val);
1736: if (val != value) continue;
1737: }
1738: DMPlexGetCone(dm, c, &cone);
1739: for (p = 0; p < *nFV; ++p) {
1740: DMLabelSetValue(subpointMap, cone[p], 0);
1741: }
1742: /* Negative face */
1743: DMPlexGetJoin(dm, *nFV, cone, &numCells, &cells);
1744: /* Not true in parallel
1745: if (numCells != 2) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cohesive cells should separate two cells"); */
1746: for (p = 0; p < numCells; ++p) {
1747: DMLabelSetValue(subpointMap, cells[p], 2);
1748: (*subCells)[subc++] = cells[p];
1749: }
1750: DMPlexRestoreJoin(dm, *nFV, cone, &numCells, &cells);
1751: /* Positive face is not included */
1752: }
1753: return(0);
1754: }
1758: static PetscErrorCode DMPlexMarkCohesiveSubmesh_Interpolated(DM dm, const char labelname[], PetscInt value, DMLabel subpointMap, DM subdm)
1759: {
1760: DMLabel label = NULL;
1761: PetscInt *pStart, *pEnd;
1762: PetscInt dim, cMax, cEnd, c, d;
1766: if (labelname) {DMPlexGetLabel(dm, labelname, &label);}
1767: DMPlexGetDimension(dm, &dim);
1768: DMPlexGetHeightStratum(dm, 0, NULL, &cEnd);
1769: DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);
1770: if (cMax < 0) return(0);
1771: PetscMalloc2(dim+1,&pStart,dim+1,&pEnd);
1772: for (d = 0; d <= dim; ++d) {DMPlexGetDepthStratum(dm, d, &pStart[d], &pEnd[d]);}
1773: for (c = cMax; c < cEnd; ++c) {
1774: const PetscInt *cone;
1775: PetscInt *closure = NULL;
1776: PetscInt fconeSize, coneSize, closureSize, cl, val;
1778: if (label) {
1779: DMLabelGetValue(label, c, &val);
1780: if (val != value) continue;
1781: }
1782: DMPlexGetConeSize(dm, c, &coneSize);
1783: DMPlexGetCone(dm, c, &cone);
1784: DMPlexGetConeSize(dm, cone[0], &fconeSize);
1785: if (coneSize != (fconeSize ? fconeSize : 1) + 2) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cohesive cells should separate two cells");
1786: /* Negative face */
1787: DMPlexGetTransitiveClosure(dm, cone[0], PETSC_TRUE, &closureSize, &closure);
1788: for (cl = 0; cl < closureSize*2; cl += 2) {
1789: const PetscInt point = closure[cl];
1791: for (d = 0; d <= dim; ++d) {
1792: if ((point >= pStart[d]) && (point < pEnd[d])) {
1793: DMLabelSetValue(subpointMap, point, d);
1794: break;
1795: }
1796: }
1797: }
1798: DMPlexRestoreTransitiveClosure(dm, cone[0], PETSC_TRUE, &closureSize, &closure);
1799: /* Cells -- positive face is not included */
1800: for (cl = 0; cl < 1; ++cl) {
1801: const PetscInt *support;
1802: PetscInt supportSize, s;
1804: DMPlexGetSupportSize(dm, cone[cl], &supportSize);
1805: /* if (supportSize != 2) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cohesive faces should separate two cells"); */
1806: DMPlexGetSupport(dm, cone[cl], &support);
1807: for (s = 0; s < supportSize; ++s) {
1808: DMLabelSetValue(subpointMap, support[s], dim);
1809: }
1810: }
1811: }
1812: PetscFree2(pStart, pEnd);
1813: return(0);
1814: }
1818: PetscErrorCode DMPlexGetFaceOrientation(DM dm, PetscInt cell, PetscInt numCorners, PetscInt indices[], PetscInt oppositeVertex, PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented)
1819: {
1820: MPI_Comm comm;
1821: PetscBool posOrient = PETSC_FALSE;
1822: const PetscInt debug = 0;
1823: PetscInt cellDim, faceSize, f;
1827: PetscObjectGetComm((PetscObject)dm,&comm);
1828: DMPlexGetDimension(dm, &cellDim);
1829: if (debug) {PetscPrintf(comm, "cellDim: %d numCorners: %d\n", cellDim, numCorners);}
1831: if (cellDim == 1 && numCorners == 2) {
1832: /* Triangle */
1833: faceSize = numCorners-1;
1834: posOrient = !(oppositeVertex%2) ? PETSC_TRUE : PETSC_FALSE;
1835: } else if (cellDim == 2 && numCorners == 3) {
1836: /* Triangle */
1837: faceSize = numCorners-1;
1838: posOrient = !(oppositeVertex%2) ? PETSC_TRUE : PETSC_FALSE;
1839: } else if (cellDim == 3 && numCorners == 4) {
1840: /* Tetrahedron */
1841: faceSize = numCorners-1;
1842: posOrient = (oppositeVertex%2) ? PETSC_TRUE : PETSC_FALSE;
1843: } else if (cellDim == 1 && numCorners == 3) {
1844: /* Quadratic line */
1845: faceSize = 1;
1846: posOrient = PETSC_TRUE;
1847: } else if (cellDim == 2 && numCorners == 4) {
1848: /* Quads */
1849: faceSize = 2;
1850: if ((indices[1] > indices[0]) && (indices[1] - indices[0] == 1)) {
1851: posOrient = PETSC_TRUE;
1852: } else if ((indices[0] == 3) && (indices[1] == 0)) {
1853: posOrient = PETSC_TRUE;
1854: } else {
1855: if (((indices[0] > indices[1]) && (indices[0] - indices[1] == 1)) || ((indices[0] == 0) && (indices[1] == 3))) {
1856: posOrient = PETSC_FALSE;
1857: } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossedge");
1858: }
1859: } else if (cellDim == 2 && numCorners == 6) {
1860: /* Quadratic triangle (I hate this) */
1861: /* Edges are determined by the first 2 vertices (corners of edges) */
1862: const PetscInt faceSizeTri = 3;
1863: PetscInt sortedIndices[3], i, iFace;
1864: PetscBool found = PETSC_FALSE;
1865: PetscInt faceVerticesTriSorted[9] = {
1866: 0, 3, 4, /* bottom */
1867: 1, 4, 5, /* right */
1868: 2, 3, 5, /* left */
1869: };
1870: PetscInt faceVerticesTri[9] = {
1871: 0, 3, 4, /* bottom */
1872: 1, 4, 5, /* right */
1873: 2, 5, 3, /* left */
1874: };
1876: faceSize = faceSizeTri;
1877: for (i = 0; i < faceSizeTri; ++i) sortedIndices[i] = indices[i];
1878: PetscSortInt(faceSizeTri, sortedIndices);
1879: for (iFace = 0; iFace < 3; ++iFace) {
1880: const PetscInt ii = iFace*faceSizeTri;
1881: PetscInt fVertex, cVertex;
1883: if ((sortedIndices[0] == faceVerticesTriSorted[ii+0]) &&
1884: (sortedIndices[1] == faceVerticesTriSorted[ii+1])) {
1885: for (fVertex = 0; fVertex < faceSizeTri; ++fVertex) {
1886: for (cVertex = 0; cVertex < faceSizeTri; ++cVertex) {
1887: if (indices[cVertex] == faceVerticesTri[ii+fVertex]) {
1888: faceVertices[fVertex] = origVertices[cVertex];
1889: break;
1890: }
1891: }
1892: }
1893: found = PETSC_TRUE;
1894: break;
1895: }
1896: }
1897: if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tri crossface");
1898: if (posOriented) *posOriented = PETSC_TRUE;
1899: return(0);
1900: } else if (cellDim == 2 && numCorners == 9) {
1901: /* Quadratic quad (I hate this) */
1902: /* Edges are determined by the first 2 vertices (corners of edges) */
1903: const PetscInt faceSizeQuad = 3;
1904: PetscInt sortedIndices[3], i, iFace;
1905: PetscBool found = PETSC_FALSE;
1906: PetscInt faceVerticesQuadSorted[12] = {
1907: 0, 1, 4, /* bottom */
1908: 1, 2, 5, /* right */
1909: 2, 3, 6, /* top */
1910: 0, 3, 7, /* left */
1911: };
1912: PetscInt faceVerticesQuad[12] = {
1913: 0, 1, 4, /* bottom */
1914: 1, 2, 5, /* right */
1915: 2, 3, 6, /* top */
1916: 3, 0, 7, /* left */
1917: };
1919: faceSize = faceSizeQuad;
1920: for (i = 0; i < faceSizeQuad; ++i) sortedIndices[i] = indices[i];
1921: PetscSortInt(faceSizeQuad, sortedIndices);
1922: for (iFace = 0; iFace < 4; ++iFace) {
1923: const PetscInt ii = iFace*faceSizeQuad;
1924: PetscInt fVertex, cVertex;
1926: if ((sortedIndices[0] == faceVerticesQuadSorted[ii+0]) &&
1927: (sortedIndices[1] == faceVerticesQuadSorted[ii+1])) {
1928: for (fVertex = 0; fVertex < faceSizeQuad; ++fVertex) {
1929: for (cVertex = 0; cVertex < faceSizeQuad; ++cVertex) {
1930: if (indices[cVertex] == faceVerticesQuad[ii+fVertex]) {
1931: faceVertices[fVertex] = origVertices[cVertex];
1932: break;
1933: }
1934: }
1935: }
1936: found = PETSC_TRUE;
1937: break;
1938: }
1939: }
1940: if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossface");
1941: if (posOriented) *posOriented = PETSC_TRUE;
1942: return(0);
1943: } else if (cellDim == 3 && numCorners == 8) {
1944: /* Hexes
1945: A hex is two oriented quads with the normal of the first
1946: pointing up at the second.
1948: 7---6
1949: /| /|
1950: 4---5 |
1951: | 1-|-2
1952: |/ |/
1953: 0---3
1955: Faces are determined by the first 4 vertices (corners of faces) */
1956: const PetscInt faceSizeHex = 4;
1957: PetscInt sortedIndices[4], i, iFace;
1958: PetscBool found = PETSC_FALSE;
1959: PetscInt faceVerticesHexSorted[24] = {
1960: 0, 1, 2, 3, /* bottom */
1961: 4, 5, 6, 7, /* top */
1962: 0, 3, 4, 5, /* front */
1963: 2, 3, 5, 6, /* right */
1964: 1, 2, 6, 7, /* back */
1965: 0, 1, 4, 7, /* left */
1966: };
1967: PetscInt faceVerticesHex[24] = {
1968: 1, 2, 3, 0, /* bottom */
1969: 4, 5, 6, 7, /* top */
1970: 0, 3, 5, 4, /* front */
1971: 3, 2, 6, 5, /* right */
1972: 2, 1, 7, 6, /* back */
1973: 1, 0, 4, 7, /* left */
1974: };
1976: faceSize = faceSizeHex;
1977: for (i = 0; i < faceSizeHex; ++i) sortedIndices[i] = indices[i];
1978: PetscSortInt(faceSizeHex, sortedIndices);
1979: for (iFace = 0; iFace < 6; ++iFace) {
1980: const PetscInt ii = iFace*faceSizeHex;
1981: PetscInt fVertex, cVertex;
1983: if ((sortedIndices[0] == faceVerticesHexSorted[ii+0]) &&
1984: (sortedIndices[1] == faceVerticesHexSorted[ii+1]) &&
1985: (sortedIndices[2] == faceVerticesHexSorted[ii+2]) &&
1986: (sortedIndices[3] == faceVerticesHexSorted[ii+3])) {
1987: for (fVertex = 0; fVertex < faceSizeHex; ++fVertex) {
1988: for (cVertex = 0; cVertex < faceSizeHex; ++cVertex) {
1989: if (indices[cVertex] == faceVerticesHex[ii+fVertex]) {
1990: faceVertices[fVertex] = origVertices[cVertex];
1991: break;
1992: }
1993: }
1994: }
1995: found = PETSC_TRUE;
1996: break;
1997: }
1998: }
1999: if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface");
2000: if (posOriented) *posOriented = PETSC_TRUE;
2001: return(0);
2002: } else if (cellDim == 3 && numCorners == 10) {
2003: /* Quadratic tet */
2004: /* Faces are determined by the first 3 vertices (corners of faces) */
2005: const PetscInt faceSizeTet = 6;
2006: PetscInt sortedIndices[6], i, iFace;
2007: PetscBool found = PETSC_FALSE;
2008: PetscInt faceVerticesTetSorted[24] = {
2009: 0, 1, 2, 6, 7, 8, /* bottom */
2010: 0, 3, 4, 6, 7, 9, /* front */
2011: 1, 4, 5, 7, 8, 9, /* right */
2012: 2, 3, 5, 6, 8, 9, /* left */
2013: };
2014: PetscInt faceVerticesTet[24] = {
2015: 0, 1, 2, 6, 7, 8, /* bottom */
2016: 0, 4, 3, 6, 7, 9, /* front */
2017: 1, 5, 4, 7, 8, 9, /* right */
2018: 2, 3, 5, 8, 6, 9, /* left */
2019: };
2021: faceSize = faceSizeTet;
2022: for (i = 0; i < faceSizeTet; ++i) sortedIndices[i] = indices[i];
2023: PetscSortInt(faceSizeTet, sortedIndices);
2024: for (iFace=0; iFace < 4; ++iFace) {
2025: const PetscInt ii = iFace*faceSizeTet;
2026: PetscInt fVertex, cVertex;
2028: if ((sortedIndices[0] == faceVerticesTetSorted[ii+0]) &&
2029: (sortedIndices[1] == faceVerticesTetSorted[ii+1]) &&
2030: (sortedIndices[2] == faceVerticesTetSorted[ii+2]) &&
2031: (sortedIndices[3] == faceVerticesTetSorted[ii+3])) {
2032: for (fVertex = 0; fVertex < faceSizeTet; ++fVertex) {
2033: for (cVertex = 0; cVertex < faceSizeTet; ++cVertex) {
2034: if (indices[cVertex] == faceVerticesTet[ii+fVertex]) {
2035: faceVertices[fVertex] = origVertices[cVertex];
2036: break;
2037: }
2038: }
2039: }
2040: found = PETSC_TRUE;
2041: break;
2042: }
2043: }
2044: if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tet crossface");
2045: if (posOriented) *posOriented = PETSC_TRUE;
2046: return(0);
2047: } else if (cellDim == 3 && numCorners == 27) {
2048: /* Quadratic hexes (I hate this)
2049: A hex is two oriented quads with the normal of the first
2050: pointing up at the second.
2052: 7---6
2053: /| /|
2054: 4---5 |
2055: | 3-|-2
2056: |/ |/
2057: 0---1
2059: Faces are determined by the first 4 vertices (corners of faces) */
2060: const PetscInt faceSizeQuadHex = 9;
2061: PetscInt sortedIndices[9], i, iFace;
2062: PetscBool found = PETSC_FALSE;
2063: PetscInt faceVerticesQuadHexSorted[54] = {
2064: 0, 1, 2, 3, 8, 9, 10, 11, 24, /* bottom */
2065: 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */
2066: 0, 1, 4, 5, 8, 12, 16, 17, 22, /* front */
2067: 1, 2, 5, 6, 9, 13, 17, 18, 21, /* right */
2068: 2, 3, 6, 7, 10, 14, 18, 19, 23, /* back */
2069: 0, 3, 4, 7, 11, 15, 16, 19, 20, /* left */
2070: };
2071: PetscInt faceVerticesQuadHex[54] = {
2072: 3, 2, 1, 0, 10, 9, 8, 11, 24, /* bottom */
2073: 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */
2074: 0, 1, 5, 4, 8, 17, 12, 16, 22, /* front */
2075: 1, 2, 6, 5, 9, 18, 13, 17, 21, /* right */
2076: 2, 3, 7, 6, 10, 19, 14, 18, 23, /* back */
2077: 3, 0, 4, 7, 11, 16, 15, 19, 20 /* left */
2078: };
2080: faceSize = faceSizeQuadHex;
2081: for (i = 0; i < faceSizeQuadHex; ++i) sortedIndices[i] = indices[i];
2082: PetscSortInt(faceSizeQuadHex, sortedIndices);
2083: for (iFace = 0; iFace < 6; ++iFace) {
2084: const PetscInt ii = iFace*faceSizeQuadHex;
2085: PetscInt fVertex, cVertex;
2087: if ((sortedIndices[0] == faceVerticesQuadHexSorted[ii+0]) &&
2088: (sortedIndices[1] == faceVerticesQuadHexSorted[ii+1]) &&
2089: (sortedIndices[2] == faceVerticesQuadHexSorted[ii+2]) &&
2090: (sortedIndices[3] == faceVerticesQuadHexSorted[ii+3])) {
2091: for (fVertex = 0; fVertex < faceSizeQuadHex; ++fVertex) {
2092: for (cVertex = 0; cVertex < faceSizeQuadHex; ++cVertex) {
2093: if (indices[cVertex] == faceVerticesQuadHex[ii+fVertex]) {
2094: faceVertices[fVertex] = origVertices[cVertex];
2095: break;
2096: }
2097: }
2098: }
2099: found = PETSC_TRUE;
2100: break;
2101: }
2102: }
2103: if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface");
2104: if (posOriented) *posOriented = PETSC_TRUE;
2105: return(0);
2106: } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unknown cell type for faceOrientation().");
2107: if (!posOrient) {
2108: if (debug) {PetscPrintf(comm, " Reversing initial face orientation\n");}
2109: for (f = 0; f < faceSize; ++f) faceVertices[f] = origVertices[faceSize-1 - f];
2110: } else {
2111: if (debug) {PetscPrintf(comm, " Keeping initial face orientation\n");}
2112: for (f = 0; f < faceSize; ++f) faceVertices[f] = origVertices[f];
2113: }
2114: if (posOriented) *posOriented = posOrient;
2115: return(0);
2116: }
2120: /*
2121: Given a cell and a face, as a set of vertices,
2122: return the oriented face, as a set of vertices, in faceVertices
2123: The orientation is such that the face normal points out of the cell
2124: */
2125: PetscErrorCode DMPlexGetOrientedFace(DM dm, PetscInt cell, PetscInt faceSize, const PetscInt face[], PetscInt numCorners, PetscInt indices[], PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented)
2126: {
2127: const PetscInt *cone = NULL;
2128: PetscInt coneSize, v, f, v2;
2129: PetscInt oppositeVertex = -1;
2130: PetscErrorCode ierr;
2133: DMPlexGetConeSize(dm, cell, &coneSize);
2134: DMPlexGetCone(dm, cell, &cone);
2135: for (v = 0, v2 = 0; v < coneSize; ++v) {
2136: PetscBool found = PETSC_FALSE;
2138: for (f = 0; f < faceSize; ++f) {
2139: if (face[f] == cone[v]) {
2140: found = PETSC_TRUE; break;
2141: }
2142: }
2143: if (found) {
2144: indices[v2] = v;
2145: origVertices[v2] = cone[v];
2146: ++v2;
2147: } else {
2148: oppositeVertex = v;
2149: }
2150: }
2151: DMPlexGetFaceOrientation(dm, cell, numCorners, indices, oppositeVertex, origVertices, faceVertices, posOriented);
2152: return(0);
2153: }
2157: /*
2158: DMPlexInsertFace_Internal - Puts a face into the mesh
2160: Not collective
2162: Input Parameters:
2163: + dm - The DMPlex
2164: . numFaceVertex - The number of vertices in the face
2165: . faceVertices - The vertices in the face for dm
2166: . subfaceVertices - The vertices in the face for subdm
2167: . numCorners - The number of vertices in the cell
2168: . cell - A cell in dm containing the face
2169: . subcell - A cell in subdm containing the face
2170: . firstFace - First face in the mesh
2171: - newFacePoint - Next face in the mesh
2173: Output Parameters:
2174: . newFacePoint - Contains next face point number on input, updated on output
2176: Level: developer
2177: */
2178: static PetscErrorCode DMPlexInsertFace_Internal(DM dm, DM subdm, PetscInt numFaceVertices, const PetscInt faceVertices[], const PetscInt subfaceVertices[], PetscInt numCorners, PetscInt cell, PetscInt subcell, PetscInt firstFace, PetscInt *newFacePoint)
2179: {
2180: MPI_Comm comm;
2181: DM_Plex *submesh = (DM_Plex*) subdm->data;
2182: const PetscInt *faces;
2183: PetscInt numFaces, coneSize;
2184: PetscErrorCode ierr;
2187: PetscObjectGetComm((PetscObject)dm,&comm);
2188: DMPlexGetConeSize(subdm, subcell, &coneSize);
2189: if (coneSize != 1) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size of cell %d is %d != 1", cell, coneSize);
2190: #if 0
2191: /* Cannot use this because support() has not been constructed yet */
2192: DMPlexGetJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);
2193: #else
2194: {
2195: PetscInt f;
2197: numFaces = 0;
2198: DMGetWorkArray(subdm, 1, PETSC_INT, (void **) &faces);
2199: for (f = firstFace; f < *newFacePoint; ++f) {
2200: PetscInt dof, off, d;
2202: PetscSectionGetDof(submesh->coneSection, f, &dof);
2203: PetscSectionGetOffset(submesh->coneSection, f, &off);
2204: /* Yes, I know this is quadratic, but I expect the sizes to be <5 */
2205: for (d = 0; d < dof; ++d) {
2206: const PetscInt p = submesh->cones[off+d];
2207: PetscInt v;
2209: for (v = 0; v < numFaceVertices; ++v) {
2210: if (subfaceVertices[v] == p) break;
2211: }
2212: if (v == numFaceVertices) break;
2213: }
2214: if (d == dof) {
2215: numFaces = 1;
2216: ((PetscInt*) faces)[0] = f;
2217: }
2218: }
2219: }
2220: #endif
2221: if (numFaces > 1) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Vertex set had %d faces, not one", numFaces);
2222: else if (numFaces == 1) {
2223: /* Add the other cell neighbor for this face */
2224: DMPlexSetCone(subdm, subcell, faces);
2225: } else {
2226: PetscInt *indices, *origVertices, *orientedVertices, *orientedSubVertices, v, ov;
2227: PetscBool posOriented;
2229: DMGetWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);
2230: origVertices = &orientedVertices[numFaceVertices];
2231: indices = &orientedVertices[numFaceVertices*2];
2232: orientedSubVertices = &orientedVertices[numFaceVertices*3];
2233: DMPlexGetOrientedFace(dm, cell, numFaceVertices, faceVertices, numCorners, indices, origVertices, orientedVertices, &posOriented);
2234: /* TODO: I know that routine should return a permutation, not the indices */
2235: for (v = 0; v < numFaceVertices; ++v) {
2236: const PetscInt vertex = faceVertices[v], subvertex = subfaceVertices[v];
2237: for (ov = 0; ov < numFaceVertices; ++ov) {
2238: if (orientedVertices[ov] == vertex) {
2239: orientedSubVertices[ov] = subvertex;
2240: break;
2241: }
2242: }
2243: if (ov == numFaceVertices) SETERRQ1(comm, PETSC_ERR_PLIB, "Could not find face vertex %d in orientated set", vertex);
2244: }
2245: DMPlexSetCone(subdm, *newFacePoint, orientedSubVertices);
2246: DMPlexSetCone(subdm, subcell, newFacePoint);
2247: DMRestoreWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);
2248: ++(*newFacePoint);
2249: }
2250: #if 0
2251: DMPlexRestoreJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);
2252: #else
2253: DMRestoreWorkArray(subdm, 1, PETSC_INT, (void **) &faces);
2254: #endif
2255: return(0);
2256: }
2260: static PetscErrorCode DMPlexCreateSubmesh_Uninterpolated(DM dm, DMLabel vertexLabel, PetscInt value, DM subdm)
2261: {
2262: MPI_Comm comm;
2263: DMLabel subpointMap;
2264: IS subvertexIS, subcellIS;
2265: const PetscInt *subVertices, *subCells;
2266: PetscInt numSubVertices, firstSubVertex, numSubCells;
2267: PetscInt *subface, maxConeSize, numSubFaces = 0, firstSubFace, newFacePoint, nFV = 0;
2268: PetscInt vStart, vEnd, c, f;
2269: PetscErrorCode ierr;
2272: PetscObjectGetComm((PetscObject)dm,&comm);
2273: /* Create subpointMap which marks the submesh */
2274: DMLabelCreate("subpoint_map", &subpointMap);
2275: DMPlexSetSubpointMap(subdm, subpointMap);
2276: DMLabelDestroy(&subpointMap);
2277: if (vertexLabel) {DMPlexMarkSubmesh_Uninterpolated(dm, vertexLabel, value, subpointMap, &numSubFaces, &nFV, subdm);}
2278: /* Setup chart */
2279: DMLabelGetStratumSize(subpointMap, 0, &numSubVertices);
2280: DMLabelGetStratumSize(subpointMap, 2, &numSubCells);
2281: DMPlexSetChart(subdm, 0, numSubCells+numSubFaces+numSubVertices);
2282: DMPlexSetVTKCellHeight(subdm, 1);
2283: /* Set cone sizes */
2284: firstSubVertex = numSubCells;
2285: firstSubFace = numSubCells+numSubVertices;
2286: newFacePoint = firstSubFace;
2287: DMLabelGetStratumIS(subpointMap, 0, &subvertexIS);
2288: if (subvertexIS) {ISGetIndices(subvertexIS, &subVertices);}
2289: DMLabelGetStratumIS(subpointMap, 2, &subcellIS);
2290: if (subcellIS) {ISGetIndices(subcellIS, &subCells);}
2291: for (c = 0; c < numSubCells; ++c) {
2292: DMPlexSetConeSize(subdm, c, 1);
2293: }
2294: for (f = firstSubFace; f < firstSubFace+numSubFaces; ++f) {
2295: DMPlexSetConeSize(subdm, f, nFV);
2296: }
2297: DMSetUp(subdm);
2298: /* Create face cones */
2299: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
2300: DMPlexGetMaxSizes(dm, &maxConeSize, NULL);
2301: DMGetWorkArray(subdm, maxConeSize, PETSC_INT, (void**) &subface);
2302: for (c = 0; c < numSubCells; ++c) {
2303: const PetscInt cell = subCells[c];
2304: const PetscInt subcell = c;
2305: PetscInt *closure = NULL;
2306: PetscInt closureSize, cl, numCorners = 0, faceSize = 0;
2308: DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);
2309: for (cl = 0; cl < closureSize*2; cl += 2) {
2310: const PetscInt point = closure[cl];
2311: PetscInt subVertex;
2313: if ((point >= vStart) && (point < vEnd)) {
2314: ++numCorners;
2315: PetscFindInt(point, numSubVertices, subVertices, &subVertex);
2316: if (subVertex >= 0) {
2317: closure[faceSize] = point;
2318: subface[faceSize] = firstSubVertex+subVertex;
2319: ++faceSize;
2320: }
2321: }
2322: }
2323: if (faceSize > nFV) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize);
2324: if (faceSize == nFV) {
2325: DMPlexInsertFace_Internal(dm, subdm, faceSize, closure, subface, numCorners, cell, subcell, firstSubFace, &newFacePoint);
2326: }
2327: DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);
2328: }
2329: DMRestoreWorkArray(subdm, maxConeSize, PETSC_INT, (void**) &subface);
2330: DMPlexSymmetrize(subdm);
2331: DMPlexStratify(subdm);
2332: /* Build coordinates */
2333: {
2334: PetscSection coordSection, subCoordSection;
2335: Vec coordinates, subCoordinates;
2336: PetscScalar *coords, *subCoords;
2337: PetscInt numComp, coordSize, v;
2339: DMGetCoordinateSection(dm, &coordSection);
2340: DMGetCoordinatesLocal(dm, &coordinates);
2341: DMGetCoordinateSection(subdm, &subCoordSection);
2342: PetscSectionSetNumFields(subCoordSection, 1);
2343: PetscSectionGetFieldComponents(coordSection, 0, &numComp);
2344: PetscSectionSetFieldComponents(subCoordSection, 0, numComp);
2345: PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex+numSubVertices);
2346: for (v = 0; v < numSubVertices; ++v) {
2347: const PetscInt vertex = subVertices[v];
2348: const PetscInt subvertex = firstSubVertex+v;
2349: PetscInt dof;
2351: PetscSectionGetDof(coordSection, vertex, &dof);
2352: PetscSectionSetDof(subCoordSection, subvertex, dof);
2353: PetscSectionSetFieldDof(subCoordSection, subvertex, 0, dof);
2354: }
2355: PetscSectionSetUp(subCoordSection);
2356: PetscSectionGetStorageSize(subCoordSection, &coordSize);
2357: VecCreate(comm, &subCoordinates);
2358: VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);
2359: VecSetType(subCoordinates,VECSTANDARD);
2360: if (coordSize) {
2361: VecGetArray(coordinates, &coords);
2362: VecGetArray(subCoordinates, &subCoords);
2363: for (v = 0; v < numSubVertices; ++v) {
2364: const PetscInt vertex = subVertices[v];
2365: const PetscInt subvertex = firstSubVertex+v;
2366: PetscInt dof, off, sdof, soff, d;
2368: PetscSectionGetDof(coordSection, vertex, &dof);
2369: PetscSectionGetOffset(coordSection, vertex, &off);
2370: PetscSectionGetDof(subCoordSection, subvertex, &sdof);
2371: PetscSectionGetOffset(subCoordSection, subvertex, &soff);
2372: if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subvertex, vertex, dof);
2373: for (d = 0; d < dof; ++d) subCoords[soff+d] = coords[off+d];
2374: }
2375: VecRestoreArray(coordinates, &coords);
2376: VecRestoreArray(subCoordinates, &subCoords);
2377: }
2378: DMSetCoordinatesLocal(subdm, subCoordinates);
2379: VecDestroy(&subCoordinates);
2380: }
2381: /* Cleanup */
2382: if (subvertexIS) {ISRestoreIndices(subvertexIS, &subVertices);}
2383: ISDestroy(&subvertexIS);
2384: if (subcellIS) {ISRestoreIndices(subcellIS, &subCells);}
2385: ISDestroy(&subcellIS);
2386: return(0);
2387: }
2391: static PetscErrorCode DMPlexCreateSubmesh_Interpolated(DM dm, DMLabel vertexLabel, PetscInt value, DM subdm)
2392: {
2393: MPI_Comm comm;
2394: DMLabel subpointMap;
2395: IS *subpointIS;
2396: const PetscInt **subpoints;
2397: PetscInt *numSubPoints, *firstSubPoint, *coneNew, *coneONew;
2398: PetscInt totSubPoints = 0, maxConeSize, dim, p, d, v;
2399: PetscErrorCode ierr;
2402: PetscObjectGetComm((PetscObject)dm,&comm);
2403: /* Create subpointMap which marks the submesh */
2404: DMLabelCreate("subpoint_map", &subpointMap);
2405: DMPlexSetSubpointMap(subdm, subpointMap);
2406: DMLabelDestroy(&subpointMap);
2407: if (vertexLabel) {DMPlexMarkSubmesh_Interpolated(dm, vertexLabel, value, subpointMap, subdm);}
2408: /* Setup chart */
2409: DMPlexGetDimension(dm, &dim);
2410: PetscMalloc4(dim+1,&numSubPoints,dim+1,&firstSubPoint,dim+1,&subpointIS,dim+1,&subpoints);
2411: for (d = 0; d <= dim; ++d) {
2412: DMLabelGetStratumSize(subpointMap, d, &numSubPoints[d]);
2413: totSubPoints += numSubPoints[d];
2414: }
2415: DMPlexSetChart(subdm, 0, totSubPoints);
2416: DMPlexSetVTKCellHeight(subdm, 1);
2417: /* Set cone sizes */
2418: firstSubPoint[dim] = 0;
2419: firstSubPoint[0] = firstSubPoint[dim] + numSubPoints[dim];
2420: if (dim > 1) {firstSubPoint[dim-1] = firstSubPoint[0] + numSubPoints[0];}
2421: if (dim > 2) {firstSubPoint[dim-2] = firstSubPoint[dim-1] + numSubPoints[dim-1];}
2422: for (d = 0; d <= dim; ++d) {
2423: DMLabelGetStratumIS(subpointMap, d, &subpointIS[d]);
2424: if (subpointIS[d]) {ISGetIndices(subpointIS[d], &subpoints[d]);}
2425: }
2426: for (d = 0; d <= dim; ++d) {
2427: for (p = 0; p < numSubPoints[d]; ++p) {
2428: const PetscInt point = subpoints[d][p];
2429: const PetscInt subpoint = firstSubPoint[d] + p;
2430: const PetscInt *cone;
2431: PetscInt coneSize, coneSizeNew, c, val;
2433: DMPlexGetConeSize(dm, point, &coneSize);
2434: DMPlexSetConeSize(subdm, subpoint, coneSize);
2435: if (d == dim) {
2436: DMPlexGetCone(dm, point, &cone);
2437: for (c = 0, coneSizeNew = 0; c < coneSize; ++c) {
2438: DMLabelGetValue(subpointMap, cone[c], &val);
2439: if (val >= 0) coneSizeNew++;
2440: }
2441: DMPlexSetConeSize(subdm, subpoint, coneSizeNew);
2442: }
2443: }
2444: }
2445: DMSetUp(subdm);
2446: /* Set cones */
2447: DMPlexGetMaxSizes(dm, &maxConeSize, NULL);
2448: PetscMalloc2(maxConeSize,&coneNew,maxConeSize,&coneONew);
2449: for (d = 0; d <= dim; ++d) {
2450: for (p = 0; p < numSubPoints[d]; ++p) {
2451: const PetscInt point = subpoints[d][p];
2452: const PetscInt subpoint = firstSubPoint[d] + p;
2453: const PetscInt *cone, *ornt;
2454: PetscInt coneSize, subconeSize, coneSizeNew, c, subc;
2456: DMPlexGetConeSize(dm, point, &coneSize);
2457: DMPlexGetConeSize(subdm, subpoint, &subconeSize);
2458: DMPlexGetCone(dm, point, &cone);
2459: DMPlexGetConeOrientation(dm, point, &ornt);
2460: for (c = 0, coneSizeNew = 0; c < coneSize; ++c) {
2461: PetscFindInt(cone[c], numSubPoints[d-1], subpoints[d-1], &subc);
2462: if (subc >= 0) {
2463: coneNew[coneSizeNew] = firstSubPoint[d-1] + subc;
2464: coneONew[coneSizeNew] = ornt[c];
2465: ++coneSizeNew;
2466: }
2467: }
2468: if (coneSizeNew != subconeSize) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of cone points located %d does not match subcone size %d", coneSizeNew, subconeSize);
2469: DMPlexSetCone(subdm, subpoint, coneNew);
2470: DMPlexSetConeOrientation(subdm, subpoint, coneONew);
2471: }
2472: }
2473: PetscFree2(coneNew,coneONew);
2474: DMPlexSymmetrize(subdm);
2475: DMPlexStratify(subdm);
2476: /* Build coordinates */
2477: {
2478: PetscSection coordSection, subCoordSection;
2479: Vec coordinates, subCoordinates;
2480: PetscScalar *coords, *subCoords;
2481: PetscInt numComp, coordSize;
2483: DMGetCoordinateSection(dm, &coordSection);
2484: DMGetCoordinatesLocal(dm, &coordinates);
2485: DMGetCoordinateSection(subdm, &subCoordSection);
2486: PetscSectionSetNumFields(subCoordSection, 1);
2487: PetscSectionGetFieldComponents(coordSection, 0, &numComp);
2488: PetscSectionSetFieldComponents(subCoordSection, 0, numComp);
2489: PetscSectionSetChart(subCoordSection, firstSubPoint[0], firstSubPoint[0]+numSubPoints[0]);
2490: for (v = 0; v < numSubPoints[0]; ++v) {
2491: const PetscInt vertex = subpoints[0][v];
2492: const PetscInt subvertex = firstSubPoint[0]+v;
2493: PetscInt dof;
2495: PetscSectionGetDof(coordSection, vertex, &dof);
2496: PetscSectionSetDof(subCoordSection, subvertex, dof);
2497: PetscSectionSetFieldDof(subCoordSection, subvertex, 0, dof);
2498: }
2499: PetscSectionSetUp(subCoordSection);
2500: PetscSectionGetStorageSize(subCoordSection, &coordSize);
2501: VecCreate(comm, &subCoordinates);
2502: VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);
2503: VecSetType(subCoordinates,VECSTANDARD);
2504: VecGetArray(coordinates, &coords);
2505: VecGetArray(subCoordinates, &subCoords);
2506: for (v = 0; v < numSubPoints[0]; ++v) {
2507: const PetscInt vertex = subpoints[0][v];
2508: const PetscInt subvertex = firstSubPoint[0]+v;
2509: PetscInt dof, off, sdof, soff, d;
2511: PetscSectionGetDof(coordSection, vertex, &dof);
2512: PetscSectionGetOffset(coordSection, vertex, &off);
2513: PetscSectionGetDof(subCoordSection, subvertex, &sdof);
2514: PetscSectionGetOffset(subCoordSection, subvertex, &soff);
2515: if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subvertex, vertex, dof);
2516: for (d = 0; d < dof; ++d) subCoords[soff+d] = coords[off+d];
2517: }
2518: VecRestoreArray(coordinates, &coords);
2519: VecRestoreArray(subCoordinates, &subCoords);
2520: DMSetCoordinatesLocal(subdm, subCoordinates);
2521: VecDestroy(&subCoordinates);
2522: }
2523: /* Cleanup */
2524: for (d = 0; d <= dim; ++d) {
2525: if (subpointIS[d]) {ISRestoreIndices(subpointIS[d], &subpoints[d]);}
2526: ISDestroy(&subpointIS[d]);
2527: }
2528: PetscFree4(numSubPoints,firstSubPoint,subpointIS,subpoints);
2529: return(0);
2530: }
2534: /*@
2535: DMPlexCreateSubmesh - Extract a hypersurface from the mesh using vertices defined by a label
2537: Input Parameters:
2538: + dm - The original mesh
2539: . vertexLabel - The DMLabel marking vertices contained in the surface
2540: - value - The label value to use
2542: Output Parameter:
2543: . subdm - The surface mesh
2545: Note: This function produces a DMLabel mapping original points in the submesh to their depth. This can be obtained using DMPlexGetSubpointMap().
2547: Level: developer
2549: .seealso: DMPlexGetSubpointMap(), DMPlexGetLabel(), DMLabelSetValue()
2550: @*/
2551: PetscErrorCode DMPlexCreateSubmesh(DM dm, DMLabel vertexLabel, PetscInt value, DM *subdm)
2552: {
2553: PetscInt dim, depth;
2559: DMPlexGetDimension(dm, &dim);
2560: DMPlexGetDepth(dm, &depth);
2561: DMCreate(PetscObjectComm((PetscObject)dm), subdm);
2562: DMSetType(*subdm, DMPLEX);
2563: DMPlexSetDimension(*subdm, dim-1);
2564: if (depth == dim) {
2565: DMPlexCreateSubmesh_Interpolated(dm, vertexLabel, value, *subdm);
2566: } else {
2567: DMPlexCreateSubmesh_Uninterpolated(dm, vertexLabel, value, *subdm);
2568: }
2569: return(0);
2570: }
2574: PETSC_STATIC_INLINE PetscInt DMPlexFilterPoint_Internal(PetscInt point, PetscInt firstSubPoint, PetscInt numSubPoints, const PetscInt subPoints[])
2575: {
2576: PetscInt subPoint;
2579: PetscFindInt(point, numSubPoints, subPoints, &subPoint); if (ierr < 0) return ierr;
2580: return subPoint < 0 ? subPoint : firstSubPoint+subPoint;
2581: }
2585: static PetscErrorCode DMPlexCreateCohesiveSubmesh_Uninterpolated(DM dm, PetscBool hasLagrange, const char label[], PetscInt value, DM subdm)
2586: {
2587: MPI_Comm comm;
2588: DMLabel subpointMap;
2589: IS subvertexIS;
2590: const PetscInt *subVertices;
2591: PetscInt numSubVertices, firstSubVertex, numSubCells, *subCells = NULL;
2592: PetscInt *subface, maxConeSize, numSubFaces, firstSubFace, newFacePoint, nFV;
2593: PetscInt cMax, c, f;
2594: PetscErrorCode ierr;
2597: PetscObjectGetComm((PetscObject)dm, &comm);
2598: /* Create subpointMap which marks the submesh */
2599: DMLabelCreate("subpoint_map", &subpointMap);
2600: DMPlexSetSubpointMap(subdm, subpointMap);
2601: DMLabelDestroy(&subpointMap);
2602: DMPlexMarkCohesiveSubmesh_Uninterpolated(dm, hasLagrange, label, value, subpointMap, &numSubFaces, &nFV, &subCells, subdm);
2603: /* Setup chart */
2604: DMLabelGetStratumSize(subpointMap, 0, &numSubVertices);
2605: DMLabelGetStratumSize(subpointMap, 2, &numSubCells);
2606: DMPlexSetChart(subdm, 0, numSubCells+numSubFaces+numSubVertices);
2607: DMPlexSetVTKCellHeight(subdm, 1);
2608: /* Set cone sizes */
2609: firstSubVertex = numSubCells;
2610: firstSubFace = numSubCells+numSubVertices;
2611: newFacePoint = firstSubFace;
2612: DMLabelGetStratumIS(subpointMap, 0, &subvertexIS);
2613: if (subvertexIS) {ISGetIndices(subvertexIS, &subVertices);}
2614: for (c = 0; c < numSubCells; ++c) {
2615: DMPlexSetConeSize(subdm, c, 1);
2616: }
2617: for (f = firstSubFace; f < firstSubFace+numSubFaces; ++f) {
2618: DMPlexSetConeSize(subdm, f, nFV);
2619: }
2620: DMSetUp(subdm);
2621: /* Create face cones */
2622: DMPlexGetMaxSizes(dm, &maxConeSize, NULL);
2623: DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);
2624: DMGetWorkArray(subdm, maxConeSize, PETSC_INT, (void**) &subface);
2625: for (c = 0; c < numSubCells; ++c) {
2626: const PetscInt cell = subCells[c];
2627: const PetscInt subcell = c;
2628: const PetscInt *cone, *cells;
2629: PetscInt numCells, subVertex, p, v;
2631: if (cell < cMax) continue;
2632: DMPlexGetCone(dm, cell, &cone);
2633: for (v = 0; v < nFV; ++v) {
2634: PetscFindInt(cone[v], numSubVertices, subVertices, &subVertex);
2635: subface[v] = firstSubVertex+subVertex;
2636: }
2637: DMPlexSetCone(subdm, newFacePoint, subface);
2638: DMPlexSetCone(subdm, subcell, &newFacePoint);
2639: DMPlexGetJoin(dm, nFV, cone, &numCells, &cells);
2640: /* Not true in parallel
2641: if (numCells != 2) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cohesive cells should separate two cells"); */
2642: for (p = 0; p < numCells; ++p) {
2643: PetscInt negsubcell;
2645: if (cells[p] >= cMax) continue;
2646: /* I know this is a crap search */
2647: for (negsubcell = 0; negsubcell < numSubCells; ++negsubcell) {
2648: if (subCells[negsubcell] == cells[p]) break;
2649: }
2650: if (negsubcell == numSubCells) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find negative face neighbor for cohesive cell %d", cell);
2651: DMPlexSetCone(subdm, negsubcell, &newFacePoint);
2652: }
2653: DMPlexRestoreJoin(dm, nFV, cone, &numCells, &cells);
2654: ++newFacePoint;
2655: }
2656: DMRestoreWorkArray(subdm, maxConeSize, PETSC_INT, (void**) &subface);
2657: DMPlexSymmetrize(subdm);
2658: DMPlexStratify(subdm);
2659: /* Build coordinates */
2660: {
2661: PetscSection coordSection, subCoordSection;
2662: Vec coordinates, subCoordinates;
2663: PetscScalar *coords, *subCoords;
2664: PetscInt numComp, coordSize, v;
2666: DMGetCoordinateSection(dm, &coordSection);
2667: DMGetCoordinatesLocal(dm, &coordinates);
2668: DMGetCoordinateSection(subdm, &subCoordSection);
2669: PetscSectionSetNumFields(subCoordSection, 1);
2670: PetscSectionGetFieldComponents(coordSection, 0, &numComp);
2671: PetscSectionSetFieldComponents(subCoordSection, 0, numComp);
2672: PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex+numSubVertices);
2673: for (v = 0; v < numSubVertices; ++v) {
2674: const PetscInt vertex = subVertices[v];
2675: const PetscInt subvertex = firstSubVertex+v;
2676: PetscInt dof;
2678: PetscSectionGetDof(coordSection, vertex, &dof);
2679: PetscSectionSetDof(subCoordSection, subvertex, dof);
2680: PetscSectionSetFieldDof(subCoordSection, subvertex, 0, dof);
2681: }
2682: PetscSectionSetUp(subCoordSection);
2683: PetscSectionGetStorageSize(subCoordSection, &coordSize);
2684: VecCreate(comm, &subCoordinates);
2685: VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);
2686: VecSetType(subCoordinates,VECSTANDARD);
2687: VecGetArray(coordinates, &coords);
2688: VecGetArray(subCoordinates, &subCoords);
2689: for (v = 0; v < numSubVertices; ++v) {
2690: const PetscInt vertex = subVertices[v];
2691: const PetscInt subvertex = firstSubVertex+v;
2692: PetscInt dof, off, sdof, soff, d;
2694: PetscSectionGetDof(coordSection, vertex, &dof);
2695: PetscSectionGetOffset(coordSection, vertex, &off);
2696: PetscSectionGetDof(subCoordSection, subvertex, &sdof);
2697: PetscSectionGetOffset(subCoordSection, subvertex, &soff);
2698: if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subvertex, vertex, dof);
2699: for (d = 0; d < dof; ++d) subCoords[soff+d] = coords[off+d];
2700: }
2701: VecRestoreArray(coordinates, &coords);
2702: VecRestoreArray(subCoordinates, &subCoords);
2703: DMSetCoordinatesLocal(subdm, subCoordinates);
2704: VecDestroy(&subCoordinates);
2705: }
2706: /* Build SF */
2707: CHKMEMQ;
2708: {
2709: PetscSF sfPoint, sfPointSub;
2710: const PetscSFNode *remotePoints;
2711: PetscSFNode *sremotePoints, *newLocalPoints, *newOwners;
2712: const PetscInt *localPoints;
2713: PetscInt *slocalPoints;
2714: PetscInt numRoots, numLeaves, numSubRoots = numSubCells+numSubFaces+numSubVertices, numSubLeaves = 0, l, sl, ll, pStart, pEnd, p, vStart, vEnd;
2715: PetscMPIInt rank;
2717: MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);
2718: DMGetPointSF(dm, &sfPoint);
2719: DMGetPointSF(subdm, &sfPointSub);
2720: DMPlexGetChart(dm, &pStart, &pEnd);
2721: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
2722: PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);
2723: if (numRoots >= 0) {
2724: /* Only vertices should be shared */
2725: PetscMalloc2(pEnd-pStart,&newLocalPoints,numRoots,&newOwners);
2726: for (p = 0; p < pEnd-pStart; ++p) {
2727: newLocalPoints[p].rank = -2;
2728: newLocalPoints[p].index = -2;
2729: }
2730: /* Set subleaves */
2731: for (l = 0; l < numLeaves; ++l) {
2732: const PetscInt point = localPoints[l];
2733: const PetscInt subPoint = DMPlexFilterPoint_Internal(point, firstSubVertex, numSubVertices, subVertices);
2735: if ((point < vStart) && (point >= vEnd)) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Should not be mapping anything but vertices, %d", point);
2736: if (subPoint < 0) continue;
2737: newLocalPoints[point-pStart].rank = rank;
2738: newLocalPoints[point-pStart].index = subPoint;
2739: ++numSubLeaves;
2740: }
2741: /* Must put in owned subpoints */
2742: for (p = pStart; p < pEnd; ++p) {
2743: const PetscInt subPoint = DMPlexFilterPoint_Internal(p, firstSubVertex, numSubVertices, subVertices);
2745: if (subPoint < 0) {
2746: newOwners[p-pStart].rank = -3;
2747: newOwners[p-pStart].index = -3;
2748: } else {
2749: newOwners[p-pStart].rank = rank;
2750: newOwners[p-pStart].index = subPoint;
2751: }
2752: }
2753: PetscSFReduceBegin(sfPoint, MPIU_2INT, newLocalPoints, newOwners, MPI_MAXLOC);
2754: PetscSFReduceEnd(sfPoint, MPIU_2INT, newLocalPoints, newOwners, MPI_MAXLOC);
2755: PetscSFBcastBegin(sfPoint, MPIU_2INT, newOwners, newLocalPoints);
2756: PetscSFBcastEnd(sfPoint, MPIU_2INT, newOwners, newLocalPoints);
2757: PetscMalloc1(numSubLeaves, &slocalPoints);
2758: PetscMalloc1(numSubLeaves, &sremotePoints);
2759: for (l = 0, sl = 0, ll = 0; l < numLeaves; ++l) {
2760: const PetscInt point = localPoints[l];
2761: const PetscInt subPoint = DMPlexFilterPoint_Internal(point, firstSubVertex, numSubVertices, subVertices);
2763: if (subPoint < 0) continue;
2764: if (newLocalPoints[point].rank == rank) {++ll; continue;}
2765: slocalPoints[sl] = subPoint;
2766: sremotePoints[sl].rank = newLocalPoints[point].rank;
2767: sremotePoints[sl].index = newLocalPoints[point].index;
2768: if (sremotePoints[sl].rank < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid remote rank for local point %d", point);
2769: if (sremotePoints[sl].index < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid remote subpoint for local point %d", point);
2770: ++sl;
2771: }
2772: PetscFree2(newLocalPoints,newOwners);
2773: if (sl + ll != numSubLeaves) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatch in number of subleaves %d + %d != %d", sl, ll, numSubLeaves);
2774: PetscSFSetGraph(sfPointSub, numSubRoots, sl, slocalPoints, PETSC_OWN_POINTER, sremotePoints, PETSC_OWN_POINTER);
2775: }
2776: }
2777: CHKMEMQ;
2778: /* Cleanup */
2779: if (subvertexIS) {ISRestoreIndices(subvertexIS, &subVertices);}
2780: ISDestroy(&subvertexIS);
2781: PetscFree(subCells);
2782: return(0);
2783: }
2787: static PetscErrorCode DMPlexCreateCohesiveSubmesh_Interpolated(DM dm, const char label[], PetscInt value, DM subdm)
2788: {
2789: MPI_Comm comm;
2790: DMLabel subpointMap;
2791: IS *subpointIS;
2792: const PetscInt **subpoints;
2793: PetscInt *numSubPoints, *firstSubPoint, *coneNew, *orntNew;
2794: PetscInt totSubPoints = 0, maxConeSize, dim, p, d, v;
2795: PetscErrorCode ierr;
2798: PetscObjectGetComm((PetscObject)dm,&comm);
2799: /* Create subpointMap which marks the submesh */
2800: DMLabelCreate("subpoint_map", &subpointMap);
2801: DMPlexSetSubpointMap(subdm, subpointMap);
2802: DMLabelDestroy(&subpointMap);
2803: DMPlexMarkCohesiveSubmesh_Interpolated(dm, label, value, subpointMap, subdm);
2804: /* Setup chart */
2805: DMPlexGetDimension(dm, &dim);
2806: PetscMalloc4(dim+1,&numSubPoints,dim+1,&firstSubPoint,dim+1,&subpointIS,dim+1,&subpoints);
2807: for (d = 0; d <= dim; ++d) {
2808: DMLabelGetStratumSize(subpointMap, d, &numSubPoints[d]);
2809: totSubPoints += numSubPoints[d];
2810: }
2811: DMPlexSetChart(subdm, 0, totSubPoints);
2812: DMPlexSetVTKCellHeight(subdm, 1);
2813: /* Set cone sizes */
2814: firstSubPoint[dim] = 0;
2815: firstSubPoint[0] = firstSubPoint[dim] + numSubPoints[dim];
2816: if (dim > 1) {firstSubPoint[dim-1] = firstSubPoint[0] + numSubPoints[0];}
2817: if (dim > 2) {firstSubPoint[dim-2] = firstSubPoint[dim-1] + numSubPoints[dim-1];}
2818: for (d = 0; d <= dim; ++d) {
2819: DMLabelGetStratumIS(subpointMap, d, &subpointIS[d]);
2820: if (subpointIS[d]) {ISGetIndices(subpointIS[d], &subpoints[d]);}
2821: }
2822: for (d = 0; d <= dim; ++d) {
2823: for (p = 0; p < numSubPoints[d]; ++p) {
2824: const PetscInt point = subpoints[d][p];
2825: const PetscInt subpoint = firstSubPoint[d] + p;
2826: const PetscInt *cone;
2827: PetscInt coneSize, coneSizeNew, c, val;
2829: DMPlexGetConeSize(dm, point, &coneSize);
2830: DMPlexSetConeSize(subdm, subpoint, coneSize);
2831: if (d == dim) {
2832: DMPlexGetCone(dm, point, &cone);
2833: for (c = 0, coneSizeNew = 0; c < coneSize; ++c) {
2834: DMLabelGetValue(subpointMap, cone[c], &val);
2835: if (val >= 0) coneSizeNew++;
2836: }
2837: DMPlexSetConeSize(subdm, subpoint, coneSizeNew);
2838: }
2839: }
2840: }
2841: DMSetUp(subdm);
2842: /* Set cones */
2843: DMPlexGetMaxSizes(dm, &maxConeSize, NULL);
2844: PetscMalloc2(maxConeSize,&coneNew,maxConeSize,&orntNew);
2845: for (d = 0; d <= dim; ++d) {
2846: for (p = 0; p < numSubPoints[d]; ++p) {
2847: const PetscInt point = subpoints[d][p];
2848: const PetscInt subpoint = firstSubPoint[d] + p;
2849: const PetscInt *cone, *ornt;
2850: PetscInt coneSize, subconeSize, coneSizeNew, c, subc;
2852: DMPlexGetConeSize(dm, point, &coneSize);
2853: DMPlexGetConeSize(subdm, subpoint, &subconeSize);
2854: DMPlexGetCone(dm, point, &cone);
2855: DMPlexGetConeOrientation(dm, point, &ornt);
2856: for (c = 0, coneSizeNew = 0; c < coneSize; ++c) {
2857: PetscFindInt(cone[c], numSubPoints[d-1], subpoints[d-1], &subc);
2858: if (subc >= 0) {
2859: coneNew[coneSizeNew] = firstSubPoint[d-1] + subc;
2860: orntNew[coneSizeNew++] = ornt[c];
2861: }
2862: }
2863: if (coneSizeNew != subconeSize) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of cone points located %d does not match subcone size %d", coneSizeNew, subconeSize);
2864: DMPlexSetCone(subdm, subpoint, coneNew);
2865: DMPlexSetConeOrientation(subdm, subpoint, orntNew);
2866: }
2867: }
2868: PetscFree2(coneNew,orntNew);
2869: DMPlexSymmetrize(subdm);
2870: DMPlexStratify(subdm);
2871: /* Build coordinates */
2872: {
2873: PetscSection coordSection, subCoordSection;
2874: Vec coordinates, subCoordinates;
2875: PetscScalar *coords, *subCoords;
2876: PetscInt numComp, coordSize;
2878: DMGetCoordinateSection(dm, &coordSection);
2879: DMGetCoordinatesLocal(dm, &coordinates);
2880: DMGetCoordinateSection(subdm, &subCoordSection);
2881: PetscSectionSetNumFields(subCoordSection, 1);
2882: PetscSectionGetFieldComponents(coordSection, 0, &numComp);
2883: PetscSectionSetFieldComponents(subCoordSection, 0, numComp);
2884: PetscSectionSetChart(subCoordSection, firstSubPoint[0], firstSubPoint[0]+numSubPoints[0]);
2885: for (v = 0; v < numSubPoints[0]; ++v) {
2886: const PetscInt vertex = subpoints[0][v];
2887: const PetscInt subvertex = firstSubPoint[0]+v;
2888: PetscInt dof;
2890: PetscSectionGetDof(coordSection, vertex, &dof);
2891: PetscSectionSetDof(subCoordSection, subvertex, dof);
2892: PetscSectionSetFieldDof(subCoordSection, subvertex, 0, dof);
2893: }
2894: PetscSectionSetUp(subCoordSection);
2895: PetscSectionGetStorageSize(subCoordSection, &coordSize);
2896: VecCreate(comm, &subCoordinates);
2897: VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);
2898: VecSetType(subCoordinates,VECSTANDARD);
2899: VecGetArray(coordinates, &coords);
2900: VecGetArray(subCoordinates, &subCoords);
2901: for (v = 0; v < numSubPoints[0]; ++v) {
2902: const PetscInt vertex = subpoints[0][v];
2903: const PetscInt subvertex = firstSubPoint[0]+v;
2904: PetscInt dof, off, sdof, soff, d;
2906: PetscSectionGetDof(coordSection, vertex, &dof);
2907: PetscSectionGetOffset(coordSection, vertex, &off);
2908: PetscSectionGetDof(subCoordSection, subvertex, &sdof);
2909: PetscSectionGetOffset(subCoordSection, subvertex, &soff);
2910: if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subvertex, vertex, dof);
2911: for (d = 0; d < dof; ++d) subCoords[soff+d] = coords[off+d];
2912: }
2913: VecRestoreArray(coordinates, &coords);
2914: VecRestoreArray(subCoordinates, &subCoords);
2915: DMSetCoordinatesLocal(subdm, subCoordinates);
2916: VecDestroy(&subCoordinates);
2917: }
2918: /* Build SF: We need this complexity because subpoints might not be selected on the owning process */
2919: {
2920: PetscSF sfPoint, sfPointSub;
2921: IS subpIS;
2922: const PetscSFNode *remotePoints;
2923: PetscSFNode *sremotePoints, *newLocalPoints, *newOwners;
2924: const PetscInt *localPoints, *subpoints;
2925: PetscInt *slocalPoints;
2926: PetscInt numRoots, numLeaves, numSubpoints = 0, numSubroots, numSubleaves = 0, l, sl, ll, pStart, pEnd, p;
2927: PetscMPIInt rank;
2929: MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);
2930: DMGetPointSF(dm, &sfPoint);
2931: DMGetPointSF(subdm, &sfPointSub);
2932: DMPlexGetChart(dm, &pStart, &pEnd);
2933: DMPlexGetChart(subdm, NULL, &numSubroots);
2934: DMPlexCreateSubpointIS(subdm, &subpIS);
2935: if (subpIS) {
2936: ISGetIndices(subpIS, &subpoints);
2937: ISGetLocalSize(subpIS, &numSubpoints);
2938: }
2939: PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);
2940: if (numRoots >= 0) {
2941: PetscMalloc2(pEnd-pStart,&newLocalPoints,numRoots,&newOwners);
2942: for (p = 0; p < pEnd-pStart; ++p) {
2943: newLocalPoints[p].rank = -2;
2944: newLocalPoints[p].index = -2;
2945: }
2946: /* Set subleaves */
2947: for (l = 0; l < numLeaves; ++l) {
2948: const PetscInt point = localPoints[l];
2949: const PetscInt subpoint = DMPlexFilterPoint_Internal(point, 0, numSubpoints, subpoints);
2951: if (subpoint < 0) continue;
2952: newLocalPoints[point-pStart].rank = rank;
2953: newLocalPoints[point-pStart].index = subpoint;
2954: ++numSubleaves;
2955: }
2956: /* Must put in owned subpoints */
2957: for (p = pStart; p < pEnd; ++p) {
2958: const PetscInt subpoint = DMPlexFilterPoint_Internal(p, 0, numSubpoints, subpoints);
2960: if (subpoint < 0) {
2961: newOwners[p-pStart].rank = -3;
2962: newOwners[p-pStart].index = -3;
2963: } else {
2964: newOwners[p-pStart].rank = rank;
2965: newOwners[p-pStart].index = subpoint;
2966: }
2967: }
2968: PetscSFReduceBegin(sfPoint, MPIU_2INT, newLocalPoints, newOwners, MPI_MAXLOC);
2969: PetscSFReduceEnd(sfPoint, MPIU_2INT, newLocalPoints, newOwners, MPI_MAXLOC);
2970: PetscSFBcastBegin(sfPoint, MPIU_2INT, newOwners, newLocalPoints);
2971: PetscSFBcastEnd(sfPoint, MPIU_2INT, newOwners, newLocalPoints);
2972: PetscMalloc(numSubleaves * sizeof(PetscInt), &slocalPoints);
2973: PetscMalloc(numSubleaves * sizeof(PetscSFNode), &sremotePoints);
2974: for (l = 0, sl = 0, ll = 0; l < numLeaves; ++l) {
2975: const PetscInt point = localPoints[l];
2976: const PetscInt subpoint = DMPlexFilterPoint_Internal(point, 0, numSubpoints, subpoints);
2978: if (subpoint < 0) continue;
2979: if (newLocalPoints[point].rank == rank) {++ll; continue;}
2980: slocalPoints[sl] = subpoint;
2981: sremotePoints[sl].rank = newLocalPoints[point].rank;
2982: sremotePoints[sl].index = newLocalPoints[point].index;
2983: if (sremotePoints[sl].rank < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid remote rank for local point %d", point);
2984: if (sremotePoints[sl].index < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid remote subpoint for local point %d", point);
2985: ++sl;
2986: }
2987: if (sl + ll != numSubleaves) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatch in number of subleaves %d + %d != %d", sl, ll, numSubleaves);
2988: PetscFree2(newLocalPoints,newOwners);
2989: PetscSFSetGraph(sfPointSub, numSubroots, sl, slocalPoints, PETSC_OWN_POINTER, sremotePoints, PETSC_OWN_POINTER);
2990: }
2991: if (subpIS) {
2992: ISRestoreIndices(subpIS, &subpoints);
2993: ISDestroy(&subpIS);
2994: }
2995: }
2996: /* Cleanup */
2997: for (d = 0; d <= dim; ++d) {
2998: if (subpointIS[d]) {ISRestoreIndices(subpointIS[d], &subpoints[d]);}
2999: ISDestroy(&subpointIS[d]);
3000: }
3001: PetscFree4(numSubPoints,firstSubPoint,subpointIS,subpoints);
3002: return(0);
3003: }
3007: /*
3008: DMPlexCreateCohesiveSubmesh - Extract from a mesh with cohesive cells the hypersurface defined by one face of the cells. Optionally, a Label an be given to restrict the cells.
3010: Input Parameters:
3011: + dm - The original mesh
3012: . hasLagrange - The mesh has Lagrange unknowns in the cohesive cells
3013: . label - A label name, or PETSC_NULL
3014: - value - A label value
3016: Output Parameter:
3017: . subdm - The surface mesh
3019: Note: This function produces a DMLabel mapping original points in the submesh to their depth. This can be obtained using DMPlexGetSubpointMap().
3021: Level: developer
3023: .seealso: DMPlexGetSubpointMap(), DMPlexCreateSubmesh()
3024: */
3025: PetscErrorCode DMPlexCreateCohesiveSubmesh(DM dm, PetscBool hasLagrange, const char label[], PetscInt value, DM *subdm)
3026: {
3027: PetscInt dim, depth;
3033: DMPlexGetDimension(dm, &dim);
3034: DMPlexGetDepth(dm, &depth);
3035: DMCreate(PetscObjectComm((PetscObject)dm), subdm);
3036: DMSetType(*subdm, DMPLEX);
3037: DMPlexSetDimension(*subdm, dim-1);
3038: if (depth == dim) {
3039: DMPlexCreateCohesiveSubmesh_Interpolated(dm, label, value, *subdm);
3040: } else {
3041: DMPlexCreateCohesiveSubmesh_Uninterpolated(dm, hasLagrange, label, value, *subdm);
3042: }
3043: return(0);
3044: }
3048: /*@
3049: DMPlexGetSubpointMap - Returns a DMLabel with point dimension as values
3051: Input Parameter:
3052: . dm - The submesh DM
3054: Output Parameter:
3055: . subpointMap - The DMLabel of all the points from the original mesh in this submesh, or NULL if this is not a submesh
3057: Level: developer
3059: .seealso: DMPlexCreateSubmesh(), DMPlexCreateSubpointIS()
3060: @*/
3061: PetscErrorCode DMPlexGetSubpointMap(DM dm, DMLabel *subpointMap)
3062: {
3063: DM_Plex *mesh = (DM_Plex*) dm->data;
3068: *subpointMap = mesh->subpointMap;
3069: return(0);
3070: }
3074: /* Note: Should normally not be called by the user, since it is set in DMPlexCreateSubmesh() */
3075: PetscErrorCode DMPlexSetSubpointMap(DM dm, DMLabel subpointMap)
3076: {
3077: DM_Plex *mesh = (DM_Plex *) dm->data;
3078: DMLabel tmp;
3083: tmp = mesh->subpointMap;
3084: mesh->subpointMap = subpointMap;
3085: ++mesh->subpointMap->refct;
3086: DMLabelDestroy(&tmp);
3087: return(0);
3088: }
3092: /*@
3093: DMPlexCreateSubpointIS - Creates an IS covering the entire subdm chart with the original points as data
3095: Input Parameter:
3096: . dm - The submesh DM
3098: Output Parameter:
3099: . subpointIS - The IS of all the points from the original mesh in this submesh, or NULL if this is not a submesh
3101: Note: This is IS is guaranteed to be sorted by the construction of the submesh
3103: Level: developer
3105: .seealso: DMPlexCreateSubmesh(), DMPlexGetSubpointMap()
3106: @*/
3107: PetscErrorCode DMPlexCreateSubpointIS(DM dm, IS *subpointIS)
3108: {
3109: MPI_Comm comm;
3110: DMLabel subpointMap;
3111: IS is;
3112: const PetscInt *opoints;
3113: PetscInt *points, *depths;
3114: PetscInt depth, depStart, depEnd, d, pStart, pEnd, p, n, off;
3115: PetscErrorCode ierr;
3120: PetscObjectGetComm((PetscObject)dm,&comm);
3121: *subpointIS = NULL;
3122: DMPlexGetSubpointMap(dm, &subpointMap);
3123: DMPlexGetDepth(dm, &depth);
3124: if (subpointMap && depth >= 0) {
3125: DMPlexGetChart(dm, &pStart, &pEnd);
3126: if (pStart) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Submeshes must start the point numbering at 0, not %d", pStart);
3127: DMGetWorkArray(dm, depth+1, PETSC_INT, &depths);
3128: depths[0] = depth;
3129: depths[1] = 0;
3130: for(d = 2; d <= depth; ++d) {depths[d] = depth+1 - d;}
3131: PetscMalloc1(pEnd, &points);
3132: for(d = 0, off = 0; d <= depth; ++d) {
3133: const PetscInt dep = depths[d];
3135: DMPlexGetDepthStratum(dm, dep, &depStart, &depEnd);
3136: DMLabelGetStratumSize(subpointMap, dep, &n);
3137: if (((d < 2) && (depth > 1)) || (d == 1)) { /* Only check vertices and cells for now since the map is broken for others */
3138: if (n != depEnd-depStart) SETERRQ3(comm, PETSC_ERR_ARG_WRONG, "The number of mapped submesh points %d at depth %d should be %d", n, dep, depEnd-depStart);
3139: } else {
3140: if (!n) {
3141: if (d == 0) {
3142: /* Missing cells */
3143: for(p = 0; p < depEnd-depStart; ++p, ++off) points[off] = -1;
3144: } else {
3145: /* Missing faces */
3146: for(p = 0; p < depEnd-depStart; ++p, ++off) points[off] = PETSC_MAX_INT;
3147: }
3148: }
3149: }
3150: if (n) {
3151: DMLabelGetStratumIS(subpointMap, dep, &is);
3152: ISGetIndices(is, &opoints);
3153: for(p = 0; p < n; ++p, ++off) points[off] = opoints[p];
3154: ISRestoreIndices(is, &opoints);
3155: ISDestroy(&is);
3156: }
3157: }
3158: DMRestoreWorkArray(dm, depth+1, PETSC_INT, &depths);
3159: if (off != pEnd) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "The number of mapped submesh points %d should be %d", off, pEnd);
3160: ISCreateGeneral(PETSC_COMM_SELF, pEnd, points, PETSC_OWN_POINTER, subpointIS);
3161: }
3162: return(0);
3163: }