1*2bc0b47dSJoe Wallwork #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2*2bc0b47dSJoe Wallwork #include <mmg/libmmg.h> 3*2bc0b47dSJoe Wallwork 4*2bc0b47dSJoe Wallwork PETSC_EXTERN PetscErrorCode DMAdaptMetric_Mmg_Plex(DM dm, Vec vertexMetric, DMLabel bdLabel, DM *dmNew) 5*2bc0b47dSJoe Wallwork { 6*2bc0b47dSJoe Wallwork MPI_Comm comm; 7*2bc0b47dSJoe Wallwork const char *bdName = "_boundary_"; 8*2bc0b47dSJoe Wallwork DM udm, cdm; 9*2bc0b47dSJoe Wallwork DMLabel bdLabelFull; 10*2bc0b47dSJoe Wallwork const char *bdLabelName; 11*2bc0b47dSJoe Wallwork IS bdIS; 12*2bc0b47dSJoe Wallwork PetscSection coordSection; 13*2bc0b47dSJoe Wallwork Vec coordinates; 14*2bc0b47dSJoe Wallwork const PetscScalar *coords, *met; 15*2bc0b47dSJoe Wallwork const PetscInt *bdFacesFull; 16*2bc0b47dSJoe Wallwork PetscInt *bdFaces, *bdFaceIds; 17*2bc0b47dSJoe Wallwork PetscReal *vertices, *metric, *verticesNew, gradationFactor; 18*2bc0b47dSJoe Wallwork PetscInt *cells, *cellsNew; 19*2bc0b47dSJoe Wallwork PetscInt *facesNew, *faceTagsNew; 20*2bc0b47dSJoe Wallwork PetscInt *verTags, *cellTags, *verTagsNew, *cellTagsNew; 21*2bc0b47dSJoe Wallwork PetscInt *corners, *requiredCells, *requiredVer, *ridges, *requiredFaces; 22*2bc0b47dSJoe Wallwork PetscInt dim, cStart, cEnd, numCells, c, coff, vStart, vEnd, numVertices, v; 23*2bc0b47dSJoe Wallwork PetscInt off, maxConeSize, numBdFaces, f, bdSize, fStart, fEnd, i, j, k, Neq; 24*2bc0b47dSJoe Wallwork PetscInt numCellsNew, numVerticesNew, numCornersNew, numFacesNew; 25*2bc0b47dSJoe Wallwork PetscInt verbosity; 26*2bc0b47dSJoe Wallwork PetscBool flg, noInsert, noSwap, noMove; 27*2bc0b47dSJoe Wallwork DMLabel bdLabelNew; 28*2bc0b47dSJoe Wallwork MMG5_pMesh mmg_mesh = NULL; 29*2bc0b47dSJoe Wallwork MMG5_pSol mmg_metric = NULL; 30*2bc0b47dSJoe Wallwork PetscErrorCode ierr; 31*2bc0b47dSJoe Wallwork 32*2bc0b47dSJoe Wallwork PetscFunctionBegin; 33*2bc0b47dSJoe Wallwork ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 34*2bc0b47dSJoe Wallwork if (bdLabel) { 35*2bc0b47dSJoe Wallwork ierr = PetscObjectGetName((PetscObject) bdLabel, &bdLabelName);CHKERRQ(ierr); 36*2bc0b47dSJoe Wallwork ierr = PetscStrcmp(bdLabelName, bdName, &flg);CHKERRQ(ierr); 37*2bc0b47dSJoe Wallwork if (flg) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "\"%s\" cannot be used as label for boundary facets", bdLabelName); 38*2bc0b47dSJoe Wallwork } 39*2bc0b47dSJoe Wallwork 40*2bc0b47dSJoe Wallwork /* Get mesh information */ 41*2bc0b47dSJoe Wallwork ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 42*2bc0b47dSJoe Wallwork Neq = (dim*(dim+1))/2; 43*2bc0b47dSJoe Wallwork ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 44*2bc0b47dSJoe Wallwork ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 45*2bc0b47dSJoe Wallwork ierr = DMPlexUninterpolate(dm, &udm);CHKERRQ(ierr); 46*2bc0b47dSJoe Wallwork ierr = DMPlexGetMaxSizes(udm, &maxConeSize, NULL);CHKERRQ(ierr); 47*2bc0b47dSJoe Wallwork numCells = cEnd - cStart; 48*2bc0b47dSJoe Wallwork numVertices = vEnd - vStart; 49*2bc0b47dSJoe Wallwork 50*2bc0b47dSJoe Wallwork /* Get cell offsets */ 51*2bc0b47dSJoe Wallwork ierr = PetscMalloc1(numCells*maxConeSize, &cells);CHKERRQ(ierr); 52*2bc0b47dSJoe Wallwork for (c = 0, coff = 0; c < numCells; ++c) { 53*2bc0b47dSJoe Wallwork const PetscInt *cone; 54*2bc0b47dSJoe Wallwork PetscInt coneSize, cl; 55*2bc0b47dSJoe Wallwork 56*2bc0b47dSJoe Wallwork ierr = DMPlexGetConeSize(udm, c, &coneSize);CHKERRQ(ierr); 57*2bc0b47dSJoe Wallwork ierr = DMPlexGetCone(udm, c, &cone);CHKERRQ(ierr); 58*2bc0b47dSJoe Wallwork for (cl = 0; cl < coneSize; ++cl) cells[coff++] = cone[cl] - vStart + 1; 59*2bc0b47dSJoe Wallwork } 60*2bc0b47dSJoe Wallwork 61*2bc0b47dSJoe Wallwork /* Get vertex coordinate array */ 62*2bc0b47dSJoe Wallwork ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 63*2bc0b47dSJoe Wallwork ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 64*2bc0b47dSJoe Wallwork ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 65*2bc0b47dSJoe Wallwork ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 66*2bc0b47dSJoe Wallwork ierr = PetscMalloc2(numVertices*Neq, &metric, dim*numVertices, &vertices);CHKERRQ(ierr); 67*2bc0b47dSJoe Wallwork for (v = 0; v < vEnd-vStart; ++v) { 68*2bc0b47dSJoe Wallwork ierr = PetscSectionGetOffset(coordSection, v+vStart, &off);CHKERRQ(ierr); 69*2bc0b47dSJoe Wallwork for (i = 0; i < dim; ++i) vertices[dim*v+i] = PetscRealPart(coords[off+i]); 70*2bc0b47dSJoe Wallwork } 71*2bc0b47dSJoe Wallwork ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 72*2bc0b47dSJoe Wallwork ierr = DMDestroy(&udm);CHKERRQ(ierr); 73*2bc0b47dSJoe Wallwork 74*2bc0b47dSJoe Wallwork /* Get boundary mesh */ 75*2bc0b47dSJoe Wallwork ierr = DMLabelCreate(PETSC_COMM_SELF, bdName, &bdLabelFull);CHKERRQ(ierr); 76*2bc0b47dSJoe Wallwork ierr = DMPlexMarkBoundaryFaces(dm, 1, bdLabelFull);CHKERRQ(ierr); 77*2bc0b47dSJoe Wallwork ierr = DMLabelGetStratumIS(bdLabelFull, 1, &bdIS);CHKERRQ(ierr); 78*2bc0b47dSJoe Wallwork ierr = DMLabelGetStratumSize(bdLabelFull, 1, &numBdFaces);CHKERRQ(ierr); 79*2bc0b47dSJoe Wallwork ierr = ISGetIndices(bdIS, &bdFacesFull);CHKERRQ(ierr); 80*2bc0b47dSJoe Wallwork for (f = 0, bdSize = 0; f < numBdFaces; ++f) { 81*2bc0b47dSJoe Wallwork PetscInt *closure = NULL; 82*2bc0b47dSJoe Wallwork PetscInt closureSize, cl; 83*2bc0b47dSJoe Wallwork 84*2bc0b47dSJoe Wallwork ierr = DMPlexGetTransitiveClosure(dm, bdFacesFull[f], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 85*2bc0b47dSJoe Wallwork for (cl = 0; cl < closureSize*2; cl += 2) { 86*2bc0b47dSJoe Wallwork if ((closure[cl] >= vStart) && (closure[cl] < vEnd)) ++bdSize; 87*2bc0b47dSJoe Wallwork } 88*2bc0b47dSJoe Wallwork ierr = DMPlexRestoreTransitiveClosure(dm, bdFacesFull[f], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 89*2bc0b47dSJoe Wallwork } 90*2bc0b47dSJoe Wallwork ierr = PetscMalloc2(bdSize, &bdFaces, numBdFaces, &bdFaceIds);CHKERRQ(ierr); 91*2bc0b47dSJoe Wallwork for (f = 0, bdSize = 0; f < numBdFaces; ++f) { 92*2bc0b47dSJoe Wallwork PetscInt *closure = NULL; 93*2bc0b47dSJoe Wallwork PetscInt closureSize, cl; 94*2bc0b47dSJoe Wallwork 95*2bc0b47dSJoe Wallwork ierr = DMPlexGetTransitiveClosure(dm, bdFacesFull[f], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 96*2bc0b47dSJoe Wallwork for (cl = 0; cl < closureSize*2; cl += 2) { 97*2bc0b47dSJoe Wallwork if ((closure[cl] >= vStart) && (closure[cl] < vEnd)) bdFaces[bdSize++] = closure[cl] - vStart + 1; 98*2bc0b47dSJoe Wallwork } 99*2bc0b47dSJoe Wallwork ierr = DMPlexRestoreTransitiveClosure(dm, bdFacesFull[f], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 100*2bc0b47dSJoe Wallwork if (bdLabel) {ierr = DMLabelGetValue(bdLabel, bdFacesFull[f], &bdFaceIds[f]);CHKERRQ(ierr);} 101*2bc0b47dSJoe Wallwork else {bdFaceIds[f] = 1;} 102*2bc0b47dSJoe Wallwork } 103*2bc0b47dSJoe Wallwork ierr = ISDestroy(&bdIS);CHKERRQ(ierr); 104*2bc0b47dSJoe Wallwork ierr = DMLabelDestroy(&bdLabelFull);CHKERRQ(ierr); 105*2bc0b47dSJoe Wallwork 106*2bc0b47dSJoe Wallwork /* Get metric */ 107*2bc0b47dSJoe Wallwork ierr = VecViewFromOptions(vertexMetric, NULL, "-adapt_metric_view");CHKERRQ(ierr); 108*2bc0b47dSJoe Wallwork ierr = VecGetArrayRead(vertexMetric, &met);CHKERRQ(ierr); 109*2bc0b47dSJoe Wallwork for (v = 0; v < (vEnd-vStart); ++v) { 110*2bc0b47dSJoe Wallwork for (i = 0, k = 0; i < dim; ++i) { 111*2bc0b47dSJoe Wallwork for (j = i; j < dim; ++j) { 112*2bc0b47dSJoe Wallwork metric[Neq*v+k] = PetscRealPart(met[dim*dim*v+dim*i+j]); 113*2bc0b47dSJoe Wallwork k++; 114*2bc0b47dSJoe Wallwork } 115*2bc0b47dSJoe Wallwork } 116*2bc0b47dSJoe Wallwork } 117*2bc0b47dSJoe Wallwork ierr = VecRestoreArrayRead(vertexMetric, &met);CHKERRQ(ierr); 118*2bc0b47dSJoe Wallwork 119*2bc0b47dSJoe Wallwork /* Send mesh to Mmg and remesh */ 120*2bc0b47dSJoe Wallwork ierr = DMPlexMetricGetVerbosity(dm, &verbosity);CHKERRQ(ierr); 121*2bc0b47dSJoe Wallwork ierr = DMPlexMetricGetGradationFactor(dm, &gradationFactor);CHKERRQ(ierr); 122*2bc0b47dSJoe Wallwork ierr = DMPlexMetricNoInsertion(dm, &noInsert);CHKERRQ(ierr); 123*2bc0b47dSJoe Wallwork ierr = DMPlexMetricNoSwapping(dm, &noSwap);CHKERRQ(ierr); 124*2bc0b47dSJoe Wallwork ierr = DMPlexMetricNoMovement(dm, &noMove);CHKERRQ(ierr); 125*2bc0b47dSJoe Wallwork ierr = PetscCalloc2(numVertices, &verTags, numCells, &cellTags);CHKERRQ(ierr); 126*2bc0b47dSJoe Wallwork switch (dim) { 127*2bc0b47dSJoe Wallwork case 2: 128*2bc0b47dSJoe Wallwork ierr = MMG2D_Init_mesh(MMG5_ARG_start, MMG5_ARG_ppMesh, &mmg_mesh, MMG5_ARG_ppMet, &mmg_metric, MMG5_ARG_end); 129*2bc0b47dSJoe Wallwork ierr = MMG2D_Set_iparameter(mmg_mesh, mmg_metric, MMG2D_IPARAM_noinsert, noInsert); 130*2bc0b47dSJoe Wallwork ierr = MMG2D_Set_iparameter(mmg_mesh, mmg_metric, MMG2D_IPARAM_noswap, noSwap); 131*2bc0b47dSJoe Wallwork ierr = MMG2D_Set_iparameter(mmg_mesh, mmg_metric, MMG2D_IPARAM_nomove, noMove); 132*2bc0b47dSJoe Wallwork ierr = MMG2D_Set_iparameter(mmg_mesh, mmg_metric, MMG2D_IPARAM_verbose, verbosity); 133*2bc0b47dSJoe Wallwork ierr = MMG2D_Set_dparameter(mmg_mesh, mmg_metric, MMG2D_DPARAM_hgrad, gradationFactor); 134*2bc0b47dSJoe Wallwork ierr = MMG2D_Set_meshSize(mmg_mesh, numVertices, numCells, 0, numBdFaces); 135*2bc0b47dSJoe Wallwork ierr = MMG2D_Set_vertices(mmg_mesh, vertices, verTags); 136*2bc0b47dSJoe Wallwork ierr = MMG2D_Set_triangles(mmg_mesh, cells, cellTags); 137*2bc0b47dSJoe Wallwork ierr = MMG2D_Set_edges(mmg_mesh, bdFaces, bdFaceIds); 138*2bc0b47dSJoe Wallwork ierr = MMG2D_Set_solSize(mmg_mesh, mmg_metric, MMG5_Vertex, numVertices, MMG5_Tensor); 139*2bc0b47dSJoe Wallwork ierr = MMG2D_Set_tensorSols(mmg_metric, metric); 140*2bc0b47dSJoe Wallwork ierr = MMG2D_mmg2dlib(mmg_mesh, mmg_metric); 141*2bc0b47dSJoe Wallwork break; 142*2bc0b47dSJoe Wallwork case 3: 143*2bc0b47dSJoe Wallwork ierr = MMG3D_Init_mesh(MMG5_ARG_start, MMG5_ARG_ppMesh, &mmg_mesh, MMG5_ARG_ppMet, &mmg_metric, MMG5_ARG_end); 144*2bc0b47dSJoe Wallwork ierr = MMG3D_Set_iparameter(mmg_mesh, mmg_metric, MMG3D_IPARAM_noinsert, noInsert); 145*2bc0b47dSJoe Wallwork ierr = MMG3D_Set_iparameter(mmg_mesh, mmg_metric, MMG3D_IPARAM_noswap, noSwap); 146*2bc0b47dSJoe Wallwork ierr = MMG3D_Set_iparameter(mmg_mesh, mmg_metric, MMG3D_IPARAM_nomove, noMove); 147*2bc0b47dSJoe Wallwork ierr = MMG3D_Set_iparameter(mmg_mesh, mmg_metric, MMG3D_IPARAM_verbose, verbosity); 148*2bc0b47dSJoe Wallwork ierr = MMG3D_Set_dparameter(mmg_mesh, mmg_metric, MMG3D_DPARAM_hgrad, gradationFactor); 149*2bc0b47dSJoe Wallwork ierr = MMG3D_Set_meshSize(mmg_mesh, numVertices, numCells, 0, numBdFaces, 0, 0); 150*2bc0b47dSJoe Wallwork ierr = MMG3D_Set_vertices(mmg_mesh, vertices, verTags); 151*2bc0b47dSJoe Wallwork ierr = MMG3D_Set_tetrahedra(mmg_mesh, cells, cellTags); 152*2bc0b47dSJoe Wallwork ierr = MMG3D_Set_triangles(mmg_mesh, bdFaces, bdFaceIds); 153*2bc0b47dSJoe Wallwork ierr = MMG3D_Set_solSize(mmg_mesh, mmg_metric, MMG5_Vertex, numVertices, MMG5_Tensor); 154*2bc0b47dSJoe Wallwork ierr = MMG3D_Set_tensorSols(mmg_metric, metric); 155*2bc0b47dSJoe Wallwork ierr = MMG3D_mmg3dlib(mmg_mesh, mmg_metric); 156*2bc0b47dSJoe Wallwork break; 157*2bc0b47dSJoe Wallwork default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No Mmg adaptation defined for dimension %D", dim); 158*2bc0b47dSJoe Wallwork } 159*2bc0b47dSJoe Wallwork 160*2bc0b47dSJoe Wallwork /* Retrieve mesh from Mmg and create new Plex*/ 161*2bc0b47dSJoe Wallwork switch (dim) { 162*2bc0b47dSJoe Wallwork case 2: 163*2bc0b47dSJoe Wallwork numCornersNew = 3; 164*2bc0b47dSJoe Wallwork ierr = MMG2D_Get_meshSize(mmg_mesh, &numVerticesNew, &numCellsNew, 0, &numFacesNew); 165*2bc0b47dSJoe Wallwork ierr = PetscMalloc4(2*numVerticesNew, &verticesNew, numVerticesNew, &verTagsNew, numVerticesNew, &corners, numVerticesNew, &requiredVer);CHKERRQ(ierr); 166*2bc0b47dSJoe Wallwork ierr = PetscMalloc3(3*numCellsNew, &cellsNew, numCellsNew, &cellTagsNew, numCellsNew, &requiredCells);CHKERRQ(ierr); 167*2bc0b47dSJoe Wallwork ierr = PetscMalloc4(2*numFacesNew, &facesNew, numFacesNew, &faceTagsNew, numFacesNew, &ridges, numFacesNew, &requiredFaces);CHKERRQ(ierr); 168*2bc0b47dSJoe Wallwork ierr = MMG2D_Get_vertices(mmg_mesh, verticesNew, verTagsNew, corners, requiredVer); 169*2bc0b47dSJoe Wallwork ierr = MMG2D_Get_triangles(mmg_mesh, cellsNew, cellTagsNew, requiredCells); 170*2bc0b47dSJoe Wallwork ierr = MMG2D_Get_edges(mmg_mesh, facesNew, faceTagsNew, ridges, requiredFaces); 171*2bc0b47dSJoe Wallwork break; 172*2bc0b47dSJoe Wallwork case 3: 173*2bc0b47dSJoe Wallwork numCornersNew = 4; 174*2bc0b47dSJoe Wallwork ierr = MMG3D_Get_meshSize(mmg_mesh, &numVerticesNew, &numCellsNew, 0, &numFacesNew, 0, 0); 175*2bc0b47dSJoe Wallwork ierr = PetscMalloc4(3*numVerticesNew, &verticesNew, numVerticesNew, &verTagsNew, numVerticesNew, &corners, numVerticesNew, &requiredVer);CHKERRQ(ierr); 176*2bc0b47dSJoe Wallwork ierr = PetscMalloc3(4*numCellsNew, &cellsNew, numCellsNew, &cellTagsNew, numCellsNew, &requiredCells);CHKERRQ(ierr); 177*2bc0b47dSJoe Wallwork ierr = PetscMalloc4(3*numFacesNew, &facesNew, numFacesNew, &faceTagsNew, numFacesNew, &ridges, numFacesNew, &requiredFaces);CHKERRQ(ierr); 178*2bc0b47dSJoe Wallwork ierr = MMG3D_Get_vertices(mmg_mesh, verticesNew, verTagsNew, corners, requiredVer); 179*2bc0b47dSJoe Wallwork ierr = MMG3D_Get_tetrahedra(mmg_mesh, cellsNew, cellTagsNew, requiredCells); 180*2bc0b47dSJoe Wallwork ierr = MMG3D_Get_triangles(mmg_mesh, facesNew, faceTagsNew, requiredFaces); 181*2bc0b47dSJoe Wallwork break; 182*2bc0b47dSJoe Wallwork default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No Mmg adaptation defined for dimension %D", dim); 183*2bc0b47dSJoe Wallwork } 184*2bc0b47dSJoe Wallwork for (i = 0; i < (dim+1)*numCellsNew; i++) cellsNew[i] -= 1; 185*2bc0b47dSJoe Wallwork for (i = 0; i < dim*numFacesNew; i++) facesNew[i] -= 1; 186*2bc0b47dSJoe Wallwork ierr = DMPlexCreateFromCellListParallelPetsc(comm, dim, numCellsNew, numVerticesNew, PETSC_DECIDE, numCornersNew, PETSC_TRUE, cellsNew, dim, verticesNew, NULL, NULL, dmNew);CHKERRQ(ierr); 187*2bc0b47dSJoe Wallwork switch (dim) { 188*2bc0b47dSJoe Wallwork case 2: 189*2bc0b47dSJoe Wallwork ierr = MMG2D_Free_all(MMG5_ARG_start, MMG5_ARG_ppMesh, &mmg_mesh, MMG5_ARG_ppMet, &mmg_metric, MMG5_ARG_end); 190*2bc0b47dSJoe Wallwork break; 191*2bc0b47dSJoe Wallwork case 3: 192*2bc0b47dSJoe Wallwork ierr = MMG3D_Free_all(MMG5_ARG_start, MMG5_ARG_ppMesh, &mmg_mesh, MMG5_ARG_ppMet, &mmg_metric, MMG5_ARG_end); 193*2bc0b47dSJoe Wallwork break; 194*2bc0b47dSJoe Wallwork default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No Mmg adaptation defined for dimension %D", dim); 195*2bc0b47dSJoe Wallwork } 196*2bc0b47dSJoe Wallwork 197*2bc0b47dSJoe Wallwork /* Rebuild boundary labels */ 198*2bc0b47dSJoe Wallwork ierr = DMCreateLabel(*dmNew, bdLabel ? bdLabelName : bdName);CHKERRQ(ierr); 199*2bc0b47dSJoe Wallwork ierr = DMGetLabel(*dmNew, bdLabel ? bdLabelName : bdName, &bdLabelNew);CHKERRQ(ierr); 200*2bc0b47dSJoe Wallwork ierr = DMPlexGetHeightStratum(*dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 201*2bc0b47dSJoe Wallwork ierr = DMPlexGetDepthStratum(*dmNew, 0, &vStart, &vEnd);CHKERRQ(ierr); 202*2bc0b47dSJoe Wallwork for (i = 0; i < numFacesNew; i++) { 203*2bc0b47dSJoe Wallwork PetscInt numCoveredPoints, numFaces = 0, facePoints[3]; 204*2bc0b47dSJoe Wallwork const PetscInt *coveredPoints = NULL; 205*2bc0b47dSJoe Wallwork 206*2bc0b47dSJoe Wallwork for (j = 0; j < dim; ++j) facePoints[j] = facesNew[i*dim+j]+vStart; 207*2bc0b47dSJoe Wallwork ierr = DMPlexGetFullJoin(*dmNew, dim, facePoints, &numCoveredPoints, &coveredPoints);CHKERRQ(ierr); 208*2bc0b47dSJoe Wallwork for (j = 0; j < numCoveredPoints; ++j) { 209*2bc0b47dSJoe Wallwork if (coveredPoints[j] >= fStart && coveredPoints[j] < fEnd) { 210*2bc0b47dSJoe Wallwork numFaces++; 211*2bc0b47dSJoe Wallwork f = j; 212*2bc0b47dSJoe Wallwork } 213*2bc0b47dSJoe Wallwork } 214*2bc0b47dSJoe Wallwork if (numFaces != 1) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "%d vertices cannot define more than 1 facet (%d)", dim, numFaces); 215*2bc0b47dSJoe Wallwork ierr = DMLabelSetValue(bdLabelNew, coveredPoints[f], faceTagsNew[i]);CHKERRQ(ierr); 216*2bc0b47dSJoe Wallwork ierr = DMPlexRestoreJoin(*dmNew, dim, facePoints, &numCoveredPoints, &coveredPoints);CHKERRQ(ierr); 217*2bc0b47dSJoe Wallwork } 218*2bc0b47dSJoe Wallwork 219*2bc0b47dSJoe Wallwork /* Clean up */ 220*2bc0b47dSJoe Wallwork ierr = PetscFree(cells);CHKERRQ(ierr); 221*2bc0b47dSJoe Wallwork ierr = PetscFree2(metric, vertices);CHKERRQ(ierr); 222*2bc0b47dSJoe Wallwork ierr = PetscFree2(bdFaces, bdFaceIds);CHKERRQ(ierr); 223*2bc0b47dSJoe Wallwork ierr = PetscFree2(verTags, cellTags);CHKERRQ(ierr); 224*2bc0b47dSJoe Wallwork ierr = PetscFree4(verticesNew, verTagsNew, corners, requiredVer);CHKERRQ(ierr); 225*2bc0b47dSJoe Wallwork ierr = PetscFree3(cellsNew, cellTagsNew, requiredCells);CHKERRQ(ierr); 226*2bc0b47dSJoe Wallwork ierr = PetscFree4(facesNew, faceTagsNew, ridges, requiredFaces);CHKERRQ(ierr); 227*2bc0b47dSJoe Wallwork PetscFunctionReturn(0); 228*2bc0b47dSJoe Wallwork } 229