1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2c58f1c22SToby Isaac #include <petsc/private/dmlabelimpl.h> /*I "petscdmlabel.h" I*/ 30c312b8eSJed Brown #include <petscsf.h> 4e6ccafaeSMatthew G Knepley 5d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCellIsHybrid_Internal(DM dm, PetscInt p, PetscBool *isHybrid) 6d71ae5a4SJacob Faibussowitsch { 7412e9a14SMatthew G. Knepley DMPolytopeType ct; 8412e9a14SMatthew G. Knepley 9412e9a14SMatthew G. Knepley PetscFunctionBegin; 109566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 11412e9a14SMatthew G. Knepley switch (ct) { 12412e9a14SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 13412e9a14SMatthew G. Knepley case DM_POLYTOPE_SEG_PRISM_TENSOR: 14412e9a14SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 15d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_QUAD_PRISM_TENSOR: 16d71ae5a4SJacob Faibussowitsch *isHybrid = PETSC_TRUE; 17d71ae5a4SJacob Faibussowitsch break; 18d71ae5a4SJacob Faibussowitsch default: 19d71ae5a4SJacob Faibussowitsch *isHybrid = PETSC_FALSE; 20d71ae5a4SJacob Faibussowitsch break; 21412e9a14SMatthew G. Knepley } 22412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 23412e9a14SMatthew G. Knepley } 24412e9a14SMatthew G. Knepley 25d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTensorPrismBounds_Internal(DM dm, PetscInt dim, PetscInt *cStart, PetscInt *cEnd) 26d71ae5a4SJacob Faibussowitsch { 27412e9a14SMatthew G. Knepley DMLabel ctLabel; 28412e9a14SMatthew G. Knepley 29412e9a14SMatthew G. Knepley PetscFunctionBegin; 30412e9a14SMatthew G. Knepley if (cStart) *cStart = -1; 31412e9a14SMatthew G. Knepley if (cEnd) *cEnd = -1; 329566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel)); 33412e9a14SMatthew G. Knepley switch (dim) { 34d71ae5a4SJacob Faibussowitsch case 1: 35d71ae5a4SJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_POINT_PRISM_TENSOR, cStart, cEnd)); 36d71ae5a4SJacob Faibussowitsch break; 37d71ae5a4SJacob Faibussowitsch case 2: 38d71ae5a4SJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_SEG_PRISM_TENSOR, cStart, cEnd)); 39d71ae5a4SJacob Faibussowitsch break; 40412e9a14SMatthew G. Knepley case 3: 419566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_TRI_PRISM_TENSOR, cStart, cEnd)); 429566063dSJacob Faibussowitsch if (*cStart < 0) PetscCall(DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_QUAD_PRISM_TENSOR, cStart, cEnd)); 43412e9a14SMatthew G. Knepley break; 44d71ae5a4SJacob Faibussowitsch default: 45d71ae5a4SJacob Faibussowitsch PetscFunctionReturn(0); 46412e9a14SMatthew G. Knepley } 47412e9a14SMatthew G. Knepley PetscFunctionReturn(0); 48412e9a14SMatthew G. Knepley } 49412e9a14SMatthew G. Knepley 50d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMarkBoundaryFaces_Internal(DM dm, PetscInt val, PetscInt cellHeight, DMLabel label) 51d71ae5a4SJacob Faibussowitsch { 5230560a7bSMatthew G. Knepley PetscInt fStart, fEnd, f; 5330560a7bSMatthew G. Knepley 5430560a7bSMatthew G. Knepley PetscFunctionBegin; 559566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight + 1, &fStart, &fEnd)); 5630560a7bSMatthew G. Knepley for (f = fStart; f < fEnd; ++f) { 5730560a7bSMatthew G. Knepley PetscInt supportSize; 5830560a7bSMatthew G. Knepley 599566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, f, &supportSize)); 60e752be1aSMatthew G. Knepley if (supportSize == 1) { 61e752be1aSMatthew G. Knepley if (val < 0) { 62e752be1aSMatthew G. Knepley PetscInt *closure = NULL; 63e752be1aSMatthew G. Knepley PetscInt clSize, cl, cval; 64e752be1aSMatthew G. Knepley 659566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, f, PETSC_TRUE, &clSize, &closure)); 66e752be1aSMatthew G. Knepley for (cl = 0; cl < clSize * 2; cl += 2) { 679566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, closure[cl], &cval)); 68e752be1aSMatthew G. Knepley if (cval < 0) continue; 699566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, f, cval)); 70e752be1aSMatthew G. Knepley break; 71e752be1aSMatthew G. Knepley } 729566063dSJacob Faibussowitsch if (cl == clSize * 2) PetscCall(DMLabelSetValue(label, f, 1)); 739566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, f, PETSC_TRUE, &clSize, &closure)); 74e752be1aSMatthew G. Knepley } else { 759566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, f, val)); 76e752be1aSMatthew G. Knepley } 77e752be1aSMatthew G. Knepley } 7830560a7bSMatthew G. Knepley } 7930560a7bSMatthew G. Knepley PetscFunctionReturn(0); 8030560a7bSMatthew G. Knepley } 8130560a7bSMatthew G. Knepley 82cd0c2139SMatthew G Knepley /*@ 83cd0c2139SMatthew G Knepley DMPlexMarkBoundaryFaces - Mark all faces on the boundary 84cd0c2139SMatthew G Knepley 85cd0c2139SMatthew G Knepley Not Collective 86cd0c2139SMatthew G Knepley 87d8d19677SJose E. Roman Input Parameters: 88e752be1aSMatthew G. Knepley + dm - The original DM 89e752be1aSMatthew G. Knepley - val - The marker value, or PETSC_DETERMINE to use some value in the closure (or 1 if none are found) 90cd0c2139SMatthew G Knepley 91cd0c2139SMatthew G Knepley Output Parameter: 92e752be1aSMatthew G. Knepley . label - The DMLabel marking boundary faces with the given value 93cd0c2139SMatthew G Knepley 94cd0c2139SMatthew G Knepley Level: developer 95cd0c2139SMatthew G Knepley 96db781477SPatrick Sanan .seealso: `DMLabelCreate()`, `DMCreateLabel()` 9709f723d9SJed Brown @*/ 98d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMarkBoundaryFaces(DM dm, PetscInt val, DMLabel label) 99d71ae5a4SJacob Faibussowitsch { 100827c4036SVaclav Hapla DMPlexInterpolatedFlag flg; 101cd0c2139SMatthew G Knepley 102cd0c2139SMatthew G Knepley PetscFunctionBegin; 103827c4036SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1049566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &flg)); 10508401ef6SPierre Jolivet PetscCheck(flg == DMPLEX_INTERPOLATED_FULL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not fully interpolated on this rank"); 1069566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces_Internal(dm, val, 0, label)); 107cd0c2139SMatthew G Knepley PetscFunctionReturn(0); 108cd0c2139SMatthew G Knepley } 109cd0c2139SMatthew G Knepley 110d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexLabelComplete_Internal(DM dm, DMLabel label, PetscBool completeCells) 111d71ae5a4SJacob Faibussowitsch { 112b0bf5782SToby Isaac IS valueIS; 113ac51f24eSSander Arens PetscSF sfPoint; 114b0bf5782SToby Isaac const PetscInt *values; 115ac51f24eSSander Arens PetscInt numValues, v, cStart, cEnd, nroots; 116b0bf5782SToby Isaac 117b0bf5782SToby Isaac PetscFunctionBegin; 1189566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 1199566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 1209566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1219566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 122b0bf5782SToby Isaac for (v = 0; v < numValues; ++v) { 123b0bf5782SToby Isaac IS pointIS; 124b0bf5782SToby Isaac const PetscInt *points; 125b0bf5782SToby Isaac PetscInt numPoints, p; 126b0bf5782SToby Isaac 1279566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, values[v], &numPoints)); 1289566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, values[v], &pointIS)); 1299566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 130b0bf5782SToby Isaac for (p = 0; p < numPoints; ++p) { 131b0bf5782SToby Isaac PetscInt q = points[p]; 132b0bf5782SToby Isaac PetscInt *closure = NULL; 133b0bf5782SToby Isaac PetscInt closureSize, c; 134b0bf5782SToby Isaac 135b0bf5782SToby Isaac if (cStart <= q && q < cEnd && !completeCells) { /* skip cells */ 136b0bf5782SToby Isaac continue; 137b0bf5782SToby Isaac } 1389566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, q, PETSC_TRUE, &closureSize, &closure)); 13948a46eb9SPierre Jolivet for (c = 0; c < closureSize * 2; c += 2) PetscCall(DMLabelSetValue(label, closure[c], values[v])); 1409566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, q, PETSC_TRUE, &closureSize, &closure)); 141b0bf5782SToby Isaac } 1429566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 1439566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 144b0bf5782SToby Isaac } 1459566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 1469566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 1479566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 1489566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL)); 149ac51f24eSSander Arens if (nroots >= 0) { 15026279d81SSanderA DMLabel lblRoots, lblLeaves; 15126279d81SSanderA IS valueIS, pointIS; 15226279d81SSanderA const PetscInt *values; 15326279d81SSanderA PetscInt numValues, v; 15426279d81SSanderA 15526279d81SSanderA /* Pull point contributions from remote leaves into local roots */ 1569566063dSJacob Faibussowitsch PetscCall(DMLabelGather(label, sfPoint, &lblLeaves)); 1579566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(lblLeaves, &valueIS)); 1589566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(valueIS, &numValues)); 1599566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 16026279d81SSanderA for (v = 0; v < numValues; ++v) { 16126279d81SSanderA const PetscInt value = values[v]; 16226279d81SSanderA 1639566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(lblLeaves, value, &pointIS)); 1649566063dSJacob Faibussowitsch PetscCall(DMLabelInsertIS(label, pointIS, value)); 1659566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 16626279d81SSanderA } 1679566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 1689566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 1699566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblLeaves)); 17026279d81SSanderA /* Push point contributions from roots into remote leaves */ 1719566063dSJacob Faibussowitsch PetscCall(DMLabelDistribute(label, sfPoint, &lblRoots)); 1729566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(lblRoots, &valueIS)); 1739566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(valueIS, &numValues)); 1749566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 17526279d81SSanderA for (v = 0; v < numValues; ++v) { 17626279d81SSanderA const PetscInt value = values[v]; 17726279d81SSanderA 1789566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(lblRoots, value, &pointIS)); 1799566063dSJacob Faibussowitsch PetscCall(DMLabelInsertIS(label, pointIS, value)); 1809566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 18126279d81SSanderA } 1829566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 1839566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 1849566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblRoots)); 18526279d81SSanderA } 186b0bf5782SToby Isaac PetscFunctionReturn(0); 187b0bf5782SToby Isaac } 188b0bf5782SToby Isaac 1892be2b188SMatthew G Knepley /*@ 1902be2b188SMatthew G Knepley DMPlexLabelComplete - Starting with a label marking points on a surface, we add the transitive closure to the surface 1912be2b188SMatthew G Knepley 1922be2b188SMatthew G Knepley Input Parameters: 1932be2b188SMatthew G Knepley + dm - The DM 1942be2b188SMatthew G Knepley - label - A DMLabel marking the surface points 1952be2b188SMatthew G Knepley 1962be2b188SMatthew G Knepley Output Parameter: 1972be2b188SMatthew G Knepley . label - A DMLabel marking all surface points in the transitive closure 1982be2b188SMatthew G Knepley 1992be2b188SMatthew G Knepley Level: developer 2002be2b188SMatthew G Knepley 201db781477SPatrick Sanan .seealso: `DMPlexLabelCohesiveComplete()` 2022be2b188SMatthew G Knepley @*/ 203d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelComplete(DM dm, DMLabel label) 204d71ae5a4SJacob Faibussowitsch { 2052be2b188SMatthew G Knepley PetscFunctionBegin; 2069566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete_Internal(dm, label, PETSC_TRUE)); 2072be2b188SMatthew G Knepley PetscFunctionReturn(0); 2082be2b188SMatthew G Knepley } 2092be2b188SMatthew G Knepley 2106cf0e42fSMatthew G. Knepley /*@ 211a6e0b375SMatthew G. Knepley DMPlexLabelAddCells - Starting with a label marking points on a surface, we add a cell for each point 2126cf0e42fSMatthew G. Knepley 2136cf0e42fSMatthew G. Knepley Input Parameters: 2146cf0e42fSMatthew G. Knepley + dm - The DM 2156cf0e42fSMatthew G. Knepley - label - A DMLabel marking the surface points 2166cf0e42fSMatthew G. Knepley 2176cf0e42fSMatthew G. Knepley Output Parameter: 2186cf0e42fSMatthew G. Knepley . label - A DMLabel incorporating cells 2196cf0e42fSMatthew G. Knepley 2206cf0e42fSMatthew G. Knepley Level: developer 2216cf0e42fSMatthew G. Knepley 2226cf0e42fSMatthew G. Knepley Note: The cells allow FEM boundary conditions to be applied using the cell geometry 2236cf0e42fSMatthew G. Knepley 224db781477SPatrick Sanan .seealso: `DMPlexLabelAddFaceCells()`, `DMPlexLabelComplete()`, `DMPlexLabelCohesiveComplete()` 2256cf0e42fSMatthew G. Knepley @*/ 226d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelAddCells(DM dm, DMLabel label) 227d71ae5a4SJacob Faibussowitsch { 2286cf0e42fSMatthew G. Knepley IS valueIS; 2296cf0e42fSMatthew G. Knepley const PetscInt *values; 230485ad865SMatthew G. Knepley PetscInt numValues, v, cStart, cEnd; 2316cf0e42fSMatthew G. Knepley 2326cf0e42fSMatthew G. Knepley PetscFunctionBegin; 2339566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 2349566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 2359566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 2369566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 2376cf0e42fSMatthew G. Knepley for (v = 0; v < numValues; ++v) { 2386cf0e42fSMatthew G. Knepley IS pointIS; 2396cf0e42fSMatthew G. Knepley const PetscInt *points; 2406cf0e42fSMatthew G. Knepley PetscInt numPoints, p; 2416cf0e42fSMatthew G. Knepley 2429566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, values[v], &numPoints)); 2439566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, values[v], &pointIS)); 2449566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 2456cf0e42fSMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 2466cf0e42fSMatthew G. Knepley PetscInt *closure = NULL; 247a6e0b375SMatthew G. Knepley PetscInt closureSize, cl; 2486cf0e42fSMatthew G. Knepley 2499566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closure)); 25022eabd52SMatthew G. Knepley for (cl = closureSize - 1; cl > 0; --cl) { 251a6e0b375SMatthew G. Knepley const PetscInt cell = closure[cl * 2]; 2529371c9d4SSatish Balay if ((cell >= cStart) && (cell < cEnd)) { 2539371c9d4SSatish Balay PetscCall(DMLabelSetValue(label, cell, values[v])); 2549371c9d4SSatish Balay break; 2559371c9d4SSatish Balay } 25622eabd52SMatthew G. Knepley } 2579566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closure)); 2586cf0e42fSMatthew G. Knepley } 2599566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 2609566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 2616cf0e42fSMatthew G. Knepley } 2629566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 2639566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 2646cf0e42fSMatthew G. Knepley PetscFunctionReturn(0); 2656cf0e42fSMatthew G. Knepley } 2666cf0e42fSMatthew G. Knepley 267f402d5e4SToby Isaac /*@ 268a6e0b375SMatthew G. Knepley DMPlexLabelAddFaceCells - Starting with a label marking faces on a surface, we add a cell for each face 269a6e0b375SMatthew G. Knepley 270a6e0b375SMatthew G. Knepley Input Parameters: 271a6e0b375SMatthew G. Knepley + dm - The DM 272a6e0b375SMatthew G. Knepley - label - A DMLabel marking the surface points 273a6e0b375SMatthew G. Knepley 274a6e0b375SMatthew G. Knepley Output Parameter: 275a6e0b375SMatthew G. Knepley . label - A DMLabel incorporating cells 276a6e0b375SMatthew G. Knepley 277a6e0b375SMatthew G. Knepley Level: developer 278a6e0b375SMatthew G. Knepley 279a6e0b375SMatthew G. Knepley Note: The cells allow FEM boundary conditions to be applied using the cell geometry 280a6e0b375SMatthew G. Knepley 281db781477SPatrick Sanan .seealso: `DMPlexLabelAddCells()`, `DMPlexLabelComplete()`, `DMPlexLabelCohesiveComplete()` 282a6e0b375SMatthew G. Knepley @*/ 283d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelAddFaceCells(DM dm, DMLabel label) 284d71ae5a4SJacob Faibussowitsch { 285a6e0b375SMatthew G. Knepley IS valueIS; 286a6e0b375SMatthew G. Knepley const PetscInt *values; 287a6e0b375SMatthew G. Knepley PetscInt numValues, v, cStart, cEnd, fStart, fEnd; 288a6e0b375SMatthew G. Knepley 289a6e0b375SMatthew G. Knepley PetscFunctionBegin; 2909566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 2919566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 2929566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 2939566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 2949566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 295a6e0b375SMatthew G. Knepley for (v = 0; v < numValues; ++v) { 296a6e0b375SMatthew G. Knepley IS pointIS; 297a6e0b375SMatthew G. Knepley const PetscInt *points; 298a6e0b375SMatthew G. Knepley PetscInt numPoints, p; 299a6e0b375SMatthew G. Knepley 3009566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, values[v], &numPoints)); 3019566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, values[v], &pointIS)); 3029566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 303a6e0b375SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 304a6e0b375SMatthew G. Knepley const PetscInt face = points[p]; 305a6e0b375SMatthew G. Knepley PetscInt *closure = NULL; 306a6e0b375SMatthew G. Knepley PetscInt closureSize, cl; 307a6e0b375SMatthew G. Knepley 308a6e0b375SMatthew G. Knepley if ((face < fStart) || (face >= fEnd)) continue; 3099566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, face, PETSC_FALSE, &closureSize, &closure)); 310a6e0b375SMatthew G. Knepley for (cl = closureSize - 1; cl > 0; --cl) { 311a6e0b375SMatthew G. Knepley const PetscInt cell = closure[cl * 2]; 3129371c9d4SSatish Balay if ((cell >= cStart) && (cell < cEnd)) { 3139371c9d4SSatish Balay PetscCall(DMLabelSetValue(label, cell, values[v])); 3149371c9d4SSatish Balay break; 3159371c9d4SSatish Balay } 316a6e0b375SMatthew G. Knepley } 3179566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, face, PETSC_FALSE, &closureSize, &closure)); 318a6e0b375SMatthew G. Knepley } 3199566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 3209566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 321a6e0b375SMatthew G. Knepley } 3229566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 3239566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 324a6e0b375SMatthew G. Knepley PetscFunctionReturn(0); 325a6e0b375SMatthew G. Knepley } 326a6e0b375SMatthew G. Knepley 327a6e0b375SMatthew G. Knepley /*@ 328f402d5e4SToby Isaac DMPlexLabelClearCells - Remove cells from a label 329f402d5e4SToby Isaac 330f402d5e4SToby Isaac Input Parameters: 331f402d5e4SToby Isaac + dm - The DM 332f402d5e4SToby Isaac - label - A DMLabel marking surface points and their adjacent cells 333f402d5e4SToby Isaac 334f402d5e4SToby Isaac Output Parameter: 335f402d5e4SToby Isaac . label - A DMLabel without cells 336f402d5e4SToby Isaac 337f402d5e4SToby Isaac Level: developer 338f402d5e4SToby Isaac 339a6e0b375SMatthew G. Knepley Note: This undoes DMPlexLabelAddCells() or DMPlexLabelAddFaceCells() 340f402d5e4SToby Isaac 341db781477SPatrick Sanan .seealso: `DMPlexLabelComplete()`, `DMPlexLabelCohesiveComplete()`, `DMPlexLabelAddCells()` 342f402d5e4SToby Isaac @*/ 343d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelClearCells(DM dm, DMLabel label) 344d71ae5a4SJacob Faibussowitsch { 345f402d5e4SToby Isaac IS valueIS; 346f402d5e4SToby Isaac const PetscInt *values; 347485ad865SMatthew G. Knepley PetscInt numValues, v, cStart, cEnd; 348f402d5e4SToby Isaac 349f402d5e4SToby Isaac PetscFunctionBegin; 3509566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 3519566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 3529566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 3539566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 354f402d5e4SToby Isaac for (v = 0; v < numValues; ++v) { 355f402d5e4SToby Isaac IS pointIS; 356f402d5e4SToby Isaac const PetscInt *points; 357f402d5e4SToby Isaac PetscInt numPoints, p; 358f402d5e4SToby Isaac 3599566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, values[v], &numPoints)); 3609566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, values[v], &pointIS)); 3619566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 362f402d5e4SToby Isaac for (p = 0; p < numPoints; ++p) { 363f402d5e4SToby Isaac PetscInt point = points[p]; 364f402d5e4SToby Isaac 36548a46eb9SPierre Jolivet if (point >= cStart && point < cEnd) PetscCall(DMLabelClearValue(label, point, values[v])); 366f402d5e4SToby Isaac } 3679566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 3689566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 369f402d5e4SToby Isaac } 3709566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 3719566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 372f402d5e4SToby Isaac PetscFunctionReturn(0); 373f402d5e4SToby Isaac } 374f402d5e4SToby Isaac 37559eef20bSToby Isaac /* take (oldEnd, added) pairs, ordered by height and convert them to (oldstart, newstart) pairs, ordered by ascending 37659eef20bSToby Isaac * index (skipping first, which is (0,0)) */ 377d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexShiftPointSetUp_Internal(PetscInt depth, PetscInt depthShift[]) 378d71ae5a4SJacob Faibussowitsch { 3792582d50cSToby Isaac PetscInt d, off = 0; 3802582d50cSToby Isaac 3812582d50cSToby Isaac PetscFunctionBegin; 38259eef20bSToby Isaac /* sort by (oldend): yes this is an O(n^2) sort, we expect depth <= 3 */ 3830974a383SToby Isaac for (d = 0; d < depth; d++) { 3842582d50cSToby Isaac PetscInt firstd = d; 3850974a383SToby Isaac PetscInt firstStart = depthShift[2 * d]; 3862582d50cSToby Isaac PetscInt e; 3872582d50cSToby Isaac 3882582d50cSToby Isaac for (e = d + 1; e <= depth; e++) { 3892582d50cSToby Isaac if (depthShift[2 * e] < firstStart) { 3902582d50cSToby Isaac firstd = e; 3912582d50cSToby Isaac firstStart = depthShift[2 * d]; 3922582d50cSToby Isaac } 3932582d50cSToby Isaac } 3942582d50cSToby Isaac if (firstd != d) { 3952582d50cSToby Isaac PetscInt swap[2]; 3962582d50cSToby Isaac 3972582d50cSToby Isaac e = firstd; 3982582d50cSToby Isaac swap[0] = depthShift[2 * d]; 3992582d50cSToby Isaac swap[1] = depthShift[2 * d + 1]; 4002582d50cSToby Isaac depthShift[2 * d] = depthShift[2 * e]; 4012582d50cSToby Isaac depthShift[2 * d + 1] = depthShift[2 * e + 1]; 4022582d50cSToby Isaac depthShift[2 * e] = swap[0]; 4032582d50cSToby Isaac depthShift[2 * e + 1] = swap[1]; 4042582d50cSToby Isaac } 4052582d50cSToby Isaac } 4062582d50cSToby Isaac /* convert (oldstart, added) to (oldstart, newstart) */ 4070974a383SToby Isaac for (d = 0; d <= depth; d++) { 4082582d50cSToby Isaac off += depthShift[2 * d + 1]; 40959eef20bSToby Isaac depthShift[2 * d + 1] = depthShift[2 * d] + off; 4102582d50cSToby Isaac } 4112582d50cSToby Isaac PetscFunctionReturn(0); 4122582d50cSToby Isaac } 4132582d50cSToby Isaac 4142582d50cSToby Isaac /* depthShift is a list of (old, new) pairs */ 415d71ae5a4SJacob Faibussowitsch static inline PetscInt DMPlexShiftPoint_Internal(PetscInt p, PetscInt depth, PetscInt depthShift[]) 416d71ae5a4SJacob Faibussowitsch { 4172582d50cSToby Isaac PetscInt d; 4182582d50cSToby Isaac PetscInt newOff = 0; 4192582d50cSToby Isaac 4202582d50cSToby Isaac for (d = 0; d <= depth; d++) { 4212582d50cSToby Isaac if (p < depthShift[2 * d]) return p + newOff; 4222582d50cSToby Isaac else newOff = depthShift[2 * d + 1] - depthShift[2 * d]; 4232582d50cSToby Isaac } 4240974a383SToby Isaac return p + newOff; 4252582d50cSToby Isaac } 4262582d50cSToby Isaac 4272582d50cSToby Isaac /* depthShift is a list of (old, new) pairs */ 428d71ae5a4SJacob Faibussowitsch static inline PetscInt DMPlexShiftPointInverse_Internal(PetscInt p, PetscInt depth, PetscInt depthShift[]) 429d71ae5a4SJacob Faibussowitsch { 4302582d50cSToby Isaac PetscInt d; 4312582d50cSToby Isaac PetscInt newOff = 0; 4322582d50cSToby Isaac 4332582d50cSToby Isaac for (d = 0; d <= depth; d++) { 4342582d50cSToby Isaac if (p < depthShift[2 * d + 1]) return p + newOff; 4352582d50cSToby Isaac else newOff = depthShift[2 * d] - depthShift[2 * d + 1]; 4362582d50cSToby Isaac } 4370974a383SToby Isaac return p + newOff; 438cd0c2139SMatthew G Knepley } 439cd0c2139SMatthew G Knepley 440d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexShiftSizes_Internal(DM dm, PetscInt depthShift[], DM dmNew) 441d71ae5a4SJacob Faibussowitsch { 442cd0c2139SMatthew G Knepley PetscInt depth = 0, d, pStart, pEnd, p; 443fa8e8ae5SToby Isaac DMLabel depthLabel; 444cd0c2139SMatthew G Knepley 445cd0c2139SMatthew G Knepley PetscFunctionBegin; 4469566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 447cd0c2139SMatthew G Knepley if (depth < 0) PetscFunctionReturn(0); 448cd0c2139SMatthew G Knepley /* Step 1: Expand chart */ 4499566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4500974a383SToby Isaac pEnd = DMPlexShiftPoint_Internal(pEnd, depth, depthShift); 4519566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dmNew, pStart, pEnd)); 4529566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dmNew, "depth")); 4539566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dmNew, &depthLabel)); 4549566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dmNew, "celltype")); 455cd0c2139SMatthew G Knepley /* Step 2: Set cone and support sizes */ 456cd0c2139SMatthew G Knepley for (d = 0; d <= depth; ++d) { 457fa8e8ae5SToby Isaac PetscInt pStartNew, pEndNew; 458fa8e8ae5SToby Isaac IS pIS; 459fa8e8ae5SToby Isaac 4609566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 461fa8e8ae5SToby Isaac pStartNew = DMPlexShiftPoint_Internal(pStart, depth, depthShift); 462fa8e8ae5SToby Isaac pEndNew = DMPlexShiftPoint_Internal(pEnd, depth, depthShift); 4639566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pEndNew - pStartNew, pStartNew, 1, &pIS)); 4649566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(depthLabel, d, pIS)); 4659566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pIS)); 466cd0c2139SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 4672582d50cSToby Isaac PetscInt newp = DMPlexShiftPoint_Internal(p, depth, depthShift); 468cd0c2139SMatthew G Knepley PetscInt size; 469412e9a14SMatthew G. Knepley DMPolytopeType ct; 470cd0c2139SMatthew G Knepley 4719566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &size)); 4729566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(dmNew, newp, size)); 4739566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &size)); 4749566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(dmNew, newp, size)); 4759566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 4769566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(dmNew, newp, ct)); 477cd0c2139SMatthew G Knepley } 478cd0c2139SMatthew G Knepley } 479cd0c2139SMatthew G Knepley PetscFunctionReturn(0); 480cd0c2139SMatthew G Knepley } 481cd0c2139SMatthew G Knepley 482d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexShiftPoints_Internal(DM dm, PetscInt depthShift[], DM dmNew) 483d71ae5a4SJacob Faibussowitsch { 4842582d50cSToby Isaac PetscInt *newpoints; 4852582d50cSToby Isaac PetscInt depth = 0, maxConeSize, maxSupportSize, maxConeSizeNew, maxSupportSizeNew, pStart, pEnd, p; 486cd0c2139SMatthew G Knepley 487cd0c2139SMatthew G Knepley PetscFunctionBegin; 4889566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 489cd0c2139SMatthew G Knepley if (depth < 0) PetscFunctionReturn(0); 4909566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 4919566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dmNew, &maxConeSizeNew, &maxSupportSizeNew)); 4929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(PetscMax(PetscMax(maxConeSize, maxSupportSize), PetscMax(maxConeSizeNew, maxSupportSizeNew)), &newpoints)); 493cd0c2139SMatthew G Knepley /* Step 5: Set cones and supports */ 4949566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 495cd0c2139SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 496cd0c2139SMatthew G Knepley const PetscInt *points = NULL, *orientations = NULL; 4972582d50cSToby Isaac PetscInt size, sizeNew, i, newp = DMPlexShiftPoint_Internal(p, depth, depthShift); 498cd0c2139SMatthew G Knepley 4999566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &size)); 5009566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &points)); 5019566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &orientations)); 502ad540459SPierre Jolivet for (i = 0; i < size; ++i) newpoints[i] = DMPlexShiftPoint_Internal(points[i], depth, depthShift); 5039566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dmNew, newp, newpoints)); 5049566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dmNew, newp, orientations)); 5059566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &size)); 5069566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmNew, newp, &sizeNew)); 5079566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &points)); 508ad540459SPierre Jolivet for (i = 0; i < size; ++i) newpoints[i] = DMPlexShiftPoint_Internal(points[i], depth, depthShift); 509dcbb62e8SMatthew G. Knepley for (i = size; i < sizeNew; ++i) newpoints[i] = 0; 5109566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupport(dmNew, newp, newpoints)); 511cd0c2139SMatthew G Knepley } 5129566063dSJacob Faibussowitsch PetscCall(PetscFree(newpoints)); 513cd0c2139SMatthew G Knepley PetscFunctionReturn(0); 514cd0c2139SMatthew G Knepley } 515cd0c2139SMatthew G Knepley 516d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexShiftCoordinates_Internal(DM dm, PetscInt depthShift[], DM dmNew) 517d71ae5a4SJacob Faibussowitsch { 518cd0c2139SMatthew G Knepley PetscSection coordSection, newCoordSection; 519cd0c2139SMatthew G Knepley Vec coordinates, newCoordinates; 520cd0c2139SMatthew G Knepley PetscScalar *coords, *newCoords; 521f2b8cce1SMatthew G. Knepley PetscInt coordSize, sStart, sEnd; 522f2b8cce1SMatthew G. Knepley PetscInt dim, depth = 0, cStart, cEnd, cStartNew, cEndNew, c, vStart, vEnd, vStartNew, vEndNew, v; 523f2b8cce1SMatthew G. Knepley PetscBool hasCells; 524cd0c2139SMatthew G Knepley 525cd0c2139SMatthew G Knepley PetscFunctionBegin; 5269566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 5279566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dmNew, dim)); 5289566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 529cd0c2139SMatthew G Knepley /* Step 8: Convert coordinates */ 5309566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 5319566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 5329566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dmNew, 0, &vStartNew, &vEndNew)); 5339566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dmNew, 0, &cStartNew, &cEndNew)); 5349566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 5359566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &newCoordSection)); 5369566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(newCoordSection, 1)); 5379566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(newCoordSection, 0, dim)); 5389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSection, &sStart, &sEnd)); 539f2b8cce1SMatthew G. Knepley hasCells = sStart == cStart ? PETSC_TRUE : PETSC_FALSE; 5409566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(newCoordSection, hasCells ? cStartNew : vStartNew, vEndNew)); 541f2b8cce1SMatthew G. Knepley if (hasCells) { 542f2b8cce1SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 543f2b8cce1SMatthew G. Knepley PetscInt cNew = DMPlexShiftPoint_Internal(c, depth, depthShift), dof; 544f2b8cce1SMatthew G. Knepley 5459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, c, &dof)); 5469566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(newCoordSection, cNew, dof)); 5479566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(newCoordSection, cNew, 0, dof)); 548f2b8cce1SMatthew G. Knepley } 549f2b8cce1SMatthew G. Knepley } 550cd0c2139SMatthew G Knepley for (v = vStartNew; v < vEndNew; ++v) { 5519566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(newCoordSection, v, dim)); 5529566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(newCoordSection, v, 0, dim)); 553cd0c2139SMatthew G Knepley } 5549566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(newCoordSection)); 5559566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateSection(dmNew, PETSC_DETERMINE, newCoordSection)); 5569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newCoordSection, &coordSize)); 5579566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &newCoordinates)); 5589566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)newCoordinates, "coordinates")); 5599566063dSJacob Faibussowitsch PetscCall(VecSetSizes(newCoordinates, coordSize, PETSC_DETERMINE)); 5609566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(newCoordinates, dim)); 5619566063dSJacob Faibussowitsch PetscCall(VecSetType(newCoordinates, VECSTANDARD)); 5629566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmNew, newCoordinates)); 5639566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 5649566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 5659566063dSJacob Faibussowitsch PetscCall(VecGetArray(newCoordinates, &newCoords)); 566f2b8cce1SMatthew G. Knepley if (hasCells) { 567f2b8cce1SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 568f2b8cce1SMatthew G. Knepley PetscInt cNew = DMPlexShiftPoint_Internal(c, depth, depthShift), dof, off, noff, d; 569f2b8cce1SMatthew G. Knepley 5709566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, c, &dof)); 5719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, c, &off)); 5729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(newCoordSection, cNew, &noff)); 573f2b8cce1SMatthew G. Knepley for (d = 0; d < dof; ++d) newCoords[noff + d] = coords[off + d]; 574f2b8cce1SMatthew G. Knepley } 575f2b8cce1SMatthew G. Knepley } 576cd0c2139SMatthew G Knepley for (v = vStart; v < vEnd; ++v) { 577cd0c2139SMatthew G Knepley PetscInt dof, off, noff, d; 578cd0c2139SMatthew G Knepley 5799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, v, &dof)); 5809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v, &off)); 5819566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(newCoordSection, DMPlexShiftPoint_Internal(v, depth, depthShift), &noff)); 582f2b8cce1SMatthew G. Knepley for (d = 0; d < dof; ++d) newCoords[noff + d] = coords[off + d]; 583cd0c2139SMatthew G Knepley } 5849566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 5859566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(newCoordinates, &newCoords)); 5869566063dSJacob Faibussowitsch PetscCall(VecDestroy(&newCoordinates)); 5879566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&newCoordSection)); 588cd0c2139SMatthew G Knepley PetscFunctionReturn(0); 589cd0c2139SMatthew G Knepley } 590cd0c2139SMatthew G Knepley 591d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexShiftSF_Single(DM dm, PetscInt depthShift[], PetscSF sf, PetscSF sfNew) 592d71ae5a4SJacob Faibussowitsch { 593cd0c2139SMatthew G Knepley const PetscSFNode *remotePoints; 594cd0c2139SMatthew G Knepley PetscSFNode *gremotePoints; 595cd0c2139SMatthew G Knepley const PetscInt *localPoints; 596cd0c2139SMatthew G Knepley PetscInt *glocalPoints, *newLocation, *newRemoteLocation; 5970e33faafSMatthew G. Knepley PetscInt numRoots, numLeaves, l, pStart, pEnd, depth = 0, totShift = 0; 598cd0c2139SMatthew G Knepley 599cd0c2139SMatthew G Knepley PetscFunctionBegin; 6009566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 6019566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 6029566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints)); 6036e21efdcSToby Isaac totShift = DMPlexShiftPoint_Internal(pEnd, depth, depthShift) - pEnd; 604cd0c2139SMatthew G Knepley if (numRoots >= 0) { 6059566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numRoots, &newLocation, pEnd - pStart, &newRemoteLocation)); 6060e33faafSMatthew G. Knepley for (l = 0; l < numRoots; ++l) newLocation[l] = DMPlexShiftPoint_Internal(l, depth, depthShift); 6079566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, newLocation, newRemoteLocation, MPI_REPLACE)); 6089566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, newLocation, newRemoteLocation, MPI_REPLACE)); 6099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeaves, &glocalPoints)); 6109566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeaves, &gremotePoints)); 611cd0c2139SMatthew G Knepley for (l = 0; l < numLeaves; ++l) { 6122582d50cSToby Isaac glocalPoints[l] = DMPlexShiftPoint_Internal(localPoints[l], depth, depthShift); 613cd0c2139SMatthew G Knepley gremotePoints[l].rank = remotePoints[l].rank; 614cd0c2139SMatthew G Knepley gremotePoints[l].index = newRemoteLocation[localPoints[l]]; 615cd0c2139SMatthew G Knepley } 6169566063dSJacob Faibussowitsch PetscCall(PetscFree2(newLocation, newRemoteLocation)); 6179566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sfNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER)); 6180e33faafSMatthew G. Knepley } 6190e33faafSMatthew G. Knepley PetscFunctionReturn(0); 6200e33faafSMatthew G. Knepley } 6210e33faafSMatthew G. Knepley 622d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexShiftSF_Internal(DM dm, PetscInt depthShift[], DM dmNew) 623d71ae5a4SJacob Faibussowitsch { 6240e33faafSMatthew G. Knepley PetscSF sfPoint, sfPointNew; 6250e33faafSMatthew G. Knepley PetscBool useNatural; 6260e33faafSMatthew G. Knepley 6270e33faafSMatthew G. Knepley PetscFunctionBegin; 6280e33faafSMatthew G. Knepley /* Step 9: Convert pointSF */ 6299566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 6309566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmNew, &sfPointNew)); 6319566063dSJacob Faibussowitsch PetscCall(DMPlexShiftSF_Single(dm, depthShift, sfPoint, sfPointNew)); 6320e33faafSMatthew G. Knepley /* Step 9b: Convert naturalSF */ 6339566063dSJacob Faibussowitsch PetscCall(DMGetUseNatural(dm, &useNatural)); 6340e33faafSMatthew G. Knepley if (useNatural) { 6350e33faafSMatthew G. Knepley PetscSF sfNat, sfNatNew; 6360e33faafSMatthew G. Knepley 6379566063dSJacob Faibussowitsch PetscCall(DMSetUseNatural(dmNew, useNatural)); 6389566063dSJacob Faibussowitsch PetscCall(DMGetNaturalSF(dm, &sfNat)); 6399566063dSJacob Faibussowitsch PetscCall(DMGetNaturalSF(dmNew, &sfNatNew)); 6409566063dSJacob Faibussowitsch PetscCall(DMPlexShiftSF_Single(dm, depthShift, sfNat, sfNatNew)); 641cd0c2139SMatthew G Knepley } 642cd0c2139SMatthew G Knepley PetscFunctionReturn(0); 643cd0c2139SMatthew G Knepley } 644cd0c2139SMatthew G Knepley 645d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexShiftLabels_Internal(DM dm, PetscInt depthShift[], DM dmNew) 646d71ae5a4SJacob Faibussowitsch { 647d56405f8SMatthew G. Knepley PetscInt depth = 0, numLabels, l; 648cd0c2139SMatthew G Knepley 649cd0c2139SMatthew G Knepley PetscFunctionBegin; 6509566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 651cd0c2139SMatthew G Knepley /* Step 10: Convert labels */ 6529566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 653cd0c2139SMatthew G Knepley for (l = 0; l < numLabels; ++l) { 654cd0c2139SMatthew G Knepley DMLabel label, newlabel; 655cd0c2139SMatthew G Knepley const char *lname; 656fa8e8ae5SToby Isaac PetscBool isDepth, isDim; 657cd0c2139SMatthew G Knepley IS valueIS; 658cd0c2139SMatthew G Knepley const PetscInt *values; 659cd0c2139SMatthew G Knepley PetscInt numValues, val; 660cd0c2139SMatthew G Knepley 6619566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &lname)); 6629566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(lname, "depth", &isDepth)); 663cd0c2139SMatthew G Knepley if (isDepth) continue; 6649566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(lname, "dim", &isDim)); 665fa8e8ae5SToby Isaac if (isDim) continue; 6669566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dmNew, lname)); 6679566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, lname, &label)); 6689566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dmNew, lname, &newlabel)); 6699566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(label, &val)); 6709566063dSJacob Faibussowitsch PetscCall(DMLabelSetDefaultValue(newlabel, val)); 6719566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 6729566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(valueIS, &numValues)); 6739566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 674cd0c2139SMatthew G Knepley for (val = 0; val < numValues; ++val) { 675cd0c2139SMatthew G Knepley IS pointIS; 676cd0c2139SMatthew G Knepley const PetscInt *points; 677cd0c2139SMatthew G Knepley PetscInt numPoints, p; 678cd0c2139SMatthew G Knepley 6799566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, values[val], &pointIS)); 6809566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &numPoints)); 6819566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 682cd0c2139SMatthew G Knepley for (p = 0; p < numPoints; ++p) { 6832582d50cSToby Isaac const PetscInt newpoint = DMPlexShiftPoint_Internal(points[p], depth, depthShift); 684cd0c2139SMatthew G Knepley 6859566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(newlabel, newpoint, values[val])); 686cd0c2139SMatthew G Knepley } 6879566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 6889566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 689cd0c2139SMatthew G Knepley } 6909566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 6919566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 692cd0c2139SMatthew G Knepley } 693d56405f8SMatthew G. Knepley PetscFunctionReturn(0); 694d56405f8SMatthew G. Knepley } 695d56405f8SMatthew G. Knepley 696d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateVTKLabel_Internal(DM dm, PetscBool createGhostLabel, DM dmNew) 697d71ae5a4SJacob Faibussowitsch { 698d56405f8SMatthew G. Knepley PetscSF sfPoint; 699d56405f8SMatthew G. Knepley DMLabel vtkLabel, ghostLabel = NULL; 700d56405f8SMatthew G. Knepley const PetscSFNode *leafRemote; 701d56405f8SMatthew G. Knepley const PetscInt *leafLocal; 702d56405f8SMatthew G. Knepley PetscInt cellHeight, cStart, cEnd, c, fStart, fEnd, f, numLeaves, l; 703d56405f8SMatthew G. Knepley PetscMPIInt rank; 704d56405f8SMatthew G. Knepley 705d56405f8SMatthew G. Knepley PetscFunctionBegin; 706cd0c2139SMatthew G Knepley /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */ 7079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 7089566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 7099566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dmNew, &cellHeight)); 7109566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 7119566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, NULL, &numLeaves, &leafLocal, &leafRemote)); 7129566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dmNew, "vtk")); 7139566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dmNew, "vtk", &vtkLabel)); 714d56405f8SMatthew G. Knepley if (createGhostLabel) { 7159566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dmNew, "ghost")); 7169566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dmNew, "ghost", &ghostLabel)); 717d56405f8SMatthew G. Knepley } 718cd0c2139SMatthew G Knepley for (l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) { 71948a46eb9SPierre Jolivet for (; c < leafLocal[l] && c < cEnd; ++c) PetscCall(DMLabelSetValue(vtkLabel, c, 1)); 720cd0c2139SMatthew G Knepley if (leafLocal[l] >= cEnd) break; 721cd0c2139SMatthew G Knepley if (leafRemote[l].rank == rank) { 7229566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(vtkLabel, c, 1)); 7231baa6e33SBarry Smith } else if (ghostLabel) PetscCall(DMLabelSetValue(ghostLabel, c, 2)); 724cd0c2139SMatthew G Knepley } 72548a46eb9SPierre Jolivet for (; c < cEnd; ++c) PetscCall(DMLabelSetValue(vtkLabel, c, 1)); 726d56405f8SMatthew G. Knepley if (ghostLabel) { 7279566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd)); 728cd0c2139SMatthew G Knepley for (f = fStart; f < fEnd; ++f) { 729cd0c2139SMatthew G Knepley PetscInt numCells; 730cd0c2139SMatthew G Knepley 7319566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmNew, f, &numCells)); 732cd0c2139SMatthew G Knepley if (numCells < 2) { 7339566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(ghostLabel, f, 1)); 734cd0c2139SMatthew G Knepley } else { 735cd0c2139SMatthew G Knepley const PetscInt *cells = NULL; 736cd0c2139SMatthew G Knepley PetscInt vA, vB; 737cd0c2139SMatthew G Knepley 7389566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmNew, f, &cells)); 7399566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(vtkLabel, cells[0], &vA)); 7409566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(vtkLabel, cells[1], &vB)); 7419566063dSJacob Faibussowitsch if (vA != 1 && vB != 1) PetscCall(DMLabelSetValue(ghostLabel, f, 1)); 742cd0c2139SMatthew G Knepley } 743cd0c2139SMatthew G Knepley } 744d56405f8SMatthew G. Knepley } 745cd0c2139SMatthew G Knepley PetscFunctionReturn(0); 746cd0c2139SMatthew G Knepley } 747cd0c2139SMatthew G Knepley 748d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexShiftTree_Internal(DM dm, PetscInt depthShift[], DM dmNew) 749d71ae5a4SJacob Faibussowitsch { 750ca04dac2SToby Isaac DM refTree; 751ca04dac2SToby Isaac PetscSection pSec; 752ca04dac2SToby Isaac PetscInt *parents, *childIDs; 753ca04dac2SToby Isaac 754ca04dac2SToby Isaac PetscFunctionBegin; 7559566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm, &refTree)); 7569566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(dmNew, refTree)); 7579566063dSJacob Faibussowitsch PetscCall(DMPlexGetTree(dm, &pSec, &parents, &childIDs, NULL, NULL)); 758ca04dac2SToby Isaac if (pSec) { 7592582d50cSToby Isaac PetscInt p, pStart, pEnd, *parentsShifted, pStartShifted, pEndShifted, depth; 760fb4630b5SToby Isaac PetscInt *childIDsShifted; 761ca04dac2SToby Isaac PetscSection pSecShifted; 762ca04dac2SToby Isaac 7639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(pSec, &pStart, &pEnd)); 7649566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 7652582d50cSToby Isaac pStartShifted = DMPlexShiftPoint_Internal(pStart, depth, depthShift); 7662582d50cSToby Isaac pEndShifted = DMPlexShiftPoint_Internal(pEnd, depth, depthShift); 7679566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEndShifted - pStartShifted, &parentsShifted, pEndShifted - pStartShifted, &childIDsShifted)); 7689566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dmNew), &pSecShifted)); 7699566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(pSecShifted, pStartShifted, pEndShifted)); 770ca04dac2SToby Isaac for (p = pStartShifted; p < pEndShifted; p++) { 771fb4630b5SToby Isaac /* start off assuming no children */ 7729566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(pSecShifted, p, 0)); 773fb4630b5SToby Isaac } 774fb4630b5SToby Isaac for (p = pStart; p < pEnd; p++) { 775fb4630b5SToby Isaac PetscInt dof; 776fb4630b5SToby Isaac PetscInt pNew = DMPlexShiftPoint_Internal(p, depth, depthShift); 777ca04dac2SToby Isaac 7789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(pSec, p, &dof)); 7799566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(pSecShifted, pNew, dof)); 780ca04dac2SToby Isaac } 7819566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(pSecShifted)); 782fb4630b5SToby Isaac for (p = pStart; p < pEnd; p++) { 783fb4630b5SToby Isaac PetscInt dof; 784fb4630b5SToby Isaac PetscInt pNew = DMPlexShiftPoint_Internal(p, depth, depthShift); 785fb4630b5SToby Isaac 7869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(pSec, p, &dof)); 787fb4630b5SToby Isaac if (dof) { 788fb4630b5SToby Isaac PetscInt off, offNew; 789fb4630b5SToby Isaac 7909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(pSec, p, &off)); 7919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(pSecShifted, pNew, &offNew)); 792fb4630b5SToby Isaac parentsShifted[offNew] = DMPlexShiftPoint_Internal(parents[off], depth, depthShift); 793fb4630b5SToby Isaac childIDsShifted[offNew] = childIDs[off]; 794fb4630b5SToby Isaac } 795fb4630b5SToby Isaac } 7969566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(dmNew, pSecShifted, parentsShifted, childIDsShifted)); 7979566063dSJacob Faibussowitsch PetscCall(PetscFree2(parentsShifted, childIDsShifted)); 7989566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&pSecShifted)); 799ca04dac2SToby Isaac } 800ca04dac2SToby Isaac PetscFunctionReturn(0); 801ca04dac2SToby Isaac } 802ca04dac2SToby Isaac 803d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexConstructGhostCells_Internal(DM dm, DMLabel label, PetscInt *numGhostCells, DM gdm) 804d71ae5a4SJacob Faibussowitsch { 805da97024aSMatthew G. Knepley PetscSF sf; 806cd0c2139SMatthew G Knepley IS valueIS; 807da97024aSMatthew G. Knepley const PetscInt *values, *leaves; 808cd0c2139SMatthew G Knepley PetscInt *depthShift; 8092582d50cSToby Isaac PetscInt d, depth = 0, nleaves, loc, Ng, numFS, fs, fStart, fEnd, ghostCell, cEnd, c; 8104fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 811cd0c2139SMatthew G Knepley 812cd0c2139SMatthew G Knepley PetscFunctionBegin; 8139566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 8149566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, &nleaves, &leaves, NULL)); 815da97024aSMatthew G. Knepley nleaves = PetscMax(0, nleaves); 8169566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 817cd0c2139SMatthew G Knepley /* Count ghost cells */ 8189566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 8199566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(valueIS, &numFS)); 8209566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 8214a6cfa73SMatthew G. Knepley Ng = 0; 822cd0c2139SMatthew G Knepley for (fs = 0; fs < numFS; ++fs) { 82346c796b9SMatthew G. Knepley IS faceIS; 82446c796b9SMatthew G. Knepley const PetscInt *faces; 82546c796b9SMatthew G. Knepley PetscInt numFaces, f, numBdFaces = 0; 826cd0c2139SMatthew G Knepley 8279566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, values[fs], &faceIS)); 8289566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(faceIS, &numFaces)); 8299566063dSJacob Faibussowitsch PetscCall(ISGetIndices(faceIS, &faces)); 83046c796b9SMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 831ca04dac2SToby Isaac PetscInt numChildren; 832ca04dac2SToby Isaac 8339566063dSJacob Faibussowitsch PetscCall(PetscFindInt(faces[f], nleaves, leaves, &loc)); 8349566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, faces[f], &numChildren, NULL)); 835ca04dac2SToby Isaac /* non-local and ancestors points don't get to register ghosts */ 836ca04dac2SToby Isaac if (loc >= 0 || numChildren) continue; 83746c796b9SMatthew G. Knepley if ((faces[f] >= fStart) && (faces[f] < fEnd)) ++numBdFaces; 83846c796b9SMatthew G. Knepley } 8394a6cfa73SMatthew G. Knepley Ng += numBdFaces; 8409566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(faceIS, &faces)); 8419566063dSJacob Faibussowitsch PetscCall(ISDestroy(&faceIS)); 842cd0c2139SMatthew G Knepley } 8439566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 8449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2 * (depth + 1), &depthShift)); 8452582d50cSToby Isaac for (d = 0; d <= depth; d++) { 84659eef20bSToby Isaac PetscInt dEnd; 8472582d50cSToby Isaac 8489566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, NULL, &dEnd)); 84959eef20bSToby Isaac depthShift[2 * d] = dEnd; 8502582d50cSToby Isaac depthShift[2 * d + 1] = 0; 8512582d50cSToby Isaac } 8522582d50cSToby Isaac if (depth >= 0) depthShift[2 * depth + 1] = Ng; 8539566063dSJacob Faibussowitsch PetscCall(DMPlexShiftPointSetUp_Internal(depth, depthShift)); 8549566063dSJacob Faibussowitsch PetscCall(DMPlexShiftSizes_Internal(dm, depthShift, gdm)); 855cd0c2139SMatthew G Knepley /* Step 3: Set cone/support sizes for new points */ 8569566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, NULL, &cEnd)); 85748a46eb9SPierre Jolivet for (c = cEnd; c < cEnd + Ng; ++c) PetscCall(DMPlexSetConeSize(gdm, c, 1)); 858cd0c2139SMatthew G Knepley for (fs = 0; fs < numFS; ++fs) { 859cd0c2139SMatthew G Knepley IS faceIS; 860cd0c2139SMatthew G Knepley const PetscInt *faces; 861cd0c2139SMatthew G Knepley PetscInt numFaces, f; 862cd0c2139SMatthew G Knepley 8639566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, values[fs], &faceIS)); 8649566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(faceIS, &numFaces)); 8659566063dSJacob Faibussowitsch PetscCall(ISGetIndices(faceIS, &faces)); 866cd0c2139SMatthew G Knepley for (f = 0; f < numFaces; ++f) { 867ca04dac2SToby Isaac PetscInt size, numChildren; 868cd0c2139SMatthew G Knepley 8699566063dSJacob Faibussowitsch PetscCall(PetscFindInt(faces[f], nleaves, leaves, &loc)); 8709566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, faces[f], &numChildren, NULL)); 871ca04dac2SToby Isaac if (loc >= 0 || numChildren) continue; 87246c796b9SMatthew G. Knepley if ((faces[f] < fStart) || (faces[f] >= fEnd)) continue; 8739566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, faces[f], &size)); 87463a3b9bcSJacob Faibussowitsch PetscCheck(size == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM has boundary face %" PetscInt_FMT " with %" PetscInt_FMT " support cells", faces[f], size); 8759566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(gdm, faces[f] + Ng, 2)); 876cd0c2139SMatthew G Knepley } 8779566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(faceIS, &faces)); 8789566063dSJacob Faibussowitsch PetscCall(ISDestroy(&faceIS)); 879cd0c2139SMatthew G Knepley } 880cd0c2139SMatthew G Knepley /* Step 4: Setup ghosted DM */ 8819566063dSJacob Faibussowitsch PetscCall(DMSetUp(gdm)); 8829566063dSJacob Faibussowitsch PetscCall(DMPlexShiftPoints_Internal(dm, depthShift, gdm)); 883cd0c2139SMatthew G Knepley /* Step 6: Set cones and supports for new points */ 884cd0c2139SMatthew G Knepley ghostCell = cEnd; 885cd0c2139SMatthew G Knepley for (fs = 0; fs < numFS; ++fs) { 886cd0c2139SMatthew G Knepley IS faceIS; 887cd0c2139SMatthew G Knepley const PetscInt *faces; 888cd0c2139SMatthew G Knepley PetscInt numFaces, f; 889cd0c2139SMatthew G Knepley 8909566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, values[fs], &faceIS)); 8919566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(faceIS, &numFaces)); 8929566063dSJacob Faibussowitsch PetscCall(ISGetIndices(faceIS, &faces)); 89346c796b9SMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 894ca04dac2SToby Isaac PetscInt newFace = faces[f] + Ng, numChildren; 895cd0c2139SMatthew G Knepley 8969566063dSJacob Faibussowitsch PetscCall(PetscFindInt(faces[f], nleaves, leaves, &loc)); 8979566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, faces[f], &numChildren, NULL)); 898ca04dac2SToby Isaac if (loc >= 0 || numChildren) continue; 89946c796b9SMatthew G. Knepley if ((faces[f] < fStart) || (faces[f] >= fEnd)) continue; 9009566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(gdm, ghostCell, &newFace)); 9019566063dSJacob Faibussowitsch PetscCall(DMPlexInsertSupport(gdm, newFace, 1, ghostCell)); 90246c796b9SMatthew G. Knepley ++ghostCell; 903cd0c2139SMatthew G Knepley } 9049566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(faceIS, &faces)); 9059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&faceIS)); 906cd0c2139SMatthew G Knepley } 9079566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 9089566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 9099566063dSJacob Faibussowitsch PetscCall(DMPlexShiftCoordinates_Internal(dm, depthShift, gdm)); 9109566063dSJacob Faibussowitsch PetscCall(DMPlexShiftSF_Internal(dm, depthShift, gdm)); 9119566063dSJacob Faibussowitsch PetscCall(DMPlexShiftLabels_Internal(dm, depthShift, gdm)); 9129566063dSJacob Faibussowitsch PetscCall(DMPlexCreateVTKLabel_Internal(dm, PETSC_TRUE, gdm)); 9139566063dSJacob Faibussowitsch PetscCall(DMPlexShiftTree_Internal(dm, depthShift, gdm)); 9149566063dSJacob Faibussowitsch PetscCall(PetscFree(depthShift)); 91548a46eb9SPierre Jolivet for (c = cEnd; c < cEnd + Ng; ++c) PetscCall(DMPlexSetCellType(gdm, c, DM_POLYTOPE_FV_GHOST)); 916966c7b3fSMatthew G. Knepley /* Step 7: Periodicity */ 9174fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, &maxCell, &Lstart, &L)); 9184fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(gdm, maxCell, Lstart, L)); 9194a6cfa73SMatthew G. Knepley if (numGhostCells) *numGhostCells = Ng; 920cd0c2139SMatthew G Knepley PetscFunctionReturn(0); 921cd0c2139SMatthew G Knepley } 922cd0c2139SMatthew G Knepley 923cd0c2139SMatthew G Knepley /*@C 924cd0c2139SMatthew G Knepley DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 925cd0c2139SMatthew G Knepley 926cd0c2139SMatthew G Knepley Collective on dm 927cd0c2139SMatthew G Knepley 928cd0c2139SMatthew G Knepley Input Parameters: 929cd0c2139SMatthew G Knepley + dm - The original DM 930cd0c2139SMatthew G Knepley - labelName - The label specifying the boundary faces, or "Face Sets" if this is NULL 931cd0c2139SMatthew G Knepley 932cd0c2139SMatthew G Knepley Output Parameters: 933cd0c2139SMatthew G Knepley + numGhostCells - The number of ghost cells added to the DM 934cd0c2139SMatthew G Knepley - dmGhosted - The new DM 935cd0c2139SMatthew G Knepley 936cd0c2139SMatthew G Knepley Note: If no label exists of that name, one will be created marking all boundary faces 937cd0c2139SMatthew G Knepley 938cd0c2139SMatthew G Knepley Level: developer 939cd0c2139SMatthew G Knepley 940db781477SPatrick Sanan .seealso: `DMCreate()` 94131266bc0SMatthew G. Knepley @*/ 942d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted) 943d71ae5a4SJacob Faibussowitsch { 944cd0c2139SMatthew G Knepley DM gdm; 945cd0c2139SMatthew G Knepley DMLabel label; 946cd0c2139SMatthew G Knepley const char *name = labelName ? labelName : "Face Sets"; 947412e9a14SMatthew G. Knepley PetscInt dim, Ng = 0; 948b0441da4SMatthew G. Knepley PetscBool useCone, useClosure; 949cd0c2139SMatthew G Knepley 950cd0c2139SMatthew G Knepley PetscFunctionBegin; 951cd0c2139SMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 952dadcf809SJacob Faibussowitsch if (numGhostCells) PetscValidIntPointer(numGhostCells, 3); 953cd0c2139SMatthew G Knepley PetscValidPointer(dmGhosted, 4); 9549566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &gdm)); 9559566063dSJacob Faibussowitsch PetscCall(DMSetType(gdm, DMPLEX)); 9569566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 9579566063dSJacob Faibussowitsch PetscCall(DMSetDimension(gdm, dim)); 9589566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 9599566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(gdm, useCone, useClosure)); 9609566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 961cd0c2139SMatthew G Knepley if (!label) { 962cd0c2139SMatthew G Knepley /* Get label for boundary faces */ 9639566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, name)); 9649566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 9659566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(dm, 1, label)); 966cd0c2139SMatthew G Knepley } 9679566063dSJacob Faibussowitsch PetscCall(DMPlexConstructGhostCells_Internal(dm, label, &Ng, gdm)); 9689566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, gdm)); 9695de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, gdm)); 970cad26855SMatthew G. Knepley gdm->setfromoptionscalled = dm->setfromoptionscalled; 971d80ece95SMatthew G. Knepley if (numGhostCells) *numGhostCells = Ng; 972cd0c2139SMatthew G Knepley *dmGhosted = gdm; 973cd0c2139SMatthew G Knepley PetscFunctionReturn(0); 974cd0c2139SMatthew G Knepley } 975cd0c2139SMatthew G Knepley 976d71ae5a4SJacob Faibussowitsch static PetscErrorCode DivideCells_Private(DM dm, DMLabel label, DMPlexPointQueue queue) 977d71ae5a4SJacob Faibussowitsch { 978accc9626SMatthew G. Knepley PetscInt dim, d, shift = 100, *pStart, *pEnd; 979accc9626SMatthew G. Knepley 980accc9626SMatthew G. Knepley PetscFunctionBegin; 981accc9626SMatthew G. Knepley PetscCall(DMGetDimension(dm, &dim)); 982accc9626SMatthew G. Knepley PetscCall(PetscMalloc2(dim, &pStart, dim, &pEnd)); 98348a46eb9SPierre Jolivet for (d = 0; d < dim; ++d) PetscCall(DMPlexGetDepthStratum(dm, d, &pStart[d], &pEnd[d])); 984accc9626SMatthew G. Knepley while (!DMPlexPointQueueEmpty(queue)) { 985accc9626SMatthew G. Knepley PetscInt cell = -1; 986accc9626SMatthew G. Knepley PetscInt *closure = NULL; 987accc9626SMatthew G. Knepley PetscInt closureSize, cl, cval; 988accc9626SMatthew G. Knepley 989accc9626SMatthew G. Knepley PetscCall(DMPlexPointQueueDequeue(queue, &cell)); 990accc9626SMatthew G. Knepley PetscCall(DMLabelGetValue(label, cell, &cval)); 991accc9626SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure)); 992accc9626SMatthew G. Knepley /* Mark points in the cell closure that touch the fault */ 993accc9626SMatthew G. Knepley for (d = 0; d < dim; ++d) { 994accc9626SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 995accc9626SMatthew G. Knepley const PetscInt clp = closure[cl]; 996accc9626SMatthew G. Knepley PetscInt clval; 997accc9626SMatthew G. Knepley 998accc9626SMatthew G. Knepley if ((clp < pStart[d]) || (clp >= pEnd[d])) continue; 999accc9626SMatthew G. Knepley PetscCall(DMLabelGetValue(label, clp, &clval)); 1000accc9626SMatthew G. Knepley if (clval == -1) { 1001accc9626SMatthew G. Knepley const PetscInt *cone; 1002accc9626SMatthew G. Knepley PetscInt coneSize, c; 1003accc9626SMatthew G. Knepley 1004accc9626SMatthew G. Knepley /* If a cone point touches the fault, then this point touches the fault */ 1005accc9626SMatthew G. Knepley PetscCall(DMPlexGetCone(dm, clp, &cone)); 1006accc9626SMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, clp, &coneSize)); 1007accc9626SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 1008accc9626SMatthew G. Knepley PetscInt cpval; 1009accc9626SMatthew G. Knepley 1010accc9626SMatthew G. Knepley PetscCall(DMLabelGetValue(label, cone[c], &cpval)); 1011accc9626SMatthew G. Knepley if (cpval != -1) { 1012accc9626SMatthew G. Knepley PetscInt dep; 1013accc9626SMatthew G. Knepley 1014accc9626SMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, clp, &dep)); 1015accc9626SMatthew G. Knepley clval = cval < 0 ? -(shift + dep) : shift + dep; 1016accc9626SMatthew G. Knepley PetscCall(DMLabelSetValue(label, clp, clval)); 1017accc9626SMatthew G. Knepley break; 1018accc9626SMatthew G. Knepley } 1019accc9626SMatthew G. Knepley } 1020accc9626SMatthew G. Knepley } 1021accc9626SMatthew G. Knepley /* Mark neighbor cells through marked faces (these cells must also touch the fault) */ 1022accc9626SMatthew G. Knepley if (d == dim - 1 && clval != -1) { 1023accc9626SMatthew G. Knepley const PetscInt *support; 1024accc9626SMatthew G. Knepley PetscInt supportSize, s, nval; 1025accc9626SMatthew G. Knepley 1026accc9626SMatthew G. Knepley PetscCall(DMPlexGetSupport(dm, clp, &support)); 1027accc9626SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, clp, &supportSize)); 1028accc9626SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 1029accc9626SMatthew G. Knepley PetscCall(DMLabelGetValue(label, support[s], &nval)); 1030accc9626SMatthew G. Knepley if (nval == -1) { 1031accc9626SMatthew G. Knepley PetscCall(DMLabelSetValue(label, support[s], clval < 0 ? clval - 1 : clval + 1)); 1032accc9626SMatthew G. Knepley PetscCall(DMPlexPointQueueEnqueue(queue, support[s])); 1033accc9626SMatthew G. Knepley } 1034accc9626SMatthew G. Knepley } 1035accc9626SMatthew G. Knepley } 1036accc9626SMatthew G. Knepley } 1037accc9626SMatthew G. Knepley } 1038accc9626SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure)); 1039accc9626SMatthew G. Knepley } 1040accc9626SMatthew G. Knepley PetscCall(PetscFree2(pStart, pEnd)); 1041accc9626SMatthew G. Knepley PetscFunctionReturn(0); 1042accc9626SMatthew G. Knepley } 1043accc9626SMatthew G. Knepley 1044accc9626SMatthew G. Knepley typedef struct { 1045accc9626SMatthew G. Knepley DM dm; 1046accc9626SMatthew G. Knepley DMPlexPointQueue queue; 1047accc9626SMatthew G. Knepley } PointDivision; 1048accc9626SMatthew G. Knepley 1049d71ae5a4SJacob Faibussowitsch static PetscErrorCode divideCell(DMLabel label, PetscInt p, PetscInt val, void *ctx) 1050d71ae5a4SJacob Faibussowitsch { 1051accc9626SMatthew G. Knepley PointDivision *div = (PointDivision *)ctx; 1052accc9626SMatthew G. Knepley PetscInt cval = val < 0 ? val - 1 : val + 1; 1053accc9626SMatthew G. Knepley const PetscInt *support; 1054accc9626SMatthew G. Knepley PetscInt supportSize, s; 1055accc9626SMatthew G. Knepley 1056accc9626SMatthew G. Knepley PetscFunctionBegin; 1057accc9626SMatthew G. Knepley PetscCall(DMPlexGetSupport(div->dm, p, &support)); 1058accc9626SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(div->dm, p, &supportSize)); 1059accc9626SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 1060accc9626SMatthew G. Knepley PetscCall(DMLabelSetValue(label, support[s], cval)); 1061accc9626SMatthew G. Knepley PetscCall(DMPlexPointQueueEnqueue(div->queue, support[s])); 1062accc9626SMatthew G. Knepley } 1063accc9626SMatthew G. Knepley PetscFunctionReturn(0); 1064accc9626SMatthew G. Knepley } 1065accc9626SMatthew G. Knepley 1066accc9626SMatthew G. Knepley /* Mark cells by label propagation */ 1067d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexLabelFaultHalo(DM dm, DMLabel faultLabel) 1068d71ae5a4SJacob Faibussowitsch { 1069accc9626SMatthew G. Knepley DMPlexPointQueue queue = NULL; 1070accc9626SMatthew G. Knepley PointDivision div; 1071accc9626SMatthew G. Knepley PetscSF pointSF; 1072accc9626SMatthew G. Knepley IS pointIS; 1073accc9626SMatthew G. Knepley const PetscInt *points; 1074accc9626SMatthew G. Knepley PetscBool empty; 1075accc9626SMatthew G. Knepley PetscInt dim, shift = 100, n, i; 1076accc9626SMatthew G. Knepley 1077accc9626SMatthew G. Knepley PetscFunctionBegin; 1078accc9626SMatthew G. Knepley PetscCall(DMGetDimension(dm, &dim)); 1079accc9626SMatthew G. Knepley PetscCall(DMPlexPointQueueCreate(1024, &queue)); 1080accc9626SMatthew G. Knepley div.dm = dm; 1081accc9626SMatthew G. Knepley div.queue = queue; 1082accc9626SMatthew G. Knepley /* Enqueue cells on fault */ 1083accc9626SMatthew G. Knepley PetscCall(DMLabelGetStratumIS(faultLabel, shift + dim, &pointIS)); 1084accc9626SMatthew G. Knepley if (pointIS) { 1085accc9626SMatthew G. Knepley PetscCall(ISGetLocalSize(pointIS, &n)); 1086accc9626SMatthew G. Knepley PetscCall(ISGetIndices(pointIS, &points)); 108748a46eb9SPierre Jolivet for (i = 0; i < n; ++i) PetscCall(DMPlexPointQueueEnqueue(queue, points[i])); 1088accc9626SMatthew G. Knepley PetscCall(ISRestoreIndices(pointIS, &points)); 1089accc9626SMatthew G. Knepley PetscCall(ISDestroy(&pointIS)); 1090accc9626SMatthew G. Knepley } 1091accc9626SMatthew G. Knepley PetscCall(DMLabelGetStratumIS(faultLabel, -(shift + dim), &pointIS)); 1092accc9626SMatthew G. Knepley if (pointIS) { 1093accc9626SMatthew G. Knepley PetscCall(ISGetLocalSize(pointIS, &n)); 1094accc9626SMatthew G. Knepley PetscCall(ISGetIndices(pointIS, &points)); 109548a46eb9SPierre Jolivet for (i = 0; i < n; ++i) PetscCall(DMPlexPointQueueEnqueue(queue, points[i])); 1096accc9626SMatthew G. Knepley PetscCall(ISRestoreIndices(pointIS, &points)); 1097accc9626SMatthew G. Knepley PetscCall(ISDestroy(&pointIS)); 1098accc9626SMatthew G. Knepley } 1099accc9626SMatthew G. Knepley 1100accc9626SMatthew G. Knepley PetscCall(DMGetPointSF(dm, &pointSF)); 1101accc9626SMatthew G. Knepley PetscCall(DMLabelPropagateBegin(faultLabel, pointSF)); 1102accc9626SMatthew G. Knepley /* While edge queue is not empty: */ 1103accc9626SMatthew G. Knepley PetscCall(DMPlexPointQueueEmptyCollective((PetscObject)dm, queue, &empty)); 1104accc9626SMatthew G. Knepley while (!empty) { 1105accc9626SMatthew G. Knepley PetscCall(DivideCells_Private(dm, faultLabel, queue)); 1106accc9626SMatthew G. Knepley PetscCall(DMLabelPropagatePush(faultLabel, pointSF, divideCell, &div)); 1107accc9626SMatthew G. Knepley PetscCall(DMPlexPointQueueEmptyCollective((PetscObject)dm, queue, &empty)); 1108accc9626SMatthew G. Knepley } 1109accc9626SMatthew G. Knepley PetscCall(DMLabelPropagateEnd(faultLabel, pointSF)); 1110accc9626SMatthew G. Knepley PetscCall(DMPlexPointQueueDestroy(&queue)); 1111accc9626SMatthew G. Knepley PetscFunctionReturn(0); 1112accc9626SMatthew G. Knepley } 1113accc9626SMatthew G. Knepley 1114607ab7a9SMatthew G. Knepley /* 1115faedd622SMatthew G. Knepley We are adding three kinds of points here: 1116607ab7a9SMatthew G. Knepley Replicated: Copies of points which exist in the mesh, such as vertices identified across a fault 1117faedd622SMatthew G. Knepley Non-replicated: Points which exist on the fault, but are not replicated 1118b6dfa339SMatthew G. Knepley Ghost: These are shared fault faces which are not owned by this process. These do not produce hybrid cells and do not replicate 1119607ab7a9SMatthew G. Knepley Hybrid: Entirely new points, such as cohesive cells 1120a6ae58d1SMatthew G. Knepley 1121a6ae58d1SMatthew G. Knepley When creating subsequent cohesive cells, we shift the old hybrid cells to the end of the numbering at 1122a6ae58d1SMatthew G. Knepley each depth so that the new split/hybrid points can be inserted as a block. 1123607ab7a9SMatthew G. Knepley */ 1124d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexConstructCohesiveCells_Internal(DM dm, DMLabel label, DMLabel splitLabel, DM sdm) 1125d71ae5a4SJacob Faibussowitsch { 1126cd0c2139SMatthew G Knepley MPI_Comm comm; 1127607ab7a9SMatthew G. Knepley IS valueIS; 1128607ab7a9SMatthew G. Knepley PetscInt numSP = 0; /* The number of depths for which we have replicated points */ 1129607ab7a9SMatthew G. Knepley const PetscInt *values; /* List of depths for which we have replicated points */ 113018c5995bSMatthew G. Knepley IS *splitIS; 113118c5995bSMatthew G. Knepley IS *unsplitIS; 1132b6dfa339SMatthew G. Knepley IS ghostIS; 1133607ab7a9SMatthew G. Knepley PetscInt *numSplitPoints; /* The number of replicated points at each depth */ 113418c5995bSMatthew G. Knepley PetscInt *numUnsplitPoints; /* The number of non-replicated points at each depth which still give rise to hybrid points */ 113536dbac82SMatthew G. Knepley PetscInt *numHybridPoints; /* The number of new hybrid points at each depth */ 113636dbac82SMatthew G. Knepley PetscInt *numHybridPointsOld; /* The number of existing hybrid points at each depth */ 1137b6dfa339SMatthew G. Knepley PetscInt numGhostPoints; /* The number of unowned, shared fault faces */ 1138607ab7a9SMatthew G. Knepley const PetscInt **splitPoints; /* Replicated points for each depth */ 113918c5995bSMatthew G. Knepley const PetscInt **unsplitPoints; /* Non-replicated points for each depth */ 1140b6dfa339SMatthew G. Knepley const PetscInt *ghostPoints; /* Ghost fault faces */ 1141cd0c2139SMatthew G Knepley PetscSection coordSection; 1142cd0c2139SMatthew G Knepley Vec coordinates; 1143cd0c2139SMatthew G Knepley PetscScalar *coords; 1144a6ae58d1SMatthew G. Knepley PetscInt *depthMax; /* The first hybrid point at each depth in the original mesh */ 1145a6ae58d1SMatthew G. Knepley PetscInt *depthEnd; /* The point limit at each depth in the original mesh */ 1146607ab7a9SMatthew G. Knepley PetscInt *depthShift; /* Number of replicated+hybrid points at each depth */ 1147607ab7a9SMatthew G. Knepley PetscInt *pMaxNew; /* The first replicated point at each depth in the new mesh, hybrids come after this */ 1148607ab7a9SMatthew G. Knepley PetscInt *coneNew, *coneONew, *supportNew; 114918c5995bSMatthew G. Knepley PetscInt shift = 100, shift2 = 200, depth = 0, dep, dim, d, sp, maxConeSize, maxSupportSize, maxConeSizeNew, maxSupportSizeNew, numLabels, vStart, vEnd, pEnd, p, v; 1150cd0c2139SMatthew G Knepley 1151cd0c2139SMatthew G Knepley PetscFunctionBegin; 11529566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 11539566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 11549566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 11559566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 1156412e9a14SMatthew G. Knepley /* We do not want this label automatically computed, instead we compute it here */ 11579566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(sdm, "celltype")); 1158cd0c2139SMatthew G Knepley /* Count split points and add cohesive cells */ 11599566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 11609566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(depth + 1, &depthMax, depth + 1, &depthEnd, 2 * (depth + 1), &depthShift, depth + 1, &pMaxNew, depth + 1, &numHybridPointsOld)); 11619566063dSJacob Faibussowitsch PetscCall(PetscMalloc7(depth + 1, &splitIS, depth + 1, &unsplitIS, depth + 1, &numSplitPoints, depth + 1, &numUnsplitPoints, depth + 1, &numHybridPoints, depth + 1, &splitPoints, depth + 1, &unsplitPoints)); 1162607ab7a9SMatthew G. Knepley for (d = 0; d <= depth; ++d) { 11639566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, NULL, &pMaxNew[d])); 11649566063dSJacob Faibussowitsch PetscCall(DMPlexGetTensorPrismBounds_Internal(dm, d, &depthMax[d], NULL)); 1165a6ae58d1SMatthew G. Knepley depthEnd[d] = pMaxNew[d]; 1166a6ae58d1SMatthew G. Knepley depthMax[d] = depthMax[d] < 0 ? depthEnd[d] : depthMax[d]; 1167607ab7a9SMatthew G. Knepley numSplitPoints[d] = 0; 116818c5995bSMatthew G. Knepley numUnsplitPoints[d] = 0; 1169607ab7a9SMatthew G. Knepley numHybridPoints[d] = 0; 1170a6ae58d1SMatthew G. Knepley numHybridPointsOld[d] = depthMax[d] < 0 ? 0 : depthEnd[d] - depthMax[d]; 1171607ab7a9SMatthew G. Knepley splitPoints[d] = NULL; 117218c5995bSMatthew G. Knepley unsplitPoints[d] = NULL; 117318c5995bSMatthew G. Knepley splitIS[d] = NULL; 117418c5995bSMatthew G. Knepley unsplitIS[d] = NULL; 117559eef20bSToby Isaac /* we are shifting the existing hybrid points with the stratum behind them, so 117659eef20bSToby Isaac * the split comes at the end of the normal points, i.e., at depthMax[d] */ 117759eef20bSToby Isaac depthShift[2 * d] = depthMax[d]; 117859eef20bSToby Isaac depthShift[2 * d + 1] = 0; 1179607ab7a9SMatthew G. Knepley } 1180b6dfa339SMatthew G. Knepley numGhostPoints = 0; 1181b6dfa339SMatthew G. Knepley ghostPoints = NULL; 1182cd0c2139SMatthew G Knepley if (label) { 11839566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 11849566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(valueIS, &numSP)); 11859566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 1186cd0c2139SMatthew G Knepley } 1187cd0c2139SMatthew G Knepley for (sp = 0; sp < numSP; ++sp) { 1188cd0c2139SMatthew G Knepley const PetscInt dep = values[sp]; 1189cd0c2139SMatthew G Knepley 1190cd0c2139SMatthew G Knepley if ((dep < 0) || (dep > depth)) continue; 11919566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, dep, &splitIS[dep])); 119218c5995bSMatthew G. Knepley if (splitIS[dep]) { 11939566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(splitIS[dep], &numSplitPoints[dep])); 11949566063dSJacob Faibussowitsch PetscCall(ISGetIndices(splitIS[dep], &splitPoints[dep])); 119518c5995bSMatthew G. Knepley } 11969566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, shift2 + dep, &unsplitIS[dep])); 119718c5995bSMatthew G. Knepley if (unsplitIS[dep]) { 11989566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(unsplitIS[dep], &numUnsplitPoints[dep])); 11999566063dSJacob Faibussowitsch PetscCall(ISGetIndices(unsplitIS[dep], &unsplitPoints[dep])); 1200cd0c2139SMatthew G Knepley } 1201cd0c2139SMatthew G Knepley } 1202b6dfa339SMatthew G. Knepley PetscCall(DMLabelGetStratumIS(label, shift2 + dim - 1, &ghostIS)); 1203b6dfa339SMatthew G. Knepley if (ghostIS) { 1204b6dfa339SMatthew G. Knepley PetscCall(ISGetLocalSize(ghostIS, &numGhostPoints)); 1205b6dfa339SMatthew G. Knepley PetscCall(ISGetIndices(ghostIS, &ghostPoints)); 1206b6dfa339SMatthew G. Knepley } 1207607ab7a9SMatthew G. Knepley /* Calculate number of hybrid points */ 120818c5995bSMatthew G. Knepley 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 */ 12092582d50cSToby Isaac for (d = 0; d <= depth; ++d) depthShift[2 * d + 1] = numSplitPoints[d] + numHybridPoints[d]; 12109566063dSJacob Faibussowitsch PetscCall(DMPlexShiftPointSetUp_Internal(depth, depthShift)); 121159eef20bSToby Isaac /* the end of the points in this stratum that come before the new points: 121259eef20bSToby Isaac * shifting pMaxNew[d] gets the new start of the next stratum, then count back the old hybrid points and the newly 121359eef20bSToby Isaac * added points */ 12142582d50cSToby Isaac for (d = 0; d <= depth; ++d) pMaxNew[d] = DMPlexShiftPoint_Internal(pMaxNew[d], depth, depthShift) - (numHybridPointsOld[d] + numSplitPoints[d] + numHybridPoints[d]); 12159566063dSJacob Faibussowitsch PetscCall(DMPlexShiftSizes_Internal(dm, depthShift, sdm)); 1216cd0c2139SMatthew G Knepley /* Step 3: Set cone/support sizes for new points */ 1217cd0c2139SMatthew G Knepley for (dep = 0; dep <= depth; ++dep) { 1218cd0c2139SMatthew G Knepley for (p = 0; p < numSplitPoints[dep]; ++p) { 1219cd0c2139SMatthew G Knepley const PetscInt oldp = splitPoints[dep][p]; 12202582d50cSToby Isaac const PetscInt newp = DMPlexShiftPoint_Internal(oldp, depth, depthShift) /*oldp + depthOffset[dep]*/; 12214c367dbcSMatthew G. Knepley const PetscInt splitp = p + pMaxNew[dep]; 1222cd0c2139SMatthew G Knepley const PetscInt *support; 1223394c2f0fSMatthew G. Knepley DMPolytopeType ct; 12244c367dbcSMatthew G. Knepley PetscInt coneSize, supportSize, qf, qn, qp, e; 1225cd0c2139SMatthew G Knepley 12269566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, oldp, &coneSize)); 12279566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(sdm, splitp, coneSize)); 12289566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, oldp, &supportSize)); 12299566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(sdm, splitp, supportSize)); 12309566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, oldp, &ct)); 12319566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(sdm, splitp, ct)); 1232cd0c2139SMatthew G Knepley if (dep == depth - 1) { 12334c367dbcSMatthew G. Knepley const PetscInt hybcell = p + pMaxNew[dep + 1] + numSplitPoints[dep + 1]; 12344c367dbcSMatthew G. Knepley 1235cd0c2139SMatthew G Knepley /* Add cohesive cells, they are prisms */ 12369566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(sdm, hybcell, 2 + coneSize)); 1237412e9a14SMatthew G. Knepley switch (coneSize) { 1238d71ae5a4SJacob Faibussowitsch case 2: 1239d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexSetCellType(sdm, hybcell, DM_POLYTOPE_SEG_PRISM_TENSOR)); 1240d71ae5a4SJacob Faibussowitsch break; 1241d71ae5a4SJacob Faibussowitsch case 3: 1242d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexSetCellType(sdm, hybcell, DM_POLYTOPE_TRI_PRISM_TENSOR)); 1243d71ae5a4SJacob Faibussowitsch break; 1244d71ae5a4SJacob Faibussowitsch case 4: 1245d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexSetCellType(sdm, hybcell, DM_POLYTOPE_QUAD_PRISM_TENSOR)); 1246d71ae5a4SJacob Faibussowitsch break; 1247412e9a14SMatthew G. Knepley } 1248b6dfa339SMatthew G. Knepley /* Shared fault faces with only one support cell now have two with the cohesive cell */ 1249b6dfa339SMatthew G. Knepley /* TODO Check thaat oldp has rootdegree == 1 */ 1250b6dfa339SMatthew G. Knepley if (supportSize == 1) { 1251b6dfa339SMatthew G. Knepley const PetscInt *support; 1252b6dfa339SMatthew G. Knepley PetscInt val; 1253b6dfa339SMatthew G. Knepley 1254b6dfa339SMatthew G. Knepley PetscCall(DMPlexGetSupport(dm, oldp, &support)); 1255b6dfa339SMatthew G. Knepley PetscCall(DMLabelGetValue(label, support[0], &val)); 1256b6dfa339SMatthew G. Knepley if (val < 0) PetscCall(DMPlexSetSupportSize(sdm, splitp, 2)); 1257b6dfa339SMatthew G. Knepley else PetscCall(DMPlexSetSupportSize(sdm, newp, 2)); 1258b6dfa339SMatthew G. Knepley } 1259cd0c2139SMatthew G Knepley } else if (dep == 0) { 12604c367dbcSMatthew G. Knepley const PetscInt hybedge = p + pMaxNew[dep + 1] + numSplitPoints[dep + 1]; 1261cd0c2139SMatthew G Knepley 12629566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, oldp, &support)); 12634c367dbcSMatthew G. Knepley for (e = 0, qn = 0, qp = 0, qf = 0; e < supportSize; ++e) { 1264cd0c2139SMatthew G Knepley PetscInt val; 1265cd0c2139SMatthew G Knepley 12669566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[e], &val)); 12674c367dbcSMatthew G. Knepley if (val == 1) ++qf; 12684c367dbcSMatthew G. Knepley if ((val == 1) || (val == (shift + 1))) ++qn; 12694c367dbcSMatthew G. Knepley if ((val == 1) || (val == -(shift + 1))) ++qp; 1270cd0c2139SMatthew G Knepley } 12714c367dbcSMatthew G. Knepley /* Split old vertex: Edges into original vertex and new cohesive edge */ 12729566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(sdm, newp, qn + 1)); 12734c367dbcSMatthew G. Knepley /* Split new vertex: Edges into split vertex and new cohesive edge */ 12749566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(sdm, splitp, qp + 1)); 12754c367dbcSMatthew G. Knepley /* Add hybrid edge */ 12769566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(sdm, hybedge, 2)); 12779566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(sdm, hybedge, qf)); 12789566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(sdm, hybedge, DM_POLYTOPE_POINT_PRISM_TENSOR)); 1279cd0c2139SMatthew G Knepley } else if (dep == dim - 2) { 12804c367dbcSMatthew G. Knepley const PetscInt hybface = p + pMaxNew[dep + 1] + numSplitPoints[dep + 1]; 12814c367dbcSMatthew G. Knepley 12829566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, oldp, &support)); 12834c367dbcSMatthew G. Knepley for (e = 0, qn = 0, qp = 0, qf = 0; e < supportSize; ++e) { 1284cd0c2139SMatthew G Knepley PetscInt val; 1285cd0c2139SMatthew G Knepley 12869566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[e], &val)); 12874c367dbcSMatthew G. Knepley if (val == dim - 1) ++qf; 12884c367dbcSMatthew G. Knepley if ((val == dim - 1) || (val == (shift + dim - 1))) ++qn; 12894c367dbcSMatthew G. Knepley if ((val == dim - 1) || (val == -(shift + dim - 1))) ++qp; 1290cd0c2139SMatthew G Knepley } 12914c367dbcSMatthew G. Knepley /* Split old edge: Faces into original edge and cohesive face (positive side?) */ 12929566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(sdm, newp, qn + 1)); 12934c367dbcSMatthew G. Knepley /* Split new edge: Faces into split edge and cohesive face (negative side?) */ 12949566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(sdm, splitp, qp + 1)); 12954c367dbcSMatthew G. Knepley /* Add hybrid face */ 12969566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(sdm, hybface, 4)); 12979566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(sdm, hybface, qf)); 12989566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(sdm, hybface, DM_POLYTOPE_SEG_PRISM_TENSOR)); 1299cd0c2139SMatthew G Knepley } 1300cd0c2139SMatthew G Knepley } 1301cd0c2139SMatthew G Knepley } 130218c5995bSMatthew G. Knepley for (dep = 0; dep <= depth; ++dep) { 130318c5995bSMatthew G. Knepley for (p = 0; p < numUnsplitPoints[dep]; ++p) { 130418c5995bSMatthew G. Knepley const PetscInt oldp = unsplitPoints[dep][p]; 13052582d50cSToby Isaac const PetscInt newp = DMPlexShiftPoint_Internal(oldp, depth, depthShift) /*oldp + depthOffset[dep]*/; 130618c5995bSMatthew G. Knepley const PetscInt *support; 1307da1dd7e4SMatthew G. Knepley PetscInt coneSize, supportSize, qf, e, s; 130818c5995bSMatthew G. Knepley 13099566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, oldp, &coneSize)); 13109566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, oldp, &supportSize)); 13119566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, oldp, &support)); 131218c5995bSMatthew G. Knepley if (dep == 0) { 131318c5995bSMatthew G. Knepley const PetscInt hybedge = p + pMaxNew[dep + 1] + numSplitPoints[dep + 1] + numSplitPoints[dep]; 131418c5995bSMatthew G. Knepley 131539254ff6SMatthew G. Knepley /* Unsplit vertex: Edges into original vertex, split edges, and new cohesive edge twice */ 131639254ff6SMatthew G. Knepley for (s = 0, qf = 0; s < supportSize; ++s, ++qf) { 13179566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[s], numSplitPoints[dep + 1], splitPoints[dep + 1], &e)); 131839254ff6SMatthew G. Knepley if (e >= 0) ++qf; 131939254ff6SMatthew G. Knepley } 13209566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(sdm, newp, qf + 2)); 132118c5995bSMatthew G. Knepley /* Add hybrid edge */ 13229566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(sdm, hybedge, 2)); 1323e1757548SMatthew G. Knepley for (e = 0, qf = 0; e < supportSize; ++e) { 1324e1757548SMatthew G. Knepley PetscInt val; 1325e1757548SMatthew G. Knepley 13269566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[e], &val)); 1327e1757548SMatthew G. Knepley /* Split and unsplit edges produce hybrid faces */ 1328da1dd7e4SMatthew G. Knepley if (val == 1) ++qf; 1329da1dd7e4SMatthew G. Knepley if (val == (shift2 + 1)) ++qf; 1330e1757548SMatthew G. Knepley } 13319566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(sdm, hybedge, qf)); 13329566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(sdm, hybedge, DM_POLYTOPE_POINT_PRISM_TENSOR)); 133318c5995bSMatthew G. Knepley } else if (dep == dim - 2) { 133418c5995bSMatthew G. Knepley const PetscInt hybface = p + pMaxNew[dep + 1] + numSplitPoints[dep + 1] + numSplitPoints[dep]; 1335cd0c2139SMatthew G Knepley PetscInt val; 1336cd0c2139SMatthew G Knepley 1337da1dd7e4SMatthew G. Knepley for (e = 0, qf = 0; e < supportSize; ++e) { 13389566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[e], &val)); 1339da1dd7e4SMatthew G. Knepley if (val == dim - 1) qf += 2; 1340da1dd7e4SMatthew G. Knepley else ++qf; 1341cd0c2139SMatthew G Knepley } 134218c5995bSMatthew G. Knepley /* Unsplit edge: Faces into original edge, split face, and cohesive face twice */ 13439566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(sdm, newp, qf + 2)); 134418c5995bSMatthew G. Knepley /* Add hybrid face */ 1345da1dd7e4SMatthew G. Knepley for (e = 0, qf = 0; e < supportSize; ++e) { 13469566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[e], &val)); 1347da1dd7e4SMatthew G. Knepley if (val == dim - 1) ++qf; 1348da1dd7e4SMatthew G. Knepley } 13499566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(sdm, hybface, 4)); 13509566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(sdm, hybface, qf)); 13519566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(sdm, hybface, DM_POLYTOPE_SEG_PRISM_TENSOR)); 1352cd0c2139SMatthew G Knepley } 1353cd0c2139SMatthew G Knepley } 1354cd0c2139SMatthew G Knepley } 1355cd0c2139SMatthew G Knepley /* Step 4: Setup split DM */ 13569566063dSJacob Faibussowitsch PetscCall(DMSetUp(sdm)); 13579566063dSJacob Faibussowitsch PetscCall(DMPlexShiftPoints_Internal(dm, depthShift, sdm)); 13589566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(sdm, &maxConeSizeNew, &maxSupportSizeNew)); 13599566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(PetscMax(maxConeSize, maxConeSizeNew) * 3, &coneNew, PetscMax(maxConeSize, maxConeSizeNew) * 3, &coneONew, PetscMax(maxSupportSize, maxSupportSizeNew), &supportNew)); 1360cd0c2139SMatthew G Knepley /* Step 6: Set cones and supports for new points */ 1361cd0c2139SMatthew G Knepley for (dep = 0; dep <= depth; ++dep) { 1362cd0c2139SMatthew G Knepley for (p = 0; p < numSplitPoints[dep]; ++p) { 1363cd0c2139SMatthew G Knepley const PetscInt oldp = splitPoints[dep][p]; 13642582d50cSToby Isaac const PetscInt newp = DMPlexShiftPoint_Internal(oldp, depth, depthShift) /*oldp + depthOffset[dep]*/; 13654c367dbcSMatthew G. Knepley const PetscInt splitp = p + pMaxNew[dep]; 1366cd0c2139SMatthew G Knepley const PetscInt *cone, *support, *ornt; 1367b5a892a1SMatthew G. Knepley DMPolytopeType ct; 13684c367dbcSMatthew G. Knepley PetscInt coneSize, supportSize, q, qf, qn, qp, v, e, s; 1369cd0c2139SMatthew G Knepley 13709566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, oldp, &ct)); 13719566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, oldp, &coneSize)); 13729566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, oldp, &cone)); 13739566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, oldp, &ornt)); 13749566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, oldp, &supportSize)); 13759566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, oldp, &support)); 1376cd0c2139SMatthew G Knepley if (dep == depth - 1) { 137796a07cd0SMatthew G. Knepley PetscBool hasUnsplit = PETSC_FALSE; 13784c367dbcSMatthew G. Knepley const PetscInt hybcell = p + pMaxNew[dep + 1] + numSplitPoints[dep + 1]; 1379cd0c2139SMatthew G Knepley const PetscInt *supportF; 1380cd0c2139SMatthew G Knepley 1381b6dfa339SMatthew G. Knepley coneONew[0] = coneONew[1] = -1000; 1382cd0c2139SMatthew G Knepley /* Split face: copy in old face to new face to start */ 13839566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(sdm, newp, &supportF)); 13849566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupport(sdm, splitp, supportF)); 1385cd0c2139SMatthew G Knepley /* Split old face: old vertices/edges in cone so no change */ 1386cd0c2139SMatthew G Knepley /* Split new face: new vertices/edges in cone */ 1387cd0c2139SMatthew G Knepley for (q = 0; q < coneSize; ++q) { 13889566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[q], numSplitPoints[dep - 1], splitPoints[dep - 1], &v)); 138918c5995bSMatthew G. Knepley if (v < 0) { 13909566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[q], numUnsplitPoints[dep - 1], unsplitPoints[dep - 1], &v)); 139163a3b9bcSJacob Faibussowitsch PetscCheck(v >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not locate point %" PetscInt_FMT " in split or unsplit points of depth %" PetscInt_FMT, cone[q], dep - 1); 13922582d50cSToby Isaac coneNew[2 + q] = DMPlexShiftPoint_Internal(cone[q], depth, depthShift) /*cone[q] + depthOffset[dep-1]*/; 139396a07cd0SMatthew G. Knepley hasUnsplit = PETSC_TRUE; 139418c5995bSMatthew G. Knepley } else { 13954c367dbcSMatthew G. Knepley coneNew[2 + q] = v + pMaxNew[dep - 1]; 1396163235baSMatthew G. Knepley if (dep > 1) { 1397163235baSMatthew G. Knepley const PetscInt *econe; 1398163235baSMatthew G. Knepley PetscInt econeSize, r, vs, vu; 1399163235baSMatthew G. Knepley 14009566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[q], &econeSize)); 14019566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[q], &econe)); 1402163235baSMatthew G. Knepley for (r = 0; r < econeSize; ++r) { 14039566063dSJacob Faibussowitsch PetscCall(PetscFindInt(econe[r], numSplitPoints[dep - 2], splitPoints[dep - 2], &vs)); 14049566063dSJacob Faibussowitsch PetscCall(PetscFindInt(econe[r], numUnsplitPoints[dep - 2], unsplitPoints[dep - 2], &vu)); 1405163235baSMatthew G. Knepley if (vs >= 0) continue; 140663a3b9bcSJacob Faibussowitsch PetscCheck(vu >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not locate point %" PetscInt_FMT " in split or unsplit points of depth %" PetscInt_FMT, econe[r], dep - 2); 1407163235baSMatthew G. Knepley hasUnsplit = PETSC_TRUE; 1408163235baSMatthew G. Knepley } 1409163235baSMatthew G. Knepley } 1410cd0c2139SMatthew G Knepley } 1411cd0c2139SMatthew G Knepley } 14129566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(sdm, splitp, &coneNew[2])); 14139566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(sdm, splitp, ornt)); 1414e537020bSMatthew G. Knepley /* Face support */ 1415b6dfa339SMatthew G. Knepley PetscInt vals[2]; 1416cd0c2139SMatthew G Knepley 1417b6dfa339SMatthew G. Knepley PetscCall(DMLabelGetValue(label, support[0], &vals[0])); 1418b6dfa339SMatthew G. Knepley if (supportSize > 1) PetscCall(DMLabelGetValue(label, support[1], &vals[1])); 1419b6dfa339SMatthew G. Knepley else vals[1] = -vals[0]; 1420b6dfa339SMatthew G. Knepley PetscCheck(vals[0] * vals[1] < 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid support labels %" PetscInt_FMT " %" PetscInt_FMT, vals[0], vals[1]); 1421b6dfa339SMatthew G. Knepley 1422b6dfa339SMatthew G. Knepley for (s = 0; s < 2; ++s) { 1423b6dfa339SMatthew G. Knepley if (s >= supportSize) { 1424b6dfa339SMatthew G. Knepley if (vals[s] < 0) { 1425b6dfa339SMatthew G. Knepley /* Ghost old face: Replace negative side cell with cohesive cell */ 1426accc9626SMatthew G. Knepley PetscCall(DMPlexInsertSupport(sdm, newp, s, hybcell)); 1427b6dfa339SMatthew G. Knepley } else { 1428b6dfa339SMatthew G. Knepley /* Ghost new face: Replace positive side cell with cohesive cell */ 1429accc9626SMatthew G. Knepley PetscCall(DMPlexInsertSupport(sdm, splitp, s, hybcell)); 1430b6dfa339SMatthew G. Knepley } 1431b6dfa339SMatthew G. Knepley } else { 1432b6dfa339SMatthew G. Knepley if (vals[s] < 0) { 1433cd0c2139SMatthew G Knepley /* Split old face: Replace negative side cell with cohesive cell */ 14349566063dSJacob Faibussowitsch PetscCall(DMPlexInsertSupport(sdm, newp, s, hybcell)); 1435cd0c2139SMatthew G Knepley } else { 1436cd0c2139SMatthew G Knepley /* Split new face: Replace positive side cell with cohesive cell */ 14379566063dSJacob Faibussowitsch PetscCall(DMPlexInsertSupport(sdm, splitp, s, hybcell)); 1438b6dfa339SMatthew G. Knepley } 1439b6dfa339SMatthew G. Knepley } 1440b6dfa339SMatthew G. Knepley } 1441b6dfa339SMatthew G. Knepley /* Get orientation for cohesive face using the positive side cell */ 1442e537020bSMatthew G. Knepley { 1443e537020bSMatthew G. Knepley const PetscInt *ncone, *nconeO; 1444b6dfa339SMatthew G. Knepley PetscInt nconeSize, nc, ocell; 1445accc9626SMatthew G. Knepley PetscBool flip = PETSC_FALSE; 1446e537020bSMatthew G. Knepley 14479371c9d4SSatish Balay if (supportSize > 1) { 14489371c9d4SSatish Balay ocell = vals[0] < 0 ? support[1] : support[0]; 14499371c9d4SSatish Balay } else { 14509371c9d4SSatish Balay ocell = support[0]; 14519371c9d4SSatish Balay flip = vals[0] < 0 ? PETSC_TRUE : PETSC_FALSE; 14529371c9d4SSatish Balay } 1453b6dfa339SMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, ocell, &nconeSize)); 1454b6dfa339SMatthew G. Knepley PetscCall(DMPlexGetCone(dm, ocell, &ncone)); 1455e1a13daeSMatthew G. Knepley PetscCall(DMPlexGetConeOrientation(dm, ocell, &nconeO)); 1456e537020bSMatthew G. Knepley for (nc = 0; nc < nconeSize; ++nc) { 1457e537020bSMatthew G. Knepley if (ncone[nc] == oldp) { 1458b6dfa339SMatthew G. Knepley coneONew[0] = flip ? -(nconeO[nc] + 1) : nconeO[nc]; 1459e537020bSMatthew G. Knepley break; 1460cd0c2139SMatthew G Knepley } 1461cd0c2139SMatthew G Knepley } 1462b6dfa339SMatthew G. Knepley PetscCheck(nc < nconeSize, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not locate face %" PetscInt_FMT " in neighboring cell %" PetscInt_FMT, oldp, ocell); 1463e537020bSMatthew G. Knepley } 14644c367dbcSMatthew G. Knepley /* Cohesive cell: Old and new split face, then new cohesive faces */ 1465b6dfa339SMatthew G. Knepley { 1466b6dfa339SMatthew G. Knepley const PetscInt No = DMPolytopeTypeGetNumArrangments(ct) / 2; 1467b6dfa339SMatthew G. Knepley PetscCheck((coneONew[0] >= -No) && (coneONew[0] < No), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid %s orientation %" PetscInt_FMT, DMPolytopeTypes[ct], coneONew[0]); 1468b6dfa339SMatthew G. Knepley } 1469b5a892a1SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, coneONew[0]); 1470b5a892a1SMatthew G. Knepley 1471fd4b9f15SMatthew G. Knepley coneNew[0] = newp; /* Extracted negative side orientation above */ 14724c367dbcSMatthew G. Knepley coneNew[1] = splitp; 14734c367dbcSMatthew G. Knepley coneONew[1] = coneONew[0]; 1474e537020bSMatthew G. Knepley for (q = 0; q < coneSize; ++q) { 1475412e9a14SMatthew G. Knepley /* Hybrid faces must follow order from oriented end face */ 1476b5a892a1SMatthew G. Knepley const PetscInt qa = arr[q * 2 + 0]; 1477b5a892a1SMatthew G. Knepley const PetscInt qo = arr[q * 2 + 1]; 1478b5a892a1SMatthew G. Knepley DMPolytopeType ft = dep == 2 ? DM_POLYTOPE_SEGMENT : DM_POLYTOPE_POINT; 1479412e9a14SMatthew G. Knepley 14809566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[qa], numSplitPoints[dep - 1], splitPoints[dep - 1], &v)); 148118c5995bSMatthew G. Knepley if (v < 0) { 14829566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[qa], numUnsplitPoints[dep - 1], unsplitPoints[dep - 1], &v)); 148318c5995bSMatthew G. Knepley coneNew[2 + q] = v + pMaxNew[dep] + numSplitPoints[dep] + numSplitPoints[dep - 1]; 148418c5995bSMatthew G. Knepley } else { 148518c5995bSMatthew G. Knepley coneNew[2 + q] = v + pMaxNew[dep] + numSplitPoints[dep]; 148618c5995bSMatthew G. Knepley } 1487b5a892a1SMatthew G. Knepley coneONew[2 + q] = DMPolytopeTypeComposeOrientation(ft, qo, ornt[qa]); 1488e537020bSMatthew G. Knepley } 14899566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(sdm, hybcell, coneNew)); 14909566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(sdm, hybcell, coneONew)); 149196a07cd0SMatthew G. Knepley /* Label the hybrid cells on the boundary of the split */ 14929566063dSJacob Faibussowitsch if (hasUnsplit) PetscCall(DMLabelSetValue(label, -hybcell, dim)); 1493cd0c2139SMatthew G Knepley } else if (dep == 0) { 14944c367dbcSMatthew G. Knepley const PetscInt hybedge = p + pMaxNew[dep + 1] + numSplitPoints[dep + 1]; 1495cd0c2139SMatthew G Knepley 1496cd0c2139SMatthew G Knepley /* Split old vertex: Edges in old split faces and new cohesive edge */ 14974c367dbcSMatthew G. Knepley for (e = 0, qn = 0; e < supportSize; ++e) { 1498cd0c2139SMatthew G Knepley PetscInt val; 1499cd0c2139SMatthew G Knepley 15009566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[e], &val)); 1501ad540459SPierre Jolivet if ((val == 1) || (val == (shift + 1))) supportNew[qn++] = DMPlexShiftPoint_Internal(support[e], depth, depthShift) /*support[e] + depthOffset[dep+1]*/; 1502cd0c2139SMatthew G Knepley } 15034c367dbcSMatthew G. Knepley supportNew[qn] = hybedge; 15049566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupport(sdm, newp, supportNew)); 1505cd0c2139SMatthew G Knepley /* Split new vertex: Edges in new split faces and new cohesive edge */ 15064c367dbcSMatthew G. Knepley for (e = 0, qp = 0; e < supportSize; ++e) { 1507cd0c2139SMatthew G Knepley PetscInt val, edge; 1508cd0c2139SMatthew G Knepley 15099566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[e], &val)); 1510cd0c2139SMatthew G Knepley if (val == 1) { 15119566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[e], numSplitPoints[dep + 1], splitPoints[dep + 1], &edge)); 151263a3b9bcSJacob Faibussowitsch PetscCheck(edge >= 0, comm, PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " is not a split edge", support[e]); 15134c367dbcSMatthew G. Knepley supportNew[qp++] = edge + pMaxNew[dep + 1]; 1514cd0c2139SMatthew G Knepley } else if (val == -(shift + 1)) { 15152582d50cSToby Isaac supportNew[qp++] = DMPlexShiftPoint_Internal(support[e], depth, depthShift) /*support[e] + depthOffset[dep+1]*/; 1516cd0c2139SMatthew G Knepley } 1517cd0c2139SMatthew G Knepley } 15184c367dbcSMatthew G. Knepley supportNew[qp] = hybedge; 15199566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupport(sdm, splitp, supportNew)); 15204c367dbcSMatthew G. Knepley /* Hybrid edge: Old and new split vertex */ 1521cd0c2139SMatthew G Knepley coneNew[0] = newp; 1522cd0c2139SMatthew G Knepley coneNew[1] = splitp; 15239566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(sdm, hybedge, coneNew)); 15244c367dbcSMatthew G. Knepley for (e = 0, qf = 0; e < supportSize; ++e) { 15254c367dbcSMatthew G. Knepley PetscInt val, edge; 15264c367dbcSMatthew G. Knepley 15279566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[e], &val)); 15284c367dbcSMatthew G. Knepley if (val == 1) { 15299566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[e], numSplitPoints[dep + 1], splitPoints[dep + 1], &edge)); 153063a3b9bcSJacob Faibussowitsch PetscCheck(edge >= 0, comm, PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " is not a split edge", support[e]); 15314c367dbcSMatthew G. Knepley supportNew[qf++] = edge + pMaxNew[dep + 2] + numSplitPoints[dep + 2]; 15324c367dbcSMatthew G. Knepley } 15334c367dbcSMatthew G. Knepley } 15349566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupport(sdm, hybedge, supportNew)); 1535cd0c2139SMatthew G Knepley } else if (dep == dim - 2) { 15364c367dbcSMatthew G. Knepley const PetscInt hybface = p + pMaxNew[dep + 1] + numSplitPoints[dep + 1]; 15374c367dbcSMatthew G. Knepley 1538cd0c2139SMatthew G Knepley /* Split old edge: old vertices in cone so no change */ 1539cd0c2139SMatthew G Knepley /* Split new edge: new vertices in cone */ 1540cd0c2139SMatthew G Knepley for (q = 0; q < coneSize; ++q) { 15419566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[q], numSplitPoints[dep - 1], splitPoints[dep - 1], &v)); 1542e1757548SMatthew G. Knepley if (v < 0) { 15439566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[q], numUnsplitPoints[dep - 1], unsplitPoints[dep - 1], &v)); 154463a3b9bcSJacob Faibussowitsch PetscCheck(v >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not locate point %" PetscInt_FMT " in split or unsplit points of depth %" PetscInt_FMT, cone[q], dep - 1); 15452582d50cSToby Isaac coneNew[q] = DMPlexShiftPoint_Internal(cone[q], depth, depthShift) /*cone[q] + depthOffset[dep-1]*/; 1546e1757548SMatthew G. Knepley } else { 15474c367dbcSMatthew G. Knepley coneNew[q] = v + pMaxNew[dep - 1]; 1548cd0c2139SMatthew G Knepley } 1549e1757548SMatthew G. Knepley } 15509566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(sdm, splitp, coneNew)); 1551cd0c2139SMatthew G Knepley /* Split old edge: Faces in positive side cells and old split faces */ 1552cd0c2139SMatthew G Knepley for (e = 0, q = 0; e < supportSize; ++e) { 1553cd0c2139SMatthew G Knepley PetscInt val; 1554cd0c2139SMatthew G Knepley 15559566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[e], &val)); 15564c367dbcSMatthew G. Knepley if (val == dim - 1) { 15572582d50cSToby Isaac supportNew[q++] = DMPlexShiftPoint_Internal(support[e], depth, depthShift) /*support[e] + depthOffset[dep+1]*/; 15584c367dbcSMatthew G. Knepley } else if (val == (shift + dim - 1)) { 15592582d50cSToby Isaac supportNew[q++] = DMPlexShiftPoint_Internal(support[e], depth, depthShift) /*support[e] + depthOffset[dep+1]*/; 1560cd0c2139SMatthew G Knepley } 1561cd0c2139SMatthew G Knepley } 1562b279cd2aSMatthew G. Knepley supportNew[q++] = p + pMaxNew[dep + 1] + numSplitPoints[dep + 1]; 15639566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupport(sdm, newp, supportNew)); 1564cd0c2139SMatthew G Knepley /* Split new edge: Faces in negative side cells and new split faces */ 1565cd0c2139SMatthew G Knepley for (e = 0, q = 0; e < supportSize; ++e) { 1566cd0c2139SMatthew G Knepley PetscInt val, face; 1567cd0c2139SMatthew G Knepley 15689566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[e], &val)); 1569cd0c2139SMatthew G Knepley if (val == dim - 1) { 15709566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[e], numSplitPoints[dep + 1], splitPoints[dep + 1], &face)); 157163a3b9bcSJacob Faibussowitsch PetscCheck(face >= 0, comm, PETSC_ERR_ARG_WRONG, "Face %" PetscInt_FMT " is not a split face", support[e]); 15724c367dbcSMatthew G. Knepley supportNew[q++] = face + pMaxNew[dep + 1]; 1573cd0c2139SMatthew G Knepley } else if (val == -(shift + dim - 1)) { 15742582d50cSToby Isaac supportNew[q++] = DMPlexShiftPoint_Internal(support[e], depth, depthShift) /*support[e] + depthOffset[dep+1]*/; 1575cd0c2139SMatthew G Knepley } 1576cd0c2139SMatthew G Knepley } 1577b279cd2aSMatthew G. Knepley supportNew[q++] = p + pMaxNew[dep + 1] + numSplitPoints[dep + 1]; 15789566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupport(sdm, splitp, supportNew)); 15794c367dbcSMatthew G. Knepley /* Hybrid face */ 15804c367dbcSMatthew G. Knepley coneNew[0] = newp; 15814c367dbcSMatthew G. Knepley coneNew[1] = splitp; 15824c367dbcSMatthew G. Knepley for (v = 0; v < coneSize; ++v) { 15834c367dbcSMatthew G. Knepley PetscInt vertex; 15849566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[v], numSplitPoints[dep - 1], splitPoints[dep - 1], &vertex)); 1585e1757548SMatthew G. Knepley if (vertex < 0) { 15869566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[v], numUnsplitPoints[dep - 1], unsplitPoints[dep - 1], &vertex)); 158763a3b9bcSJacob Faibussowitsch PetscCheck(vertex >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not locate point %" PetscInt_FMT " in split or unsplit points of depth %" PetscInt_FMT, cone[v], dep - 1); 1588e1757548SMatthew G. Knepley coneNew[2 + v] = vertex + pMaxNew[dep] + numSplitPoints[dep] + numSplitPoints[dep - 1]; 1589e1757548SMatthew G. Knepley } else { 15904c367dbcSMatthew G. Knepley coneNew[2 + v] = vertex + pMaxNew[dep] + numSplitPoints[dep]; 15914c367dbcSMatthew G. Knepley } 1592e1757548SMatthew G. Knepley } 15939566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(sdm, hybface, coneNew)); 15944c367dbcSMatthew G. Knepley for (e = 0, qf = 0; e < supportSize; ++e) { 15954c367dbcSMatthew G. Knepley PetscInt val, face; 15964c367dbcSMatthew G. Knepley 15979566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[e], &val)); 15984c367dbcSMatthew G. Knepley if (val == dim - 1) { 15999566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[e], numSplitPoints[dep + 1], splitPoints[dep + 1], &face)); 160063a3b9bcSJacob Faibussowitsch PetscCheck(face >= 0, comm, PETSC_ERR_ARG_WRONG, "Face %" PetscInt_FMT " is not a split face", support[e]); 16014c367dbcSMatthew G. Knepley supportNew[qf++] = face + pMaxNew[dep + 2] + numSplitPoints[dep + 2]; 16024c367dbcSMatthew G. Knepley } 16034c367dbcSMatthew G. Knepley } 16049566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupport(sdm, hybface, supportNew)); 1605cd0c2139SMatthew G Knepley } 1606cd0c2139SMatthew G Knepley } 1607cd0c2139SMatthew G Knepley } 160818c5995bSMatthew G. Knepley for (dep = 0; dep <= depth; ++dep) { 160918c5995bSMatthew G. Knepley for (p = 0; p < numUnsplitPoints[dep]; ++p) { 161018c5995bSMatthew G. Knepley const PetscInt oldp = unsplitPoints[dep][p]; 16112582d50cSToby Isaac const PetscInt newp = DMPlexShiftPoint_Internal(oldp, depth, depthShift) /*oldp + depthOffset[dep]*/; 1612b5a892a1SMatthew G. Knepley const PetscInt *cone, *support; 1613e1757548SMatthew G. Knepley PetscInt coneSize, supportSize, supportSizeNew, q, qf, e, f, s; 161418c5995bSMatthew G. Knepley 16159566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, oldp, &coneSize)); 16169566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, oldp, &cone)); 16179566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, oldp, &supportSize)); 16189566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, oldp, &support)); 161918c5995bSMatthew G. Knepley if (dep == 0) { 162018c5995bSMatthew G. Knepley const PetscInt hybedge = p + pMaxNew[dep + 1] + numSplitPoints[dep + 1] + numSplitPoints[dep]; 162118c5995bSMatthew G. Knepley 162218c5995bSMatthew G. Knepley /* Unsplit vertex */ 16239566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(sdm, newp, &supportSizeNew)); 162418c5995bSMatthew G. Knepley for (s = 0, q = 0; s < supportSize; ++s) { 16252582d50cSToby Isaac supportNew[q++] = DMPlexShiftPoint_Internal(support[s], depth, depthShift) /*support[s] + depthOffset[dep+1]*/; 16269566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[s], numSplitPoints[dep + 1], splitPoints[dep + 1], &e)); 1627ad540459SPierre Jolivet if (e >= 0) supportNew[q++] = e + pMaxNew[dep + 1]; 162818c5995bSMatthew G. Knepley } 162918c5995bSMatthew G. Knepley supportNew[q++] = hybedge; 163018c5995bSMatthew G. Knepley supportNew[q++] = hybedge; 163163a3b9bcSJacob Faibussowitsch PetscCheck(q == supportSizeNew, comm, PETSC_ERR_ARG_WRONG, "Support size %" PetscInt_FMT " != %" PetscInt_FMT " for vertex %" PetscInt_FMT, q, supportSizeNew, newp); 16329566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupport(sdm, newp, supportNew)); 163318c5995bSMatthew G. Knepley /* Hybrid edge */ 163418c5995bSMatthew G. Knepley coneNew[0] = newp; 163518c5995bSMatthew G. Knepley coneNew[1] = newp; 16369566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(sdm, hybedge, coneNew)); 163718c5995bSMatthew G. Knepley for (e = 0, qf = 0; e < supportSize; ++e) { 163818c5995bSMatthew G. Knepley PetscInt val, edge; 163918c5995bSMatthew G. Knepley 16409566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[e], &val)); 164118c5995bSMatthew G. Knepley if (val == 1) { 16429566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[e], numSplitPoints[dep + 1], splitPoints[dep + 1], &edge)); 164363a3b9bcSJacob Faibussowitsch PetscCheck(edge >= 0, comm, PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " is not a split edge", support[e]); 164418c5995bSMatthew G. Knepley supportNew[qf++] = edge + pMaxNew[dep + 2] + numSplitPoints[dep + 2]; 1645e1757548SMatthew G. Knepley } else if (val == (shift2 + 1)) { 16469566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[e], numUnsplitPoints[dep + 1], unsplitPoints[dep + 1], &edge)); 164763a3b9bcSJacob Faibussowitsch PetscCheck(edge >= 0, comm, PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " is not a unsplit edge", support[e]); 1648e1757548SMatthew G. Knepley supportNew[qf++] = edge + pMaxNew[dep + 2] + numSplitPoints[dep + 2] + numSplitPoints[dep + 1]; 164918c5995bSMatthew G. Knepley } 165018c5995bSMatthew G. Knepley } 16519566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupport(sdm, hybedge, supportNew)); 1652e1757548SMatthew G. Knepley } else if (dep == dim - 2) { 1653e1757548SMatthew G. Knepley const PetscInt hybface = p + pMaxNew[dep + 1] + numSplitPoints[dep + 1] + numSplitPoints[dep]; 1654e1757548SMatthew G. Knepley 1655da1dd7e4SMatthew G. Knepley /* Unsplit edge: Faces into original edge, split face, and hybrid face twice */ 1656e1757548SMatthew G. Knepley for (f = 0, qf = 0; f < supportSize; ++f) { 1657e1757548SMatthew G. Knepley PetscInt val, face; 1658e1757548SMatthew G. Knepley 16599566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[f], &val)); 1660e1757548SMatthew G. Knepley if (val == dim - 1) { 16619566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[f], numSplitPoints[dep + 1], splitPoints[dep + 1], &face)); 166263a3b9bcSJacob Faibussowitsch PetscCheck(face >= 0, comm, PETSC_ERR_ARG_WRONG, "Face %" PetscInt_FMT " is not a split face", support[f]); 16632582d50cSToby Isaac supportNew[qf++] = DMPlexShiftPoint_Internal(support[f], depth, depthShift) /*support[f] + depthOffset[dep+1]*/; 1664e1757548SMatthew G. Knepley supportNew[qf++] = face + pMaxNew[dep + 1]; 1665e1757548SMatthew G. Knepley } else { 16662582d50cSToby Isaac supportNew[qf++] = DMPlexShiftPoint_Internal(support[f], depth, depthShift) /*support[f] + depthOffset[dep+1]*/; 1667e1757548SMatthew G. Knepley } 1668e1757548SMatthew G. Knepley } 1669e1757548SMatthew G. Knepley supportNew[qf++] = hybface; 1670e1757548SMatthew G. Knepley supportNew[qf++] = hybface; 16719566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(sdm, newp, &supportSizeNew)); 167263a3b9bcSJacob Faibussowitsch PetscCheck(qf == supportSizeNew, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Support size for unsplit edge %" PetscInt_FMT " is %" PetscInt_FMT " != %" PetscInt_FMT, newp, qf, supportSizeNew); 16739566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupport(sdm, newp, supportNew)); 1674e1757548SMatthew G. Knepley /* Add hybrid face */ 1675e1757548SMatthew G. Knepley coneNew[0] = newp; 1676212cc919SMatthew G. Knepley coneNew[1] = newp; 16779566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[0], numUnsplitPoints[dep - 1], unsplitPoints[dep - 1], &v)); 167863a3b9bcSJacob Faibussowitsch PetscCheck(v >= 0, comm, PETSC_ERR_ARG_WRONG, "Vertex %" PetscInt_FMT " is not an unsplit vertex", cone[0]); 1679212cc919SMatthew G. Knepley coneNew[2] = v + pMaxNew[dep] + numSplitPoints[dep] + numSplitPoints[dep - 1]; 16809566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[1], numUnsplitPoints[dep - 1], unsplitPoints[dep - 1], &v)); 168163a3b9bcSJacob Faibussowitsch PetscCheck(v >= 0, comm, PETSC_ERR_ARG_WRONG, "Vertex %" PetscInt_FMT " is not an unsplit vertex", cone[1]); 1682e1757548SMatthew G. Knepley coneNew[3] = v + pMaxNew[dep] + numSplitPoints[dep] + numSplitPoints[dep - 1]; 16839566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(sdm, hybface, coneNew)); 1684da1dd7e4SMatthew G. Knepley for (f = 0, qf = 0; f < supportSize; ++f) { 1685da1dd7e4SMatthew G. Knepley PetscInt val, face; 1686da1dd7e4SMatthew G. Knepley 16879566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[f], &val)); 1688da1dd7e4SMatthew G. Knepley if (val == dim - 1) { 16899566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[f], numSplitPoints[dep + 1], splitPoints[dep + 1], &face)); 1690da1dd7e4SMatthew G. Knepley supportNew[qf++] = face + pMaxNew[dep + 2] + numSplitPoints[dep + 2]; 1691da1dd7e4SMatthew G. Knepley } 1692da1dd7e4SMatthew G. Knepley } 16939566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(sdm, hybface, &supportSizeNew)); 169463a3b9bcSJacob Faibussowitsch PetscCheck(qf == supportSizeNew, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Support size for hybrid face %" PetscInt_FMT " is %" PetscInt_FMT " != %" PetscInt_FMT, hybface, qf, supportSizeNew); 16959566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupport(sdm, hybface, supportNew)); 1696cd0c2139SMatthew G Knepley } 1697cd0c2139SMatthew G Knepley } 1698cd0c2139SMatthew G Knepley } 1699cd0c2139SMatthew G Knepley /* Step 6b: Replace split points in negative side cones */ 1700cd0c2139SMatthew G Knepley for (sp = 0; sp < numSP; ++sp) { 1701cd0c2139SMatthew G Knepley PetscInt dep = values[sp]; 1702cd0c2139SMatthew G Knepley IS pIS; 1703cd0c2139SMatthew G Knepley PetscInt numPoints; 1704cd0c2139SMatthew G Knepley const PetscInt *points; 1705cd0c2139SMatthew G Knepley 1706cd0c2139SMatthew G Knepley if (dep >= 0) continue; 17079566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, dep, &pIS)); 1708cd0c2139SMatthew G Knepley if (!pIS) continue; 1709cd0c2139SMatthew G Knepley dep = -dep - shift; 17109566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pIS, &numPoints)); 17119566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pIS, &points)); 1712cd0c2139SMatthew G Knepley for (p = 0; p < numPoints; ++p) { 1713cd0c2139SMatthew G Knepley const PetscInt oldp = points[p]; 17142582d50cSToby Isaac const PetscInt newp = DMPlexShiftPoint_Internal(oldp, depth, depthShift) /*depthOffset[dep] + oldp*/; 1715cd0c2139SMatthew G Knepley const PetscInt *cone; 1716cd0c2139SMatthew G Knepley PetscInt coneSize, c; 171750cf782dSMatthew G. Knepley /* PetscBool replaced = PETSC_FALSE; */ 1718cd0c2139SMatthew G Knepley 1719cd0c2139SMatthew G Knepley /* Negative edge: replace split vertex */ 1720cd0c2139SMatthew G Knepley /* Negative cell: replace split face */ 17219566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(sdm, newp, &coneSize)); 17229566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(sdm, newp, &cone)); 1723cd0c2139SMatthew G Knepley for (c = 0; c < coneSize; ++c) { 1724e38fbfedSToby Isaac const PetscInt coldp = DMPlexShiftPointInverse_Internal(cone[c], depth, depthShift); 1725cd0c2139SMatthew G Knepley PetscInt csplitp, cp, val; 1726cd0c2139SMatthew G Knepley 17279566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, coldp, &val)); 1728cd0c2139SMatthew G Knepley if (val == dep - 1) { 17299566063dSJacob Faibussowitsch PetscCall(PetscFindInt(coldp, numSplitPoints[dep - 1], splitPoints[dep - 1], &cp)); 173063a3b9bcSJacob Faibussowitsch PetscCheck(cp >= 0, comm, PETSC_ERR_ARG_WRONG, "Point %" PetscInt_FMT " is not a split point of dimension %" PetscInt_FMT, oldp, dep - 1); 1731cd0c2139SMatthew G Knepley csplitp = pMaxNew[dep - 1] + cp; 17329566063dSJacob Faibussowitsch PetscCall(DMPlexInsertCone(sdm, newp, c, csplitp)); 173350cf782dSMatthew G. Knepley /* replaced = PETSC_TRUE; */ 1734cd0c2139SMatthew G Knepley } 1735cd0c2139SMatthew G Knepley } 17364a189a86SMatthew G. Knepley /* Cells with only a vertex or edge on the submesh have no replacement */ 173728b400f6SJacob Faibussowitsch /* PetscCheck(replaced,comm, PETSC_ERR_ARG_WRONG, "The cone of point %d does not contain split points", oldp); */ 1738cd0c2139SMatthew G Knepley } 17399566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pIS, &points)); 17409566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pIS)); 1741cd0c2139SMatthew G Knepley } 1742fa8e8ae5SToby Isaac /* Step 7: Coordinates */ 17439566063dSJacob Faibussowitsch PetscCall(DMPlexShiftCoordinates_Internal(dm, depthShift, sdm)); 17449566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(sdm, &coordSection)); 17459566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(sdm, &coordinates)); 17469566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 1747cd0c2139SMatthew G Knepley for (v = 0; v < (numSplitPoints ? numSplitPoints[0] : 0); ++v) { 17482582d50cSToby Isaac const PetscInt newp = DMPlexShiftPoint_Internal(splitPoints[0][v], depth, depthShift) /*depthOffset[0] + splitPoints[0][v]*/; 1749cd0c2139SMatthew G Knepley const PetscInt splitp = pMaxNew[0] + v; 1750cd0c2139SMatthew G Knepley PetscInt dof, off, soff, d; 1751cd0c2139SMatthew G Knepley 17529566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, newp, &dof)); 17539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, newp, &off)); 17549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, splitp, &soff)); 1755cd0c2139SMatthew G Knepley for (d = 0; d < dof; ++d) coords[soff + d] = coords[off + d]; 1756cd0c2139SMatthew G Knepley } 17579566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 1758fa8e8ae5SToby Isaac /* Step 8: SF, if I can figure this out we can split the mesh in parallel */ 17599566063dSJacob Faibussowitsch PetscCall(DMPlexShiftSF_Internal(dm, depthShift, sdm)); 1760b6dfa339SMatthew G. Knepley /* TODO We need to associate the ghost points with the correct replica */ 1761fa8e8ae5SToby Isaac /* Step 9: Labels */ 17629566063dSJacob Faibussowitsch PetscCall(DMPlexShiftLabels_Internal(dm, depthShift, sdm)); 17639566063dSJacob Faibussowitsch PetscCall(DMPlexCreateVTKLabel_Internal(dm, PETSC_FALSE, sdm)); 17649566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(sdm, &numLabels)); 1765cd0c2139SMatthew G Knepley for (dep = 0; dep <= depth; ++dep) { 1766cd0c2139SMatthew G Knepley for (p = 0; p < numSplitPoints[dep]; ++p) { 17672582d50cSToby Isaac const PetscInt newp = DMPlexShiftPoint_Internal(splitPoints[dep][p], depth, depthShift) /*depthOffset[dep] + splitPoints[dep][p]*/; 1768cd0c2139SMatthew G Knepley const PetscInt splitp = pMaxNew[dep] + p; 1769cd0c2139SMatthew G Knepley PetscInt l; 1770cd0c2139SMatthew G Knepley 17717db7e0a7SMatthew G. Knepley if (splitLabel) { 17727db7e0a7SMatthew G. Knepley const PetscInt val = 100 + dep; 17737db7e0a7SMatthew G. Knepley 17749566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(splitLabel, newp, val)); 17759566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(splitLabel, splitp, -val)); 17767db7e0a7SMatthew G. Knepley } 1777cd0c2139SMatthew G Knepley for (l = 0; l < numLabels; ++l) { 1778cd0c2139SMatthew G Knepley DMLabel mlabel; 1779cd0c2139SMatthew G Knepley const char *lname; 1780cd0c2139SMatthew G Knepley PetscInt val; 17819a356370SMatthew G. Knepley PetscBool isDepth; 1782cd0c2139SMatthew G Knepley 17839566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(sdm, l, &lname)); 17849566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(lname, "depth", &isDepth)); 17859a356370SMatthew G. Knepley if (isDepth) continue; 17869566063dSJacob Faibussowitsch PetscCall(DMGetLabel(sdm, lname, &mlabel)); 17879566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(mlabel, newp, &val)); 178848a46eb9SPierre Jolivet if (val >= 0) PetscCall(DMLabelSetValue(mlabel, splitp, val)); 1789cd0c2139SMatthew G Knepley } 1790cd0c2139SMatthew G Knepley } 1791cd0c2139SMatthew G Knepley } 1792cd0c2139SMatthew G Knepley for (sp = 0; sp < numSP; ++sp) { 1793cd0c2139SMatthew G Knepley const PetscInt dep = values[sp]; 1794cd0c2139SMatthew G Knepley 1795cd0c2139SMatthew G Knepley if ((dep < 0) || (dep > depth)) continue; 17969566063dSJacob Faibussowitsch if (splitIS[dep]) PetscCall(ISRestoreIndices(splitIS[dep], &splitPoints[dep])); 17979566063dSJacob Faibussowitsch PetscCall(ISDestroy(&splitIS[dep])); 17989566063dSJacob Faibussowitsch if (unsplitIS[dep]) PetscCall(ISRestoreIndices(unsplitIS[dep], &unsplitPoints[dep])); 17999566063dSJacob Faibussowitsch PetscCall(ISDestroy(&unsplitIS[dep])); 1800cd0c2139SMatthew G Knepley } 1801b6dfa339SMatthew G. Knepley if (ghostIS) PetscCall(ISRestoreIndices(ghostIS, &ghostPoints)); 1802b6dfa339SMatthew G. Knepley PetscCall(ISDestroy(&ghostIS)); 1803cd0c2139SMatthew G Knepley if (label) { 18049566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 18059566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 1806cd0c2139SMatthew G Knepley } 18070d4d4d06SMatthew G. Knepley for (d = 0; d <= depth; ++d) { 18089566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(sdm, d, NULL, &pEnd)); 180936dbac82SMatthew G. Knepley pMaxNew[d] = pEnd - numHybridPoints[d] - numHybridPointsOld[d]; 18100d4d4d06SMatthew G. Knepley } 18119566063dSJacob Faibussowitsch PetscCall(PetscFree3(coneNew, coneONew, supportNew)); 18129566063dSJacob Faibussowitsch PetscCall(PetscFree5(depthMax, depthEnd, depthShift, pMaxNew, numHybridPointsOld)); 18139566063dSJacob Faibussowitsch PetscCall(PetscFree7(splitIS, unsplitIS, numSplitPoints, numUnsplitPoints, numHybridPoints, splitPoints, unsplitPoints)); 1814cd0c2139SMatthew G Knepley PetscFunctionReturn(0); 1815cd0c2139SMatthew G Knepley } 1816cd0c2139SMatthew G Knepley 1817cd0c2139SMatthew G Knepley /*@C 1818cd0c2139SMatthew G Knepley DMPlexConstructCohesiveCells - Construct cohesive cells which split the face along an internal interface 1819cd0c2139SMatthew G Knepley 1820cd0c2139SMatthew G Knepley Collective on dm 1821cd0c2139SMatthew G Knepley 1822cd0c2139SMatthew G Knepley Input Parameters: 1823cd0c2139SMatthew G Knepley + dm - The original DM 182453156dfcSMatthew G. Knepley - label - The label specifying the boundary faces (this could be auto-generated) 1825cd0c2139SMatthew G Knepley 1826cd0c2139SMatthew G Knepley Output Parameters: 18277db7e0a7SMatthew G. Knepley + splitLabel - The label containing the split points, or NULL if no output is desired 1828cd0c2139SMatthew G Knepley - dmSplit - The new DM 1829cd0c2139SMatthew G Knepley 1830cd0c2139SMatthew G Knepley Level: developer 1831cd0c2139SMatthew G Knepley 1832db781477SPatrick Sanan .seealso: `DMCreate()`, `DMPlexLabelCohesiveComplete()` 1833cd0c2139SMatthew G Knepley @*/ 1834d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexConstructCohesiveCells(DM dm, DMLabel label, DMLabel splitLabel, DM *dmSplit) 1835d71ae5a4SJacob Faibussowitsch { 1836cd0c2139SMatthew G Knepley DM sdm; 1837cd0c2139SMatthew G Knepley PetscInt dim; 1838cd0c2139SMatthew G Knepley 1839cd0c2139SMatthew G Knepley PetscFunctionBegin; 1840cd0c2139SMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1841064a246eSJacob Faibussowitsch PetscValidPointer(dmSplit, 4); 18429566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm)); 18439566063dSJacob Faibussowitsch PetscCall(DMSetType(sdm, DMPLEX)); 18449566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 18459566063dSJacob Faibussowitsch PetscCall(DMSetDimension(sdm, dim)); 1846cd0c2139SMatthew G Knepley switch (dim) { 1847cd0c2139SMatthew G Knepley case 2: 1848d71ae5a4SJacob Faibussowitsch case 3: 1849d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexConstructCohesiveCells_Internal(dm, label, splitLabel, sdm)); 1850d71ae5a4SJacob Faibussowitsch break; 1851d71ae5a4SJacob Faibussowitsch default: 1852d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct cohesive cells for dimension %" PetscInt_FMT, dim); 1853cd0c2139SMatthew G Knepley } 1854cd0c2139SMatthew G Knepley *dmSplit = sdm; 1855cd0c2139SMatthew G Knepley PetscFunctionReturn(0); 1856cd0c2139SMatthew G Knepley } 1857cd0c2139SMatthew G Knepley 18580f66a230SMatthew G. Knepley /* Returns the side of the surface for a given cell with a face on the surface */ 1859d71ae5a4SJacob Faibussowitsch static PetscErrorCode GetSurfaceSide_Static(DM dm, DM subdm, PetscInt numSubpoints, const PetscInt *subpoints, PetscInt cell, PetscInt face, PetscBool *pos) 1860d71ae5a4SJacob Faibussowitsch { 18610f66a230SMatthew G. Knepley const PetscInt *cone, *ornt; 18620f66a230SMatthew G. Knepley PetscInt dim, coneSize, c; 18630f66a230SMatthew G. Knepley 18640f66a230SMatthew G. Knepley PetscFunctionBegin; 18650f66a230SMatthew G. Knepley *pos = PETSC_TRUE; 18669566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 18679566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cell, &coneSize)); 18689566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cell, &cone)); 18699566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, cell, &ornt)); 18700f66a230SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 18710f66a230SMatthew G. Knepley if (cone[c] == face) { 18720f66a230SMatthew G. Knepley PetscInt o = ornt[c]; 18730f66a230SMatthew G. Knepley 18740f66a230SMatthew G. Knepley if (subdm) { 18750f66a230SMatthew G. Knepley const PetscInt *subcone, *subornt; 18760f66a230SMatthew G. Knepley PetscInt subpoint, subface, subconeSize, sc; 18770f66a230SMatthew G. Knepley 18789566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cell, numSubpoints, subpoints, &subpoint)); 18799566063dSJacob Faibussowitsch PetscCall(PetscFindInt(face, numSubpoints, subpoints, &subface)); 18809566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(subdm, subpoint, &subconeSize)); 18819566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(subdm, subpoint, &subcone)); 18829566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(subdm, subpoint, &subornt)); 18830f66a230SMatthew G. Knepley for (sc = 0; sc < subconeSize; ++sc) { 18840f66a230SMatthew G. Knepley if (subcone[sc] == subface) { 18850f66a230SMatthew G. Knepley o = subornt[0]; 18860f66a230SMatthew G. Knepley break; 18870f66a230SMatthew G. Knepley } 18880f66a230SMatthew G. Knepley } 188963a3b9bcSJacob Faibussowitsch PetscCheck(sc < subconeSize, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find subpoint %" PetscInt_FMT " (%" PetscInt_FMT ") in cone for subpoint %" PetscInt_FMT " (%" PetscInt_FMT ")", subface, face, subpoint, cell); 18900f66a230SMatthew G. Knepley } 18910f66a230SMatthew G. Knepley if (o >= 0) *pos = PETSC_TRUE; 18920f66a230SMatthew G. Knepley else *pos = PETSC_FALSE; 18930f66a230SMatthew G. Knepley break; 18940f66a230SMatthew G. Knepley } 18950f66a230SMatthew G. Knepley } 189663a3b9bcSJacob Faibussowitsch PetscCheck(c != coneSize, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " in split face %" PetscInt_FMT " support does not have it in the cone", cell, face); 18970f66a230SMatthew G. Knepley PetscFunctionReturn(0); 18980f66a230SMatthew G. Knepley } 18990f66a230SMatthew G. Knepley 1900d71ae5a4SJacob Faibussowitsch static PetscErrorCode CheckFaultEdge_Private(DM dm, DMLabel label) 1901d71ae5a4SJacob Faibussowitsch { 1902accc9626SMatthew G. Knepley IS facePosIS, faceNegIS, dimIS; 1903accc9626SMatthew G. Knepley const PetscInt *points; 1904accc9626SMatthew G. Knepley PetscInt dim, numPoints, p, shift = 100, shift2 = 200; 1905accc9626SMatthew G. Knepley 1906accc9626SMatthew G. Knepley PetscFunctionBegin; 1907accc9626SMatthew G. Knepley PetscCall(DMGetDimension(dm, &dim)); 1908accc9626SMatthew G. Knepley /* If any faces touching the fault divide cells on either side, split them */ 1909accc9626SMatthew G. Knepley PetscCall(DMLabelGetStratumIS(label, shift + dim - 1, &facePosIS)); 1910accc9626SMatthew G. Knepley PetscCall(DMLabelGetStratumIS(label, -(shift + dim - 1), &faceNegIS)); 1911accc9626SMatthew G. Knepley if (!facePosIS || !faceNegIS) { 1912accc9626SMatthew G. Knepley PetscCall(ISDestroy(&facePosIS)); 1913accc9626SMatthew G. Knepley PetscCall(ISDestroy(&faceNegIS)); 1914accc9626SMatthew G. Knepley PetscFunctionReturn(0); 1915accc9626SMatthew G. Knepley } 1916accc9626SMatthew G. Knepley PetscCall(ISExpand(facePosIS, faceNegIS, &dimIS)); 1917accc9626SMatthew G. Knepley PetscCall(ISDestroy(&facePosIS)); 1918accc9626SMatthew G. Knepley PetscCall(ISDestroy(&faceNegIS)); 1919accc9626SMatthew G. Knepley PetscCall(ISGetLocalSize(dimIS, &numPoints)); 1920accc9626SMatthew G. Knepley PetscCall(ISGetIndices(dimIS, &points)); 1921accc9626SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 1922accc9626SMatthew G. Knepley const PetscInt point = points[p]; 1923accc9626SMatthew G. Knepley const PetscInt *support; 1924accc9626SMatthew G. Knepley PetscInt supportSize, valA, valB; 1925accc9626SMatthew G. Knepley 1926accc9626SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, point, &supportSize)); 1927accc9626SMatthew G. Knepley if (supportSize != 2) continue; 1928accc9626SMatthew G. Knepley PetscCall(DMPlexGetSupport(dm, point, &support)); 1929accc9626SMatthew G. Knepley PetscCall(DMLabelGetValue(label, support[0], &valA)); 1930accc9626SMatthew G. Knepley PetscCall(DMLabelGetValue(label, support[1], &valB)); 1931accc9626SMatthew G. Knepley if ((valA == -1) || (valB == -1)) continue; 1932accc9626SMatthew G. Knepley if (valA * valB > 0) continue; 1933e1a13daeSMatthew G. Knepley /* Check that this face is not incident on only unsplit faces, meaning has at least one split face */ 1934e1a13daeSMatthew G. Knepley { 1935e1a13daeSMatthew G. Knepley PetscInt *closure = NULL; 1936e1a13daeSMatthew G. Knepley PetscBool split = PETSC_FALSE; 1937e1a13daeSMatthew G. Knepley PetscInt closureSize, cl; 1938e1a13daeSMatthew G. Knepley 1939e1a13daeSMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure)); 1940e1a13daeSMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 1941e1a13daeSMatthew G. Knepley PetscCall(DMLabelGetValue(label, closure[cl], &valA)); 19429371c9d4SSatish Balay if ((valA >= 0) && (valA <= dim)) { 19439371c9d4SSatish Balay split = PETSC_TRUE; 19449371c9d4SSatish Balay break; 19459371c9d4SSatish Balay } 1946e1a13daeSMatthew G. Knepley } 1947e1a13daeSMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure)); 1948e1a13daeSMatthew G. Knepley if (!split) continue; 1949e1a13daeSMatthew G. Knepley } 1950accc9626SMatthew G. Knepley /* Split the face */ 1951accc9626SMatthew G. Knepley PetscCall(DMLabelGetValue(label, point, &valA)); 1952accc9626SMatthew G. Knepley PetscCall(DMLabelClearValue(label, point, valA)); 1953accc9626SMatthew G. Knepley PetscCall(DMLabelSetValue(label, point, dim - 1)); 1954accc9626SMatthew G. Knepley /* Label its closure: 1955accc9626SMatthew G. Knepley unmarked: label as unsplit 1956accc9626SMatthew G. Knepley incident: relabel as split 1957accc9626SMatthew G. Knepley split: do nothing 1958accc9626SMatthew G. Knepley */ 1959accc9626SMatthew G. Knepley { 1960accc9626SMatthew G. Knepley PetscInt *closure = NULL; 1961accc9626SMatthew G. Knepley PetscInt closureSize, cl, dep; 1962accc9626SMatthew G. Knepley 1963accc9626SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure)); 1964accc9626SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 1965accc9626SMatthew G. Knepley PetscCall(DMLabelGetValue(label, closure[cl], &valA)); 1966accc9626SMatthew G. Knepley if (valA == -1) { /* Mark as unsplit */ 1967accc9626SMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, closure[cl], &dep)); 1968accc9626SMatthew G. Knepley PetscCall(DMLabelSetValue(label, closure[cl], shift2 + dep)); 1969accc9626SMatthew G. Knepley } else if (((valA >= shift) && (valA < shift2)) || ((valA <= -shift) && (valA > -shift2))) { 1970accc9626SMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, closure[cl], &dep)); 1971accc9626SMatthew G. Knepley PetscCall(DMLabelClearValue(label, closure[cl], valA)); 1972accc9626SMatthew G. Knepley PetscCall(DMLabelSetValue(label, closure[cl], dep)); 1973accc9626SMatthew G. Knepley } 1974accc9626SMatthew G. Knepley } 1975accc9626SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure)); 1976accc9626SMatthew G. Knepley } 1977accc9626SMatthew G. Knepley } 1978accc9626SMatthew G. Knepley PetscCall(ISRestoreIndices(dimIS, &points)); 1979accc9626SMatthew G. Knepley PetscCall(ISDestroy(&dimIS)); 1980accc9626SMatthew G. Knepley PetscFunctionReturn(0); 1981accc9626SMatthew G. Knepley } 1982accc9626SMatthew G. Knepley 1983cd0c2139SMatthew G Knepley /*@ 19840f66a230SMatthew G. Knepley DMPlexLabelCohesiveComplete - Starting with a label marking points on an internal surface, we add all other mesh pieces 1985cd0c2139SMatthew G Knepley to complete the surface 1986cd0c2139SMatthew G Knepley 1987cd0c2139SMatthew G Knepley Input Parameters: 1988cd0c2139SMatthew G Knepley + dm - The DM 19890f66a230SMatthew G. Knepley . label - A DMLabel marking the surface 19900f66a230SMatthew G. Knepley . blabel - A DMLabel marking the vertices on the boundary which will not be duplicated, or NULL to find them automatically 1991caf9e14dSMatthew G. Knepley . bvalue - Value of DMLabel marking the vertices on the boundary 1992bb55d314SMatthew G. Knepley . flip - Flag to flip the submesh normal and replace points on the other side 199347946fd8SMatthew G. Knepley - subdm - The subDM associated with the label, or NULL 1994cd0c2139SMatthew G Knepley 1995cd0c2139SMatthew G Knepley Output Parameter: 1996cd0c2139SMatthew G Knepley . label - A DMLabel marking all surface points 1997cd0c2139SMatthew G Knepley 19980f66a230SMatthew G. Knepley Note: The vertices in blabel are called "unsplit" in the terminology from hybrid cell creation. 19990f66a230SMatthew G. Knepley 2000cd0c2139SMatthew G Knepley Level: developer 2001cd0c2139SMatthew G Knepley 2002db781477SPatrick Sanan .seealso: `DMPlexConstructCohesiveCells()`, `DMPlexLabelComplete()` 2003cd0c2139SMatthew G Knepley @*/ 2004d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelCohesiveComplete(DM dm, DMLabel label, DMLabel blabel, PetscInt bvalue, PetscBool flip, DM subdm) 2005d71ae5a4SJacob Faibussowitsch { 2006d90583fdSMatthew G. Knepley DMLabel depthLabel; 2007accc9626SMatthew G. Knepley IS dimIS, subpointIS = NULL; 200847946fd8SMatthew G. Knepley const PetscInt *points, *subpoints; 2009bb55d314SMatthew G. Knepley const PetscInt rev = flip ? -1 : 1; 2010accc9626SMatthew G. Knepley PetscInt shift = 100, shift2 = 200, shift3 = 300, dim, depth, numPoints, numSubpoints, p, val; 2011cd0c2139SMatthew G Knepley 2012cd0c2139SMatthew G Knepley PetscFunctionBegin; 20139566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 20149566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 20159566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 201647946fd8SMatthew G. Knepley if (subdm) { 20179566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(subdm, &subpointIS)); 201847946fd8SMatthew G. Knepley if (subpointIS) { 20199566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(subpointIS, &numSubpoints)); 20209566063dSJacob Faibussowitsch PetscCall(ISGetIndices(subpointIS, &subpoints)); 202147946fd8SMatthew G. Knepley } 202247946fd8SMatthew G. Knepley } 2023d7c8f101SMatthew G. Knepley /* Mark cell on the fault, and its faces which touch the fault: cell orientation for face gives the side of the fault */ 20249566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, dim - 1, &dimIS)); 2025accc9626SMatthew G. Knepley if (!dimIS) goto divide; 20269566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(dimIS, &numPoints)); 20279566063dSJacob Faibussowitsch PetscCall(ISGetIndices(dimIS, &points)); 2028d7c8f101SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { /* Loop over fault faces */ 2029cd0c2139SMatthew G Knepley const PetscInt *support; 2030cd0c2139SMatthew G Knepley PetscInt supportSize, s; 2031cd0c2139SMatthew G Knepley 20329566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, points[p], &supportSize)); 2033c4419245SMatthew G. Knepley #if 0 2034c4419245SMatthew G. Knepley if (supportSize != 2) { 2035c4419245SMatthew G. Knepley const PetscInt *lp; 2036c4419245SMatthew G. Knepley PetscInt Nlp, pind; 2037c4419245SMatthew G. Knepley 2038c4419245SMatthew G. Knepley /* Check that for a cell with a single support face, that face is in the SF */ 2039c4419245SMatthew G. Knepley /* THis check only works for the remote side. We would need root side information */ 20409566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(dm->sf, NULL, &Nlp, &lp, NULL)); 20419566063dSJacob Faibussowitsch PetscCall(PetscFindInt(points[p], Nlp, lp, &pind)); 204263a3b9bcSJacob Faibussowitsch PetscCheck(pind >= 0,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Split face %" PetscInt_FMT " has %" PetscInt_FMT " != 2 supports, and the face is not shared with another process", points[p], supportSize); 2043c4419245SMatthew G. Knepley } 2044c4419245SMatthew G. Knepley #endif 20459566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, points[p], &support)); 2046cd0c2139SMatthew G Knepley for (s = 0; s < supportSize; ++s) { 20470f66a230SMatthew G. Knepley const PetscInt *cone; 2048cd0c2139SMatthew G Knepley PetscInt coneSize, c; 20490f66a230SMatthew G. Knepley PetscBool pos; 2050cd0c2139SMatthew G Knepley 20519566063dSJacob Faibussowitsch PetscCall(GetSurfaceSide_Static(dm, subdm, numSubpoints, subpoints, support[s], points[p], &pos)); 20529566063dSJacob Faibussowitsch if (pos) PetscCall(DMLabelSetValue(label, support[s], rev * (shift + dim))); 20539566063dSJacob Faibussowitsch else PetscCall(DMLabelSetValue(label, support[s], -rev * (shift + dim))); 20540f66a230SMatthew G. Knepley if (rev < 0) pos = !pos ? PETSC_TRUE : PETSC_FALSE; 20550f66a230SMatthew G. Knepley /* Put faces touching the fault in the label */ 20569566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize)); 20579566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, support[s], &cone)); 2058cd0c2139SMatthew G Knepley for (c = 0; c < coneSize; ++c) { 2059cd0c2139SMatthew G Knepley const PetscInt point = cone[c]; 2060cd0c2139SMatthew G Knepley 20619566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, point, &val)); 2062cd0c2139SMatthew G Knepley if (val == -1) { 2063cd0c2139SMatthew G Knepley PetscInt *closure = NULL; 2064cd0c2139SMatthew G Knepley PetscInt closureSize, cl; 2065cd0c2139SMatthew G Knepley 20669566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure)); 2067cd0c2139SMatthew G Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 2068cd0c2139SMatthew G Knepley const PetscInt clp = closure[cl]; 2069a0541d8aSMatthew G. Knepley PetscInt bval = -1; 2070cd0c2139SMatthew G Knepley 20719566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, clp, &val)); 20729566063dSJacob Faibussowitsch if (blabel) PetscCall(DMLabelGetValue(blabel, clp, &bval)); 2073a0541d8aSMatthew G. Knepley if ((val >= 0) && (val < dim - 1) && (bval < 0)) { 20749566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, point, pos == PETSC_TRUE ? shift + dim - 1 : -(shift + dim - 1))); 2075cd0c2139SMatthew G Knepley break; 2076cd0c2139SMatthew G Knepley } 2077cd0c2139SMatthew G Knepley } 20789566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure)); 2079cd0c2139SMatthew G Knepley } 2080cd0c2139SMatthew G Knepley } 2081cd0c2139SMatthew G Knepley } 2082cd0c2139SMatthew G Knepley } 2083accc9626SMatthew G. Knepley PetscCall(ISRestoreIndices(dimIS, &points)); 2084accc9626SMatthew G. Knepley PetscCall(ISDestroy(&dimIS)); 2085a0541d8aSMatthew G. Knepley /* Mark boundary points as unsplit */ 208686200784SMatthew G. Knepley if (blabel) { 2087accc9626SMatthew G. Knepley IS bdIS; 2088accc9626SMatthew G. Knepley 2089caf9e14dSMatthew G. Knepley PetscCall(DMLabelGetStratumIS(blabel, bvalue, &bdIS)); 2090accc9626SMatthew G. Knepley PetscCall(ISGetLocalSize(bdIS, &numPoints)); 2091accc9626SMatthew G. Knepley PetscCall(ISGetIndices(bdIS, &points)); 2092a0541d8aSMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 2093a0541d8aSMatthew G. Knepley const PetscInt point = points[p]; 2094a0541d8aSMatthew G. Knepley PetscInt val, bval; 2095a0541d8aSMatthew G. Knepley 20969566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(blabel, point, &bval)); 2097a0541d8aSMatthew G. Knepley if (bval >= 0) { 20989566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, point, &val)); 2099f7019248SMatthew G. Knepley if ((val < 0) || (val > dim)) { 2100f7019248SMatthew G. Knepley /* This could be a point added from splitting a vertex on an adjacent fault, otherwise its just wrong */ 21019566063dSJacob Faibussowitsch PetscCall(DMLabelClearValue(blabel, point, bval)); 2102f7019248SMatthew G. Knepley } 2103f7019248SMatthew G. Knepley } 2104f7019248SMatthew G. Knepley } 2105f7019248SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 2106f7019248SMatthew G. Knepley const PetscInt point = points[p]; 2107f7019248SMatthew G. Knepley PetscInt val, bval; 2108f7019248SMatthew G. Knepley 21099566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(blabel, point, &bval)); 2110f7019248SMatthew G. Knepley if (bval >= 0) { 211186200784SMatthew G. Knepley const PetscInt *cone, *support; 211286200784SMatthew G. Knepley PetscInt coneSize, supportSize, s, valA, valB, valE; 211386200784SMatthew G. Knepley 2114a0541d8aSMatthew G. Knepley /* Mark as unsplit */ 21159566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, point, &val)); 2116e1a13daeSMatthew G. Knepley PetscCheck(val >= 0 && val <= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " has label value %" PetscInt_FMT ", should be part of the fault", point, val); 21179566063dSJacob Faibussowitsch PetscCall(DMLabelClearValue(label, point, val)); 21189566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, point, shift2 + val)); 21192c06a818SMatthew G. Knepley /* Check for cross-edge 21202c06a818SMatthew G. Knepley A cross-edge has endpoints which are both on the boundary of the surface, but the edge itself is not. */ 212186200784SMatthew G. Knepley if (val != 0) continue; 21229566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, point, &support)); 21239566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, point, &supportSize)); 212486200784SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 21259566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, support[s], &cone)); 21269566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize)); 212763a3b9bcSJacob Faibussowitsch PetscCheck(coneSize == 2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Edge %" PetscInt_FMT " has %" PetscInt_FMT " vertices != 2", support[s], coneSize); 21289566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(blabel, cone[0], &valA)); 21299566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(blabel, cone[1], &valB)); 21309566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(blabel, support[s], &valE)); 21319566063dSJacob Faibussowitsch if ((valE < 0) && (valA >= 0) && (valB >= 0) && (cone[0] != cone[1])) PetscCall(DMLabelSetValue(blabel, support[s], 2)); 213286200784SMatthew G. Knepley } 2133a0541d8aSMatthew G. Knepley } 2134a0541d8aSMatthew G. Knepley } 2135accc9626SMatthew G. Knepley PetscCall(ISRestoreIndices(bdIS, &points)); 2136accc9626SMatthew G. Knepley PetscCall(ISDestroy(&bdIS)); 2137a0541d8aSMatthew G. Knepley } 2138b6dfa339SMatthew G. Knepley /* Mark ghost fault cells */ 2139b6dfa339SMatthew G. Knepley { 2140b6dfa339SMatthew G. Knepley PetscSF sf; 2141b6dfa339SMatthew G. Knepley const PetscInt *leaves; 2142b6dfa339SMatthew G. Knepley PetscInt Nl, l; 2143b6dfa339SMatthew G. Knepley 2144b6dfa339SMatthew G. Knepley PetscCall(DMGetPointSF(dm, &sf)); 2145b6dfa339SMatthew G. Knepley PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &leaves, NULL)); 2146accc9626SMatthew G. Knepley PetscCall(DMLabelGetStratumIS(label, dim - 1, &dimIS)); 2147accc9626SMatthew G. Knepley if (!dimIS) goto divide; 2148accc9626SMatthew G. Knepley PetscCall(ISGetLocalSize(dimIS, &numPoints)); 2149accc9626SMatthew G. Knepley PetscCall(ISGetIndices(dimIS, &points)); 2150b6dfa339SMatthew G. Knepley if (Nl > 0) { 2151b6dfa339SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 2152b6dfa339SMatthew G. Knepley const PetscInt point = points[p]; 2153b6dfa339SMatthew G. Knepley PetscInt val; 2154b6dfa339SMatthew G. Knepley 2155b6dfa339SMatthew G. Knepley PetscCall(PetscFindInt(point, Nl, leaves, &l)); 2156b6dfa339SMatthew G. Knepley if (l >= 0) { 2157b6dfa339SMatthew G. Knepley PetscInt *closure = NULL; 2158b6dfa339SMatthew G. Knepley PetscInt closureSize, cl; 2159b6dfa339SMatthew G. Knepley 2160b6dfa339SMatthew G. Knepley PetscCall(DMLabelGetValue(label, point, &val)); 2161b6dfa339SMatthew G. Knepley PetscCheck((val == dim - 1) || (val == shift2 + dim - 1), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " has label value %" PetscInt_FMT ", should be a fault face", point, val); 2162b6dfa339SMatthew G. Knepley PetscCall(DMLabelClearValue(label, point, val)); 2163b6dfa339SMatthew G. Knepley PetscCall(DMLabelSetValue(label, point, shift3 + val)); 2164b6dfa339SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure)); 2165accc9626SMatthew G. Knepley for (cl = 2; cl < closureSize * 2; cl += 2) { 2166b6dfa339SMatthew G. Knepley const PetscInt clp = closure[cl]; 2167b6dfa339SMatthew G. Knepley 2168b6dfa339SMatthew G. Knepley PetscCall(DMLabelGetValue(label, clp, &val)); 2169b6dfa339SMatthew G. Knepley PetscCheck(val != -1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " is missing from label, but is in the closure of a fault face", point); 2170b6dfa339SMatthew G. Knepley PetscCall(DMLabelClearValue(label, clp, val)); 2171b6dfa339SMatthew G. Knepley PetscCall(DMLabelSetValue(label, clp, shift3 + val)); 2172b6dfa339SMatthew G. Knepley } 2173b6dfa339SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure)); 2174b6dfa339SMatthew G. Knepley } 2175b6dfa339SMatthew G. Knepley } 2176b6dfa339SMatthew G. Knepley } 2177b6dfa339SMatthew G. Knepley PetscCall(ISRestoreIndices(dimIS, &points)); 2178b6dfa339SMatthew G. Knepley PetscCall(ISDestroy(&dimIS)); 2179accc9626SMatthew G. Knepley } 2180accc9626SMatthew G. Knepley divide: 2181b6dfa339SMatthew G. Knepley if (subpointIS) PetscCall(ISRestoreIndices(subpointIS, &subpoints)); 2182accc9626SMatthew G. Knepley PetscCall(DMPlexLabelFaultHalo(dm, label)); 2183accc9626SMatthew G. Knepley PetscCall(CheckFaultEdge_Private(dm, label)); 2184cd0c2139SMatthew G Knepley PetscFunctionReturn(0); 2185cd0c2139SMatthew G Knepley } 2186cd0c2139SMatthew G Knepley 2187720e594eSMatthew G. Knepley /* Check that no cell have all vertices on the fault */ 2188d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckValidSubmesh_Private(DM dm, DMLabel label, DM subdm) 2189d71ae5a4SJacob Faibussowitsch { 2190720e594eSMatthew G. Knepley IS subpointIS; 2191720e594eSMatthew G. Knepley const PetscInt *dmpoints; 2192720e594eSMatthew G. Knepley PetscInt defaultValue, cStart, cEnd, c, vStart, vEnd; 2193720e594eSMatthew G. Knepley 2194720e594eSMatthew G. Knepley PetscFunctionBegin; 2195720e594eSMatthew G. Knepley if (!label) PetscFunctionReturn(0); 21969566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(label, &defaultValue)); 21979566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(subdm, &subpointIS)); 2198720e594eSMatthew G. Knepley if (!subpointIS) PetscFunctionReturn(0); 21999566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(subdm, 0, &cStart, &cEnd)); 22009566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 22019566063dSJacob Faibussowitsch PetscCall(ISGetIndices(subpointIS, &dmpoints)); 2202720e594eSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 2203720e594eSMatthew G. Knepley PetscBool invalidCell = PETSC_TRUE; 2204720e594eSMatthew G. Knepley PetscInt *closure = NULL; 2205720e594eSMatthew G. Knepley PetscInt closureSize, cl; 2206720e594eSMatthew G. Knepley 22079566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, dmpoints[c], PETSC_TRUE, &closureSize, &closure)); 2208720e594eSMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 2209720e594eSMatthew G. Knepley PetscInt value = 0; 2210720e594eSMatthew G. Knepley 2211720e594eSMatthew G. Knepley if ((closure[cl] < vStart) || (closure[cl] >= vEnd)) continue; 22129566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, closure[cl], &value)); 22139371c9d4SSatish Balay if (value == defaultValue) { 22149371c9d4SSatish Balay invalidCell = PETSC_FALSE; 22159371c9d4SSatish Balay break; 22169371c9d4SSatish Balay } 2217720e594eSMatthew G. Knepley } 22189566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, dmpoints[c], PETSC_TRUE, &closureSize, &closure)); 2219720e594eSMatthew G. Knepley if (invalidCell) { 22209566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(subpointIS, &dmpoints)); 22219566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subpointIS)); 22229566063dSJacob Faibussowitsch PetscCall(DMDestroy(&subdm)); 222363a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Ambiguous submesh. Cell %" PetscInt_FMT " has all of its vertices on the submesh.", dmpoints[c]); 2224720e594eSMatthew G. Knepley } 2225720e594eSMatthew G. Knepley } 22269566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(subpointIS, &dmpoints)); 2227720e594eSMatthew G. Knepley PetscFunctionReturn(0); 2228720e594eSMatthew G. Knepley } 2229720e594eSMatthew G. Knepley 2230c08575a3SMatthew G. Knepley /*@ 22313cf72582SMatthew G. Knepley DMPlexCreateHybridMesh - Create a mesh with hybrid cells along an internal interface 22323cf72582SMatthew G. Knepley 22333cf72582SMatthew G. Knepley Collective on dm 22343cf72582SMatthew G. Knepley 22353cf72582SMatthew G. Knepley Input Parameters: 22363cf72582SMatthew G. Knepley + dm - The original DM 2237720e594eSMatthew G. Knepley . label - The label specifying the interface vertices 2238caf9e14dSMatthew G. Knepley . bdlabel - The optional label specifying the interface boundary vertices 2239caf9e14dSMatthew G. Knepley - bdvalue - Value of optional label specifying the interface boundary vertices 22403cf72582SMatthew G. Knepley 22413cf72582SMatthew G. Knepley Output Parameters: 22427db7e0a7SMatthew G. Knepley + hybridLabel - The label fully marking the interface, or NULL if no output is desired 22437db7e0a7SMatthew G. Knepley . splitLabel - The label containing the split points, or NULL if no output is desired 2244720e594eSMatthew G. Knepley . dmInterface - The new interface DM, or NULL 2245720e594eSMatthew G. Knepley - dmHybrid - The new DM with cohesive cells 22463cf72582SMatthew G. Knepley 22476eccb800SMatthew Knepley Note: The hybridLabel indicates what parts of the original mesh impinged on the on division surface. For points 22486eccb800SMatthew Knepley directly on the division surface, they are labeled with their dimension, so an edge 7 on the division surface would be 22496eccb800SMatthew Knepley 7 (1) in hybridLabel. For points that impinge from the positive side, they are labeled with 100+dim, so an edge 6 with 22506eccb800SMatthew Knepley one vertex 3 on the surface would be 6 (101) and 3 (0) in hybridLabel. If an edge 9 from the negative side of the 22516eccb800SMatthew Knepley surface also hits vertex 3, it would be 9 (-101) in hybridLabel. 22526eccb800SMatthew Knepley 22536eccb800SMatthew Knepley The splitLabel indicates what points in the new hybrid mesh were the result of splitting points in the original 22546eccb800SMatthew Knepley mesh. The label value is +=100+dim for each point. For example, if two edges 10 and 14 in the hybrid resulting from 22556eccb800SMatthew Knepley splitting an edge in the original mesh, you would have 10 (101) and 14 (-101) in the splitLabel. 22566eccb800SMatthew Knepley 22576eccb800SMatthew Knepley The dmInterface is a DM built from the original division surface. It has a label which can be retrieved using 22586eccb800SMatthew Knepley DMPlexGetSubpointMap() which maps each point back to the point in the surface of the original mesh. 22596eccb800SMatthew Knepley 22603cf72582SMatthew G. Knepley Level: developer 22613cf72582SMatthew G. Knepley 2262db781477SPatrick Sanan .seealso: `DMPlexConstructCohesiveCells()`, `DMPlexLabelCohesiveComplete()`, `DMPlexGetSubpointMap()`, `DMCreate()` 22633cf72582SMatthew G. Knepley @*/ 2264d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateHybridMesh(DM dm, DMLabel label, DMLabel bdlabel, PetscInt bdvalue, DMLabel *hybridLabel, DMLabel *splitLabel, DM *dmInterface, DM *dmHybrid) 2265d71ae5a4SJacob Faibussowitsch { 22663cf72582SMatthew G. Knepley DM idm; 22677db7e0a7SMatthew G. Knepley DMLabel subpointMap, hlabel, slabel = NULL; 22683cf72582SMatthew G. Knepley PetscInt dim; 22693cf72582SMatthew G. Knepley 22703cf72582SMatthew G. Knepley PetscFunctionBegin; 22713cf72582SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 227292ef8ba2SVaclav Hapla if (label) PetscValidPointer(label, 2); 2273720e594eSMatthew G. Knepley if (bdlabel) PetscValidPointer(bdlabel, 3); 227492ef8ba2SVaclav Hapla if (hybridLabel) PetscValidPointer(hybridLabel, 5); 227592ef8ba2SVaclav Hapla if (splitLabel) PetscValidPointer(splitLabel, 6); 227692ef8ba2SVaclav Hapla if (dmInterface) PetscValidPointer(dmInterface, 7); 227792ef8ba2SVaclav Hapla PetscValidPointer(dmHybrid, 8); 22789566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 22799566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSubmesh(dm, label, 1, PETSC_FALSE, &idm)); 22809566063dSJacob Faibussowitsch PetscCall(DMPlexCheckValidSubmesh_Private(dm, label, idm)); 22819566063dSJacob Faibussowitsch PetscCall(DMPlexOrient(idm)); 22829566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointMap(idm, &subpointMap)); 22839566063dSJacob Faibussowitsch PetscCall(DMLabelDuplicate(subpointMap, &hlabel)); 22849566063dSJacob Faibussowitsch PetscCall(DMLabelClearStratum(hlabel, dim)); 22857db7e0a7SMatthew G. Knepley if (splitLabel) { 22867db7e0a7SMatthew G. Knepley const char *name; 22877db7e0a7SMatthew G. Knepley char sname[PETSC_MAX_PATH_LEN]; 22887db7e0a7SMatthew G. Knepley 22899566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)hlabel, &name)); 22909566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(sname, name, PETSC_MAX_PATH_LEN)); 22919566063dSJacob Faibussowitsch PetscCall(PetscStrcat(sname, " split")); 22929566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, sname, &slabel)); 22937db7e0a7SMatthew G. Knepley } 2294caf9e14dSMatthew G. Knepley PetscCall(DMPlexLabelCohesiveComplete(dm, hlabel, bdlabel, bdvalue, PETSC_FALSE, idm)); 22959371c9d4SSatish Balay if (dmInterface) { 22969371c9d4SSatish Balay *dmInterface = idm; 22979371c9d4SSatish Balay } else PetscCall(DMDestroy(&idm)); 22989566063dSJacob Faibussowitsch PetscCall(DMPlexConstructCohesiveCells(dm, hlabel, slabel, dmHybrid)); 22995de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, *dmHybrid)); 23003cf72582SMatthew G. Knepley if (hybridLabel) *hybridLabel = hlabel; 23019566063dSJacob Faibussowitsch else PetscCall(DMLabelDestroy(&hlabel)); 23027db7e0a7SMatthew G. Knepley if (splitLabel) *splitLabel = slabel; 23034a7ee7d0SMatthew G. Knepley { 23044a7ee7d0SMatthew G. Knepley DM cdm; 23054a7ee7d0SMatthew G. Knepley DMLabel ctLabel; 23064a7ee7d0SMatthew G. Knepley 23074a7ee7d0SMatthew G. Knepley /* We need to somehow share the celltype label with the coordinate dm */ 23089566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(*dmHybrid, &cdm)); 23099566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(*dmHybrid, &ctLabel)); 23109566063dSJacob Faibussowitsch PetscCall(DMSetLabel(cdm, ctLabel)); 23114a7ee7d0SMatthew G. Knepley } 2312cd0c2139SMatthew G Knepley PetscFunctionReturn(0); 2313cd0c2139SMatthew G Knepley } 2314cd0c2139SMatthew G Knepley 2315efa14ee0SMatthew G Knepley /* Here we need the explicit assumption that: 2316efa14ee0SMatthew G Knepley 2317efa14ee0SMatthew G Knepley For any marked cell, the marked vertices constitute a single face 2318efa14ee0SMatthew G Knepley */ 2319d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMarkSubmesh_Uninterpolated(DM dm, DMLabel vertexLabel, PetscInt value, DMLabel subpointMap, PetscInt *numFaces, PetscInt *nFV, DM subdm) 2320d71ae5a4SJacob Faibussowitsch { 2321fed694aaSMatthew G. Knepley IS subvertexIS = NULL; 2322efa14ee0SMatthew G Knepley const PetscInt *subvertices; 2323412e9a14SMatthew G. Knepley PetscInt *pStart, *pEnd, pSize; 2324efa14ee0SMatthew G Knepley PetscInt depth, dim, d, numSubVerticesInitial = 0, v; 2325efa14ee0SMatthew G Knepley 2326efa14ee0SMatthew G Knepley PetscFunctionBegin; 2327efa14ee0SMatthew G Knepley *numFaces = 0; 2328efa14ee0SMatthew G Knepley *nFV = 0; 23299566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 23309566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 233177d178adSMatthew G. Knepley pSize = PetscMax(depth, dim) + 1; 23329566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pSize, &pStart, pSize, &pEnd)); 233348a46eb9SPierre Jolivet for (d = 0; d <= depth; ++d) PetscCall(DMPlexGetSimplexOrBoxCells(dm, depth - d, &pStart[d], &pEnd[d])); 2334efa14ee0SMatthew G Knepley /* Loop over initial vertices and mark all faces in the collective star() */ 23359566063dSJacob Faibussowitsch if (vertexLabel) PetscCall(DMLabelGetStratumIS(vertexLabel, value, &subvertexIS)); 2336efa14ee0SMatthew G Knepley if (subvertexIS) { 23379566063dSJacob Faibussowitsch PetscCall(ISGetSize(subvertexIS, &numSubVerticesInitial)); 23389566063dSJacob Faibussowitsch PetscCall(ISGetIndices(subvertexIS, &subvertices)); 2339efa14ee0SMatthew G Knepley } 2340efa14ee0SMatthew G Knepley for (v = 0; v < numSubVerticesInitial; ++v) { 2341efa14ee0SMatthew G Knepley const PetscInt vertex = subvertices[v]; 23420298fd71SBarry Smith PetscInt *star = NULL; 2343efa14ee0SMatthew G Knepley PetscInt starSize, s, numCells = 0, c; 2344efa14ee0SMatthew G Knepley 23459566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star)); 2346efa14ee0SMatthew G Knepley for (s = 0; s < starSize * 2; s += 2) { 2347efa14ee0SMatthew G Knepley const PetscInt point = star[s]; 2348efa14ee0SMatthew G Knepley if ((point >= pStart[depth]) && (point < pEnd[depth])) star[numCells++] = point; 2349efa14ee0SMatthew G Knepley } 2350efa14ee0SMatthew G Knepley for (c = 0; c < numCells; ++c) { 2351efa14ee0SMatthew G Knepley const PetscInt cell = star[c]; 23520298fd71SBarry Smith PetscInt *closure = NULL; 2353efa14ee0SMatthew G Knepley PetscInt closureSize, cl; 2354efa14ee0SMatthew G Knepley PetscInt cellLoc, numCorners = 0, faceSize = 0; 2355efa14ee0SMatthew G Knepley 23569566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(subpointMap, cell, &cellLoc)); 235765560c7fSMatthew G Knepley if (cellLoc == 2) continue; 235863a3b9bcSJacob Faibussowitsch PetscCheck(cellLoc < 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Cell %" PetscInt_FMT " has dimension %" PetscInt_FMT " in the surface label", cell, cellLoc); 23599566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure)); 2360efa14ee0SMatthew G Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 2361efa14ee0SMatthew G Knepley const PetscInt point = closure[cl]; 2362efa14ee0SMatthew G Knepley PetscInt vertexLoc; 2363efa14ee0SMatthew G Knepley 2364efa14ee0SMatthew G Knepley if ((point >= pStart[0]) && (point < pEnd[0])) { 2365efa14ee0SMatthew G Knepley ++numCorners; 23669566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(vertexLabel, point, &vertexLoc)); 2367830e53efSMatthew G. Knepley if (vertexLoc == value) closure[faceSize++] = point; 2368efa14ee0SMatthew G Knepley } 2369efa14ee0SMatthew G Knepley } 23709566063dSJacob Faibussowitsch if (!(*nFV)) PetscCall(DMPlexGetNumFaceVertices(dm, dim, numCorners, nFV)); 237163a3b9bcSJacob Faibussowitsch PetscCheck(faceSize <= *nFV, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %" PetscInt_FMT " of an element on the surface", faceSize); 2372efa14ee0SMatthew G Knepley if (faceSize == *nFV) { 2373007baee2SMatthew G. Knepley const PetscInt *cells = NULL; 2374007baee2SMatthew G. Knepley PetscInt numCells, nc; 2375007baee2SMatthew G. Knepley 2376efa14ee0SMatthew G Knepley ++(*numFaces); 237748a46eb9SPierre Jolivet for (cl = 0; cl < faceSize; ++cl) PetscCall(DMLabelSetValue(subpointMap, closure[cl], 0)); 23789566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, faceSize, closure, &numCells, &cells)); 237948a46eb9SPierre Jolivet for (nc = 0; nc < numCells; ++nc) PetscCall(DMLabelSetValue(subpointMap, cells[nc], 2)); 23809566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, faceSize, closure, &numCells, &cells)); 2381efa14ee0SMatthew G Knepley } 23829566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure)); 2383efa14ee0SMatthew G Knepley } 23849566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star)); 2385efa14ee0SMatthew G Knepley } 238648a46eb9SPierre Jolivet if (subvertexIS) PetscCall(ISRestoreIndices(subvertexIS, &subvertices)); 23879566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subvertexIS)); 23889566063dSJacob Faibussowitsch PetscCall(PetscFree2(pStart, pEnd)); 2389efa14ee0SMatthew G Knepley PetscFunctionReturn(0); 2390efa14ee0SMatthew G Knepley } 2391efa14ee0SMatthew G Knepley 2392d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMarkSubmesh_Interpolated(DM dm, DMLabel vertexLabel, PetscInt value, PetscBool markedFaces, DMLabel subpointMap, DM subdm) 2393d71ae5a4SJacob Faibussowitsch { 239434b4c39eSMatthew G. Knepley IS subvertexIS = NULL; 2395efa14ee0SMatthew G Knepley const PetscInt *subvertices; 2396412e9a14SMatthew G. Knepley PetscInt *pStart, *pEnd; 2397efa14ee0SMatthew G Knepley PetscInt dim, d, numSubVerticesInitial = 0, v; 2398efa14ee0SMatthew G Knepley 2399efa14ee0SMatthew G Knepley PetscFunctionBegin; 24009566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 24019566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(dim + 1, &pStart, dim + 1, &pEnd)); 240248a46eb9SPierre Jolivet for (d = 0; d <= dim; ++d) PetscCall(DMPlexGetSimplexOrBoxCells(dm, dim - d, &pStart[d], &pEnd[d])); 2403efa14ee0SMatthew G Knepley /* Loop over initial vertices and mark all faces in the collective star() */ 240434b4c39eSMatthew G. Knepley if (vertexLabel) { 24059566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(vertexLabel, value, &subvertexIS)); 2406efa14ee0SMatthew G Knepley if (subvertexIS) { 24079566063dSJacob Faibussowitsch PetscCall(ISGetSize(subvertexIS, &numSubVerticesInitial)); 24089566063dSJacob Faibussowitsch PetscCall(ISGetIndices(subvertexIS, &subvertices)); 2409efa14ee0SMatthew G Knepley } 241034b4c39eSMatthew G. Knepley } 2411efa14ee0SMatthew G Knepley for (v = 0; v < numSubVerticesInitial; ++v) { 2412efa14ee0SMatthew G Knepley const PetscInt vertex = subvertices[v]; 24130298fd71SBarry Smith PetscInt *star = NULL; 2414efa14ee0SMatthew G Knepley PetscInt starSize, s, numFaces = 0, f; 2415efa14ee0SMatthew G Knepley 24169566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star)); 2417efa14ee0SMatthew G Knepley for (s = 0; s < starSize * 2; s += 2) { 2418efa14ee0SMatthew G Knepley const PetscInt point = star[s]; 2419158acfadSMatthew G. Knepley PetscInt faceLoc; 2420158acfadSMatthew G. Knepley 2421158acfadSMatthew G. Knepley if ((point >= pStart[dim - 1]) && (point < pEnd[dim - 1])) { 2422158acfadSMatthew G. Knepley if (markedFaces) { 24239566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(vertexLabel, point, &faceLoc)); 2424158acfadSMatthew G. Knepley if (faceLoc < 0) continue; 2425158acfadSMatthew G. Knepley } 2426158acfadSMatthew G. Knepley star[numFaces++] = point; 2427158acfadSMatthew G. Knepley } 2428efa14ee0SMatthew G Knepley } 2429efa14ee0SMatthew G Knepley for (f = 0; f < numFaces; ++f) { 2430efa14ee0SMatthew G Knepley const PetscInt face = star[f]; 24310298fd71SBarry Smith PetscInt *closure = NULL; 2432efa14ee0SMatthew G Knepley PetscInt closureSize, c; 2433efa14ee0SMatthew G Knepley PetscInt faceLoc; 2434efa14ee0SMatthew G Knepley 24359566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(subpointMap, face, &faceLoc)); 2436efa14ee0SMatthew G Knepley if (faceLoc == dim - 1) continue; 243763a3b9bcSJacob Faibussowitsch PetscCheck(faceLoc < 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Face %" PetscInt_FMT " has dimension %" PetscInt_FMT " in the surface label", face, faceLoc); 24389566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, face, PETSC_TRUE, &closureSize, &closure)); 2439efa14ee0SMatthew G Knepley for (c = 0; c < closureSize * 2; c += 2) { 2440efa14ee0SMatthew G Knepley const PetscInt point = closure[c]; 2441efa14ee0SMatthew G Knepley PetscInt vertexLoc; 2442efa14ee0SMatthew G Knepley 2443efa14ee0SMatthew G Knepley if ((point >= pStart[0]) && (point < pEnd[0])) { 24449566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(vertexLabel, point, &vertexLoc)); 2445830e53efSMatthew G. Knepley if (vertexLoc != value) break; 2446efa14ee0SMatthew G Knepley } 2447efa14ee0SMatthew G Knepley } 2448efa14ee0SMatthew G Knepley if (c == closureSize * 2) { 2449efa14ee0SMatthew G Knepley const PetscInt *support; 2450efa14ee0SMatthew G Knepley PetscInt supportSize, s; 2451efa14ee0SMatthew G Knepley 2452efa14ee0SMatthew G Knepley for (c = 0; c < closureSize * 2; c += 2) { 2453efa14ee0SMatthew G Knepley const PetscInt point = closure[c]; 2454efa14ee0SMatthew G Knepley 2455efa14ee0SMatthew G Knepley for (d = 0; d < dim; ++d) { 2456efa14ee0SMatthew G Knepley if ((point >= pStart[d]) && (point < pEnd[d])) { 24579566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(subpointMap, point, d)); 2458efa14ee0SMatthew G Knepley break; 2459efa14ee0SMatthew G Knepley } 2460efa14ee0SMatthew G Knepley } 2461efa14ee0SMatthew G Knepley } 24629566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, face, &supportSize)); 24639566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, face, &support)); 246448a46eb9SPierre Jolivet for (s = 0; s < supportSize; ++s) PetscCall(DMLabelSetValue(subpointMap, support[s], dim)); 2465efa14ee0SMatthew G Knepley } 24669566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, face, PETSC_TRUE, &closureSize, &closure)); 2467efa14ee0SMatthew G Knepley } 24689566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star)); 2469efa14ee0SMatthew G Knepley } 24709566063dSJacob Faibussowitsch if (subvertexIS) PetscCall(ISRestoreIndices(subvertexIS, &subvertices)); 24719566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subvertexIS)); 24729566063dSJacob Faibussowitsch PetscCall(PetscFree2(pStart, pEnd)); 2473efa14ee0SMatthew G Knepley PetscFunctionReturn(0); 2474efa14ee0SMatthew G Knepley } 2475efa14ee0SMatthew G Knepley 2476d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMarkCohesiveSubmesh_Uninterpolated(DM dm, PetscBool hasLagrange, const char labelname[], PetscInt value, DMLabel subpointMap, PetscInt *numFaces, PetscInt *nFV, PetscInt *subCells[], DM subdm) 2477d71ae5a4SJacob Faibussowitsch { 247827c04023SMatthew G. Knepley DMLabel label = NULL; 2479766ab985SMatthew G. Knepley const PetscInt *cone; 24809fc93327SToby Isaac PetscInt dim, cMax, cEnd, c, subc = 0, p, coneSize = -1; 2481766ab985SMatthew G. Knepley 2482812bfc34SJed Brown PetscFunctionBegin; 2483c0ed958bSJed Brown *numFaces = 0; 2484c0ed958bSJed Brown *nFV = 0; 24859566063dSJacob Faibussowitsch if (labelname) PetscCall(DMGetLabel(dm, labelname, &label)); 2486fed694aaSMatthew G. Knepley *subCells = NULL; 24879566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 24889566063dSJacob Faibussowitsch PetscCall(DMPlexGetTensorPrismBounds_Internal(dm, dim, &cMax, &cEnd)); 2489766ab985SMatthew G. Knepley if (cMax < 0) PetscFunctionReturn(0); 249027c04023SMatthew G. Knepley if (label) { 249127c04023SMatthew G. Knepley for (c = cMax; c < cEnd; ++c) { 249227c04023SMatthew G. Knepley PetscInt val; 249327c04023SMatthew G. Knepley 24949566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, c, &val)); 249527c04023SMatthew G. Knepley if (val == value) { 249627c04023SMatthew G. Knepley ++(*numFaces); 24979566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 249827c04023SMatthew G. Knepley } 249927c04023SMatthew G. Knepley } 250027c04023SMatthew G. Knepley } else { 2501766ab985SMatthew G. Knepley *numFaces = cEnd - cMax; 25029566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cMax, &coneSize)); 250327c04023SMatthew G. Knepley } 25049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(*numFaces * 2, subCells)); 25059fc93327SToby Isaac if (!(*numFaces)) PetscFunctionReturn(0); 25069fc93327SToby Isaac *nFV = hasLagrange ? coneSize / 3 : coneSize / 2; 2507766ab985SMatthew G. Knepley for (c = cMax; c < cEnd; ++c) { 2508766ab985SMatthew G. Knepley const PetscInt *cells; 2509766ab985SMatthew G. Knepley PetscInt numCells; 2510766ab985SMatthew G. Knepley 251127c04023SMatthew G. Knepley if (label) { 251227c04023SMatthew G. Knepley PetscInt val; 251327c04023SMatthew G. Knepley 25149566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, c, &val)); 251527c04023SMatthew G. Knepley if (val != value) continue; 251627c04023SMatthew G. Knepley } 25179566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 251848a46eb9SPierre Jolivet for (p = 0; p < *nFV; ++p) PetscCall(DMLabelSetValue(subpointMap, cone[p], 0)); 2519766ab985SMatthew G. Knepley /* Negative face */ 25209566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, *nFV, cone, &numCells, &cells)); 252127234c99SMatthew G. Knepley /* Not true in parallel 252208401ef6SPierre Jolivet PetscCheck(numCells == 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cohesive cells should separate two cells"); */ 2523766ab985SMatthew G. Knepley for (p = 0; p < numCells; ++p) { 25249566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(subpointMap, cells[p], 2)); 252527234c99SMatthew G. Knepley (*subCells)[subc++] = cells[p]; 2526766ab985SMatthew G. Knepley } 25279566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, *nFV, cone, &numCells, &cells)); 2528766ab985SMatthew G. Knepley /* Positive face is not included */ 2529766ab985SMatthew G. Knepley } 2530766ab985SMatthew G. Knepley PetscFunctionReturn(0); 2531766ab985SMatthew G. Knepley } 2532766ab985SMatthew G. Knepley 2533d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMarkCohesiveSubmesh_Interpolated(DM dm, DMLabel label, PetscInt value, DMLabel subpointMap, DM subdm) 2534d71ae5a4SJacob Faibussowitsch { 2535766ab985SMatthew G. Knepley PetscInt *pStart, *pEnd; 2536766ab985SMatthew G. Knepley PetscInt dim, cMax, cEnd, c, d; 2537766ab985SMatthew G. Knepley 2538812bfc34SJed Brown PetscFunctionBegin; 25399566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 25409566063dSJacob Faibussowitsch PetscCall(DMPlexGetTensorPrismBounds_Internal(dm, dim, &cMax, &cEnd)); 2541766ab985SMatthew G. Knepley if (cMax < 0) PetscFunctionReturn(0); 25429566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(dim + 1, &pStart, dim + 1, &pEnd)); 25439566063dSJacob Faibussowitsch for (d = 0; d <= dim; ++d) PetscCall(DMPlexGetDepthStratum(dm, d, &pStart[d], &pEnd[d])); 2544766ab985SMatthew G. Knepley for (c = cMax; c < cEnd; ++c) { 2545766ab985SMatthew G. Knepley const PetscInt *cone; 2546766ab985SMatthew G. Knepley PetscInt *closure = NULL; 2547b3154360SMatthew G. Knepley PetscInt fconeSize, coneSize, closureSize, cl, val; 2548766ab985SMatthew G. Knepley 254927c04023SMatthew G. Knepley if (label) { 25509566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, c, &val)); 255127c04023SMatthew G. Knepley if (val != value) continue; 255227c04023SMatthew G. Knepley } 25539566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 25549566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 25559566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[0], &fconeSize)); 25561dca8a05SBarry Smith PetscCheck(coneSize == (fconeSize ? fconeSize : 1) + 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cohesive cells should separate two cells"); 2557b3154360SMatthew G. Knepley /* Negative face */ 25589566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, cone[0], PETSC_TRUE, &closureSize, &closure)); 2559766ab985SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 2560766ab985SMatthew G. Knepley const PetscInt point = closure[cl]; 2561766ab985SMatthew G. Knepley 2562766ab985SMatthew G. Knepley for (d = 0; d <= dim; ++d) { 2563766ab985SMatthew G. Knepley if ((point >= pStart[d]) && (point < pEnd[d])) { 25649566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(subpointMap, point, d)); 2565766ab985SMatthew G. Knepley break; 2566766ab985SMatthew G. Knepley } 2567766ab985SMatthew G. Knepley } 2568766ab985SMatthew G. Knepley } 25699566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], PETSC_TRUE, &closureSize, &closure)); 2570766ab985SMatthew G. Knepley /* Cells -- positive face is not included */ 2571766ab985SMatthew G. Knepley for (cl = 0; cl < 1; ++cl) { 2572766ab985SMatthew G. Knepley const PetscInt *support; 2573766ab985SMatthew G. Knepley PetscInt supportSize, s; 2574766ab985SMatthew G. Knepley 25759566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, cone[cl], &supportSize)); 257608401ef6SPierre Jolivet /* PetscCheck(supportSize == 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cohesive faces should separate two cells"); */ 25779566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, cone[cl], &support)); 257848a46eb9SPierre Jolivet for (s = 0; s < supportSize; ++s) PetscCall(DMLabelSetValue(subpointMap, support[s], dim)); 2579766ab985SMatthew G. Knepley } 2580766ab985SMatthew G. Knepley } 25819566063dSJacob Faibussowitsch PetscCall(PetscFree2(pStart, pEnd)); 2582766ab985SMatthew G. Knepley PetscFunctionReturn(0); 2583766ab985SMatthew G. Knepley } 2584766ab985SMatthew G. Knepley 2585d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetFaceOrientation(DM dm, PetscInt cell, PetscInt numCorners, PetscInt indices[], PetscInt oppositeVertex, PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 2586d71ae5a4SJacob Faibussowitsch { 258782f516ccSBarry Smith MPI_Comm comm; 2588e6ccafaeSMatthew G Knepley PetscBool posOrient = PETSC_FALSE; 2589e6ccafaeSMatthew G Knepley const PetscInt debug = 0; 2590e6ccafaeSMatthew G Knepley PetscInt cellDim, faceSize, f; 2591e6ccafaeSMatthew G Knepley 259282f516ccSBarry Smith PetscFunctionBegin; 25939566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 25949566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &cellDim)); 259563a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscPrintf(comm, "cellDim: %" PetscInt_FMT " numCorners: %" PetscInt_FMT "\n", cellDim, numCorners)); 2596e6ccafaeSMatthew G Knepley 2597ddeab2a6SMatthew G. Knepley if (cellDim == 1 && numCorners == 2) { 2598ddeab2a6SMatthew G. Knepley /* Triangle */ 2599e6ccafaeSMatthew G Knepley faceSize = numCorners - 1; 2600e6ccafaeSMatthew G Knepley posOrient = !(oppositeVertex % 2) ? PETSC_TRUE : PETSC_FALSE; 2601ddeab2a6SMatthew G. Knepley } else if (cellDim == 2 && numCorners == 3) { 2602ddeab2a6SMatthew G. Knepley /* Triangle */ 2603ddeab2a6SMatthew G. Knepley faceSize = numCorners - 1; 2604ddeab2a6SMatthew G. Knepley posOrient = !(oppositeVertex % 2) ? PETSC_TRUE : PETSC_FALSE; 2605ddeab2a6SMatthew G. Knepley } else if (cellDim == 3 && numCorners == 4) { 2606ddeab2a6SMatthew G. Knepley /* Tetrahedron */ 2607ddeab2a6SMatthew G. Knepley faceSize = numCorners - 1; 2608ddeab2a6SMatthew G. Knepley posOrient = (oppositeVertex % 2) ? PETSC_TRUE : PETSC_FALSE; 2609e6ccafaeSMatthew G Knepley } else if (cellDim == 1 && numCorners == 3) { 2610e6ccafaeSMatthew G Knepley /* Quadratic line */ 2611e6ccafaeSMatthew G Knepley faceSize = 1; 2612e6ccafaeSMatthew G Knepley posOrient = PETSC_TRUE; 2613e6ccafaeSMatthew G Knepley } else if (cellDim == 2 && numCorners == 4) { 2614e6ccafaeSMatthew G Knepley /* Quads */ 2615e6ccafaeSMatthew G Knepley faceSize = 2; 2616e6ccafaeSMatthew G Knepley if ((indices[1] > indices[0]) && (indices[1] - indices[0] == 1)) { 2617e6ccafaeSMatthew G Knepley posOrient = PETSC_TRUE; 2618e6ccafaeSMatthew G Knepley } else if ((indices[0] == 3) && (indices[1] == 0)) { 2619e6ccafaeSMatthew G Knepley posOrient = PETSC_TRUE; 2620e6ccafaeSMatthew G Knepley } else { 2621e6ccafaeSMatthew G Knepley if (((indices[0] > indices[1]) && (indices[0] - indices[1] == 1)) || ((indices[0] == 0) && (indices[1] == 3))) { 2622e6ccafaeSMatthew G Knepley posOrient = PETSC_FALSE; 2623e6ccafaeSMatthew G Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossedge"); 2624e6ccafaeSMatthew G Knepley } 2625e6ccafaeSMatthew G Knepley } else if (cellDim == 2 && numCorners == 6) { 2626e6ccafaeSMatthew G Knepley /* Quadratic triangle (I hate this) */ 2627e6ccafaeSMatthew G Knepley /* Edges are determined by the first 2 vertices (corners of edges) */ 2628e6ccafaeSMatthew G Knepley const PetscInt faceSizeTri = 3; 2629e6ccafaeSMatthew G Knepley PetscInt sortedIndices[3], i, iFace; 2630e6ccafaeSMatthew G Knepley PetscBool found = PETSC_FALSE; 2631e6ccafaeSMatthew G Knepley PetscInt faceVerticesTriSorted[9] = { 2632e6ccafaeSMatthew G Knepley 0, 3, 4, /* bottom */ 2633e6ccafaeSMatthew G Knepley 1, 4, 5, /* right */ 2634e6ccafaeSMatthew G Knepley 2, 3, 5, /* left */ 2635e6ccafaeSMatthew G Knepley }; 2636e6ccafaeSMatthew G Knepley PetscInt faceVerticesTri[9] = { 2637e6ccafaeSMatthew G Knepley 0, 3, 4, /* bottom */ 2638e6ccafaeSMatthew G Knepley 1, 4, 5, /* right */ 2639e6ccafaeSMatthew G Knepley 2, 5, 3, /* left */ 2640e6ccafaeSMatthew G Knepley }; 2641e6ccafaeSMatthew G Knepley 2642e6ccafaeSMatthew G Knepley for (i = 0; i < faceSizeTri; ++i) sortedIndices[i] = indices[i]; 26439566063dSJacob Faibussowitsch PetscCall(PetscSortInt(faceSizeTri, sortedIndices)); 2644e6ccafaeSMatthew G Knepley for (iFace = 0; iFace < 3; ++iFace) { 2645e6ccafaeSMatthew G Knepley const PetscInt ii = iFace * faceSizeTri; 2646e6ccafaeSMatthew G Knepley PetscInt fVertex, cVertex; 2647e6ccafaeSMatthew G Knepley 26489371c9d4SSatish Balay if ((sortedIndices[0] == faceVerticesTriSorted[ii + 0]) && (sortedIndices[1] == faceVerticesTriSorted[ii + 1])) { 2649e6ccafaeSMatthew G Knepley for (fVertex = 0; fVertex < faceSizeTri; ++fVertex) { 2650e6ccafaeSMatthew G Knepley for (cVertex = 0; cVertex < faceSizeTri; ++cVertex) { 2651e6ccafaeSMatthew G Knepley if (indices[cVertex] == faceVerticesTri[ii + fVertex]) { 2652e6ccafaeSMatthew G Knepley faceVertices[fVertex] = origVertices[cVertex]; 2653e6ccafaeSMatthew G Knepley break; 2654e6ccafaeSMatthew G Knepley } 2655e6ccafaeSMatthew G Knepley } 2656e6ccafaeSMatthew G Knepley } 2657e6ccafaeSMatthew G Knepley found = PETSC_TRUE; 2658e6ccafaeSMatthew G Knepley break; 2659e6ccafaeSMatthew G Knepley } 2660e6ccafaeSMatthew G Knepley } 266128b400f6SJacob Faibussowitsch PetscCheck(found, comm, PETSC_ERR_ARG_WRONG, "Invalid tri crossface"); 2662e6ccafaeSMatthew G Knepley if (posOriented) *posOriented = PETSC_TRUE; 2663e6ccafaeSMatthew G Knepley PetscFunctionReturn(0); 2664e6ccafaeSMatthew G Knepley } else if (cellDim == 2 && numCorners == 9) { 2665e6ccafaeSMatthew G Knepley /* Quadratic quad (I hate this) */ 2666e6ccafaeSMatthew G Knepley /* Edges are determined by the first 2 vertices (corners of edges) */ 2667e6ccafaeSMatthew G Knepley const PetscInt faceSizeQuad = 3; 2668e6ccafaeSMatthew G Knepley PetscInt sortedIndices[3], i, iFace; 2669e6ccafaeSMatthew G Knepley PetscBool found = PETSC_FALSE; 2670e6ccafaeSMatthew G Knepley PetscInt faceVerticesQuadSorted[12] = { 2671e6ccafaeSMatthew G Knepley 0, 1, 4, /* bottom */ 2672e6ccafaeSMatthew G Knepley 1, 2, 5, /* right */ 2673e6ccafaeSMatthew G Knepley 2, 3, 6, /* top */ 2674e6ccafaeSMatthew G Knepley 0, 3, 7, /* left */ 2675e6ccafaeSMatthew G Knepley }; 2676e6ccafaeSMatthew G Knepley PetscInt faceVerticesQuad[12] = { 2677e6ccafaeSMatthew G Knepley 0, 1, 4, /* bottom */ 2678e6ccafaeSMatthew G Knepley 1, 2, 5, /* right */ 2679e6ccafaeSMatthew G Knepley 2, 3, 6, /* top */ 2680e6ccafaeSMatthew G Knepley 3, 0, 7, /* left */ 2681e6ccafaeSMatthew G Knepley }; 2682e6ccafaeSMatthew G Knepley 2683e6ccafaeSMatthew G Knepley for (i = 0; i < faceSizeQuad; ++i) sortedIndices[i] = indices[i]; 26849566063dSJacob Faibussowitsch PetscCall(PetscSortInt(faceSizeQuad, sortedIndices)); 2685e6ccafaeSMatthew G Knepley for (iFace = 0; iFace < 4; ++iFace) { 2686e6ccafaeSMatthew G Knepley const PetscInt ii = iFace * faceSizeQuad; 2687e6ccafaeSMatthew G Knepley PetscInt fVertex, cVertex; 2688e6ccafaeSMatthew G Knepley 26899371c9d4SSatish Balay if ((sortedIndices[0] == faceVerticesQuadSorted[ii + 0]) && (sortedIndices[1] == faceVerticesQuadSorted[ii + 1])) { 2690e6ccafaeSMatthew G Knepley for (fVertex = 0; fVertex < faceSizeQuad; ++fVertex) { 2691e6ccafaeSMatthew G Knepley for (cVertex = 0; cVertex < faceSizeQuad; ++cVertex) { 2692e6ccafaeSMatthew G Knepley if (indices[cVertex] == faceVerticesQuad[ii + fVertex]) { 2693e6ccafaeSMatthew G Knepley faceVertices[fVertex] = origVertices[cVertex]; 2694e6ccafaeSMatthew G Knepley break; 2695e6ccafaeSMatthew G Knepley } 2696e6ccafaeSMatthew G Knepley } 2697e6ccafaeSMatthew G Knepley } 2698e6ccafaeSMatthew G Knepley found = PETSC_TRUE; 2699e6ccafaeSMatthew G Knepley break; 2700e6ccafaeSMatthew G Knepley } 2701e6ccafaeSMatthew G Knepley } 270228b400f6SJacob Faibussowitsch PetscCheck(found, comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossface"); 2703e6ccafaeSMatthew G Knepley if (posOriented) *posOriented = PETSC_TRUE; 2704e6ccafaeSMatthew G Knepley PetscFunctionReturn(0); 2705e6ccafaeSMatthew G Knepley } else if (cellDim == 3 && numCorners == 8) { 2706e6ccafaeSMatthew G Knepley /* Hexes 2707e6ccafaeSMatthew G Knepley A hex is two oriented quads with the normal of the first 2708e6ccafaeSMatthew G Knepley pointing up at the second. 2709e6ccafaeSMatthew G Knepley 2710e6ccafaeSMatthew G Knepley 7---6 2711e6ccafaeSMatthew G Knepley /| /| 2712e6ccafaeSMatthew G Knepley 4---5 | 2713ddeab2a6SMatthew G. Knepley | 1-|-2 2714e6ccafaeSMatthew G Knepley |/ |/ 2715ddeab2a6SMatthew G. Knepley 0---3 2716e6ccafaeSMatthew G Knepley 2717e6ccafaeSMatthew G Knepley Faces are determined by the first 4 vertices (corners of faces) */ 2718e6ccafaeSMatthew G Knepley const PetscInt faceSizeHex = 4; 2719e6ccafaeSMatthew G Knepley PetscInt sortedIndices[4], i, iFace; 2720e6ccafaeSMatthew G Knepley PetscBool found = PETSC_FALSE; 2721e6ccafaeSMatthew G Knepley PetscInt faceVerticesHexSorted[24] = { 2722e6ccafaeSMatthew G Knepley 0, 1, 2, 3, /* bottom */ 2723e6ccafaeSMatthew G Knepley 4, 5, 6, 7, /* top */ 2724ddeab2a6SMatthew G. Knepley 0, 3, 4, 5, /* front */ 2725ddeab2a6SMatthew G. Knepley 2, 3, 5, 6, /* right */ 2726ddeab2a6SMatthew G. Knepley 1, 2, 6, 7, /* back */ 2727ddeab2a6SMatthew G. Knepley 0, 1, 4, 7, /* left */ 2728e6ccafaeSMatthew G Knepley }; 2729e6ccafaeSMatthew G Knepley PetscInt faceVerticesHex[24] = { 2730ddeab2a6SMatthew G. Knepley 1, 2, 3, 0, /* bottom */ 2731e6ccafaeSMatthew G Knepley 4, 5, 6, 7, /* top */ 2732ddeab2a6SMatthew G. Knepley 0, 3, 5, 4, /* front */ 2733ddeab2a6SMatthew G. Knepley 3, 2, 6, 5, /* right */ 2734ddeab2a6SMatthew G. Knepley 2, 1, 7, 6, /* back */ 2735ddeab2a6SMatthew G. Knepley 1, 0, 4, 7, /* left */ 2736e6ccafaeSMatthew G Knepley }; 2737e6ccafaeSMatthew G Knepley 2738e6ccafaeSMatthew G Knepley for (i = 0; i < faceSizeHex; ++i) sortedIndices[i] = indices[i]; 27399566063dSJacob Faibussowitsch PetscCall(PetscSortInt(faceSizeHex, sortedIndices)); 2740e6ccafaeSMatthew G Knepley for (iFace = 0; iFace < 6; ++iFace) { 2741e6ccafaeSMatthew G Knepley const PetscInt ii = iFace * faceSizeHex; 2742e6ccafaeSMatthew G Knepley PetscInt fVertex, cVertex; 2743e6ccafaeSMatthew G Knepley 27449371c9d4SSatish Balay if ((sortedIndices[0] == faceVerticesHexSorted[ii + 0]) && (sortedIndices[1] == faceVerticesHexSorted[ii + 1]) && (sortedIndices[2] == faceVerticesHexSorted[ii + 2]) && (sortedIndices[3] == faceVerticesHexSorted[ii + 3])) { 2745e6ccafaeSMatthew G Knepley for (fVertex = 0; fVertex < faceSizeHex; ++fVertex) { 2746e6ccafaeSMatthew G Knepley for (cVertex = 0; cVertex < faceSizeHex; ++cVertex) { 2747e6ccafaeSMatthew G Knepley if (indices[cVertex] == faceVerticesHex[ii + fVertex]) { 2748e6ccafaeSMatthew G Knepley faceVertices[fVertex] = origVertices[cVertex]; 2749e6ccafaeSMatthew G Knepley break; 2750e6ccafaeSMatthew G Knepley } 2751e6ccafaeSMatthew G Knepley } 2752e6ccafaeSMatthew G Knepley } 2753e6ccafaeSMatthew G Knepley found = PETSC_TRUE; 2754e6ccafaeSMatthew G Knepley break; 2755e6ccafaeSMatthew G Knepley } 2756e6ccafaeSMatthew G Knepley } 275728b400f6SJacob Faibussowitsch PetscCheck(found, comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 2758e6ccafaeSMatthew G Knepley if (posOriented) *posOriented = PETSC_TRUE; 2759e6ccafaeSMatthew G Knepley PetscFunctionReturn(0); 2760e6ccafaeSMatthew G Knepley } else if (cellDim == 3 && numCorners == 10) { 2761e6ccafaeSMatthew G Knepley /* Quadratic tet */ 2762e6ccafaeSMatthew G Knepley /* Faces are determined by the first 3 vertices (corners of faces) */ 2763e6ccafaeSMatthew G Knepley const PetscInt faceSizeTet = 6; 2764e6ccafaeSMatthew G Knepley PetscInt sortedIndices[6], i, iFace; 2765e6ccafaeSMatthew G Knepley PetscBool found = PETSC_FALSE; 2766e6ccafaeSMatthew G Knepley PetscInt faceVerticesTetSorted[24] = { 2767e6ccafaeSMatthew G Knepley 0, 1, 2, 6, 7, 8, /* bottom */ 2768e6ccafaeSMatthew G Knepley 0, 3, 4, 6, 7, 9, /* front */ 2769e6ccafaeSMatthew G Knepley 1, 4, 5, 7, 8, 9, /* right */ 2770e6ccafaeSMatthew G Knepley 2, 3, 5, 6, 8, 9, /* left */ 2771e6ccafaeSMatthew G Knepley }; 2772e6ccafaeSMatthew G Knepley PetscInt faceVerticesTet[24] = { 2773e6ccafaeSMatthew G Knepley 0, 1, 2, 6, 7, 8, /* bottom */ 2774e6ccafaeSMatthew G Knepley 0, 4, 3, 6, 7, 9, /* front */ 2775e6ccafaeSMatthew G Knepley 1, 5, 4, 7, 8, 9, /* right */ 2776e6ccafaeSMatthew G Knepley 2, 3, 5, 8, 6, 9, /* left */ 2777e6ccafaeSMatthew G Knepley }; 2778e6ccafaeSMatthew G Knepley 2779e6ccafaeSMatthew G Knepley for (i = 0; i < faceSizeTet; ++i) sortedIndices[i] = indices[i]; 27809566063dSJacob Faibussowitsch PetscCall(PetscSortInt(faceSizeTet, sortedIndices)); 2781e6ccafaeSMatthew G Knepley for (iFace = 0; iFace < 4; ++iFace) { 2782e6ccafaeSMatthew G Knepley const PetscInt ii = iFace * faceSizeTet; 2783e6ccafaeSMatthew G Knepley PetscInt fVertex, cVertex; 2784e6ccafaeSMatthew G Knepley 27859371c9d4SSatish Balay if ((sortedIndices[0] == faceVerticesTetSorted[ii + 0]) && (sortedIndices[1] == faceVerticesTetSorted[ii + 1]) && (sortedIndices[2] == faceVerticesTetSorted[ii + 2]) && (sortedIndices[3] == faceVerticesTetSorted[ii + 3])) { 2786e6ccafaeSMatthew G Knepley for (fVertex = 0; fVertex < faceSizeTet; ++fVertex) { 2787e6ccafaeSMatthew G Knepley for (cVertex = 0; cVertex < faceSizeTet; ++cVertex) { 2788e6ccafaeSMatthew G Knepley if (indices[cVertex] == faceVerticesTet[ii + fVertex]) { 2789e6ccafaeSMatthew G Knepley faceVertices[fVertex] = origVertices[cVertex]; 2790e6ccafaeSMatthew G Knepley break; 2791e6ccafaeSMatthew G Knepley } 2792e6ccafaeSMatthew G Knepley } 2793e6ccafaeSMatthew G Knepley } 2794e6ccafaeSMatthew G Knepley found = PETSC_TRUE; 2795e6ccafaeSMatthew G Knepley break; 2796e6ccafaeSMatthew G Knepley } 2797e6ccafaeSMatthew G Knepley } 279828b400f6SJacob Faibussowitsch PetscCheck(found, comm, PETSC_ERR_ARG_WRONG, "Invalid tet crossface"); 2799e6ccafaeSMatthew G Knepley if (posOriented) *posOriented = PETSC_TRUE; 2800e6ccafaeSMatthew G Knepley PetscFunctionReturn(0); 2801e6ccafaeSMatthew G Knepley } else if (cellDim == 3 && numCorners == 27) { 2802e6ccafaeSMatthew G Knepley /* Quadratic hexes (I hate this) 2803e6ccafaeSMatthew G Knepley A hex is two oriented quads with the normal of the first 2804e6ccafaeSMatthew G Knepley pointing up at the second. 2805e6ccafaeSMatthew G Knepley 2806e6ccafaeSMatthew G Knepley 7---6 2807e6ccafaeSMatthew G Knepley /| /| 2808e6ccafaeSMatthew G Knepley 4---5 | 2809e6ccafaeSMatthew G Knepley | 3-|-2 2810e6ccafaeSMatthew G Knepley |/ |/ 2811e6ccafaeSMatthew G Knepley 0---1 2812e6ccafaeSMatthew G Knepley 2813e6ccafaeSMatthew G Knepley Faces are determined by the first 4 vertices (corners of faces) */ 2814e6ccafaeSMatthew G Knepley const PetscInt faceSizeQuadHex = 9; 2815e6ccafaeSMatthew G Knepley PetscInt sortedIndices[9], i, iFace; 2816e6ccafaeSMatthew G Knepley PetscBool found = PETSC_FALSE; 2817e6ccafaeSMatthew G Knepley PetscInt faceVerticesQuadHexSorted[54] = { 2818e6ccafaeSMatthew G Knepley 0, 1, 2, 3, 8, 9, 10, 11, 24, /* bottom */ 2819e6ccafaeSMatthew G Knepley 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 2820e6ccafaeSMatthew G Knepley 0, 1, 4, 5, 8, 12, 16, 17, 22, /* front */ 2821e6ccafaeSMatthew G Knepley 1, 2, 5, 6, 9, 13, 17, 18, 21, /* right */ 2822e6ccafaeSMatthew G Knepley 2, 3, 6, 7, 10, 14, 18, 19, 23, /* back */ 2823e6ccafaeSMatthew G Knepley 0, 3, 4, 7, 11, 15, 16, 19, 20, /* left */ 2824e6ccafaeSMatthew G Knepley }; 2825e6ccafaeSMatthew G Knepley PetscInt faceVerticesQuadHex[54] = { 2826e6ccafaeSMatthew G Knepley 3, 2, 1, 0, 10, 9, 8, 11, 24, /* bottom */ 2827e6ccafaeSMatthew G Knepley 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 2828e6ccafaeSMatthew G Knepley 0, 1, 5, 4, 8, 17, 12, 16, 22, /* front */ 2829e6ccafaeSMatthew G Knepley 1, 2, 6, 5, 9, 18, 13, 17, 21, /* right */ 2830e6ccafaeSMatthew G Knepley 2, 3, 7, 6, 10, 19, 14, 18, 23, /* back */ 2831e6ccafaeSMatthew G Knepley 3, 0, 4, 7, 11, 16, 15, 19, 20 /* left */ 2832e6ccafaeSMatthew G Knepley }; 2833e6ccafaeSMatthew G Knepley 2834e6ccafaeSMatthew G Knepley for (i = 0; i < faceSizeQuadHex; ++i) sortedIndices[i] = indices[i]; 28359566063dSJacob Faibussowitsch PetscCall(PetscSortInt(faceSizeQuadHex, sortedIndices)); 2836e6ccafaeSMatthew G Knepley for (iFace = 0; iFace < 6; ++iFace) { 2837e6ccafaeSMatthew G Knepley const PetscInt ii = iFace * faceSizeQuadHex; 2838e6ccafaeSMatthew G Knepley PetscInt fVertex, cVertex; 2839e6ccafaeSMatthew G Knepley 28409371c9d4SSatish Balay if ((sortedIndices[0] == faceVerticesQuadHexSorted[ii + 0]) && (sortedIndices[1] == faceVerticesQuadHexSorted[ii + 1]) && (sortedIndices[2] == faceVerticesQuadHexSorted[ii + 2]) && (sortedIndices[3] == faceVerticesQuadHexSorted[ii + 3])) { 2841e6ccafaeSMatthew G Knepley for (fVertex = 0; fVertex < faceSizeQuadHex; ++fVertex) { 2842e6ccafaeSMatthew G Knepley for (cVertex = 0; cVertex < faceSizeQuadHex; ++cVertex) { 2843e6ccafaeSMatthew G Knepley if (indices[cVertex] == faceVerticesQuadHex[ii + fVertex]) { 2844e6ccafaeSMatthew G Knepley faceVertices[fVertex] = origVertices[cVertex]; 2845e6ccafaeSMatthew G Knepley break; 2846e6ccafaeSMatthew G Knepley } 2847e6ccafaeSMatthew G Knepley } 2848e6ccafaeSMatthew G Knepley } 2849e6ccafaeSMatthew G Knepley found = PETSC_TRUE; 2850e6ccafaeSMatthew G Knepley break; 2851e6ccafaeSMatthew G Knepley } 2852e6ccafaeSMatthew G Knepley } 285328b400f6SJacob Faibussowitsch PetscCheck(found, comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 2854e6ccafaeSMatthew G Knepley if (posOriented) *posOriented = PETSC_TRUE; 2855e6ccafaeSMatthew G Knepley PetscFunctionReturn(0); 2856e6ccafaeSMatthew G Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unknown cell type for faceOrientation()."); 2857e6ccafaeSMatthew G Knepley if (!posOrient) { 28589566063dSJacob Faibussowitsch if (debug) PetscCall(PetscPrintf(comm, " Reversing initial face orientation\n")); 2859e6ccafaeSMatthew G Knepley for (f = 0; f < faceSize; ++f) faceVertices[f] = origVertices[faceSize - 1 - f]; 2860e6ccafaeSMatthew G Knepley } else { 28619566063dSJacob Faibussowitsch if (debug) PetscCall(PetscPrintf(comm, " Keeping initial face orientation\n")); 2862e6ccafaeSMatthew G Knepley for (f = 0; f < faceSize; ++f) faceVertices[f] = origVertices[f]; 2863e6ccafaeSMatthew G Knepley } 2864e6ccafaeSMatthew G Knepley if (posOriented) *posOriented = posOrient; 2865e6ccafaeSMatthew G Knepley PetscFunctionReturn(0); 2866e6ccafaeSMatthew G Knepley } 2867e6ccafaeSMatthew G Knepley 2868c08575a3SMatthew G. Knepley /*@ 2869c08575a3SMatthew G. Knepley DMPlexGetOrientedFace - Given a cell and a face, as a set of vertices, return the oriented face, as a set of vertices, 2870c08575a3SMatthew G. Knepley in faceVertices. The orientation is such that the face normal points out of the cell 2871c08575a3SMatthew G. Knepley 2872c08575a3SMatthew G. Knepley Not collective 2873c08575a3SMatthew G. Knepley 2874c08575a3SMatthew G. Knepley Input Parameters: 2875c08575a3SMatthew G. Knepley + dm - The original mesh 2876c08575a3SMatthew G. Knepley . cell - The cell mesh point 2877c08575a3SMatthew G. Knepley . faceSize - The number of vertices on the face 2878c08575a3SMatthew G. Knepley . face - The face vertices 2879c08575a3SMatthew G. Knepley . numCorners - The number of vertices on the cell 2880c08575a3SMatthew G. Knepley . indices - Local numbering of face vertices in cell cone 2881c08575a3SMatthew G. Knepley - origVertices - Original face vertices 2882c08575a3SMatthew G. Knepley 2883d8d19677SJose E. Roman Output Parameters: 2884c08575a3SMatthew G. Knepley + faceVertices - The face vertices properly oriented 2885c08575a3SMatthew G. Knepley - posOriented - PETSC_TRUE if the face was oriented with outward normal 2886c08575a3SMatthew G. Knepley 2887c08575a3SMatthew G. Knepley Level: developer 2888c08575a3SMatthew G. Knepley 2889db781477SPatrick Sanan .seealso: `DMPlexGetCone()` 2890c08575a3SMatthew G. Knepley @*/ 2891d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetOrientedFace(DM dm, PetscInt cell, PetscInt faceSize, const PetscInt face[], PetscInt numCorners, PetscInt indices[], PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 2892d71ae5a4SJacob Faibussowitsch { 28930298fd71SBarry Smith const PetscInt *cone = NULL; 2894e6ccafaeSMatthew G Knepley PetscInt coneSize, v, f, v2; 2895e6ccafaeSMatthew G Knepley PetscInt oppositeVertex = -1; 2896e6ccafaeSMatthew G Knepley 2897e6ccafaeSMatthew G Knepley PetscFunctionBegin; 28989566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cell, &coneSize)); 28999566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cell, &cone)); 2900e6ccafaeSMatthew G Knepley for (v = 0, v2 = 0; v < coneSize; ++v) { 2901e6ccafaeSMatthew G Knepley PetscBool found = PETSC_FALSE; 2902e6ccafaeSMatthew G Knepley 2903e6ccafaeSMatthew G Knepley for (f = 0; f < faceSize; ++f) { 2904e6ccafaeSMatthew G Knepley if (face[f] == cone[v]) { 29059371c9d4SSatish Balay found = PETSC_TRUE; 29069371c9d4SSatish Balay break; 2907e6ccafaeSMatthew G Knepley } 2908e6ccafaeSMatthew G Knepley } 2909e6ccafaeSMatthew G Knepley if (found) { 2910e6ccafaeSMatthew G Knepley indices[v2] = v; 2911e6ccafaeSMatthew G Knepley origVertices[v2] = cone[v]; 2912e6ccafaeSMatthew G Knepley ++v2; 2913e6ccafaeSMatthew G Knepley } else { 2914e6ccafaeSMatthew G Knepley oppositeVertex = v; 2915e6ccafaeSMatthew G Knepley } 2916e6ccafaeSMatthew G Knepley } 29179566063dSJacob Faibussowitsch PetscCall(DMPlexGetFaceOrientation(dm, cell, numCorners, indices, oppositeVertex, origVertices, faceVertices, posOriented)); 2918e6ccafaeSMatthew G Knepley PetscFunctionReturn(0); 2919e6ccafaeSMatthew G Knepley } 2920e6ccafaeSMatthew G Knepley 2921e6ccafaeSMatthew G Knepley /* 2922cd0c2139SMatthew G Knepley DMPlexInsertFace_Internal - Puts a face into the mesh 2923e6ccafaeSMatthew G Knepley 2924e6ccafaeSMatthew G Knepley Not collective 2925e6ccafaeSMatthew G Knepley 2926e6ccafaeSMatthew G Knepley Input Parameters: 2927e6ccafaeSMatthew G Knepley + dm - The DMPlex 2928e6ccafaeSMatthew G Knepley . numFaceVertex - The number of vertices in the face 2929e6ccafaeSMatthew G Knepley . faceVertices - The vertices in the face for dm 2930e6ccafaeSMatthew G Knepley . subfaceVertices - The vertices in the face for subdm 2931e6ccafaeSMatthew G Knepley . numCorners - The number of vertices in the cell 2932e6ccafaeSMatthew G Knepley . cell - A cell in dm containing the face 2933e6ccafaeSMatthew G Knepley . subcell - A cell in subdm containing the face 2934e6ccafaeSMatthew G Knepley . firstFace - First face in the mesh 2935e6ccafaeSMatthew G Knepley - newFacePoint - Next face in the mesh 2936e6ccafaeSMatthew G Knepley 2937e6ccafaeSMatthew G Knepley Output Parameters: 2938e6ccafaeSMatthew G Knepley . newFacePoint - Contains next face point number on input, updated on output 2939e6ccafaeSMatthew G Knepley 2940e6ccafaeSMatthew G Knepley Level: developer 2941e6ccafaeSMatthew G Knepley */ 2942d71ae5a4SJacob Faibussowitsch 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) 2943d71ae5a4SJacob Faibussowitsch { 294482f516ccSBarry Smith MPI_Comm comm; 2945e6ccafaeSMatthew G Knepley DM_Plex *submesh = (DM_Plex *)subdm->data; 2946e6ccafaeSMatthew G Knepley const PetscInt *faces; 2947e6ccafaeSMatthew G Knepley PetscInt numFaces, coneSize; 2948e6ccafaeSMatthew G Knepley 2949e6ccafaeSMatthew G Knepley PetscFunctionBegin; 29509566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 29519566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(subdm, subcell, &coneSize)); 295263a3b9bcSJacob Faibussowitsch PetscCheck(coneSize == 1, comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size of cell %" PetscInt_FMT " is %" PetscInt_FMT " != 1", cell, coneSize); 2953e6ccafaeSMatthew G Knepley #if 0 2954e6ccafaeSMatthew G Knepley /* Cannot use this because support() has not been constructed yet */ 29559566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces)); 2956e6ccafaeSMatthew G Knepley #else 2957e6ccafaeSMatthew G Knepley { 2958e6ccafaeSMatthew G Knepley PetscInt f; 2959e6ccafaeSMatthew G Knepley 2960e6ccafaeSMatthew G Knepley numFaces = 0; 29619566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(subdm, 1, MPIU_INT, (void **)&faces)); 2962e6ccafaeSMatthew G Knepley for (f = firstFace; f < *newFacePoint; ++f) { 2963e6ccafaeSMatthew G Knepley PetscInt dof, off, d; 2964e6ccafaeSMatthew G Knepley 29659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(submesh->coneSection, f, &dof)); 29669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(submesh->coneSection, f, &off)); 2967e6ccafaeSMatthew G Knepley /* Yes, I know this is quadratic, but I expect the sizes to be <5 */ 2968e6ccafaeSMatthew G Knepley for (d = 0; d < dof; ++d) { 2969e6ccafaeSMatthew G Knepley const PetscInt p = submesh->cones[off + d]; 2970e6ccafaeSMatthew G Knepley PetscInt v; 2971e6ccafaeSMatthew G Knepley 2972e6ccafaeSMatthew G Knepley for (v = 0; v < numFaceVertices; ++v) { 2973e6ccafaeSMatthew G Knepley if (subfaceVertices[v] == p) break; 2974e6ccafaeSMatthew G Knepley } 2975e6ccafaeSMatthew G Knepley if (v == numFaceVertices) break; 2976e6ccafaeSMatthew G Knepley } 2977e6ccafaeSMatthew G Knepley if (d == dof) { 2978e6ccafaeSMatthew G Knepley numFaces = 1; 2979e6ccafaeSMatthew G Knepley ((PetscInt *)faces)[0] = f; 2980e6ccafaeSMatthew G Knepley } 2981e6ccafaeSMatthew G Knepley } 2982e6ccafaeSMatthew G Knepley } 2983e6ccafaeSMatthew G Knepley #endif 298463a3b9bcSJacob Faibussowitsch PetscCheck(numFaces <= 1, comm, PETSC_ERR_ARG_WRONG, "Vertex set had %" PetscInt_FMT " faces, not one", numFaces); 2985f7d195e4SLawrence Mitchell if (numFaces == 1) { 2986e6ccafaeSMatthew G Knepley /* Add the other cell neighbor for this face */ 29879566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(subdm, subcell, faces)); 2988e6ccafaeSMatthew G Knepley } else { 2989e6ccafaeSMatthew G Knepley PetscInt *indices, *origVertices, *orientedVertices, *orientedSubVertices, v, ov; 2990e6ccafaeSMatthew G Knepley PetscBool posOriented; 2991e6ccafaeSMatthew G Knepley 29929566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(subdm, 4 * numFaceVertices * sizeof(PetscInt), MPIU_INT, &orientedVertices)); 2993e6ccafaeSMatthew G Knepley origVertices = &orientedVertices[numFaceVertices]; 2994e6ccafaeSMatthew G Knepley indices = &orientedVertices[numFaceVertices * 2]; 2995e6ccafaeSMatthew G Knepley orientedSubVertices = &orientedVertices[numFaceVertices * 3]; 29969566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrientedFace(dm, cell, numFaceVertices, faceVertices, numCorners, indices, origVertices, orientedVertices, &posOriented)); 2997e6ccafaeSMatthew G Knepley /* TODO: I know that routine should return a permutation, not the indices */ 2998e6ccafaeSMatthew G Knepley for (v = 0; v < numFaceVertices; ++v) { 2999e6ccafaeSMatthew G Knepley const PetscInt vertex = faceVertices[v], subvertex = subfaceVertices[v]; 3000e6ccafaeSMatthew G Knepley for (ov = 0; ov < numFaceVertices; ++ov) { 3001e6ccafaeSMatthew G Knepley if (orientedVertices[ov] == vertex) { 3002e6ccafaeSMatthew G Knepley orientedSubVertices[ov] = subvertex; 3003e6ccafaeSMatthew G Knepley break; 3004e6ccafaeSMatthew G Knepley } 3005e6ccafaeSMatthew G Knepley } 300663a3b9bcSJacob Faibussowitsch PetscCheck(ov != numFaceVertices, comm, PETSC_ERR_PLIB, "Could not find face vertex %" PetscInt_FMT " in orientated set", vertex); 3007e6ccafaeSMatthew G Knepley } 30089566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(subdm, *newFacePoint, orientedSubVertices)); 30099566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(subdm, subcell, newFacePoint)); 30109566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(subdm, 4 * numFaceVertices * sizeof(PetscInt), MPIU_INT, &orientedVertices)); 3011e6ccafaeSMatthew G Knepley ++(*newFacePoint); 3012e6ccafaeSMatthew G Knepley } 3013ef07cca7SMatthew G. Knepley #if 0 30149566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces)); 3015ef07cca7SMatthew G. Knepley #else 30169566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(subdm, 1, MPIU_INT, (void **)&faces)); 3017ef07cca7SMatthew G. Knepley #endif 3018e6ccafaeSMatthew G Knepley PetscFunctionReturn(0); 3019e6ccafaeSMatthew G Knepley } 3020e6ccafaeSMatthew G Knepley 3021d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSubmesh_Uninterpolated(DM dm, DMLabel vertexLabel, PetscInt value, DM subdm) 3022d71ae5a4SJacob Faibussowitsch { 302382f516ccSBarry Smith MPI_Comm comm; 302453156dfcSMatthew G. Knepley DMLabel subpointMap; 3025efa14ee0SMatthew G Knepley IS subvertexIS, subcellIS; 3026efa14ee0SMatthew G Knepley const PetscInt *subVertices, *subCells; 3027efa14ee0SMatthew G Knepley PetscInt numSubVertices, firstSubVertex, numSubCells; 3028fed694aaSMatthew G. Knepley PetscInt *subface, maxConeSize, numSubFaces = 0, firstSubFace, newFacePoint, nFV = 0; 3029efa14ee0SMatthew G Knepley PetscInt vStart, vEnd, c, f; 3030e6ccafaeSMatthew G Knepley 3031e6ccafaeSMatthew G Knepley PetscFunctionBegin; 30329566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 3033efa14ee0SMatthew G Knepley /* Create subpointMap which marks the submesh */ 30349566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "subpoint_map", &subpointMap)); 30359566063dSJacob Faibussowitsch PetscCall(DMPlexSetSubpointMap(subdm, subpointMap)); 30369566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&subpointMap)); 30379566063dSJacob Faibussowitsch if (vertexLabel) PetscCall(DMPlexMarkSubmesh_Uninterpolated(dm, vertexLabel, value, subpointMap, &numSubFaces, &nFV, subdm)); 3038efa14ee0SMatthew G Knepley /* Setup chart */ 30399566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(subpointMap, 0, &numSubVertices)); 30409566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(subpointMap, 2, &numSubCells)); 30419566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(subdm, 0, numSubCells + numSubFaces + numSubVertices)); 30429566063dSJacob Faibussowitsch PetscCall(DMPlexSetVTKCellHeight(subdm, 1)); 3043e6ccafaeSMatthew G Knepley /* Set cone sizes */ 3044e6ccafaeSMatthew G Knepley firstSubVertex = numSubCells; 3045efa14ee0SMatthew G Knepley firstSubFace = numSubCells + numSubVertices; 3046e6ccafaeSMatthew G Knepley newFacePoint = firstSubFace; 30479566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(subpointMap, 0, &subvertexIS)); 30489566063dSJacob Faibussowitsch if (subvertexIS) PetscCall(ISGetIndices(subvertexIS, &subVertices)); 30499566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(subpointMap, 2, &subcellIS)); 30509566063dSJacob Faibussowitsch if (subcellIS) PetscCall(ISGetIndices(subcellIS, &subCells)); 305148a46eb9SPierre Jolivet for (c = 0; c < numSubCells; ++c) PetscCall(DMPlexSetConeSize(subdm, c, 1)); 305248a46eb9SPierre Jolivet for (f = firstSubFace; f < firstSubFace + numSubFaces; ++f) PetscCall(DMPlexSetConeSize(subdm, f, nFV)); 30539566063dSJacob Faibussowitsch PetscCall(DMSetUp(subdm)); 3054e6ccafaeSMatthew G Knepley /* Create face cones */ 30559566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 30569566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, NULL)); 30579566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(subdm, maxConeSize, MPIU_INT, (void **)&subface)); 3058e6ccafaeSMatthew G Knepley for (c = 0; c < numSubCells; ++c) { 3059e6ccafaeSMatthew G Knepley const PetscInt cell = subCells[c]; 3060efa14ee0SMatthew G Knepley const PetscInt subcell = c; 30610298fd71SBarry Smith PetscInt *closure = NULL; 3062efa14ee0SMatthew G Knepley PetscInt closureSize, cl, numCorners = 0, faceSize = 0; 3063e6ccafaeSMatthew G Knepley 30649566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure)); 3065efa14ee0SMatthew G Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 3066efa14ee0SMatthew G Knepley const PetscInt point = closure[cl]; 3067e6ccafaeSMatthew G Knepley PetscInt subVertex; 3068e6ccafaeSMatthew G Knepley 3069efa14ee0SMatthew G Knepley if ((point >= vStart) && (point < vEnd)) { 3070efa14ee0SMatthew G Knepley ++numCorners; 30719566063dSJacob Faibussowitsch PetscCall(PetscFindInt(point, numSubVertices, subVertices, &subVertex)); 3072efa14ee0SMatthew G Knepley if (subVertex >= 0) { 3073efa14ee0SMatthew G Knepley closure[faceSize] = point; 307465560c7fSMatthew G Knepley subface[faceSize] = firstSubVertex + subVertex; 3075e6ccafaeSMatthew G Knepley ++faceSize; 3076e6ccafaeSMatthew G Knepley } 3077e6ccafaeSMatthew G Knepley } 3078e6ccafaeSMatthew G Knepley } 307963a3b9bcSJacob Faibussowitsch PetscCheck(faceSize <= nFV, comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %" PetscInt_FMT " of an element on the surface", faceSize); 308048a46eb9SPierre Jolivet if (faceSize == nFV) PetscCall(DMPlexInsertFace_Internal(dm, subdm, faceSize, closure, subface, numCorners, cell, subcell, firstSubFace, &newFacePoint)); 30819566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure)); 3082e6ccafaeSMatthew G Knepley } 30839566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(subdm, maxConeSize, MPIU_INT, (void **)&subface)); 30849566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(subdm)); 30859566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(subdm)); 3086e6ccafaeSMatthew G Knepley /* Build coordinates */ 3087efa14ee0SMatthew G Knepley { 3088efa14ee0SMatthew G Knepley PetscSection coordSection, subCoordSection; 3089efa14ee0SMatthew G Knepley Vec coordinates, subCoordinates; 3090efa14ee0SMatthew G Knepley PetscScalar *coords, *subCoords; 3091285d324eSMatthew G. Knepley PetscInt numComp, coordSize, v; 309224640c55SToby Isaac const char *name; 3093efa14ee0SMatthew G Knepley 30949566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 30959566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 30969566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(subdm, &subCoordSection)); 30979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(subCoordSection, 1)); 30989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &numComp)); 30999566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(subCoordSection, 0, numComp)); 31009566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex + numSubVertices)); 3101efa14ee0SMatthew G Knepley for (v = 0; v < numSubVertices; ++v) { 3102efa14ee0SMatthew G Knepley const PetscInt vertex = subVertices[v]; 3103efa14ee0SMatthew G Knepley const PetscInt subvertex = firstSubVertex + v; 3104efa14ee0SMatthew G Knepley PetscInt dof; 3105efa14ee0SMatthew G Knepley 31069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, vertex, &dof)); 31079566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(subCoordSection, subvertex, dof)); 31089566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(subCoordSection, subvertex, 0, dof)); 3109e6ccafaeSMatthew G Knepley } 31109566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(subCoordSection)); 31119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(subCoordSection, &coordSize)); 31129566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &subCoordinates)); 31139566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)coordinates, &name)); 31149566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)subCoordinates, name)); 31159566063dSJacob Faibussowitsch PetscCall(VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE)); 31169566063dSJacob Faibussowitsch PetscCall(VecSetType(subCoordinates, VECSTANDARD)); 3117830e53efSMatthew G. Knepley if (coordSize) { 31189566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 31199566063dSJacob Faibussowitsch PetscCall(VecGetArray(subCoordinates, &subCoords)); 3120efa14ee0SMatthew G Knepley for (v = 0; v < numSubVertices; ++v) { 3121efa14ee0SMatthew G Knepley const PetscInt vertex = subVertices[v]; 3122efa14ee0SMatthew G Knepley const PetscInt subvertex = firstSubVertex + v; 3123efa14ee0SMatthew G Knepley PetscInt dof, off, sdof, soff, d; 3124e6ccafaeSMatthew G Knepley 31259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, vertex, &dof)); 31269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, vertex, &off)); 31279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subCoordSection, subvertex, &sdof)); 31289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(subCoordSection, subvertex, &soff)); 312963a3b9bcSJacob Faibussowitsch PetscCheck(dof == sdof, comm, PETSC_ERR_PLIB, "Coordinate dimension %" PetscInt_FMT " on subvertex %" PetscInt_FMT ", vertex %" PetscInt_FMT " should be %" PetscInt_FMT, sdof, subvertex, vertex, dof); 3130e6ccafaeSMatthew G Knepley for (d = 0; d < dof; ++d) subCoords[soff + d] = coords[off + d]; 3131e6ccafaeSMatthew G Knepley } 31329566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 31339566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(subCoordinates, &subCoords)); 31343b399e24SMatthew G. Knepley } 31359566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(subdm, subCoordinates)); 31369566063dSJacob Faibussowitsch PetscCall(VecDestroy(&subCoordinates)); 3137e6ccafaeSMatthew G Knepley } 3138efa14ee0SMatthew G Knepley /* Cleanup */ 31399566063dSJacob Faibussowitsch if (subvertexIS) PetscCall(ISRestoreIndices(subvertexIS, &subVertices)); 31409566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subvertexIS)); 31419566063dSJacob Faibussowitsch if (subcellIS) PetscCall(ISRestoreIndices(subcellIS, &subCells)); 31429566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subcellIS)); 3143e6ccafaeSMatthew G Knepley PetscFunctionReturn(0); 3144e6ccafaeSMatthew G Knepley } 3145e6ccafaeSMatthew G Knepley 3146*d5b43468SJose E. Roman /* TODO: Fix this to properly propagate up error conditions it may find */ 3147d71ae5a4SJacob Faibussowitsch static inline PetscInt DMPlexFilterPoint_Internal(PetscInt point, PetscInt firstSubPoint, PetscInt numSubPoints, const PetscInt subPoints[]) 3148d71ae5a4SJacob Faibussowitsch { 31493982b651SMatthew G. Knepley PetscInt subPoint; 31503982b651SMatthew G. Knepley PetscErrorCode ierr; 31513982b651SMatthew G. Knepley 31529371c9d4SSatish Balay ierr = PetscFindInt(point, numSubPoints, subPoints, &subPoint); 31539371c9d4SSatish Balay if (ierr) return -1; 31543982b651SMatthew G. Knepley return subPoint < 0 ? subPoint : firstSubPoint + subPoint; 31553982b651SMatthew G. Knepley } 31563982b651SMatthew G. Knepley 3157*d5b43468SJose E. Roman /* TODO: Fix this to properly propagate up error conditions it may find */ 3158d71ae5a4SJacob Faibussowitsch static inline PetscInt DMPlexFilterPointPerm_Internal(PetscInt point, PetscInt firstSubPoint, PetscInt numSubPoints, const PetscInt subPoints[], const PetscInt subIndices[]) 3159d71ae5a4SJacob Faibussowitsch { 3160dd05d810SMatthew G. Knepley PetscInt subPoint; 3161dd05d810SMatthew G. Knepley PetscErrorCode ierr; 3162dd05d810SMatthew G. Knepley 3163dd05d810SMatthew G. Knepley ierr = PetscFindInt(point, numSubPoints, subPoints, &subPoint); 3164dd05d810SMatthew G. Knepley if (ierr) return -1; 3165dd05d810SMatthew G. Knepley return subPoint < 0 ? subPoint : firstSubPoint + (subIndices ? subIndices[subPoint] : subPoint); 3166dd05d810SMatthew G. Knepley } 3167dd05d810SMatthew G. Knepley 3168d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexFilterLabels_Internal(DM dm, const PetscInt numSubPoints[], const PetscInt *subpoints[], const PetscInt firstSubPoint[], DM subdm) 3169d71ae5a4SJacob Faibussowitsch { 3170695799ffSMatthew G. Knepley DMLabel depthLabel; 3171212103e5SMatthew Knepley PetscInt Nl, l, d; 3172212103e5SMatthew Knepley 3173212103e5SMatthew Knepley PetscFunctionBegin; 3174695799ffSMatthew G. Knepley // Reset depth label for fast lookup 3175695799ffSMatthew G. Knepley PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 3176695799ffSMatthew G. Knepley PetscCall(DMLabelMakeAllInvalid_Internal(depthLabel)); 31779566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &Nl)); 3178212103e5SMatthew Knepley for (l = 0; l < Nl; ++l) { 3179212103e5SMatthew Knepley DMLabel label, newlabel; 3180212103e5SMatthew Knepley const char *lname; 3181d56405f8SMatthew G. Knepley PetscBool isDepth, isDim, isCelltype, isVTK; 3182212103e5SMatthew Knepley IS valueIS; 3183212103e5SMatthew Knepley const PetscInt *values; 3184212103e5SMatthew Knepley PetscInt Nv, v; 3185212103e5SMatthew Knepley 31869566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &lname)); 31879566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(lname, "depth", &isDepth)); 31889566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(lname, "dim", &isDim)); 31899566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(lname, "celltype", &isCelltype)); 31909566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(lname, "vtk", &isVTK)); 3191d56405f8SMatthew G. Knepley if (isDepth || isDim || isCelltype || isVTK) continue; 31929566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(subdm, lname)); 31939566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, lname, &label)); 31949566063dSJacob Faibussowitsch PetscCall(DMGetLabel(subdm, lname, &newlabel)); 31959566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(label, &v)); 31969566063dSJacob Faibussowitsch PetscCall(DMLabelSetDefaultValue(newlabel, v)); 31979566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 31989566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(valueIS, &Nv)); 31999566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 3200212103e5SMatthew Knepley for (v = 0; v < Nv; ++v) { 3201212103e5SMatthew Knepley IS pointIS; 3202212103e5SMatthew Knepley const PetscInt *points; 3203212103e5SMatthew Knepley PetscInt Np, p; 3204212103e5SMatthew Knepley 32059566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, values[v], &pointIS)); 32069566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &Np)); 32079566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 3208212103e5SMatthew Knepley for (p = 0; p < Np; ++p) { 3209212103e5SMatthew Knepley const PetscInt point = points[p]; 3210212103e5SMatthew Knepley PetscInt subp; 3211212103e5SMatthew Knepley 32129566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, point, &d)); 3213212103e5SMatthew Knepley subp = DMPlexFilterPoint_Internal(point, firstSubPoint[d], numSubPoints[d], subpoints[d]); 32149566063dSJacob Faibussowitsch if (subp >= 0) PetscCall(DMLabelSetValue(newlabel, subp, values[v])); 3215212103e5SMatthew Knepley } 32169566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 32179566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 3218212103e5SMatthew Knepley } 32199566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 32209566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 3221212103e5SMatthew Knepley } 3222212103e5SMatthew Knepley PetscFunctionReturn(0); 3223212103e5SMatthew Knepley } 3224212103e5SMatthew Knepley 3225d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSubmeshGeneric_Interpolated(DM dm, DMLabel label, PetscInt value, PetscBool markedFaces, PetscBool isCohesive, PetscInt cellHeight, DM subdm) 3226d71ae5a4SJacob Faibussowitsch { 322782f516ccSBarry Smith MPI_Comm comm; 322853156dfcSMatthew G. Knepley DMLabel subpointMap; 3229efa14ee0SMatthew G Knepley IS *subpointIS; 3230efa14ee0SMatthew G Knepley const PetscInt **subpoints; 32313982b651SMatthew G. Knepley PetscInt *numSubPoints, *firstSubPoint, *coneNew, *orntNew; 3232dd05d810SMatthew G. Knepley PetscInt totSubPoints = 0, maxConeSize, dim, sdim, cdim, p, d, v; 32330d366550SMatthew G. Knepley PetscMPIInt rank; 3234e6ccafaeSMatthew G Knepley 3235e6ccafaeSMatthew G Knepley PetscFunctionBegin; 32369566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 32379566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 3238efa14ee0SMatthew G Knepley /* Create subpointMap which marks the submesh */ 32399566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "subpoint_map", &subpointMap)); 32409566063dSJacob Faibussowitsch PetscCall(DMPlexSetSubpointMap(subdm, subpointMap)); 3241bec263e5SMatthew G. Knepley if (cellHeight) { 32429566063dSJacob Faibussowitsch if (isCohesive) PetscCall(DMPlexMarkCohesiveSubmesh_Interpolated(dm, label, value, subpointMap, subdm)); 32439566063dSJacob Faibussowitsch else PetscCall(DMPlexMarkSubmesh_Interpolated(dm, label, value, markedFaces, subpointMap, subdm)); 3244bec263e5SMatthew G. Knepley } else { 3245bec263e5SMatthew G. Knepley DMLabel depth; 3246bec263e5SMatthew G. Knepley IS pointIS; 3247bec263e5SMatthew G. Knepley const PetscInt *points; 3248b85c8bf9SMatthew G. Knepley PetscInt numPoints = 0; 3249bec263e5SMatthew G. Knepley 32509566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depth)); 32519566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, value, &pointIS)); 3252b85c8bf9SMatthew G. Knepley if (pointIS) { 32539566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 32549566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &numPoints)); 3255b85c8bf9SMatthew G. Knepley } 3256bec263e5SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 3257bec263e5SMatthew G. Knepley PetscInt *closure = NULL; 3258bec263e5SMatthew G. Knepley PetscInt closureSize, c, pdim; 3259bec263e5SMatthew G. Knepley 32609566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure)); 3261bec263e5SMatthew G. Knepley for (c = 0; c < closureSize * 2; c += 2) { 32629566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depth, closure[c], &pdim)); 32639566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(subpointMap, closure[c], pdim)); 3264bec263e5SMatthew G. Knepley } 32659566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure)); 3266bec263e5SMatthew G. Knepley } 32679566063dSJacob Faibussowitsch if (pointIS) PetscCall(ISRestoreIndices(pointIS, &points)); 32689566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 3269bec263e5SMatthew G. Knepley } 3270efa14ee0SMatthew G Knepley /* Setup chart */ 32719566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 3272dd05d810SMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim)); 32739566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(dim + 1, &numSubPoints, dim + 1, &firstSubPoint, dim + 1, &subpointIS, dim + 1, &subpoints)); 3274e6ccafaeSMatthew G Knepley for (d = 0; d <= dim; ++d) { 32759566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(subpointMap, d, &numSubPoints[d])); 3276e6ccafaeSMatthew G Knepley totSubPoints += numSubPoints[d]; 3277e6ccafaeSMatthew G Knepley } 3278dd05d810SMatthew G. Knepley // Determine submesh dimension 3279dd05d810SMatthew G. Knepley PetscCall(DMGetDimension(subdm, &sdim)); 3280dd05d810SMatthew G. Knepley if (sdim > 0) { 3281dd05d810SMatthew G. Knepley // Calling function knows what dimension to use, and we include neighboring cells as well 3282dd05d810SMatthew G. Knepley sdim = dim; 3283dd05d810SMatthew G. Knepley } else { 3284dd05d810SMatthew G. Knepley // We reset the subdimension based on what is being selected 3285dd05d810SMatthew G. Knepley PetscInt lsdim; 3286dd05d810SMatthew G. Knepley for (lsdim = dim; lsdim >= 0; --lsdim) 3287dd05d810SMatthew G. Knepley if (numSubPoints[lsdim]) break; 3288dd05d810SMatthew G. Knepley PetscCall(MPI_Allreduce(&lsdim, &sdim, 1, MPIU_INT, MPIU_MAX, comm)); 3289dd05d810SMatthew G. Knepley PetscCall(DMSetDimension(subdm, sdim)); 3290dd05d810SMatthew G. Knepley PetscCall(DMSetCoordinateDim(subdm, cdim)); 3291dd05d810SMatthew G. Knepley } 32929566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(subdm, 0, totSubPoints)); 32939566063dSJacob Faibussowitsch PetscCall(DMPlexSetVTKCellHeight(subdm, cellHeight)); 3294e6ccafaeSMatthew G Knepley /* Set cone sizes */ 3295dd05d810SMatthew G. Knepley firstSubPoint[sdim] = 0; 3296dd05d810SMatthew G. Knepley firstSubPoint[0] = firstSubPoint[sdim] + numSubPoints[sdim]; 3297dd05d810SMatthew G. Knepley if (sdim > 1) firstSubPoint[sdim - 1] = firstSubPoint[0] + numSubPoints[0]; 3298dd05d810SMatthew G. Knepley if (sdim > 2) firstSubPoint[sdim - 2] = firstSubPoint[sdim - 1] + numSubPoints[sdim - 1]; 3299dd05d810SMatthew G. Knepley for (d = 0; d <= sdim; ++d) { 33009566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(subpointMap, d, &subpointIS[d])); 33019566063dSJacob Faibussowitsch if (subpointIS[d]) PetscCall(ISGetIndices(subpointIS[d], &subpoints[d])); 3302e6ccafaeSMatthew G Knepley } 3303412e9a14SMatthew G. Knepley /* We do not want this label automatically computed, instead we compute it here */ 33049566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(subdm, "celltype")); 3305dd05d810SMatthew G. Knepley for (d = 0; d <= sdim; ++d) { 3306e6ccafaeSMatthew G Knepley for (p = 0; p < numSubPoints[d]; ++p) { 3307e6ccafaeSMatthew G Knepley const PetscInt point = subpoints[d][p]; 3308e6ccafaeSMatthew G Knepley const PetscInt subpoint = firstSubPoint[d] + p; 3309e6ccafaeSMatthew G Knepley const PetscInt *cone; 331015100a53SVaclav Hapla PetscInt coneSize; 3311e6ccafaeSMatthew G Knepley 33129566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 3313dd05d810SMatthew G. Knepley if (cellHeight && (d == sdim)) { 331415100a53SVaclav Hapla PetscInt coneSizeNew, c, val; 331515100a53SVaclav Hapla 33169566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 3317e6ccafaeSMatthew G Knepley for (c = 0, coneSizeNew = 0; c < coneSize; ++c) { 33189566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(subpointMap, cone[c], &val)); 3319e6ccafaeSMatthew G Knepley if (val >= 0) coneSizeNew++; 3320e6ccafaeSMatthew G Knepley } 33219566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(subdm, subpoint, coneSizeNew)); 33229566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(subdm, subpoint, DM_POLYTOPE_FV_GHOST)); 332315100a53SVaclav Hapla } else { 332415100a53SVaclav Hapla DMPolytopeType ct; 332515100a53SVaclav Hapla 332615100a53SVaclav Hapla PetscCall(DMPlexSetConeSize(subdm, subpoint, coneSize)); 332715100a53SVaclav Hapla PetscCall(DMPlexGetCellType(dm, point, &ct)); 332815100a53SVaclav Hapla PetscCall(DMPlexSetCellType(subdm, subpoint, ct)); 3329e6ccafaeSMatthew G Knepley } 3330e6ccafaeSMatthew G Knepley } 3331e6ccafaeSMatthew G Knepley } 33329566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&subpointMap)); 33339566063dSJacob Faibussowitsch PetscCall(DMSetUp(subdm)); 3334e6ccafaeSMatthew G Knepley /* Set cones */ 33359566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, NULL)); 33369566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(maxConeSize, &coneNew, maxConeSize, &orntNew)); 3337dd05d810SMatthew G. Knepley for (d = 0; d <= sdim; ++d) { 3338e6ccafaeSMatthew G Knepley for (p = 0; p < numSubPoints[d]; ++p) { 3339e6ccafaeSMatthew G Knepley const PetscInt point = subpoints[d][p]; 3340e6ccafaeSMatthew G Knepley const PetscInt subpoint = firstSubPoint[d] + p; 33410e49e2e2SMatthew G. Knepley const PetscInt *cone, *ornt; 33420d366550SMatthew G. Knepley PetscInt coneSize, subconeSize, coneSizeNew, c, subc, fornt = 0; 3343e6ccafaeSMatthew G Knepley 3344dd05d810SMatthew G. Knepley if (d == sdim - 1) { 33450d366550SMatthew G. Knepley const PetscInt *support, *cone, *ornt; 33460d366550SMatthew G. Knepley PetscInt supportSize, coneSize, s, subc; 33470d366550SMatthew G. Knepley 33489566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, point, &support)); 33499566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, point, &supportSize)); 33500d366550SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 3351064cae4fSPierre Jolivet PetscBool isHybrid = PETSC_FALSE; 3352412e9a14SMatthew G. Knepley 33539566063dSJacob Faibussowitsch PetscCall(DMPlexCellIsHybrid_Internal(dm, support[s], &isHybrid)); 3354412e9a14SMatthew G. Knepley if (!isHybrid) continue; 33559566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[s], numSubPoints[d + 1], subpoints[d + 1], &subc)); 33560d366550SMatthew G. Knepley if (subc >= 0) { 33570d366550SMatthew G. Knepley const PetscInt ccell = subpoints[d + 1][subc]; 33580d366550SMatthew G. Knepley 33599566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, ccell, &cone)); 33609566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, ccell, &coneSize)); 33619566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, ccell, &ornt)); 33620d366550SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 33630d366550SMatthew G. Knepley if (cone[c] == point) { 33640d366550SMatthew G. Knepley fornt = ornt[c]; 33650d366550SMatthew G. Knepley break; 33660d366550SMatthew G. Knepley } 33670d366550SMatthew G. Knepley } 33680d366550SMatthew G. Knepley break; 33690d366550SMatthew G. Knepley } 33700d366550SMatthew G. Knepley } 33710d366550SMatthew G. Knepley } 33729566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 33739566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(subdm, subpoint, &subconeSize)); 33749566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 33759566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &ornt)); 3376e6ccafaeSMatthew G Knepley for (c = 0, coneSizeNew = 0; c < coneSize; ++c) { 33779566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[c], numSubPoints[d - 1], subpoints[d - 1], &subc)); 337801a2673eSMatthew G. Knepley if (subc >= 0) { 337901a2673eSMatthew G. Knepley coneNew[coneSizeNew] = firstSubPoint[d - 1] + subc; 33803982b651SMatthew G. Knepley orntNew[coneSizeNew] = ornt[c]; 338101a2673eSMatthew G. Knepley ++coneSizeNew; 338201a2673eSMatthew G. Knepley } 3383e6ccafaeSMatthew G Knepley } 338463a3b9bcSJacob Faibussowitsch PetscCheck(coneSizeNew == subconeSize, comm, PETSC_ERR_PLIB, "Number of cone points located %" PetscInt_FMT " does not match subcone size %" PetscInt_FMT, coneSizeNew, subconeSize); 33859566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(subdm, subpoint, coneNew)); 33869566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(subdm, subpoint, orntNew)); 33879566063dSJacob Faibussowitsch if (fornt < 0) PetscCall(DMPlexOrientPoint(subdm, subpoint, fornt)); 3388e6ccafaeSMatthew G Knepley } 3389e6ccafaeSMatthew G Knepley } 33909566063dSJacob Faibussowitsch PetscCall(PetscFree2(coneNew, orntNew)); 33919566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(subdm)); 33929566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(subdm)); 3393e6ccafaeSMatthew G Knepley /* Build coordinates */ 3394e6ccafaeSMatthew G Knepley { 3395e6ccafaeSMatthew G Knepley PetscSection coordSection, subCoordSection; 3396e6ccafaeSMatthew G Knepley Vec coordinates, subCoordinates; 3397e6ccafaeSMatthew G Knepley PetscScalar *coords, *subCoords; 3398c0e8cf5fSMatthew G. Knepley PetscInt cdim, numComp, coordSize; 339924640c55SToby Isaac const char *name; 3400e6ccafaeSMatthew G Knepley 34019566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 34029566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 34039566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 34049566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(subdm, &subCoordSection)); 34059566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(subCoordSection, 1)); 34069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &numComp)); 34079566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(subCoordSection, 0, numComp)); 34089566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(subCoordSection, firstSubPoint[0], firstSubPoint[0] + numSubPoints[0])); 3409e6ccafaeSMatthew G Knepley for (v = 0; v < numSubPoints[0]; ++v) { 3410e6ccafaeSMatthew G Knepley const PetscInt vertex = subpoints[0][v]; 3411e6ccafaeSMatthew G Knepley const PetscInt subvertex = firstSubPoint[0] + v; 3412e6ccafaeSMatthew G Knepley PetscInt dof; 3413e6ccafaeSMatthew G Knepley 34149566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, vertex, &dof)); 34159566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(subCoordSection, subvertex, dof)); 34169566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(subCoordSection, subvertex, 0, dof)); 3417e6ccafaeSMatthew G Knepley } 34189566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(subCoordSection)); 34199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(subCoordSection, &coordSize)); 34209566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &subCoordinates)); 34219566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)coordinates, &name)); 34229566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)subCoordinates, name)); 34239566063dSJacob Faibussowitsch PetscCall(VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE)); 34249566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(subCoordinates, cdim)); 34259566063dSJacob Faibussowitsch PetscCall(VecSetType(subCoordinates, VECSTANDARD)); 34269566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 34279566063dSJacob Faibussowitsch PetscCall(VecGetArray(subCoordinates, &subCoords)); 3428e6ccafaeSMatthew G Knepley for (v = 0; v < numSubPoints[0]; ++v) { 3429e6ccafaeSMatthew G Knepley const PetscInt vertex = subpoints[0][v]; 3430e6ccafaeSMatthew G Knepley const PetscInt subvertex = firstSubPoint[0] + v; 3431e6ccafaeSMatthew G Knepley PetscInt dof, off, sdof, soff, d; 3432e6ccafaeSMatthew G Knepley 34339566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, vertex, &dof)); 34349566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, vertex, &off)); 34359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subCoordSection, subvertex, &sdof)); 34369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(subCoordSection, subvertex, &soff)); 343763a3b9bcSJacob Faibussowitsch PetscCheck(dof == sdof, comm, PETSC_ERR_PLIB, "Coordinate dimension %" PetscInt_FMT " on subvertex %" PetscInt_FMT ", vertex %" PetscInt_FMT " should be %" PetscInt_FMT, sdof, subvertex, vertex, dof); 3438efa14ee0SMatthew G Knepley for (d = 0; d < dof; ++d) subCoords[soff + d] = coords[off + d]; 3439e6ccafaeSMatthew G Knepley } 34409566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 34419566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(subCoordinates, &subCoords)); 34429566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(subdm, subCoordinates)); 34439566063dSJacob Faibussowitsch PetscCall(VecDestroy(&subCoordinates)); 3444e6ccafaeSMatthew G Knepley } 34453982b651SMatthew G. Knepley /* Build SF: We need this complexity because subpoints might not be selected on the owning process */ 34463982b651SMatthew G. Knepley { 34473982b651SMatthew G. Knepley PetscSF sfPoint, sfPointSub; 34483982b651SMatthew G. Knepley IS subpIS; 34493982b651SMatthew G. Knepley const PetscSFNode *remotePoints; 34505033f954SMatthew G. Knepley PetscSFNode *sremotePoints = NULL, *newLocalPoints = NULL, *newOwners = NULL; 34515033f954SMatthew G. Knepley const PetscInt *localPoints, *subpoints, *rootdegree; 3452dd05d810SMatthew G. Knepley PetscInt *slocalPoints = NULL, *sortedPoints = NULL, *sortedIndices = NULL; 34535033f954SMatthew G. Knepley PetscInt numRoots, numLeaves, numSubpoints = 0, numSubroots, numSubleaves = 0, l, sl = 0, ll = 0, pStart, pEnd, p; 34545033f954SMatthew G. Knepley PetscMPIInt rank, size; 34553982b651SMatthew G. Knepley 34569566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 34575033f954SMatthew G. Knepley PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 34589566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 34599566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(subdm, &sfPointSub)); 34609566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 34619566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(subdm, NULL, &numSubroots)); 34629566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(subdm, &subpIS)); 34633982b651SMatthew G. Knepley if (subpIS) { 3464dd05d810SMatthew G. Knepley PetscBool sorted = PETSC_TRUE; 3465dd05d810SMatthew G. Knepley 34669566063dSJacob Faibussowitsch PetscCall(ISGetIndices(subpIS, &subpoints)); 34679566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(subpIS, &numSubpoints)); 3468dd05d810SMatthew G. Knepley for (p = 1; p < numSubpoints; ++p) sorted = sorted && (subpoints[p] >= subpoints[p - 1]) ? PETSC_TRUE : PETSC_FALSE; 3469dd05d810SMatthew G. Knepley if (!sorted) { 3470dd05d810SMatthew G. Knepley PetscCall(PetscMalloc2(numSubpoints, &sortedPoints, numSubpoints, &sortedIndices)); 3471dd05d810SMatthew G. Knepley for (p = 0; p < numSubpoints; ++p) sortedIndices[p] = p; 3472dd05d810SMatthew G. Knepley PetscCall(PetscArraycpy(sortedPoints, subpoints, numSubpoints)); 3473dd05d810SMatthew G. Knepley PetscCall(PetscSortIntWithArray(numSubpoints, sortedPoints, sortedIndices)); 3474dd05d810SMatthew G. Knepley } 34753982b651SMatthew G. Knepley } 34769566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints)); 34773982b651SMatthew G. Knepley if (numRoots >= 0) { 34785033f954SMatthew G. Knepley PetscCall(PetscSFComputeDegreeBegin(sfPoint, &rootdegree)); 34795033f954SMatthew G. Knepley PetscCall(PetscSFComputeDegreeEnd(sfPoint, &rootdegree)); 34809566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEnd - pStart, &newLocalPoints, numRoots, &newOwners)); 34813982b651SMatthew G. Knepley for (p = 0; p < pEnd - pStart; ++p) { 34823982b651SMatthew G. Knepley newLocalPoints[p].rank = -2; 34833982b651SMatthew G. Knepley newLocalPoints[p].index = -2; 34843982b651SMatthew G. Knepley } 34853982b651SMatthew G. Knepley /* Set subleaves */ 34863982b651SMatthew G. Knepley for (l = 0; l < numLeaves; ++l) { 34873982b651SMatthew G. Knepley const PetscInt point = localPoints[l]; 3488dd05d810SMatthew G. Knepley const PetscInt subpoint = DMPlexFilterPointPerm_Internal(point, 0, numSubpoints, sortedPoints ? sortedPoints : subpoints, sortedIndices); 34893982b651SMatthew G. Knepley 34903982b651SMatthew G. Knepley if (subpoint < 0) continue; 34913982b651SMatthew G. Knepley newLocalPoints[point - pStart].rank = rank; 34923982b651SMatthew G. Knepley newLocalPoints[point - pStart].index = subpoint; 34933982b651SMatthew G. Knepley ++numSubleaves; 34943982b651SMatthew G. Knepley } 34953982b651SMatthew G. Knepley /* Must put in owned subpoints */ 34963982b651SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 34973982b651SMatthew G. Knepley newOwners[p - pStart].rank = -3; 34983982b651SMatthew G. Knepley newOwners[p - pStart].index = -3; 34993982b651SMatthew G. Knepley } 3500d9384f27SMatthew G. Knepley for (p = 0; p < numSubpoints; ++p) { 35015033f954SMatthew G. Knepley /* Hold on to currently owned points */ 35025033f954SMatthew G. Knepley if (rootdegree[subpoints[p] - pStart]) newOwners[subpoints[p] - pStart].rank = rank + size; 35035033f954SMatthew G. Knepley else newOwners[subpoints[p] - pStart].rank = rank; 3504d9384f27SMatthew G. Knepley newOwners[subpoints[p] - pStart].index = p; 35053982b651SMatthew G. Knepley } 35069566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(sfPoint, MPIU_2INT, newLocalPoints, newOwners, MPI_MAXLOC)); 35079566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(sfPoint, MPIU_2INT, newLocalPoints, newOwners, MPI_MAXLOC)); 35089371c9d4SSatish Balay for (p = pStart; p < pEnd; ++p) 35099371c9d4SSatish Balay if (newOwners[p - pStart].rank >= size) newOwners[p - pStart].rank -= size; 35109566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfPoint, MPIU_2INT, newOwners, newLocalPoints, MPI_REPLACE)); 35119566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfPoint, MPIU_2INT, newOwners, newLocalPoints, MPI_REPLACE)); 35129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numSubleaves, &slocalPoints)); 35139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numSubleaves, &sremotePoints)); 35145033f954SMatthew G. Knepley for (l = 0; l < numLeaves; ++l) { 35153982b651SMatthew G. Knepley const PetscInt point = localPoints[l]; 3516dd05d810SMatthew G. Knepley const PetscInt subpoint = DMPlexFilterPointPerm_Internal(point, 0, numSubpoints, sortedPoints ? sortedPoints : subpoints, sortedIndices); 35173982b651SMatthew G. Knepley 35183982b651SMatthew G. Knepley if (subpoint < 0) continue; 35199371c9d4SSatish Balay if (newLocalPoints[point].rank == rank) { 35209371c9d4SSatish Balay ++ll; 35219371c9d4SSatish Balay continue; 35229371c9d4SSatish Balay } 35233982b651SMatthew G. Knepley slocalPoints[sl] = subpoint; 35243982b651SMatthew G. Knepley sremotePoints[sl].rank = newLocalPoints[point].rank; 35253982b651SMatthew G. Knepley sremotePoints[sl].index = newLocalPoints[point].index; 352663a3b9bcSJacob Faibussowitsch PetscCheck(sremotePoints[sl].rank >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid remote rank for local point %" PetscInt_FMT, point); 352763a3b9bcSJacob Faibussowitsch PetscCheck(sremotePoints[sl].index >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid remote subpoint for local point %" PetscInt_FMT, point); 35283982b651SMatthew G. Knepley ++sl; 35293982b651SMatthew G. Knepley } 35301dca8a05SBarry Smith PetscCheck(sl + ll == numSubleaves, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatch in number of subleaves %" PetscInt_FMT " + %" PetscInt_FMT " != %" PetscInt_FMT, sl, ll, numSubleaves); 35319566063dSJacob Faibussowitsch PetscCall(PetscFree2(newLocalPoints, newOwners)); 35329566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sfPointSub, numSubroots, sl, slocalPoints, PETSC_OWN_POINTER, sremotePoints, PETSC_OWN_POINTER)); 35333982b651SMatthew G. Knepley } 353448a46eb9SPierre Jolivet if (subpIS) PetscCall(ISRestoreIndices(subpIS, &subpoints)); 3535dd05d810SMatthew G. Knepley PetscCall(PetscFree2(sortedPoints, sortedIndices)); 35363982b651SMatthew G. Knepley } 3537212103e5SMatthew Knepley /* Filter labels */ 35389566063dSJacob Faibussowitsch PetscCall(DMPlexFilterLabels_Internal(dm, numSubPoints, subpoints, firstSubPoint, subdm)); 3539efa14ee0SMatthew G Knepley /* Cleanup */ 3540dd05d810SMatthew G. Knepley for (d = 0; d <= sdim; ++d) { 35419566063dSJacob Faibussowitsch if (subpointIS[d]) PetscCall(ISRestoreIndices(subpointIS[d], &subpoints[d])); 35429566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subpointIS[d])); 3543e6ccafaeSMatthew G Knepley } 35449566063dSJacob Faibussowitsch PetscCall(PetscFree4(numSubPoints, firstSubPoint, subpointIS, subpoints)); 3545e6ccafaeSMatthew G Knepley PetscFunctionReturn(0); 3546e6ccafaeSMatthew G Knepley } 3547e6ccafaeSMatthew G Knepley 3548d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSubmesh_Interpolated(DM dm, DMLabel vertexLabel, PetscInt value, PetscBool markedFaces, DM subdm) 3549d71ae5a4SJacob Faibussowitsch { 35503982b651SMatthew G. Knepley PetscFunctionBegin; 35519566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSubmeshGeneric_Interpolated(dm, vertexLabel, value, markedFaces, PETSC_FALSE, 1, subdm)); 35523982b651SMatthew G. Knepley PetscFunctionReturn(0); 35533982b651SMatthew G. Knepley } 35543982b651SMatthew G. Knepley 3555d0fa310fSMatthew G. Knepley /*@ 3556e6ccafaeSMatthew G Knepley DMPlexCreateSubmesh - Extract a hypersurface from the mesh using vertices defined by a label 3557e6ccafaeSMatthew G Knepley 3558e6ccafaeSMatthew G Knepley Input Parameters: 3559e6ccafaeSMatthew G Knepley + dm - The original mesh 3560158acfadSMatthew G. Knepley . vertexLabel - The DMLabel marking points contained in the surface 3561158acfadSMatthew G. Knepley . value - The label value to use 3562158acfadSMatthew G. Knepley - markedFaces - PETSC_TRUE if surface faces are marked in addition to vertices, PETSC_FALSE if only vertices are marked 3563e6ccafaeSMatthew G Knepley 3564e6ccafaeSMatthew G Knepley Output Parameter: 3565e6ccafaeSMatthew G Knepley . subdm - The surface mesh 3566e6ccafaeSMatthew G Knepley 3567e6ccafaeSMatthew G Knepley Note: This function produces a DMLabel mapping original points in the submesh to their depth. This can be obtained using DMPlexGetSubpointMap(). 3568e6ccafaeSMatthew G Knepley 3569e6ccafaeSMatthew G Knepley Level: developer 3570e6ccafaeSMatthew G Knepley 3571db781477SPatrick Sanan .seealso: `DMPlexGetSubpointMap()`, `DMGetLabel()`, `DMLabelSetValue()` 3572830e53efSMatthew G. Knepley @*/ 3573d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSubmesh(DM dm, DMLabel vertexLabel, PetscInt value, PetscBool markedFaces, DM *subdm) 3574d71ae5a4SJacob Faibussowitsch { 3575827c4036SVaclav Hapla DMPlexInterpolatedFlag interpolated; 3576827c4036SVaclav Hapla PetscInt dim, cdim; 3577e6ccafaeSMatthew G Knepley 3578e6ccafaeSMatthew G Knepley PetscFunctionBegin; 3579e6ccafaeSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3580064a246eSJacob Faibussowitsch PetscValidPointer(subdm, 5); 35819566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 35829566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), subdm)); 35839566063dSJacob Faibussowitsch PetscCall(DMSetType(*subdm, DMPLEX)); 35849566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*subdm, dim - 1)); 35859566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 35869566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*subdm, cdim)); 35879566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated)); 358808401ef6SPierre Jolivet PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes"); 3589827c4036SVaclav Hapla if (interpolated) { 35909566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSubmesh_Interpolated(dm, vertexLabel, value, markedFaces, *subdm)); 3591e6ccafaeSMatthew G Knepley } else { 35929566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSubmesh_Uninterpolated(dm, vertexLabel, value, *subdm)); 3593e6ccafaeSMatthew G Knepley } 35945de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, *subdm)); 3595e6ccafaeSMatthew G Knepley PetscFunctionReturn(0); 3596e6ccafaeSMatthew G Knepley } 3597e6ccafaeSMatthew G Knepley 3598d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCohesiveSubmesh_Uninterpolated(DM dm, PetscBool hasLagrange, const char label[], PetscInt value, DM subdm) 3599d71ae5a4SJacob Faibussowitsch { 3600766ab985SMatthew G. Knepley MPI_Comm comm; 3601766ab985SMatthew G. Knepley DMLabel subpointMap; 3602766ab985SMatthew G. Knepley IS subvertexIS; 3603766ab985SMatthew G. Knepley const PetscInt *subVertices; 3604fed694aaSMatthew G. Knepley PetscInt numSubVertices, firstSubVertex, numSubCells, *subCells = NULL; 3605766ab985SMatthew G. Knepley PetscInt *subface, maxConeSize, numSubFaces, firstSubFace, newFacePoint, nFV; 3606412e9a14SMatthew G. Knepley PetscInt c, f; 3607766ab985SMatthew G. Knepley 3608766ab985SMatthew G. Knepley PetscFunctionBegin; 36099566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 3610766ab985SMatthew G. Knepley /* Create subpointMap which marks the submesh */ 36119566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "subpoint_map", &subpointMap)); 36129566063dSJacob Faibussowitsch PetscCall(DMPlexSetSubpointMap(subdm, subpointMap)); 36139566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&subpointMap)); 36149566063dSJacob Faibussowitsch PetscCall(DMPlexMarkCohesiveSubmesh_Uninterpolated(dm, hasLagrange, label, value, subpointMap, &numSubFaces, &nFV, &subCells, subdm)); 3615766ab985SMatthew G. Knepley /* Setup chart */ 36169566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(subpointMap, 0, &numSubVertices)); 36179566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(subpointMap, 2, &numSubCells)); 36189566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(subdm, 0, numSubCells + numSubFaces + numSubVertices)); 36199566063dSJacob Faibussowitsch PetscCall(DMPlexSetVTKCellHeight(subdm, 1)); 3620766ab985SMatthew G. Knepley /* Set cone sizes */ 3621766ab985SMatthew G. Knepley firstSubVertex = numSubCells; 3622766ab985SMatthew G. Knepley firstSubFace = numSubCells + numSubVertices; 3623766ab985SMatthew G. Knepley newFacePoint = firstSubFace; 36249566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(subpointMap, 0, &subvertexIS)); 36259566063dSJacob Faibussowitsch if (subvertexIS) PetscCall(ISGetIndices(subvertexIS, &subVertices)); 362648a46eb9SPierre Jolivet for (c = 0; c < numSubCells; ++c) PetscCall(DMPlexSetConeSize(subdm, c, 1)); 362748a46eb9SPierre Jolivet for (f = firstSubFace; f < firstSubFace + numSubFaces; ++f) PetscCall(DMPlexSetConeSize(subdm, f, nFV)); 36289566063dSJacob Faibussowitsch PetscCall(DMSetUp(subdm)); 3629766ab985SMatthew G. Knepley /* Create face cones */ 36309566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, NULL)); 36319566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(subdm, maxConeSize, MPIU_INT, (void **)&subface)); 3632766ab985SMatthew G. Knepley for (c = 0; c < numSubCells; ++c) { 3633766ab985SMatthew G. Knepley const PetscInt cell = subCells[c]; 3634766ab985SMatthew G. Knepley const PetscInt subcell = c; 363587feddfdSMatthew G. Knepley const PetscInt *cone, *cells; 3636064cae4fSPierre Jolivet PetscBool isHybrid = PETSC_FALSE; 363787feddfdSMatthew G. Knepley PetscInt numCells, subVertex, p, v; 3638766ab985SMatthew G. Knepley 36399566063dSJacob Faibussowitsch PetscCall(DMPlexCellIsHybrid_Internal(dm, cell, &isHybrid)); 3640412e9a14SMatthew G. Knepley if (!isHybrid) continue; 36419566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cell, &cone)); 364287feddfdSMatthew G. Knepley for (v = 0; v < nFV; ++v) { 36439566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[v], numSubVertices, subVertices, &subVertex)); 364487feddfdSMatthew G. Knepley subface[v] = firstSubVertex + subVertex; 364587feddfdSMatthew G. Knepley } 36469566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(subdm, newFacePoint, subface)); 36479566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(subdm, subcell, &newFacePoint)); 36489566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, nFV, cone, &numCells, &cells)); 364927234c99SMatthew G. Knepley /* Not true in parallel 365008401ef6SPierre Jolivet PetscCheck(numCells == 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cohesive cells should separate two cells"); */ 365187feddfdSMatthew G. Knepley for (p = 0; p < numCells; ++p) { 365287feddfdSMatthew G. Knepley PetscInt negsubcell; 3653064cae4fSPierre Jolivet PetscBool isHybrid = PETSC_FALSE; 3654766ab985SMatthew G. Knepley 36559566063dSJacob Faibussowitsch PetscCall(DMPlexCellIsHybrid_Internal(dm, cells[p], &isHybrid)); 3656412e9a14SMatthew G. Knepley if (isHybrid) continue; 365787feddfdSMatthew G. Knepley /* I know this is a crap search */ 365887feddfdSMatthew G. Knepley for (negsubcell = 0; negsubcell < numSubCells; ++negsubcell) { 365987feddfdSMatthew G. Knepley if (subCells[negsubcell] == cells[p]) break; 3660766ab985SMatthew G. Knepley } 366163a3b9bcSJacob Faibussowitsch PetscCheck(negsubcell != numSubCells, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find negative face neighbor for cohesive cell %" PetscInt_FMT, cell); 36629566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(subdm, negsubcell, &newFacePoint)); 3663766ab985SMatthew G. Knepley } 36649566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, nFV, cone, &numCells, &cells)); 366587feddfdSMatthew G. Knepley ++newFacePoint; 3666766ab985SMatthew G. Knepley } 36679566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(subdm, maxConeSize, MPIU_INT, (void **)&subface)); 36689566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(subdm)); 36699566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(subdm)); 3670766ab985SMatthew G. Knepley /* Build coordinates */ 3671766ab985SMatthew G. Knepley { 3672766ab985SMatthew G. Knepley PetscSection coordSection, subCoordSection; 3673766ab985SMatthew G. Knepley Vec coordinates, subCoordinates; 3674766ab985SMatthew G. Knepley PetscScalar *coords, *subCoords; 3675c0e8cf5fSMatthew G. Knepley PetscInt cdim, numComp, coordSize, v; 367624640c55SToby Isaac const char *name; 3677766ab985SMatthew G. Knepley 36789566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 36799566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 36809566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 36819566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(subdm, &subCoordSection)); 36829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(subCoordSection, 1)); 36839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &numComp)); 36849566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(subCoordSection, 0, numComp)); 36859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex + numSubVertices)); 3686766ab985SMatthew G. Knepley for (v = 0; v < numSubVertices; ++v) { 3687766ab985SMatthew G. Knepley const PetscInt vertex = subVertices[v]; 3688766ab985SMatthew G. Knepley const PetscInt subvertex = firstSubVertex + v; 3689766ab985SMatthew G. Knepley PetscInt dof; 3690766ab985SMatthew G. Knepley 36919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, vertex, &dof)); 36929566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(subCoordSection, subvertex, dof)); 36939566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(subCoordSection, subvertex, 0, dof)); 3694766ab985SMatthew G. Knepley } 36959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(subCoordSection)); 36969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(subCoordSection, &coordSize)); 36979566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &subCoordinates)); 36989566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)coordinates, &name)); 36999566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)subCoordinates, name)); 37009566063dSJacob Faibussowitsch PetscCall(VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE)); 37019566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(subCoordinates, cdim)); 37029566063dSJacob Faibussowitsch PetscCall(VecSetType(subCoordinates, VECSTANDARD)); 37039566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 37049566063dSJacob Faibussowitsch PetscCall(VecGetArray(subCoordinates, &subCoords)); 3705766ab985SMatthew G. Knepley for (v = 0; v < numSubVertices; ++v) { 3706766ab985SMatthew G. Knepley const PetscInt vertex = subVertices[v]; 3707766ab985SMatthew G. Knepley const PetscInt subvertex = firstSubVertex + v; 3708766ab985SMatthew G. Knepley PetscInt dof, off, sdof, soff, d; 3709766ab985SMatthew G. Knepley 37109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, vertex, &dof)); 37119566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, vertex, &off)); 37129566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subCoordSection, subvertex, &sdof)); 37139566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(subCoordSection, subvertex, &soff)); 371463a3b9bcSJacob Faibussowitsch PetscCheck(dof == sdof, comm, PETSC_ERR_PLIB, "Coordinate dimension %" PetscInt_FMT " on subvertex %" PetscInt_FMT ", vertex %" PetscInt_FMT " should be %" PetscInt_FMT, sdof, subvertex, vertex, dof); 3715766ab985SMatthew G. Knepley for (d = 0; d < dof; ++d) subCoords[soff + d] = coords[off + d]; 3716766ab985SMatthew G. Knepley } 37179566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 37189566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(subCoordinates, &subCoords)); 37199566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(subdm, subCoordinates)); 37209566063dSJacob Faibussowitsch PetscCall(VecDestroy(&subCoordinates)); 3721766ab985SMatthew G. Knepley } 3722aca35d17SMatthew G. Knepley /* Build SF */ 3723aca35d17SMatthew G. Knepley CHKMEMQ; 3724aca35d17SMatthew G. Knepley { 3725aca35d17SMatthew G. Knepley PetscSF sfPoint, sfPointSub; 3726aca35d17SMatthew G. Knepley const PetscSFNode *remotePoints; 3727bdcf2095SMatthew G. Knepley PetscSFNode *sremotePoints, *newLocalPoints, *newOwners; 3728aca35d17SMatthew G. Knepley const PetscInt *localPoints; 3729bdcf2095SMatthew G. Knepley PetscInt *slocalPoints; 373049c26ae4SMatthew G. Knepley PetscInt numRoots, numLeaves, numSubRoots = numSubCells + numSubFaces + numSubVertices, numSubLeaves = 0, l, sl, ll, pStart, pEnd, p, vStart, vEnd; 3731bdcf2095SMatthew G. Knepley PetscMPIInt rank; 3732aca35d17SMatthew G. Knepley 37339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 37349566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 37359566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(subdm, &sfPointSub)); 37369566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 37379566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 37389566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints)); 3739aca35d17SMatthew G. Knepley if (numRoots >= 0) { 3740aca35d17SMatthew G. Knepley /* Only vertices should be shared */ 37419566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEnd - pStart, &newLocalPoints, numRoots, &newOwners)); 3742bdcf2095SMatthew G. Knepley for (p = 0; p < pEnd - pStart; ++p) { 3743bdcf2095SMatthew G. Knepley newLocalPoints[p].rank = -2; 3744bdcf2095SMatthew G. Knepley newLocalPoints[p].index = -2; 3745bdcf2095SMatthew G. Knepley } 37469e0823b2SMatthew G. Knepley /* Set subleaves */ 3747aca35d17SMatthew G. Knepley for (l = 0; l < numLeaves; ++l) { 3748aca35d17SMatthew G. Knepley const PetscInt point = localPoints[l]; 3749bdcf2095SMatthew G. Knepley const PetscInt subPoint = DMPlexFilterPoint_Internal(point, firstSubVertex, numSubVertices, subVertices); 3750aca35d17SMatthew G. Knepley 375163a3b9bcSJacob Faibussowitsch PetscCheck(!(point < vStart) || !(point >= vEnd), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Should not be mapping anything but vertices, %" PetscInt_FMT, point); 3752bdcf2095SMatthew G. Knepley if (subPoint < 0) continue; 3753bdcf2095SMatthew G. Knepley newLocalPoints[point - pStart].rank = rank; 3754bdcf2095SMatthew G. Knepley newLocalPoints[point - pStart].index = subPoint; 3755bdcf2095SMatthew G. Knepley ++numSubLeaves; 3756aca35d17SMatthew G. Knepley } 37579e0823b2SMatthew G. Knepley /* Must put in owned subpoints */ 37589e0823b2SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 37599e0823b2SMatthew G. Knepley const PetscInt subPoint = DMPlexFilterPoint_Internal(p, firstSubVertex, numSubVertices, subVertices); 37609e0823b2SMatthew G. Knepley 37619e0823b2SMatthew G. Knepley if (subPoint < 0) { 37629e0823b2SMatthew G. Knepley newOwners[p - pStart].rank = -3; 37639e0823b2SMatthew G. Knepley newOwners[p - pStart].index = -3; 37649e0823b2SMatthew G. Knepley } else { 37659e0823b2SMatthew G. Knepley newOwners[p - pStart].rank = rank; 37669e0823b2SMatthew G. Knepley newOwners[p - pStart].index = subPoint; 37679e0823b2SMatthew G. Knepley } 3768bdcf2095SMatthew G. Knepley } 37699566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(sfPoint, MPIU_2INT, newLocalPoints, newOwners, MPI_MAXLOC)); 37709566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(sfPoint, MPIU_2INT, newLocalPoints, newOwners, MPI_MAXLOC)); 37719566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfPoint, MPIU_2INT, newOwners, newLocalPoints, MPI_REPLACE)); 37729566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfPoint, MPIU_2INT, newOwners, newLocalPoints, MPI_REPLACE)); 37739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numSubLeaves, &slocalPoints)); 37749566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numSubLeaves, &sremotePoints)); 377549c26ae4SMatthew G. Knepley for (l = 0, sl = 0, ll = 0; l < numLeaves; ++l) { 3776bdcf2095SMatthew G. Knepley const PetscInt point = localPoints[l]; 3777bdcf2095SMatthew G. Knepley const PetscInt subPoint = DMPlexFilterPoint_Internal(point, firstSubVertex, numSubVertices, subVertices); 3778aca35d17SMatthew G. Knepley 3779aca35d17SMatthew G. Knepley if (subPoint < 0) continue; 37809371c9d4SSatish Balay if (newLocalPoints[point].rank == rank) { 37819371c9d4SSatish Balay ++ll; 37829371c9d4SSatish Balay continue; 37839371c9d4SSatish Balay } 3784aca35d17SMatthew G. Knepley slocalPoints[sl] = subPoint; 3785bdcf2095SMatthew G. Knepley sremotePoints[sl].rank = newLocalPoints[point].rank; 3786bdcf2095SMatthew G. Knepley sremotePoints[sl].index = newLocalPoints[point].index; 378763a3b9bcSJacob Faibussowitsch PetscCheck(sremotePoints[sl].rank >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid remote rank for local point %" PetscInt_FMT, point); 378863a3b9bcSJacob Faibussowitsch PetscCheck(sremotePoints[sl].index >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid remote subpoint for local point %" PetscInt_FMT, point); 3789aca35d17SMatthew G. Knepley ++sl; 3790aca35d17SMatthew G. Knepley } 37919566063dSJacob Faibussowitsch PetscCall(PetscFree2(newLocalPoints, newOwners)); 37921dca8a05SBarry Smith PetscCheck(sl + ll == numSubLeaves, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatch in number of subleaves %" PetscInt_FMT " + %" PetscInt_FMT " != %" PetscInt_FMT, sl, ll, numSubLeaves); 37939566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sfPointSub, numSubRoots, sl, slocalPoints, PETSC_OWN_POINTER, sremotePoints, PETSC_OWN_POINTER)); 3794aca35d17SMatthew G. Knepley } 3795aca35d17SMatthew G. Knepley } 3796aca35d17SMatthew G. Knepley CHKMEMQ; 3797766ab985SMatthew G. Knepley /* Cleanup */ 37989566063dSJacob Faibussowitsch if (subvertexIS) PetscCall(ISRestoreIndices(subvertexIS, &subVertices)); 37999566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subvertexIS)); 38009566063dSJacob Faibussowitsch PetscCall(PetscFree(subCells)); 3801766ab985SMatthew G. Knepley PetscFunctionReturn(0); 3802766ab985SMatthew G. Knepley } 3803766ab985SMatthew G. Knepley 3804d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCohesiveSubmesh_Interpolated(DM dm, const char labelname[], PetscInt value, DM subdm) 3805d71ae5a4SJacob Faibussowitsch { 38063982b651SMatthew G. Knepley DMLabel label = NULL; 3807766ab985SMatthew G. Knepley 3808766ab985SMatthew G. Knepley PetscFunctionBegin; 38099566063dSJacob Faibussowitsch if (labelname) PetscCall(DMGetLabel(dm, labelname, &label)); 38109566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSubmeshGeneric_Interpolated(dm, label, value, PETSC_FALSE, PETSC_TRUE, 1, subdm)); 3811766ab985SMatthew G. Knepley PetscFunctionReturn(0); 3812766ab985SMatthew G. Knepley } 3813766ab985SMatthew G. Knepley 3814c08575a3SMatthew G. Knepley /*@C 38157d2fefb6SMatthew G. Knepley DMPlexCreateCohesiveSubmesh - Extract from a mesh with cohesive cells the hypersurface defined by one face of the cells. Optionally, a Label can be given to restrict the cells. 3816766ab985SMatthew G. Knepley 3817766ab985SMatthew G. Knepley Input Parameters: 3818766ab985SMatthew G. Knepley + dm - The original mesh 381927c04023SMatthew G. Knepley . hasLagrange - The mesh has Lagrange unknowns in the cohesive cells 38207afc1a8bSJed Brown . label - A label name, or NULL 382127c04023SMatthew G. Knepley - value - A label value 3822766ab985SMatthew G. Knepley 3823766ab985SMatthew G. Knepley Output Parameter: 3824766ab985SMatthew G. Knepley . subdm - The surface mesh 3825766ab985SMatthew G. Knepley 3826766ab985SMatthew G. Knepley Note: This function produces a DMLabel mapping original points in the submesh to their depth. This can be obtained using DMPlexGetSubpointMap(). 3827766ab985SMatthew G. Knepley 3828766ab985SMatthew G. Knepley Level: developer 3829766ab985SMatthew G. Knepley 3830db781477SPatrick Sanan .seealso: `DMPlexGetSubpointMap()`, `DMPlexCreateSubmesh()` 3831c08575a3SMatthew G. Knepley @*/ 3832d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCohesiveSubmesh(DM dm, PetscBool hasLagrange, const char label[], PetscInt value, DM *subdm) 3833d71ae5a4SJacob Faibussowitsch { 3834c0e8cf5fSMatthew G. Knepley PetscInt dim, cdim, depth; 3835766ab985SMatthew G. Knepley 3836766ab985SMatthew G. Knepley PetscFunctionBegin; 3837766ab985SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 383827c04023SMatthew G. Knepley PetscValidPointer(subdm, 5); 38399566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 38409566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 38419566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), subdm)); 38429566063dSJacob Faibussowitsch PetscCall(DMSetType(*subdm, DMPLEX)); 38439566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*subdm, dim - 1)); 38449566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 38459566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*subdm, cdim)); 3846766ab985SMatthew G. Knepley if (depth == dim) { 38479566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCohesiveSubmesh_Interpolated(dm, label, value, *subdm)); 3848766ab985SMatthew G. Knepley } else { 38499566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCohesiveSubmesh_Uninterpolated(dm, hasLagrange, label, value, *subdm)); 3850e6ccafaeSMatthew G Knepley } 38515de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, *subdm)); 3852e6ccafaeSMatthew G Knepley PetscFunctionReturn(0); 3853e6ccafaeSMatthew G Knepley } 3854e6ccafaeSMatthew G Knepley 3855bec263e5SMatthew G. Knepley /*@ 3856bec263e5SMatthew G. Knepley DMPlexFilter - Extract a subset of mesh cells defined by a label as a separate mesh 3857bec263e5SMatthew G. Knepley 3858bec263e5SMatthew G. Knepley Input Parameters: 3859bec263e5SMatthew G. Knepley + dm - The original mesh 3860bec263e5SMatthew G. Knepley . cellLabel - The DMLabel marking cells contained in the new mesh 3861bec263e5SMatthew G. Knepley - value - The label value to use 3862bec263e5SMatthew G. Knepley 3863bec263e5SMatthew G. Knepley Output Parameter: 3864bec263e5SMatthew G. Knepley . subdm - The new mesh 3865bec263e5SMatthew G. Knepley 3866dd05d810SMatthew G. Knepley Notes: 3867dd05d810SMatthew G. Knepley This function produces a `DMLabel` mapping original points in the submesh to their depth. This can be obtained using `DMPlexGetSubpointMap()`. 3868bec263e5SMatthew G. Knepley 3869bec263e5SMatthew G. Knepley Level: developer 3870bec263e5SMatthew G. Knepley 3871dd05d810SMatthew G. Knepley .seealso: `DMPlexGetSubpointMap()`, `DMGetLabel()`, `DMLabelSetValue()`, `DMPlexCreateSubmesh()` 3872bec263e5SMatthew G. Knepley @*/ 3873d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexFilter(DM dm, DMLabel cellLabel, PetscInt value, DM *subdm) 3874d71ae5a4SJacob Faibussowitsch { 3875b47cd10cSMatthew G. Knepley PetscInt dim, overlap; 3876bec263e5SMatthew G. Knepley 3877bec263e5SMatthew G. Knepley PetscFunctionBegin; 3878bec263e5SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3879064a246eSJacob Faibussowitsch PetscValidPointer(subdm, 4); 38809566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 38819566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), subdm)); 38829566063dSJacob Faibussowitsch PetscCall(DMSetType(*subdm, DMPLEX)); 3883bec263e5SMatthew G. Knepley /* Extract submesh in place, could be empty on some procs, could have inconsistency if procs do not both extract a shared cell */ 38849566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSubmeshGeneric_Interpolated(dm, cellLabel, value, PETSC_FALSE, PETSC_FALSE, 0, *subdm)); 38855de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, *subdm)); 3886b47cd10cSMatthew G. Knepley // It is possible to obtain a surface mesh where some faces are in SF 3887b47cd10cSMatthew G. Knepley // We should either mark the mesh as having an overlap, or delete these from the SF 3888b47cd10cSMatthew G. Knepley PetscCall(DMPlexGetOverlap(dm, &overlap)); 3889b47cd10cSMatthew G. Knepley if (!overlap) { 3890b47cd10cSMatthew G. Knepley PetscSF sf; 3891b47cd10cSMatthew G. Knepley const PetscInt *leaves; 3892b47cd10cSMatthew G. Knepley PetscInt cStart, cEnd, Nl; 3893b47cd10cSMatthew G. Knepley PetscBool hasSubcell = PETSC_FALSE, ghasSubcell; 3894b47cd10cSMatthew G. Knepley 3895b47cd10cSMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(*subdm, 0, &cStart, &cEnd)); 3896b47cd10cSMatthew G. Knepley PetscCall(DMGetPointSF(*subdm, &sf)); 3897b47cd10cSMatthew G. Knepley PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &leaves, NULL)); 3898b47cd10cSMatthew G. Knepley for (PetscInt l = 0; l < Nl; ++l) { 3899b47cd10cSMatthew G. Knepley const PetscInt point = leaves ? leaves[l] : l; 3900b47cd10cSMatthew G. Knepley 3901b47cd10cSMatthew G. Knepley if (point >= cStart && point < cEnd) { 3902b47cd10cSMatthew G. Knepley hasSubcell = PETSC_TRUE; 3903b47cd10cSMatthew G. Knepley break; 3904b47cd10cSMatthew G. Knepley } 3905b47cd10cSMatthew G. Knepley } 3906b47cd10cSMatthew G. Knepley PetscCall(MPIU_Allreduce(&hasSubcell, &ghasSubcell, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm))); 3907b47cd10cSMatthew G. Knepley if (ghasSubcell) PetscCall(DMPlexSetOverlap(*subdm, NULL, 1)); 3908b47cd10cSMatthew G. Knepley } 3909bec263e5SMatthew G. Knepley PetscFunctionReturn(0); 3910bec263e5SMatthew G. Knepley } 3911bec263e5SMatthew G. Knepley 391264beef6dSMatthew G. Knepley /*@ 391364beef6dSMatthew G. Knepley DMPlexGetSubpointMap - Returns a DMLabel with point dimension as values 391464beef6dSMatthew G. Knepley 391564beef6dSMatthew G. Knepley Input Parameter: 391664beef6dSMatthew G. Knepley . dm - The submesh DM 391764beef6dSMatthew G. Knepley 391864beef6dSMatthew G. Knepley Output Parameter: 391964beef6dSMatthew G. Knepley . subpointMap - The DMLabel of all the points from the original mesh in this submesh, or NULL if this is not a submesh 392064beef6dSMatthew G. Knepley 392164beef6dSMatthew G. Knepley Level: developer 392264beef6dSMatthew G. Knepley 3923db781477SPatrick Sanan .seealso: `DMPlexCreateSubmesh()`, `DMPlexGetSubpointIS()` 392464beef6dSMatthew G. Knepley @*/ 3925d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSubpointMap(DM dm, DMLabel *subpointMap) 3926d71ae5a4SJacob Faibussowitsch { 3927e6ccafaeSMatthew G Knepley PetscFunctionBegin; 3928e6ccafaeSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3929e6ccafaeSMatthew G Knepley PetscValidPointer(subpointMap, 2); 393065663942SMatthew G. Knepley *subpointMap = ((DM_Plex *)dm->data)->subpointMap; 3931e6ccafaeSMatthew G Knepley PetscFunctionReturn(0); 3932e6ccafaeSMatthew G Knepley } 3933e6ccafaeSMatthew G Knepley 3934c08575a3SMatthew G. Knepley /*@ 3935c08575a3SMatthew G. Knepley DMPlexSetSubpointMap - Sets the DMLabel with point dimension as values 3936c08575a3SMatthew G. Knepley 3937c08575a3SMatthew G. Knepley Input Parameters: 3938c08575a3SMatthew G. Knepley + dm - The submesh DM 3939c08575a3SMatthew G. Knepley - subpointMap - The DMLabel of all the points from the original mesh in this submesh 3940c08575a3SMatthew G. Knepley 3941c08575a3SMatthew G. Knepley Note: Should normally not be called by the user, since it is set in DMPlexCreateSubmesh() 3942c08575a3SMatthew G. Knepley 3943c08575a3SMatthew G. Knepley Level: developer 3944c08575a3SMatthew G. Knepley 3945db781477SPatrick Sanan .seealso: `DMPlexCreateSubmesh()`, `DMPlexGetSubpointIS()` 3946c08575a3SMatthew G. Knepley @*/ 3947d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSubpointMap(DM dm, DMLabel subpointMap) 3948d71ae5a4SJacob Faibussowitsch { 3949e6ccafaeSMatthew G Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 3950285d324eSMatthew G. Knepley DMLabel tmp; 3951e6ccafaeSMatthew G Knepley 3952e6ccafaeSMatthew G Knepley PetscFunctionBegin; 3953e6ccafaeSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3954285d324eSMatthew G. Knepley tmp = mesh->subpointMap; 3955e6ccafaeSMatthew G Knepley mesh->subpointMap = subpointMap; 39569566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)mesh->subpointMap)); 39579566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&tmp)); 3958e6ccafaeSMatthew G Knepley PetscFunctionReturn(0); 3959e6ccafaeSMatthew G Knepley } 3960e6ccafaeSMatthew G Knepley 3961d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSubpointIS_Internal(DM dm, IS *subpointIS) 3962d71ae5a4SJacob Faibussowitsch { 396397d8846cSMatthew Knepley DMLabel spmap; 396497d8846cSMatthew Knepley PetscInt depth, d; 396597d8846cSMatthew Knepley 396697d8846cSMatthew Knepley PetscFunctionBegin; 39679566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointMap(dm, &spmap)); 39689566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 396997d8846cSMatthew Knepley if (spmap && depth >= 0) { 397097d8846cSMatthew Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 397197d8846cSMatthew Knepley PetscInt *points, *depths; 397297d8846cSMatthew Knepley PetscInt pStart, pEnd, p, off; 397397d8846cSMatthew Knepley 39749566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 397563a3b9bcSJacob Faibussowitsch PetscCheck(!pStart, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Submeshes must start the point numbering at 0, not %" PetscInt_FMT, pStart); 39769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd, &points)); 39779566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, depth + 1, MPIU_INT, &depths)); 397897d8846cSMatthew Knepley depths[0] = depth; 397997d8846cSMatthew Knepley depths[1] = 0; 3980ad540459SPierre Jolivet for (d = 2; d <= depth; ++d) depths[d] = depth + 1 - d; 398197d8846cSMatthew Knepley for (d = 0, off = 0; d <= depth; ++d) { 398297d8846cSMatthew Knepley const PetscInt dep = depths[d]; 398397d8846cSMatthew Knepley PetscInt depStart, depEnd, n; 398497d8846cSMatthew Knepley 39859566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dep, &depStart, &depEnd)); 39869566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(spmap, dep, &n)); 398797d8846cSMatthew Knepley if (((d < 2) && (depth > 1)) || (d == 1)) { /* Only check vertices and cells for now since the map is broken for others */ 398863a3b9bcSJacob Faibussowitsch PetscCheck(n == depEnd - depStart, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of mapped submesh points %" PetscInt_FMT " at depth %" PetscInt_FMT " should be %" PetscInt_FMT, n, dep, depEnd - depStart); 398997d8846cSMatthew Knepley } else { 399097d8846cSMatthew Knepley if (!n) { 399197d8846cSMatthew Knepley if (d == 0) { 399297d8846cSMatthew Knepley /* Missing cells */ 399397d8846cSMatthew Knepley for (p = 0; p < depEnd - depStart; ++p, ++off) points[off] = -1; 399497d8846cSMatthew Knepley } else { 399597d8846cSMatthew Knepley /* Missing faces */ 399697d8846cSMatthew Knepley for (p = 0; p < depEnd - depStart; ++p, ++off) points[off] = PETSC_MAX_INT; 399797d8846cSMatthew Knepley } 399897d8846cSMatthew Knepley } 399997d8846cSMatthew Knepley } 400097d8846cSMatthew Knepley if (n) { 400197d8846cSMatthew Knepley IS is; 400297d8846cSMatthew Knepley const PetscInt *opoints; 400397d8846cSMatthew Knepley 40049566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(spmap, dep, &is)); 40059566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, &opoints)); 400697d8846cSMatthew Knepley for (p = 0; p < n; ++p, ++off) points[off] = opoints[p]; 40079566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, &opoints)); 40089566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 400997d8846cSMatthew Knepley } 401097d8846cSMatthew Knepley } 40119566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, depth + 1, MPIU_INT, &depths)); 401263a3b9bcSJacob Faibussowitsch PetscCheck(off == pEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of mapped submesh points %" PetscInt_FMT " should be %" PetscInt_FMT, off, pEnd); 40139566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, pEnd, points, PETSC_OWN_POINTER, subpointIS)); 40149566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)spmap, &mesh->subpointState)); 401597d8846cSMatthew Knepley } 401697d8846cSMatthew Knepley PetscFunctionReturn(0); 401797d8846cSMatthew Knepley } 401897d8846cSMatthew Knepley 401964beef6dSMatthew G. Knepley /*@ 402097d8846cSMatthew Knepley DMPlexGetSubpointIS - Returns an IS covering the entire subdm chart with the original points as data 4021e6ccafaeSMatthew G Knepley 4022e6ccafaeSMatthew G Knepley Input Parameter: 4023e6ccafaeSMatthew G Knepley . dm - The submesh DM 4024e6ccafaeSMatthew G Knepley 4025e6ccafaeSMatthew G Knepley Output Parameter: 40260298fd71SBarry Smith . subpointIS - The IS of all the points from the original mesh in this submesh, or NULL if this is not a submesh 4027e6ccafaeSMatthew G Knepley 40283982b651SMatthew G. Knepley Note: This IS is guaranteed to be sorted by the construction of the submesh 402964beef6dSMatthew G. Knepley 403064beef6dSMatthew G. Knepley Level: developer 403164beef6dSMatthew G. Knepley 4032db781477SPatrick Sanan .seealso: `DMPlexCreateSubmesh()`, `DMPlexGetSubpointMap()` 403364beef6dSMatthew G. Knepley @*/ 4034d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSubpointIS(DM dm, IS *subpointIS) 4035d71ae5a4SJacob Faibussowitsch { 403697d8846cSMatthew Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 403797d8846cSMatthew Knepley DMLabel spmap; 403897d8846cSMatthew Knepley PetscObjectState state; 4039e6ccafaeSMatthew G Knepley 4040e6ccafaeSMatthew G Knepley PetscFunctionBegin; 4041e6ccafaeSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4042e6ccafaeSMatthew G Knepley PetscValidPointer(subpointIS, 2); 40439566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointMap(dm, &spmap)); 40449566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)spmap, &state)); 40459566063dSJacob Faibussowitsch if (state != mesh->subpointState || !mesh->subpointIS) PetscCall(DMPlexCreateSubpointIS_Internal(dm, &mesh->subpointIS)); 404697d8846cSMatthew Knepley *subpointIS = mesh->subpointIS; 4047e6ccafaeSMatthew G Knepley PetscFunctionReturn(0); 4048e6ccafaeSMatthew G Knepley } 4049559a1558SMatthew G. Knepley 4050559a1558SMatthew G. Knepley /*@ 4051a6e0b375SMatthew G. Knepley DMGetEnclosureRelation - Get the relationship between dmA and dmB 4052559a1558SMatthew G. Knepley 4053559a1558SMatthew G. Knepley Input Parameters: 4054a6e0b375SMatthew G. Knepley + dmA - The first DM 4055a6e0b375SMatthew G. Knepley - dmB - The second DM 4056559a1558SMatthew G. Knepley 4057559a1558SMatthew G. Knepley Output Parameter: 4058a6e0b375SMatthew G. Knepley . rel - The relation of dmA to dmB 4059559a1558SMatthew G. Knepley 4060a6e0b375SMatthew G. Knepley Level: intermediate 4061559a1558SMatthew G. Knepley 4062db781477SPatrick Sanan .seealso: `DMGetEnclosurePoint()` 4063559a1558SMatthew G. Knepley @*/ 4064d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetEnclosureRelation(DM dmA, DM dmB, DMEnclosureType *rel) 4065d71ae5a4SJacob Faibussowitsch { 4066a6e0b375SMatthew G. Knepley DM plexA, plexB, sdm; 4067559a1558SMatthew G. Knepley DMLabel spmap; 4068a6e0b375SMatthew G. Knepley PetscInt pStartA, pEndA, pStartB, pEndB, NpA, NpB; 4069559a1558SMatthew G. Knepley 407044171101SMatthew G. Knepley PetscFunctionBegin; 4071a6e0b375SMatthew G. Knepley PetscValidPointer(rel, 3); 4072a6e0b375SMatthew G. Knepley *rel = DM_ENC_NONE; 4073a6e0b375SMatthew G. Knepley if (!dmA || !dmB) PetscFunctionReturn(0); 4074a6e0b375SMatthew G. Knepley PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 4075064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 40769371c9d4SSatish Balay if (dmA == dmB) { 40779371c9d4SSatish Balay *rel = DM_ENC_EQUALITY; 40789371c9d4SSatish Balay PetscFunctionReturn(0); 40799371c9d4SSatish Balay } 40809566063dSJacob Faibussowitsch PetscCall(DMConvert(dmA, DMPLEX, &plexA)); 40819566063dSJacob Faibussowitsch PetscCall(DMConvert(dmB, DMPLEX, &plexB)); 40829566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexA, &pStartA, &pEndA)); 40839566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexB, &pStartB, &pEndB)); 4084a6e0b375SMatthew G. Knepley /* Assumption 1: subDMs have smaller charts than the DMs that they originate from 4085a6e0b375SMatthew G. Knepley - The degenerate case of a subdomain which includes all of the domain on some process can be treated as equality */ 4086a6e0b375SMatthew G. Knepley if ((pStartA == pStartB) && (pEndA == pEndB)) { 4087a6e0b375SMatthew G. Knepley *rel = DM_ENC_EQUALITY; 4088a6e0b375SMatthew G. Knepley goto end; 4089559a1558SMatthew G. Knepley } 4090a6e0b375SMatthew G. Knepley NpA = pEndA - pStartA; 4091a6e0b375SMatthew G. Knepley NpB = pEndB - pStartB; 4092a6e0b375SMatthew G. Knepley if (NpA == NpB) goto end; 4093a6e0b375SMatthew G. Knepley sdm = NpA > NpB ? plexB : plexA; /* The other is the original, enclosing dm */ 40949566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointMap(sdm, &spmap)); 4095a6e0b375SMatthew G. Knepley if (!spmap) goto end; 4096a6e0b375SMatthew G. Knepley /* TODO Check the space mapped to by subpointMap is same size as dm */ 4097a6e0b375SMatthew G. Knepley if (NpA > NpB) { 4098a6e0b375SMatthew G. Knepley *rel = DM_ENC_SUPERMESH; 4099a6e0b375SMatthew G. Knepley } else { 4100a6e0b375SMatthew G. Knepley *rel = DM_ENC_SUBMESH; 4101a6e0b375SMatthew G. Knepley } 4102a6e0b375SMatthew G. Knepley end: 41039566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plexA)); 41049566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plexB)); 4105559a1558SMatthew G. Knepley PetscFunctionReturn(0); 4106559a1558SMatthew G. Knepley } 410744171101SMatthew G. Knepley 410844171101SMatthew G. Knepley /*@ 4109a6e0b375SMatthew G. Knepley DMGetEnclosurePoint - Get the point pA in dmA which corresponds to the point pB in dmB 411044171101SMatthew G. Knepley 411144171101SMatthew G. Knepley Input Parameters: 4112a6e0b375SMatthew G. Knepley + dmA - The first DM 4113a6e0b375SMatthew G. Knepley . dmB - The second DM 4114a6e0b375SMatthew G. Knepley . etype - The type of enclosure relation that dmA has to dmB 4115a6e0b375SMatthew G. Knepley - pB - A point of dmB 411644171101SMatthew G. Knepley 411744171101SMatthew G. Knepley Output Parameter: 4118a6e0b375SMatthew G. Knepley . pA - The corresponding point of dmA 411944171101SMatthew G. Knepley 4120a6e0b375SMatthew G. Knepley Level: intermediate 412144171101SMatthew G. Knepley 4122db781477SPatrick Sanan .seealso: `DMGetEnclosureRelation()` 412344171101SMatthew G. Knepley @*/ 4124d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetEnclosurePoint(DM dmA, DM dmB, DMEnclosureType etype, PetscInt pB, PetscInt *pA) 4125d71ae5a4SJacob Faibussowitsch { 4126a6e0b375SMatthew G. Knepley DM sdm; 4127a6e0b375SMatthew G. Knepley IS subpointIS; 4128a6e0b375SMatthew G. Knepley const PetscInt *subpoints; 4129a6e0b375SMatthew G. Knepley PetscInt numSubpoints; 413044171101SMatthew G. Knepley 413144171101SMatthew G. Knepley PetscFunctionBegin; 4132a6e0b375SMatthew G. Knepley /* TODO Cache the IS, making it look like an index */ 4133a6e0b375SMatthew G. Knepley switch (etype) { 4134a6e0b375SMatthew G. Knepley case DM_ENC_SUPERMESH: 4135a6e0b375SMatthew G. Knepley sdm = dmB; 41369566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(sdm, &subpointIS)); 41379566063dSJacob Faibussowitsch PetscCall(ISGetIndices(subpointIS, &subpoints)); 4138a6e0b375SMatthew G. Knepley *pA = subpoints[pB]; 41399566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(subpointIS, &subpoints)); 4140a6e0b375SMatthew G. Knepley break; 4141a6e0b375SMatthew G. Knepley case DM_ENC_SUBMESH: 4142a6e0b375SMatthew G. Knepley sdm = dmA; 41439566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(sdm, &subpointIS)); 41449566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(subpointIS, &numSubpoints)); 41459566063dSJacob Faibussowitsch PetscCall(ISGetIndices(subpointIS, &subpoints)); 41469566063dSJacob Faibussowitsch PetscCall(PetscFindInt(pB, numSubpoints, subpoints, pA)); 4147a6e0b375SMatthew G. Knepley if (*pA < 0) { 41489566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dmA, NULL, "-dm_enc_A_view")); 41499566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dmB, NULL, "-dm_enc_B_view")); 415063a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %" PetscInt_FMT " not found in submesh", pB); 4151a6e0b375SMatthew G. Knepley } 41529566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(subpointIS, &subpoints)); 4153a6e0b375SMatthew G. Knepley break; 4154a6e0b375SMatthew G. Knepley case DM_ENC_EQUALITY: 4155d71ae5a4SJacob Faibussowitsch case DM_ENC_NONE: 4156d71ae5a4SJacob Faibussowitsch *pA = pB; 4157d71ae5a4SJacob Faibussowitsch break; 41589371c9d4SSatish Balay case DM_ENC_UNKNOWN: { 4159a6e0b375SMatthew G. Knepley DMEnclosureType enc; 416044171101SMatthew G. Knepley 41619566063dSJacob Faibussowitsch PetscCall(DMGetEnclosureRelation(dmA, dmB, &enc)); 41629566063dSJacob Faibussowitsch PetscCall(DMGetEnclosurePoint(dmA, dmB, enc, pB, pA)); 41639371c9d4SSatish Balay } break; 4164d71ae5a4SJacob Faibussowitsch default: 4165d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_ARG_OUTOFRANGE, "Invalid enclosure type %d", (int)etype); 416644171101SMatthew G. Knepley } 416744171101SMatthew G. Knepley PetscFunctionReturn(0); 416844171101SMatthew G. Knepley } 4169