1 #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 3 #ifdef PETSC_HAVE_EGADS 4 #include <egads.h> 5 #include <egads_lite.h> 6 #endif 7 8 #if defined(PETSC_HAVE_TETGEN_TETLIBRARY_NEEDED) 9 #define TETLIBRARY 10 #endif 11 #if defined(__clang__) 12 #pragma clang diagnostic push 13 #pragma clang diagnostic ignored "-Wunused-parameter" 14 #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" 15 #elif defined(__GNUC__) || defined(__GNUG__) 16 #pragma GCC diagnostic push 17 #pragma GCC diagnostic ignored "-Wunused-parameter" 18 #endif 19 #include <tetgen.h> 20 #if defined(__clang__) 21 #pragma clang diagnostic pop 22 #elif defined(__GNUC__) || defined(__GNUG__) 23 #pragma GCC diagnostic pop 24 #endif 25 26 /* This is to fix the tetrahedron orientation from TetGen */ 27 static PetscErrorCode DMPlexInvertCells_Tetgen(PetscInt numCells, PetscInt numCorners, PetscInt cells[]) 28 { 29 PetscInt bound = numCells * numCorners, coff; 30 31 PetscFunctionBegin; 32 #define SWAP(a, b) \ 33 do { \ 34 PetscInt tmp = (a); \ 35 (a) = (b); \ 36 (b) = tmp; \ 37 } while (0) 38 for (coff = 0; coff < bound; coff += numCorners) SWAP(cells[coff], cells[coff + 1]); 39 #undef SWAP 40 PetscFunctionReturn(PETSC_SUCCESS); 41 } 42 43 PETSC_EXTERN PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 44 { 45 MPI_Comm comm; 46 const PetscInt dim = 3; 47 ::tetgenio in; 48 ::tetgenio out; 49 PetscContainer modelObj; 50 DMUniversalLabel universal; 51 PetscInt vStart, vEnd, v, eStart, eEnd, e, fStart, fEnd, f, defVal; 52 DMPlexInterpolatedFlag isInterpolated; 53 PetscMPIInt rank; 54 55 PetscFunctionBegin; 56 PetscCall(PetscObjectGetComm((PetscObject)boundary, &comm)); 57 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 58 PetscCall(DMPlexIsInterpolatedCollective(boundary, &isInterpolated)); 59 PetscCall(DMUniversalLabelCreate(boundary, &universal)); 60 PetscCall(DMLabelGetDefaultValue(universal->label, &defVal)); 61 62 PetscCall(DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd)); 63 in.numberofpoints = vEnd - vStart; 64 if (in.numberofpoints > 0) { 65 PetscSection coordSection; 66 Vec coordinates; 67 const PetscScalar *array; 68 69 in.pointlist = new double[in.numberofpoints * dim]; 70 in.pointmarkerlist = new int[in.numberofpoints]; 71 72 PetscCall(PetscArrayzero(in.pointmarkerlist, (size_t)in.numberofpoints)); 73 PetscCall(DMGetCoordinatesLocal(boundary, &coordinates)); 74 PetscCall(DMGetCoordinateSection(boundary, &coordSection)); 75 PetscCall(VecGetArrayRead(coordinates, &array)); 76 for (v = vStart; v < vEnd; ++v) { 77 const PetscInt idx = v - vStart; 78 PetscInt off, d, val; 79 80 PetscCall(PetscSectionGetOffset(coordSection, v, &off)); 81 for (d = 0; d < dim; ++d) in.pointlist[idx * dim + d] = PetscRealPart(array[off + d]); 82 PetscCall(DMLabelGetValue(universal->label, v, &val)); 83 if (val != defVal) in.pointmarkerlist[idx] = (int)val; 84 } 85 PetscCall(VecRestoreArrayRead(coordinates, &array)); 86 } 87 88 PetscCall(DMPlexGetHeightStratum(boundary, 1, &eStart, &eEnd)); 89 in.numberofedges = eEnd - eStart; 90 if (isInterpolated == DMPLEX_INTERPOLATED_FULL && in.numberofedges > 0) { 91 in.edgelist = new int[in.numberofedges * 2]; 92 in.edgemarkerlist = new int[in.numberofedges]; 93 for (e = eStart; e < eEnd; ++e) { 94 const PetscInt idx = e - eStart; 95 const PetscInt *cone; 96 PetscInt coneSize, val; 97 98 PetscCall(DMPlexGetConeSize(boundary, e, &coneSize)); 99 PetscCall(DMPlexGetCone(boundary, e, &cone)); 100 in.edgelist[idx * 2] = cone[0] - vStart; 101 in.edgelist[idx * 2 + 1] = cone[1] - vStart; 102 103 PetscCall(DMLabelGetValue(universal->label, e, &val)); 104 if (val != defVal) in.edgemarkerlist[idx] = (int)val; 105 } 106 } 107 108 PetscCall(DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd)); 109 in.numberoffacets = fEnd - fStart; 110 if (in.numberoffacets > 0) { 111 in.facetlist = new tetgenio::facet[in.numberoffacets]; 112 in.facetmarkerlist = new int[in.numberoffacets]; 113 for (f = fStart; f < fEnd; ++f) { 114 const PetscInt idx = f - fStart; 115 PetscInt *points = nullptr, numPoints, p, numVertices = 0, v, val = -1; 116 117 in.facetlist[idx].numberofpolygons = 1; 118 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 119 in.facetlist[idx].numberofholes = 0; 120 in.facetlist[idx].holelist = nullptr; 121 122 PetscCall(DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points)); 123 for (p = 0; p < numPoints * 2; p += 2) { 124 const PetscInt point = points[p]; 125 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 126 } 127 128 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 129 poly->numberofvertices = numVertices; 130 poly->vertexlist = new int[poly->numberofvertices]; 131 for (v = 0; v < numVertices; ++v) { 132 const PetscInt vIdx = points[v] - vStart; 133 poly->vertexlist[v] = vIdx; 134 } 135 PetscCall(DMLabelGetValue(universal->label, f, &val)); 136 if (val != defVal) in.facetmarkerlist[idx] = (int)val; 137 PetscCall(DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points)); 138 } 139 } 140 if (rank == 0) { 141 DM_Plex *mesh = (DM_Plex *)boundary->data; 142 char args[32]; 143 144 /* Take away 'Q' for verbose output */ 145 #ifdef PETSC_HAVE_EGADS 146 PetscCall(PetscStrncpy(args, "pYqezQY", sizeof(args))); 147 #else 148 PetscCall(PetscStrncpy(args, "pqezQ", sizeof(args))); 149 #endif 150 if (mesh->tetgenOpts) { 151 ::tetrahedralize(mesh->tetgenOpts, &in, &out); 152 } else { 153 ::tetrahedralize(args, &in, &out); 154 } 155 } 156 { 157 const PetscInt numCorners = 4; 158 const PetscInt numCells = out.numberoftetrahedra; 159 const PetscInt numVertices = out.numberofpoints; 160 PetscReal *meshCoords = nullptr; 161 PetscInt *cells = nullptr; 162 163 if (sizeof(PetscReal) == sizeof(out.pointlist[0])) { 164 meshCoords = (PetscReal *)out.pointlist; 165 } else { 166 PetscInt i; 167 168 meshCoords = new PetscReal[dim * numVertices]; 169 for (i = 0; i < dim * numVertices; ++i) meshCoords[i] = (PetscReal)out.pointlist[i]; 170 } 171 if (sizeof(PetscInt) == sizeof(out.tetrahedronlist[0])) { 172 cells = (PetscInt *)out.tetrahedronlist; 173 } else { 174 PetscInt i; 175 176 cells = new PetscInt[numCells * numCorners]; 177 for (i = 0; i < numCells * numCorners; i++) cells[i] = (PetscInt)out.tetrahedronlist[i]; 178 } 179 180 PetscCall(DMPlexInvertCells_Tetgen(numCells, numCorners, cells)); 181 PetscCall(DMPlexCreateFromCellListPetsc(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm)); 182 183 /* Set labels */ 184 PetscCall(DMUniversalLabelCreateLabels(universal, PETSC_TRUE, *dm)); 185 for (v = 0; v < numVertices; ++v) { 186 if (out.pointmarkerlist[v]) PetscCall(DMUniversalLabelSetLabelValue(universal, *dm, PETSC_TRUE, v + numCells, out.pointmarkerlist[v])); 187 } 188 if (interpolate) { 189 PetscInt e; 190 191 for (e = 0; e < out.numberofedges; e++) { 192 if (out.edgemarkerlist[e]) { 193 const PetscInt vertices[2] = {out.edgelist[e * 2 + 0] + numCells, out.edgelist[e * 2 + 1] + numCells}; 194 const PetscInt *edges; 195 PetscInt numEdges; 196 197 PetscCall(DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges)); 198 PetscCheck(numEdges == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %" PetscInt_FMT, numEdges); 199 PetscCall(DMUniversalLabelSetLabelValue(universal, *dm, PETSC_TRUE, edges[0], out.edgemarkerlist[e])); 200 PetscCall(DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges)); 201 } 202 } 203 for (f = 0; f < out.numberoftrifaces; f++) { 204 if (out.trifacemarkerlist[f]) { 205 const PetscInt vertices[3] = {out.trifacelist[f * 3 + 0] + numCells, out.trifacelist[f * 3 + 1] + numCells, out.trifacelist[f * 3 + 2] + numCells}; 206 const PetscInt *faces; 207 PetscInt numFaces; 208 209 PetscCall(DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces)); 210 PetscCheck(numFaces == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %" PetscInt_FMT, numFaces); 211 PetscCall(DMUniversalLabelSetLabelValue(universal, *dm, PETSC_TRUE, faces[0], out.trifacemarkerlist[f])); 212 PetscCall(DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces)); 213 } 214 } 215 } 216 217 PetscCall(PetscObjectQuery((PetscObject)boundary, "EGADS Model", (PetscObject *)&modelObj)); 218 if (!modelObj) { PetscCall(PetscObjectQuery((PetscObject)boundary, "EGADSlite Model", (PetscObject *)&modelObj)); } 219 220 if (modelObj) { 221 #ifdef PETSC_HAVE_EGADS 222 DMLabel bodyLabel; 223 PetscInt cStart, cEnd, c, eStart, eEnd, fStart, fEnd; 224 PetscBool islite = PETSC_FALSE; 225 ego *bodies; 226 ego model, geom; 227 int Nb, oclass, mtype, *senses; 228 229 PetscCall(DMPlexCopyEGADSInfo_Internal(boundary, *dm)); 230 231 // Get Attached EGADS Model from Original DMPlex 232 PetscCall(PetscObjectQuery((PetscObject)boundary, "EGADS Model", (PetscObject *)&modelObj)); 233 if (modelObj) { 234 PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 235 PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, nullptr, &Nb, &bodies, &senses)); 236 } else { 237 PetscCall(PetscObjectQuery((PetscObject)boundary, "EGADSlite Model", (PetscObject *)&modelObj)); 238 if (modelObj) { 239 PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 240 PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, nullptr, &Nb, &bodies, &senses)); 241 islite = PETSC_TRUE; 242 } 243 } 244 if (!modelObj) goto skip_egads; 245 246 /* Set Cell Labels */ 247 PetscCall(DMGetLabel(*dm, "EGADS Body ID", &bodyLabel)); 248 PetscCall(DMPlexGetHeightStratum(*dm, 0, &cStart, &cEnd)); 249 PetscCall(DMPlexGetHeightStratum(*dm, 1, &fStart, &fEnd)); 250 PetscCall(DMPlexGetDepthStratum(*dm, 1, &eStart, &eEnd)); 251 252 for (c = cStart; c < cEnd; ++c) { 253 PetscReal centroid[3] = {0., 0., 0.}; 254 PetscInt b; 255 256 /* Determine what body the cell's centroid is located in */ 257 if (!interpolate) { 258 PetscSection coordSection; 259 Vec coordinates; 260 PetscScalar *coords = nullptr; 261 PetscInt coordSize, s, d; 262 263 PetscCall(DMGetCoordinatesLocal(*dm, &coordinates)); 264 PetscCall(DMGetCoordinateSection(*dm, &coordSection)); 265 PetscCall(DMPlexVecGetClosure(*dm, coordSection, coordinates, c, &coordSize, &coords)); 266 for (s = 0; s < coordSize; ++s) 267 for (d = 0; d < dim; ++d) centroid[d] += coords[s * dim + d]; 268 PetscCall(DMPlexVecRestoreClosure(*dm, coordSection, coordinates, c, &coordSize, &coords)); 269 } else PetscCall(DMPlexComputeCellGeometryFVM(*dm, c, nullptr, centroid, nullptr)); 270 for (b = 0; b < Nb; ++b) { 271 if (islite) { 272 if (EGlite_inTopology(bodies[b], centroid) == EGADS_SUCCESS) break; 273 } else { 274 if (EG_inTopology(bodies[b], centroid) == EGADS_SUCCESS) break; 275 } 276 } 277 if (b < Nb) { 278 PetscInt cval = b, eVal, fVal; 279 PetscInt *closure = nullptr, Ncl, cl; 280 281 PetscCall(DMLabelSetValue(bodyLabel, c, cval)); 282 PetscCall(DMPlexGetTransitiveClosure(*dm, c, PETSC_TRUE, &Ncl, &closure)); 283 for (cl = 0; cl < Ncl; cl += 2) { 284 const PetscInt p = closure[cl]; 285 286 if (p >= eStart && p < eEnd) { 287 PetscCall(DMLabelGetValue(bodyLabel, p, &eVal)); 288 if (eVal < 0) PetscCall(DMLabelSetValue(bodyLabel, p, cval)); 289 } 290 if (p >= fStart && p < fEnd) { 291 PetscCall(DMLabelGetValue(bodyLabel, p, &fVal)); 292 if (fVal < 0) PetscCall(DMLabelSetValue(bodyLabel, p, cval)); 293 } 294 } 295 PetscCall(DMPlexRestoreTransitiveClosure(*dm, c, PETSC_TRUE, &Ncl, &closure)); 296 } 297 } 298 skip_egads:; 299 #endif 300 } 301 PetscCall(DMPlexSetRefinementUniform(*dm, PETSC_FALSE)); 302 } 303 PetscCall(DMUniversalLabelDestroy(&universal)); 304 PetscFunctionReturn(PETSC_SUCCESS); 305 } 306 307 PETSC_EXTERN PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 308 { 309 MPI_Comm comm; 310 const PetscInt dim = 3; 311 ::tetgenio in; 312 ::tetgenio out; 313 PetscContainer modelObj; 314 DMUniversalLabel universal; 315 PetscInt vStart, vEnd, v, eStart, eEnd, e, fStart, fEnd, f, cStart, cEnd, c, defVal; 316 DMPlexInterpolatedFlag isInterpolated; 317 PetscMPIInt rank; 318 319 PetscFunctionBegin; 320 PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 321 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 322 PetscCall(DMPlexIsInterpolatedCollective(dm, &isInterpolated)); 323 PetscCall(DMUniversalLabelCreate(dm, &universal)); 324 PetscCall(DMLabelGetDefaultValue(universal->label, &defVal)); 325 326 PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 327 in.numberofpoints = vEnd - vStart; 328 if (in.numberofpoints > 0) { 329 PetscSection coordSection; 330 Vec coordinates; 331 PetscScalar *array; 332 333 in.pointlist = new double[in.numberofpoints * dim]; 334 in.pointmarkerlist = new int[in.numberofpoints]; 335 336 PetscCall(PetscArrayzero(in.pointmarkerlist, (size_t)in.numberofpoints)); 337 PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 338 PetscCall(DMGetCoordinateSection(dm, &coordSection)); 339 PetscCall(VecGetArray(coordinates, &array)); 340 for (v = vStart; v < vEnd; ++v) { 341 const PetscInt idx = v - vStart; 342 PetscInt off, d, val; 343 344 PetscCall(PetscSectionGetOffset(coordSection, v, &off)); 345 for (d = 0; d < dim; ++d) in.pointlist[idx * dim + d] = PetscRealPart(array[off + d]); 346 PetscCall(DMLabelGetValue(universal->label, v, &val)); 347 if (val != defVal) in.pointmarkerlist[idx] = (int)val; 348 } 349 PetscCall(VecRestoreArray(coordinates, &array)); 350 } 351 352 PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd)); 353 in.numberofedges = eEnd - eStart; 354 if (isInterpolated == DMPLEX_INTERPOLATED_FULL && in.numberofedges > 0) { 355 in.edgelist = new int[in.numberofedges * 2]; 356 in.edgemarkerlist = new int[in.numberofedges]; 357 for (e = eStart; e < eEnd; ++e) { 358 const PetscInt idx = e - eStart; 359 const PetscInt *cone; 360 PetscInt coneSize, val; 361 362 PetscCall(DMPlexGetConeSize(dm, e, &coneSize)); 363 PetscCall(DMPlexGetCone(dm, e, &cone)); 364 in.edgelist[idx * 2] = cone[0] - vStart; 365 in.edgelist[idx * 2 + 1] = cone[1] - vStart; 366 367 PetscCall(DMLabelGetValue(universal->label, e, &val)); 368 if (val != defVal) in.edgemarkerlist[idx] = (int)val; 369 } 370 } 371 372 PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 373 in.numberoffacets = fEnd - fStart; 374 if (isInterpolated == DMPLEX_INTERPOLATED_FULL && in.numberoffacets > 0) { 375 in.facetlist = new tetgenio::facet[in.numberoffacets]; 376 in.facetmarkerlist = new int[in.numberoffacets]; 377 for (f = fStart; f < fEnd; ++f) { 378 const PetscInt idx = f - fStart; 379 PetscInt *points = nullptr, numPoints, p, numVertices = 0, v, val; 380 381 in.facetlist[idx].numberofpolygons = 1; 382 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 383 in.facetlist[idx].numberofholes = 0; 384 in.facetlist[idx].holelist = nullptr; 385 386 PetscCall(DMPlexGetTransitiveClosure(dm, f, PETSC_TRUE, &numPoints, &points)); 387 for (p = 0; p < numPoints * 2; p += 2) { 388 const PetscInt point = points[p]; 389 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 390 } 391 392 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 393 poly->numberofvertices = numVertices; 394 poly->vertexlist = new int[poly->numberofvertices]; 395 for (v = 0; v < numVertices; ++v) { 396 const PetscInt vIdx = points[v] - vStart; 397 poly->vertexlist[v] = vIdx; 398 } 399 400 PetscCall(DMLabelGetValue(universal->label, f, &val)); 401 if (val != defVal) in.facetmarkerlist[idx] = (int)val; 402 403 PetscCall(DMPlexRestoreTransitiveClosure(dm, f, PETSC_TRUE, &numPoints, &points)); 404 } 405 } 406 407 PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 408 in.numberofcorners = 4; 409 in.numberoftetrahedra = cEnd - cStart; 410 in.tetrahedronvolumelist = (double *)maxVolumes; 411 if (in.numberoftetrahedra > 0) { 412 in.tetrahedronlist = new int[in.numberoftetrahedra * in.numberofcorners]; 413 for (c = cStart; c < cEnd; ++c) { 414 const PetscInt idx = c - cStart; 415 PetscInt *closure = nullptr; 416 PetscInt closureSize; 417 418 PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 419 PetscCheck(!(closureSize != 5) || !(closureSize != 15), comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %" PetscInt_FMT " vertices in closure", closureSize); 420 for (v = 0; v < 4; ++v) in.tetrahedronlist[idx * in.numberofcorners + v] = closure[(v + closureSize - 4) * 2] - vStart; 421 PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure)); 422 } 423 } 424 425 if (rank == 0) { 426 char args[32]; 427 428 /* Take away 'Q' for verbose output */ 429 PetscCall(PetscStrncpy(args, "qezQra", sizeof(args))); 430 ::tetrahedralize(args, &in, &out); 431 } 432 433 in.tetrahedronvolumelist = nullptr; 434 { 435 const PetscInt numCorners = 4; 436 const PetscInt numCells = out.numberoftetrahedra; 437 const PetscInt numVertices = out.numberofpoints; 438 PetscReal *meshCoords = nullptr; 439 PetscInt *cells = nullptr; 440 PetscBool interpolate = isInterpolated == DMPLEX_INTERPOLATED_FULL ? PETSC_TRUE : PETSC_FALSE; 441 442 if (sizeof(PetscReal) == sizeof(out.pointlist[0])) { 443 meshCoords = (PetscReal *)out.pointlist; 444 } else { 445 PetscInt i; 446 447 meshCoords = new PetscReal[dim * numVertices]; 448 for (i = 0; i < dim * numVertices; ++i) meshCoords[i] = (PetscReal)out.pointlist[i]; 449 } 450 if (sizeof(PetscInt) == sizeof(out.tetrahedronlist[0])) { 451 cells = (PetscInt *)out.tetrahedronlist; 452 } else { 453 PetscInt i; 454 455 cells = new PetscInt[numCells * numCorners]; 456 for (i = 0; i < numCells * numCorners; ++i) cells[i] = (PetscInt)out.tetrahedronlist[i]; 457 } 458 459 PetscCall(DMPlexInvertCells_Tetgen(numCells, numCorners, cells)); 460 PetscCall(DMPlexCreateFromCellListPetsc(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined)); 461 if (sizeof(PetscReal) != sizeof(out.pointlist[0])) delete[] meshCoords; 462 if (sizeof(PetscInt) != sizeof(out.tetrahedronlist[0])) delete[] cells; 463 464 /* Set labels */ 465 PetscCall(DMUniversalLabelCreateLabels(universal, PETSC_TRUE, *dmRefined)); 466 for (v = 0; v < numVertices; ++v) { 467 if (out.pointmarkerlist[v]) PetscCall(DMUniversalLabelSetLabelValue(universal, *dmRefined, PETSC_TRUE, v + numCells, out.pointmarkerlist[v])); 468 } 469 if (interpolate) { 470 PetscInt e, f; 471 472 for (e = 0; e < out.numberofedges; ++e) { 473 if (out.edgemarkerlist[e]) { 474 const PetscInt vertices[2] = {out.edgelist[e * 2 + 0] + numCells, out.edgelist[e * 2 + 1] + numCells}; 475 const PetscInt *edges; 476 PetscInt numEdges; 477 478 PetscCall(DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges)); 479 PetscCheck(numEdges == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %" PetscInt_FMT, numEdges); 480 PetscCall(DMUniversalLabelSetLabelValue(universal, *dmRefined, PETSC_TRUE, edges[0], out.edgemarkerlist[e])); 481 PetscCall(DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges)); 482 } 483 } 484 for (f = 0; f < out.numberoftrifaces; ++f) { 485 if (out.trifacemarkerlist[f]) { 486 const PetscInt vertices[3] = {out.trifacelist[f * 3 + 0] + numCells, out.trifacelist[f * 3 + 1] + numCells, out.trifacelist[f * 3 + 2] + numCells}; 487 const PetscInt *faces; 488 PetscInt numFaces; 489 490 PetscCall(DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces)); 491 PetscCheck(numFaces == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %" PetscInt_FMT, numFaces); 492 PetscCall(DMUniversalLabelSetLabelValue(universal, *dmRefined, PETSC_TRUE, faces[0], out.trifacemarkerlist[f])); 493 PetscCall(DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces)); 494 } 495 } 496 } 497 498 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 499 if (modelObj) { 500 #ifdef PETSC_HAVE_EGADS 501 DMLabel bodyLabel; 502 PetscInt cStart, cEnd, c, eStart, eEnd, fStart, fEnd; 503 PetscBool islite = PETSC_FALSE; 504 ego *bodies; 505 ego model, geom; 506 int Nb, oclass, mtype, *senses; 507 508 PetscCall(DMPlexCopyEGADSInfo_Internal(dm, *dmRefined)); 509 510 /* Get Attached EGADS Model from Original DMPlex */ 511 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 512 if (modelObj) { 513 PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 514 PetscCall(EG_getTopology(model, &geom, &oclass, &mtype, nullptr, &Nb, &bodies, &senses)); 515 } else { 516 PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 517 if (modelObj) { 518 PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 519 PetscCall(EGlite_getTopology(model, &geom, &oclass, &mtype, nullptr, &Nb, &bodies, &senses)); 520 islite = PETSC_TRUE; 521 } 522 } 523 if (!modelObj) goto skip_egads; 524 525 /* Set Cell Labels */ 526 PetscCall(DMGetLabel(*dmRefined, "EGADS Body ID", &bodyLabel)); 527 PetscCall(DMPlexGetHeightStratum(*dmRefined, 0, &cStart, &cEnd)); 528 PetscCall(DMPlexGetHeightStratum(*dmRefined, 1, &fStart, &fEnd)); 529 PetscCall(DMPlexGetDepthStratum(*dmRefined, 1, &eStart, &eEnd)); 530 531 for (c = cStart; c < cEnd; ++c) { 532 PetscReal centroid[3] = {0., 0., 0.}; 533 PetscInt b; 534 535 /* Determine what body the cell's centroid is located in */ 536 if (!interpolate) { 537 PetscSection coordSection; 538 Vec coordinates; 539 PetscScalar *coords = nullptr; 540 PetscInt coordSize, s, d; 541 542 PetscCall(DMGetCoordinatesLocal(*dmRefined, &coordinates)); 543 PetscCall(DMGetCoordinateSection(*dmRefined, &coordSection)); 544 PetscCall(DMPlexVecGetClosure(*dmRefined, coordSection, coordinates, c, &coordSize, &coords)); 545 for (s = 0; s < coordSize; ++s) 546 for (d = 0; d < dim; ++d) centroid[d] += coords[s * dim + d]; 547 PetscCall(DMPlexVecRestoreClosure(*dmRefined, coordSection, coordinates, c, &coordSize, &coords)); 548 } else PetscCall(DMPlexComputeCellGeometryFVM(*dmRefined, c, nullptr, centroid, nullptr)); 549 for (b = 0; b < Nb; ++b) { 550 if (islite) { 551 if (EGlite_inTopology(bodies[b], centroid) == EGADS_SUCCESS) break; 552 } else { 553 if (EG_inTopology(bodies[b], centroid) == EGADS_SUCCESS) break; 554 } 555 } 556 if (b < Nb) { 557 PetscInt cval = b, eVal, fVal; 558 PetscInt *closure = nullptr, Ncl, cl; 559 560 PetscCall(DMLabelSetValue(bodyLabel, c, cval)); 561 PetscCall(DMPlexGetTransitiveClosure(*dmRefined, c, PETSC_TRUE, &Ncl, &closure)); 562 for (cl = 0; cl < Ncl; cl += 2) { 563 const PetscInt p = closure[cl]; 564 565 if (p >= eStart && p < eEnd) { 566 PetscCall(DMLabelGetValue(bodyLabel, p, &eVal)); 567 if (eVal < 0) PetscCall(DMLabelSetValue(bodyLabel, p, cval)); 568 } 569 if (p >= fStart && p < fEnd) { 570 PetscCall(DMLabelGetValue(bodyLabel, p, &fVal)); 571 if (fVal < 0) PetscCall(DMLabelSetValue(bodyLabel, p, cval)); 572 } 573 } 574 PetscCall(DMPlexRestoreTransitiveClosure(*dmRefined, c, PETSC_TRUE, &Ncl, &closure)); 575 } 576 } 577 skip_egads:; 578 #endif 579 } 580 PetscCall(DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE)); 581 } 582 PetscFunctionReturn(PETSC_SUCCESS); 583 } 584