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 } 223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 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: 453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46412e9a14SMatthew G. Knepley } 473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48412e9a14SMatthew G. Knepley } 49412e9a14SMatthew G. Knepley 50*69941377SStefano Zampini PetscErrorCode DMPlexMarkBoundaryFaces_Internal(DM dm, PetscInt val, PetscInt cellHeight, DMLabel label, PetscBool missing_only) 51d71ae5a4SJacob Faibussowitsch { 52*69941377SStefano Zampini PetscInt depth, pStart, pEnd, fStart, fEnd, f, supportSize, nroots = -1, nleaves = -1, defval; 53429fa399SMatthew G. Knepley PetscSF sf; 5441e3e744Sksagiyam const PetscSFNode *iremote = NULL; 5541e3e744Sksagiyam const PetscInt *ilocal = NULL; 5641e3e744Sksagiyam PetscInt *leafData; 5730560a7bSMatthew G. Knepley 5830560a7bSMatthew G. Knepley PetscFunctionBegin; 5941e3e744Sksagiyam PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 6041e3e744Sksagiyam PetscCall(DMPlexGetDepth(dm, &depth)); 6141e3e744Sksagiyam if (depth >= cellHeight + 1) { 629566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight + 1, &fStart, &fEnd)); 6341e3e744Sksagiyam } else { 6441e3e744Sksagiyam /* Note DMPlexGetHeightStratum() returns fStart, fEnd = pStart, pEnd */ 6541e3e744Sksagiyam /* if height > depth, which is not what we want here. */ 6641e3e744Sksagiyam fStart = 0; 6741e3e744Sksagiyam fEnd = 0; 6841e3e744Sksagiyam } 69*69941377SStefano Zampini PetscCall(DMLabelGetDefaultValue(label, &defval)); 7041e3e744Sksagiyam PetscCall(PetscCalloc1(pEnd - pStart, &leafData)); 7141e3e744Sksagiyam leafData -= pStart; 7241e3e744Sksagiyam PetscCall(DMGetPointSF(dm, &sf)); 7341e3e744Sksagiyam if (sf) PetscCall(PetscSFGetGraph(sf, &nroots, &nleaves, &ilocal, &iremote)); 7441e3e744Sksagiyam if (sf && nroots >= 0) { 7541e3e744Sksagiyam PetscInt cStart, cEnd, c, i; 7641e3e744Sksagiyam PetscInt *rootData, *rootData1, *cellOwners, hasTwoSupportCells = -2; 7741e3e744Sksagiyam const PetscInt *support; 7841e3e744Sksagiyam PetscMPIInt rank; 7930560a7bSMatthew G. Knepley 8041e3e744Sksagiyam PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 8141e3e744Sksagiyam PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 8241e3e744Sksagiyam PetscCall(PetscCalloc3(pEnd - pStart, &rootData, pEnd - pStart, &rootData1, cEnd - cStart, &cellOwners)); 8341e3e744Sksagiyam rootData -= pStart; 8441e3e744Sksagiyam rootData1 -= pStart; 8541e3e744Sksagiyam for (c = cStart; c < cEnd; ++c) cellOwners[c - cStart] = (PetscInt)rank; 8641e3e744Sksagiyam for (i = 0; i < nleaves; ++i) { 8741e3e744Sksagiyam c = ilocal ? ilocal[i] : i; 8841e3e744Sksagiyam if (c >= cStart && c < cEnd) cellOwners[c - cStart] = iremote[i].rank; 8941e3e744Sksagiyam } 9041e3e744Sksagiyam for (f = fStart; f < fEnd; ++f) { 919566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, f, &supportSize)); 92e752be1aSMatthew G. Knepley if (supportSize == 1) { 9341e3e744Sksagiyam PetscCall(DMPlexGetSupport(dm, f, &support)); 9441e3e744Sksagiyam leafData[f] = cellOwners[support[0] - cStart]; 9541e3e744Sksagiyam } else { 9641e3e744Sksagiyam /* TODO: When using DMForest, we could have a parent facet (a coarse facet) */ 9741e3e744Sksagiyam /* supportSize of which alone does not tell us if it is an interior */ 9841e3e744Sksagiyam /* facet or an exterior facet. Those facets can be identified by checking */ 9941e3e744Sksagiyam /* if they are in the parent tree. We should probably skip those parent */ 10041e3e744Sksagiyam /* facets here, which will allow for including the following check, and */ 10141e3e744Sksagiyam /* see if they are exterior facets or not afterwards by checking if the */ 10241e3e744Sksagiyam /* children are exterior or not. */ 10341e3e744Sksagiyam /* PetscCheck(supportSize == 2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid facet support size (%" PetscInt_FMT ") on facet (%" PetscInt_FMT ")", supportSize, f); */ 10441e3e744Sksagiyam leafData[f] = hasTwoSupportCells; /* some negative PetscInt */ 105429fa399SMatthew G. Knepley } 10641e3e744Sksagiyam rootData[f] = leafData[f]; 10741e3e744Sksagiyam rootData1[f] = leafData[f]; 10841e3e744Sksagiyam } 10941e3e744Sksagiyam PetscCall(PetscSFReduceBegin(sf, MPIU_INT, leafData, rootData, MPI_MIN)); 11041e3e744Sksagiyam PetscCall(PetscSFReduceBegin(sf, MPIU_INT, leafData, rootData1, MPI_MAX)); 11141e3e744Sksagiyam PetscCall(PetscSFReduceEnd(sf, MPIU_INT, leafData, rootData, MPI_MIN)); 11241e3e744Sksagiyam PetscCall(PetscSFReduceEnd(sf, MPIU_INT, leafData, rootData1, MPI_MAX)); 11341e3e744Sksagiyam for (f = fStart; f < fEnd; ++f) { 11441e3e744Sksagiyam /* Store global support size of f. */ 11541e3e744Sksagiyam /* Facet f is an interior facet if and only if one of the following two is satisfied: */ 11641e3e744Sksagiyam /* 1. supportSize is 2 on some rank. */ 11741e3e744Sksagiyam /* 2. supportSize is 1 on any rank that can see f, but f is on a partition boundary; */ 11841e3e744Sksagiyam /* i.e., rootData[f] < rootData1[f]. */ 11941e3e744Sksagiyam rootData[f] = (rootData[f] == hasTwoSupportCells || (rootData[f] < rootData1[f])) ? 2 : 1; 12041e3e744Sksagiyam leafData[f] = rootData[f]; 12141e3e744Sksagiyam } 12241e3e744Sksagiyam PetscCall(PetscSFBcastBegin(sf, MPIU_INT, rootData, leafData, MPI_REPLACE)); 12341e3e744Sksagiyam PetscCall(PetscSFBcastEnd(sf, MPIU_INT, rootData, leafData, MPI_REPLACE)); 12441e3e744Sksagiyam rootData += pStart; 12541e3e744Sksagiyam rootData1 += pStart; 12641e3e744Sksagiyam PetscCall(PetscFree3(rootData, rootData1, cellOwners)); 12741e3e744Sksagiyam } else { 12841e3e744Sksagiyam for (f = fStart; f < fEnd; ++f) { 12941e3e744Sksagiyam PetscCall(DMPlexGetSupportSize(dm, f, &supportSize)); 13041e3e744Sksagiyam leafData[f] = supportSize; 13141e3e744Sksagiyam } 13241e3e744Sksagiyam } 13341e3e744Sksagiyam for (f = fStart; f < fEnd; ++f) { 13441e3e744Sksagiyam if (leafData[f] == 1) { 135e752be1aSMatthew G. Knepley if (val < 0) { 136e752be1aSMatthew G. Knepley PetscInt *closure = NULL; 137e752be1aSMatthew G. Knepley PetscInt clSize, cl, cval; 138e752be1aSMatthew G. Knepley 139*69941377SStefano Zampini PetscAssert(!missing_only, PETSC_COMM_SELF, PETSC_ERR_SUP, "Not implemented"); 1409566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, f, PETSC_TRUE, &clSize, &closure)); 141e752be1aSMatthew G. Knepley for (cl = 0; cl < clSize * 2; cl += 2) { 1429566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, closure[cl], &cval)); 143e752be1aSMatthew G. Knepley if (cval < 0) continue; 1449566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, f, cval)); 145e752be1aSMatthew G. Knepley break; 146e752be1aSMatthew G. Knepley } 1479566063dSJacob Faibussowitsch if (cl == clSize * 2) PetscCall(DMLabelSetValue(label, f, 1)); 1489566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, f, PETSC_TRUE, &clSize, &closure)); 149e752be1aSMatthew G. Knepley } else { 150*69941377SStefano Zampini if (missing_only) { 151*69941377SStefano Zampini PetscInt fval; 152*69941377SStefano Zampini PetscCall(DMLabelGetValue(label, f, &fval)); 153*69941377SStefano Zampini if (fval != defval) PetscCall(DMLabelClearValue(label, f, fval)); 154*69941377SStefano Zampini else PetscCall(DMLabelSetValue(label, f, val)); 155*69941377SStefano Zampini } else { 1569566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, f, val)); 157e752be1aSMatthew G. Knepley } 158*69941377SStefano Zampini } 15941e3e744Sksagiyam } else { 16041e3e744Sksagiyam /* TODO: See the above comment on DMForest */ 16141e3e744Sksagiyam /* PetscCheck(leafData[f] == 2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid facet support size (%" PetscInt_FMT ") on facet (%" PetscInt_FMT ")", leafData[f], f); */ 162e752be1aSMatthew G. Knepley } 16330560a7bSMatthew G. Knepley } 16441e3e744Sksagiyam leafData += pStart; 16541e3e744Sksagiyam PetscCall(PetscFree(leafData)); 1663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16730560a7bSMatthew G. Knepley } 16830560a7bSMatthew G. Knepley 169cd0c2139SMatthew G Knepley /*@ 170cd0c2139SMatthew G Knepley DMPlexMarkBoundaryFaces - Mark all faces on the boundary 171cd0c2139SMatthew G Knepley 17241e3e744Sksagiyam Collective 173cd0c2139SMatthew G Knepley 174d8d19677SJose E. Roman Input Parameters: 175429fa399SMatthew G. Knepley + dm - The original `DM` 17620f4b53cSBarry Smith - val - The marker value, or `PETSC_DETERMINE` to use some value in the closure (or 1 if none are found) 177cd0c2139SMatthew G Knepley 178cd0c2139SMatthew G Knepley Output Parameter: 17920f4b53cSBarry Smith . label - The `DMLabel` marking boundary faces with the given value 180429fa399SMatthew G. Knepley 181cd0c2139SMatthew G Knepley Level: developer 182cd0c2139SMatthew G Knepley 18320f4b53cSBarry Smith Note: 18441e3e744Sksagiyam This function will use the point `PetscSF` from the input `DM` and the ownership of the support cells to exclude points on the partition boundary from being marked. If you also wish to mark the partition boundary, you can use `DMSetPointSF()` to temporarily set it to `NULL`, and then reset it to the original object after the call. 18541e3e744Sksagiyam 18641e3e744Sksagiyam In DMForest there can be facets support sizes of which alone can not determine whether they are on the boundary. Currently, this function is not guaranteed to produce the correct result in such case. 18720f4b53cSBarry Smith 1881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLabelCreate()`, `DMCreateLabel()` 18909f723d9SJed Brown @*/ 190d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMarkBoundaryFaces(DM dm, PetscInt val, DMLabel label) 191d71ae5a4SJacob Faibussowitsch { 192827c4036SVaclav Hapla DMPlexInterpolatedFlag flg; 193cd0c2139SMatthew G Knepley 194cd0c2139SMatthew G Knepley PetscFunctionBegin; 195827c4036SVaclav Hapla PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1969566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &flg)); 19708401ef6SPierre Jolivet PetscCheck(flg == DMPLEX_INTERPOLATED_FULL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not fully interpolated on this rank"); 198*69941377SStefano Zampini PetscCall(DMPlexMarkBoundaryFaces_Internal(dm, val, 0, label, PETSC_FALSE)); 1993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 200cd0c2139SMatthew G Knepley } 201cd0c2139SMatthew G Knepley 202d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexLabelComplete_Internal(DM dm, DMLabel label, PetscBool completeCells) 203d71ae5a4SJacob Faibussowitsch { 204b0bf5782SToby Isaac IS valueIS; 205ac51f24eSSander Arens PetscSF sfPoint; 206b0bf5782SToby Isaac const PetscInt *values; 207ac51f24eSSander Arens PetscInt numValues, v, cStart, cEnd, nroots; 208b0bf5782SToby Isaac 209b0bf5782SToby Isaac PetscFunctionBegin; 2109566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 2119566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 2129566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 2139566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 214b0bf5782SToby Isaac for (v = 0; v < numValues; ++v) { 215b0bf5782SToby Isaac IS pointIS; 216b0bf5782SToby Isaac const PetscInt *points; 217b0bf5782SToby Isaac PetscInt numPoints, p; 218b0bf5782SToby Isaac 2199566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, values[v], &numPoints)); 2209566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, values[v], &pointIS)); 2219566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 222b0bf5782SToby Isaac for (p = 0; p < numPoints; ++p) { 223b0bf5782SToby Isaac PetscInt q = points[p]; 224b0bf5782SToby Isaac PetscInt *closure = NULL; 225b0bf5782SToby Isaac PetscInt closureSize, c; 226b0bf5782SToby Isaac 227b0bf5782SToby Isaac if (cStart <= q && q < cEnd && !completeCells) { /* skip cells */ 228b0bf5782SToby Isaac continue; 229b0bf5782SToby Isaac } 2309566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, q, PETSC_TRUE, &closureSize, &closure)); 23148a46eb9SPierre Jolivet for (c = 0; c < closureSize * 2; c += 2) PetscCall(DMLabelSetValue(label, closure[c], values[v])); 2329566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, q, PETSC_TRUE, &closureSize, &closure)); 233b0bf5782SToby Isaac } 2349566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 2359566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 236b0bf5782SToby Isaac } 2379566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 2389566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 2399566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 2409566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL)); 241ac51f24eSSander Arens if (nroots >= 0) { 24226279d81SSanderA DMLabel lblRoots, lblLeaves; 24326279d81SSanderA IS valueIS, pointIS; 24426279d81SSanderA const PetscInt *values; 24526279d81SSanderA PetscInt numValues, v; 24626279d81SSanderA 24726279d81SSanderA /* Pull point contributions from remote leaves into local roots */ 2489566063dSJacob Faibussowitsch PetscCall(DMLabelGather(label, sfPoint, &lblLeaves)); 2499566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(lblLeaves, &valueIS)); 2509566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(valueIS, &numValues)); 2519566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 25226279d81SSanderA for (v = 0; v < numValues; ++v) { 25326279d81SSanderA const PetscInt value = values[v]; 25426279d81SSanderA 2559566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(lblLeaves, value, &pointIS)); 2569566063dSJacob Faibussowitsch PetscCall(DMLabelInsertIS(label, pointIS, value)); 2579566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 25826279d81SSanderA } 2599566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 2609566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 2619566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblLeaves)); 26226279d81SSanderA /* Push point contributions from roots into remote leaves */ 2639566063dSJacob Faibussowitsch PetscCall(DMLabelDistribute(label, sfPoint, &lblRoots)); 2649566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(lblRoots, &valueIS)); 2659566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(valueIS, &numValues)); 2669566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 26726279d81SSanderA for (v = 0; v < numValues; ++v) { 26826279d81SSanderA const PetscInt value = values[v]; 26926279d81SSanderA 2709566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(lblRoots, value, &pointIS)); 2719566063dSJacob Faibussowitsch PetscCall(DMLabelInsertIS(label, pointIS, value)); 2729566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 27326279d81SSanderA } 2749566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 2759566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 2769566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&lblRoots)); 27726279d81SSanderA } 2783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 279b0bf5782SToby Isaac } 280b0bf5782SToby Isaac 2812be2b188SMatthew G Knepley /*@ 2822be2b188SMatthew G Knepley DMPlexLabelComplete - Starting with a label marking points on a surface, we add the transitive closure to the surface 2832be2b188SMatthew G Knepley 2842be2b188SMatthew G Knepley Input Parameters: 28520f4b53cSBarry Smith + dm - The `DM` 28620f4b53cSBarry Smith - label - A `DMLabel` marking the surface points 2872be2b188SMatthew G Knepley 2882be2b188SMatthew G Knepley Output Parameter: 28920f4b53cSBarry Smith . label - A `DMLabel` marking all surface points in the transitive closure 2902be2b188SMatthew G Knepley 2912be2b188SMatthew G Knepley Level: developer 2922be2b188SMatthew G Knepley 2931cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexLabelCohesiveComplete()` 2942be2b188SMatthew G Knepley @*/ 295d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelComplete(DM dm, DMLabel label) 296d71ae5a4SJacob Faibussowitsch { 2972be2b188SMatthew G Knepley PetscFunctionBegin; 2989566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete_Internal(dm, label, PETSC_TRUE)); 2993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3002be2b188SMatthew G Knepley } 3012be2b188SMatthew G Knepley 3026cf0e42fSMatthew G. Knepley /*@ 303a6e0b375SMatthew G. Knepley DMPlexLabelAddCells - Starting with a label marking points on a surface, we add a cell for each point 3046cf0e42fSMatthew G. Knepley 3056cf0e42fSMatthew G. Knepley Input Parameters: 30620f4b53cSBarry Smith + dm - The `DM` 30720f4b53cSBarry Smith - label - A `DMLabel` marking the surface points 3086cf0e42fSMatthew G. Knepley 3096cf0e42fSMatthew G. Knepley Output Parameter: 31020f4b53cSBarry Smith . label - A `DMLabel` incorporating cells 3116cf0e42fSMatthew G. Knepley 3126cf0e42fSMatthew G. Knepley Level: developer 3136cf0e42fSMatthew G. Knepley 31420f4b53cSBarry Smith Note: 31520f4b53cSBarry Smith The cells allow FEM boundary conditions to be applied using the cell geometry 3166cf0e42fSMatthew G. Knepley 3171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexLabelAddFaceCells()`, `DMPlexLabelComplete()`, `DMPlexLabelCohesiveComplete()` 3186cf0e42fSMatthew G. Knepley @*/ 319d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelAddCells(DM dm, DMLabel label) 320d71ae5a4SJacob Faibussowitsch { 3216cf0e42fSMatthew G. Knepley IS valueIS; 3226cf0e42fSMatthew G. Knepley const PetscInt *values; 3239df54392SMatthew G. Knepley PetscInt numValues, v, csStart, csEnd, chStart, chEnd; 3246cf0e42fSMatthew G. Knepley 3256cf0e42fSMatthew G. Knepley PetscFunctionBegin; 3269df54392SMatthew G. Knepley PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &csStart, &csEnd)); 3279df54392SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, 0, &chStart, &chEnd)); 3289566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 3299566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 3309566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 3316cf0e42fSMatthew G. Knepley for (v = 0; v < numValues; ++v) { 3326cf0e42fSMatthew G. Knepley IS pointIS; 3336cf0e42fSMatthew G. Knepley const PetscInt *points; 3346cf0e42fSMatthew G. Knepley PetscInt numPoints, p; 3356cf0e42fSMatthew G. Knepley 3369566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, values[v], &numPoints)); 3379566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, values[v], &pointIS)); 3389566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 3396cf0e42fSMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 3409df54392SMatthew G. Knepley const PetscInt point = points[p]; 3416cf0e42fSMatthew G. Knepley PetscInt *closure = NULL; 3429df54392SMatthew G. Knepley PetscInt closureSize, cl, h, pStart, pEnd, cStart, cEnd; 3439df54392SMatthew G. Knepley 3449df54392SMatthew G. Knepley // If the point is a hybrid, allow hybrid cells 3459df54392SMatthew G. Knepley PetscCall(DMPlexGetPointHeight(dm, point, &h)); 3469df54392SMatthew G. Knepley PetscCall(DMPlexGetSimplexOrBoxCells(dm, h, &pStart, &pEnd)); 3479df54392SMatthew G. Knepley if (point >= pStart && point < pEnd) { 3489df54392SMatthew G. Knepley cStart = csStart; 3499df54392SMatthew G. Knepley cEnd = csEnd; 3509df54392SMatthew G. Knepley } else { 3519df54392SMatthew G. Knepley cStart = chStart; 3529df54392SMatthew G. Knepley cEnd = chEnd; 3539df54392SMatthew G. Knepley } 3546cf0e42fSMatthew G. Knepley 3559566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closure)); 35622eabd52SMatthew G. Knepley for (cl = closureSize - 1; cl > 0; --cl) { 357a6e0b375SMatthew G. Knepley const PetscInt cell = closure[cl * 2]; 3589371c9d4SSatish Balay if ((cell >= cStart) && (cell < cEnd)) { 3599371c9d4SSatish Balay PetscCall(DMLabelSetValue(label, cell, values[v])); 3609371c9d4SSatish Balay break; 3619371c9d4SSatish Balay } 36222eabd52SMatthew G. Knepley } 3639566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closure)); 3646cf0e42fSMatthew G. Knepley } 3659566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 3669566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 3676cf0e42fSMatthew G. Knepley } 3689566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 3699566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 3703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3716cf0e42fSMatthew G. Knepley } 3726cf0e42fSMatthew G. Knepley 373f402d5e4SToby Isaac /*@ 374a6e0b375SMatthew G. Knepley DMPlexLabelAddFaceCells - Starting with a label marking faces on a surface, we add a cell for each face 375a6e0b375SMatthew G. Knepley 376a6e0b375SMatthew G. Knepley Input Parameters: 37720f4b53cSBarry Smith + dm - The `DM` 37820f4b53cSBarry Smith - label - A `DMLabel` marking the surface points 379a6e0b375SMatthew G. Knepley 380a6e0b375SMatthew G. Knepley Output Parameter: 38120f4b53cSBarry Smith . label - A `DMLabel` incorporating cells 382a6e0b375SMatthew G. Knepley 383a6e0b375SMatthew G. Knepley Level: developer 384a6e0b375SMatthew G. Knepley 38520f4b53cSBarry Smith Note: 38620f4b53cSBarry Smith The cells allow FEM boundary conditions to be applied using the cell geometry 387a6e0b375SMatthew G. Knepley 3881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexLabelAddCells()`, `DMPlexLabelComplete()`, `DMPlexLabelCohesiveComplete()` 389a6e0b375SMatthew G. Knepley @*/ 390d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelAddFaceCells(DM dm, DMLabel label) 391d71ae5a4SJacob Faibussowitsch { 392a6e0b375SMatthew G. Knepley IS valueIS; 393a6e0b375SMatthew G. Knepley const PetscInt *values; 394a6e0b375SMatthew G. Knepley PetscInt numValues, v, cStart, cEnd, fStart, fEnd; 395a6e0b375SMatthew G. Knepley 396a6e0b375SMatthew G. Knepley PetscFunctionBegin; 3979566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 3989566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 3999566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 4009566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 4019566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 402a6e0b375SMatthew G. Knepley for (v = 0; v < numValues; ++v) { 403a6e0b375SMatthew G. Knepley IS pointIS; 404a6e0b375SMatthew G. Knepley const PetscInt *points; 405a6e0b375SMatthew G. Knepley PetscInt numPoints, p; 406a6e0b375SMatthew G. Knepley 4079566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, values[v], &numPoints)); 4089566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, values[v], &pointIS)); 4099566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 410a6e0b375SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 411a6e0b375SMatthew G. Knepley const PetscInt face = points[p]; 412a6e0b375SMatthew G. Knepley PetscInt *closure = NULL; 413a6e0b375SMatthew G. Knepley PetscInt closureSize, cl; 414a6e0b375SMatthew G. Knepley 415a6e0b375SMatthew G. Knepley if ((face < fStart) || (face >= fEnd)) continue; 4169566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, face, PETSC_FALSE, &closureSize, &closure)); 417a6e0b375SMatthew G. Knepley for (cl = closureSize - 1; cl > 0; --cl) { 418a6e0b375SMatthew G. Knepley const PetscInt cell = closure[cl * 2]; 4199371c9d4SSatish Balay if ((cell >= cStart) && (cell < cEnd)) { 4209371c9d4SSatish Balay PetscCall(DMLabelSetValue(label, cell, values[v])); 4219371c9d4SSatish Balay break; 4229371c9d4SSatish Balay } 423a6e0b375SMatthew G. Knepley } 4249566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, face, PETSC_FALSE, &closureSize, &closure)); 425a6e0b375SMatthew G. Knepley } 4269566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 4279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 428a6e0b375SMatthew G. Knepley } 4299566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 4309566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 4313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 432a6e0b375SMatthew G. Knepley } 433a6e0b375SMatthew G. Knepley 434a6e0b375SMatthew G. Knepley /*@ 435f402d5e4SToby Isaac DMPlexLabelClearCells - Remove cells from a label 436f402d5e4SToby Isaac 437f402d5e4SToby Isaac Input Parameters: 43820f4b53cSBarry Smith + dm - The `DM` 43920f4b53cSBarry Smith - label - A `DMLabel` marking surface points and their adjacent cells 440f402d5e4SToby Isaac 441f402d5e4SToby Isaac Output Parameter: 44220f4b53cSBarry Smith . label - A `DMLabel` without cells 443f402d5e4SToby Isaac 444f402d5e4SToby Isaac Level: developer 445f402d5e4SToby Isaac 44620f4b53cSBarry Smith Note: 44720f4b53cSBarry Smith This undoes `DMPlexLabelAddCells()` or `DMPlexLabelAddFaceCells()` 448f402d5e4SToby Isaac 4491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexLabelComplete()`, `DMPlexLabelCohesiveComplete()`, `DMPlexLabelAddCells()` 450f402d5e4SToby Isaac @*/ 451d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelClearCells(DM dm, DMLabel label) 452d71ae5a4SJacob Faibussowitsch { 453f402d5e4SToby Isaac IS valueIS; 454f402d5e4SToby Isaac const PetscInt *values; 455485ad865SMatthew G. Knepley PetscInt numValues, v, cStart, cEnd; 456f402d5e4SToby Isaac 457f402d5e4SToby Isaac PetscFunctionBegin; 4589566063dSJacob Faibussowitsch PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd)); 4599566063dSJacob Faibussowitsch PetscCall(DMLabelGetNumValues(label, &numValues)); 4609566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 4619566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 462f402d5e4SToby Isaac for (v = 0; v < numValues; ++v) { 463f402d5e4SToby Isaac IS pointIS; 464f402d5e4SToby Isaac const PetscInt *points; 465f402d5e4SToby Isaac PetscInt numPoints, p; 466f402d5e4SToby Isaac 4679566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(label, values[v], &numPoints)); 4689566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, values[v], &pointIS)); 4699566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 470f402d5e4SToby Isaac for (p = 0; p < numPoints; ++p) { 471f402d5e4SToby Isaac PetscInt point = points[p]; 472f402d5e4SToby Isaac 47348a46eb9SPierre Jolivet if (point >= cStart && point < cEnd) PetscCall(DMLabelClearValue(label, point, values[v])); 474f402d5e4SToby Isaac } 4759566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 4769566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 477f402d5e4SToby Isaac } 4789566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 4799566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 4803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 481f402d5e4SToby Isaac } 482f402d5e4SToby Isaac 48359eef20bSToby Isaac /* take (oldEnd, added) pairs, ordered by height and convert them to (oldstart, newstart) pairs, ordered by ascending 48459eef20bSToby Isaac * index (skipping first, which is (0,0)) */ 485d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexShiftPointSetUp_Internal(PetscInt depth, PetscInt depthShift[]) 486d71ae5a4SJacob Faibussowitsch { 4872582d50cSToby Isaac PetscInt d, off = 0; 4882582d50cSToby Isaac 4892582d50cSToby Isaac PetscFunctionBegin; 49059eef20bSToby Isaac /* sort by (oldend): yes this is an O(n^2) sort, we expect depth <= 3 */ 4910974a383SToby Isaac for (d = 0; d < depth; d++) { 4922582d50cSToby Isaac PetscInt firstd = d; 4930974a383SToby Isaac PetscInt firstStart = depthShift[2 * d]; 4942582d50cSToby Isaac PetscInt e; 4952582d50cSToby Isaac 4962582d50cSToby Isaac for (e = d + 1; e <= depth; e++) { 4972582d50cSToby Isaac if (depthShift[2 * e] < firstStart) { 4982582d50cSToby Isaac firstd = e; 4992582d50cSToby Isaac firstStart = depthShift[2 * d]; 5002582d50cSToby Isaac } 5012582d50cSToby Isaac } 5022582d50cSToby Isaac if (firstd != d) { 5032582d50cSToby Isaac PetscInt swap[2]; 5042582d50cSToby Isaac 5052582d50cSToby Isaac e = firstd; 5062582d50cSToby Isaac swap[0] = depthShift[2 * d]; 5072582d50cSToby Isaac swap[1] = depthShift[2 * d + 1]; 5082582d50cSToby Isaac depthShift[2 * d] = depthShift[2 * e]; 5092582d50cSToby Isaac depthShift[2 * d + 1] = depthShift[2 * e + 1]; 5102582d50cSToby Isaac depthShift[2 * e] = swap[0]; 5112582d50cSToby Isaac depthShift[2 * e + 1] = swap[1]; 5122582d50cSToby Isaac } 5132582d50cSToby Isaac } 5142582d50cSToby Isaac /* convert (oldstart, added) to (oldstart, newstart) */ 5150974a383SToby Isaac for (d = 0; d <= depth; d++) { 5162582d50cSToby Isaac off += depthShift[2 * d + 1]; 51759eef20bSToby Isaac depthShift[2 * d + 1] = depthShift[2 * d] + off; 5182582d50cSToby Isaac } 5193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5202582d50cSToby Isaac } 5212582d50cSToby Isaac 5222582d50cSToby Isaac /* depthShift is a list of (old, new) pairs */ 523d71ae5a4SJacob Faibussowitsch static inline PetscInt DMPlexShiftPoint_Internal(PetscInt p, PetscInt depth, PetscInt depthShift[]) 524d71ae5a4SJacob Faibussowitsch { 5252582d50cSToby Isaac PetscInt d; 5262582d50cSToby Isaac PetscInt newOff = 0; 5272582d50cSToby Isaac 5282582d50cSToby Isaac for (d = 0; d <= depth; d++) { 5292582d50cSToby Isaac if (p < depthShift[2 * d]) return p + newOff; 5302582d50cSToby Isaac else newOff = depthShift[2 * d + 1] - depthShift[2 * d]; 5312582d50cSToby Isaac } 5320974a383SToby Isaac return p + newOff; 5332582d50cSToby Isaac } 5342582d50cSToby Isaac 5352582d50cSToby Isaac /* depthShift is a list of (old, new) pairs */ 536d71ae5a4SJacob Faibussowitsch static inline PetscInt DMPlexShiftPointInverse_Internal(PetscInt p, PetscInt depth, PetscInt depthShift[]) 537d71ae5a4SJacob Faibussowitsch { 5382582d50cSToby Isaac PetscInt d; 5392582d50cSToby Isaac PetscInt newOff = 0; 5402582d50cSToby Isaac 5412582d50cSToby Isaac for (d = 0; d <= depth; d++) { 5422582d50cSToby Isaac if (p < depthShift[2 * d + 1]) return p + newOff; 5432582d50cSToby Isaac else newOff = depthShift[2 * d] - depthShift[2 * d + 1]; 5442582d50cSToby Isaac } 5450974a383SToby Isaac return p + newOff; 546cd0c2139SMatthew G Knepley } 547cd0c2139SMatthew G Knepley 548d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexShiftSizes_Internal(DM dm, PetscInt depthShift[], DM dmNew) 549d71ae5a4SJacob Faibussowitsch { 550cd0c2139SMatthew G Knepley PetscInt depth = 0, d, pStart, pEnd, p; 551fa8e8ae5SToby Isaac DMLabel depthLabel; 552cd0c2139SMatthew G Knepley 553cd0c2139SMatthew G Knepley PetscFunctionBegin; 5549566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 5553ba16761SJacob Faibussowitsch if (depth < 0) PetscFunctionReturn(PETSC_SUCCESS); 556cd0c2139SMatthew G Knepley /* Step 1: Expand chart */ 5579566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 5580974a383SToby Isaac pEnd = DMPlexShiftPoint_Internal(pEnd, depth, depthShift); 5599566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dmNew, pStart, pEnd)); 5609566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dmNew, "depth")); 5619566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dmNew, &depthLabel)); 5629566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dmNew, "celltype")); 563cd0c2139SMatthew G Knepley /* Step 2: Set cone and support sizes */ 564cd0c2139SMatthew G Knepley for (d = 0; d <= depth; ++d) { 565fa8e8ae5SToby Isaac PetscInt pStartNew, pEndNew; 566fa8e8ae5SToby Isaac IS pIS; 567fa8e8ae5SToby Isaac 5689566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd)); 569fa8e8ae5SToby Isaac pStartNew = DMPlexShiftPoint_Internal(pStart, depth, depthShift); 570fa8e8ae5SToby Isaac pEndNew = DMPlexShiftPoint_Internal(pEnd, depth, depthShift); 5719566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, pEndNew - pStartNew, pStartNew, 1, &pIS)); 5729566063dSJacob Faibussowitsch PetscCall(DMLabelSetStratumIS(depthLabel, d, pIS)); 5739566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pIS)); 574cd0c2139SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 5752582d50cSToby Isaac PetscInt newp = DMPlexShiftPoint_Internal(p, depth, depthShift); 576cd0c2139SMatthew G Knepley PetscInt size; 577412e9a14SMatthew G. Knepley DMPolytopeType ct; 578cd0c2139SMatthew G Knepley 5799566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &size)); 5809566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(dmNew, newp, size)); 5819566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &size)); 5829566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(dmNew, newp, size)); 5839566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, p, &ct)); 5849566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(dmNew, newp, ct)); 585cd0c2139SMatthew G Knepley } 586cd0c2139SMatthew G Knepley } 5873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 588cd0c2139SMatthew G Knepley } 589cd0c2139SMatthew G Knepley 590d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexShiftPoints_Internal(DM dm, PetscInt depthShift[], DM dmNew) 591d71ae5a4SJacob Faibussowitsch { 5922582d50cSToby Isaac PetscInt *newpoints; 5932582d50cSToby Isaac PetscInt depth = 0, maxConeSize, maxSupportSize, maxConeSizeNew, maxSupportSizeNew, pStart, pEnd, p; 594cd0c2139SMatthew G Knepley 595cd0c2139SMatthew G Knepley PetscFunctionBegin; 5969566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 5973ba16761SJacob Faibussowitsch if (depth < 0) PetscFunctionReturn(PETSC_SUCCESS); 5989566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 5999566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dmNew, &maxConeSizeNew, &maxSupportSizeNew)); 6009566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(PetscMax(PetscMax(maxConeSize, maxSupportSize), PetscMax(maxConeSizeNew, maxSupportSizeNew)), &newpoints)); 601cd0c2139SMatthew G Knepley /* Step 5: Set cones and supports */ 6029566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 603cd0c2139SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 604cd0c2139SMatthew G Knepley const PetscInt *points = NULL, *orientations = NULL; 6052582d50cSToby Isaac PetscInt size, sizeNew, i, newp = DMPlexShiftPoint_Internal(p, depth, depthShift); 606cd0c2139SMatthew G Knepley 6079566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, p, &size)); 6089566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, p, &points)); 6099566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, p, &orientations)); 610ad540459SPierre Jolivet for (i = 0; i < size; ++i) newpoints[i] = DMPlexShiftPoint_Internal(points[i], depth, depthShift); 6119566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dmNew, newp, newpoints)); 6129566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dmNew, newp, orientations)); 6139566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, p, &size)); 6149566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmNew, newp, &sizeNew)); 6159566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, p, &points)); 616ad540459SPierre Jolivet for (i = 0; i < size; ++i) newpoints[i] = DMPlexShiftPoint_Internal(points[i], depth, depthShift); 617dcbb62e8SMatthew G. Knepley for (i = size; i < sizeNew; ++i) newpoints[i] = 0; 6189566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupport(dmNew, newp, newpoints)); 619cd0c2139SMatthew G Knepley } 6209566063dSJacob Faibussowitsch PetscCall(PetscFree(newpoints)); 6213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 622cd0c2139SMatthew G Knepley } 623cd0c2139SMatthew G Knepley 624d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexShiftCoordinates_Internal(DM dm, PetscInt depthShift[], DM dmNew) 625d71ae5a4SJacob Faibussowitsch { 626cd0c2139SMatthew G Knepley PetscSection coordSection, newCoordSection; 627cd0c2139SMatthew G Knepley Vec coordinates, newCoordinates; 628cd0c2139SMatthew G Knepley PetscScalar *coords, *newCoords; 629f2b8cce1SMatthew G. Knepley PetscInt coordSize, sStart, sEnd; 630f2b8cce1SMatthew G. Knepley PetscInt dim, depth = 0, cStart, cEnd, cStartNew, cEndNew, c, vStart, vEnd, vStartNew, vEndNew, v; 631f2b8cce1SMatthew G. Knepley PetscBool hasCells; 632cd0c2139SMatthew G Knepley 633cd0c2139SMatthew G Knepley PetscFunctionBegin; 6349566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dim)); 6359566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dmNew, dim)); 6369566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 637cd0c2139SMatthew G Knepley /* Step 8: Convert coordinates */ 6389566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 6399566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 6409566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dmNew, 0, &vStartNew, &vEndNew)); 6419566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dmNew, 0, &cStartNew, &cEndNew)); 6429566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 6439566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &newCoordSection)); 6449566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(newCoordSection, 1)); 6459566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(newCoordSection, 0, dim)); 6469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(coordSection, &sStart, &sEnd)); 647f2b8cce1SMatthew G. Knepley hasCells = sStart == cStart ? PETSC_TRUE : PETSC_FALSE; 6489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(newCoordSection, hasCells ? cStartNew : vStartNew, vEndNew)); 649f2b8cce1SMatthew G. Knepley if (hasCells) { 650f2b8cce1SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 651f2b8cce1SMatthew G. Knepley PetscInt cNew = DMPlexShiftPoint_Internal(c, depth, depthShift), dof; 652f2b8cce1SMatthew G. Knepley 6539566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, c, &dof)); 6549566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(newCoordSection, cNew, dof)); 6559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(newCoordSection, cNew, 0, dof)); 656f2b8cce1SMatthew G. Knepley } 657f2b8cce1SMatthew G. Knepley } 658cd0c2139SMatthew G Knepley for (v = vStartNew; v < vEndNew; ++v) { 6599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(newCoordSection, v, dim)); 6609566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(newCoordSection, v, 0, dim)); 661cd0c2139SMatthew G Knepley } 6629566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(newCoordSection)); 6639566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateSection(dmNew, PETSC_DETERMINE, newCoordSection)); 6649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(newCoordSection, &coordSize)); 6659566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &newCoordinates)); 6669566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)newCoordinates, "coordinates")); 6679566063dSJacob Faibussowitsch PetscCall(VecSetSizes(newCoordinates, coordSize, PETSC_DETERMINE)); 6689566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(newCoordinates, dim)); 6699566063dSJacob Faibussowitsch PetscCall(VecSetType(newCoordinates, VECSTANDARD)); 6709566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmNew, newCoordinates)); 6719566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 6729566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 6739566063dSJacob Faibussowitsch PetscCall(VecGetArray(newCoordinates, &newCoords)); 674f2b8cce1SMatthew G. Knepley if (hasCells) { 675f2b8cce1SMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 676f2b8cce1SMatthew G. Knepley PetscInt cNew = DMPlexShiftPoint_Internal(c, depth, depthShift), dof, off, noff, d; 677f2b8cce1SMatthew G. Knepley 6789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, c, &dof)); 6799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, c, &off)); 6809566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(newCoordSection, cNew, &noff)); 681f2b8cce1SMatthew G. Knepley for (d = 0; d < dof; ++d) newCoords[noff + d] = coords[off + d]; 682f2b8cce1SMatthew G. Knepley } 683f2b8cce1SMatthew G. Knepley } 684cd0c2139SMatthew G Knepley for (v = vStart; v < vEnd; ++v) { 685cd0c2139SMatthew G Knepley PetscInt dof, off, noff, d; 686cd0c2139SMatthew G Knepley 6879566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, v, &dof)); 6889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v, &off)); 6899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(newCoordSection, DMPlexShiftPoint_Internal(v, depth, depthShift), &noff)); 690f2b8cce1SMatthew G. Knepley for (d = 0; d < dof; ++d) newCoords[noff + d] = coords[off + d]; 691cd0c2139SMatthew G Knepley } 6929566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 6939566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(newCoordinates, &newCoords)); 6949566063dSJacob Faibussowitsch PetscCall(VecDestroy(&newCoordinates)); 6959566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&newCoordSection)); 6963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 697cd0c2139SMatthew G Knepley } 698cd0c2139SMatthew G Knepley 699d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexShiftSF_Single(DM dm, PetscInt depthShift[], PetscSF sf, PetscSF sfNew) 700d71ae5a4SJacob Faibussowitsch { 701cd0c2139SMatthew G Knepley const PetscSFNode *remotePoints; 702cd0c2139SMatthew G Knepley PetscSFNode *gremotePoints; 703cd0c2139SMatthew G Knepley const PetscInt *localPoints; 704cd0c2139SMatthew G Knepley PetscInt *glocalPoints, *newLocation, *newRemoteLocation; 7050e33faafSMatthew G. Knepley PetscInt numRoots, numLeaves, l, pStart, pEnd, depth = 0, totShift = 0; 706cd0c2139SMatthew G Knepley 707cd0c2139SMatthew G Knepley PetscFunctionBegin; 7089566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 7099566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 7109566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints)); 7116e21efdcSToby Isaac totShift = DMPlexShiftPoint_Internal(pEnd, depth, depthShift) - pEnd; 712cd0c2139SMatthew G Knepley if (numRoots >= 0) { 7139566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(numRoots, &newLocation, pEnd - pStart, &newRemoteLocation)); 7140e33faafSMatthew G. Knepley for (l = 0; l < numRoots; ++l) newLocation[l] = DMPlexShiftPoint_Internal(l, depth, depthShift); 7159566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sf, MPIU_INT, newLocation, newRemoteLocation, MPI_REPLACE)); 7169566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sf, MPIU_INT, newLocation, newRemoteLocation, MPI_REPLACE)); 7179566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeaves, &glocalPoints)); 7189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numLeaves, &gremotePoints)); 719cd0c2139SMatthew G Knepley for (l = 0; l < numLeaves; ++l) { 7202582d50cSToby Isaac glocalPoints[l] = DMPlexShiftPoint_Internal(localPoints[l], depth, depthShift); 721cd0c2139SMatthew G Knepley gremotePoints[l].rank = remotePoints[l].rank; 722cd0c2139SMatthew G Knepley gremotePoints[l].index = newRemoteLocation[localPoints[l]]; 723cd0c2139SMatthew G Knepley } 7249566063dSJacob Faibussowitsch PetscCall(PetscFree2(newLocation, newRemoteLocation)); 7259566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sfNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER)); 7260e33faafSMatthew G. Knepley } 7273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7280e33faafSMatthew G. Knepley } 7290e33faafSMatthew G. Knepley 730d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexShiftSF_Internal(DM dm, PetscInt depthShift[], DM dmNew) 731d71ae5a4SJacob Faibussowitsch { 7320e33faafSMatthew G. Knepley PetscSF sfPoint, sfPointNew; 7330e33faafSMatthew G. Knepley PetscBool useNatural; 7340e33faafSMatthew G. Knepley 7350e33faafSMatthew G. Knepley PetscFunctionBegin; 7360e33faafSMatthew G. Knepley /* Step 9: Convert pointSF */ 7379566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 7389566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmNew, &sfPointNew)); 7399566063dSJacob Faibussowitsch PetscCall(DMPlexShiftSF_Single(dm, depthShift, sfPoint, sfPointNew)); 7400e33faafSMatthew G. Knepley /* Step 9b: Convert naturalSF */ 7419566063dSJacob Faibussowitsch PetscCall(DMGetUseNatural(dm, &useNatural)); 7420e33faafSMatthew G. Knepley if (useNatural) { 7430e33faafSMatthew G. Knepley PetscSF sfNat, sfNatNew; 7440e33faafSMatthew G. Knepley 7459566063dSJacob Faibussowitsch PetscCall(DMSetUseNatural(dmNew, useNatural)); 7469566063dSJacob Faibussowitsch PetscCall(DMGetNaturalSF(dm, &sfNat)); 7479566063dSJacob Faibussowitsch PetscCall(DMGetNaturalSF(dmNew, &sfNatNew)); 7489566063dSJacob Faibussowitsch PetscCall(DMPlexShiftSF_Single(dm, depthShift, sfNat, sfNatNew)); 749cd0c2139SMatthew G Knepley } 7503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 751cd0c2139SMatthew G Knepley } 752cd0c2139SMatthew G Knepley 753d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexShiftLabels_Internal(DM dm, PetscInt depthShift[], DM dmNew) 754d71ae5a4SJacob Faibussowitsch { 755d56405f8SMatthew G. Knepley PetscInt depth = 0, numLabels, l; 756cd0c2139SMatthew G Knepley 757cd0c2139SMatthew G Knepley PetscFunctionBegin; 7589566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 759cd0c2139SMatthew G Knepley /* Step 10: Convert labels */ 7609566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &numLabels)); 761cd0c2139SMatthew G Knepley for (l = 0; l < numLabels; ++l) { 762cd0c2139SMatthew G Knepley DMLabel label, newlabel; 763cd0c2139SMatthew G Knepley const char *lname; 764fa8e8ae5SToby Isaac PetscBool isDepth, isDim; 765cd0c2139SMatthew G Knepley IS valueIS; 766cd0c2139SMatthew G Knepley const PetscInt *values; 767cd0c2139SMatthew G Knepley PetscInt numValues, val; 768cd0c2139SMatthew G Knepley 7699566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &lname)); 7709566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(lname, "depth", &isDepth)); 771cd0c2139SMatthew G Knepley if (isDepth) continue; 7729566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(lname, "dim", &isDim)); 773fa8e8ae5SToby Isaac if (isDim) continue; 7749566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dmNew, lname)); 7759566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, lname, &label)); 7769566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dmNew, lname, &newlabel)); 7779566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(label, &val)); 7789566063dSJacob Faibussowitsch PetscCall(DMLabelSetDefaultValue(newlabel, val)); 7799566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 7809566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(valueIS, &numValues)); 7819566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 782cd0c2139SMatthew G Knepley for (val = 0; val < numValues; ++val) { 783cd0c2139SMatthew G Knepley IS pointIS; 784cd0c2139SMatthew G Knepley const PetscInt *points; 785cd0c2139SMatthew G Knepley PetscInt numPoints, p; 786cd0c2139SMatthew G Knepley 7879566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, values[val], &pointIS)); 7889566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &numPoints)); 7899566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 790cd0c2139SMatthew G Knepley for (p = 0; p < numPoints; ++p) { 7912582d50cSToby Isaac const PetscInt newpoint = DMPlexShiftPoint_Internal(points[p], depth, depthShift); 792cd0c2139SMatthew G Knepley 7939566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(newlabel, newpoint, values[val])); 794cd0c2139SMatthew G Knepley } 7959566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 7969566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 797cd0c2139SMatthew G Knepley } 7989566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 7999566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 800cd0c2139SMatthew G Knepley } 8013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 802d56405f8SMatthew G. Knepley } 803d56405f8SMatthew G. Knepley 804d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateVTKLabel_Internal(DM dm, PetscBool createGhostLabel, DM dmNew) 805d71ae5a4SJacob Faibussowitsch { 806d56405f8SMatthew G. Knepley PetscSF sfPoint; 807d56405f8SMatthew G. Knepley DMLabel vtkLabel, ghostLabel = NULL; 808d56405f8SMatthew G. Knepley const PetscSFNode *leafRemote; 809d56405f8SMatthew G. Knepley const PetscInt *leafLocal; 810d56405f8SMatthew G. Knepley PetscInt cellHeight, cStart, cEnd, c, fStart, fEnd, f, numLeaves, l; 811d56405f8SMatthew G. Knepley PetscMPIInt rank; 812d56405f8SMatthew G. Knepley 813d56405f8SMatthew G. Knepley PetscFunctionBegin; 814cd0c2139SMatthew G Knepley /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */ 8159566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 8169566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 8179566063dSJacob Faibussowitsch PetscCall(DMPlexGetVTKCellHeight(dmNew, &cellHeight)); 8189566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd)); 8199566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, NULL, &numLeaves, &leafLocal, &leafRemote)); 8209566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dmNew, "vtk")); 8219566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dmNew, "vtk", &vtkLabel)); 822d56405f8SMatthew G. Knepley if (createGhostLabel) { 8239566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dmNew, "ghost")); 8249566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dmNew, "ghost", &ghostLabel)); 825d56405f8SMatthew G. Knepley } 826cd0c2139SMatthew G Knepley for (l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) { 82748a46eb9SPierre Jolivet for (; c < leafLocal[l] && c < cEnd; ++c) PetscCall(DMLabelSetValue(vtkLabel, c, 1)); 828cd0c2139SMatthew G Knepley if (leafLocal[l] >= cEnd) break; 829cd0c2139SMatthew G Knepley if (leafRemote[l].rank == rank) { 8309566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(vtkLabel, c, 1)); 8311baa6e33SBarry Smith } else if (ghostLabel) PetscCall(DMLabelSetValue(ghostLabel, c, 2)); 832cd0c2139SMatthew G Knepley } 83348a46eb9SPierre Jolivet for (; c < cEnd; ++c) PetscCall(DMLabelSetValue(vtkLabel, c, 1)); 834d56405f8SMatthew G. Knepley if (ghostLabel) { 8359566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd)); 836cd0c2139SMatthew G Knepley for (f = fStart; f < fEnd; ++f) { 837cd0c2139SMatthew G Knepley PetscInt numCells; 838cd0c2139SMatthew G Knepley 8399566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dmNew, f, &numCells)); 840cd0c2139SMatthew G Knepley if (numCells < 2) { 8419566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(ghostLabel, f, 1)); 842cd0c2139SMatthew G Knepley } else { 843cd0c2139SMatthew G Knepley const PetscInt *cells = NULL; 844cd0c2139SMatthew G Knepley PetscInt vA, vB; 845cd0c2139SMatthew G Knepley 8469566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dmNew, f, &cells)); 8479566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(vtkLabel, cells[0], &vA)); 8489566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(vtkLabel, cells[1], &vB)); 8499566063dSJacob Faibussowitsch if (vA != 1 && vB != 1) PetscCall(DMLabelSetValue(ghostLabel, f, 1)); 850cd0c2139SMatthew G Knepley } 851cd0c2139SMatthew G Knepley } 852d56405f8SMatthew G. Knepley } 8533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 854cd0c2139SMatthew G Knepley } 855cd0c2139SMatthew G Knepley 856d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexShiftTree_Internal(DM dm, PetscInt depthShift[], DM dmNew) 857d71ae5a4SJacob Faibussowitsch { 858ca04dac2SToby Isaac DM refTree; 859ca04dac2SToby Isaac PetscSection pSec; 860ca04dac2SToby Isaac PetscInt *parents, *childIDs; 861ca04dac2SToby Isaac 862ca04dac2SToby Isaac PetscFunctionBegin; 8639566063dSJacob Faibussowitsch PetscCall(DMPlexGetReferenceTree(dm, &refTree)); 8649566063dSJacob Faibussowitsch PetscCall(DMPlexSetReferenceTree(dmNew, refTree)); 8659566063dSJacob Faibussowitsch PetscCall(DMPlexGetTree(dm, &pSec, &parents, &childIDs, NULL, NULL)); 866ca04dac2SToby Isaac if (pSec) { 8672582d50cSToby Isaac PetscInt p, pStart, pEnd, *parentsShifted, pStartShifted, pEndShifted, depth; 868fb4630b5SToby Isaac PetscInt *childIDsShifted; 869ca04dac2SToby Isaac PetscSection pSecShifted; 870ca04dac2SToby Isaac 8719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetChart(pSec, &pStart, &pEnd)); 8729566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 8732582d50cSToby Isaac pStartShifted = DMPlexShiftPoint_Internal(pStart, depth, depthShift); 8742582d50cSToby Isaac pEndShifted = DMPlexShiftPoint_Internal(pEnd, depth, depthShift); 8759566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEndShifted - pStartShifted, &parentsShifted, pEndShifted - pStartShifted, &childIDsShifted)); 8769566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dmNew), &pSecShifted)); 8779566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(pSecShifted, pStartShifted, pEndShifted)); 878ca04dac2SToby Isaac for (p = pStartShifted; p < pEndShifted; p++) { 879fb4630b5SToby Isaac /* start off assuming no children */ 8809566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(pSecShifted, p, 0)); 881fb4630b5SToby Isaac } 882fb4630b5SToby Isaac for (p = pStart; p < pEnd; p++) { 883fb4630b5SToby Isaac PetscInt dof; 884fb4630b5SToby Isaac PetscInt pNew = DMPlexShiftPoint_Internal(p, depth, depthShift); 885ca04dac2SToby Isaac 8869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(pSec, p, &dof)); 8879566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(pSecShifted, pNew, dof)); 888ca04dac2SToby Isaac } 8899566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(pSecShifted)); 890fb4630b5SToby Isaac for (p = pStart; p < pEnd; p++) { 891fb4630b5SToby Isaac PetscInt dof; 892fb4630b5SToby Isaac PetscInt pNew = DMPlexShiftPoint_Internal(p, depth, depthShift); 893fb4630b5SToby Isaac 8949566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(pSec, p, &dof)); 895fb4630b5SToby Isaac if (dof) { 896fb4630b5SToby Isaac PetscInt off, offNew; 897fb4630b5SToby Isaac 8989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(pSec, p, &off)); 8999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(pSecShifted, pNew, &offNew)); 900fb4630b5SToby Isaac parentsShifted[offNew] = DMPlexShiftPoint_Internal(parents[off], depth, depthShift); 901fb4630b5SToby Isaac childIDsShifted[offNew] = childIDs[off]; 902fb4630b5SToby Isaac } 903fb4630b5SToby Isaac } 9049566063dSJacob Faibussowitsch PetscCall(DMPlexSetTree(dmNew, pSecShifted, parentsShifted, childIDsShifted)); 9059566063dSJacob Faibussowitsch PetscCall(PetscFree2(parentsShifted, childIDsShifted)); 9069566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(&pSecShifted)); 907ca04dac2SToby Isaac } 9083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 909ca04dac2SToby Isaac } 910ca04dac2SToby Isaac 911d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexConstructGhostCells_Internal(DM dm, DMLabel label, PetscInt *numGhostCells, DM gdm) 912d71ae5a4SJacob Faibussowitsch { 913da97024aSMatthew G. Knepley PetscSF sf; 914cd0c2139SMatthew G Knepley IS valueIS; 915da97024aSMatthew G. Knepley const PetscInt *values, *leaves; 916cd0c2139SMatthew G Knepley PetscInt *depthShift; 9172582d50cSToby Isaac PetscInt d, depth = 0, nleaves, loc, Ng, numFS, fs, fStart, fEnd, ghostCell, cEnd, c; 9184fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 919cd0c2139SMatthew G Knepley 920cd0c2139SMatthew G Knepley PetscFunctionBegin; 9219566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 9229566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sf, NULL, &nleaves, &leaves, NULL)); 923da97024aSMatthew G. Knepley nleaves = PetscMax(0, nleaves); 9249566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 925cd0c2139SMatthew G Knepley /* Count ghost cells */ 9269566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 9279566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(valueIS, &numFS)); 9289566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 9294a6cfa73SMatthew G. Knepley Ng = 0; 930cd0c2139SMatthew G Knepley for (fs = 0; fs < numFS; ++fs) { 93146c796b9SMatthew G. Knepley IS faceIS; 93246c796b9SMatthew G. Knepley const PetscInt *faces; 93346c796b9SMatthew G. Knepley PetscInt numFaces, f, numBdFaces = 0; 934cd0c2139SMatthew G Knepley 9359566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, values[fs], &faceIS)); 9369566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(faceIS, &numFaces)); 9379566063dSJacob Faibussowitsch PetscCall(ISGetIndices(faceIS, &faces)); 93846c796b9SMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 939ca04dac2SToby Isaac PetscInt numChildren; 940ca04dac2SToby Isaac 9419566063dSJacob Faibussowitsch PetscCall(PetscFindInt(faces[f], nleaves, leaves, &loc)); 9429566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, faces[f], &numChildren, NULL)); 943ca04dac2SToby Isaac /* non-local and ancestors points don't get to register ghosts */ 944ca04dac2SToby Isaac if (loc >= 0 || numChildren) continue; 94546c796b9SMatthew G. Knepley if ((faces[f] >= fStart) && (faces[f] < fEnd)) ++numBdFaces; 94646c796b9SMatthew G. Knepley } 9474a6cfa73SMatthew G. Knepley Ng += numBdFaces; 9489566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(faceIS, &faces)); 9499566063dSJacob Faibussowitsch PetscCall(ISDestroy(&faceIS)); 950cd0c2139SMatthew G Knepley } 9519566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 9529566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(2 * (depth + 1), &depthShift)); 9532582d50cSToby Isaac for (d = 0; d <= depth; d++) { 95459eef20bSToby Isaac PetscInt dEnd; 9552582d50cSToby Isaac 9569566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, NULL, &dEnd)); 95759eef20bSToby Isaac depthShift[2 * d] = dEnd; 9582582d50cSToby Isaac depthShift[2 * d + 1] = 0; 9592582d50cSToby Isaac } 9602582d50cSToby Isaac if (depth >= 0) depthShift[2 * depth + 1] = Ng; 9619566063dSJacob Faibussowitsch PetscCall(DMPlexShiftPointSetUp_Internal(depth, depthShift)); 9629566063dSJacob Faibussowitsch PetscCall(DMPlexShiftSizes_Internal(dm, depthShift, gdm)); 963cd0c2139SMatthew G Knepley /* Step 3: Set cone/support sizes for new points */ 9649566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 0, NULL, &cEnd)); 96548a46eb9SPierre Jolivet for (c = cEnd; c < cEnd + Ng; ++c) PetscCall(DMPlexSetConeSize(gdm, c, 1)); 966cd0c2139SMatthew G Knepley for (fs = 0; fs < numFS; ++fs) { 967cd0c2139SMatthew G Knepley IS faceIS; 968cd0c2139SMatthew G Knepley const PetscInt *faces; 969cd0c2139SMatthew G Knepley PetscInt numFaces, f; 970cd0c2139SMatthew G Knepley 9719566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, values[fs], &faceIS)); 9729566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(faceIS, &numFaces)); 9739566063dSJacob Faibussowitsch PetscCall(ISGetIndices(faceIS, &faces)); 974cd0c2139SMatthew G Knepley for (f = 0; f < numFaces; ++f) { 975ca04dac2SToby Isaac PetscInt size, numChildren; 976cd0c2139SMatthew G Knepley 9779566063dSJacob Faibussowitsch PetscCall(PetscFindInt(faces[f], nleaves, leaves, &loc)); 9789566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, faces[f], &numChildren, NULL)); 979ca04dac2SToby Isaac if (loc >= 0 || numChildren) continue; 98046c796b9SMatthew G. Knepley if ((faces[f] < fStart) || (faces[f] >= fEnd)) continue; 9819566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, faces[f], &size)); 98263a3b9bcSJacob 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); 9839566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(gdm, faces[f] + Ng, 2)); 984cd0c2139SMatthew G Knepley } 9859566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(faceIS, &faces)); 9869566063dSJacob Faibussowitsch PetscCall(ISDestroy(&faceIS)); 987cd0c2139SMatthew G Knepley } 988cd0c2139SMatthew G Knepley /* Step 4: Setup ghosted DM */ 9899566063dSJacob Faibussowitsch PetscCall(DMSetUp(gdm)); 9909566063dSJacob Faibussowitsch PetscCall(DMPlexShiftPoints_Internal(dm, depthShift, gdm)); 991cd0c2139SMatthew G Knepley /* Step 6: Set cones and supports for new points */ 992cd0c2139SMatthew G Knepley ghostCell = cEnd; 993cd0c2139SMatthew G Knepley for (fs = 0; fs < numFS; ++fs) { 994cd0c2139SMatthew G Knepley IS faceIS; 995cd0c2139SMatthew G Knepley const PetscInt *faces; 996cd0c2139SMatthew G Knepley PetscInt numFaces, f; 997cd0c2139SMatthew G Knepley 9989566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, values[fs], &faceIS)); 9999566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(faceIS, &numFaces)); 10009566063dSJacob Faibussowitsch PetscCall(ISGetIndices(faceIS, &faces)); 100146c796b9SMatthew G. Knepley for (f = 0; f < numFaces; ++f) { 1002ca04dac2SToby Isaac PetscInt newFace = faces[f] + Ng, numChildren; 1003cd0c2139SMatthew G Knepley 10049566063dSJacob Faibussowitsch PetscCall(PetscFindInt(faces[f], nleaves, leaves, &loc)); 10059566063dSJacob Faibussowitsch PetscCall(DMPlexGetTreeChildren(dm, faces[f], &numChildren, NULL)); 1006ca04dac2SToby Isaac if (loc >= 0 || numChildren) continue; 100746c796b9SMatthew G. Knepley if ((faces[f] < fStart) || (faces[f] >= fEnd)) continue; 10089566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(gdm, ghostCell, &newFace)); 10099566063dSJacob Faibussowitsch PetscCall(DMPlexInsertSupport(gdm, newFace, 1, ghostCell)); 101046c796b9SMatthew G. Knepley ++ghostCell; 1011cd0c2139SMatthew G Knepley } 10129566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(faceIS, &faces)); 10139566063dSJacob Faibussowitsch PetscCall(ISDestroy(&faceIS)); 1014cd0c2139SMatthew G Knepley } 10159566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 10169566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 10179566063dSJacob Faibussowitsch PetscCall(DMPlexShiftCoordinates_Internal(dm, depthShift, gdm)); 10189566063dSJacob Faibussowitsch PetscCall(DMPlexShiftSF_Internal(dm, depthShift, gdm)); 10199566063dSJacob Faibussowitsch PetscCall(DMPlexShiftLabels_Internal(dm, depthShift, gdm)); 10209566063dSJacob Faibussowitsch PetscCall(DMPlexCreateVTKLabel_Internal(dm, PETSC_TRUE, gdm)); 10219566063dSJacob Faibussowitsch PetscCall(DMPlexShiftTree_Internal(dm, depthShift, gdm)); 10229566063dSJacob Faibussowitsch PetscCall(PetscFree(depthShift)); 102348a46eb9SPierre Jolivet for (c = cEnd; c < cEnd + Ng; ++c) PetscCall(DMPlexSetCellType(gdm, c, DM_POLYTOPE_FV_GHOST)); 1024966c7b3fSMatthew G. Knepley /* Step 7: Periodicity */ 10254fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dm, &maxCell, &Lstart, &L)); 10264fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(gdm, maxCell, Lstart, L)); 10274a6cfa73SMatthew G. Knepley if (numGhostCells) *numGhostCells = Ng; 10283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1029cd0c2139SMatthew G Knepley } 1030cd0c2139SMatthew G Knepley 1031cd0c2139SMatthew G Knepley /*@C 1032cd0c2139SMatthew G Knepley DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 1033cd0c2139SMatthew G Knepley 103420f4b53cSBarry Smith Collective 1035cd0c2139SMatthew G Knepley 1036cd0c2139SMatthew G Knepley Input Parameters: 103720f4b53cSBarry Smith + dm - The original `DM` 103820f4b53cSBarry Smith - labelName - The label specifying the boundary faces, or "Face Sets" if this is `NULL` 1039cd0c2139SMatthew G Knepley 1040cd0c2139SMatthew G Knepley Output Parameters: 104120f4b53cSBarry Smith + numGhostCells - The number of ghost cells added to the `DM` 104220f4b53cSBarry Smith - dmGhosted - The new `DM` 1043cd0c2139SMatthew G Knepley 1044cd0c2139SMatthew G Knepley Level: developer 1045cd0c2139SMatthew G Knepley 104620f4b53cSBarry Smith Note: 104720f4b53cSBarry Smith If no label exists of that name, one will be created marking all boundary faces 104820f4b53cSBarry Smith 10491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()` 105031266bc0SMatthew G. Knepley @*/ 1051d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted) 1052d71ae5a4SJacob Faibussowitsch { 1053cd0c2139SMatthew G Knepley DM gdm; 1054cd0c2139SMatthew G Knepley DMLabel label; 1055cd0c2139SMatthew G Knepley const char *name = labelName ? labelName : "Face Sets"; 1056412e9a14SMatthew G. Knepley PetscInt dim, Ng = 0; 1057b0441da4SMatthew G. Knepley PetscBool useCone, useClosure; 1058cd0c2139SMatthew G Knepley 1059cd0c2139SMatthew G Knepley PetscFunctionBegin; 1060cd0c2139SMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 10614f572ea9SToby Isaac if (numGhostCells) PetscAssertPointer(numGhostCells, 3); 10624f572ea9SToby Isaac PetscAssertPointer(dmGhosted, 4); 10639566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &gdm)); 10649566063dSJacob Faibussowitsch PetscCall(DMSetType(gdm, DMPLEX)); 10659566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 10669566063dSJacob Faibussowitsch PetscCall(DMSetDimension(gdm, dim)); 10679566063dSJacob Faibussowitsch PetscCall(DMGetBasicAdjacency(dm, &useCone, &useClosure)); 10689566063dSJacob Faibussowitsch PetscCall(DMSetBasicAdjacency(gdm, useCone, useClosure)); 10699566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 1070cd0c2139SMatthew G Knepley if (!label) { 1071cd0c2139SMatthew G Knepley /* Get label for boundary faces */ 10729566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, name)); 10739566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 10749566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(dm, 1, label)); 1075cd0c2139SMatthew G Knepley } 10769566063dSJacob Faibussowitsch PetscCall(DMPlexConstructGhostCells_Internal(dm, label, &Ng, gdm)); 10779566063dSJacob Faibussowitsch PetscCall(DMCopyDisc(dm, gdm)); 10785de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, gdm)); 1079cad26855SMatthew G. Knepley gdm->setfromoptionscalled = dm->setfromoptionscalled; 1080d80ece95SMatthew G. Knepley if (numGhostCells) *numGhostCells = Ng; 1081cd0c2139SMatthew G Knepley *dmGhosted = gdm; 10823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1083cd0c2139SMatthew G Knepley } 1084cd0c2139SMatthew G Knepley 1085d71ae5a4SJacob Faibussowitsch static PetscErrorCode DivideCells_Private(DM dm, DMLabel label, DMPlexPointQueue queue) 1086d71ae5a4SJacob Faibussowitsch { 1087accc9626SMatthew G. Knepley PetscInt dim, d, shift = 100, *pStart, *pEnd; 1088accc9626SMatthew G. Knepley 1089accc9626SMatthew G. Knepley PetscFunctionBegin; 1090accc9626SMatthew G. Knepley PetscCall(DMGetDimension(dm, &dim)); 1091accc9626SMatthew G. Knepley PetscCall(PetscMalloc2(dim, &pStart, dim, &pEnd)); 109248a46eb9SPierre Jolivet for (d = 0; d < dim; ++d) PetscCall(DMPlexGetDepthStratum(dm, d, &pStart[d], &pEnd[d])); 1093accc9626SMatthew G. Knepley while (!DMPlexPointQueueEmpty(queue)) { 1094accc9626SMatthew G. Knepley PetscInt cell = -1; 1095accc9626SMatthew G. Knepley PetscInt *closure = NULL; 1096accc9626SMatthew G. Knepley PetscInt closureSize, cl, cval; 1097accc9626SMatthew G. Knepley 1098accc9626SMatthew G. Knepley PetscCall(DMPlexPointQueueDequeue(queue, &cell)); 1099accc9626SMatthew G. Knepley PetscCall(DMLabelGetValue(label, cell, &cval)); 1100accc9626SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure)); 1101accc9626SMatthew G. Knepley /* Mark points in the cell closure that touch the fault */ 1102accc9626SMatthew G. Knepley for (d = 0; d < dim; ++d) { 1103accc9626SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 1104accc9626SMatthew G. Knepley const PetscInt clp = closure[cl]; 1105accc9626SMatthew G. Knepley PetscInt clval; 1106accc9626SMatthew G. Knepley 1107accc9626SMatthew G. Knepley if ((clp < pStart[d]) || (clp >= pEnd[d])) continue; 1108accc9626SMatthew G. Knepley PetscCall(DMLabelGetValue(label, clp, &clval)); 1109accc9626SMatthew G. Knepley if (clval == -1) { 1110accc9626SMatthew G. Knepley const PetscInt *cone; 1111accc9626SMatthew G. Knepley PetscInt coneSize, c; 1112accc9626SMatthew G. Knepley 1113accc9626SMatthew G. Knepley /* If a cone point touches the fault, then this point touches the fault */ 1114accc9626SMatthew G. Knepley PetscCall(DMPlexGetCone(dm, clp, &cone)); 1115accc9626SMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, clp, &coneSize)); 1116accc9626SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 1117accc9626SMatthew G. Knepley PetscInt cpval; 1118accc9626SMatthew G. Knepley 1119accc9626SMatthew G. Knepley PetscCall(DMLabelGetValue(label, cone[c], &cpval)); 1120accc9626SMatthew G. Knepley if (cpval != -1) { 1121accc9626SMatthew G. Knepley PetscInt dep; 1122accc9626SMatthew G. Knepley 1123accc9626SMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, clp, &dep)); 1124accc9626SMatthew G. Knepley clval = cval < 0 ? -(shift + dep) : shift + dep; 1125accc9626SMatthew G. Knepley PetscCall(DMLabelSetValue(label, clp, clval)); 1126accc9626SMatthew G. Knepley break; 1127accc9626SMatthew G. Knepley } 1128accc9626SMatthew G. Knepley } 1129accc9626SMatthew G. Knepley } 1130accc9626SMatthew G. Knepley /* Mark neighbor cells through marked faces (these cells must also touch the fault) */ 1131accc9626SMatthew G. Knepley if (d == dim - 1 && clval != -1) { 1132accc9626SMatthew G. Knepley const PetscInt *support; 1133accc9626SMatthew G. Knepley PetscInt supportSize, s, nval; 1134accc9626SMatthew G. Knepley 1135accc9626SMatthew G. Knepley PetscCall(DMPlexGetSupport(dm, clp, &support)); 1136accc9626SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, clp, &supportSize)); 1137accc9626SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 1138accc9626SMatthew G. Knepley PetscCall(DMLabelGetValue(label, support[s], &nval)); 1139accc9626SMatthew G. Knepley if (nval == -1) { 1140accc9626SMatthew G. Knepley PetscCall(DMLabelSetValue(label, support[s], clval < 0 ? clval - 1 : clval + 1)); 1141accc9626SMatthew G. Knepley PetscCall(DMPlexPointQueueEnqueue(queue, support[s])); 1142accc9626SMatthew G. Knepley } 1143accc9626SMatthew G. Knepley } 1144accc9626SMatthew G. Knepley } 1145accc9626SMatthew G. Knepley } 1146accc9626SMatthew G. Knepley } 1147accc9626SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure)); 1148accc9626SMatthew G. Knepley } 1149accc9626SMatthew G. Knepley PetscCall(PetscFree2(pStart, pEnd)); 11503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1151accc9626SMatthew G. Knepley } 1152accc9626SMatthew G. Knepley 1153accc9626SMatthew G. Knepley typedef struct { 1154accc9626SMatthew G. Knepley DM dm; 1155accc9626SMatthew G. Knepley DMPlexPointQueue queue; 1156accc9626SMatthew G. Knepley } PointDivision; 1157accc9626SMatthew G. Knepley 1158d71ae5a4SJacob Faibussowitsch static PetscErrorCode divideCell(DMLabel label, PetscInt p, PetscInt val, void *ctx) 1159d71ae5a4SJacob Faibussowitsch { 1160accc9626SMatthew G. Knepley PointDivision *div = (PointDivision *)ctx; 1161accc9626SMatthew G. Knepley PetscInt cval = val < 0 ? val - 1 : val + 1; 1162accc9626SMatthew G. Knepley const PetscInt *support; 1163accc9626SMatthew G. Knepley PetscInt supportSize, s; 1164accc9626SMatthew G. Knepley 1165accc9626SMatthew G. Knepley PetscFunctionBegin; 1166accc9626SMatthew G. Knepley PetscCall(DMPlexGetSupport(div->dm, p, &support)); 1167accc9626SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(div->dm, p, &supportSize)); 1168accc9626SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 1169accc9626SMatthew G. Knepley PetscCall(DMLabelSetValue(label, support[s], cval)); 1170accc9626SMatthew G. Knepley PetscCall(DMPlexPointQueueEnqueue(div->queue, support[s])); 1171accc9626SMatthew G. Knepley } 11723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1173accc9626SMatthew G. Knepley } 1174accc9626SMatthew G. Knepley 1175accc9626SMatthew G. Knepley /* Mark cells by label propagation */ 1176d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexLabelFaultHalo(DM dm, DMLabel faultLabel) 1177d71ae5a4SJacob Faibussowitsch { 1178accc9626SMatthew G. Knepley DMPlexPointQueue queue = NULL; 1179accc9626SMatthew G. Knepley PointDivision div; 1180accc9626SMatthew G. Knepley PetscSF pointSF; 1181accc9626SMatthew G. Knepley IS pointIS; 1182accc9626SMatthew G. Knepley const PetscInt *points; 1183accc9626SMatthew G. Knepley PetscBool empty; 1184accc9626SMatthew G. Knepley PetscInt dim, shift = 100, n, i; 1185accc9626SMatthew G. Knepley 1186accc9626SMatthew G. Knepley PetscFunctionBegin; 1187accc9626SMatthew G. Knepley PetscCall(DMGetDimension(dm, &dim)); 1188accc9626SMatthew G. Knepley PetscCall(DMPlexPointQueueCreate(1024, &queue)); 1189accc9626SMatthew G. Knepley div.dm = dm; 1190accc9626SMatthew G. Knepley div.queue = queue; 1191accc9626SMatthew G. Knepley /* Enqueue cells on fault */ 1192accc9626SMatthew G. Knepley PetscCall(DMLabelGetStratumIS(faultLabel, shift + dim, &pointIS)); 1193accc9626SMatthew G. Knepley if (pointIS) { 1194accc9626SMatthew G. Knepley PetscCall(ISGetLocalSize(pointIS, &n)); 1195accc9626SMatthew G. Knepley PetscCall(ISGetIndices(pointIS, &points)); 119648a46eb9SPierre Jolivet for (i = 0; i < n; ++i) PetscCall(DMPlexPointQueueEnqueue(queue, points[i])); 1197accc9626SMatthew G. Knepley PetscCall(ISRestoreIndices(pointIS, &points)); 1198accc9626SMatthew G. Knepley PetscCall(ISDestroy(&pointIS)); 1199accc9626SMatthew G. Knepley } 1200accc9626SMatthew G. Knepley PetscCall(DMLabelGetStratumIS(faultLabel, -(shift + dim), &pointIS)); 1201accc9626SMatthew G. Knepley if (pointIS) { 1202accc9626SMatthew G. Knepley PetscCall(ISGetLocalSize(pointIS, &n)); 1203accc9626SMatthew G. Knepley PetscCall(ISGetIndices(pointIS, &points)); 120448a46eb9SPierre Jolivet for (i = 0; i < n; ++i) PetscCall(DMPlexPointQueueEnqueue(queue, points[i])); 1205accc9626SMatthew G. Knepley PetscCall(ISRestoreIndices(pointIS, &points)); 1206accc9626SMatthew G. Knepley PetscCall(ISDestroy(&pointIS)); 1207accc9626SMatthew G. Knepley } 1208accc9626SMatthew G. Knepley 1209accc9626SMatthew G. Knepley PetscCall(DMGetPointSF(dm, &pointSF)); 1210accc9626SMatthew G. Knepley PetscCall(DMLabelPropagateBegin(faultLabel, pointSF)); 1211accc9626SMatthew G. Knepley /* While edge queue is not empty: */ 1212accc9626SMatthew G. Knepley PetscCall(DMPlexPointQueueEmptyCollective((PetscObject)dm, queue, &empty)); 1213accc9626SMatthew G. Knepley while (!empty) { 1214accc9626SMatthew G. Knepley PetscCall(DivideCells_Private(dm, faultLabel, queue)); 1215accc9626SMatthew G. Knepley PetscCall(DMLabelPropagatePush(faultLabel, pointSF, divideCell, &div)); 1216accc9626SMatthew G. Knepley PetscCall(DMPlexPointQueueEmptyCollective((PetscObject)dm, queue, &empty)); 1217accc9626SMatthew G. Knepley } 1218accc9626SMatthew G. Knepley PetscCall(DMLabelPropagateEnd(faultLabel, pointSF)); 1219accc9626SMatthew G. Knepley PetscCall(DMPlexPointQueueDestroy(&queue)); 12203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1221accc9626SMatthew G. Knepley } 1222accc9626SMatthew G. Knepley 1223607ab7a9SMatthew G. Knepley /* 1224faedd622SMatthew G. Knepley We are adding three kinds of points here: 1225607ab7a9SMatthew G. Knepley Replicated: Copies of points which exist in the mesh, such as vertices identified across a fault 1226faedd622SMatthew G. Knepley Non-replicated: Points which exist on the fault, but are not replicated 1227b6dfa339SMatthew 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 1228607ab7a9SMatthew G. Knepley Hybrid: Entirely new points, such as cohesive cells 1229a6ae58d1SMatthew G. Knepley 1230a6ae58d1SMatthew G. Knepley When creating subsequent cohesive cells, we shift the old hybrid cells to the end of the numbering at 1231a6ae58d1SMatthew G. Knepley each depth so that the new split/hybrid points can be inserted as a block. 1232607ab7a9SMatthew G. Knepley */ 1233d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexConstructCohesiveCells_Internal(DM dm, DMLabel label, DMLabel splitLabel, DM sdm) 1234d71ae5a4SJacob Faibussowitsch { 1235cd0c2139SMatthew G Knepley MPI_Comm comm; 1236607ab7a9SMatthew G. Knepley IS valueIS; 1237607ab7a9SMatthew G. Knepley PetscInt numSP = 0; /* The number of depths for which we have replicated points */ 1238607ab7a9SMatthew G. Knepley const PetscInt *values; /* List of depths for which we have replicated points */ 123918c5995bSMatthew G. Knepley IS *splitIS; 124018c5995bSMatthew G. Knepley IS *unsplitIS; 1241b6dfa339SMatthew G. Knepley IS ghostIS; 1242607ab7a9SMatthew G. Knepley PetscInt *numSplitPoints; /* The number of replicated points at each depth */ 124318c5995bSMatthew G. Knepley PetscInt *numUnsplitPoints; /* The number of non-replicated points at each depth which still give rise to hybrid points */ 124436dbac82SMatthew G. Knepley PetscInt *numHybridPoints; /* The number of new hybrid points at each depth */ 124536dbac82SMatthew G. Knepley PetscInt *numHybridPointsOld; /* The number of existing hybrid points at each depth */ 1246b6dfa339SMatthew G. Knepley PetscInt numGhostPoints; /* The number of unowned, shared fault faces */ 1247607ab7a9SMatthew G. Knepley const PetscInt **splitPoints; /* Replicated points for each depth */ 124818c5995bSMatthew G. Knepley const PetscInt **unsplitPoints; /* Non-replicated points for each depth */ 1249b6dfa339SMatthew G. Knepley const PetscInt *ghostPoints; /* Ghost fault faces */ 1250cd0c2139SMatthew G Knepley PetscSection coordSection; 1251cd0c2139SMatthew G Knepley Vec coordinates; 1252cd0c2139SMatthew G Knepley PetscScalar *coords; 1253a6ae58d1SMatthew G. Knepley PetscInt *depthMax; /* The first hybrid point at each depth in the original mesh */ 1254a6ae58d1SMatthew G. Knepley PetscInt *depthEnd; /* The point limit at each depth in the original mesh */ 1255607ab7a9SMatthew G. Knepley PetscInt *depthShift; /* Number of replicated+hybrid points at each depth */ 1256607ab7a9SMatthew G. Knepley PetscInt *pMaxNew; /* The first replicated point at each depth in the new mesh, hybrids come after this */ 1257607ab7a9SMatthew G. Knepley PetscInt *coneNew, *coneONew, *supportNew; 125818c5995bSMatthew G. Knepley PetscInt shift = 100, shift2 = 200, depth = 0, dep, dim, d, sp, maxConeSize, maxSupportSize, maxConeSizeNew, maxSupportSizeNew, numLabels, vStart, vEnd, pEnd, p, v; 1259cd0c2139SMatthew G Knepley 1260cd0c2139SMatthew G Knepley PetscFunctionBegin; 12619566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 12629566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 12639566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 12649566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 1265412e9a14SMatthew G. Knepley /* We do not want this label automatically computed, instead we compute it here */ 12669566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(sdm, "celltype")); 1267cd0c2139SMatthew G Knepley /* Count split points and add cohesive cells */ 12689566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize)); 12699566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(depth + 1, &depthMax, depth + 1, &depthEnd, 2 * (depth + 1), &depthShift, depth + 1, &pMaxNew, depth + 1, &numHybridPointsOld)); 12709566063dSJacob Faibussowitsch PetscCall(PetscMalloc7(depth + 1, &splitIS, depth + 1, &unsplitIS, depth + 1, &numSplitPoints, depth + 1, &numUnsplitPoints, depth + 1, &numHybridPoints, depth + 1, &splitPoints, depth + 1, &unsplitPoints)); 1271607ab7a9SMatthew G. Knepley for (d = 0; d <= depth; ++d) { 12729566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, d, NULL, &pMaxNew[d])); 12739566063dSJacob Faibussowitsch PetscCall(DMPlexGetTensorPrismBounds_Internal(dm, d, &depthMax[d], NULL)); 1274a6ae58d1SMatthew G. Knepley depthEnd[d] = pMaxNew[d]; 1275a6ae58d1SMatthew G. Knepley depthMax[d] = depthMax[d] < 0 ? depthEnd[d] : depthMax[d]; 1276607ab7a9SMatthew G. Knepley numSplitPoints[d] = 0; 127718c5995bSMatthew G. Knepley numUnsplitPoints[d] = 0; 1278607ab7a9SMatthew G. Knepley numHybridPoints[d] = 0; 1279a6ae58d1SMatthew G. Knepley numHybridPointsOld[d] = depthMax[d] < 0 ? 0 : depthEnd[d] - depthMax[d]; 1280607ab7a9SMatthew G. Knepley splitPoints[d] = NULL; 128118c5995bSMatthew G. Knepley unsplitPoints[d] = NULL; 128218c5995bSMatthew G. Knepley splitIS[d] = NULL; 128318c5995bSMatthew G. Knepley unsplitIS[d] = NULL; 128459eef20bSToby Isaac /* we are shifting the existing hybrid points with the stratum behind them, so 128559eef20bSToby Isaac * the split comes at the end of the normal points, i.e., at depthMax[d] */ 128659eef20bSToby Isaac depthShift[2 * d] = depthMax[d]; 128759eef20bSToby Isaac depthShift[2 * d + 1] = 0; 1288607ab7a9SMatthew G. Knepley } 1289b6dfa339SMatthew G. Knepley numGhostPoints = 0; 1290b6dfa339SMatthew G. Knepley ghostPoints = NULL; 1291cd0c2139SMatthew G Knepley if (label) { 12929566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 12939566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(valueIS, &numSP)); 12949566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 1295cd0c2139SMatthew G Knepley } 1296cd0c2139SMatthew G Knepley for (sp = 0; sp < numSP; ++sp) { 1297cd0c2139SMatthew G Knepley const PetscInt dep = values[sp]; 1298cd0c2139SMatthew G Knepley 1299cd0c2139SMatthew G Knepley if ((dep < 0) || (dep > depth)) continue; 13009566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, dep, &splitIS[dep])); 130118c5995bSMatthew G. Knepley if (splitIS[dep]) { 13029566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(splitIS[dep], &numSplitPoints[dep])); 13039566063dSJacob Faibussowitsch PetscCall(ISGetIndices(splitIS[dep], &splitPoints[dep])); 130418c5995bSMatthew G. Knepley } 13059566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, shift2 + dep, &unsplitIS[dep])); 130618c5995bSMatthew G. Knepley if (unsplitIS[dep]) { 13079566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(unsplitIS[dep], &numUnsplitPoints[dep])); 13089566063dSJacob Faibussowitsch PetscCall(ISGetIndices(unsplitIS[dep], &unsplitPoints[dep])); 1309cd0c2139SMatthew G Knepley } 1310cd0c2139SMatthew G Knepley } 1311b6dfa339SMatthew G. Knepley PetscCall(DMLabelGetStratumIS(label, shift2 + dim - 1, &ghostIS)); 1312b6dfa339SMatthew G. Knepley if (ghostIS) { 1313b6dfa339SMatthew G. Knepley PetscCall(ISGetLocalSize(ghostIS, &numGhostPoints)); 1314b6dfa339SMatthew G. Knepley PetscCall(ISGetIndices(ghostIS, &ghostPoints)); 1315b6dfa339SMatthew G. Knepley } 1316607ab7a9SMatthew G. Knepley /* Calculate number of hybrid points */ 131718c5995bSMatthew 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 */ 13182582d50cSToby Isaac for (d = 0; d <= depth; ++d) depthShift[2 * d + 1] = numSplitPoints[d] + numHybridPoints[d]; 13199566063dSJacob Faibussowitsch PetscCall(DMPlexShiftPointSetUp_Internal(depth, depthShift)); 132059eef20bSToby Isaac /* the end of the points in this stratum that come before the new points: 132159eef20bSToby Isaac * shifting pMaxNew[d] gets the new start of the next stratum, then count back the old hybrid points and the newly 132259eef20bSToby Isaac * added points */ 13232582d50cSToby Isaac for (d = 0; d <= depth; ++d) pMaxNew[d] = DMPlexShiftPoint_Internal(pMaxNew[d], depth, depthShift) - (numHybridPointsOld[d] + numSplitPoints[d] + numHybridPoints[d]); 13249566063dSJacob Faibussowitsch PetscCall(DMPlexShiftSizes_Internal(dm, depthShift, sdm)); 1325cd0c2139SMatthew G Knepley /* Step 3: Set cone/support sizes for new points */ 1326cd0c2139SMatthew G Knepley for (dep = 0; dep <= depth; ++dep) { 1327cd0c2139SMatthew G Knepley for (p = 0; p < numSplitPoints[dep]; ++p) { 1328cd0c2139SMatthew G Knepley const PetscInt oldp = splitPoints[dep][p]; 13292582d50cSToby Isaac const PetscInt newp = DMPlexShiftPoint_Internal(oldp, depth, depthShift) /*oldp + depthOffset[dep]*/; 13304c367dbcSMatthew G. Knepley const PetscInt splitp = p + pMaxNew[dep]; 1331cd0c2139SMatthew G Knepley const PetscInt *support; 1332394c2f0fSMatthew G. Knepley DMPolytopeType ct; 13334c367dbcSMatthew G. Knepley PetscInt coneSize, supportSize, qf, qn, qp, e; 1334cd0c2139SMatthew G Knepley 13359566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, oldp, &coneSize)); 13369566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(sdm, splitp, coneSize)); 13379566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, oldp, &supportSize)); 13389566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(sdm, splitp, supportSize)); 13399566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, oldp, &ct)); 13409566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(sdm, splitp, ct)); 1341cd0c2139SMatthew G Knepley if (dep == depth - 1) { 13424c367dbcSMatthew G. Knepley const PetscInt hybcell = p + pMaxNew[dep + 1] + numSplitPoints[dep + 1]; 13434c367dbcSMatthew G. Knepley 1344cd0c2139SMatthew G Knepley /* Add cohesive cells, they are prisms */ 13459566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(sdm, hybcell, 2 + coneSize)); 1346412e9a14SMatthew G. Knepley switch (coneSize) { 1347d71ae5a4SJacob Faibussowitsch case 2: 1348d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexSetCellType(sdm, hybcell, DM_POLYTOPE_SEG_PRISM_TENSOR)); 1349d71ae5a4SJacob Faibussowitsch break; 1350d71ae5a4SJacob Faibussowitsch case 3: 1351d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexSetCellType(sdm, hybcell, DM_POLYTOPE_TRI_PRISM_TENSOR)); 1352d71ae5a4SJacob Faibussowitsch break; 1353d71ae5a4SJacob Faibussowitsch case 4: 1354d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexSetCellType(sdm, hybcell, DM_POLYTOPE_QUAD_PRISM_TENSOR)); 1355d71ae5a4SJacob Faibussowitsch break; 1356412e9a14SMatthew G. Knepley } 1357b6dfa339SMatthew G. Knepley /* Shared fault faces with only one support cell now have two with the cohesive cell */ 1358b6dfa339SMatthew G. Knepley /* TODO Check thaat oldp has rootdegree == 1 */ 1359b6dfa339SMatthew G. Knepley if (supportSize == 1) { 1360b6dfa339SMatthew G. Knepley const PetscInt *support; 1361b6dfa339SMatthew G. Knepley PetscInt val; 1362b6dfa339SMatthew G. Knepley 1363b6dfa339SMatthew G. Knepley PetscCall(DMPlexGetSupport(dm, oldp, &support)); 1364b6dfa339SMatthew G. Knepley PetscCall(DMLabelGetValue(label, support[0], &val)); 1365b6dfa339SMatthew G. Knepley if (val < 0) PetscCall(DMPlexSetSupportSize(sdm, splitp, 2)); 1366b6dfa339SMatthew G. Knepley else PetscCall(DMPlexSetSupportSize(sdm, newp, 2)); 1367b6dfa339SMatthew G. Knepley } 1368cd0c2139SMatthew G Knepley } else if (dep == 0) { 13694c367dbcSMatthew G. Knepley const PetscInt hybedge = p + pMaxNew[dep + 1] + numSplitPoints[dep + 1]; 1370cd0c2139SMatthew G Knepley 13719566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, oldp, &support)); 13724c367dbcSMatthew G. Knepley for (e = 0, qn = 0, qp = 0, qf = 0; e < supportSize; ++e) { 1373cd0c2139SMatthew G Knepley PetscInt val; 1374cd0c2139SMatthew G Knepley 13759566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[e], &val)); 13764c367dbcSMatthew G. Knepley if (val == 1) ++qf; 13774c367dbcSMatthew G. Knepley if ((val == 1) || (val == (shift + 1))) ++qn; 13784c367dbcSMatthew G. Knepley if ((val == 1) || (val == -(shift + 1))) ++qp; 1379cd0c2139SMatthew G Knepley } 13804c367dbcSMatthew G. Knepley /* Split old vertex: Edges into original vertex and new cohesive edge */ 13819566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(sdm, newp, qn + 1)); 13824c367dbcSMatthew G. Knepley /* Split new vertex: Edges into split vertex and new cohesive edge */ 13839566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(sdm, splitp, qp + 1)); 13844c367dbcSMatthew G. Knepley /* Add hybrid edge */ 13859566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(sdm, hybedge, 2)); 13869566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(sdm, hybedge, qf)); 13879566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(sdm, hybedge, DM_POLYTOPE_POINT_PRISM_TENSOR)); 1388cd0c2139SMatthew G Knepley } else if (dep == dim - 2) { 13894c367dbcSMatthew G. Knepley const PetscInt hybface = p + pMaxNew[dep + 1] + numSplitPoints[dep + 1]; 13904c367dbcSMatthew G. Knepley 13919566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, oldp, &support)); 13924c367dbcSMatthew G. Knepley for (e = 0, qn = 0, qp = 0, qf = 0; e < supportSize; ++e) { 1393cd0c2139SMatthew G Knepley PetscInt val; 1394cd0c2139SMatthew G Knepley 13959566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[e], &val)); 13964c367dbcSMatthew G. Knepley if (val == dim - 1) ++qf; 13974c367dbcSMatthew G. Knepley if ((val == dim - 1) || (val == (shift + dim - 1))) ++qn; 13984c367dbcSMatthew G. Knepley if ((val == dim - 1) || (val == -(shift + dim - 1))) ++qp; 1399cd0c2139SMatthew G Knepley } 14004c367dbcSMatthew G. Knepley /* Split old edge: Faces into original edge and cohesive face (positive side?) */ 14019566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(sdm, newp, qn + 1)); 14024c367dbcSMatthew G. Knepley /* Split new edge: Faces into split edge and cohesive face (negative side?) */ 14039566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(sdm, splitp, qp + 1)); 14044c367dbcSMatthew G. Knepley /* Add hybrid face */ 14059566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(sdm, hybface, 4)); 14069566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(sdm, hybface, qf)); 14079566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(sdm, hybface, DM_POLYTOPE_SEG_PRISM_TENSOR)); 1408cd0c2139SMatthew G Knepley } 1409cd0c2139SMatthew G Knepley } 1410cd0c2139SMatthew G Knepley } 141118c5995bSMatthew G. Knepley for (dep = 0; dep <= depth; ++dep) { 141218c5995bSMatthew G. Knepley for (p = 0; p < numUnsplitPoints[dep]; ++p) { 141318c5995bSMatthew G. Knepley const PetscInt oldp = unsplitPoints[dep][p]; 14142582d50cSToby Isaac const PetscInt newp = DMPlexShiftPoint_Internal(oldp, depth, depthShift) /*oldp + depthOffset[dep]*/; 141518c5995bSMatthew G. Knepley const PetscInt *support; 1416da1dd7e4SMatthew G. Knepley PetscInt coneSize, supportSize, qf, e, s; 141718c5995bSMatthew G. Knepley 14189566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, oldp, &coneSize)); 14199566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, oldp, &supportSize)); 14209566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, oldp, &support)); 142118c5995bSMatthew G. Knepley if (dep == 0) { 142218c5995bSMatthew G. Knepley const PetscInt hybedge = p + pMaxNew[dep + 1] + numSplitPoints[dep + 1] + numSplitPoints[dep]; 142318c5995bSMatthew G. Knepley 142439254ff6SMatthew G. Knepley /* Unsplit vertex: Edges into original vertex, split edges, and new cohesive edge twice */ 142539254ff6SMatthew G. Knepley for (s = 0, qf = 0; s < supportSize; ++s, ++qf) { 14269566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[s], numSplitPoints[dep + 1], splitPoints[dep + 1], &e)); 142739254ff6SMatthew G. Knepley if (e >= 0) ++qf; 142839254ff6SMatthew G. Knepley } 14299566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(sdm, newp, qf + 2)); 143018c5995bSMatthew G. Knepley /* Add hybrid edge */ 14319566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(sdm, hybedge, 2)); 1432e1757548SMatthew G. Knepley for (e = 0, qf = 0; e < supportSize; ++e) { 1433e1757548SMatthew G. Knepley PetscInt val; 1434e1757548SMatthew G. Knepley 14359566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[e], &val)); 1436e1757548SMatthew G. Knepley /* Split and unsplit edges produce hybrid faces */ 1437da1dd7e4SMatthew G. Knepley if (val == 1) ++qf; 1438da1dd7e4SMatthew G. Knepley if (val == (shift2 + 1)) ++qf; 1439e1757548SMatthew G. Knepley } 14409566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(sdm, hybedge, qf)); 14419566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(sdm, hybedge, DM_POLYTOPE_POINT_PRISM_TENSOR)); 144218c5995bSMatthew G. Knepley } else if (dep == dim - 2) { 144318c5995bSMatthew G. Knepley const PetscInt hybface = p + pMaxNew[dep + 1] + numSplitPoints[dep + 1] + numSplitPoints[dep]; 1444cd0c2139SMatthew G Knepley PetscInt val; 1445cd0c2139SMatthew G Knepley 1446da1dd7e4SMatthew G. Knepley for (e = 0, qf = 0; e < supportSize; ++e) { 14479566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[e], &val)); 1448da1dd7e4SMatthew G. Knepley if (val == dim - 1) qf += 2; 1449da1dd7e4SMatthew G. Knepley else ++qf; 1450cd0c2139SMatthew G Knepley } 145118c5995bSMatthew G. Knepley /* Unsplit edge: Faces into original edge, split face, and cohesive face twice */ 14529566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(sdm, newp, qf + 2)); 145318c5995bSMatthew G. Knepley /* Add hybrid face */ 1454da1dd7e4SMatthew G. Knepley for (e = 0, qf = 0; e < supportSize; ++e) { 14559566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[e], &val)); 1456da1dd7e4SMatthew G. Knepley if (val == dim - 1) ++qf; 1457da1dd7e4SMatthew G. Knepley } 14589566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(sdm, hybface, 4)); 14599566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupportSize(sdm, hybface, qf)); 14609566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(sdm, hybface, DM_POLYTOPE_SEG_PRISM_TENSOR)); 1461cd0c2139SMatthew G Knepley } 1462cd0c2139SMatthew G Knepley } 1463cd0c2139SMatthew G Knepley } 1464cd0c2139SMatthew G Knepley /* Step 4: Setup split DM */ 14659566063dSJacob Faibussowitsch PetscCall(DMSetUp(sdm)); 14669566063dSJacob Faibussowitsch PetscCall(DMPlexShiftPoints_Internal(dm, depthShift, sdm)); 14679566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(sdm, &maxConeSizeNew, &maxSupportSizeNew)); 14689566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(PetscMax(maxConeSize, maxConeSizeNew) * 3, &coneNew, PetscMax(maxConeSize, maxConeSizeNew) * 3, &coneONew, PetscMax(maxSupportSize, maxSupportSizeNew), &supportNew)); 1469cd0c2139SMatthew G Knepley /* Step 6: Set cones and supports for new points */ 1470cd0c2139SMatthew G Knepley for (dep = 0; dep <= depth; ++dep) { 1471cd0c2139SMatthew G Knepley for (p = 0; p < numSplitPoints[dep]; ++p) { 1472cd0c2139SMatthew G Knepley const PetscInt oldp = splitPoints[dep][p]; 14732582d50cSToby Isaac const PetscInt newp = DMPlexShiftPoint_Internal(oldp, depth, depthShift) /*oldp + depthOffset[dep]*/; 14744c367dbcSMatthew G. Knepley const PetscInt splitp = p + pMaxNew[dep]; 1475cd0c2139SMatthew G Knepley const PetscInt *cone, *support, *ornt; 1476b5a892a1SMatthew G. Knepley DMPolytopeType ct; 14774c367dbcSMatthew G. Knepley PetscInt coneSize, supportSize, q, qf, qn, qp, v, e, s; 1478cd0c2139SMatthew G Knepley 14799566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellType(dm, oldp, &ct)); 14809566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, oldp, &coneSize)); 14819566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, oldp, &cone)); 14829566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, oldp, &ornt)); 14839566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, oldp, &supportSize)); 14849566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, oldp, &support)); 1485cd0c2139SMatthew G Knepley if (dep == depth - 1) { 148696a07cd0SMatthew G. Knepley PetscBool hasUnsplit = PETSC_FALSE; 14874c367dbcSMatthew G. Knepley const PetscInt hybcell = p + pMaxNew[dep + 1] + numSplitPoints[dep + 1]; 1488cd0c2139SMatthew G Knepley const PetscInt *supportF; 1489cd0c2139SMatthew G Knepley 1490b6dfa339SMatthew G. Knepley coneONew[0] = coneONew[1] = -1000; 1491cd0c2139SMatthew G Knepley /* Split face: copy in old face to new face to start */ 14929566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(sdm, newp, &supportF)); 14939566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupport(sdm, splitp, supportF)); 1494cd0c2139SMatthew G Knepley /* Split old face: old vertices/edges in cone so no change */ 1495cd0c2139SMatthew G Knepley /* Split new face: new vertices/edges in cone */ 1496cd0c2139SMatthew G Knepley for (q = 0; q < coneSize; ++q) { 14979566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[q], numSplitPoints[dep - 1], splitPoints[dep - 1], &v)); 149818c5995bSMatthew G. Knepley if (v < 0) { 14999566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[q], numUnsplitPoints[dep - 1], unsplitPoints[dep - 1], &v)); 150063a3b9bcSJacob 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); 15012582d50cSToby Isaac coneNew[2 + q] = DMPlexShiftPoint_Internal(cone[q], depth, depthShift) /*cone[q] + depthOffset[dep-1]*/; 150296a07cd0SMatthew G. Knepley hasUnsplit = PETSC_TRUE; 150318c5995bSMatthew G. Knepley } else { 15044c367dbcSMatthew G. Knepley coneNew[2 + q] = v + pMaxNew[dep - 1]; 1505163235baSMatthew G. Knepley if (dep > 1) { 1506163235baSMatthew G. Knepley const PetscInt *econe; 1507163235baSMatthew G. Knepley PetscInt econeSize, r, vs, vu; 1508163235baSMatthew G. Knepley 15099566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[q], &econeSize)); 15109566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cone[q], &econe)); 1511163235baSMatthew G. Knepley for (r = 0; r < econeSize; ++r) { 15129566063dSJacob Faibussowitsch PetscCall(PetscFindInt(econe[r], numSplitPoints[dep - 2], splitPoints[dep - 2], &vs)); 15139566063dSJacob Faibussowitsch PetscCall(PetscFindInt(econe[r], numUnsplitPoints[dep - 2], unsplitPoints[dep - 2], &vu)); 1514163235baSMatthew G. Knepley if (vs >= 0) continue; 151563a3b9bcSJacob 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); 1516163235baSMatthew G. Knepley hasUnsplit = PETSC_TRUE; 1517163235baSMatthew G. Knepley } 1518163235baSMatthew G. Knepley } 1519cd0c2139SMatthew G Knepley } 1520cd0c2139SMatthew G Knepley } 15219566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(sdm, splitp, &coneNew[2])); 15229566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(sdm, splitp, ornt)); 1523e537020bSMatthew G. Knepley /* Face support */ 1524b6dfa339SMatthew G. Knepley PetscInt vals[2]; 1525cd0c2139SMatthew G Knepley 1526b6dfa339SMatthew G. Knepley PetscCall(DMLabelGetValue(label, support[0], &vals[0])); 1527b6dfa339SMatthew G. Knepley if (supportSize > 1) PetscCall(DMLabelGetValue(label, support[1], &vals[1])); 1528b6dfa339SMatthew G. Knepley else vals[1] = -vals[0]; 1529b6dfa339SMatthew 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]); 1530b6dfa339SMatthew G. Knepley 1531b6dfa339SMatthew G. Knepley for (s = 0; s < 2; ++s) { 1532b6dfa339SMatthew G. Knepley if (s >= supportSize) { 1533b6dfa339SMatthew G. Knepley if (vals[s] < 0) { 1534b6dfa339SMatthew G. Knepley /* Ghost old face: Replace negative side cell with cohesive cell */ 1535accc9626SMatthew G. Knepley PetscCall(DMPlexInsertSupport(sdm, newp, s, hybcell)); 1536b6dfa339SMatthew G. Knepley } else { 1537b6dfa339SMatthew G. Knepley /* Ghost new face: Replace positive side cell with cohesive cell */ 1538accc9626SMatthew G. Knepley PetscCall(DMPlexInsertSupport(sdm, splitp, s, hybcell)); 1539b6dfa339SMatthew G. Knepley } 1540b6dfa339SMatthew G. Knepley } else { 1541b6dfa339SMatthew G. Knepley if (vals[s] < 0) { 1542cd0c2139SMatthew G Knepley /* Split old face: Replace negative side cell with cohesive cell */ 15439566063dSJacob Faibussowitsch PetscCall(DMPlexInsertSupport(sdm, newp, s, hybcell)); 1544cd0c2139SMatthew G Knepley } else { 1545cd0c2139SMatthew G Knepley /* Split new face: Replace positive side cell with cohesive cell */ 15469566063dSJacob Faibussowitsch PetscCall(DMPlexInsertSupport(sdm, splitp, s, hybcell)); 1547b6dfa339SMatthew G. Knepley } 1548b6dfa339SMatthew G. Knepley } 1549b6dfa339SMatthew G. Knepley } 1550b6dfa339SMatthew G. Knepley /* Get orientation for cohesive face using the positive side cell */ 1551e537020bSMatthew G. Knepley { 1552e537020bSMatthew G. Knepley const PetscInt *ncone, *nconeO; 1553b6dfa339SMatthew G. Knepley PetscInt nconeSize, nc, ocell; 1554accc9626SMatthew G. Knepley PetscBool flip = PETSC_FALSE; 1555e537020bSMatthew G. Knepley 15569371c9d4SSatish Balay if (supportSize > 1) { 15579371c9d4SSatish Balay ocell = vals[0] < 0 ? support[1] : support[0]; 15589371c9d4SSatish Balay } else { 15599371c9d4SSatish Balay ocell = support[0]; 15609371c9d4SSatish Balay flip = vals[0] < 0 ? PETSC_TRUE : PETSC_FALSE; 15619371c9d4SSatish Balay } 1562b6dfa339SMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, ocell, &nconeSize)); 1563b6dfa339SMatthew G. Knepley PetscCall(DMPlexGetCone(dm, ocell, &ncone)); 1564e1a13daeSMatthew G. Knepley PetscCall(DMPlexGetConeOrientation(dm, ocell, &nconeO)); 1565e537020bSMatthew G. Knepley for (nc = 0; nc < nconeSize; ++nc) { 1566e537020bSMatthew G. Knepley if (ncone[nc] == oldp) { 1567b6dfa339SMatthew G. Knepley coneONew[0] = flip ? -(nconeO[nc] + 1) : nconeO[nc]; 1568e537020bSMatthew G. Knepley break; 1569cd0c2139SMatthew G Knepley } 1570cd0c2139SMatthew G Knepley } 1571b6dfa339SMatthew 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); 1572e537020bSMatthew G. Knepley } 15734c367dbcSMatthew G. Knepley /* Cohesive cell: Old and new split face, then new cohesive faces */ 1574b6dfa339SMatthew G. Knepley { 1575b6dfa339SMatthew G. Knepley const PetscInt No = DMPolytopeTypeGetNumArrangments(ct) / 2; 1576b6dfa339SMatthew G. Knepley PetscCheck((coneONew[0] >= -No) && (coneONew[0] < No), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid %s orientation %" PetscInt_FMT, DMPolytopeTypes[ct], coneONew[0]); 1577b6dfa339SMatthew G. Knepley } 1578b5a892a1SMatthew G. Knepley const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, coneONew[0]); 1579b5a892a1SMatthew G. Knepley 1580fd4b9f15SMatthew G. Knepley coneNew[0] = newp; /* Extracted negative side orientation above */ 15814c367dbcSMatthew G. Knepley coneNew[1] = splitp; 15824c367dbcSMatthew G. Knepley coneONew[1] = coneONew[0]; 1583e537020bSMatthew G. Knepley for (q = 0; q < coneSize; ++q) { 1584412e9a14SMatthew G. Knepley /* Hybrid faces must follow order from oriented end face */ 1585b5a892a1SMatthew G. Knepley const PetscInt qa = arr[q * 2 + 0]; 1586b5a892a1SMatthew G. Knepley const PetscInt qo = arr[q * 2 + 1]; 1587b5a892a1SMatthew G. Knepley DMPolytopeType ft = dep == 2 ? DM_POLYTOPE_SEGMENT : DM_POLYTOPE_POINT; 1588412e9a14SMatthew G. Knepley 15899566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[qa], numSplitPoints[dep - 1], splitPoints[dep - 1], &v)); 159018c5995bSMatthew G. Knepley if (v < 0) { 15919566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[qa], numUnsplitPoints[dep - 1], unsplitPoints[dep - 1], &v)); 159218c5995bSMatthew G. Knepley coneNew[2 + q] = v + pMaxNew[dep] + numSplitPoints[dep] + numSplitPoints[dep - 1]; 159318c5995bSMatthew G. Knepley } else { 159418c5995bSMatthew G. Knepley coneNew[2 + q] = v + pMaxNew[dep] + numSplitPoints[dep]; 159518c5995bSMatthew G. Knepley } 1596b5a892a1SMatthew G. Knepley coneONew[2 + q] = DMPolytopeTypeComposeOrientation(ft, qo, ornt[qa]); 1597e537020bSMatthew G. Knepley } 15989566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(sdm, hybcell, coneNew)); 15999566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(sdm, hybcell, coneONew)); 160096a07cd0SMatthew G. Knepley /* Label the hybrid cells on the boundary of the split */ 16019566063dSJacob Faibussowitsch if (hasUnsplit) PetscCall(DMLabelSetValue(label, -hybcell, dim)); 1602cd0c2139SMatthew G Knepley } else if (dep == 0) { 16034c367dbcSMatthew G. Knepley const PetscInt hybedge = p + pMaxNew[dep + 1] + numSplitPoints[dep + 1]; 1604cd0c2139SMatthew G Knepley 1605cd0c2139SMatthew G Knepley /* Split old vertex: Edges in old split faces and new cohesive edge */ 16064c367dbcSMatthew G. Knepley for (e = 0, qn = 0; e < supportSize; ++e) { 1607cd0c2139SMatthew G Knepley PetscInt val; 1608cd0c2139SMatthew G Knepley 16099566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[e], &val)); 1610ad540459SPierre Jolivet if ((val == 1) || (val == (shift + 1))) supportNew[qn++] = DMPlexShiftPoint_Internal(support[e], depth, depthShift) /*support[e] + depthOffset[dep+1]*/; 1611cd0c2139SMatthew G Knepley } 16124c367dbcSMatthew G. Knepley supportNew[qn] = hybedge; 16139566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupport(sdm, newp, supportNew)); 1614cd0c2139SMatthew G Knepley /* Split new vertex: Edges in new split faces and new cohesive edge */ 16154c367dbcSMatthew G. Knepley for (e = 0, qp = 0; e < supportSize; ++e) { 1616cd0c2139SMatthew G Knepley PetscInt val, edge; 1617cd0c2139SMatthew G Knepley 16189566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[e], &val)); 1619cd0c2139SMatthew G Knepley if (val == 1) { 16209566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[e], numSplitPoints[dep + 1], splitPoints[dep + 1], &edge)); 162163a3b9bcSJacob Faibussowitsch PetscCheck(edge >= 0, comm, PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " is not a split edge", support[e]); 16224c367dbcSMatthew G. Knepley supportNew[qp++] = edge + pMaxNew[dep + 1]; 1623cd0c2139SMatthew G Knepley } else if (val == -(shift + 1)) { 16242582d50cSToby Isaac supportNew[qp++] = DMPlexShiftPoint_Internal(support[e], depth, depthShift) /*support[e] + depthOffset[dep+1]*/; 1625cd0c2139SMatthew G Knepley } 1626cd0c2139SMatthew G Knepley } 16274c367dbcSMatthew G. Knepley supportNew[qp] = hybedge; 16289566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupport(sdm, splitp, supportNew)); 16294c367dbcSMatthew G. Knepley /* Hybrid edge: Old and new split vertex */ 1630cd0c2139SMatthew G Knepley coneNew[0] = newp; 1631cd0c2139SMatthew G Knepley coneNew[1] = splitp; 16329566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(sdm, hybedge, coneNew)); 16334c367dbcSMatthew G. Knepley for (e = 0, qf = 0; e < supportSize; ++e) { 16344c367dbcSMatthew G. Knepley PetscInt val, edge; 16354c367dbcSMatthew G. Knepley 16369566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[e], &val)); 16374c367dbcSMatthew G. Knepley if (val == 1) { 16389566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[e], numSplitPoints[dep + 1], splitPoints[dep + 1], &edge)); 163963a3b9bcSJacob Faibussowitsch PetscCheck(edge >= 0, comm, PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " is not a split edge", support[e]); 16404c367dbcSMatthew G. Knepley supportNew[qf++] = edge + pMaxNew[dep + 2] + numSplitPoints[dep + 2]; 16414c367dbcSMatthew G. Knepley } 16424c367dbcSMatthew G. Knepley } 16439566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupport(sdm, hybedge, supportNew)); 1644cd0c2139SMatthew G Knepley } else if (dep == dim - 2) { 16454c367dbcSMatthew G. Knepley const PetscInt hybface = p + pMaxNew[dep + 1] + numSplitPoints[dep + 1]; 16464c367dbcSMatthew G. Knepley 1647cd0c2139SMatthew G Knepley /* Split old edge: old vertices in cone so no change */ 1648cd0c2139SMatthew G Knepley /* Split new edge: new vertices in cone */ 1649cd0c2139SMatthew G Knepley for (q = 0; q < coneSize; ++q) { 16509566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[q], numSplitPoints[dep - 1], splitPoints[dep - 1], &v)); 1651e1757548SMatthew G. Knepley if (v < 0) { 16529566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[q], numUnsplitPoints[dep - 1], unsplitPoints[dep - 1], &v)); 165363a3b9bcSJacob 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); 16542582d50cSToby Isaac coneNew[q] = DMPlexShiftPoint_Internal(cone[q], depth, depthShift) /*cone[q] + depthOffset[dep-1]*/; 1655e1757548SMatthew G. Knepley } else { 16564c367dbcSMatthew G. Knepley coneNew[q] = v + pMaxNew[dep - 1]; 1657cd0c2139SMatthew G Knepley } 1658e1757548SMatthew G. Knepley } 16599566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(sdm, splitp, coneNew)); 1660cd0c2139SMatthew G Knepley /* Split old edge: Faces in positive side cells and old split faces */ 1661cd0c2139SMatthew G Knepley for (e = 0, q = 0; e < supportSize; ++e) { 1662cd0c2139SMatthew G Knepley PetscInt val; 1663cd0c2139SMatthew G Knepley 16649566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[e], &val)); 16654c367dbcSMatthew G. Knepley if (val == dim - 1) { 16662582d50cSToby Isaac supportNew[q++] = DMPlexShiftPoint_Internal(support[e], depth, depthShift) /*support[e] + depthOffset[dep+1]*/; 16674c367dbcSMatthew G. Knepley } else if (val == (shift + dim - 1)) { 16682582d50cSToby Isaac supportNew[q++] = DMPlexShiftPoint_Internal(support[e], depth, depthShift) /*support[e] + depthOffset[dep+1]*/; 1669cd0c2139SMatthew G Knepley } 1670cd0c2139SMatthew G Knepley } 1671b279cd2aSMatthew G. Knepley supportNew[q++] = p + pMaxNew[dep + 1] + numSplitPoints[dep + 1]; 16729566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupport(sdm, newp, supportNew)); 1673cd0c2139SMatthew G Knepley /* Split new edge: Faces in negative side cells and new split faces */ 1674cd0c2139SMatthew G Knepley for (e = 0, q = 0; e < supportSize; ++e) { 1675cd0c2139SMatthew G Knepley PetscInt val, face; 1676cd0c2139SMatthew G Knepley 16779566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[e], &val)); 1678cd0c2139SMatthew G Knepley if (val == dim - 1) { 16799566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[e], numSplitPoints[dep + 1], splitPoints[dep + 1], &face)); 168063a3b9bcSJacob Faibussowitsch PetscCheck(face >= 0, comm, PETSC_ERR_ARG_WRONG, "Face %" PetscInt_FMT " is not a split face", support[e]); 16814c367dbcSMatthew G. Knepley supportNew[q++] = face + pMaxNew[dep + 1]; 1682cd0c2139SMatthew G Knepley } else if (val == -(shift + dim - 1)) { 16832582d50cSToby Isaac supportNew[q++] = DMPlexShiftPoint_Internal(support[e], depth, depthShift) /*support[e] + depthOffset[dep+1]*/; 1684cd0c2139SMatthew G Knepley } 1685cd0c2139SMatthew G Knepley } 1686b279cd2aSMatthew G. Knepley supportNew[q++] = p + pMaxNew[dep + 1] + numSplitPoints[dep + 1]; 16879566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupport(sdm, splitp, supportNew)); 16884c367dbcSMatthew G. Knepley /* Hybrid face */ 16894c367dbcSMatthew G. Knepley coneNew[0] = newp; 16904c367dbcSMatthew G. Knepley coneNew[1] = splitp; 16914c367dbcSMatthew G. Knepley for (v = 0; v < coneSize; ++v) { 16924c367dbcSMatthew G. Knepley PetscInt vertex; 16939566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[v], numSplitPoints[dep - 1], splitPoints[dep - 1], &vertex)); 1694e1757548SMatthew G. Knepley if (vertex < 0) { 16959566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[v], numUnsplitPoints[dep - 1], unsplitPoints[dep - 1], &vertex)); 169663a3b9bcSJacob 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); 1697e1757548SMatthew G. Knepley coneNew[2 + v] = vertex + pMaxNew[dep] + numSplitPoints[dep] + numSplitPoints[dep - 1]; 1698e1757548SMatthew G. Knepley } else { 16994c367dbcSMatthew G. Knepley coneNew[2 + v] = vertex + pMaxNew[dep] + numSplitPoints[dep]; 17004c367dbcSMatthew G. Knepley } 1701e1757548SMatthew G. Knepley } 17029566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(sdm, hybface, coneNew)); 17034c367dbcSMatthew G. Knepley for (e = 0, qf = 0; e < supportSize; ++e) { 17044c367dbcSMatthew G. Knepley PetscInt val, face; 17054c367dbcSMatthew G. Knepley 17069566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[e], &val)); 17074c367dbcSMatthew G. Knepley if (val == dim - 1) { 17089566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[e], numSplitPoints[dep + 1], splitPoints[dep + 1], &face)); 170963a3b9bcSJacob Faibussowitsch PetscCheck(face >= 0, comm, PETSC_ERR_ARG_WRONG, "Face %" PetscInt_FMT " is not a split face", support[e]); 17104c367dbcSMatthew G. Knepley supportNew[qf++] = face + pMaxNew[dep + 2] + numSplitPoints[dep + 2]; 17114c367dbcSMatthew G. Knepley } 17124c367dbcSMatthew G. Knepley } 17139566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupport(sdm, hybface, supportNew)); 1714cd0c2139SMatthew G Knepley } 1715cd0c2139SMatthew G Knepley } 1716cd0c2139SMatthew G Knepley } 171718c5995bSMatthew G. Knepley for (dep = 0; dep <= depth; ++dep) { 171818c5995bSMatthew G. Knepley for (p = 0; p < numUnsplitPoints[dep]; ++p) { 171918c5995bSMatthew G. Knepley const PetscInt oldp = unsplitPoints[dep][p]; 17202582d50cSToby Isaac const PetscInt newp = DMPlexShiftPoint_Internal(oldp, depth, depthShift) /*oldp + depthOffset[dep]*/; 1721b5a892a1SMatthew G. Knepley const PetscInt *cone, *support; 1722e1757548SMatthew G. Knepley PetscInt coneSize, supportSize, supportSizeNew, q, qf, e, f, s; 172318c5995bSMatthew G. Knepley 17249566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, oldp, &coneSize)); 17259566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, oldp, &cone)); 17269566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, oldp, &supportSize)); 17279566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, oldp, &support)); 172818c5995bSMatthew G. Knepley if (dep == 0) { 172918c5995bSMatthew G. Knepley const PetscInt hybedge = p + pMaxNew[dep + 1] + numSplitPoints[dep + 1] + numSplitPoints[dep]; 173018c5995bSMatthew G. Knepley 173118c5995bSMatthew G. Knepley /* Unsplit vertex */ 17329566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(sdm, newp, &supportSizeNew)); 173318c5995bSMatthew G. Knepley for (s = 0, q = 0; s < supportSize; ++s) { 17342582d50cSToby Isaac supportNew[q++] = DMPlexShiftPoint_Internal(support[s], depth, depthShift) /*support[s] + depthOffset[dep+1]*/; 17359566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[s], numSplitPoints[dep + 1], splitPoints[dep + 1], &e)); 1736ad540459SPierre Jolivet if (e >= 0) supportNew[q++] = e + pMaxNew[dep + 1]; 173718c5995bSMatthew G. Knepley } 173818c5995bSMatthew G. Knepley supportNew[q++] = hybedge; 173918c5995bSMatthew G. Knepley supportNew[q++] = hybedge; 174063a3b9bcSJacob Faibussowitsch PetscCheck(q == supportSizeNew, comm, PETSC_ERR_ARG_WRONG, "Support size %" PetscInt_FMT " != %" PetscInt_FMT " for vertex %" PetscInt_FMT, q, supportSizeNew, newp); 17419566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupport(sdm, newp, supportNew)); 174218c5995bSMatthew G. Knepley /* Hybrid edge */ 174318c5995bSMatthew G. Knepley coneNew[0] = newp; 174418c5995bSMatthew G. Knepley coneNew[1] = newp; 17459566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(sdm, hybedge, coneNew)); 174618c5995bSMatthew G. Knepley for (e = 0, qf = 0; e < supportSize; ++e) { 174718c5995bSMatthew G. Knepley PetscInt val, edge; 174818c5995bSMatthew G. Knepley 17499566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[e], &val)); 175018c5995bSMatthew G. Knepley if (val == 1) { 17519566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[e], numSplitPoints[dep + 1], splitPoints[dep + 1], &edge)); 175263a3b9bcSJacob Faibussowitsch PetscCheck(edge >= 0, comm, PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " is not a split edge", support[e]); 175318c5995bSMatthew G. Knepley supportNew[qf++] = edge + pMaxNew[dep + 2] + numSplitPoints[dep + 2]; 1754e1757548SMatthew G. Knepley } else if (val == (shift2 + 1)) { 17559566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[e], numUnsplitPoints[dep + 1], unsplitPoints[dep + 1], &edge)); 175663a3b9bcSJacob Faibussowitsch PetscCheck(edge >= 0, comm, PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " is not a unsplit edge", support[e]); 1757e1757548SMatthew G. Knepley supportNew[qf++] = edge + pMaxNew[dep + 2] + numSplitPoints[dep + 2] + numSplitPoints[dep + 1]; 175818c5995bSMatthew G. Knepley } 175918c5995bSMatthew G. Knepley } 17609566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupport(sdm, hybedge, supportNew)); 1761e1757548SMatthew G. Knepley } else if (dep == dim - 2) { 1762e1757548SMatthew G. Knepley const PetscInt hybface = p + pMaxNew[dep + 1] + numSplitPoints[dep + 1] + numSplitPoints[dep]; 1763e1757548SMatthew G. Knepley 1764da1dd7e4SMatthew G. Knepley /* Unsplit edge: Faces into original edge, split face, and hybrid face twice */ 1765e1757548SMatthew G. Knepley for (f = 0, qf = 0; f < supportSize; ++f) { 1766e1757548SMatthew G. Knepley PetscInt val, face; 1767e1757548SMatthew G. Knepley 17689566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[f], &val)); 1769e1757548SMatthew G. Knepley if (val == dim - 1) { 17709566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[f], numSplitPoints[dep + 1], splitPoints[dep + 1], &face)); 177163a3b9bcSJacob Faibussowitsch PetscCheck(face >= 0, comm, PETSC_ERR_ARG_WRONG, "Face %" PetscInt_FMT " is not a split face", support[f]); 17722582d50cSToby Isaac supportNew[qf++] = DMPlexShiftPoint_Internal(support[f], depth, depthShift) /*support[f] + depthOffset[dep+1]*/; 1773e1757548SMatthew G. Knepley supportNew[qf++] = face + pMaxNew[dep + 1]; 1774e1757548SMatthew G. Knepley } else { 17752582d50cSToby Isaac supportNew[qf++] = DMPlexShiftPoint_Internal(support[f], depth, depthShift) /*support[f] + depthOffset[dep+1]*/; 1776e1757548SMatthew G. Knepley } 1777e1757548SMatthew G. Knepley } 1778e1757548SMatthew G. Knepley supportNew[qf++] = hybface; 1779e1757548SMatthew G. Knepley supportNew[qf++] = hybface; 17809566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(sdm, newp, &supportSizeNew)); 178163a3b9bcSJacob 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); 17829566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupport(sdm, newp, supportNew)); 1783e1757548SMatthew G. Knepley /* Add hybrid face */ 1784e1757548SMatthew G. Knepley coneNew[0] = newp; 1785212cc919SMatthew G. Knepley coneNew[1] = newp; 17869566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[0], numUnsplitPoints[dep - 1], unsplitPoints[dep - 1], &v)); 178763a3b9bcSJacob Faibussowitsch PetscCheck(v >= 0, comm, PETSC_ERR_ARG_WRONG, "Vertex %" PetscInt_FMT " is not an unsplit vertex", cone[0]); 1788212cc919SMatthew G. Knepley coneNew[2] = v + pMaxNew[dep] + numSplitPoints[dep] + numSplitPoints[dep - 1]; 17899566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[1], numUnsplitPoints[dep - 1], unsplitPoints[dep - 1], &v)); 179063a3b9bcSJacob Faibussowitsch PetscCheck(v >= 0, comm, PETSC_ERR_ARG_WRONG, "Vertex %" PetscInt_FMT " is not an unsplit vertex", cone[1]); 1791e1757548SMatthew G. Knepley coneNew[3] = v + pMaxNew[dep] + numSplitPoints[dep] + numSplitPoints[dep - 1]; 17929566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(sdm, hybface, coneNew)); 1793da1dd7e4SMatthew G. Knepley for (f = 0, qf = 0; f < supportSize; ++f) { 1794da1dd7e4SMatthew G. Knepley PetscInt val, face; 1795da1dd7e4SMatthew G. Knepley 17969566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, support[f], &val)); 1797da1dd7e4SMatthew G. Knepley if (val == dim - 1) { 17989566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[f], numSplitPoints[dep + 1], splitPoints[dep + 1], &face)); 1799da1dd7e4SMatthew G. Knepley supportNew[qf++] = face + pMaxNew[dep + 2] + numSplitPoints[dep + 2]; 1800da1dd7e4SMatthew G. Knepley } 1801da1dd7e4SMatthew G. Knepley } 18029566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(sdm, hybface, &supportSizeNew)); 180363a3b9bcSJacob 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); 18049566063dSJacob Faibussowitsch PetscCall(DMPlexSetSupport(sdm, hybface, supportNew)); 1805cd0c2139SMatthew G Knepley } 1806cd0c2139SMatthew G Knepley } 1807cd0c2139SMatthew G Knepley } 1808cd0c2139SMatthew G Knepley /* Step 6b: Replace split points in negative side cones */ 1809cd0c2139SMatthew G Knepley for (sp = 0; sp < numSP; ++sp) { 1810cd0c2139SMatthew G Knepley PetscInt dep = values[sp]; 1811cd0c2139SMatthew G Knepley IS pIS; 1812cd0c2139SMatthew G Knepley PetscInt numPoints; 1813cd0c2139SMatthew G Knepley const PetscInt *points; 1814cd0c2139SMatthew G Knepley 1815cd0c2139SMatthew G Knepley if (dep >= 0) continue; 18169566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, dep, &pIS)); 1817cd0c2139SMatthew G Knepley if (!pIS) continue; 1818cd0c2139SMatthew G Knepley dep = -dep - shift; 18199566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pIS, &numPoints)); 18209566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pIS, &points)); 1821cd0c2139SMatthew G Knepley for (p = 0; p < numPoints; ++p) { 1822cd0c2139SMatthew G Knepley const PetscInt oldp = points[p]; 18232582d50cSToby Isaac const PetscInt newp = DMPlexShiftPoint_Internal(oldp, depth, depthShift) /*depthOffset[dep] + oldp*/; 1824cd0c2139SMatthew G Knepley const PetscInt *cone; 1825cd0c2139SMatthew G Knepley PetscInt coneSize, c; 182650cf782dSMatthew G. Knepley /* PetscBool replaced = PETSC_FALSE; */ 1827cd0c2139SMatthew G Knepley 1828cd0c2139SMatthew G Knepley /* Negative edge: replace split vertex */ 1829cd0c2139SMatthew G Knepley /* Negative cell: replace split face */ 18309566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(sdm, newp, &coneSize)); 18319566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(sdm, newp, &cone)); 1832cd0c2139SMatthew G Knepley for (c = 0; c < coneSize; ++c) { 1833e38fbfedSToby Isaac const PetscInt coldp = DMPlexShiftPointInverse_Internal(cone[c], depth, depthShift); 1834cd0c2139SMatthew G Knepley PetscInt csplitp, cp, val; 1835cd0c2139SMatthew G Knepley 18369566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, coldp, &val)); 1837cd0c2139SMatthew G Knepley if (val == dep - 1) { 18389566063dSJacob Faibussowitsch PetscCall(PetscFindInt(coldp, numSplitPoints[dep - 1], splitPoints[dep - 1], &cp)); 183963a3b9bcSJacob Faibussowitsch PetscCheck(cp >= 0, comm, PETSC_ERR_ARG_WRONG, "Point %" PetscInt_FMT " is not a split point of dimension %" PetscInt_FMT, oldp, dep - 1); 1840cd0c2139SMatthew G Knepley csplitp = pMaxNew[dep - 1] + cp; 18419566063dSJacob Faibussowitsch PetscCall(DMPlexInsertCone(sdm, newp, c, csplitp)); 184250cf782dSMatthew G. Knepley /* replaced = PETSC_TRUE; */ 1843cd0c2139SMatthew G Knepley } 1844cd0c2139SMatthew G Knepley } 18454a189a86SMatthew G. Knepley /* Cells with only a vertex or edge on the submesh have no replacement */ 184628b400f6SJacob Faibussowitsch /* PetscCheck(replaced,comm, PETSC_ERR_ARG_WRONG, "The cone of point %d does not contain split points", oldp); */ 1847cd0c2139SMatthew G Knepley } 18489566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pIS, &points)); 18499566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pIS)); 1850cd0c2139SMatthew G Knepley } 18510e18dc48SMatthew G. Knepley PetscCall(DMPlexReorderCohesiveSupports(sdm)); 1852fa8e8ae5SToby Isaac /* Step 7: Coordinates */ 18539566063dSJacob Faibussowitsch PetscCall(DMPlexShiftCoordinates_Internal(dm, depthShift, sdm)); 18549566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(sdm, &coordSection)); 18559566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(sdm, &coordinates)); 18569566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 1857cd0c2139SMatthew G Knepley for (v = 0; v < (numSplitPoints ? numSplitPoints[0] : 0); ++v) { 18582582d50cSToby Isaac const PetscInt newp = DMPlexShiftPoint_Internal(splitPoints[0][v], depth, depthShift) /*depthOffset[0] + splitPoints[0][v]*/; 1859cd0c2139SMatthew G Knepley const PetscInt splitp = pMaxNew[0] + v; 1860cd0c2139SMatthew G Knepley PetscInt dof, off, soff, d; 1861cd0c2139SMatthew G Knepley 18629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, newp, &dof)); 18639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, newp, &off)); 18649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, splitp, &soff)); 1865cd0c2139SMatthew G Knepley for (d = 0; d < dof; ++d) coords[soff + d] = coords[off + d]; 1866cd0c2139SMatthew G Knepley } 18679566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 1868fa8e8ae5SToby Isaac /* Step 8: SF, if I can figure this out we can split the mesh in parallel */ 18699566063dSJacob Faibussowitsch PetscCall(DMPlexShiftSF_Internal(dm, depthShift, sdm)); 1870b6dfa339SMatthew G. Knepley /* TODO We need to associate the ghost points with the correct replica */ 1871fa8e8ae5SToby Isaac /* Step 9: Labels */ 18729566063dSJacob Faibussowitsch PetscCall(DMPlexShiftLabels_Internal(dm, depthShift, sdm)); 18739566063dSJacob Faibussowitsch PetscCall(DMPlexCreateVTKLabel_Internal(dm, PETSC_FALSE, sdm)); 18749566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(sdm, &numLabels)); 1875cd0c2139SMatthew G Knepley for (dep = 0; dep <= depth; ++dep) { 1876cd0c2139SMatthew G Knepley for (p = 0; p < numSplitPoints[dep]; ++p) { 18772582d50cSToby Isaac const PetscInt newp = DMPlexShiftPoint_Internal(splitPoints[dep][p], depth, depthShift) /*depthOffset[dep] + splitPoints[dep][p]*/; 1878cd0c2139SMatthew G Knepley const PetscInt splitp = pMaxNew[dep] + p; 1879cd0c2139SMatthew G Knepley PetscInt l; 1880cd0c2139SMatthew G Knepley 18817db7e0a7SMatthew G. Knepley if (splitLabel) { 18827db7e0a7SMatthew G. Knepley const PetscInt val = 100 + dep; 18837db7e0a7SMatthew G. Knepley 18849566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(splitLabel, newp, val)); 18859566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(splitLabel, splitp, -val)); 18867db7e0a7SMatthew G. Knepley } 1887cd0c2139SMatthew G Knepley for (l = 0; l < numLabels; ++l) { 1888cd0c2139SMatthew G Knepley DMLabel mlabel; 1889cd0c2139SMatthew G Knepley const char *lname; 1890cd0c2139SMatthew G Knepley PetscInt val; 18919a356370SMatthew G. Knepley PetscBool isDepth; 1892cd0c2139SMatthew G Knepley 18939566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(sdm, l, &lname)); 18949566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(lname, "depth", &isDepth)); 18959a356370SMatthew G. Knepley if (isDepth) continue; 18969566063dSJacob Faibussowitsch PetscCall(DMGetLabel(sdm, lname, &mlabel)); 18979566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(mlabel, newp, &val)); 189848a46eb9SPierre Jolivet if (val >= 0) PetscCall(DMLabelSetValue(mlabel, splitp, val)); 1899cd0c2139SMatthew G Knepley } 1900cd0c2139SMatthew G Knepley } 1901cd0c2139SMatthew G Knepley } 1902cd0c2139SMatthew G Knepley for (sp = 0; sp < numSP; ++sp) { 1903cd0c2139SMatthew G Knepley const PetscInt dep = values[sp]; 1904cd0c2139SMatthew G Knepley 1905cd0c2139SMatthew G Knepley if ((dep < 0) || (dep > depth)) continue; 19069566063dSJacob Faibussowitsch if (splitIS[dep]) PetscCall(ISRestoreIndices(splitIS[dep], &splitPoints[dep])); 19079566063dSJacob Faibussowitsch PetscCall(ISDestroy(&splitIS[dep])); 19089566063dSJacob Faibussowitsch if (unsplitIS[dep]) PetscCall(ISRestoreIndices(unsplitIS[dep], &unsplitPoints[dep])); 19099566063dSJacob Faibussowitsch PetscCall(ISDestroy(&unsplitIS[dep])); 1910cd0c2139SMatthew G Knepley } 1911b6dfa339SMatthew G. Knepley if (ghostIS) PetscCall(ISRestoreIndices(ghostIS, &ghostPoints)); 1912b6dfa339SMatthew G. Knepley PetscCall(ISDestroy(&ghostIS)); 1913cd0c2139SMatthew G Knepley if (label) { 19149566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 19159566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 1916cd0c2139SMatthew G Knepley } 19170d4d4d06SMatthew G. Knepley for (d = 0; d <= depth; ++d) { 19189566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(sdm, d, NULL, &pEnd)); 191936dbac82SMatthew G. Knepley pMaxNew[d] = pEnd - numHybridPoints[d] - numHybridPointsOld[d]; 19200d4d4d06SMatthew G. Knepley } 19219566063dSJacob Faibussowitsch PetscCall(PetscFree3(coneNew, coneONew, supportNew)); 19229566063dSJacob Faibussowitsch PetscCall(PetscFree5(depthMax, depthEnd, depthShift, pMaxNew, numHybridPointsOld)); 19239566063dSJacob Faibussowitsch PetscCall(PetscFree7(splitIS, unsplitIS, numSplitPoints, numUnsplitPoints, numHybridPoints, splitPoints, unsplitPoints)); 19243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1925cd0c2139SMatthew G Knepley } 1926cd0c2139SMatthew G Knepley 1927cd0c2139SMatthew G Knepley /*@C 1928cd0c2139SMatthew G Knepley DMPlexConstructCohesiveCells - Construct cohesive cells which split the face along an internal interface 1929cd0c2139SMatthew G Knepley 193020f4b53cSBarry Smith Collective 1931cd0c2139SMatthew G Knepley 1932cd0c2139SMatthew G Knepley Input Parameters: 193320f4b53cSBarry Smith + dm - The original `DM` 193420f4b53cSBarry Smith - label - The `DMLabel` specifying the boundary faces (this could be auto-generated) 1935cd0c2139SMatthew G Knepley 1936cd0c2139SMatthew G Knepley Output Parameters: 193720f4b53cSBarry Smith + splitLabel - The `DMLabel` containing the split points, or `NULL` if no output is desired 193820f4b53cSBarry Smith - dmSplit - The new `DM` 1939cd0c2139SMatthew G Knepley 1940cd0c2139SMatthew G Knepley Level: developer 1941cd0c2139SMatthew G Knepley 19421cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexLabelCohesiveComplete()` 1943cd0c2139SMatthew G Knepley @*/ 1944d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexConstructCohesiveCells(DM dm, DMLabel label, DMLabel splitLabel, DM *dmSplit) 1945d71ae5a4SJacob Faibussowitsch { 1946cd0c2139SMatthew G Knepley DM sdm; 1947cd0c2139SMatthew G Knepley PetscInt dim; 1948cd0c2139SMatthew G Knepley 1949cd0c2139SMatthew G Knepley PetscFunctionBegin; 1950cd0c2139SMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 19514f572ea9SToby Isaac PetscAssertPointer(dmSplit, 4); 19529566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm)); 19539566063dSJacob Faibussowitsch PetscCall(DMSetType(sdm, DMPLEX)); 19549566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 19559566063dSJacob Faibussowitsch PetscCall(DMSetDimension(sdm, dim)); 1956cd0c2139SMatthew G Knepley switch (dim) { 1957cd0c2139SMatthew G Knepley case 2: 1958d71ae5a4SJacob Faibussowitsch case 3: 1959d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexConstructCohesiveCells_Internal(dm, label, splitLabel, sdm)); 1960d71ae5a4SJacob Faibussowitsch break; 1961d71ae5a4SJacob Faibussowitsch default: 1962d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct cohesive cells for dimension %" PetscInt_FMT, dim); 1963cd0c2139SMatthew G Knepley } 1964cd0c2139SMatthew G Knepley *dmSplit = sdm; 19653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1966cd0c2139SMatthew G Knepley } 1967cd0c2139SMatthew G Knepley 19680f66a230SMatthew G. Knepley /* Returns the side of the surface for a given cell with a face on the surface */ 1969d71ae5a4SJacob Faibussowitsch static PetscErrorCode GetSurfaceSide_Static(DM dm, DM subdm, PetscInt numSubpoints, const PetscInt *subpoints, PetscInt cell, PetscInt face, PetscBool *pos) 1970d71ae5a4SJacob Faibussowitsch { 19710f66a230SMatthew G. Knepley const PetscInt *cone, *ornt; 19720f66a230SMatthew G. Knepley PetscInt dim, coneSize, c; 19730f66a230SMatthew G. Knepley 19740f66a230SMatthew G. Knepley PetscFunctionBegin; 19750f66a230SMatthew G. Knepley *pos = PETSC_TRUE; 19769566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 19779566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cell, &coneSize)); 19789566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cell, &cone)); 19799566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, cell, &ornt)); 19800f66a230SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 19810f66a230SMatthew G. Knepley if (cone[c] == face) { 19820f66a230SMatthew G. Knepley PetscInt o = ornt[c]; 19830f66a230SMatthew G. Knepley 19840f66a230SMatthew G. Knepley if (subdm) { 19850f66a230SMatthew G. Knepley const PetscInt *subcone, *subornt; 19860f66a230SMatthew G. Knepley PetscInt subpoint, subface, subconeSize, sc; 19870f66a230SMatthew G. Knepley 19889566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cell, numSubpoints, subpoints, &subpoint)); 19899566063dSJacob Faibussowitsch PetscCall(PetscFindInt(face, numSubpoints, subpoints, &subface)); 19909566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(subdm, subpoint, &subconeSize)); 19919566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(subdm, subpoint, &subcone)); 19929566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(subdm, subpoint, &subornt)); 19930f66a230SMatthew G. Knepley for (sc = 0; sc < subconeSize; ++sc) { 19940f66a230SMatthew G. Knepley if (subcone[sc] == subface) { 19950f66a230SMatthew G. Knepley o = subornt[0]; 19960f66a230SMatthew G. Knepley break; 19970f66a230SMatthew G. Knepley } 19980f66a230SMatthew G. Knepley } 199963a3b9bcSJacob 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); 20000f66a230SMatthew G. Knepley } 20010f66a230SMatthew G. Knepley if (o >= 0) *pos = PETSC_TRUE; 20020f66a230SMatthew G. Knepley else *pos = PETSC_FALSE; 20030f66a230SMatthew G. Knepley break; 20040f66a230SMatthew G. Knepley } 20050f66a230SMatthew G. Knepley } 200663a3b9bcSJacob 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); 20073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20080f66a230SMatthew G. Knepley } 20090f66a230SMatthew G. Knepley 2010d71ae5a4SJacob Faibussowitsch static PetscErrorCode CheckFaultEdge_Private(DM dm, DMLabel label) 2011d71ae5a4SJacob Faibussowitsch { 2012accc9626SMatthew G. Knepley IS facePosIS, faceNegIS, dimIS; 2013accc9626SMatthew G. Knepley const PetscInt *points; 2014accc9626SMatthew G. Knepley PetscInt dim, numPoints, p, shift = 100, shift2 = 200; 2015accc9626SMatthew G. Knepley 2016accc9626SMatthew G. Knepley PetscFunctionBegin; 2017accc9626SMatthew G. Knepley PetscCall(DMGetDimension(dm, &dim)); 2018accc9626SMatthew G. Knepley /* If any faces touching the fault divide cells on either side, split them */ 2019accc9626SMatthew G. Knepley PetscCall(DMLabelGetStratumIS(label, shift + dim - 1, &facePosIS)); 2020accc9626SMatthew G. Knepley PetscCall(DMLabelGetStratumIS(label, -(shift + dim - 1), &faceNegIS)); 2021accc9626SMatthew G. Knepley if (!facePosIS || !faceNegIS) { 2022accc9626SMatthew G. Knepley PetscCall(ISDestroy(&facePosIS)); 2023accc9626SMatthew G. Knepley PetscCall(ISDestroy(&faceNegIS)); 20243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2025accc9626SMatthew G. Knepley } 2026accc9626SMatthew G. Knepley PetscCall(ISExpand(facePosIS, faceNegIS, &dimIS)); 2027accc9626SMatthew G. Knepley PetscCall(ISDestroy(&facePosIS)); 2028accc9626SMatthew G. Knepley PetscCall(ISDestroy(&faceNegIS)); 2029accc9626SMatthew G. Knepley PetscCall(ISGetLocalSize(dimIS, &numPoints)); 2030accc9626SMatthew G. Knepley PetscCall(ISGetIndices(dimIS, &points)); 2031accc9626SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 2032accc9626SMatthew G. Knepley const PetscInt point = points[p]; 2033accc9626SMatthew G. Knepley const PetscInt *support; 2034accc9626SMatthew G. Knepley PetscInt supportSize, valA, valB; 2035accc9626SMatthew G. Knepley 2036accc9626SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, point, &supportSize)); 2037accc9626SMatthew G. Knepley if (supportSize != 2) continue; 2038accc9626SMatthew G. Knepley PetscCall(DMPlexGetSupport(dm, point, &support)); 2039accc9626SMatthew G. Knepley PetscCall(DMLabelGetValue(label, support[0], &valA)); 2040accc9626SMatthew G. Knepley PetscCall(DMLabelGetValue(label, support[1], &valB)); 2041accc9626SMatthew G. Knepley if ((valA == -1) || (valB == -1)) continue; 2042accc9626SMatthew G. Knepley if (valA * valB > 0) continue; 2043e1a13daeSMatthew G. Knepley /* Check that this face is not incident on only unsplit faces, meaning has at least one split face */ 2044e1a13daeSMatthew G. Knepley { 2045e1a13daeSMatthew G. Knepley PetscInt *closure = NULL; 2046e1a13daeSMatthew G. Knepley PetscBool split = PETSC_FALSE; 2047e1a13daeSMatthew G. Knepley PetscInt closureSize, cl; 2048e1a13daeSMatthew G. Knepley 2049e1a13daeSMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure)); 2050e1a13daeSMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 2051e1a13daeSMatthew G. Knepley PetscCall(DMLabelGetValue(label, closure[cl], &valA)); 20529371c9d4SSatish Balay if ((valA >= 0) && (valA <= dim)) { 20539371c9d4SSatish Balay split = PETSC_TRUE; 20549371c9d4SSatish Balay break; 20559371c9d4SSatish Balay } 2056e1a13daeSMatthew G. Knepley } 2057e1a13daeSMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure)); 2058e1a13daeSMatthew G. Knepley if (!split) continue; 2059e1a13daeSMatthew G. Knepley } 2060accc9626SMatthew G. Knepley /* Split the face */ 2061accc9626SMatthew G. Knepley PetscCall(DMLabelGetValue(label, point, &valA)); 2062accc9626SMatthew G. Knepley PetscCall(DMLabelClearValue(label, point, valA)); 2063accc9626SMatthew G. Knepley PetscCall(DMLabelSetValue(label, point, dim - 1)); 2064accc9626SMatthew G. Knepley /* Label its closure: 2065accc9626SMatthew G. Knepley unmarked: label as unsplit 2066accc9626SMatthew G. Knepley incident: relabel as split 2067accc9626SMatthew G. Knepley split: do nothing 2068accc9626SMatthew G. Knepley */ 2069accc9626SMatthew G. Knepley { 2070accc9626SMatthew G. Knepley PetscInt *closure = NULL; 2071accc9626SMatthew G. Knepley PetscInt closureSize, cl, dep; 2072accc9626SMatthew G. Knepley 2073accc9626SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure)); 2074accc9626SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 2075accc9626SMatthew G. Knepley PetscCall(DMLabelGetValue(label, closure[cl], &valA)); 2076accc9626SMatthew G. Knepley if (valA == -1) { /* Mark as unsplit */ 2077accc9626SMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, closure[cl], &dep)); 2078accc9626SMatthew G. Knepley PetscCall(DMLabelSetValue(label, closure[cl], shift2 + dep)); 2079accc9626SMatthew G. Knepley } else if (((valA >= shift) && (valA < shift2)) || ((valA <= -shift) && (valA > -shift2))) { 2080accc9626SMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, closure[cl], &dep)); 2081accc9626SMatthew G. Knepley PetscCall(DMLabelClearValue(label, closure[cl], valA)); 2082accc9626SMatthew G. Knepley PetscCall(DMLabelSetValue(label, closure[cl], dep)); 2083accc9626SMatthew G. Knepley } 2084accc9626SMatthew G. Knepley } 2085accc9626SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure)); 2086accc9626SMatthew G. Knepley } 2087accc9626SMatthew G. Knepley } 2088accc9626SMatthew G. Knepley PetscCall(ISRestoreIndices(dimIS, &points)); 2089accc9626SMatthew G. Knepley PetscCall(ISDestroy(&dimIS)); 20903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2091accc9626SMatthew G. Knepley } 2092accc9626SMatthew G. Knepley 2093cd0c2139SMatthew G Knepley /*@ 20940f66a230SMatthew G. Knepley DMPlexLabelCohesiveComplete - Starting with a label marking points on an internal surface, we add all other mesh pieces 2095cd0c2139SMatthew G Knepley to complete the surface 2096cd0c2139SMatthew G Knepley 2097cd0c2139SMatthew G Knepley Input Parameters: 209820f4b53cSBarry Smith + dm - The `DM` 209920f4b53cSBarry Smith . label - A `DMLabel` marking the surface 210020f4b53cSBarry Smith . blabel - A `DMLabel` marking the vertices on the boundary which will not be duplicated, or `NULL` to find them automatically 210120f4b53cSBarry Smith . bvalue - Value of `DMLabel` marking the vertices on the boundary 2102bb55d314SMatthew G. Knepley . flip - Flag to flip the submesh normal and replace points on the other side 210320f4b53cSBarry Smith - subdm - The `DM` associated with the label, or `NULL` 2104cd0c2139SMatthew G Knepley 2105cd0c2139SMatthew G Knepley Output Parameter: 210620f4b53cSBarry Smith . label - A `DMLabel` marking all surface points 21070f66a230SMatthew G. Knepley 2108cd0c2139SMatthew G Knepley Level: developer 2109cd0c2139SMatthew G Knepley 211020f4b53cSBarry Smith Note: 211120f4b53cSBarry Smith The vertices in blabel are called "unsplit" in the terminology from hybrid cell creation. 211220f4b53cSBarry Smith 21131cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructCohesiveCells()`, `DMPlexLabelComplete()` 2114cd0c2139SMatthew G Knepley @*/ 2115d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelCohesiveComplete(DM dm, DMLabel label, DMLabel blabel, PetscInt bvalue, PetscBool flip, DM subdm) 2116d71ae5a4SJacob Faibussowitsch { 2117d90583fdSMatthew G. Knepley DMLabel depthLabel; 2118accc9626SMatthew G. Knepley IS dimIS, subpointIS = NULL; 211947946fd8SMatthew G. Knepley const PetscInt *points, *subpoints; 2120bb55d314SMatthew G. Knepley const PetscInt rev = flip ? -1 : 1; 2121accc9626SMatthew G. Knepley PetscInt shift = 100, shift2 = 200, shift3 = 300, dim, depth, numPoints, numSubpoints, p, val; 2122cd0c2139SMatthew G Knepley 2123cd0c2139SMatthew G Knepley PetscFunctionBegin; 21249566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 21259566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 21269566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 212747946fd8SMatthew G. Knepley if (subdm) { 21289566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(subdm, &subpointIS)); 212947946fd8SMatthew G. Knepley if (subpointIS) { 21309566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(subpointIS, &numSubpoints)); 21319566063dSJacob Faibussowitsch PetscCall(ISGetIndices(subpointIS, &subpoints)); 213247946fd8SMatthew G. Knepley } 213347946fd8SMatthew G. Knepley } 2134d7c8f101SMatthew G. Knepley /* Mark cell on the fault, and its faces which touch the fault: cell orientation for face gives the side of the fault */ 21359566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, dim - 1, &dimIS)); 2136accc9626SMatthew G. Knepley if (!dimIS) goto divide; 21379566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(dimIS, &numPoints)); 21389566063dSJacob Faibussowitsch PetscCall(ISGetIndices(dimIS, &points)); 2139d7c8f101SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { /* Loop over fault faces */ 2140cd0c2139SMatthew G Knepley const PetscInt *support; 2141cd0c2139SMatthew G Knepley PetscInt supportSize, s; 2142cd0c2139SMatthew G Knepley 21439566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, points[p], &supportSize)); 2144c4419245SMatthew G. Knepley #if 0 2145c4419245SMatthew G. Knepley if (supportSize != 2) { 2146c4419245SMatthew G. Knepley const PetscInt *lp; 2147c4419245SMatthew G. Knepley PetscInt Nlp, pind; 2148c4419245SMatthew G. Knepley 2149c4419245SMatthew G. Knepley /* Check that for a cell with a single support face, that face is in the SF */ 2150c4419245SMatthew G. Knepley /* THis check only works for the remote side. We would need root side information */ 21519566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(dm->sf, NULL, &Nlp, &lp, NULL)); 21529566063dSJacob Faibussowitsch PetscCall(PetscFindInt(points[p], Nlp, lp, &pind)); 215363a3b9bcSJacob 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); 2154c4419245SMatthew G. Knepley } 2155c4419245SMatthew G. Knepley #endif 21569566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, points[p], &support)); 2157cd0c2139SMatthew G Knepley for (s = 0; s < supportSize; ++s) { 21580f66a230SMatthew G. Knepley const PetscInt *cone; 2159cd0c2139SMatthew G Knepley PetscInt coneSize, c; 21600f66a230SMatthew G. Knepley PetscBool pos; 2161cd0c2139SMatthew G Knepley 21629566063dSJacob Faibussowitsch PetscCall(GetSurfaceSide_Static(dm, subdm, numSubpoints, subpoints, support[s], points[p], &pos)); 21639566063dSJacob Faibussowitsch if (pos) PetscCall(DMLabelSetValue(label, support[s], rev * (shift + dim))); 21649566063dSJacob Faibussowitsch else PetscCall(DMLabelSetValue(label, support[s], -rev * (shift + dim))); 21650f66a230SMatthew G. Knepley if (rev < 0) pos = !pos ? PETSC_TRUE : PETSC_FALSE; 21660f66a230SMatthew G. Knepley /* Put faces touching the fault in the label */ 21679566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize)); 21689566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, support[s], &cone)); 2169cd0c2139SMatthew G Knepley for (c = 0; c < coneSize; ++c) { 2170cd0c2139SMatthew G Knepley const PetscInt point = cone[c]; 2171cd0c2139SMatthew G Knepley 21729566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, point, &val)); 2173cd0c2139SMatthew G Knepley if (val == -1) { 2174cd0c2139SMatthew G Knepley PetscInt *closure = NULL; 2175cd0c2139SMatthew G Knepley PetscInt closureSize, cl; 2176cd0c2139SMatthew G Knepley 21779566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure)); 2178cd0c2139SMatthew G Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 2179cd0c2139SMatthew G Knepley const PetscInt clp = closure[cl]; 2180a0541d8aSMatthew G. Knepley PetscInt bval = -1; 2181cd0c2139SMatthew G Knepley 21829566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, clp, &val)); 21839566063dSJacob Faibussowitsch if (blabel) PetscCall(DMLabelGetValue(blabel, clp, &bval)); 2184a0541d8aSMatthew G. Knepley if ((val >= 0) && (val < dim - 1) && (bval < 0)) { 21859566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, point, pos == PETSC_TRUE ? shift + dim - 1 : -(shift + dim - 1))); 2186cd0c2139SMatthew G Knepley break; 2187cd0c2139SMatthew G Knepley } 2188cd0c2139SMatthew G Knepley } 21899566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure)); 2190cd0c2139SMatthew G Knepley } 2191cd0c2139SMatthew G Knepley } 2192cd0c2139SMatthew G Knepley } 2193cd0c2139SMatthew G Knepley } 2194accc9626SMatthew G. Knepley PetscCall(ISRestoreIndices(dimIS, &points)); 2195accc9626SMatthew G. Knepley PetscCall(ISDestroy(&dimIS)); 2196a0541d8aSMatthew G. Knepley /* Mark boundary points as unsplit */ 219786200784SMatthew G. Knepley if (blabel) { 2198accc9626SMatthew G. Knepley IS bdIS; 2199accc9626SMatthew G. Knepley 2200caf9e14dSMatthew G. Knepley PetscCall(DMLabelGetStratumIS(blabel, bvalue, &bdIS)); 2201accc9626SMatthew G. Knepley PetscCall(ISGetLocalSize(bdIS, &numPoints)); 2202accc9626SMatthew G. Knepley PetscCall(ISGetIndices(bdIS, &points)); 2203a0541d8aSMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 2204a0541d8aSMatthew G. Knepley const PetscInt point = points[p]; 2205a0541d8aSMatthew G. Knepley PetscInt val, bval; 2206a0541d8aSMatthew G. Knepley 22079566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(blabel, point, &bval)); 2208a0541d8aSMatthew G. Knepley if (bval >= 0) { 22099566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, point, &val)); 2210f7019248SMatthew G. Knepley if ((val < 0) || (val > dim)) { 2211f7019248SMatthew G. Knepley /* This could be a point added from splitting a vertex on an adjacent fault, otherwise its just wrong */ 22129566063dSJacob Faibussowitsch PetscCall(DMLabelClearValue(blabel, point, bval)); 2213f7019248SMatthew G. Knepley } 2214f7019248SMatthew G. Knepley } 2215f7019248SMatthew G. Knepley } 2216f7019248SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 2217f7019248SMatthew G. Knepley const PetscInt point = points[p]; 2218f7019248SMatthew G. Knepley PetscInt val, bval; 2219f7019248SMatthew G. Knepley 22209566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(blabel, point, &bval)); 2221f7019248SMatthew G. Knepley if (bval >= 0) { 222286200784SMatthew G. Knepley const PetscInt *cone, *support; 222386200784SMatthew G. Knepley PetscInt coneSize, supportSize, s, valA, valB, valE; 222486200784SMatthew G. Knepley 2225a0541d8aSMatthew G. Knepley /* Mark as unsplit */ 22269566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, point, &val)); 2227e1a13daeSMatthew 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); 22289566063dSJacob Faibussowitsch PetscCall(DMLabelClearValue(label, point, val)); 22299566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, point, shift2 + val)); 22302c06a818SMatthew G. Knepley /* Check for cross-edge 22312c06a818SMatthew G. Knepley A cross-edge has endpoints which are both on the boundary of the surface, but the edge itself is not. */ 223286200784SMatthew G. Knepley if (val != 0) continue; 22339566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, point, &support)); 22349566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, point, &supportSize)); 223586200784SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 22369566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, support[s], &cone)); 22379566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize)); 223863a3b9bcSJacob Faibussowitsch PetscCheck(coneSize == 2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Edge %" PetscInt_FMT " has %" PetscInt_FMT " vertices != 2", support[s], coneSize); 22399566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(blabel, cone[0], &valA)); 22409566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(blabel, cone[1], &valB)); 22419566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(blabel, support[s], &valE)); 22429566063dSJacob Faibussowitsch if ((valE < 0) && (valA >= 0) && (valB >= 0) && (cone[0] != cone[1])) PetscCall(DMLabelSetValue(blabel, support[s], 2)); 224386200784SMatthew G. Knepley } 2244a0541d8aSMatthew G. Knepley } 2245a0541d8aSMatthew G. Knepley } 2246accc9626SMatthew G. Knepley PetscCall(ISRestoreIndices(bdIS, &points)); 2247accc9626SMatthew G. Knepley PetscCall(ISDestroy(&bdIS)); 2248a0541d8aSMatthew G. Knepley } 2249b6dfa339SMatthew G. Knepley /* Mark ghost fault cells */ 2250b6dfa339SMatthew G. Knepley { 2251b6dfa339SMatthew G. Knepley PetscSF sf; 2252b6dfa339SMatthew G. Knepley const PetscInt *leaves; 2253b6dfa339SMatthew G. Knepley PetscInt Nl, l; 2254b6dfa339SMatthew G. Knepley 2255b6dfa339SMatthew G. Knepley PetscCall(DMGetPointSF(dm, &sf)); 2256b6dfa339SMatthew G. Knepley PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &leaves, NULL)); 2257accc9626SMatthew G. Knepley PetscCall(DMLabelGetStratumIS(label, dim - 1, &dimIS)); 2258accc9626SMatthew G. Knepley if (!dimIS) goto divide; 2259accc9626SMatthew G. Knepley PetscCall(ISGetLocalSize(dimIS, &numPoints)); 2260accc9626SMatthew G. Knepley PetscCall(ISGetIndices(dimIS, &points)); 2261b6dfa339SMatthew G. Knepley if (Nl > 0) { 2262b6dfa339SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 2263b6dfa339SMatthew G. Knepley const PetscInt point = points[p]; 2264b6dfa339SMatthew G. Knepley PetscInt val; 2265b6dfa339SMatthew G. Knepley 2266b6dfa339SMatthew G. Knepley PetscCall(PetscFindInt(point, Nl, leaves, &l)); 2267b6dfa339SMatthew G. Knepley if (l >= 0) { 2268b6dfa339SMatthew G. Knepley PetscInt *closure = NULL; 2269b6dfa339SMatthew G. Knepley PetscInt closureSize, cl; 2270b6dfa339SMatthew G. Knepley 2271b6dfa339SMatthew G. Knepley PetscCall(DMLabelGetValue(label, point, &val)); 2272b6dfa339SMatthew 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); 2273b6dfa339SMatthew G. Knepley PetscCall(DMLabelClearValue(label, point, val)); 2274b6dfa339SMatthew G. Knepley PetscCall(DMLabelSetValue(label, point, shift3 + val)); 2275b6dfa339SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure)); 2276accc9626SMatthew G. Knepley for (cl = 2; cl < closureSize * 2; cl += 2) { 2277b6dfa339SMatthew G. Knepley const PetscInt clp = closure[cl]; 2278b6dfa339SMatthew G. Knepley 2279b6dfa339SMatthew G. Knepley PetscCall(DMLabelGetValue(label, clp, &val)); 2280b6dfa339SMatthew 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); 2281b6dfa339SMatthew G. Knepley PetscCall(DMLabelClearValue(label, clp, val)); 2282b6dfa339SMatthew G. Knepley PetscCall(DMLabelSetValue(label, clp, shift3 + val)); 2283b6dfa339SMatthew G. Knepley } 2284b6dfa339SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure)); 2285b6dfa339SMatthew G. Knepley } 2286b6dfa339SMatthew G. Knepley } 2287b6dfa339SMatthew G. Knepley } 2288b6dfa339SMatthew G. Knepley PetscCall(ISRestoreIndices(dimIS, &points)); 2289b6dfa339SMatthew G. Knepley PetscCall(ISDestroy(&dimIS)); 2290accc9626SMatthew G. Knepley } 2291accc9626SMatthew G. Knepley divide: 2292b6dfa339SMatthew G. Knepley if (subpointIS) PetscCall(ISRestoreIndices(subpointIS, &subpoints)); 2293accc9626SMatthew G. Knepley PetscCall(DMPlexLabelFaultHalo(dm, label)); 2294accc9626SMatthew G. Knepley PetscCall(CheckFaultEdge_Private(dm, label)); 22953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2296cd0c2139SMatthew G Knepley } 2297cd0c2139SMatthew G Knepley 2298720e594eSMatthew G. Knepley /* Check that no cell have all vertices on the fault */ 229966976f2fSJacob Faibussowitsch static PetscErrorCode DMPlexCheckValidSubmesh_Private(DM dm, DMLabel label, DM subdm) 2300d71ae5a4SJacob Faibussowitsch { 2301720e594eSMatthew G. Knepley IS subpointIS; 2302720e594eSMatthew G. Knepley const PetscInt *dmpoints; 2303720e594eSMatthew G. Knepley PetscInt defaultValue, cStart, cEnd, c, vStart, vEnd; 2304720e594eSMatthew G. Knepley 2305720e594eSMatthew G. Knepley PetscFunctionBegin; 23063ba16761SJacob Faibussowitsch if (!label) PetscFunctionReturn(PETSC_SUCCESS); 23079566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(label, &defaultValue)); 23089566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(subdm, &subpointIS)); 23093ba16761SJacob Faibussowitsch if (!subpointIS) PetscFunctionReturn(PETSC_SUCCESS); 23109566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(subdm, 0, &cStart, &cEnd)); 23119566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 23129566063dSJacob Faibussowitsch PetscCall(ISGetIndices(subpointIS, &dmpoints)); 2313720e594eSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 2314720e594eSMatthew G. Knepley PetscBool invalidCell = PETSC_TRUE; 2315720e594eSMatthew G. Knepley PetscInt *closure = NULL; 2316720e594eSMatthew G. Knepley PetscInt closureSize, cl; 2317720e594eSMatthew G. Knepley 23189566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, dmpoints[c], PETSC_TRUE, &closureSize, &closure)); 2319720e594eSMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 2320720e594eSMatthew G. Knepley PetscInt value = 0; 2321720e594eSMatthew G. Knepley 2322720e594eSMatthew G. Knepley if ((closure[cl] < vStart) || (closure[cl] >= vEnd)) continue; 23239566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, closure[cl], &value)); 23249371c9d4SSatish Balay if (value == defaultValue) { 23259371c9d4SSatish Balay invalidCell = PETSC_FALSE; 23269371c9d4SSatish Balay break; 23279371c9d4SSatish Balay } 2328720e594eSMatthew G. Knepley } 23299566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, dmpoints[c], PETSC_TRUE, &closureSize, &closure)); 2330720e594eSMatthew G. Knepley if (invalidCell) { 23319566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(subpointIS, &dmpoints)); 23329566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subpointIS)); 23339566063dSJacob Faibussowitsch PetscCall(DMDestroy(&subdm)); 233463a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Ambiguous submesh. Cell %" PetscInt_FMT " has all of its vertices on the submesh.", dmpoints[c]); 2335720e594eSMatthew G. Knepley } 2336720e594eSMatthew G. Knepley } 23379566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(subpointIS, &dmpoints)); 23383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2339720e594eSMatthew G. Knepley } 2340720e594eSMatthew G. Knepley 2341c08575a3SMatthew G. Knepley /*@ 23423cf72582SMatthew G. Knepley DMPlexCreateHybridMesh - Create a mesh with hybrid cells along an internal interface 23433cf72582SMatthew G. Knepley 234420f4b53cSBarry Smith Collective 23453cf72582SMatthew G. Knepley 23463cf72582SMatthew G. Knepley Input Parameters: 234720f4b53cSBarry Smith + dm - The original `DM` 2348720e594eSMatthew G. Knepley . label - The label specifying the interface vertices 2349caf9e14dSMatthew G. Knepley . bdlabel - The optional label specifying the interface boundary vertices 2350caf9e14dSMatthew G. Knepley - bdvalue - Value of optional label specifying the interface boundary vertices 23513cf72582SMatthew G. Knepley 23523cf72582SMatthew G. Knepley Output Parameters: 235320f4b53cSBarry Smith + hybridLabel - The label fully marking the interface, or `NULL` if no output is desired 235420f4b53cSBarry Smith . splitLabel - The label containing the split points, or `NULL` if no output is desired 235520f4b53cSBarry Smith . dmInterface - The new interface `DM`, or `NULL` 235620f4b53cSBarry Smith - dmHybrid - The new `DM` with cohesive cells 23573cf72582SMatthew G. Knepley 235820f4b53cSBarry Smith Level: developer 235920f4b53cSBarry Smith 236020f4b53cSBarry Smith Note: 236120f4b53cSBarry Smith The hybridLabel indicates what parts of the original mesh impinged on the division surface. For points 23626eccb800SMatthew Knepley directly on the division surface, they are labeled with their dimension, so an edge 7 on the division surface would be 23636eccb800SMatthew Knepley 7 (1) in hybridLabel. For points that impinge from the positive side, they are labeled with 100+dim, so an edge 6 with 23646eccb800SMatthew 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 23656eccb800SMatthew Knepley surface also hits vertex 3, it would be 9 (-101) in hybridLabel. 23666eccb800SMatthew Knepley 23676eccb800SMatthew Knepley The splitLabel indicates what points in the new hybrid mesh were the result of splitting points in the original 236840cdb708SMatthew Knepley mesh. The label value is $\pm 100+dim$ for each point. For example, if two edges 10 and 14 in the hybrid resulting from 23696eccb800SMatthew Knepley splitting an edge in the original mesh, you would have 10 (101) and 14 (-101) in the splitLabel. 23706eccb800SMatthew Knepley 237120f4b53cSBarry Smith The dmInterface is a `DM` built from the original division surface. It has a label which can be retrieved using 237220f4b53cSBarry Smith `DMPlexGetSubpointMap()` which maps each point back to the point in the surface of the original mesh. 23736eccb800SMatthew Knepley 23741cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructCohesiveCells()`, `DMPlexLabelCohesiveComplete()`, `DMPlexGetSubpointMap()`, `DMCreate()` 23753cf72582SMatthew G. Knepley @*/ 2376d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateHybridMesh(DM dm, DMLabel label, DMLabel bdlabel, PetscInt bdvalue, DMLabel *hybridLabel, DMLabel *splitLabel, DM *dmInterface, DM *dmHybrid) 2377d71ae5a4SJacob Faibussowitsch { 23783cf72582SMatthew G. Knepley DM idm; 23797db7e0a7SMatthew G. Knepley DMLabel subpointMap, hlabel, slabel = NULL; 23803cf72582SMatthew G. Knepley PetscInt dim; 23813cf72582SMatthew G. Knepley 23823cf72582SMatthew G. Knepley PetscFunctionBegin; 23833cf72582SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23844f572ea9SToby Isaac if (label) PetscAssertPointer(label, 2); 23854f572ea9SToby Isaac if (bdlabel) PetscAssertPointer(bdlabel, 3); 23864f572ea9SToby Isaac if (hybridLabel) PetscAssertPointer(hybridLabel, 5); 23874f572ea9SToby Isaac if (splitLabel) PetscAssertPointer(splitLabel, 6); 23884f572ea9SToby Isaac if (dmInterface) PetscAssertPointer(dmInterface, 7); 23894f572ea9SToby Isaac PetscAssertPointer(dmHybrid, 8); 23909566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 23919566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSubmesh(dm, label, 1, PETSC_FALSE, &idm)); 23929566063dSJacob Faibussowitsch PetscCall(DMPlexCheckValidSubmesh_Private(dm, label, idm)); 23939566063dSJacob Faibussowitsch PetscCall(DMPlexOrient(idm)); 23949566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointMap(idm, &subpointMap)); 23959566063dSJacob Faibussowitsch PetscCall(DMLabelDuplicate(subpointMap, &hlabel)); 23969566063dSJacob Faibussowitsch PetscCall(DMLabelClearStratum(hlabel, dim)); 23977db7e0a7SMatthew G. Knepley if (splitLabel) { 23987db7e0a7SMatthew G. Knepley const char *name; 23997db7e0a7SMatthew G. Knepley char sname[PETSC_MAX_PATH_LEN]; 24007db7e0a7SMatthew G. Knepley 24019566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)hlabel, &name)); 2402c6a7a370SJeremy L Thompson PetscCall(PetscStrncpy(sname, name, sizeof(sname))); 2403c6a7a370SJeremy L Thompson PetscCall(PetscStrlcat(sname, " split", sizeof(sname))); 24049566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, sname, &slabel)); 24057db7e0a7SMatthew G. Knepley } 2406caf9e14dSMatthew G. Knepley PetscCall(DMPlexLabelCohesiveComplete(dm, hlabel, bdlabel, bdvalue, PETSC_FALSE, idm)); 24079371c9d4SSatish Balay if (dmInterface) { 24089371c9d4SSatish Balay *dmInterface = idm; 24099371c9d4SSatish Balay } else PetscCall(DMDestroy(&idm)); 24109566063dSJacob Faibussowitsch PetscCall(DMPlexConstructCohesiveCells(dm, hlabel, slabel, dmHybrid)); 24115de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, *dmHybrid)); 24123cf72582SMatthew G. Knepley if (hybridLabel) *hybridLabel = hlabel; 24139566063dSJacob Faibussowitsch else PetscCall(DMLabelDestroy(&hlabel)); 24147db7e0a7SMatthew G. Knepley if (splitLabel) *splitLabel = slabel; 24154a7ee7d0SMatthew G. Knepley { 24164a7ee7d0SMatthew G. Knepley DM cdm; 24174a7ee7d0SMatthew G. Knepley DMLabel ctLabel; 24184a7ee7d0SMatthew G. Knepley 24194a7ee7d0SMatthew G. Knepley /* We need to somehow share the celltype label with the coordinate dm */ 24209566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(*dmHybrid, &cdm)); 24219566063dSJacob Faibussowitsch PetscCall(DMPlexGetCellTypeLabel(*dmHybrid, &ctLabel)); 24229566063dSJacob Faibussowitsch PetscCall(DMSetLabel(cdm, ctLabel)); 24234a7ee7d0SMatthew G. Knepley } 24243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2425cd0c2139SMatthew G Knepley } 2426cd0c2139SMatthew G Knepley 2427efa14ee0SMatthew G Knepley /* Here we need the explicit assumption that: 2428efa14ee0SMatthew G Knepley 2429efa14ee0SMatthew G Knepley For any marked cell, the marked vertices constitute a single face 2430efa14ee0SMatthew G Knepley */ 2431d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMarkSubmesh_Uninterpolated(DM dm, DMLabel vertexLabel, PetscInt value, DMLabel subpointMap, PetscInt *numFaces, PetscInt *nFV, DM subdm) 2432d71ae5a4SJacob Faibussowitsch { 2433fed694aaSMatthew G. Knepley IS subvertexIS = NULL; 2434efa14ee0SMatthew G Knepley const PetscInt *subvertices; 2435412e9a14SMatthew G. Knepley PetscInt *pStart, *pEnd, pSize; 2436efa14ee0SMatthew G Knepley PetscInt depth, dim, d, numSubVerticesInitial = 0, v; 2437efa14ee0SMatthew G Knepley 2438efa14ee0SMatthew G Knepley PetscFunctionBegin; 2439efa14ee0SMatthew G Knepley *numFaces = 0; 2440efa14ee0SMatthew G Knepley *nFV = 0; 24419566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 24429566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 244377d178adSMatthew G. Knepley pSize = PetscMax(depth, dim) + 1; 24449566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pSize, &pStart, pSize, &pEnd)); 244548a46eb9SPierre Jolivet for (d = 0; d <= depth; ++d) PetscCall(DMPlexGetSimplexOrBoxCells(dm, depth - d, &pStart[d], &pEnd[d])); 2446efa14ee0SMatthew G Knepley /* Loop over initial vertices and mark all faces in the collective star() */ 24479566063dSJacob Faibussowitsch if (vertexLabel) PetscCall(DMLabelGetStratumIS(vertexLabel, value, &subvertexIS)); 2448efa14ee0SMatthew G Knepley if (subvertexIS) { 24499566063dSJacob Faibussowitsch PetscCall(ISGetSize(subvertexIS, &numSubVerticesInitial)); 24509566063dSJacob Faibussowitsch PetscCall(ISGetIndices(subvertexIS, &subvertices)); 2451efa14ee0SMatthew G Knepley } 2452efa14ee0SMatthew G Knepley for (v = 0; v < numSubVerticesInitial; ++v) { 2453efa14ee0SMatthew G Knepley const PetscInt vertex = subvertices[v]; 24540298fd71SBarry Smith PetscInt *star = NULL; 2455efa14ee0SMatthew G Knepley PetscInt starSize, s, numCells = 0, c; 2456efa14ee0SMatthew G Knepley 24579566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star)); 2458efa14ee0SMatthew G Knepley for (s = 0; s < starSize * 2; s += 2) { 2459efa14ee0SMatthew G Knepley const PetscInt point = star[s]; 2460efa14ee0SMatthew G Knepley if ((point >= pStart[depth]) && (point < pEnd[depth])) star[numCells++] = point; 2461efa14ee0SMatthew G Knepley } 2462efa14ee0SMatthew G Knepley for (c = 0; c < numCells; ++c) { 2463efa14ee0SMatthew G Knepley const PetscInt cell = star[c]; 24640298fd71SBarry Smith PetscInt *closure = NULL; 2465efa14ee0SMatthew G Knepley PetscInt closureSize, cl; 2466efa14ee0SMatthew G Knepley PetscInt cellLoc, numCorners = 0, faceSize = 0; 2467efa14ee0SMatthew G Knepley 24689566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(subpointMap, cell, &cellLoc)); 246965560c7fSMatthew G Knepley if (cellLoc == 2) continue; 247063a3b9bcSJacob Faibussowitsch PetscCheck(cellLoc < 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Cell %" PetscInt_FMT " has dimension %" PetscInt_FMT " in the surface label", cell, cellLoc); 24719566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure)); 2472efa14ee0SMatthew G Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 2473efa14ee0SMatthew G Knepley const PetscInt point = closure[cl]; 2474efa14ee0SMatthew G Knepley PetscInt vertexLoc; 2475efa14ee0SMatthew G Knepley 2476efa14ee0SMatthew G Knepley if ((point >= pStart[0]) && (point < pEnd[0])) { 2477efa14ee0SMatthew G Knepley ++numCorners; 24789566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(vertexLabel, point, &vertexLoc)); 2479830e53efSMatthew G. Knepley if (vertexLoc == value) closure[faceSize++] = point; 2480efa14ee0SMatthew G Knepley } 2481efa14ee0SMatthew G Knepley } 24829566063dSJacob Faibussowitsch if (!(*nFV)) PetscCall(DMPlexGetNumFaceVertices(dm, dim, numCorners, nFV)); 248363a3b9bcSJacob 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); 2484efa14ee0SMatthew G Knepley if (faceSize == *nFV) { 2485007baee2SMatthew G. Knepley const PetscInt *cells = NULL; 2486007baee2SMatthew G. Knepley PetscInt numCells, nc; 2487007baee2SMatthew G. Knepley 2488efa14ee0SMatthew G Knepley ++(*numFaces); 248948a46eb9SPierre Jolivet for (cl = 0; cl < faceSize; ++cl) PetscCall(DMLabelSetValue(subpointMap, closure[cl], 0)); 24909566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, faceSize, closure, &numCells, &cells)); 249148a46eb9SPierre Jolivet for (nc = 0; nc < numCells; ++nc) PetscCall(DMLabelSetValue(subpointMap, cells[nc], 2)); 24929566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, faceSize, closure, &numCells, &cells)); 2493efa14ee0SMatthew G Knepley } 24949566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure)); 2495efa14ee0SMatthew G Knepley } 24969566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star)); 2497efa14ee0SMatthew G Knepley } 249848a46eb9SPierre Jolivet if (subvertexIS) PetscCall(ISRestoreIndices(subvertexIS, &subvertices)); 24999566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subvertexIS)); 25009566063dSJacob Faibussowitsch PetscCall(PetscFree2(pStart, pEnd)); 25013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2502efa14ee0SMatthew G Knepley } 2503efa14ee0SMatthew G Knepley 2504d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMarkSubmesh_Interpolated(DM dm, DMLabel vertexLabel, PetscInt value, PetscBool markedFaces, DMLabel subpointMap, DM subdm) 2505d71ae5a4SJacob Faibussowitsch { 250634b4c39eSMatthew G. Knepley IS subvertexIS = NULL; 2507efa14ee0SMatthew G Knepley const PetscInt *subvertices; 2508412e9a14SMatthew G. Knepley PetscInt *pStart, *pEnd; 2509efa14ee0SMatthew G Knepley PetscInt dim, d, numSubVerticesInitial = 0, v; 2510efa14ee0SMatthew G Knepley 2511efa14ee0SMatthew G Knepley PetscFunctionBegin; 25129566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 25139566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(dim + 1, &pStart, dim + 1, &pEnd)); 251448a46eb9SPierre Jolivet for (d = 0; d <= dim; ++d) PetscCall(DMPlexGetSimplexOrBoxCells(dm, dim - d, &pStart[d], &pEnd[d])); 2515efa14ee0SMatthew G Knepley /* Loop over initial vertices and mark all faces in the collective star() */ 251634b4c39eSMatthew G. Knepley if (vertexLabel) { 25179566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(vertexLabel, value, &subvertexIS)); 2518efa14ee0SMatthew G Knepley if (subvertexIS) { 25199566063dSJacob Faibussowitsch PetscCall(ISGetSize(subvertexIS, &numSubVerticesInitial)); 25209566063dSJacob Faibussowitsch PetscCall(ISGetIndices(subvertexIS, &subvertices)); 2521efa14ee0SMatthew G Knepley } 252234b4c39eSMatthew G. Knepley } 2523efa14ee0SMatthew G Knepley for (v = 0; v < numSubVerticesInitial; ++v) { 2524efa14ee0SMatthew G Knepley const PetscInt vertex = subvertices[v]; 25250298fd71SBarry Smith PetscInt *star = NULL; 2526efa14ee0SMatthew G Knepley PetscInt starSize, s, numFaces = 0, f; 2527efa14ee0SMatthew G Knepley 25289566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star)); 2529efa14ee0SMatthew G Knepley for (s = 0; s < starSize * 2; s += 2) { 2530efa14ee0SMatthew G Knepley const PetscInt point = star[s]; 2531158acfadSMatthew G. Knepley PetscInt faceLoc; 2532158acfadSMatthew G. Knepley 2533158acfadSMatthew G. Knepley if ((point >= pStart[dim - 1]) && (point < pEnd[dim - 1])) { 2534158acfadSMatthew G. Knepley if (markedFaces) { 25359566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(vertexLabel, point, &faceLoc)); 2536158acfadSMatthew G. Knepley if (faceLoc < 0) continue; 2537158acfadSMatthew G. Knepley } 2538158acfadSMatthew G. Knepley star[numFaces++] = point; 2539158acfadSMatthew G. Knepley } 2540efa14ee0SMatthew G Knepley } 2541efa14ee0SMatthew G Knepley for (f = 0; f < numFaces; ++f) { 2542efa14ee0SMatthew G Knepley const PetscInt face = star[f]; 25430298fd71SBarry Smith PetscInt *closure = NULL; 2544efa14ee0SMatthew G Knepley PetscInt closureSize, c; 2545efa14ee0SMatthew G Knepley PetscInt faceLoc; 2546efa14ee0SMatthew G Knepley 25479566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(subpointMap, face, &faceLoc)); 2548efa14ee0SMatthew G Knepley if (faceLoc == dim - 1) continue; 254963a3b9bcSJacob Faibussowitsch PetscCheck(faceLoc < 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Face %" PetscInt_FMT " has dimension %" PetscInt_FMT " in the surface label", face, faceLoc); 25509566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, face, PETSC_TRUE, &closureSize, &closure)); 2551efa14ee0SMatthew G Knepley for (c = 0; c < closureSize * 2; c += 2) { 2552efa14ee0SMatthew G Knepley const PetscInt point = closure[c]; 2553efa14ee0SMatthew G Knepley PetscInt vertexLoc; 2554efa14ee0SMatthew G Knepley 2555efa14ee0SMatthew G Knepley if ((point >= pStart[0]) && (point < pEnd[0])) { 25569566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(vertexLabel, point, &vertexLoc)); 2557830e53efSMatthew G. Knepley if (vertexLoc != value) break; 2558efa14ee0SMatthew G Knepley } 2559efa14ee0SMatthew G Knepley } 2560efa14ee0SMatthew G Knepley if (c == closureSize * 2) { 2561efa14ee0SMatthew G Knepley const PetscInt *support; 2562efa14ee0SMatthew G Knepley PetscInt supportSize, s; 2563efa14ee0SMatthew G Knepley 2564efa14ee0SMatthew G Knepley for (c = 0; c < closureSize * 2; c += 2) { 2565efa14ee0SMatthew G Knepley const PetscInt point = closure[c]; 2566efa14ee0SMatthew G Knepley 2567efa14ee0SMatthew G Knepley for (d = 0; d < dim; ++d) { 2568efa14ee0SMatthew G Knepley if ((point >= pStart[d]) && (point < pEnd[d])) { 25699566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(subpointMap, point, d)); 2570efa14ee0SMatthew G Knepley break; 2571efa14ee0SMatthew G Knepley } 2572efa14ee0SMatthew G Knepley } 2573efa14ee0SMatthew G Knepley } 25749566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, face, &supportSize)); 25759566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, face, &support)); 257648a46eb9SPierre Jolivet for (s = 0; s < supportSize; ++s) PetscCall(DMLabelSetValue(subpointMap, support[s], dim)); 2577efa14ee0SMatthew G Knepley } 25789566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, face, PETSC_TRUE, &closureSize, &closure)); 2579efa14ee0SMatthew G Knepley } 25809566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star)); 2581efa14ee0SMatthew G Knepley } 25829566063dSJacob Faibussowitsch if (subvertexIS) PetscCall(ISRestoreIndices(subvertexIS, &subvertices)); 25839566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subvertexIS)); 25849566063dSJacob Faibussowitsch PetscCall(PetscFree2(pStart, pEnd)); 25853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2586efa14ee0SMatthew G Knepley } 2587efa14ee0SMatthew G Knepley 2588d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMarkCohesiveSubmesh_Uninterpolated(DM dm, PetscBool hasLagrange, const char labelname[], PetscInt value, DMLabel subpointMap, PetscInt *numFaces, PetscInt *nFV, PetscInt *subCells[], DM subdm) 2589d71ae5a4SJacob Faibussowitsch { 259027c04023SMatthew G. Knepley DMLabel label = NULL; 2591766ab985SMatthew G. Knepley const PetscInt *cone; 25929fc93327SToby Isaac PetscInt dim, cMax, cEnd, c, subc = 0, p, coneSize = -1; 2593766ab985SMatthew G. Knepley 2594812bfc34SJed Brown PetscFunctionBegin; 2595c0ed958bSJed Brown *numFaces = 0; 2596c0ed958bSJed Brown *nFV = 0; 25979566063dSJacob Faibussowitsch if (labelname) PetscCall(DMGetLabel(dm, labelname, &label)); 2598fed694aaSMatthew G. Knepley *subCells = NULL; 25999566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 26009566063dSJacob Faibussowitsch PetscCall(DMPlexGetTensorPrismBounds_Internal(dm, dim, &cMax, &cEnd)); 26013ba16761SJacob Faibussowitsch if (cMax < 0) PetscFunctionReturn(PETSC_SUCCESS); 260227c04023SMatthew G. Knepley if (label) { 260327c04023SMatthew G. Knepley for (c = cMax; c < cEnd; ++c) { 260427c04023SMatthew G. Knepley PetscInt val; 260527c04023SMatthew G. Knepley 26069566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, c, &val)); 260727c04023SMatthew G. Knepley if (val == value) { 260827c04023SMatthew G. Knepley ++(*numFaces); 26099566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 261027c04023SMatthew G. Knepley } 261127c04023SMatthew G. Knepley } 261227c04023SMatthew G. Knepley } else { 2613766ab985SMatthew G. Knepley *numFaces = cEnd - cMax; 26149566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cMax, &coneSize)); 261527c04023SMatthew G. Knepley } 26169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(*numFaces * 2, subCells)); 26173ba16761SJacob Faibussowitsch if (!(*numFaces)) PetscFunctionReturn(PETSC_SUCCESS); 26189fc93327SToby Isaac *nFV = hasLagrange ? coneSize / 3 : coneSize / 2; 2619766ab985SMatthew G. Knepley for (c = cMax; c < cEnd; ++c) { 2620766ab985SMatthew G. Knepley const PetscInt *cells; 2621766ab985SMatthew G. Knepley PetscInt numCells; 2622766ab985SMatthew G. Knepley 262327c04023SMatthew G. Knepley if (label) { 262427c04023SMatthew G. Knepley PetscInt val; 262527c04023SMatthew G. Knepley 26269566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, c, &val)); 262727c04023SMatthew G. Knepley if (val != value) continue; 262827c04023SMatthew G. Knepley } 26299566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 263048a46eb9SPierre Jolivet for (p = 0; p < *nFV; ++p) PetscCall(DMLabelSetValue(subpointMap, cone[p], 0)); 2631766ab985SMatthew G. Knepley /* Negative face */ 26329566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, *nFV, cone, &numCells, &cells)); 263327234c99SMatthew G. Knepley /* Not true in parallel 263408401ef6SPierre Jolivet PetscCheck(numCells == 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cohesive cells should separate two cells"); */ 2635766ab985SMatthew G. Knepley for (p = 0; p < numCells; ++p) { 26369566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(subpointMap, cells[p], 2)); 263727234c99SMatthew G. Knepley (*subCells)[subc++] = cells[p]; 2638766ab985SMatthew G. Knepley } 26399566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, *nFV, cone, &numCells, &cells)); 2640766ab985SMatthew G. Knepley /* Positive face is not included */ 2641766ab985SMatthew G. Knepley } 26423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2643766ab985SMatthew G. Knepley } 2644766ab985SMatthew G. Knepley 2645d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexMarkCohesiveSubmesh_Interpolated(DM dm, DMLabel label, PetscInt value, DMLabel subpointMap, DM subdm) 2646d71ae5a4SJacob Faibussowitsch { 2647766ab985SMatthew G. Knepley PetscInt *pStart, *pEnd; 2648766ab985SMatthew G. Knepley PetscInt dim, cMax, cEnd, c, d; 2649766ab985SMatthew G. Knepley 2650812bfc34SJed Brown PetscFunctionBegin; 26519566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 26529566063dSJacob Faibussowitsch PetscCall(DMPlexGetTensorPrismBounds_Internal(dm, dim, &cMax, &cEnd)); 26533ba16761SJacob Faibussowitsch if (cMax < 0) PetscFunctionReturn(PETSC_SUCCESS); 26549566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(dim + 1, &pStart, dim + 1, &pEnd)); 26559566063dSJacob Faibussowitsch for (d = 0; d <= dim; ++d) PetscCall(DMPlexGetDepthStratum(dm, d, &pStart[d], &pEnd[d])); 2656766ab985SMatthew G. Knepley for (c = cMax; c < cEnd; ++c) { 2657766ab985SMatthew G. Knepley const PetscInt *cone; 2658766ab985SMatthew G. Knepley PetscInt *closure = NULL; 2659b3154360SMatthew G. Knepley PetscInt fconeSize, coneSize, closureSize, cl, val; 2660766ab985SMatthew G. Knepley 266127c04023SMatthew G. Knepley if (label) { 26629566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(label, c, &val)); 266327c04023SMatthew G. Knepley if (val != value) continue; 266427c04023SMatthew G. Knepley } 26659566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 26669566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, c, &cone)); 26679566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cone[0], &fconeSize)); 26681dca8a05SBarry Smith PetscCheck(coneSize == (fconeSize ? fconeSize : 1) + 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cohesive cells should separate two cells"); 2669b3154360SMatthew G. Knepley /* Negative face */ 26709566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, cone[0], PETSC_TRUE, &closureSize, &closure)); 2671766ab985SMatthew G. Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 2672766ab985SMatthew G. Knepley const PetscInt point = closure[cl]; 2673766ab985SMatthew G. Knepley 2674766ab985SMatthew G. Knepley for (d = 0; d <= dim; ++d) { 2675766ab985SMatthew G. Knepley if ((point >= pStart[d]) && (point < pEnd[d])) { 26769566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(subpointMap, point, d)); 2677766ab985SMatthew G. Knepley break; 2678766ab985SMatthew G. Knepley } 2679766ab985SMatthew G. Knepley } 2680766ab985SMatthew G. Knepley } 26819566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], PETSC_TRUE, &closureSize, &closure)); 2682766ab985SMatthew G. Knepley /* Cells -- positive face is not included */ 2683766ab985SMatthew G. Knepley for (cl = 0; cl < 1; ++cl) { 2684766ab985SMatthew G. Knepley const PetscInt *support; 2685766ab985SMatthew G. Knepley PetscInt supportSize, s; 2686766ab985SMatthew G. Knepley 26879566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, cone[cl], &supportSize)); 268808401ef6SPierre Jolivet /* PetscCheck(supportSize == 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cohesive faces should separate two cells"); */ 26899566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, cone[cl], &support)); 269048a46eb9SPierre Jolivet for (s = 0; s < supportSize; ++s) PetscCall(DMLabelSetValue(subpointMap, support[s], dim)); 2691766ab985SMatthew G. Knepley } 2692766ab985SMatthew G. Knepley } 26939566063dSJacob Faibussowitsch PetscCall(PetscFree2(pStart, pEnd)); 26943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2695766ab985SMatthew G. Knepley } 2696766ab985SMatthew G. Knepley 2697d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetFaceOrientation(DM dm, PetscInt cell, PetscInt numCorners, PetscInt indices[], PetscInt oppositeVertex, PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 2698d71ae5a4SJacob Faibussowitsch { 269982f516ccSBarry Smith MPI_Comm comm; 2700e6ccafaeSMatthew G Knepley PetscBool posOrient = PETSC_FALSE; 2701e6ccafaeSMatthew G Knepley const PetscInt debug = 0; 2702e6ccafaeSMatthew G Knepley PetscInt cellDim, faceSize, f; 2703e6ccafaeSMatthew G Knepley 270482f516ccSBarry Smith PetscFunctionBegin; 27059566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 27069566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &cellDim)); 270763a3b9bcSJacob Faibussowitsch if (debug) PetscCall(PetscPrintf(comm, "cellDim: %" PetscInt_FMT " numCorners: %" PetscInt_FMT "\n", cellDim, numCorners)); 2708e6ccafaeSMatthew G Knepley 2709ddeab2a6SMatthew G. Knepley if (cellDim == 1 && numCorners == 2) { 2710ddeab2a6SMatthew G. Knepley /* Triangle */ 2711e6ccafaeSMatthew G Knepley faceSize = numCorners - 1; 2712e6ccafaeSMatthew G Knepley posOrient = !(oppositeVertex % 2) ? PETSC_TRUE : PETSC_FALSE; 2713ddeab2a6SMatthew G. Knepley } else if (cellDim == 2 && numCorners == 3) { 2714ddeab2a6SMatthew G. Knepley /* Triangle */ 2715ddeab2a6SMatthew G. Knepley faceSize = numCorners - 1; 2716ddeab2a6SMatthew G. Knepley posOrient = !(oppositeVertex % 2) ? PETSC_TRUE : PETSC_FALSE; 2717ddeab2a6SMatthew G. Knepley } else if (cellDim == 3 && numCorners == 4) { 2718ddeab2a6SMatthew G. Knepley /* Tetrahedron */ 2719ddeab2a6SMatthew G. Knepley faceSize = numCorners - 1; 2720ddeab2a6SMatthew G. Knepley posOrient = (oppositeVertex % 2) ? PETSC_TRUE : PETSC_FALSE; 2721e6ccafaeSMatthew G Knepley } else if (cellDim == 1 && numCorners == 3) { 2722e6ccafaeSMatthew G Knepley /* Quadratic line */ 2723e6ccafaeSMatthew G Knepley faceSize = 1; 2724e6ccafaeSMatthew G Knepley posOrient = PETSC_TRUE; 2725e6ccafaeSMatthew G Knepley } else if (cellDim == 2 && numCorners == 4) { 2726e6ccafaeSMatthew G Knepley /* Quads */ 2727e6ccafaeSMatthew G Knepley faceSize = 2; 2728e6ccafaeSMatthew G Knepley if ((indices[1] > indices[0]) && (indices[1] - indices[0] == 1)) { 2729e6ccafaeSMatthew G Knepley posOrient = PETSC_TRUE; 2730e6ccafaeSMatthew G Knepley } else if ((indices[0] == 3) && (indices[1] == 0)) { 2731e6ccafaeSMatthew G Knepley posOrient = PETSC_TRUE; 2732e6ccafaeSMatthew G Knepley } else { 2733e6ccafaeSMatthew G Knepley if (((indices[0] > indices[1]) && (indices[0] - indices[1] == 1)) || ((indices[0] == 0) && (indices[1] == 3))) { 2734e6ccafaeSMatthew G Knepley posOrient = PETSC_FALSE; 2735e6ccafaeSMatthew G Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossedge"); 2736e6ccafaeSMatthew G Knepley } 2737e6ccafaeSMatthew G Knepley } else if (cellDim == 2 && numCorners == 6) { 2738e6ccafaeSMatthew G Knepley /* Quadratic triangle (I hate this) */ 2739e6ccafaeSMatthew G Knepley /* Edges are determined by the first 2 vertices (corners of edges) */ 2740e6ccafaeSMatthew G Knepley const PetscInt faceSizeTri = 3; 2741e6ccafaeSMatthew G Knepley PetscInt sortedIndices[3], i, iFace; 2742e6ccafaeSMatthew G Knepley PetscBool found = PETSC_FALSE; 2743e6ccafaeSMatthew G Knepley PetscInt faceVerticesTriSorted[9] = { 2744e6ccafaeSMatthew G Knepley 0, 3, 4, /* bottom */ 2745e6ccafaeSMatthew G Knepley 1, 4, 5, /* right */ 2746e6ccafaeSMatthew G Knepley 2, 3, 5, /* left */ 2747e6ccafaeSMatthew G Knepley }; 2748e6ccafaeSMatthew G Knepley PetscInt faceVerticesTri[9] = { 2749e6ccafaeSMatthew G Knepley 0, 3, 4, /* bottom */ 2750e6ccafaeSMatthew G Knepley 1, 4, 5, /* right */ 2751e6ccafaeSMatthew G Knepley 2, 5, 3, /* left */ 2752e6ccafaeSMatthew G Knepley }; 2753e6ccafaeSMatthew G Knepley 2754e6ccafaeSMatthew G Knepley for (i = 0; i < faceSizeTri; ++i) sortedIndices[i] = indices[i]; 27559566063dSJacob Faibussowitsch PetscCall(PetscSortInt(faceSizeTri, sortedIndices)); 2756e6ccafaeSMatthew G Knepley for (iFace = 0; iFace < 3; ++iFace) { 2757e6ccafaeSMatthew G Knepley const PetscInt ii = iFace * faceSizeTri; 2758e6ccafaeSMatthew G Knepley PetscInt fVertex, cVertex; 2759e6ccafaeSMatthew G Knepley 27609371c9d4SSatish Balay if ((sortedIndices[0] == faceVerticesTriSorted[ii + 0]) && (sortedIndices[1] == faceVerticesTriSorted[ii + 1])) { 2761e6ccafaeSMatthew G Knepley for (fVertex = 0; fVertex < faceSizeTri; ++fVertex) { 2762e6ccafaeSMatthew G Knepley for (cVertex = 0; cVertex < faceSizeTri; ++cVertex) { 2763e6ccafaeSMatthew G Knepley if (indices[cVertex] == faceVerticesTri[ii + fVertex]) { 2764e6ccafaeSMatthew G Knepley faceVertices[fVertex] = origVertices[cVertex]; 2765e6ccafaeSMatthew G Knepley break; 2766e6ccafaeSMatthew G Knepley } 2767e6ccafaeSMatthew G Knepley } 2768e6ccafaeSMatthew G Knepley } 2769e6ccafaeSMatthew G Knepley found = PETSC_TRUE; 2770e6ccafaeSMatthew G Knepley break; 2771e6ccafaeSMatthew G Knepley } 2772e6ccafaeSMatthew G Knepley } 277328b400f6SJacob Faibussowitsch PetscCheck(found, comm, PETSC_ERR_ARG_WRONG, "Invalid tri crossface"); 2774e6ccafaeSMatthew G Knepley if (posOriented) *posOriented = PETSC_TRUE; 27753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2776e6ccafaeSMatthew G Knepley } else if (cellDim == 2 && numCorners == 9) { 2777e6ccafaeSMatthew G Knepley /* Quadratic quad (I hate this) */ 2778e6ccafaeSMatthew G Knepley /* Edges are determined by the first 2 vertices (corners of edges) */ 2779e6ccafaeSMatthew G Knepley const PetscInt faceSizeQuad = 3; 2780e6ccafaeSMatthew G Knepley PetscInt sortedIndices[3], i, iFace; 2781e6ccafaeSMatthew G Knepley PetscBool found = PETSC_FALSE; 2782e6ccafaeSMatthew G Knepley PetscInt faceVerticesQuadSorted[12] = { 2783e6ccafaeSMatthew G Knepley 0, 1, 4, /* bottom */ 2784e6ccafaeSMatthew G Knepley 1, 2, 5, /* right */ 2785e6ccafaeSMatthew G Knepley 2, 3, 6, /* top */ 2786e6ccafaeSMatthew G Knepley 0, 3, 7, /* left */ 2787e6ccafaeSMatthew G Knepley }; 2788e6ccafaeSMatthew G Knepley PetscInt faceVerticesQuad[12] = { 2789e6ccafaeSMatthew G Knepley 0, 1, 4, /* bottom */ 2790e6ccafaeSMatthew G Knepley 1, 2, 5, /* right */ 2791e6ccafaeSMatthew G Knepley 2, 3, 6, /* top */ 2792e6ccafaeSMatthew G Knepley 3, 0, 7, /* left */ 2793e6ccafaeSMatthew G Knepley }; 2794e6ccafaeSMatthew G Knepley 2795e6ccafaeSMatthew G Knepley for (i = 0; i < faceSizeQuad; ++i) sortedIndices[i] = indices[i]; 27969566063dSJacob Faibussowitsch PetscCall(PetscSortInt(faceSizeQuad, sortedIndices)); 2797e6ccafaeSMatthew G Knepley for (iFace = 0; iFace < 4; ++iFace) { 2798e6ccafaeSMatthew G Knepley const PetscInt ii = iFace * faceSizeQuad; 2799e6ccafaeSMatthew G Knepley PetscInt fVertex, cVertex; 2800e6ccafaeSMatthew G Knepley 28019371c9d4SSatish Balay if ((sortedIndices[0] == faceVerticesQuadSorted[ii + 0]) && (sortedIndices[1] == faceVerticesQuadSorted[ii + 1])) { 2802e6ccafaeSMatthew G Knepley for (fVertex = 0; fVertex < faceSizeQuad; ++fVertex) { 2803e6ccafaeSMatthew G Knepley for (cVertex = 0; cVertex < faceSizeQuad; ++cVertex) { 2804e6ccafaeSMatthew G Knepley if (indices[cVertex] == faceVerticesQuad[ii + fVertex]) { 2805e6ccafaeSMatthew G Knepley faceVertices[fVertex] = origVertices[cVertex]; 2806e6ccafaeSMatthew G Knepley break; 2807e6ccafaeSMatthew G Knepley } 2808e6ccafaeSMatthew G Knepley } 2809e6ccafaeSMatthew G Knepley } 2810e6ccafaeSMatthew G Knepley found = PETSC_TRUE; 2811e6ccafaeSMatthew G Knepley break; 2812e6ccafaeSMatthew G Knepley } 2813e6ccafaeSMatthew G Knepley } 281428b400f6SJacob Faibussowitsch PetscCheck(found, comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossface"); 2815e6ccafaeSMatthew G Knepley if (posOriented) *posOriented = PETSC_TRUE; 28163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2817e6ccafaeSMatthew G Knepley } else if (cellDim == 3 && numCorners == 8) { 2818e6ccafaeSMatthew G Knepley /* Hexes 2819e6ccafaeSMatthew G Knepley A hex is two oriented quads with the normal of the first 2820e6ccafaeSMatthew G Knepley pointing up at the second. 2821e6ccafaeSMatthew G Knepley 2822e6ccafaeSMatthew G Knepley 7---6 2823e6ccafaeSMatthew G Knepley /| /| 2824e6ccafaeSMatthew G Knepley 4---5 | 2825ddeab2a6SMatthew G. Knepley | 1-|-2 2826e6ccafaeSMatthew G Knepley |/ |/ 2827ddeab2a6SMatthew G. Knepley 0---3 2828e6ccafaeSMatthew G Knepley 2829e6ccafaeSMatthew G Knepley Faces are determined by the first 4 vertices (corners of faces) */ 2830e6ccafaeSMatthew G Knepley const PetscInt faceSizeHex = 4; 2831e6ccafaeSMatthew G Knepley PetscInt sortedIndices[4], i, iFace; 2832e6ccafaeSMatthew G Knepley PetscBool found = PETSC_FALSE; 2833e6ccafaeSMatthew G Knepley PetscInt faceVerticesHexSorted[24] = { 2834e6ccafaeSMatthew G Knepley 0, 1, 2, 3, /* bottom */ 2835e6ccafaeSMatthew G Knepley 4, 5, 6, 7, /* top */ 2836ddeab2a6SMatthew G. Knepley 0, 3, 4, 5, /* front */ 2837ddeab2a6SMatthew G. Knepley 2, 3, 5, 6, /* right */ 2838ddeab2a6SMatthew G. Knepley 1, 2, 6, 7, /* back */ 2839ddeab2a6SMatthew G. Knepley 0, 1, 4, 7, /* left */ 2840e6ccafaeSMatthew G Knepley }; 2841e6ccafaeSMatthew G Knepley PetscInt faceVerticesHex[24] = { 2842ddeab2a6SMatthew G. Knepley 1, 2, 3, 0, /* bottom */ 2843e6ccafaeSMatthew G Knepley 4, 5, 6, 7, /* top */ 2844ddeab2a6SMatthew G. Knepley 0, 3, 5, 4, /* front */ 2845ddeab2a6SMatthew G. Knepley 3, 2, 6, 5, /* right */ 2846ddeab2a6SMatthew G. Knepley 2, 1, 7, 6, /* back */ 2847ddeab2a6SMatthew G. Knepley 1, 0, 4, 7, /* left */ 2848e6ccafaeSMatthew G Knepley }; 2849e6ccafaeSMatthew G Knepley 2850e6ccafaeSMatthew G Knepley for (i = 0; i < faceSizeHex; ++i) sortedIndices[i] = indices[i]; 28519566063dSJacob Faibussowitsch PetscCall(PetscSortInt(faceSizeHex, sortedIndices)); 2852e6ccafaeSMatthew G Knepley for (iFace = 0; iFace < 6; ++iFace) { 2853e6ccafaeSMatthew G Knepley const PetscInt ii = iFace * faceSizeHex; 2854e6ccafaeSMatthew G Knepley PetscInt fVertex, cVertex; 2855e6ccafaeSMatthew G Knepley 28569371c9d4SSatish Balay if ((sortedIndices[0] == faceVerticesHexSorted[ii + 0]) && (sortedIndices[1] == faceVerticesHexSorted[ii + 1]) && (sortedIndices[2] == faceVerticesHexSorted[ii + 2]) && (sortedIndices[3] == faceVerticesHexSorted[ii + 3])) { 2857e6ccafaeSMatthew G Knepley for (fVertex = 0; fVertex < faceSizeHex; ++fVertex) { 2858e6ccafaeSMatthew G Knepley for (cVertex = 0; cVertex < faceSizeHex; ++cVertex) { 2859e6ccafaeSMatthew G Knepley if (indices[cVertex] == faceVerticesHex[ii + fVertex]) { 2860e6ccafaeSMatthew G Knepley faceVertices[fVertex] = origVertices[cVertex]; 2861e6ccafaeSMatthew G Knepley break; 2862e6ccafaeSMatthew G Knepley } 2863e6ccafaeSMatthew G Knepley } 2864e6ccafaeSMatthew G Knepley } 2865e6ccafaeSMatthew G Knepley found = PETSC_TRUE; 2866e6ccafaeSMatthew G Knepley break; 2867e6ccafaeSMatthew G Knepley } 2868e6ccafaeSMatthew G Knepley } 286928b400f6SJacob Faibussowitsch PetscCheck(found, comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 2870e6ccafaeSMatthew G Knepley if (posOriented) *posOriented = PETSC_TRUE; 28713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2872e6ccafaeSMatthew G Knepley } else if (cellDim == 3 && numCorners == 10) { 2873e6ccafaeSMatthew G Knepley /* Quadratic tet */ 2874e6ccafaeSMatthew G Knepley /* Faces are determined by the first 3 vertices (corners of faces) */ 2875e6ccafaeSMatthew G Knepley const PetscInt faceSizeTet = 6; 2876e6ccafaeSMatthew G Knepley PetscInt sortedIndices[6], i, iFace; 2877e6ccafaeSMatthew G Knepley PetscBool found = PETSC_FALSE; 2878e6ccafaeSMatthew G Knepley PetscInt faceVerticesTetSorted[24] = { 2879e6ccafaeSMatthew G Knepley 0, 1, 2, 6, 7, 8, /* bottom */ 2880e6ccafaeSMatthew G Knepley 0, 3, 4, 6, 7, 9, /* front */ 2881e6ccafaeSMatthew G Knepley 1, 4, 5, 7, 8, 9, /* right */ 2882e6ccafaeSMatthew G Knepley 2, 3, 5, 6, 8, 9, /* left */ 2883e6ccafaeSMatthew G Knepley }; 2884e6ccafaeSMatthew G Knepley PetscInt faceVerticesTet[24] = { 2885e6ccafaeSMatthew G Knepley 0, 1, 2, 6, 7, 8, /* bottom */ 2886e6ccafaeSMatthew G Knepley 0, 4, 3, 6, 7, 9, /* front */ 2887e6ccafaeSMatthew G Knepley 1, 5, 4, 7, 8, 9, /* right */ 2888e6ccafaeSMatthew G Knepley 2, 3, 5, 8, 6, 9, /* left */ 2889e6ccafaeSMatthew G Knepley }; 2890e6ccafaeSMatthew G Knepley 2891e6ccafaeSMatthew G Knepley for (i = 0; i < faceSizeTet; ++i) sortedIndices[i] = indices[i]; 28929566063dSJacob Faibussowitsch PetscCall(PetscSortInt(faceSizeTet, sortedIndices)); 2893e6ccafaeSMatthew G Knepley for (iFace = 0; iFace < 4; ++iFace) { 2894e6ccafaeSMatthew G Knepley const PetscInt ii = iFace * faceSizeTet; 2895e6ccafaeSMatthew G Knepley PetscInt fVertex, cVertex; 2896e6ccafaeSMatthew G Knepley 28979371c9d4SSatish Balay if ((sortedIndices[0] == faceVerticesTetSorted[ii + 0]) && (sortedIndices[1] == faceVerticesTetSorted[ii + 1]) && (sortedIndices[2] == faceVerticesTetSorted[ii + 2]) && (sortedIndices[3] == faceVerticesTetSorted[ii + 3])) { 2898e6ccafaeSMatthew G Knepley for (fVertex = 0; fVertex < faceSizeTet; ++fVertex) { 2899e6ccafaeSMatthew G Knepley for (cVertex = 0; cVertex < faceSizeTet; ++cVertex) { 2900e6ccafaeSMatthew G Knepley if (indices[cVertex] == faceVerticesTet[ii + fVertex]) { 2901e6ccafaeSMatthew G Knepley faceVertices[fVertex] = origVertices[cVertex]; 2902e6ccafaeSMatthew G Knepley break; 2903e6ccafaeSMatthew G Knepley } 2904e6ccafaeSMatthew G Knepley } 2905e6ccafaeSMatthew G Knepley } 2906e6ccafaeSMatthew G Knepley found = PETSC_TRUE; 2907e6ccafaeSMatthew G Knepley break; 2908e6ccafaeSMatthew G Knepley } 2909e6ccafaeSMatthew G Knepley } 291028b400f6SJacob Faibussowitsch PetscCheck(found, comm, PETSC_ERR_ARG_WRONG, "Invalid tet crossface"); 2911e6ccafaeSMatthew G Knepley if (posOriented) *posOriented = PETSC_TRUE; 29123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2913e6ccafaeSMatthew G Knepley } else if (cellDim == 3 && numCorners == 27) { 2914e6ccafaeSMatthew G Knepley /* Quadratic hexes (I hate this) 2915e6ccafaeSMatthew G Knepley A hex is two oriented quads with the normal of the first 2916e6ccafaeSMatthew G Knepley pointing up at the second. 2917e6ccafaeSMatthew G Knepley 2918e6ccafaeSMatthew G Knepley 7---6 2919e6ccafaeSMatthew G Knepley /| /| 2920e6ccafaeSMatthew G Knepley 4---5 | 2921e6ccafaeSMatthew G Knepley | 3-|-2 2922e6ccafaeSMatthew G Knepley |/ |/ 2923e6ccafaeSMatthew G Knepley 0---1 2924e6ccafaeSMatthew G Knepley 2925e6ccafaeSMatthew G Knepley Faces are determined by the first 4 vertices (corners of faces) */ 2926e6ccafaeSMatthew G Knepley const PetscInt faceSizeQuadHex = 9; 2927e6ccafaeSMatthew G Knepley PetscInt sortedIndices[9], i, iFace; 2928e6ccafaeSMatthew G Knepley PetscBool found = PETSC_FALSE; 2929e6ccafaeSMatthew G Knepley PetscInt faceVerticesQuadHexSorted[54] = { 2930e6ccafaeSMatthew G Knepley 0, 1, 2, 3, 8, 9, 10, 11, 24, /* bottom */ 2931e6ccafaeSMatthew G Knepley 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 2932e6ccafaeSMatthew G Knepley 0, 1, 4, 5, 8, 12, 16, 17, 22, /* front */ 2933e6ccafaeSMatthew G Knepley 1, 2, 5, 6, 9, 13, 17, 18, 21, /* right */ 2934e6ccafaeSMatthew G Knepley 2, 3, 6, 7, 10, 14, 18, 19, 23, /* back */ 2935e6ccafaeSMatthew G Knepley 0, 3, 4, 7, 11, 15, 16, 19, 20, /* left */ 2936e6ccafaeSMatthew G Knepley }; 2937e6ccafaeSMatthew G Knepley PetscInt faceVerticesQuadHex[54] = { 2938e6ccafaeSMatthew G Knepley 3, 2, 1, 0, 10, 9, 8, 11, 24, /* bottom */ 2939e6ccafaeSMatthew G Knepley 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 2940e6ccafaeSMatthew G Knepley 0, 1, 5, 4, 8, 17, 12, 16, 22, /* front */ 2941e6ccafaeSMatthew G Knepley 1, 2, 6, 5, 9, 18, 13, 17, 21, /* right */ 2942e6ccafaeSMatthew G Knepley 2, 3, 7, 6, 10, 19, 14, 18, 23, /* back */ 2943e6ccafaeSMatthew G Knepley 3, 0, 4, 7, 11, 16, 15, 19, 20 /* left */ 2944e6ccafaeSMatthew G Knepley }; 2945e6ccafaeSMatthew G Knepley 2946e6ccafaeSMatthew G Knepley for (i = 0; i < faceSizeQuadHex; ++i) sortedIndices[i] = indices[i]; 29479566063dSJacob Faibussowitsch PetscCall(PetscSortInt(faceSizeQuadHex, sortedIndices)); 2948e6ccafaeSMatthew G Knepley for (iFace = 0; iFace < 6; ++iFace) { 2949e6ccafaeSMatthew G Knepley const PetscInt ii = iFace * faceSizeQuadHex; 2950e6ccafaeSMatthew G Knepley PetscInt fVertex, cVertex; 2951e6ccafaeSMatthew G Knepley 29529371c9d4SSatish Balay if ((sortedIndices[0] == faceVerticesQuadHexSorted[ii + 0]) && (sortedIndices[1] == faceVerticesQuadHexSorted[ii + 1]) && (sortedIndices[2] == faceVerticesQuadHexSorted[ii + 2]) && (sortedIndices[3] == faceVerticesQuadHexSorted[ii + 3])) { 2953e6ccafaeSMatthew G Knepley for (fVertex = 0; fVertex < faceSizeQuadHex; ++fVertex) { 2954e6ccafaeSMatthew G Knepley for (cVertex = 0; cVertex < faceSizeQuadHex; ++cVertex) { 2955e6ccafaeSMatthew G Knepley if (indices[cVertex] == faceVerticesQuadHex[ii + fVertex]) { 2956e6ccafaeSMatthew G Knepley faceVertices[fVertex] = origVertices[cVertex]; 2957e6ccafaeSMatthew G Knepley break; 2958e6ccafaeSMatthew G Knepley } 2959e6ccafaeSMatthew G Knepley } 2960e6ccafaeSMatthew G Knepley } 2961e6ccafaeSMatthew G Knepley found = PETSC_TRUE; 2962e6ccafaeSMatthew G Knepley break; 2963e6ccafaeSMatthew G Knepley } 2964e6ccafaeSMatthew G Knepley } 296528b400f6SJacob Faibussowitsch PetscCheck(found, comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 2966e6ccafaeSMatthew G Knepley if (posOriented) *posOriented = PETSC_TRUE; 29673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2968e6ccafaeSMatthew G Knepley } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unknown cell type for faceOrientation()."); 2969e6ccafaeSMatthew G Knepley if (!posOrient) { 29709566063dSJacob Faibussowitsch if (debug) PetscCall(PetscPrintf(comm, " Reversing initial face orientation\n")); 2971e6ccafaeSMatthew G Knepley for (f = 0; f < faceSize; ++f) faceVertices[f] = origVertices[faceSize - 1 - f]; 2972e6ccafaeSMatthew G Knepley } else { 29739566063dSJacob Faibussowitsch if (debug) PetscCall(PetscPrintf(comm, " Keeping initial face orientation\n")); 2974e6ccafaeSMatthew G Knepley for (f = 0; f < faceSize; ++f) faceVertices[f] = origVertices[f]; 2975e6ccafaeSMatthew G Knepley } 2976e6ccafaeSMatthew G Knepley if (posOriented) *posOriented = posOrient; 29773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2978e6ccafaeSMatthew G Knepley } 2979e6ccafaeSMatthew G Knepley 2980c08575a3SMatthew G. Knepley /*@ 2981c08575a3SMatthew G. Knepley DMPlexGetOrientedFace - Given a cell and a face, as a set of vertices, return the oriented face, as a set of vertices, 2982c08575a3SMatthew G. Knepley in faceVertices. The orientation is such that the face normal points out of the cell 2983c08575a3SMatthew G. Knepley 298420f4b53cSBarry Smith Not Collective 2985c08575a3SMatthew G. Knepley 2986c08575a3SMatthew G. Knepley Input Parameters: 2987c08575a3SMatthew G. Knepley + dm - The original mesh 2988c08575a3SMatthew G. Knepley . cell - The cell mesh point 2989c08575a3SMatthew G. Knepley . faceSize - The number of vertices on the face 2990c08575a3SMatthew G. Knepley . face - The face vertices 2991c08575a3SMatthew G. Knepley . numCorners - The number of vertices on the cell 2992c08575a3SMatthew G. Knepley . indices - Local numbering of face vertices in cell cone 2993c08575a3SMatthew G. Knepley - origVertices - Original face vertices 2994c08575a3SMatthew G. Knepley 2995d8d19677SJose E. Roman Output Parameters: 2996c08575a3SMatthew G. Knepley + faceVertices - The face vertices properly oriented 299720f4b53cSBarry Smith - posOriented - `PETSC_TRUE` if the face was oriented with outward normal 2998c08575a3SMatthew G. Knepley 2999c08575a3SMatthew G. Knepley Level: developer 3000c08575a3SMatthew G. Knepley 30011cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()` 3002c08575a3SMatthew G. Knepley @*/ 3003d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetOrientedFace(DM dm, PetscInt cell, PetscInt faceSize, const PetscInt face[], PetscInt numCorners, PetscInt indices[], PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 3004d71ae5a4SJacob Faibussowitsch { 30050298fd71SBarry Smith const PetscInt *cone = NULL; 3006e6ccafaeSMatthew G Knepley PetscInt coneSize, v, f, v2; 3007e6ccafaeSMatthew G Knepley PetscInt oppositeVertex = -1; 3008e6ccafaeSMatthew G Knepley 3009e6ccafaeSMatthew G Knepley PetscFunctionBegin; 30109566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, cell, &coneSize)); 30119566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cell, &cone)); 3012e6ccafaeSMatthew G Knepley for (v = 0, v2 = 0; v < coneSize; ++v) { 3013e6ccafaeSMatthew G Knepley PetscBool found = PETSC_FALSE; 3014e6ccafaeSMatthew G Knepley 3015e6ccafaeSMatthew G Knepley for (f = 0; f < faceSize; ++f) { 3016e6ccafaeSMatthew G Knepley if (face[f] == cone[v]) { 30179371c9d4SSatish Balay found = PETSC_TRUE; 30189371c9d4SSatish Balay break; 3019e6ccafaeSMatthew G Knepley } 3020e6ccafaeSMatthew G Knepley } 3021e6ccafaeSMatthew G Knepley if (found) { 3022e6ccafaeSMatthew G Knepley indices[v2] = v; 3023e6ccafaeSMatthew G Knepley origVertices[v2] = cone[v]; 3024e6ccafaeSMatthew G Knepley ++v2; 3025e6ccafaeSMatthew G Knepley } else { 3026e6ccafaeSMatthew G Knepley oppositeVertex = v; 3027e6ccafaeSMatthew G Knepley } 3028e6ccafaeSMatthew G Knepley } 30299566063dSJacob Faibussowitsch PetscCall(DMPlexGetFaceOrientation(dm, cell, numCorners, indices, oppositeVertex, origVertices, faceVertices, posOriented)); 30303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3031e6ccafaeSMatthew G Knepley } 3032e6ccafaeSMatthew G Knepley 3033e6ccafaeSMatthew G Knepley /* 3034cd0c2139SMatthew G Knepley DMPlexInsertFace_Internal - Puts a face into the mesh 3035e6ccafaeSMatthew G Knepley 303620f4b53cSBarry Smith Not Collective 3037e6ccafaeSMatthew G Knepley 3038e6ccafaeSMatthew G Knepley Input Parameters: 303920f4b53cSBarry Smith + dm - The `DMPLEX` 3040e6ccafaeSMatthew G Knepley . numFaceVertex - The number of vertices in the face 304120f4b53cSBarry Smith . faceVertices - The vertices in the face for `dm` 3042e6ccafaeSMatthew G Knepley . subfaceVertices - The vertices in the face for subdm 304320f4b53cSBarry Smith . numCorners - The number of vertices in the `cell` 304420f4b53cSBarry Smith . cell - A cell in `dm` containing the face 3045e6ccafaeSMatthew G Knepley . subcell - A cell in subdm containing the face 3046e6ccafaeSMatthew G Knepley . firstFace - First face in the mesh 3047e6ccafaeSMatthew G Knepley - newFacePoint - Next face in the mesh 3048e6ccafaeSMatthew G Knepley 30492fe279fdSBarry Smith Output Parameter: 3050e6ccafaeSMatthew G Knepley . newFacePoint - Contains next face point number on input, updated on output 3051e6ccafaeSMatthew G Knepley 3052e6ccafaeSMatthew G Knepley Level: developer 3053e6ccafaeSMatthew G Knepley */ 3054d71ae5a4SJacob 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) 3055d71ae5a4SJacob Faibussowitsch { 305682f516ccSBarry Smith MPI_Comm comm; 3057e6ccafaeSMatthew G Knepley DM_Plex *submesh = (DM_Plex *)subdm->data; 3058e6ccafaeSMatthew G Knepley const PetscInt *faces; 3059e6ccafaeSMatthew G Knepley PetscInt numFaces, coneSize; 3060e6ccafaeSMatthew G Knepley 3061e6ccafaeSMatthew G Knepley PetscFunctionBegin; 30629566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 30639566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(subdm, subcell, &coneSize)); 306463a3b9bcSJacob Faibussowitsch PetscCheck(coneSize == 1, comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size of cell %" PetscInt_FMT " is %" PetscInt_FMT " != 1", cell, coneSize); 3065e6ccafaeSMatthew G Knepley #if 0 3066e6ccafaeSMatthew G Knepley /* Cannot use this because support() has not been constructed yet */ 30679566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces)); 3068e6ccafaeSMatthew G Knepley #else 3069e6ccafaeSMatthew G Knepley { 3070e6ccafaeSMatthew G Knepley PetscInt f; 3071e6ccafaeSMatthew G Knepley 3072e6ccafaeSMatthew G Knepley numFaces = 0; 30739566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(subdm, 1, MPIU_INT, (void **)&faces)); 3074e6ccafaeSMatthew G Knepley for (f = firstFace; f < *newFacePoint; ++f) { 3075e6ccafaeSMatthew G Knepley PetscInt dof, off, d; 3076e6ccafaeSMatthew G Knepley 30779566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(submesh->coneSection, f, &dof)); 30789566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(submesh->coneSection, f, &off)); 3079e6ccafaeSMatthew G Knepley /* Yes, I know this is quadratic, but I expect the sizes to be <5 */ 3080e6ccafaeSMatthew G Knepley for (d = 0; d < dof; ++d) { 3081e6ccafaeSMatthew G Knepley const PetscInt p = submesh->cones[off + d]; 3082e6ccafaeSMatthew G Knepley PetscInt v; 3083e6ccafaeSMatthew G Knepley 3084e6ccafaeSMatthew G Knepley for (v = 0; v < numFaceVertices; ++v) { 3085e6ccafaeSMatthew G Knepley if (subfaceVertices[v] == p) break; 3086e6ccafaeSMatthew G Knepley } 3087e6ccafaeSMatthew G Knepley if (v == numFaceVertices) break; 3088e6ccafaeSMatthew G Knepley } 3089e6ccafaeSMatthew G Knepley if (d == dof) { 3090e6ccafaeSMatthew G Knepley numFaces = 1; 3091e6ccafaeSMatthew G Knepley ((PetscInt *)faces)[0] = f; 3092e6ccafaeSMatthew G Knepley } 3093e6ccafaeSMatthew G Knepley } 3094e6ccafaeSMatthew G Knepley } 3095e6ccafaeSMatthew G Knepley #endif 309663a3b9bcSJacob Faibussowitsch PetscCheck(numFaces <= 1, comm, PETSC_ERR_ARG_WRONG, "Vertex set had %" PetscInt_FMT " faces, not one", numFaces); 3097f7d195e4SLawrence Mitchell if (numFaces == 1) { 3098e6ccafaeSMatthew G Knepley /* Add the other cell neighbor for this face */ 30999566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(subdm, subcell, faces)); 3100e6ccafaeSMatthew G Knepley } else { 3101e6ccafaeSMatthew G Knepley PetscInt *indices, *origVertices, *orientedVertices, *orientedSubVertices, v, ov; 3102e6ccafaeSMatthew G Knepley PetscBool posOriented; 3103e6ccafaeSMatthew G Knepley 31049566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(subdm, 4 * numFaceVertices * sizeof(PetscInt), MPIU_INT, &orientedVertices)); 3105e6ccafaeSMatthew G Knepley origVertices = &orientedVertices[numFaceVertices]; 3106e6ccafaeSMatthew G Knepley indices = &orientedVertices[numFaceVertices * 2]; 3107e6ccafaeSMatthew G Knepley orientedSubVertices = &orientedVertices[numFaceVertices * 3]; 31089566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrientedFace(dm, cell, numFaceVertices, faceVertices, numCorners, indices, origVertices, orientedVertices, &posOriented)); 3109e6ccafaeSMatthew G Knepley /* TODO: I know that routine should return a permutation, not the indices */ 3110e6ccafaeSMatthew G Knepley for (v = 0; v < numFaceVertices; ++v) { 3111e6ccafaeSMatthew G Knepley const PetscInt vertex = faceVertices[v], subvertex = subfaceVertices[v]; 3112e6ccafaeSMatthew G Knepley for (ov = 0; ov < numFaceVertices; ++ov) { 3113e6ccafaeSMatthew G Knepley if (orientedVertices[ov] == vertex) { 3114e6ccafaeSMatthew G Knepley orientedSubVertices[ov] = subvertex; 3115e6ccafaeSMatthew G Knepley break; 3116e6ccafaeSMatthew G Knepley } 3117e6ccafaeSMatthew G Knepley } 311863a3b9bcSJacob Faibussowitsch PetscCheck(ov != numFaceVertices, comm, PETSC_ERR_PLIB, "Could not find face vertex %" PetscInt_FMT " in orientated set", vertex); 3119e6ccafaeSMatthew G Knepley } 31209566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(subdm, *newFacePoint, orientedSubVertices)); 31219566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(subdm, subcell, newFacePoint)); 31229566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(subdm, 4 * numFaceVertices * sizeof(PetscInt), MPIU_INT, &orientedVertices)); 3123e6ccafaeSMatthew G Knepley ++(*newFacePoint); 3124e6ccafaeSMatthew G Knepley } 3125ef07cca7SMatthew G. Knepley #if 0 31269566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces)); 3127ef07cca7SMatthew G. Knepley #else 31289566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(subdm, 1, MPIU_INT, (void **)&faces)); 3129ef07cca7SMatthew G. Knepley #endif 31303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3131e6ccafaeSMatthew G Knepley } 3132e6ccafaeSMatthew G Knepley 3133d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSubmesh_Uninterpolated(DM dm, DMLabel vertexLabel, PetscInt value, DM subdm) 3134d71ae5a4SJacob Faibussowitsch { 313582f516ccSBarry Smith MPI_Comm comm; 313653156dfcSMatthew G. Knepley DMLabel subpointMap; 3137efa14ee0SMatthew G Knepley IS subvertexIS, subcellIS; 3138efa14ee0SMatthew G Knepley const PetscInt *subVertices, *subCells; 3139efa14ee0SMatthew G Knepley PetscInt numSubVertices, firstSubVertex, numSubCells; 3140fed694aaSMatthew G. Knepley PetscInt *subface, maxConeSize, numSubFaces = 0, firstSubFace, newFacePoint, nFV = 0; 3141efa14ee0SMatthew G Knepley PetscInt vStart, vEnd, c, f; 3142e6ccafaeSMatthew G Knepley 3143e6ccafaeSMatthew G Knepley PetscFunctionBegin; 31449566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 3145efa14ee0SMatthew G Knepley /* Create subpointMap which marks the submesh */ 31469566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "subpoint_map", &subpointMap)); 31479566063dSJacob Faibussowitsch PetscCall(DMPlexSetSubpointMap(subdm, subpointMap)); 31489566063dSJacob Faibussowitsch if (vertexLabel) PetscCall(DMPlexMarkSubmesh_Uninterpolated(dm, vertexLabel, value, subpointMap, &numSubFaces, &nFV, subdm)); 3149efa14ee0SMatthew G Knepley /* Setup chart */ 31509566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(subpointMap, 0, &numSubVertices)); 31519566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(subpointMap, 2, &numSubCells)); 31529566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(subdm, 0, numSubCells + numSubFaces + numSubVertices)); 31539566063dSJacob Faibussowitsch PetscCall(DMPlexSetVTKCellHeight(subdm, 1)); 3154e6ccafaeSMatthew G Knepley /* Set cone sizes */ 3155e6ccafaeSMatthew G Knepley firstSubVertex = numSubCells; 3156efa14ee0SMatthew G Knepley firstSubFace = numSubCells + numSubVertices; 3157e6ccafaeSMatthew G Knepley newFacePoint = firstSubFace; 31589566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(subpointMap, 0, &subvertexIS)); 31599566063dSJacob Faibussowitsch if (subvertexIS) PetscCall(ISGetIndices(subvertexIS, &subVertices)); 31609566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(subpointMap, 2, &subcellIS)); 31619566063dSJacob Faibussowitsch if (subcellIS) PetscCall(ISGetIndices(subcellIS, &subCells)); 316248a46eb9SPierre Jolivet for (c = 0; c < numSubCells; ++c) PetscCall(DMPlexSetConeSize(subdm, c, 1)); 316348a46eb9SPierre Jolivet for (f = firstSubFace; f < firstSubFace + numSubFaces; ++f) PetscCall(DMPlexSetConeSize(subdm, f, nFV)); 31649566063dSJacob Faibussowitsch PetscCall(DMSetUp(subdm)); 3165d24a712aSStefano Zampini PetscCall(DMLabelDestroy(&subpointMap)); 3166e6ccafaeSMatthew G Knepley /* Create face cones */ 31679566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 31689566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, NULL)); 31699566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(subdm, maxConeSize, MPIU_INT, (void **)&subface)); 3170e6ccafaeSMatthew G Knepley for (c = 0; c < numSubCells; ++c) { 3171e6ccafaeSMatthew G Knepley const PetscInt cell = subCells[c]; 3172efa14ee0SMatthew G Knepley const PetscInt subcell = c; 31730298fd71SBarry Smith PetscInt *closure = NULL; 3174efa14ee0SMatthew G Knepley PetscInt closureSize, cl, numCorners = 0, faceSize = 0; 3175e6ccafaeSMatthew G Knepley 31769566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure)); 3177efa14ee0SMatthew G Knepley for (cl = 0; cl < closureSize * 2; cl += 2) { 3178efa14ee0SMatthew G Knepley const PetscInt point = closure[cl]; 3179e6ccafaeSMatthew G Knepley PetscInt subVertex; 3180e6ccafaeSMatthew G Knepley 3181efa14ee0SMatthew G Knepley if ((point >= vStart) && (point < vEnd)) { 3182efa14ee0SMatthew G Knepley ++numCorners; 31839566063dSJacob Faibussowitsch PetscCall(PetscFindInt(point, numSubVertices, subVertices, &subVertex)); 3184efa14ee0SMatthew G Knepley if (subVertex >= 0) { 3185efa14ee0SMatthew G Knepley closure[faceSize] = point; 318665560c7fSMatthew G Knepley subface[faceSize] = firstSubVertex + subVertex; 3187e6ccafaeSMatthew G Knepley ++faceSize; 3188e6ccafaeSMatthew G Knepley } 3189e6ccafaeSMatthew G Knepley } 3190e6ccafaeSMatthew G Knepley } 319163a3b9bcSJacob Faibussowitsch PetscCheck(faceSize <= nFV, comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %" PetscInt_FMT " of an element on the surface", faceSize); 319248a46eb9SPierre Jolivet if (faceSize == nFV) PetscCall(DMPlexInsertFace_Internal(dm, subdm, faceSize, closure, subface, numCorners, cell, subcell, firstSubFace, &newFacePoint)); 31939566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure)); 3194e6ccafaeSMatthew G Knepley } 31959566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(subdm, maxConeSize, MPIU_INT, (void **)&subface)); 31969566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(subdm)); 31979566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(subdm)); 3198e6ccafaeSMatthew G Knepley /* Build coordinates */ 3199efa14ee0SMatthew G Knepley { 3200efa14ee0SMatthew G Knepley PetscSection coordSection, subCoordSection; 3201efa14ee0SMatthew G Knepley Vec coordinates, subCoordinates; 3202efa14ee0SMatthew G Knepley PetscScalar *coords, *subCoords; 3203285d324eSMatthew G. Knepley PetscInt numComp, coordSize, v; 320424640c55SToby Isaac const char *name; 3205efa14ee0SMatthew G Knepley 32069566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 32079566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 32089566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(subdm, &subCoordSection)); 32099566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(subCoordSection, 1)); 32109566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &numComp)); 32119566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(subCoordSection, 0, numComp)); 32129566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex + numSubVertices)); 3213efa14ee0SMatthew G Knepley for (v = 0; v < numSubVertices; ++v) { 3214efa14ee0SMatthew G Knepley const PetscInt vertex = subVertices[v]; 3215efa14ee0SMatthew G Knepley const PetscInt subvertex = firstSubVertex + v; 3216efa14ee0SMatthew G Knepley PetscInt dof; 3217efa14ee0SMatthew G Knepley 32189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, vertex, &dof)); 32199566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(subCoordSection, subvertex, dof)); 32209566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(subCoordSection, subvertex, 0, dof)); 3221e6ccafaeSMatthew G Knepley } 32229566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(subCoordSection)); 32239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(subCoordSection, &coordSize)); 32249566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &subCoordinates)); 32259566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)coordinates, &name)); 32269566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)subCoordinates, name)); 32279566063dSJacob Faibussowitsch PetscCall(VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE)); 32289566063dSJacob Faibussowitsch PetscCall(VecSetType(subCoordinates, VECSTANDARD)); 3229830e53efSMatthew G. Knepley if (coordSize) { 32309566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 32319566063dSJacob Faibussowitsch PetscCall(VecGetArray(subCoordinates, &subCoords)); 3232efa14ee0SMatthew G Knepley for (v = 0; v < numSubVertices; ++v) { 3233efa14ee0SMatthew G Knepley const PetscInt vertex = subVertices[v]; 3234efa14ee0SMatthew G Knepley const PetscInt subvertex = firstSubVertex + v; 3235efa14ee0SMatthew G Knepley PetscInt dof, off, sdof, soff, d; 3236e6ccafaeSMatthew G Knepley 32379566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, vertex, &dof)); 32389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, vertex, &off)); 32399566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subCoordSection, subvertex, &sdof)); 32409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(subCoordSection, subvertex, &soff)); 324163a3b9bcSJacob 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); 3242e6ccafaeSMatthew G Knepley for (d = 0; d < dof; ++d) subCoords[soff + d] = coords[off + d]; 3243e6ccafaeSMatthew G Knepley } 32449566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 32459566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(subCoordinates, &subCoords)); 32463b399e24SMatthew G. Knepley } 32479566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(subdm, subCoordinates)); 32489566063dSJacob Faibussowitsch PetscCall(VecDestroy(&subCoordinates)); 3249e6ccafaeSMatthew G Knepley } 3250efa14ee0SMatthew G Knepley /* Cleanup */ 32519566063dSJacob Faibussowitsch if (subvertexIS) PetscCall(ISRestoreIndices(subvertexIS, &subVertices)); 32529566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subvertexIS)); 32539566063dSJacob Faibussowitsch if (subcellIS) PetscCall(ISRestoreIndices(subcellIS, &subCells)); 32549566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subcellIS)); 32553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3256e6ccafaeSMatthew G Knepley } 3257e6ccafaeSMatthew G Knepley 3258d5b43468SJose E. Roman /* TODO: Fix this to properly propagate up error conditions it may find */ 3259d71ae5a4SJacob Faibussowitsch static inline PetscInt DMPlexFilterPoint_Internal(PetscInt point, PetscInt firstSubPoint, PetscInt numSubPoints, const PetscInt subPoints[]) 3260d71ae5a4SJacob Faibussowitsch { 32613982b651SMatthew G. Knepley PetscInt subPoint; 32623982b651SMatthew G. Knepley PetscErrorCode ierr; 32633982b651SMatthew G. Knepley 32649371c9d4SSatish Balay ierr = PetscFindInt(point, numSubPoints, subPoints, &subPoint); 32659371c9d4SSatish Balay if (ierr) return -1; 32663982b651SMatthew G. Knepley return subPoint < 0 ? subPoint : firstSubPoint + subPoint; 32673982b651SMatthew G. Knepley } 32683982b651SMatthew G. Knepley 3269d5b43468SJose E. Roman /* TODO: Fix this to properly propagate up error conditions it may find */ 3270d71ae5a4SJacob Faibussowitsch static inline PetscInt DMPlexFilterPointPerm_Internal(PetscInt point, PetscInt firstSubPoint, PetscInt numSubPoints, const PetscInt subPoints[], const PetscInt subIndices[]) 3271d71ae5a4SJacob Faibussowitsch { 3272dd05d810SMatthew G. Knepley PetscInt subPoint; 3273dd05d810SMatthew G. Knepley PetscErrorCode ierr; 3274dd05d810SMatthew G. Knepley 3275dd05d810SMatthew G. Knepley ierr = PetscFindInt(point, numSubPoints, subPoints, &subPoint); 3276dd05d810SMatthew G. Knepley if (ierr) return -1; 3277dd05d810SMatthew G. Knepley return subPoint < 0 ? subPoint : firstSubPoint + (subIndices ? subIndices[subPoint] : subPoint); 3278dd05d810SMatthew G. Knepley } 3279dd05d810SMatthew G. Knepley 3280d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexFilterLabels_Internal(DM dm, const PetscInt numSubPoints[], const PetscInt *subpoints[], const PetscInt firstSubPoint[], DM subdm) 3281d71ae5a4SJacob Faibussowitsch { 3282695799ffSMatthew G. Knepley DMLabel depthLabel; 3283212103e5SMatthew Knepley PetscInt Nl, l, d; 3284212103e5SMatthew Knepley 3285212103e5SMatthew Knepley PetscFunctionBegin; 3286695799ffSMatthew G. Knepley // Reset depth label for fast lookup 3287695799ffSMatthew G. Knepley PetscCall(DMPlexGetDepthLabel(dm, &depthLabel)); 3288695799ffSMatthew G. Knepley PetscCall(DMLabelMakeAllInvalid_Internal(depthLabel)); 32899566063dSJacob Faibussowitsch PetscCall(DMGetNumLabels(dm, &Nl)); 3290212103e5SMatthew Knepley for (l = 0; l < Nl; ++l) { 3291212103e5SMatthew Knepley DMLabel label, newlabel; 3292212103e5SMatthew Knepley const char *lname; 3293d56405f8SMatthew G. Knepley PetscBool isDepth, isDim, isCelltype, isVTK; 3294212103e5SMatthew Knepley IS valueIS; 3295212103e5SMatthew Knepley const PetscInt *values; 3296212103e5SMatthew Knepley PetscInt Nv, v; 3297212103e5SMatthew Knepley 32989566063dSJacob Faibussowitsch PetscCall(DMGetLabelName(dm, l, &lname)); 32999566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(lname, "depth", &isDepth)); 33009566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(lname, "dim", &isDim)); 33019566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(lname, "celltype", &isCelltype)); 33029566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(lname, "vtk", &isVTK)); 3303d56405f8SMatthew G. Knepley if (isDepth || isDim || isCelltype || isVTK) continue; 33049566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(subdm, lname)); 33059566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, lname, &label)); 33069566063dSJacob Faibussowitsch PetscCall(DMGetLabel(subdm, lname, &newlabel)); 33079566063dSJacob Faibussowitsch PetscCall(DMLabelGetDefaultValue(label, &v)); 33089566063dSJacob Faibussowitsch PetscCall(DMLabelSetDefaultValue(newlabel, v)); 33099566063dSJacob Faibussowitsch PetscCall(DMLabelGetValueIS(label, &valueIS)); 33109566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(valueIS, &Nv)); 33119566063dSJacob Faibussowitsch PetscCall(ISGetIndices(valueIS, &values)); 3312212103e5SMatthew Knepley for (v = 0; v < Nv; ++v) { 3313212103e5SMatthew Knepley IS pointIS; 3314212103e5SMatthew Knepley const PetscInt *points; 3315212103e5SMatthew Knepley PetscInt Np, p; 3316212103e5SMatthew Knepley 33179566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, values[v], &pointIS)); 33189566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &Np)); 33199566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 3320212103e5SMatthew Knepley for (p = 0; p < Np; ++p) { 3321212103e5SMatthew Knepley const PetscInt point = points[p]; 3322212103e5SMatthew Knepley PetscInt subp; 3323212103e5SMatthew Knepley 33249566063dSJacob Faibussowitsch PetscCall(DMPlexGetPointDepth(dm, point, &d)); 3325212103e5SMatthew Knepley subp = DMPlexFilterPoint_Internal(point, firstSubPoint[d], numSubPoints[d], subpoints[d]); 33269566063dSJacob Faibussowitsch if (subp >= 0) PetscCall(DMLabelSetValue(newlabel, subp, values[v])); 3327212103e5SMatthew Knepley } 33289566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(pointIS, &points)); 33299566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 3330212103e5SMatthew Knepley } 33319566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(valueIS, &values)); 33329566063dSJacob Faibussowitsch PetscCall(ISDestroy(&valueIS)); 3333212103e5SMatthew Knepley } 33343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3335212103e5SMatthew Knepley } 3336212103e5SMatthew Knepley 3337d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSubmeshGeneric_Interpolated(DM dm, DMLabel label, PetscInt value, PetscBool markedFaces, PetscBool isCohesive, PetscInt cellHeight, DM subdm) 3338d71ae5a4SJacob Faibussowitsch { 333982f516ccSBarry Smith MPI_Comm comm; 334053156dfcSMatthew G. Knepley DMLabel subpointMap; 3341efa14ee0SMatthew G Knepley IS *subpointIS; 3342efa14ee0SMatthew G Knepley const PetscInt **subpoints; 33433982b651SMatthew G. Knepley PetscInt *numSubPoints, *firstSubPoint, *coneNew, *orntNew; 3344dd05d810SMatthew G. Knepley PetscInt totSubPoints = 0, maxConeSize, dim, sdim, cdim, p, d, v; 33450d366550SMatthew G. Knepley PetscMPIInt rank; 3346e6ccafaeSMatthew G Knepley 3347e6ccafaeSMatthew G Knepley PetscFunctionBegin; 33489566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 33499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 3350efa14ee0SMatthew G Knepley /* Create subpointMap which marks the submesh */ 33519566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "subpoint_map", &subpointMap)); 33529566063dSJacob Faibussowitsch PetscCall(DMPlexSetSubpointMap(subdm, subpointMap)); 3353bec263e5SMatthew G. Knepley if (cellHeight) { 33549566063dSJacob Faibussowitsch if (isCohesive) PetscCall(DMPlexMarkCohesiveSubmesh_Interpolated(dm, label, value, subpointMap, subdm)); 33559566063dSJacob Faibussowitsch else PetscCall(DMPlexMarkSubmesh_Interpolated(dm, label, value, markedFaces, subpointMap, subdm)); 3356bec263e5SMatthew G. Knepley } else { 3357bec263e5SMatthew G. Knepley DMLabel depth; 3358bec263e5SMatthew G. Knepley IS pointIS; 3359bec263e5SMatthew G. Knepley const PetscInt *points; 3360b85c8bf9SMatthew G. Knepley PetscInt numPoints = 0; 3361bec263e5SMatthew G. Knepley 33629566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthLabel(dm, &depth)); 33639566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(label, value, &pointIS)); 3364b85c8bf9SMatthew G. Knepley if (pointIS) { 33659566063dSJacob Faibussowitsch PetscCall(ISGetIndices(pointIS, &points)); 33669566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(pointIS, &numPoints)); 3367b85c8bf9SMatthew G. Knepley } 3368bec263e5SMatthew G. Knepley for (p = 0; p < numPoints; ++p) { 3369bec263e5SMatthew G. Knepley PetscInt *closure = NULL; 3370bec263e5SMatthew G. Knepley PetscInt closureSize, c, pdim; 3371bec263e5SMatthew G. Knepley 33729566063dSJacob Faibussowitsch PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure)); 3373bec263e5SMatthew G. Knepley for (c = 0; c < closureSize * 2; c += 2) { 33749566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(depth, closure[c], &pdim)); 33759566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(subpointMap, closure[c], pdim)); 3376bec263e5SMatthew G. Knepley } 33779566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure)); 3378bec263e5SMatthew G. Knepley } 33799566063dSJacob Faibussowitsch if (pointIS) PetscCall(ISRestoreIndices(pointIS, &points)); 33809566063dSJacob Faibussowitsch PetscCall(ISDestroy(&pointIS)); 3381bec263e5SMatthew G. Knepley } 3382efa14ee0SMatthew G Knepley /* Setup chart */ 33839566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 3384dd05d810SMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim)); 33859566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(dim + 1, &numSubPoints, dim + 1, &firstSubPoint, dim + 1, &subpointIS, dim + 1, &subpoints)); 3386e6ccafaeSMatthew G Knepley for (d = 0; d <= dim; ++d) { 33879566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(subpointMap, d, &numSubPoints[d])); 3388e6ccafaeSMatthew G Knepley totSubPoints += numSubPoints[d]; 3389e6ccafaeSMatthew G Knepley } 3390dd05d810SMatthew G. Knepley // Determine submesh dimension 3391dd05d810SMatthew G. Knepley PetscCall(DMGetDimension(subdm, &sdim)); 3392dd05d810SMatthew G. Knepley if (sdim > 0) { 3393dd05d810SMatthew G. Knepley // Calling function knows what dimension to use, and we include neighboring cells as well 3394dd05d810SMatthew G. Knepley sdim = dim; 3395dd05d810SMatthew G. Knepley } else { 3396dd05d810SMatthew G. Knepley // We reset the subdimension based on what is being selected 3397dd05d810SMatthew G. Knepley PetscInt lsdim; 3398dd05d810SMatthew G. Knepley for (lsdim = dim; lsdim >= 0; --lsdim) 3399dd05d810SMatthew G. Knepley if (numSubPoints[lsdim]) break; 3400a5a714f4SStefano Zampini PetscCall(MPIU_Allreduce(&lsdim, &sdim, 1, MPIU_INT, MPI_MAX, comm)); 3401dd05d810SMatthew G. Knepley PetscCall(DMSetDimension(subdm, sdim)); 3402dd05d810SMatthew G. Knepley PetscCall(DMSetCoordinateDim(subdm, cdim)); 3403dd05d810SMatthew G. Knepley } 34049566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(subdm, 0, totSubPoints)); 34059566063dSJacob Faibussowitsch PetscCall(DMPlexSetVTKCellHeight(subdm, cellHeight)); 3406e6ccafaeSMatthew G Knepley /* Set cone sizes */ 3407dd05d810SMatthew G. Knepley firstSubPoint[sdim] = 0; 3408dd05d810SMatthew G. Knepley firstSubPoint[0] = firstSubPoint[sdim] + numSubPoints[sdim]; 3409dd05d810SMatthew G. Knepley if (sdim > 1) firstSubPoint[sdim - 1] = firstSubPoint[0] + numSubPoints[0]; 3410dd05d810SMatthew G. Knepley if (sdim > 2) firstSubPoint[sdim - 2] = firstSubPoint[sdim - 1] + numSubPoints[sdim - 1]; 3411dd05d810SMatthew G. Knepley for (d = 0; d <= sdim; ++d) { 34129566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(subpointMap, d, &subpointIS[d])); 34139566063dSJacob Faibussowitsch if (subpointIS[d]) PetscCall(ISGetIndices(subpointIS[d], &subpoints[d])); 3414e6ccafaeSMatthew G Knepley } 3415412e9a14SMatthew G. Knepley /* We do not want this label automatically computed, instead we compute it here */ 34169566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(subdm, "celltype")); 3417dd05d810SMatthew G. Knepley for (d = 0; d <= sdim; ++d) { 3418e6ccafaeSMatthew G Knepley for (p = 0; p < numSubPoints[d]; ++p) { 3419e6ccafaeSMatthew G Knepley const PetscInt point = subpoints[d][p]; 3420e6ccafaeSMatthew G Knepley const PetscInt subpoint = firstSubPoint[d] + p; 3421e6ccafaeSMatthew G Knepley const PetscInt *cone; 342215100a53SVaclav Hapla PetscInt coneSize; 3423e6ccafaeSMatthew G Knepley 34249566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 3425dd05d810SMatthew G. Knepley if (cellHeight && (d == sdim)) { 342615100a53SVaclav Hapla PetscInt coneSizeNew, c, val; 342715100a53SVaclav Hapla 34289566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 3429e6ccafaeSMatthew G Knepley for (c = 0, coneSizeNew = 0; c < coneSize; ++c) { 34309566063dSJacob Faibussowitsch PetscCall(DMLabelGetValue(subpointMap, cone[c], &val)); 3431e6ccafaeSMatthew G Knepley if (val >= 0) coneSizeNew++; 3432e6ccafaeSMatthew G Knepley } 34339566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(subdm, subpoint, coneSizeNew)); 34349566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(subdm, subpoint, DM_POLYTOPE_FV_GHOST)); 343515100a53SVaclav Hapla } else { 343615100a53SVaclav Hapla DMPolytopeType ct; 343715100a53SVaclav Hapla 343815100a53SVaclav Hapla PetscCall(DMPlexSetConeSize(subdm, subpoint, coneSize)); 343915100a53SVaclav Hapla PetscCall(DMPlexGetCellType(dm, point, &ct)); 344015100a53SVaclav Hapla PetscCall(DMPlexSetCellType(subdm, subpoint, ct)); 3441e6ccafaeSMatthew G Knepley } 3442e6ccafaeSMatthew G Knepley } 3443e6ccafaeSMatthew G Knepley } 34449566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&subpointMap)); 34459566063dSJacob Faibussowitsch PetscCall(DMSetUp(subdm)); 3446e6ccafaeSMatthew G Knepley /* Set cones */ 34479566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, NULL)); 34489566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(maxConeSize, &coneNew, maxConeSize, &orntNew)); 3449dd05d810SMatthew G. Knepley for (d = 0; d <= sdim; ++d) { 3450e6ccafaeSMatthew G Knepley for (p = 0; p < numSubPoints[d]; ++p) { 3451e6ccafaeSMatthew G Knepley const PetscInt point = subpoints[d][p]; 3452e6ccafaeSMatthew G Knepley const PetscInt subpoint = firstSubPoint[d] + p; 34530e49e2e2SMatthew G. Knepley const PetscInt *cone, *ornt; 34540d366550SMatthew G. Knepley PetscInt coneSize, subconeSize, coneSizeNew, c, subc, fornt = 0; 3455e6ccafaeSMatthew G Knepley 3456dd05d810SMatthew G. Knepley if (d == sdim - 1) { 34570d366550SMatthew G. Knepley const PetscInt *support, *cone, *ornt; 34580d366550SMatthew G. Knepley PetscInt supportSize, coneSize, s, subc; 34590d366550SMatthew G. Knepley 34609566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupport(dm, point, &support)); 34619566063dSJacob Faibussowitsch PetscCall(DMPlexGetSupportSize(dm, point, &supportSize)); 34620d366550SMatthew G. Knepley for (s = 0; s < supportSize; ++s) { 3463064cae4fSPierre Jolivet PetscBool isHybrid = PETSC_FALSE; 3464412e9a14SMatthew G. Knepley 34659566063dSJacob Faibussowitsch PetscCall(DMPlexCellIsHybrid_Internal(dm, support[s], &isHybrid)); 3466412e9a14SMatthew G. Knepley if (!isHybrid) continue; 34679566063dSJacob Faibussowitsch PetscCall(PetscFindInt(support[s], numSubPoints[d + 1], subpoints[d + 1], &subc)); 34680d366550SMatthew G. Knepley if (subc >= 0) { 34690d366550SMatthew G. Knepley const PetscInt ccell = subpoints[d + 1][subc]; 34700d366550SMatthew G. Knepley 34719566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, ccell, &cone)); 34729566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, ccell, &coneSize)); 34739566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, ccell, &ornt)); 34740d366550SMatthew G. Knepley for (c = 0; c < coneSize; ++c) { 34750d366550SMatthew G. Knepley if (cone[c] == point) { 34760d366550SMatthew G. Knepley fornt = ornt[c]; 34770d366550SMatthew G. Knepley break; 34780d366550SMatthew G. Knepley } 34790d366550SMatthew G. Knepley } 34800d366550SMatthew G. Knepley break; 34810d366550SMatthew G. Knepley } 34820d366550SMatthew G. Knepley } 34830d366550SMatthew G. Knepley } 34849566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(dm, point, &coneSize)); 34859566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeSize(subdm, subpoint, &subconeSize)); 34869566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, point, &cone)); 34879566063dSJacob Faibussowitsch PetscCall(DMPlexGetConeOrientation(dm, point, &ornt)); 3488e6ccafaeSMatthew G Knepley for (c = 0, coneSizeNew = 0; c < coneSize; ++c) { 34899566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[c], numSubPoints[d - 1], subpoints[d - 1], &subc)); 349001a2673eSMatthew G. Knepley if (subc >= 0) { 349101a2673eSMatthew G. Knepley coneNew[coneSizeNew] = firstSubPoint[d - 1] + subc; 34923982b651SMatthew G. Knepley orntNew[coneSizeNew] = ornt[c]; 349301a2673eSMatthew G. Knepley ++coneSizeNew; 349401a2673eSMatthew G. Knepley } 3495e6ccafaeSMatthew G Knepley } 349663a3b9bcSJacob Faibussowitsch PetscCheck(coneSizeNew == subconeSize, comm, PETSC_ERR_PLIB, "Number of cone points located %" PetscInt_FMT " does not match subcone size %" PetscInt_FMT, coneSizeNew, subconeSize); 34979566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(subdm, subpoint, coneNew)); 34989566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(subdm, subpoint, orntNew)); 34999566063dSJacob Faibussowitsch if (fornt < 0) PetscCall(DMPlexOrientPoint(subdm, subpoint, fornt)); 3500e6ccafaeSMatthew G Knepley } 3501e6ccafaeSMatthew G Knepley } 35029566063dSJacob Faibussowitsch PetscCall(PetscFree2(coneNew, orntNew)); 35039566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(subdm)); 35049566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(subdm)); 3505e6ccafaeSMatthew G Knepley /* Build coordinates */ 3506e6ccafaeSMatthew G Knepley { 3507e6ccafaeSMatthew G Knepley PetscSection coordSection, subCoordSection; 3508e6ccafaeSMatthew G Knepley Vec coordinates, subCoordinates; 3509e6ccafaeSMatthew G Knepley PetscScalar *coords, *subCoords; 3510c0e8cf5fSMatthew G. Knepley PetscInt cdim, numComp, coordSize; 351124640c55SToby Isaac const char *name; 3512e6ccafaeSMatthew G Knepley 35139566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 35149566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 35159566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 35169566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(subdm, &subCoordSection)); 35179566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(subCoordSection, 1)); 35189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &numComp)); 35199566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(subCoordSection, 0, numComp)); 35209566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(subCoordSection, firstSubPoint[0], firstSubPoint[0] + numSubPoints[0])); 3521e6ccafaeSMatthew G Knepley for (v = 0; v < numSubPoints[0]; ++v) { 3522e6ccafaeSMatthew G Knepley const PetscInt vertex = subpoints[0][v]; 3523e6ccafaeSMatthew G Knepley const PetscInt subvertex = firstSubPoint[0] + v; 3524e6ccafaeSMatthew G Knepley PetscInt dof; 3525e6ccafaeSMatthew G Knepley 35269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, vertex, &dof)); 35279566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(subCoordSection, subvertex, dof)); 35289566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(subCoordSection, subvertex, 0, dof)); 3529e6ccafaeSMatthew G Knepley } 35309566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(subCoordSection)); 35319566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(subCoordSection, &coordSize)); 35329566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &subCoordinates)); 35339566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)coordinates, &name)); 35349566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)subCoordinates, name)); 35359566063dSJacob Faibussowitsch PetscCall(VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE)); 35369566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(subCoordinates, cdim)); 35379566063dSJacob Faibussowitsch PetscCall(VecSetType(subCoordinates, VECSTANDARD)); 35389566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 35399566063dSJacob Faibussowitsch PetscCall(VecGetArray(subCoordinates, &subCoords)); 3540e6ccafaeSMatthew G Knepley for (v = 0; v < numSubPoints[0]; ++v) { 3541e6ccafaeSMatthew G Knepley const PetscInt vertex = subpoints[0][v]; 3542e6ccafaeSMatthew G Knepley const PetscInt subvertex = firstSubPoint[0] + v; 3543e6ccafaeSMatthew G Knepley PetscInt dof, off, sdof, soff, d; 3544e6ccafaeSMatthew G Knepley 35459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, vertex, &dof)); 35469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, vertex, &off)); 35479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subCoordSection, subvertex, &sdof)); 35489566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(subCoordSection, subvertex, &soff)); 354963a3b9bcSJacob 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); 3550efa14ee0SMatthew G Knepley for (d = 0; d < dof; ++d) subCoords[soff + d] = coords[off + d]; 3551e6ccafaeSMatthew G Knepley } 35529566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 35539566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(subCoordinates, &subCoords)); 35549566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(subdm, subCoordinates)); 35559566063dSJacob Faibussowitsch PetscCall(VecDestroy(&subCoordinates)); 3556e6ccafaeSMatthew G Knepley } 35573982b651SMatthew G. Knepley /* Build SF: We need this complexity because subpoints might not be selected on the owning process */ 35583982b651SMatthew G. Knepley { 35593982b651SMatthew G. Knepley PetscSF sfPoint, sfPointSub; 35603982b651SMatthew G. Knepley IS subpIS; 35613982b651SMatthew G. Knepley const PetscSFNode *remotePoints; 35625033f954SMatthew G. Knepley PetscSFNode *sremotePoints = NULL, *newLocalPoints = NULL, *newOwners = NULL; 35635033f954SMatthew G. Knepley const PetscInt *localPoints, *subpoints, *rootdegree; 3564dd05d810SMatthew G. Knepley PetscInt *slocalPoints = NULL, *sortedPoints = NULL, *sortedIndices = NULL; 35655033f954SMatthew G. Knepley PetscInt numRoots, numLeaves, numSubpoints = 0, numSubroots, numSubleaves = 0, l, sl = 0, ll = 0, pStart, pEnd, p; 35665033f954SMatthew G. Knepley PetscMPIInt rank, size; 35673982b651SMatthew G. Knepley 35689566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 35695033f954SMatthew G. Knepley PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 35709566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 35719566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(subdm, &sfPointSub)); 35729566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 35739566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(subdm, NULL, &numSubroots)); 35749566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(subdm, &subpIS)); 35753982b651SMatthew G. Knepley if (subpIS) { 3576dd05d810SMatthew G. Knepley PetscBool sorted = PETSC_TRUE; 3577dd05d810SMatthew G. Knepley 35789566063dSJacob Faibussowitsch PetscCall(ISGetIndices(subpIS, &subpoints)); 35799566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(subpIS, &numSubpoints)); 3580dd05d810SMatthew G. Knepley for (p = 1; p < numSubpoints; ++p) sorted = sorted && (subpoints[p] >= subpoints[p - 1]) ? PETSC_TRUE : PETSC_FALSE; 3581dd05d810SMatthew G. Knepley if (!sorted) { 3582dd05d810SMatthew G. Knepley PetscCall(PetscMalloc2(numSubpoints, &sortedPoints, numSubpoints, &sortedIndices)); 3583dd05d810SMatthew G. Knepley for (p = 0; p < numSubpoints; ++p) sortedIndices[p] = p; 3584dd05d810SMatthew G. Knepley PetscCall(PetscArraycpy(sortedPoints, subpoints, numSubpoints)); 3585dd05d810SMatthew G. Knepley PetscCall(PetscSortIntWithArray(numSubpoints, sortedPoints, sortedIndices)); 3586dd05d810SMatthew G. Knepley } 35873982b651SMatthew G. Knepley } 35889566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints)); 35893982b651SMatthew G. Knepley if (numRoots >= 0) { 35905033f954SMatthew G. Knepley PetscCall(PetscSFComputeDegreeBegin(sfPoint, &rootdegree)); 35915033f954SMatthew G. Knepley PetscCall(PetscSFComputeDegreeEnd(sfPoint, &rootdegree)); 35929566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEnd - pStart, &newLocalPoints, numRoots, &newOwners)); 35933982b651SMatthew G. Knepley for (p = 0; p < pEnd - pStart; ++p) { 35943982b651SMatthew G. Knepley newLocalPoints[p].rank = -2; 35953982b651SMatthew G. Knepley newLocalPoints[p].index = -2; 35963982b651SMatthew G. Knepley } 35973982b651SMatthew G. Knepley /* Set subleaves */ 35983982b651SMatthew G. Knepley for (l = 0; l < numLeaves; ++l) { 35993982b651SMatthew G. Knepley const PetscInt point = localPoints[l]; 3600dd05d810SMatthew G. Knepley const PetscInt subpoint = DMPlexFilterPointPerm_Internal(point, 0, numSubpoints, sortedPoints ? sortedPoints : subpoints, sortedIndices); 36013982b651SMatthew G. Knepley 36023982b651SMatthew G. Knepley if (subpoint < 0) continue; 36033982b651SMatthew G. Knepley newLocalPoints[point - pStart].rank = rank; 36043982b651SMatthew G. Knepley newLocalPoints[point - pStart].index = subpoint; 36053982b651SMatthew G. Knepley ++numSubleaves; 36063982b651SMatthew G. Knepley } 36073982b651SMatthew G. Knepley /* Must put in owned subpoints */ 36083982b651SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 36093982b651SMatthew G. Knepley newOwners[p - pStart].rank = -3; 36103982b651SMatthew G. Knepley newOwners[p - pStart].index = -3; 36113982b651SMatthew G. Knepley } 3612d9384f27SMatthew G. Knepley for (p = 0; p < numSubpoints; ++p) { 36135033f954SMatthew G. Knepley /* Hold on to currently owned points */ 36145033f954SMatthew G. Knepley if (rootdegree[subpoints[p] - pStart]) newOwners[subpoints[p] - pStart].rank = rank + size; 36155033f954SMatthew G. Knepley else newOwners[subpoints[p] - pStart].rank = rank; 3616d9384f27SMatthew G. Knepley newOwners[subpoints[p] - pStart].index = p; 36173982b651SMatthew G. Knepley } 36189566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(sfPoint, MPIU_2INT, newLocalPoints, newOwners, MPI_MAXLOC)); 36199566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(sfPoint, MPIU_2INT, newLocalPoints, newOwners, MPI_MAXLOC)); 36209371c9d4SSatish Balay for (p = pStart; p < pEnd; ++p) 36219371c9d4SSatish Balay if (newOwners[p - pStart].rank >= size) newOwners[p - pStart].rank -= size; 36229566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfPoint, MPIU_2INT, newOwners, newLocalPoints, MPI_REPLACE)); 36239566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfPoint, MPIU_2INT, newOwners, newLocalPoints, MPI_REPLACE)); 36249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numSubleaves, &slocalPoints)); 36259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numSubleaves, &sremotePoints)); 36265033f954SMatthew G. Knepley for (l = 0; l < numLeaves; ++l) { 36273982b651SMatthew G. Knepley const PetscInt point = localPoints[l]; 3628dd05d810SMatthew G. Knepley const PetscInt subpoint = DMPlexFilterPointPerm_Internal(point, 0, numSubpoints, sortedPoints ? sortedPoints : subpoints, sortedIndices); 36293982b651SMatthew G. Knepley 36303982b651SMatthew G. Knepley if (subpoint < 0) continue; 36319371c9d4SSatish Balay if (newLocalPoints[point].rank == rank) { 36329371c9d4SSatish Balay ++ll; 36339371c9d4SSatish Balay continue; 36349371c9d4SSatish Balay } 36353982b651SMatthew G. Knepley slocalPoints[sl] = subpoint; 36363982b651SMatthew G. Knepley sremotePoints[sl].rank = newLocalPoints[point].rank; 36373982b651SMatthew G. Knepley sremotePoints[sl].index = newLocalPoints[point].index; 363863a3b9bcSJacob Faibussowitsch PetscCheck(sremotePoints[sl].rank >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid remote rank for local point %" PetscInt_FMT, point); 363963a3b9bcSJacob Faibussowitsch PetscCheck(sremotePoints[sl].index >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid remote subpoint for local point %" PetscInt_FMT, point); 36403982b651SMatthew G. Knepley ++sl; 36413982b651SMatthew G. Knepley } 36421dca8a05SBarry 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); 36439566063dSJacob Faibussowitsch PetscCall(PetscFree2(newLocalPoints, newOwners)); 36449566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sfPointSub, numSubroots, sl, slocalPoints, PETSC_OWN_POINTER, sremotePoints, PETSC_OWN_POINTER)); 36453982b651SMatthew G. Knepley } 364648a46eb9SPierre Jolivet if (subpIS) PetscCall(ISRestoreIndices(subpIS, &subpoints)); 3647dd05d810SMatthew G. Knepley PetscCall(PetscFree2(sortedPoints, sortedIndices)); 36483982b651SMatthew G. Knepley } 3649212103e5SMatthew Knepley /* Filter labels */ 36509566063dSJacob Faibussowitsch PetscCall(DMPlexFilterLabels_Internal(dm, numSubPoints, subpoints, firstSubPoint, subdm)); 3651efa14ee0SMatthew G Knepley /* Cleanup */ 3652dd05d810SMatthew G. Knepley for (d = 0; d <= sdim; ++d) { 36539566063dSJacob Faibussowitsch if (subpointIS[d]) PetscCall(ISRestoreIndices(subpointIS[d], &subpoints[d])); 36549566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subpointIS[d])); 3655e6ccafaeSMatthew G Knepley } 36569566063dSJacob Faibussowitsch PetscCall(PetscFree4(numSubPoints, firstSubPoint, subpointIS, subpoints)); 36573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3658e6ccafaeSMatthew G Knepley } 3659e6ccafaeSMatthew G Knepley 3660d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSubmesh_Interpolated(DM dm, DMLabel vertexLabel, PetscInt value, PetscBool markedFaces, DM subdm) 3661d71ae5a4SJacob Faibussowitsch { 36623982b651SMatthew G. Knepley PetscFunctionBegin; 36639566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSubmeshGeneric_Interpolated(dm, vertexLabel, value, markedFaces, PETSC_FALSE, 1, subdm)); 36643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 36653982b651SMatthew G. Knepley } 36663982b651SMatthew G. Knepley 3667d0fa310fSMatthew G. Knepley /*@ 3668e6ccafaeSMatthew G Knepley DMPlexCreateSubmesh - Extract a hypersurface from the mesh using vertices defined by a label 3669e6ccafaeSMatthew G Knepley 3670e6ccafaeSMatthew G Knepley Input Parameters: 3671e6ccafaeSMatthew G Knepley + dm - The original mesh 367220f4b53cSBarry Smith . vertexLabel - The `DMLabel` marking points contained in the surface 3673158acfadSMatthew G. Knepley . value - The label value to use 367420f4b53cSBarry Smith - markedFaces - `PETSC_TRUE` if surface faces are marked in addition to vertices, `PETSC_FALSE` if only vertices are marked 3675e6ccafaeSMatthew G Knepley 3676e6ccafaeSMatthew G Knepley Output Parameter: 3677e6ccafaeSMatthew G Knepley . subdm - The surface mesh 3678e6ccafaeSMatthew G Knepley 3679e6ccafaeSMatthew G Knepley Level: developer 3680e6ccafaeSMatthew G Knepley 368120f4b53cSBarry Smith Note: 368220f4b53cSBarry Smith This function produces a `DMLabel` mapping original points in the submesh to their depth. This can be obtained using `DMPlexGetSubpointMap()`. 368320f4b53cSBarry Smith 36841cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSubpointMap()`, `DMGetLabel()`, `DMLabelSetValue()` 3685830e53efSMatthew G. Knepley @*/ 3686d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSubmesh(DM dm, DMLabel vertexLabel, PetscInt value, PetscBool markedFaces, DM *subdm) 3687d71ae5a4SJacob Faibussowitsch { 3688827c4036SVaclav Hapla DMPlexInterpolatedFlag interpolated; 3689827c4036SVaclav Hapla PetscInt dim, cdim; 3690e6ccafaeSMatthew G Knepley 3691e6ccafaeSMatthew G Knepley PetscFunctionBegin; 3692e6ccafaeSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36934f572ea9SToby Isaac PetscAssertPointer(subdm, 5); 36949566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 36959566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), subdm)); 36969566063dSJacob Faibussowitsch PetscCall(DMSetType(*subdm, DMPLEX)); 36979566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*subdm, dim - 1)); 36989566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 36999566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*subdm, cdim)); 37009566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated)); 370108401ef6SPierre Jolivet PetscCheck(interpolated != DMPLEX_INTERPOLATED_PARTIAL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes"); 3702827c4036SVaclav Hapla if (interpolated) { 37039566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSubmesh_Interpolated(dm, vertexLabel, value, markedFaces, *subdm)); 3704e6ccafaeSMatthew G Knepley } else { 37059566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSubmesh_Uninterpolated(dm, vertexLabel, value, *subdm)); 3706e6ccafaeSMatthew G Knepley } 37075de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, *subdm)); 37083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3709e6ccafaeSMatthew G Knepley } 3710e6ccafaeSMatthew G Knepley 3711d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCohesiveSubmesh_Uninterpolated(DM dm, PetscBool hasLagrange, const char label[], PetscInt value, DM subdm) 3712d71ae5a4SJacob Faibussowitsch { 3713766ab985SMatthew G. Knepley MPI_Comm comm; 3714766ab985SMatthew G. Knepley DMLabel subpointMap; 3715766ab985SMatthew G. Knepley IS subvertexIS; 3716766ab985SMatthew G. Knepley const PetscInt *subVertices; 3717fed694aaSMatthew G. Knepley PetscInt numSubVertices, firstSubVertex, numSubCells, *subCells = NULL; 3718766ab985SMatthew G. Knepley PetscInt *subface, maxConeSize, numSubFaces, firstSubFace, newFacePoint, nFV; 3719412e9a14SMatthew G. Knepley PetscInt c, f; 3720766ab985SMatthew G. Knepley 3721766ab985SMatthew G. Knepley PetscFunctionBegin; 37229566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 3723766ab985SMatthew G. Knepley /* Create subpointMap which marks the submesh */ 37249566063dSJacob Faibussowitsch PetscCall(DMLabelCreate(PETSC_COMM_SELF, "subpoint_map", &subpointMap)); 37259566063dSJacob Faibussowitsch PetscCall(DMPlexSetSubpointMap(subdm, subpointMap)); 37269566063dSJacob Faibussowitsch PetscCall(DMPlexMarkCohesiveSubmesh_Uninterpolated(dm, hasLagrange, label, value, subpointMap, &numSubFaces, &nFV, &subCells, subdm)); 3727766ab985SMatthew G. Knepley /* Setup chart */ 37289566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(subpointMap, 0, &numSubVertices)); 37299566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(subpointMap, 2, &numSubCells)); 37309566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(subdm, 0, numSubCells + numSubFaces + numSubVertices)); 37319566063dSJacob Faibussowitsch PetscCall(DMPlexSetVTKCellHeight(subdm, 1)); 3732766ab985SMatthew G. Knepley /* Set cone sizes */ 3733766ab985SMatthew G. Knepley firstSubVertex = numSubCells; 3734766ab985SMatthew G. Knepley firstSubFace = numSubCells + numSubVertices; 3735766ab985SMatthew G. Knepley newFacePoint = firstSubFace; 37369566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(subpointMap, 0, &subvertexIS)); 37379566063dSJacob Faibussowitsch if (subvertexIS) PetscCall(ISGetIndices(subvertexIS, &subVertices)); 373848a46eb9SPierre Jolivet for (c = 0; c < numSubCells; ++c) PetscCall(DMPlexSetConeSize(subdm, c, 1)); 373948a46eb9SPierre Jolivet for (f = firstSubFace; f < firstSubFace + numSubFaces; ++f) PetscCall(DMPlexSetConeSize(subdm, f, nFV)); 37409566063dSJacob Faibussowitsch PetscCall(DMSetUp(subdm)); 3741d24a712aSStefano Zampini PetscCall(DMLabelDestroy(&subpointMap)); 3742766ab985SMatthew G. Knepley /* Create face cones */ 37439566063dSJacob Faibussowitsch PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, NULL)); 37449566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(subdm, maxConeSize, MPIU_INT, (void **)&subface)); 3745766ab985SMatthew G. Knepley for (c = 0; c < numSubCells; ++c) { 3746766ab985SMatthew G. Knepley const PetscInt cell = subCells[c]; 3747766ab985SMatthew G. Knepley const PetscInt subcell = c; 374887feddfdSMatthew G. Knepley const PetscInt *cone, *cells; 3749064cae4fSPierre Jolivet PetscBool isHybrid = PETSC_FALSE; 375087feddfdSMatthew G. Knepley PetscInt numCells, subVertex, p, v; 3751766ab985SMatthew G. Knepley 37529566063dSJacob Faibussowitsch PetscCall(DMPlexCellIsHybrid_Internal(dm, cell, &isHybrid)); 3753412e9a14SMatthew G. Knepley if (!isHybrid) continue; 37549566063dSJacob Faibussowitsch PetscCall(DMPlexGetCone(dm, cell, &cone)); 375587feddfdSMatthew G. Knepley for (v = 0; v < nFV; ++v) { 37569566063dSJacob Faibussowitsch PetscCall(PetscFindInt(cone[v], numSubVertices, subVertices, &subVertex)); 375787feddfdSMatthew G. Knepley subface[v] = firstSubVertex + subVertex; 375887feddfdSMatthew G. Knepley } 37599566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(subdm, newFacePoint, subface)); 37609566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(subdm, subcell, &newFacePoint)); 37619566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, nFV, cone, &numCells, &cells)); 376227234c99SMatthew G. Knepley /* Not true in parallel 376308401ef6SPierre Jolivet PetscCheck(numCells == 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cohesive cells should separate two cells"); */ 376487feddfdSMatthew G. Knepley for (p = 0; p < numCells; ++p) { 376587feddfdSMatthew G. Knepley PetscInt negsubcell; 3766064cae4fSPierre Jolivet PetscBool isHybrid = PETSC_FALSE; 3767766ab985SMatthew G. Knepley 37689566063dSJacob Faibussowitsch PetscCall(DMPlexCellIsHybrid_Internal(dm, cells[p], &isHybrid)); 3769412e9a14SMatthew G. Knepley if (isHybrid) continue; 377087feddfdSMatthew G. Knepley /* I know this is a crap search */ 377187feddfdSMatthew G. Knepley for (negsubcell = 0; negsubcell < numSubCells; ++negsubcell) { 377287feddfdSMatthew G. Knepley if (subCells[negsubcell] == cells[p]) break; 3773766ab985SMatthew G. Knepley } 377463a3b9bcSJacob Faibussowitsch PetscCheck(negsubcell != numSubCells, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find negative face neighbor for cohesive cell %" PetscInt_FMT, cell); 37759566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(subdm, negsubcell, &newFacePoint)); 3776766ab985SMatthew G. Knepley } 37779566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, nFV, cone, &numCells, &cells)); 377887feddfdSMatthew G. Knepley ++newFacePoint; 3779766ab985SMatthew G. Knepley } 37809566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(subdm, maxConeSize, MPIU_INT, (void **)&subface)); 37819566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(subdm)); 37829566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(subdm)); 3783766ab985SMatthew G. Knepley /* Build coordinates */ 3784766ab985SMatthew G. Knepley { 3785766ab985SMatthew G. Knepley PetscSection coordSection, subCoordSection; 3786766ab985SMatthew G. Knepley Vec coordinates, subCoordinates; 3787766ab985SMatthew G. Knepley PetscScalar *coords, *subCoords; 3788c0e8cf5fSMatthew G. Knepley PetscInt cdim, numComp, coordSize, v; 378924640c55SToby Isaac const char *name; 3790766ab985SMatthew G. Knepley 37919566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 37929566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 37939566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 37949566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(subdm, &subCoordSection)); 37959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(subCoordSection, 1)); 37969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &numComp)); 37979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(subCoordSection, 0, numComp)); 37989566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex + numSubVertices)); 3799766ab985SMatthew G. Knepley for (v = 0; v < numSubVertices; ++v) { 3800766ab985SMatthew G. Knepley const PetscInt vertex = subVertices[v]; 3801766ab985SMatthew G. Knepley const PetscInt subvertex = firstSubVertex + v; 3802766ab985SMatthew G. Knepley PetscInt dof; 3803766ab985SMatthew G. Knepley 38049566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, vertex, &dof)); 38059566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(subCoordSection, subvertex, dof)); 38069566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(subCoordSection, subvertex, 0, dof)); 3807766ab985SMatthew G. Knepley } 38089566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(subCoordSection)); 38099566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(subCoordSection, &coordSize)); 38109566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &subCoordinates)); 38119566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)coordinates, &name)); 38129566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)subCoordinates, name)); 38139566063dSJacob Faibussowitsch PetscCall(VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE)); 38149566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(subCoordinates, cdim)); 38159566063dSJacob Faibussowitsch PetscCall(VecSetType(subCoordinates, VECSTANDARD)); 38169566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 38179566063dSJacob Faibussowitsch PetscCall(VecGetArray(subCoordinates, &subCoords)); 3818766ab985SMatthew G. Knepley for (v = 0; v < numSubVertices; ++v) { 3819766ab985SMatthew G. Knepley const PetscInt vertex = subVertices[v]; 3820766ab985SMatthew G. Knepley const PetscInt subvertex = firstSubVertex + v; 3821766ab985SMatthew G. Knepley PetscInt dof, off, sdof, soff, d; 3822766ab985SMatthew G. Knepley 38239566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(coordSection, vertex, &dof)); 38249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, vertex, &off)); 38259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetDof(subCoordSection, subvertex, &sdof)); 38269566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(subCoordSection, subvertex, &soff)); 382763a3b9bcSJacob 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); 3828766ab985SMatthew G. Knepley for (d = 0; d < dof; ++d) subCoords[soff + d] = coords[off + d]; 3829766ab985SMatthew G. Knepley } 38309566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 38319566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(subCoordinates, &subCoords)); 38329566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(subdm, subCoordinates)); 38339566063dSJacob Faibussowitsch PetscCall(VecDestroy(&subCoordinates)); 3834766ab985SMatthew G. Knepley } 3835aca35d17SMatthew G. Knepley /* Build SF */ 3836aca35d17SMatthew G. Knepley CHKMEMQ; 3837aca35d17SMatthew G. Knepley { 3838aca35d17SMatthew G. Knepley PetscSF sfPoint, sfPointSub; 3839aca35d17SMatthew G. Knepley const PetscSFNode *remotePoints; 3840bdcf2095SMatthew G. Knepley PetscSFNode *sremotePoints, *newLocalPoints, *newOwners; 3841aca35d17SMatthew G. Knepley const PetscInt *localPoints; 3842bdcf2095SMatthew G. Knepley PetscInt *slocalPoints; 384349c26ae4SMatthew G. Knepley PetscInt numRoots, numLeaves, numSubRoots = numSubCells + numSubFaces + numSubVertices, numSubLeaves = 0, l, sl, ll, pStart, pEnd, p, vStart, vEnd; 3844bdcf2095SMatthew G. Knepley PetscMPIInt rank; 3845aca35d17SMatthew G. Knepley 38469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 38479566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sfPoint)); 38489566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(subdm, &sfPointSub)); 38499566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 38509566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 38519566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints)); 3852aca35d17SMatthew G. Knepley if (numRoots >= 0) { 3853aca35d17SMatthew G. Knepley /* Only vertices should be shared */ 38549566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(pEnd - pStart, &newLocalPoints, numRoots, &newOwners)); 3855bdcf2095SMatthew G. Knepley for (p = 0; p < pEnd - pStart; ++p) { 3856bdcf2095SMatthew G. Knepley newLocalPoints[p].rank = -2; 3857bdcf2095SMatthew G. Knepley newLocalPoints[p].index = -2; 3858bdcf2095SMatthew G. Knepley } 38599e0823b2SMatthew G. Knepley /* Set subleaves */ 3860aca35d17SMatthew G. Knepley for (l = 0; l < numLeaves; ++l) { 3861aca35d17SMatthew G. Knepley const PetscInt point = localPoints[l]; 3862bdcf2095SMatthew G. Knepley const PetscInt subPoint = DMPlexFilterPoint_Internal(point, firstSubVertex, numSubVertices, subVertices); 3863aca35d17SMatthew G. Knepley 386463a3b9bcSJacob Faibussowitsch PetscCheck(!(point < vStart) || !(point >= vEnd), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Should not be mapping anything but vertices, %" PetscInt_FMT, point); 3865bdcf2095SMatthew G. Knepley if (subPoint < 0) continue; 3866bdcf2095SMatthew G. Knepley newLocalPoints[point - pStart].rank = rank; 3867bdcf2095SMatthew G. Knepley newLocalPoints[point - pStart].index = subPoint; 3868bdcf2095SMatthew G. Knepley ++numSubLeaves; 3869aca35d17SMatthew G. Knepley } 38709e0823b2SMatthew G. Knepley /* Must put in owned subpoints */ 38719e0823b2SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 38729e0823b2SMatthew G. Knepley const PetscInt subPoint = DMPlexFilterPoint_Internal(p, firstSubVertex, numSubVertices, subVertices); 38739e0823b2SMatthew G. Knepley 38749e0823b2SMatthew G. Knepley if (subPoint < 0) { 38759e0823b2SMatthew G. Knepley newOwners[p - pStart].rank = -3; 38769e0823b2SMatthew G. Knepley newOwners[p - pStart].index = -3; 38779e0823b2SMatthew G. Knepley } else { 38789e0823b2SMatthew G. Knepley newOwners[p - pStart].rank = rank; 38799e0823b2SMatthew G. Knepley newOwners[p - pStart].index = subPoint; 38809e0823b2SMatthew G. Knepley } 3881bdcf2095SMatthew G. Knepley } 38829566063dSJacob Faibussowitsch PetscCall(PetscSFReduceBegin(sfPoint, MPIU_2INT, newLocalPoints, newOwners, MPI_MAXLOC)); 38839566063dSJacob Faibussowitsch PetscCall(PetscSFReduceEnd(sfPoint, MPIU_2INT, newLocalPoints, newOwners, MPI_MAXLOC)); 38849566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfPoint, MPIU_2INT, newOwners, newLocalPoints, MPI_REPLACE)); 38859566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfPoint, MPIU_2INT, newOwners, newLocalPoints, MPI_REPLACE)); 38869566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numSubLeaves, &slocalPoints)); 38879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numSubLeaves, &sremotePoints)); 388849c26ae4SMatthew G. Knepley for (l = 0, sl = 0, ll = 0; l < numLeaves; ++l) { 3889bdcf2095SMatthew G. Knepley const PetscInt point = localPoints[l]; 3890bdcf2095SMatthew G. Knepley const PetscInt subPoint = DMPlexFilterPoint_Internal(point, firstSubVertex, numSubVertices, subVertices); 3891aca35d17SMatthew G. Knepley 3892aca35d17SMatthew G. Knepley if (subPoint < 0) continue; 38939371c9d4SSatish Balay if (newLocalPoints[point].rank == rank) { 38949371c9d4SSatish Balay ++ll; 38959371c9d4SSatish Balay continue; 38969371c9d4SSatish Balay } 3897aca35d17SMatthew G. Knepley slocalPoints[sl] = subPoint; 3898bdcf2095SMatthew G. Knepley sremotePoints[sl].rank = newLocalPoints[point].rank; 3899bdcf2095SMatthew G. Knepley sremotePoints[sl].index = newLocalPoints[point].index; 390063a3b9bcSJacob Faibussowitsch PetscCheck(sremotePoints[sl].rank >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid remote rank for local point %" PetscInt_FMT, point); 390163a3b9bcSJacob Faibussowitsch PetscCheck(sremotePoints[sl].index >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid remote subpoint for local point %" PetscInt_FMT, point); 3902aca35d17SMatthew G. Knepley ++sl; 3903aca35d17SMatthew G. Knepley } 39049566063dSJacob Faibussowitsch PetscCall(PetscFree2(newLocalPoints, newOwners)); 39051dca8a05SBarry 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); 39069566063dSJacob Faibussowitsch PetscCall(PetscSFSetGraph(sfPointSub, numSubRoots, sl, slocalPoints, PETSC_OWN_POINTER, sremotePoints, PETSC_OWN_POINTER)); 3907aca35d17SMatthew G. Knepley } 3908aca35d17SMatthew G. Knepley } 3909aca35d17SMatthew G. Knepley CHKMEMQ; 3910766ab985SMatthew G. Knepley /* Cleanup */ 39119566063dSJacob Faibussowitsch if (subvertexIS) PetscCall(ISRestoreIndices(subvertexIS, &subVertices)); 39129566063dSJacob Faibussowitsch PetscCall(ISDestroy(&subvertexIS)); 39139566063dSJacob Faibussowitsch PetscCall(PetscFree(subCells)); 39143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3915766ab985SMatthew G. Knepley } 3916766ab985SMatthew G. Knepley 3917d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCohesiveSubmesh_Interpolated(DM dm, const char labelname[], PetscInt value, DM subdm) 3918d71ae5a4SJacob Faibussowitsch { 39193982b651SMatthew G. Knepley DMLabel label = NULL; 3920766ab985SMatthew G. Knepley 3921766ab985SMatthew G. Knepley PetscFunctionBegin; 39229566063dSJacob Faibussowitsch if (labelname) PetscCall(DMGetLabel(dm, labelname, &label)); 39239566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSubmeshGeneric_Interpolated(dm, label, value, PETSC_FALSE, PETSC_TRUE, 1, subdm)); 39243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3925766ab985SMatthew G. Knepley } 3926766ab985SMatthew G. Knepley 3927c08575a3SMatthew G. Knepley /*@C 392820f4b53cSBarry Smith 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. 3929766ab985SMatthew G. Knepley 3930766ab985SMatthew G. Knepley Input Parameters: 3931766ab985SMatthew G. Knepley + dm - The original mesh 393227c04023SMatthew G. Knepley . hasLagrange - The mesh has Lagrange unknowns in the cohesive cells 393320f4b53cSBarry Smith . label - A label name, or `NULL` 393427c04023SMatthew G. Knepley - value - A label value 3935766ab985SMatthew G. Knepley 3936766ab985SMatthew G. Knepley Output Parameter: 3937766ab985SMatthew G. Knepley . subdm - The surface mesh 3938766ab985SMatthew G. Knepley 3939766ab985SMatthew G. Knepley Level: developer 3940766ab985SMatthew G. Knepley 394120f4b53cSBarry Smith Note: 394220f4b53cSBarry Smith This function produces a `DMLabel` mapping original points in the submesh to their depth. This can be obtained using `DMPlexGetSubpointMap()`. 394320f4b53cSBarry Smith 39441cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSubpointMap()`, `DMPlexCreateSubmesh()` 3945c08575a3SMatthew G. Knepley @*/ 3946d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCohesiveSubmesh(DM dm, PetscBool hasLagrange, const char label[], PetscInt value, DM *subdm) 3947d71ae5a4SJacob Faibussowitsch { 3948c0e8cf5fSMatthew G. Knepley PetscInt dim, cdim, depth; 3949766ab985SMatthew G. Knepley 3950766ab985SMatthew G. Knepley PetscFunctionBegin; 3951766ab985SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 39524f572ea9SToby Isaac PetscAssertPointer(subdm, 5); 39539566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 39549566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 39559566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), subdm)); 39569566063dSJacob Faibussowitsch PetscCall(DMSetType(*subdm, DMPLEX)); 39579566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*subdm, dim - 1)); 39589566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &cdim)); 39599566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*subdm, cdim)); 3960766ab985SMatthew G. Knepley if (depth == dim) { 39619566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCohesiveSubmesh_Interpolated(dm, label, value, *subdm)); 3962766ab985SMatthew G. Knepley } else { 39639566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCohesiveSubmesh_Uninterpolated(dm, hasLagrange, label, value, *subdm)); 3964e6ccafaeSMatthew G Knepley } 39655de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, *subdm)); 39663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3967e6ccafaeSMatthew G Knepley } 3968e6ccafaeSMatthew G Knepley 3969bec263e5SMatthew G. Knepley /*@ 39700e18dc48SMatthew G. Knepley DMPlexReorderCohesiveSupports - Ensure that face supports for cohesive end caps are ordered 39710e18dc48SMatthew G. Knepley 39720e18dc48SMatthew G. Knepley Not Collective 39730e18dc48SMatthew G. Knepley 39740e18dc48SMatthew G. Knepley Input Parameter: 39750e18dc48SMatthew G. Knepley . dm - The `DM` containing cohesive cells 39760e18dc48SMatthew G. Knepley 39770e18dc48SMatthew G. Knepley Level: developer 39780e18dc48SMatthew G. Knepley 3979a4e35b19SJacob Faibussowitsch Note: 3980a4e35b19SJacob Faibussowitsch For the negative size (first) face, the cohesive cell should be first in the support, and for 3981a4e35b19SJacob Faibussowitsch the positive side (second) face, the cohesive cell should be second in the support. 39820e18dc48SMatthew G. Knepley 39830e18dc48SMatthew G. Knepley .seealso: `DMPlexConstructCohesiveCells()`, `DMPlexCreateCohesiveSubmesh()` 39840e18dc48SMatthew G. Knepley @*/ 39850e18dc48SMatthew G. Knepley PetscErrorCode DMPlexReorderCohesiveSupports(DM dm) 39860e18dc48SMatthew G. Knepley { 39870e18dc48SMatthew G. Knepley PetscInt dim, cStart, cEnd; 39880e18dc48SMatthew G. Knepley 39890e18dc48SMatthew G. Knepley PetscFunctionBegin; 39900e18dc48SMatthew G. Knepley PetscCall(DMGetDimension(dm, &dim)); 39910e18dc48SMatthew G. Knepley PetscCall(DMPlexGetTensorPrismBounds_Internal(dm, dim, &cStart, &cEnd)); 39920e18dc48SMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) { 39930e18dc48SMatthew G. Knepley const PetscInt *cone; 39940e18dc48SMatthew G. Knepley PetscInt coneSize; 39950e18dc48SMatthew G. Knepley 39960e18dc48SMatthew G. Knepley PetscCall(DMPlexGetConeSize(dm, c, &coneSize)); 39970e18dc48SMatthew G. Knepley PetscCall(DMPlexGetCone(dm, c, &cone)); 39980e18dc48SMatthew G. Knepley PetscCheck(coneSize >= 2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Hybrid cell %" PetscInt_FMT " cone size %" PetscInt_FMT " must be >= 2", c, coneSize); 39990e18dc48SMatthew G. Knepley for (PetscInt s = 0; s < 2; ++s) { 40000e18dc48SMatthew G. Knepley const PetscInt *supp; 40010e18dc48SMatthew G. Knepley PetscInt suppSize, newsupp[2]; 40020e18dc48SMatthew G. Knepley 40030e18dc48SMatthew G. Knepley PetscCall(DMPlexGetSupportSize(dm, cone[s], &suppSize)); 40040e18dc48SMatthew G. Knepley PetscCall(DMPlexGetSupport(dm, cone[s], &supp)); 40050e18dc48SMatthew G. Knepley if (suppSize == 2) { 40060e18dc48SMatthew G. Knepley /* Reorder hybrid end cap support */ 40070e18dc48SMatthew G. Knepley if (supp[s] == c) { 40080e18dc48SMatthew G. Knepley newsupp[0] = supp[1]; 40090e18dc48SMatthew G. Knepley newsupp[1] = supp[0]; 40100e18dc48SMatthew G. Knepley } else { 40110e18dc48SMatthew G. Knepley newsupp[0] = supp[0]; 40120e18dc48SMatthew G. Knepley newsupp[1] = supp[1]; 40130e18dc48SMatthew G. Knepley } 40140e18dc48SMatthew G. Knepley PetscCheck(newsupp[1 - s] == c, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Hybrid end cap %" PetscInt_FMT " support entry %" PetscInt_FMT " != %" PetscInt_FMT " hybrid cell", cone[s], newsupp[1 - s], c); 40150e18dc48SMatthew G. Knepley PetscCall(DMPlexSetSupport(dm, cone[s], newsupp)); 40160e18dc48SMatthew G. Knepley } 40170e18dc48SMatthew G. Knepley } 40180e18dc48SMatthew G. Knepley } 40190e18dc48SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 40200e18dc48SMatthew G. Knepley } 40210e18dc48SMatthew G. Knepley 40220e18dc48SMatthew G. Knepley /*@ 4023bec263e5SMatthew G. Knepley DMPlexFilter - Extract a subset of mesh cells defined by a label as a separate mesh 4024bec263e5SMatthew G. Knepley 4025bec263e5SMatthew G. Knepley Input Parameters: 4026bec263e5SMatthew G. Knepley + dm - The original mesh 402720f4b53cSBarry Smith . cellLabel - The `DMLabel` marking cells contained in the new mesh 4028bec263e5SMatthew G. Knepley - value - The label value to use 4029bec263e5SMatthew G. Knepley 4030bec263e5SMatthew G. Knepley Output Parameter: 4031bec263e5SMatthew G. Knepley . subdm - The new mesh 4032bec263e5SMatthew G. Knepley 4033bec263e5SMatthew G. Knepley Level: developer 4034bec263e5SMatthew G. Knepley 403520f4b53cSBarry Smith Note: 403620f4b53cSBarry Smith This function produces a `DMLabel` mapping original points in the submesh to their depth. This can be obtained using `DMPlexGetSubpointMap()`. 403720f4b53cSBarry Smith 40381cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSubpointMap()`, `DMGetLabel()`, `DMLabelSetValue()`, `DMPlexCreateSubmesh()` 4039bec263e5SMatthew G. Knepley @*/ 4040d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexFilter(DM dm, DMLabel cellLabel, PetscInt value, DM *subdm) 4041d71ae5a4SJacob Faibussowitsch { 4042b47cd10cSMatthew G. Knepley PetscInt dim, overlap; 4043bec263e5SMatthew G. Knepley 4044bec263e5SMatthew G. Knepley PetscFunctionBegin; 4045bec263e5SMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 40464f572ea9SToby Isaac PetscAssertPointer(subdm, 4); 40479566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 40489566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), subdm)); 40499566063dSJacob Faibussowitsch PetscCall(DMSetType(*subdm, DMPLEX)); 4050bec263e5SMatthew G. Knepley /* Extract submesh in place, could be empty on some procs, could have inconsistency if procs do not both extract a shared cell */ 40519566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSubmeshGeneric_Interpolated(dm, cellLabel, value, PETSC_FALSE, PETSC_FALSE, 0, *subdm)); 40525de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_TRUE, *subdm)); 4053b47cd10cSMatthew G. Knepley // It is possible to obtain a surface mesh where some faces are in SF 4054b47cd10cSMatthew G. Knepley // We should either mark the mesh as having an overlap, or delete these from the SF 4055b47cd10cSMatthew G. Knepley PetscCall(DMPlexGetOverlap(dm, &overlap)); 4056b47cd10cSMatthew G. Knepley if (!overlap) { 4057b47cd10cSMatthew G. Knepley PetscSF sf; 4058b47cd10cSMatthew G. Knepley const PetscInt *leaves; 4059b47cd10cSMatthew G. Knepley PetscInt cStart, cEnd, Nl; 4060b47cd10cSMatthew G. Knepley PetscBool hasSubcell = PETSC_FALSE, ghasSubcell; 4061b47cd10cSMatthew G. Knepley 4062b47cd10cSMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(*subdm, 0, &cStart, &cEnd)); 4063b47cd10cSMatthew G. Knepley PetscCall(DMGetPointSF(*subdm, &sf)); 4064b47cd10cSMatthew G. Knepley PetscCall(PetscSFGetGraph(sf, NULL, &Nl, &leaves, NULL)); 4065b47cd10cSMatthew G. Knepley for (PetscInt l = 0; l < Nl; ++l) { 4066b47cd10cSMatthew G. Knepley const PetscInt point = leaves ? leaves[l] : l; 4067b47cd10cSMatthew G. Knepley 4068b47cd10cSMatthew G. Knepley if (point >= cStart && point < cEnd) { 4069b47cd10cSMatthew G. Knepley hasSubcell = PETSC_TRUE; 4070b47cd10cSMatthew G. Knepley break; 4071b47cd10cSMatthew G. Knepley } 4072b47cd10cSMatthew G. Knepley } 4073b47cd10cSMatthew G. Knepley PetscCall(MPIU_Allreduce(&hasSubcell, &ghasSubcell, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm))); 4074b47cd10cSMatthew G. Knepley if (ghasSubcell) PetscCall(DMPlexSetOverlap(*subdm, NULL, 1)); 4075b47cd10cSMatthew G. Knepley } 40763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4077bec263e5SMatthew G. Knepley } 4078bec263e5SMatthew G. Knepley 407964beef6dSMatthew G. Knepley /*@ 408020f4b53cSBarry Smith DMPlexGetSubpointMap - Returns a `DMLabel` with point dimension as values 408164beef6dSMatthew G. Knepley 408264beef6dSMatthew G. Knepley Input Parameter: 408320f4b53cSBarry Smith . dm - The submesh `DM` 408464beef6dSMatthew G. Knepley 408564beef6dSMatthew G. Knepley Output Parameter: 408620f4b53cSBarry Smith . subpointMap - The `DMLabel` of all the points from the original mesh in this submesh, or `NULL` if this is not a submesh 408764beef6dSMatthew G. Knepley 408864beef6dSMatthew G. Knepley Level: developer 408964beef6dSMatthew G. Knepley 40901cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSubmesh()`, `DMPlexGetSubpointIS()` 409164beef6dSMatthew G. Knepley @*/ 4092d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSubpointMap(DM dm, DMLabel *subpointMap) 4093d71ae5a4SJacob Faibussowitsch { 4094e6ccafaeSMatthew G Knepley PetscFunctionBegin; 4095e6ccafaeSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 40964f572ea9SToby Isaac PetscAssertPointer(subpointMap, 2); 409765663942SMatthew G. Knepley *subpointMap = ((DM_Plex *)dm->data)->subpointMap; 40983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4099e6ccafaeSMatthew G Knepley } 4100e6ccafaeSMatthew G Knepley 4101c08575a3SMatthew G. Knepley /*@ 410220f4b53cSBarry Smith DMPlexSetSubpointMap - Sets the `DMLabel` with point dimension as values 4103c08575a3SMatthew G. Knepley 4104c08575a3SMatthew G. Knepley Input Parameters: 410520f4b53cSBarry Smith + dm - The submesh `DM` 410620f4b53cSBarry Smith - subpointMap - The `DMLabel` of all the points from the original mesh in this submesh 4107c08575a3SMatthew G. Knepley 4108c08575a3SMatthew G. Knepley Level: developer 4109c08575a3SMatthew G. Knepley 411020f4b53cSBarry Smith Note: 411120f4b53cSBarry Smith Should normally not be called by the user, since it is set in `DMPlexCreateSubmesh()` 411220f4b53cSBarry Smith 41131cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSubmesh()`, `DMPlexGetSubpointIS()` 4114c08575a3SMatthew G. Knepley @*/ 4115d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSubpointMap(DM dm, DMLabel subpointMap) 4116d71ae5a4SJacob Faibussowitsch { 4117e6ccafaeSMatthew G Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 4118285d324eSMatthew G. Knepley DMLabel tmp; 4119e6ccafaeSMatthew G Knepley 4120e6ccafaeSMatthew G Knepley PetscFunctionBegin; 4121e6ccafaeSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4122285d324eSMatthew G. Knepley tmp = mesh->subpointMap; 4123e6ccafaeSMatthew G Knepley mesh->subpointMap = subpointMap; 41249566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)mesh->subpointMap)); 41259566063dSJacob Faibussowitsch PetscCall(DMLabelDestroy(&tmp)); 41263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4127e6ccafaeSMatthew G Knepley } 4128e6ccafaeSMatthew G Knepley 4129d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSubpointIS_Internal(DM dm, IS *subpointIS) 4130d71ae5a4SJacob Faibussowitsch { 413197d8846cSMatthew Knepley DMLabel spmap; 413297d8846cSMatthew Knepley PetscInt depth, d; 413397d8846cSMatthew Knepley 413497d8846cSMatthew Knepley PetscFunctionBegin; 41359566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointMap(dm, &spmap)); 41369566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 413797d8846cSMatthew Knepley if (spmap && depth >= 0) { 413897d8846cSMatthew Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 413997d8846cSMatthew Knepley PetscInt *points, *depths; 414097d8846cSMatthew Knepley PetscInt pStart, pEnd, p, off; 414197d8846cSMatthew Knepley 41429566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 414363a3b9bcSJacob Faibussowitsch PetscCheck(!pStart, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Submeshes must start the point numbering at 0, not %" PetscInt_FMT, pStart); 41449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(pEnd, &points)); 41459566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, depth + 1, MPIU_INT, &depths)); 414697d8846cSMatthew Knepley depths[0] = depth; 414797d8846cSMatthew Knepley depths[1] = 0; 4148ad540459SPierre Jolivet for (d = 2; d <= depth; ++d) depths[d] = depth + 1 - d; 414997d8846cSMatthew Knepley for (d = 0, off = 0; d <= depth; ++d) { 415097d8846cSMatthew Knepley const PetscInt dep = depths[d]; 415197d8846cSMatthew Knepley PetscInt depStart, depEnd, n; 415297d8846cSMatthew Knepley 41539566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dep, &depStart, &depEnd)); 41549566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumSize(spmap, dep, &n)); 415597d8846cSMatthew Knepley if (((d < 2) && (depth > 1)) || (d == 1)) { /* Only check vertices and cells for now since the map is broken for others */ 415663a3b9bcSJacob 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); 415797d8846cSMatthew Knepley } else { 415897d8846cSMatthew Knepley if (!n) { 415997d8846cSMatthew Knepley if (d == 0) { 416097d8846cSMatthew Knepley /* Missing cells */ 416197d8846cSMatthew Knepley for (p = 0; p < depEnd - depStart; ++p, ++off) points[off] = -1; 416297d8846cSMatthew Knepley } else { 416397d8846cSMatthew Knepley /* Missing faces */ 416497d8846cSMatthew Knepley for (p = 0; p < depEnd - depStart; ++p, ++off) points[off] = PETSC_MAX_INT; 416597d8846cSMatthew Knepley } 416697d8846cSMatthew Knepley } 416797d8846cSMatthew Knepley } 416897d8846cSMatthew Knepley if (n) { 416997d8846cSMatthew Knepley IS is; 417097d8846cSMatthew Knepley const PetscInt *opoints; 417197d8846cSMatthew Knepley 41729566063dSJacob Faibussowitsch PetscCall(DMLabelGetStratumIS(spmap, dep, &is)); 41739566063dSJacob Faibussowitsch PetscCall(ISGetIndices(is, &opoints)); 417497d8846cSMatthew Knepley for (p = 0; p < n; ++p, ++off) points[off] = opoints[p]; 41759566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(is, &opoints)); 41769566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is)); 417797d8846cSMatthew Knepley } 417897d8846cSMatthew Knepley } 41799566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, depth + 1, MPIU_INT, &depths)); 418063a3b9bcSJacob 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); 41819566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, pEnd, points, PETSC_OWN_POINTER, subpointIS)); 41829566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)spmap, &mesh->subpointState)); 418397d8846cSMatthew Knepley } 41843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 418597d8846cSMatthew Knepley } 418697d8846cSMatthew Knepley 418764beef6dSMatthew G. Knepley /*@ 418820f4b53cSBarry Smith DMPlexGetSubpointIS - Returns an `IS` covering the entire subdm chart with the original points as data 4189e6ccafaeSMatthew G Knepley 4190e6ccafaeSMatthew G Knepley Input Parameter: 419120f4b53cSBarry Smith . dm - The submesh `DM` 4192e6ccafaeSMatthew G Knepley 4193e6ccafaeSMatthew G Knepley Output Parameter: 419420f4b53cSBarry Smith . subpointIS - The `IS` of all the points from the original mesh in this submesh, or `NULL` if this is not a submesh 419564beef6dSMatthew G. Knepley 419664beef6dSMatthew G. Knepley Level: developer 419764beef6dSMatthew G. Knepley 419820f4b53cSBarry Smith Note: 419920f4b53cSBarry Smith This `IS` is guaranteed to be sorted by the construction of the submesh 420020f4b53cSBarry Smith 42011cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSubmesh()`, `DMPlexGetSubpointMap()` 420264beef6dSMatthew G. Knepley @*/ 4203d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSubpointIS(DM dm, IS *subpointIS) 4204d71ae5a4SJacob Faibussowitsch { 420597d8846cSMatthew Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 420697d8846cSMatthew Knepley DMLabel spmap; 420797d8846cSMatthew Knepley PetscObjectState state; 4208e6ccafaeSMatthew G Knepley 4209e6ccafaeSMatthew G Knepley PetscFunctionBegin; 4210e6ccafaeSMatthew G Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 42114f572ea9SToby Isaac PetscAssertPointer(subpointIS, 2); 42129566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointMap(dm, &spmap)); 42139566063dSJacob Faibussowitsch PetscCall(PetscObjectStateGet((PetscObject)spmap, &state)); 42149566063dSJacob Faibussowitsch if (state != mesh->subpointState || !mesh->subpointIS) PetscCall(DMPlexCreateSubpointIS_Internal(dm, &mesh->subpointIS)); 421597d8846cSMatthew Knepley *subpointIS = mesh->subpointIS; 42163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4217e6ccafaeSMatthew G Knepley } 4218559a1558SMatthew G. Knepley 4219559a1558SMatthew G. Knepley /*@ 422020f4b53cSBarry Smith DMGetEnclosureRelation - Get the relationship between `dmA` and `dmB` 4221559a1558SMatthew G. Knepley 4222559a1558SMatthew G. Knepley Input Parameters: 422320f4b53cSBarry Smith + dmA - The first `DM` 422420f4b53cSBarry Smith - dmB - The second `DM` 4225559a1558SMatthew G. Knepley 4226559a1558SMatthew G. Knepley Output Parameter: 422720f4b53cSBarry Smith . rel - The relation of `dmA` to `dmB` 4228559a1558SMatthew G. Knepley 4229a6e0b375SMatthew G. Knepley Level: intermediate 4230559a1558SMatthew G. Knepley 42311cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetEnclosurePoint()` 4232559a1558SMatthew G. Knepley @*/ 4233d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetEnclosureRelation(DM dmA, DM dmB, DMEnclosureType *rel) 4234d71ae5a4SJacob Faibussowitsch { 4235a6e0b375SMatthew G. Knepley DM plexA, plexB, sdm; 4236559a1558SMatthew G. Knepley DMLabel spmap; 4237a6e0b375SMatthew G. Knepley PetscInt pStartA, pEndA, pStartB, pEndB, NpA, NpB; 4238559a1558SMatthew G. Knepley 423944171101SMatthew G. Knepley PetscFunctionBegin; 42404f572ea9SToby Isaac PetscAssertPointer(rel, 3); 4241a6e0b375SMatthew G. Knepley *rel = DM_ENC_NONE; 42423ba16761SJacob Faibussowitsch if (!dmA || !dmB) PetscFunctionReturn(PETSC_SUCCESS); 4243a6e0b375SMatthew G. Knepley PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 4244064a246eSJacob Faibussowitsch PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 42459371c9d4SSatish Balay if (dmA == dmB) { 42469371c9d4SSatish Balay *rel = DM_ENC_EQUALITY; 42473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42489371c9d4SSatish Balay } 42499566063dSJacob Faibussowitsch PetscCall(DMConvert(dmA, DMPLEX, &plexA)); 42509566063dSJacob Faibussowitsch PetscCall(DMConvert(dmB, DMPLEX, &plexB)); 42519566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexA, &pStartA, &pEndA)); 42529566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(plexB, &pStartB, &pEndB)); 4253a6e0b375SMatthew G. Knepley /* Assumption 1: subDMs have smaller charts than the DMs that they originate from 4254a6e0b375SMatthew G. Knepley - The degenerate case of a subdomain which includes all of the domain on some process can be treated as equality */ 4255a6e0b375SMatthew G. Knepley if ((pStartA == pStartB) && (pEndA == pEndB)) { 4256a6e0b375SMatthew G. Knepley *rel = DM_ENC_EQUALITY; 4257a6e0b375SMatthew G. Knepley goto end; 4258559a1558SMatthew G. Knepley } 4259a6e0b375SMatthew G. Knepley NpA = pEndA - pStartA; 4260a6e0b375SMatthew G. Knepley NpB = pEndB - pStartB; 4261a6e0b375SMatthew G. Knepley if (NpA == NpB) goto end; 4262a6e0b375SMatthew G. Knepley sdm = NpA > NpB ? plexB : plexA; /* The other is the original, enclosing dm */ 42639566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointMap(sdm, &spmap)); 4264a6e0b375SMatthew G. Knepley if (!spmap) goto end; 4265a6e0b375SMatthew G. Knepley /* TODO Check the space mapped to by subpointMap is same size as dm */ 4266a6e0b375SMatthew G. Knepley if (NpA > NpB) { 4267a6e0b375SMatthew G. Knepley *rel = DM_ENC_SUPERMESH; 4268a6e0b375SMatthew G. Knepley } else { 4269a6e0b375SMatthew G. Knepley *rel = DM_ENC_SUBMESH; 4270a6e0b375SMatthew G. Knepley } 4271a6e0b375SMatthew G. Knepley end: 42729566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plexA)); 42739566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plexB)); 42743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4275559a1558SMatthew G. Knepley } 427644171101SMatthew G. Knepley 427744171101SMatthew G. Knepley /*@ 427820f4b53cSBarry Smith DMGetEnclosurePoint - Get the point `pA` in `dmA` which corresponds to the point `pB` in `dmB` 427944171101SMatthew G. Knepley 428044171101SMatthew G. Knepley Input Parameters: 428120f4b53cSBarry Smith + dmA - The first `DM` 428220f4b53cSBarry Smith . dmB - The second `DM` 428320f4b53cSBarry Smith . etype - The type of enclosure relation that `dmA` has to `dmB` 428420f4b53cSBarry Smith - pB - A point of `dmB` 428544171101SMatthew G. Knepley 428644171101SMatthew G. Knepley Output Parameter: 428720f4b53cSBarry Smith . pA - The corresponding point of `dmA` 428844171101SMatthew G. Knepley 4289a6e0b375SMatthew G. Knepley Level: intermediate 429044171101SMatthew G. Knepley 42911cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetEnclosureRelation()` 429244171101SMatthew G. Knepley @*/ 4293d71ae5a4SJacob Faibussowitsch PetscErrorCode DMGetEnclosurePoint(DM dmA, DM dmB, DMEnclosureType etype, PetscInt pB, PetscInt *pA) 4294d71ae5a4SJacob Faibussowitsch { 4295a6e0b375SMatthew G. Knepley DM sdm; 4296a6e0b375SMatthew G. Knepley IS subpointIS; 4297a6e0b375SMatthew G. Knepley const PetscInt *subpoints; 4298a6e0b375SMatthew G. Knepley PetscInt numSubpoints; 429944171101SMatthew G. Knepley 430044171101SMatthew G. Knepley PetscFunctionBegin; 4301a6e0b375SMatthew G. Knepley /* TODO Cache the IS, making it look like an index */ 4302a6e0b375SMatthew G. Knepley switch (etype) { 4303a6e0b375SMatthew G. Knepley case DM_ENC_SUPERMESH: 4304a6e0b375SMatthew G. Knepley sdm = dmB; 43059566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(sdm, &subpointIS)); 43069566063dSJacob Faibussowitsch PetscCall(ISGetIndices(subpointIS, &subpoints)); 4307a6e0b375SMatthew G. Knepley *pA = subpoints[pB]; 43089566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(subpointIS, &subpoints)); 4309a6e0b375SMatthew G. Knepley break; 4310a6e0b375SMatthew G. Knepley case DM_ENC_SUBMESH: 4311a6e0b375SMatthew G. Knepley sdm = dmA; 43129566063dSJacob Faibussowitsch PetscCall(DMPlexGetSubpointIS(sdm, &subpointIS)); 43139566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(subpointIS, &numSubpoints)); 43149566063dSJacob Faibussowitsch PetscCall(ISGetIndices(subpointIS, &subpoints)); 43159566063dSJacob Faibussowitsch PetscCall(PetscFindInt(pB, numSubpoints, subpoints, pA)); 4316a6e0b375SMatthew G. Knepley if (*pA < 0) { 43179566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dmA, NULL, "-dm_enc_A_view")); 43189566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dmB, NULL, "-dm_enc_B_view")); 431963a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %" PetscInt_FMT " not found in submesh", pB); 4320a6e0b375SMatthew G. Knepley } 43219566063dSJacob Faibussowitsch PetscCall(ISRestoreIndices(subpointIS, &subpoints)); 4322a6e0b375SMatthew G. Knepley break; 4323a6e0b375SMatthew G. Knepley case DM_ENC_EQUALITY: 4324d71ae5a4SJacob Faibussowitsch case DM_ENC_NONE: 4325d71ae5a4SJacob Faibussowitsch *pA = pB; 4326d71ae5a4SJacob Faibussowitsch break; 43279371c9d4SSatish Balay case DM_ENC_UNKNOWN: { 4328a6e0b375SMatthew G. Knepley DMEnclosureType enc; 432944171101SMatthew G. Knepley 43309566063dSJacob Faibussowitsch PetscCall(DMGetEnclosureRelation(dmA, dmB, &enc)); 43319566063dSJacob Faibussowitsch PetscCall(DMGetEnclosurePoint(dmA, dmB, enc, pB, pA)); 43329371c9d4SSatish Balay } break; 4333d71ae5a4SJacob Faibussowitsch default: 4334d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dmA), PETSC_ERR_ARG_OUTOFRANGE, "Invalid enclosure type %d", (int)etype); 433544171101SMatthew G. Knepley } 43363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 433744171101SMatthew G. Knepley } 4338