1 #include <petsc-private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 3 #undef __FUNCT__ 4 #define __FUNCT__ "DMPlexInvertCell_Internal" 5 PetscErrorCode DMPlexInvertCell_Internal(PetscInt dim, PetscInt numCorners, PetscInt cone[]) 6 { 7 int tmpc; 8 9 PetscFunctionBegin; 10 if (dim != 3) PetscFunctionReturn(0); 11 switch (numCorners) { 12 case 4: 13 tmpc = cone[0]; 14 cone[0] = cone[1]; 15 cone[1] = tmpc; 16 break; 17 case 8: 18 tmpc = cone[1]; 19 cone[1] = cone[3]; 20 cone[3] = tmpc; 21 break; 22 default: break; 23 } 24 PetscFunctionReturn(0); 25 } 26 27 #undef __FUNCT__ 28 #define __FUNCT__ "DMPlexInvertCell" 29 /*@C 30 DMPlexInvertCell - This flips tetrahedron and hexahedron orientation since Plex stores them internally with outward normals. Other cells are left untouched. 31 32 Input Parameters: 33 + numCorners - The number of vertices in a cell 34 - cone - The incoming cone 35 36 Output Parameter: 37 . cone - The inverted cone (in-place) 38 39 Level: developer 40 41 .seealso: DMPlexGenerate() 42 @*/ 43 PetscErrorCode DMPlexInvertCell(PetscInt dim, PetscInt numCorners, int cone[]) 44 { 45 int tmpc; 46 47 PetscFunctionBegin; 48 if (dim != 3) PetscFunctionReturn(0); 49 switch (numCorners) { 50 case 4: 51 tmpc = cone[0]; 52 cone[0] = cone[1]; 53 cone[1] = tmpc; 54 break; 55 case 8: 56 tmpc = cone[1]; 57 cone[1] = cone[3]; 58 cone[3] = tmpc; 59 break; 60 default: break; 61 } 62 PetscFunctionReturn(0); 63 } 64 65 #undef __FUNCT__ 66 #define __FUNCT__ "DMPlexInvertCells_Internal" 67 /* This is to fix the tetrahedron orientation from TetGen */ 68 PETSC_UNUSED static PetscErrorCode DMPlexInvertCells_Internal(PetscInt dim, PetscInt numCells, PetscInt numCorners, int cells[]) 69 { 70 PetscInt bound = numCells*numCorners, coff; 71 PetscErrorCode ierr; 72 73 PetscFunctionBegin; 74 for (coff = 0; coff < bound; coff += numCorners) { 75 ierr = DMPlexInvertCell(dim, numCorners, &cells[coff]);CHKERRQ(ierr); 76 } 77 PetscFunctionReturn(0); 78 } 79 80 #undef __FUNCT__ 81 #define __FUNCT__ "DMPlexTriangleSetOptions" 82 /*@ 83 DMPlexTriangleSetOptions - Set the options used for the Triangle mesh generator 84 85 Not Collective 86 87 Inputs Parameters: 88 + dm - The DMPlex object 89 - opts - The command line options 90 91 Level: developer 92 93 .keywords: mesh, points 94 .seealso: DMPlexTetgenSetOptions(), DMPlexGenerate() 95 @*/ 96 PetscErrorCode DMPlexTriangleSetOptions(DM dm, const char *opts) 97 { 98 DM_Plex *mesh = (DM_Plex*) dm->data; 99 PetscErrorCode ierr; 100 101 PetscFunctionBegin; 102 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 103 PetscValidPointer(opts, 2); 104 ierr = PetscFree(mesh->triangleOpts);CHKERRQ(ierr); 105 ierr = PetscStrallocpy(opts, &mesh->triangleOpts);CHKERRQ(ierr); 106 PetscFunctionReturn(0); 107 } 108 109 #undef __FUNCT__ 110 #define __FUNCT__ "DMPlexTetgenSetOptions" 111 /*@ 112 DMPlexTetgenSetOptions - Set the options used for the Tetgen mesh generator 113 114 Not Collective 115 116 Inputs Parameters: 117 + dm - The DMPlex object 118 - opts - The command line options 119 120 Level: developer 121 122 .keywords: mesh, points 123 .seealso: DMPlexTriangleSetOptions(), DMPlexGenerate() 124 @*/ 125 PetscErrorCode DMPlexTetgenSetOptions(DM dm, const char *opts) 126 { 127 DM_Plex *mesh = (DM_Plex*) dm->data; 128 PetscErrorCode ierr; 129 130 PetscFunctionBegin; 131 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 132 PetscValidPointer(opts, 2); 133 ierr = PetscFree(mesh->tetgenOpts);CHKERRQ(ierr); 134 ierr = PetscStrallocpy(opts, &mesh->tetgenOpts);CHKERRQ(ierr); 135 PetscFunctionReturn(0); 136 } 137 138 #if defined(PETSC_HAVE_TRIANGLE) 139 #include <triangle.h> 140 141 #undef __FUNCT__ 142 #define __FUNCT__ "InitInput_Triangle" 143 PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) 144 { 145 PetscFunctionBegin; 146 inputCtx->numberofpoints = 0; 147 inputCtx->numberofpointattributes = 0; 148 inputCtx->pointlist = NULL; 149 inputCtx->pointattributelist = NULL; 150 inputCtx->pointmarkerlist = NULL; 151 inputCtx->numberofsegments = 0; 152 inputCtx->segmentlist = NULL; 153 inputCtx->segmentmarkerlist = NULL; 154 inputCtx->numberoftriangleattributes = 0; 155 inputCtx->trianglelist = NULL; 156 inputCtx->numberofholes = 0; 157 inputCtx->holelist = NULL; 158 inputCtx->numberofregions = 0; 159 inputCtx->regionlist = NULL; 160 PetscFunctionReturn(0); 161 } 162 163 #undef __FUNCT__ 164 #define __FUNCT__ "InitOutput_Triangle" 165 PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) 166 { 167 PetscFunctionBegin; 168 outputCtx->numberofpoints = 0; 169 outputCtx->pointlist = NULL; 170 outputCtx->pointattributelist = NULL; 171 outputCtx->pointmarkerlist = NULL; 172 outputCtx->numberoftriangles = 0; 173 outputCtx->trianglelist = NULL; 174 outputCtx->triangleattributelist = NULL; 175 outputCtx->neighborlist = NULL; 176 outputCtx->segmentlist = NULL; 177 outputCtx->segmentmarkerlist = NULL; 178 outputCtx->numberofedges = 0; 179 outputCtx->edgelist = NULL; 180 outputCtx->edgemarkerlist = NULL; 181 PetscFunctionReturn(0); 182 } 183 184 #undef __FUNCT__ 185 #define __FUNCT__ "FiniOutput_Triangle" 186 PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) 187 { 188 PetscFunctionBegin; 189 free(outputCtx->pointlist); 190 free(outputCtx->pointmarkerlist); 191 free(outputCtx->segmentlist); 192 free(outputCtx->segmentmarkerlist); 193 free(outputCtx->edgelist); 194 free(outputCtx->edgemarkerlist); 195 free(outputCtx->trianglelist); 196 free(outputCtx->neighborlist); 197 PetscFunctionReturn(0); 198 } 199 200 #undef __FUNCT__ 201 #define __FUNCT__ "DMPlexGenerate_Triangle" 202 PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 203 { 204 MPI_Comm comm; 205 DM_Plex *mesh = (DM_Plex *) boundary->data; 206 PetscInt dim = 2; 207 const PetscBool createConvexHull = PETSC_FALSE; 208 const PetscBool constrained = PETSC_FALSE; 209 const char *labelName = "marker"; 210 struct triangulateio in; 211 struct triangulateio out; 212 DMLabel label; 213 PetscInt vStart, vEnd, v, eStart, eEnd, e; 214 PetscMPIInt rank; 215 PetscErrorCode ierr; 216 217 PetscFunctionBegin; 218 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 219 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 220 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 221 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 222 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 223 ierr = DMPlexGetLabel(boundary, labelName, &label);CHKERRQ(ierr); 224 225 in.numberofpoints = vEnd - vStart; 226 if (in.numberofpoints > 0) { 227 PetscSection coordSection; 228 Vec coordinates; 229 PetscScalar *array; 230 231 ierr = PetscMalloc1(in.numberofpoints*dim, &in.pointlist);CHKERRQ(ierr); 232 ierr = PetscMalloc1(in.numberofpoints, &in.pointmarkerlist);CHKERRQ(ierr); 233 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 234 ierr = DMGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 235 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 236 for (v = vStart; v < vEnd; ++v) { 237 const PetscInt idx = v - vStart; 238 PetscInt off, d; 239 240 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 241 for (d = 0; d < dim; ++d) { 242 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 243 } 244 if (label) {ierr = DMLabelGetValue(label, v, &in.pointmarkerlist[idx]);CHKERRQ(ierr);} 245 } 246 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 247 } 248 ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 249 in.numberofsegments = eEnd - eStart; 250 if (in.numberofsegments > 0) { 251 ierr = PetscMalloc1(in.numberofsegments*2, &in.segmentlist);CHKERRQ(ierr); 252 ierr = PetscMalloc1(in.numberofsegments, &in.segmentmarkerlist);CHKERRQ(ierr); 253 for (e = eStart; e < eEnd; ++e) { 254 const PetscInt idx = e - eStart; 255 const PetscInt *cone; 256 257 ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 258 259 in.segmentlist[idx*2+0] = cone[0] - vStart; 260 in.segmentlist[idx*2+1] = cone[1] - vStart; 261 262 if (label) {ierr = DMLabelGetValue(label, e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr);} 263 } 264 } 265 #if 0 /* Do not currently support holes */ 266 PetscReal *holeCoords; 267 PetscInt h, d; 268 269 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 270 if (in.numberofholes > 0) { 271 ierr = PetscMalloc1(in.numberofholes*dim, &in.holelist);CHKERRQ(ierr); 272 for (h = 0; h < in.numberofholes; ++h) { 273 for (d = 0; d < dim; ++d) { 274 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 275 } 276 } 277 } 278 #endif 279 if (!rank) { 280 char args[32]; 281 282 /* Take away 'Q' for verbose output */ 283 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 284 if (createConvexHull) {ierr = PetscStrcat(args, "c");CHKERRQ(ierr);} 285 if (constrained) {ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr);} 286 if (mesh->triangleOpts) {triangulate(mesh->triangleOpts, &in, &out, NULL);} 287 else {triangulate(args, &in, &out, NULL);} 288 } 289 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 290 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 291 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 292 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 293 ierr = PetscFree(in.holelist);CHKERRQ(ierr); 294 295 { 296 DMLabel glabel = NULL; 297 const PetscInt numCorners = 3; 298 const PetscInt numCells = out.numberoftriangles; 299 const PetscInt numVertices = out.numberofpoints; 300 const int *cells = out.trianglelist; 301 const double *meshCoords = out.pointlist; 302 303 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 304 if (label) {ierr = DMPlexCreateLabel(*dm, labelName); ierr = DMPlexGetLabel(*dm, labelName, &glabel);} 305 /* Set labels */ 306 for (v = 0; v < numVertices; ++v) { 307 if (out.pointmarkerlist[v]) { 308 if (glabel) {ierr = DMLabelSetValue(glabel, v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr);} 309 } 310 } 311 if (interpolate) { 312 for (e = 0; e < out.numberofedges; e++) { 313 if (out.edgemarkerlist[e]) { 314 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 315 const PetscInt *edges; 316 PetscInt numEdges; 317 318 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 319 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 320 if (glabel) {ierr = DMLabelSetValue(glabel, edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr);} 321 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 322 } 323 } 324 } 325 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 326 } 327 #if 0 /* Do not currently support holes */ 328 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 329 #endif 330 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 331 PetscFunctionReturn(0); 332 } 333 334 #undef __FUNCT__ 335 #define __FUNCT__ "DMPlexRefine_Triangle" 336 PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 337 { 338 MPI_Comm comm; 339 PetscInt dim = 2; 340 const char *labelName = "marker"; 341 struct triangulateio in; 342 struct triangulateio out; 343 DMLabel label; 344 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 345 PetscMPIInt rank; 346 PetscErrorCode ierr; 347 348 PetscFunctionBegin; 349 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 350 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 351 ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 352 ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 353 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 354 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 355 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 356 ierr = DMPlexGetLabel(dm, labelName, &label);CHKERRQ(ierr); 357 358 in.numberofpoints = vEnd - vStart; 359 if (in.numberofpoints > 0) { 360 PetscSection coordSection; 361 Vec coordinates; 362 PetscScalar *array; 363 364 ierr = PetscMalloc1(in.numberofpoints*dim, &in.pointlist);CHKERRQ(ierr); 365 ierr = PetscMalloc1(in.numberofpoints, &in.pointmarkerlist);CHKERRQ(ierr); 366 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 367 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 368 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 369 for (v = vStart; v < vEnd; ++v) { 370 const PetscInt idx = v - vStart; 371 PetscInt off, d; 372 373 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 374 for (d = 0; d < dim; ++d) { 375 in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 376 } 377 if (label) {ierr = DMLabelGetValue(label, v, &in.pointmarkerlist[idx]);CHKERRQ(ierr);} 378 } 379 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 380 } 381 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 382 383 in.numberofcorners = 3; 384 in.numberoftriangles = cEnd - cStart; 385 386 in.trianglearealist = (double*) maxVolumes; 387 if (in.numberoftriangles > 0) { 388 ierr = PetscMalloc1(in.numberoftriangles*in.numberofcorners, &in.trianglelist);CHKERRQ(ierr); 389 for (c = cStart; c < cEnd; ++c) { 390 const PetscInt idx = c - cStart; 391 PetscInt *closure = NULL; 392 PetscInt closureSize; 393 394 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 395 if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 396 for (v = 0; v < 3; ++v) { 397 in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 398 } 399 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 400 } 401 } 402 /* TODO: Segment markers are missing on input */ 403 #if 0 /* Do not currently support holes */ 404 PetscReal *holeCoords; 405 PetscInt h, d; 406 407 ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 408 if (in.numberofholes > 0) { 409 ierr = PetscMalloc1(in.numberofholes*dim, &in.holelist);CHKERRQ(ierr); 410 for (h = 0; h < in.numberofholes; ++h) { 411 for (d = 0; d < dim; ++d) { 412 in.holelist[h*dim+d] = holeCoords[h*dim+d]; 413 } 414 } 415 } 416 #endif 417 if (!rank) { 418 char args[32]; 419 420 /* Take away 'Q' for verbose output */ 421 ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 422 triangulate(args, &in, &out, NULL); 423 } 424 ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 425 ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 426 ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 427 ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 428 ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 429 430 { 431 DMLabel rlabel = NULL; 432 const PetscInt numCorners = 3; 433 const PetscInt numCells = out.numberoftriangles; 434 const PetscInt numVertices = out.numberofpoints; 435 const int *cells = out.trianglelist; 436 const double *meshCoords = out.pointlist; 437 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 438 439 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 440 if (label) {ierr = DMPlexCreateLabel(*dmRefined, labelName); ierr = DMPlexGetLabel(*dmRefined, labelName, &rlabel);} 441 /* Set labels */ 442 for (v = 0; v < numVertices; ++v) { 443 if (out.pointmarkerlist[v]) { 444 if (rlabel) {ierr = DMLabelSetValue(rlabel, v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr);} 445 } 446 } 447 if (interpolate) { 448 PetscInt e; 449 450 for (e = 0; e < out.numberofedges; e++) { 451 if (out.edgemarkerlist[e]) { 452 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 453 const PetscInt *edges; 454 PetscInt numEdges; 455 456 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 457 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 458 if (rlabel) {ierr = DMLabelSetValue(rlabel, edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr);} 459 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 460 } 461 } 462 } 463 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 464 } 465 #if 0 /* Do not currently support holes */ 466 ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 467 #endif 468 ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 469 PetscFunctionReturn(0); 470 } 471 #endif /* PETSC_HAVE_TRIANGLE */ 472 473 #if defined(PETSC_HAVE_TETGEN) 474 #include <tetgen.h> 475 #undef __FUNCT__ 476 #define __FUNCT__ "DMPlexGenerate_Tetgen" 477 PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 478 { 479 MPI_Comm comm; 480 DM_Plex *mesh = (DM_Plex *) boundary->data; 481 const PetscInt dim = 3; 482 const char *labelName = "marker"; 483 ::tetgenio in; 484 ::tetgenio out; 485 DMLabel label; 486 PetscInt vStart, vEnd, v, fStart, fEnd, f; 487 PetscMPIInt rank; 488 PetscErrorCode ierr; 489 490 PetscFunctionBegin; 491 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 492 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 493 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 494 ierr = DMPlexGetLabel(boundary, labelName, &label);CHKERRQ(ierr); 495 496 in.numberofpoints = vEnd - vStart; 497 if (in.numberofpoints > 0) { 498 PetscSection coordSection; 499 Vec coordinates; 500 PetscScalar *array; 501 502 in.pointlist = new double[in.numberofpoints*dim]; 503 in.pointmarkerlist = new int[in.numberofpoints]; 504 505 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 506 ierr = DMGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 507 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 508 for (v = vStart; v < vEnd; ++v) { 509 const PetscInt idx = v - vStart; 510 PetscInt off, d; 511 512 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 513 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 514 if (label) {ierr = DMLabelGetValue(label, v, &in.pointmarkerlist[idx]);CHKERRQ(ierr);} 515 } 516 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 517 } 518 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 519 520 in.numberoffacets = fEnd - fStart; 521 if (in.numberoffacets > 0) { 522 in.facetlist = new tetgenio::facet[in.numberoffacets]; 523 in.facetmarkerlist = new int[in.numberoffacets]; 524 for (f = fStart; f < fEnd; ++f) { 525 const PetscInt idx = f - fStart; 526 PetscInt *points = NULL, numPoints, p, numVertices = 0, v; 527 528 in.facetlist[idx].numberofpolygons = 1; 529 in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 530 in.facetlist[idx].numberofholes = 0; 531 in.facetlist[idx].holelist = NULL; 532 533 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 534 for (p = 0; p < numPoints*2; p += 2) { 535 const PetscInt point = points[p]; 536 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 537 } 538 539 tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 540 poly->numberofvertices = numVertices; 541 poly->vertexlist = new int[poly->numberofvertices]; 542 for (v = 0; v < numVertices; ++v) { 543 const PetscInt vIdx = points[v] - vStart; 544 poly->vertexlist[v] = vIdx; 545 } 546 if (label) {ierr = DMLabelGetValue(label, f, &in.facetmarkerlist[idx]);CHKERRQ(ierr);} 547 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 548 } 549 } 550 if (!rank) { 551 char args[32]; 552 553 /* Take away 'Q' for verbose output */ 554 ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 555 if (mesh->tetgenOpts) {::tetrahedralize(mesh->tetgenOpts, &in, &out);} 556 else {::tetrahedralize(args, &in, &out);} 557 } 558 { 559 DMLabel glabel = NULL; 560 const PetscInt numCorners = 4; 561 const PetscInt numCells = out.numberoftetrahedra; 562 const PetscInt numVertices = out.numberofpoints; 563 const double *meshCoords = out.pointlist; 564 int *cells = out.tetrahedronlist; 565 566 ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr); 567 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 568 if (label) {ierr = DMPlexCreateLabel(*dm, labelName); ierr = DMPlexGetLabel(*dm, labelName, &glabel);} 569 /* Set labels */ 570 for (v = 0; v < numVertices; ++v) { 571 if (out.pointmarkerlist[v]) { 572 if (glabel) {ierr = DMLabelSetValue(glabel, v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr);} 573 } 574 } 575 if (interpolate) { 576 PetscInt e; 577 578 for (e = 0; e < out.numberofedges; e++) { 579 if (out.edgemarkerlist[e]) { 580 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 581 const PetscInt *edges; 582 PetscInt numEdges; 583 584 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 585 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 586 if (glabel) {ierr = DMLabelSetValue(glabel, edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr);} 587 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 588 } 589 } 590 for (f = 0; f < out.numberoftrifaces; f++) { 591 if (out.trifacemarkerlist[f]) { 592 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 593 const PetscInt *faces; 594 PetscInt numFaces; 595 596 ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 597 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 598 if (glabel) {ierr = DMLabelSetValue(glabel, faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr);} 599 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 600 } 601 } 602 } 603 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 604 } 605 PetscFunctionReturn(0); 606 } 607 608 #undef __FUNCT__ 609 #define __FUNCT__ "DMPlexRefine_Tetgen" 610 PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 611 { 612 MPI_Comm comm; 613 const PetscInt dim = 3; 614 const char *labelName = "marker"; 615 ::tetgenio in; 616 ::tetgenio out; 617 DMLabel label; 618 PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 619 PetscMPIInt rank; 620 PetscErrorCode ierr; 621 622 PetscFunctionBegin; 623 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 624 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 625 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 626 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 627 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 628 ierr = DMPlexGetLabel(dm, labelName, &label);CHKERRQ(ierr); 629 630 in.numberofpoints = vEnd - vStart; 631 if (in.numberofpoints > 0) { 632 PetscSection coordSection; 633 Vec coordinates; 634 PetscScalar *array; 635 636 in.pointlist = new double[in.numberofpoints*dim]; 637 in.pointmarkerlist = new int[in.numberofpoints]; 638 639 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 640 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 641 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 642 for (v = vStart; v < vEnd; ++v) { 643 const PetscInt idx = v - vStart; 644 PetscInt off, d; 645 646 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 647 for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 648 if (label) {ierr = DMLabelGetValue(label, v, &in.pointmarkerlist[idx]);CHKERRQ(ierr);} 649 } 650 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 651 } 652 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 653 654 in.numberofcorners = 4; 655 in.numberoftetrahedra = cEnd - cStart; 656 in.tetrahedronvolumelist = (double*) maxVolumes; 657 if (in.numberoftetrahedra > 0) { 658 in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 659 for (c = cStart; c < cEnd; ++c) { 660 const PetscInt idx = c - cStart; 661 PetscInt *closure = NULL; 662 PetscInt closureSize; 663 664 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 665 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 666 for (v = 0; v < 4; ++v) { 667 in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 668 } 669 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 670 } 671 } 672 /* TODO: Put in boundary faces with markers */ 673 if (!rank) { 674 char args[32]; 675 676 /* Take away 'Q' for verbose output */ 677 /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */ 678 ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 679 ::tetrahedralize(args, &in, &out); 680 } 681 in.tetrahedronvolumelist = NULL; 682 683 { 684 DMLabel rlabel = NULL; 685 const PetscInt numCorners = 4; 686 const PetscInt numCells = out.numberoftetrahedra; 687 const PetscInt numVertices = out.numberofpoints; 688 const double *meshCoords = out.pointlist; 689 int *cells = out.tetrahedronlist; 690 691 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 692 693 ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr); 694 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 695 if (label) {ierr = DMPlexCreateLabel(*dmRefined, labelName); ierr = DMPlexGetLabel(*dmRefined, labelName, &rlabel);} 696 /* Set labels */ 697 for (v = 0; v < numVertices; ++v) { 698 if (out.pointmarkerlist[v]) { 699 if (rlabel) {ierr = DMLabelSetValue(rlabel, v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr);} 700 } 701 } 702 if (interpolate) { 703 PetscInt e, f; 704 705 for (e = 0; e < out.numberofedges; e++) { 706 if (out.edgemarkerlist[e]) { 707 const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 708 const PetscInt *edges; 709 PetscInt numEdges; 710 711 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 712 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 713 if (rlabel) {ierr = DMLabelSetValue(rlabel, edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr);} 714 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 715 } 716 } 717 for (f = 0; f < out.numberoftrifaces; f++) { 718 if (out.trifacemarkerlist[f]) { 719 const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 720 const PetscInt *faces; 721 PetscInt numFaces; 722 723 ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 724 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 725 if (rlabel) {ierr = DMLabelSetValue(rlabel, faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr);} 726 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 727 } 728 } 729 } 730 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 731 } 732 PetscFunctionReturn(0); 733 } 734 #endif /* PETSC_HAVE_TETGEN */ 735 736 #if defined(PETSC_HAVE_CTETGEN) 737 #include <ctetgen.h> 738 739 #undef __FUNCT__ 740 #define __FUNCT__ "DMPlexGenerate_CTetgen" 741 PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 742 { 743 MPI_Comm comm; 744 const PetscInt dim = 3; 745 const char *labelName = "marker"; 746 PLC *in, *out; 747 DMLabel label; 748 PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 749 PetscMPIInt rank; 750 PetscErrorCode ierr; 751 752 PetscFunctionBegin; 753 ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); 754 ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 755 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 756 ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 757 ierr = DMPlexGetLabel(boundary, labelName, &label);CHKERRQ(ierr); 758 ierr = PLCCreate(&in);CHKERRQ(ierr); 759 ierr = PLCCreate(&out);CHKERRQ(ierr); 760 761 in->numberofpoints = vEnd - vStart; 762 if (in->numberofpoints > 0) { 763 PetscSection coordSection; 764 Vec coordinates; 765 PetscScalar *array; 766 767 ierr = PetscMalloc1(in->numberofpoints*dim, &in->pointlist);CHKERRQ(ierr); 768 ierr = PetscMalloc1(in->numberofpoints, &in->pointmarkerlist);CHKERRQ(ierr); 769 ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 770 ierr = DMGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 771 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 772 for (v = vStart; v < vEnd; ++v) { 773 const PetscInt idx = v - vStart; 774 PetscInt off, d, m = -1; 775 776 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 777 for (d = 0; d < dim; ++d) { 778 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 779 } 780 if (label) {ierr = DMLabelGetValue(label, v, &m);CHKERRQ(ierr);} 781 782 in->pointmarkerlist[idx] = (int) m; 783 } 784 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 785 } 786 ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 787 788 in->numberoffacets = fEnd - fStart; 789 if (in->numberoffacets > 0) { 790 ierr = PetscMalloc1(in->numberoffacets, &in->facetlist);CHKERRQ(ierr); 791 ierr = PetscMalloc1(in->numberoffacets, &in->facetmarkerlist);CHKERRQ(ierr); 792 for (f = fStart; f < fEnd; ++f) { 793 const PetscInt idx = f - fStart; 794 PetscInt *points = NULL, numPoints, p, numVertices = 0, v, m = -1; 795 polygon *poly; 796 797 in->facetlist[idx].numberofpolygons = 1; 798 799 ierr = PetscMalloc1(in->facetlist[idx].numberofpolygons, &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 800 801 in->facetlist[idx].numberofholes = 0; 802 in->facetlist[idx].holelist = NULL; 803 804 ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 805 for (p = 0; p < numPoints*2; p += 2) { 806 const PetscInt point = points[p]; 807 if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; 808 } 809 810 poly = in->facetlist[idx].polygonlist; 811 poly->numberofvertices = numVertices; 812 ierr = PetscMalloc1(poly->numberofvertices, &poly->vertexlist);CHKERRQ(ierr); 813 for (v = 0; v < numVertices; ++v) { 814 const PetscInt vIdx = points[v] - vStart; 815 poly->vertexlist[v] = vIdx; 816 } 817 if (label) {ierr = DMLabelGetValue(label, f, &m);CHKERRQ(ierr);} 818 in->facetmarkerlist[idx] = (int) m; 819 ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 820 } 821 } 822 if (!rank) { 823 TetGenOpts t; 824 825 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 826 t.in = boundary; /* Should go away */ 827 t.plc = 1; 828 t.quality = 1; 829 t.edgesout = 1; 830 t.zeroindex = 1; 831 t.quiet = 1; 832 t.verbose = verbose; 833 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 834 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 835 } 836 { 837 DMLabel glabel = NULL; 838 const PetscInt numCorners = 4; 839 const PetscInt numCells = out->numberoftetrahedra; 840 const PetscInt numVertices = out->numberofpoints; 841 const double *meshCoords = out->pointlist; 842 int *cells = out->tetrahedronlist; 843 844 ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr); 845 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 846 if (label) {ierr = DMPlexCreateLabel(*dm, labelName); ierr = DMPlexGetLabel(*dm, labelName, &glabel);} 847 /* Set labels */ 848 for (v = 0; v < numVertices; ++v) { 849 if (out->pointmarkerlist[v]) { 850 if (glabel) {ierr = DMLabelSetValue(glabel, v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr);} 851 } 852 } 853 if (interpolate) { 854 PetscInt e; 855 856 for (e = 0; e < out->numberofedges; e++) { 857 if (out->edgemarkerlist[e]) { 858 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 859 const PetscInt *edges; 860 PetscInt numEdges; 861 862 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 863 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 864 if (glabel) {ierr = DMLabelSetValue(glabel, edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr);} 865 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 866 } 867 } 868 for (f = 0; f < out->numberoftrifaces; f++) { 869 if (out->trifacemarkerlist[f]) { 870 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 871 const PetscInt *faces; 872 PetscInt numFaces; 873 874 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 875 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 876 if (glabel) {ierr = DMLabelSetValue(glabel, faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr);} 877 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 878 } 879 } 880 } 881 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 882 } 883 884 ierr = PLCDestroy(&in);CHKERRQ(ierr); 885 ierr = PLCDestroy(&out);CHKERRQ(ierr); 886 PetscFunctionReturn(0); 887 } 888 889 #undef __FUNCT__ 890 #define __FUNCT__ "DMPlexRefine_CTetgen" 891 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 892 { 893 MPI_Comm comm; 894 const PetscInt dim = 3; 895 const char *labelName = "marker"; 896 PLC *in, *out; 897 DMLabel label; 898 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 899 PetscMPIInt rank; 900 PetscErrorCode ierr; 901 902 PetscFunctionBegin; 903 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 904 ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 905 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 906 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 907 ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 908 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 909 ierr = DMPlexGetLabel(dm, labelName, &label);CHKERRQ(ierr); 910 ierr = PLCCreate(&in);CHKERRQ(ierr); 911 ierr = PLCCreate(&out);CHKERRQ(ierr); 912 913 in->numberofpoints = vEnd - vStart; 914 if (in->numberofpoints > 0) { 915 PetscSection coordSection; 916 Vec coordinates; 917 PetscScalar *array; 918 919 ierr = PetscMalloc1(in->numberofpoints*dim, &in->pointlist);CHKERRQ(ierr); 920 ierr = PetscMalloc1(in->numberofpoints, &in->pointmarkerlist);CHKERRQ(ierr); 921 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 922 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 923 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 924 for (v = vStart; v < vEnd; ++v) { 925 const PetscInt idx = v - vStart; 926 PetscInt off, d, m = -1; 927 928 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 929 for (d = 0; d < dim; ++d) { 930 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 931 } 932 if (label) {ierr = DMLabelGetValue(label, v, &m);CHKERRQ(ierr);} 933 934 in->pointmarkerlist[idx] = (int) m; 935 } 936 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 937 } 938 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 939 940 in->numberofcorners = 4; 941 in->numberoftetrahedra = cEnd - cStart; 942 in->tetrahedronvolumelist = maxVolumes; 943 if (in->numberoftetrahedra > 0) { 944 ierr = PetscMalloc1(in->numberoftetrahedra*in->numberofcorners, &in->tetrahedronlist);CHKERRQ(ierr); 945 for (c = cStart; c < cEnd; ++c) { 946 const PetscInt idx = c - cStart; 947 PetscInt *closure = NULL; 948 PetscInt closureSize; 949 950 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 951 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 952 for (v = 0; v < 4; ++v) { 953 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 954 } 955 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 956 } 957 } 958 if (!rank) { 959 TetGenOpts t; 960 961 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 962 963 t.in = dm; /* Should go away */ 964 t.refine = 1; 965 t.varvolume = 1; 966 t.quality = 1; 967 t.edgesout = 1; 968 t.zeroindex = 1; 969 t.quiet = 1; 970 t.verbose = verbose; /* Change this */ 971 972 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 973 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 974 } 975 { 976 DMLabel rlabel = NULL; 977 const PetscInt numCorners = 4; 978 const PetscInt numCells = out->numberoftetrahedra; 979 const PetscInt numVertices = out->numberofpoints; 980 const double *meshCoords = out->pointlist; 981 int *cells = out->tetrahedronlist; 982 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 983 984 ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr); 985 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 986 if (label) {ierr = DMPlexCreateLabel(*dmRefined, labelName); ierr = DMPlexGetLabel(*dmRefined, labelName, &rlabel);} 987 /* Set labels */ 988 for (v = 0; v < numVertices; ++v) { 989 if (out->pointmarkerlist[v]) { 990 if (rlabel) {ierr = DMLabelSetValue(rlabel, v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr);} 991 } 992 } 993 if (interpolate) { 994 PetscInt e, f; 995 996 for (e = 0; e < out->numberofedges; e++) { 997 if (out->edgemarkerlist[e]) { 998 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 999 const PetscInt *edges; 1000 PetscInt numEdges; 1001 1002 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 1003 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 1004 if (rlabel) {ierr = DMLabelSetValue(rlabel, edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr);} 1005 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 1006 } 1007 } 1008 for (f = 0; f < out->numberoftrifaces; f++) { 1009 if (out->trifacemarkerlist[f]) { 1010 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 1011 const PetscInt *faces; 1012 PetscInt numFaces; 1013 1014 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 1015 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 1016 if (rlabel) {ierr = DMLabelSetValue(rlabel, faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr);} 1017 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 1018 } 1019 } 1020 } 1021 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 1022 } 1023 ierr = PLCDestroy(&in);CHKERRQ(ierr); 1024 ierr = PLCDestroy(&out);CHKERRQ(ierr); 1025 PetscFunctionReturn(0); 1026 } 1027 #endif /* PETSC_HAVE_CTETGEN */ 1028 1029 #undef __FUNCT__ 1030 #define __FUNCT__ "DMPlexGenerate" 1031 /*@C 1032 DMPlexGenerate - Generates a mesh. 1033 1034 Not Collective 1035 1036 Input Parameters: 1037 + boundary - The DMPlex boundary object 1038 . name - The mesh generation package name 1039 - interpolate - Flag to create intermediate mesh elements 1040 1041 Output Parameter: 1042 . mesh - The DMPlex object 1043 1044 Level: intermediate 1045 1046 .keywords: mesh, elements 1047 .seealso: DMPlexCreate(), DMRefine() 1048 @*/ 1049 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 1050 { 1051 PetscInt dim; 1052 char genname[1024]; 1053 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 1054 PetscErrorCode ierr; 1055 1056 PetscFunctionBegin; 1057 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 1058 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 1059 ierr = DMGetDimension(boundary, &dim);CHKERRQ(ierr); 1060 ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 1061 if (flg) name = genname; 1062 if (name) { 1063 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 1064 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 1065 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 1066 } 1067 switch (dim) { 1068 case 1: 1069 if (!name || isTriangle) { 1070 #if defined(PETSC_HAVE_TRIANGLE) 1071 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 1072 #else 1073 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 1074 #endif 1075 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 1076 break; 1077 case 2: 1078 if (!name || isCTetgen) { 1079 #if defined(PETSC_HAVE_CTETGEN) 1080 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 1081 #else 1082 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 1083 #endif 1084 } else if (isTetgen) { 1085 #if defined(PETSC_HAVE_TETGEN) 1086 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 1087 #else 1088 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 1089 #endif 1090 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 1091 break; 1092 default: 1093 SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 1094 } 1095 PetscFunctionReturn(0); 1096 } 1097 1098 #undef __FUNCT__ 1099 #define __FUNCT__ "DMRefine_Plex" 1100 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 1101 { 1102 PetscReal refinementLimit; 1103 PetscInt dim, cStart, cEnd; 1104 char genname[1024], *name = NULL; 1105 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 1106 PetscErrorCode ierr; 1107 1108 PetscFunctionBegin; 1109 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 1110 if (isUniform) { 1111 CellRefiner cellRefiner; 1112 1113 ierr = DMPlexGetCellRefiner_Internal(dm, &cellRefiner);CHKERRQ(ierr); 1114 ierr = DMPlexRefineUniform_Internal(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 1115 ierr = DMPlexCopyBoundary(dm, *dmRefined);CHKERRQ(ierr); 1116 PetscFunctionReturn(0); 1117 } 1118 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 1119 if (refinementLimit == 0.0) PetscFunctionReturn(0); 1120 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1121 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1122 ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 1123 if (flg) name = genname; 1124 if (name) { 1125 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 1126 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 1127 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 1128 } 1129 switch (dim) { 1130 case 2: 1131 if (!name || isTriangle) { 1132 #if defined(PETSC_HAVE_TRIANGLE) 1133 double *maxVolumes; 1134 PetscInt c; 1135 1136 ierr = PetscMalloc1(cEnd - cStart, &maxVolumes);CHKERRQ(ierr); 1137 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 1138 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 1139 ierr = PetscFree(maxVolumes);CHKERRQ(ierr); 1140 #else 1141 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 1142 #endif 1143 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 1144 break; 1145 case 3: 1146 if (!name || isCTetgen) { 1147 #if defined(PETSC_HAVE_CTETGEN) 1148 PetscReal *maxVolumes; 1149 PetscInt c; 1150 1151 ierr = PetscMalloc1(cEnd - cStart, &maxVolumes);CHKERRQ(ierr); 1152 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 1153 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 1154 #else 1155 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 1156 #endif 1157 } else if (isTetgen) { 1158 #if defined(PETSC_HAVE_TETGEN) 1159 double *maxVolumes; 1160 PetscInt c; 1161 1162 ierr = PetscMalloc1(cEnd - cStart, &maxVolumes);CHKERRQ(ierr); 1163 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 1164 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 1165 #else 1166 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 1167 #endif 1168 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 1169 break; 1170 default: 1171 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 1172 } 1173 ierr = DMPlexCopyBoundary(dm, *dmRefined);CHKERRQ(ierr); 1174 PetscFunctionReturn(0); 1175 } 1176 1177 #undef __FUNCT__ 1178 #define __FUNCT__ "DMRefineHierarchy_Plex" 1179 PetscErrorCode DMRefineHierarchy_Plex(DM dm, PetscInt nlevels, DM dmRefined[]) 1180 { 1181 DM cdm = dm; 1182 PetscInt r; 1183 PetscBool isUniform; 1184 PetscErrorCode ierr; 1185 1186 PetscFunctionBegin; 1187 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 1188 if (!isUniform) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Non-uniform refinement is incompatible with the hierarchy"); 1189 for (r = 0; r < nlevels; ++r) { 1190 CellRefiner cellRefiner; 1191 1192 ierr = DMPlexGetCellRefiner_Internal(cdm, &cellRefiner);CHKERRQ(ierr); 1193 ierr = DMPlexRefineUniform_Internal(cdm, cellRefiner, &dmRefined[r]);CHKERRQ(ierr); 1194 ierr = DMPlexSetCoarseDM(dmRefined[r], cdm);CHKERRQ(ierr); 1195 cdm = dmRefined[r]; 1196 } 1197 PetscFunctionReturn(0); 1198 } 1199 1200 #undef __FUNCT__ 1201 #define __FUNCT__ "DMCoarsen_Plex" 1202 PetscErrorCode DMCoarsen_Plex(DM dm, MPI_Comm comm, DM *dmCoarsened) 1203 { 1204 DM_Plex *mesh = (DM_Plex*) dm->data; 1205 PetscErrorCode ierr; 1206 1207 PetscFunctionBegin; 1208 ierr = PetscObjectReference((PetscObject) mesh->coarseMesh);CHKERRQ(ierr); 1209 *dmCoarsened = mesh->coarseMesh; 1210 PetscFunctionReturn(0); 1211 } 1212