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 = DMGetLabel(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 = DMCreateLabel(*dm, labelName); ierr = DMGetLabel(*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 = MPIU_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 355 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 356 ierr = DMGetLabel(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 = DMCreateLabel(*dmRefined, labelName); ierr = DMGetLabel(*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 = DMGetLabel(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 = DMCreateLabel(*dm, labelName); ierr = DMGetLabel(*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 = MPIU_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 627 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 628 ierr = DMGetLabel(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 = DMCreateLabel(*dmRefined, labelName); ierr = DMGetLabel(*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(NULL,((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 = DMGetLabel(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 double *meshCoords; 842 int *cells = out->tetrahedronlist; 843 844 if (sizeof (PetscReal) == sizeof (double)) { 845 meshCoords = (double *) out->pointlist; 846 } 847 else { 848 PetscInt i; 849 850 ierr = PetscMalloc1(3 * numVertices,&meshCoords);CHKERRQ(ierr); 851 for (i = 0; i < 3 * numVertices; i++) { 852 meshCoords[i] = (PetscReal) out->pointlist[i]; 853 } 854 } 855 856 ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr); 857 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); 858 if (sizeof (PetscReal) != sizeof (double)) { 859 ierr = PetscFree(meshCoords);CHKERRQ(ierr); 860 } 861 if (label) {ierr = DMCreateLabel(*dm, labelName); ierr = DMGetLabel(*dm, labelName, &glabel);} 862 /* Set labels */ 863 for (v = 0; v < numVertices; ++v) { 864 if (out->pointmarkerlist[v]) { 865 if (glabel) {ierr = DMLabelSetValue(glabel, v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr);} 866 } 867 } 868 if (interpolate) { 869 PetscInt e; 870 871 for (e = 0; e < out->numberofedges; e++) { 872 if (out->edgemarkerlist[e]) { 873 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 874 const PetscInt *edges; 875 PetscInt numEdges; 876 877 ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 878 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 879 if (glabel) {ierr = DMLabelSetValue(glabel, edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr);} 880 ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 881 } 882 } 883 for (f = 0; f < out->numberoftrifaces; f++) { 884 if (out->trifacemarkerlist[f]) { 885 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 886 const PetscInt *faces; 887 PetscInt numFaces; 888 889 ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 890 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 891 if (glabel) {ierr = DMLabelSetValue(glabel, faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr);} 892 ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 893 } 894 } 895 } 896 ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 897 } 898 899 ierr = PLCDestroy(&in);CHKERRQ(ierr); 900 ierr = PLCDestroy(&out);CHKERRQ(ierr); 901 PetscFunctionReturn(0); 902 } 903 904 #undef __FUNCT__ 905 #define __FUNCT__ "DMPlexRefine_CTetgen" 906 PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 907 { 908 MPI_Comm comm; 909 const PetscInt dim = 3; 910 const char *labelName = "marker"; 911 PLC *in, *out; 912 DMLabel label; 913 PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 914 PetscMPIInt rank; 915 PetscErrorCode ierr; 916 917 PetscFunctionBegin; 918 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 919 ierr = PetscOptionsGetInt(NULL,((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); 920 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 921 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 922 ierr = MPIU_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 923 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 924 ierr = DMGetLabel(dm, labelName, &label);CHKERRQ(ierr); 925 ierr = PLCCreate(&in);CHKERRQ(ierr); 926 ierr = PLCCreate(&out);CHKERRQ(ierr); 927 928 in->numberofpoints = vEnd - vStart; 929 if (in->numberofpoints > 0) { 930 PetscSection coordSection; 931 Vec coordinates; 932 PetscScalar *array; 933 934 ierr = PetscMalloc1(in->numberofpoints*dim, &in->pointlist);CHKERRQ(ierr); 935 ierr = PetscMalloc1(in->numberofpoints, &in->pointmarkerlist);CHKERRQ(ierr); 936 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 937 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 938 ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 939 for (v = vStart; v < vEnd; ++v) { 940 const PetscInt idx = v - vStart; 941 PetscInt off, d, m = -1; 942 943 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 944 for (d = 0; d < dim; ++d) { 945 in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 946 } 947 if (label) {ierr = DMLabelGetValue(label, v, &m);CHKERRQ(ierr);} 948 949 in->pointmarkerlist[idx] = (int) m; 950 } 951 ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 952 } 953 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 954 955 in->numberofcorners = 4; 956 in->numberoftetrahedra = cEnd - cStart; 957 in->tetrahedronvolumelist = maxVolumes; 958 if (in->numberoftetrahedra > 0) { 959 ierr = PetscMalloc1(in->numberoftetrahedra*in->numberofcorners, &in->tetrahedronlist);CHKERRQ(ierr); 960 for (c = cStart; c < cEnd; ++c) { 961 const PetscInt idx = c - cStart; 962 PetscInt *closure = NULL; 963 PetscInt closureSize; 964 965 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 966 if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 967 for (v = 0; v < 4; ++v) { 968 in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 969 } 970 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 971 } 972 } 973 if (!rank) { 974 TetGenOpts t; 975 976 ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 977 978 t.in = dm; /* Should go away */ 979 t.refine = 1; 980 t.varvolume = 1; 981 t.quality = 1; 982 t.edgesout = 1; 983 t.zeroindex = 1; 984 t.quiet = 1; 985 t.verbose = verbose; /* Change this */ 986 987 ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 988 ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 989 } 990 { 991 DMLabel rlabel = NULL; 992 const PetscInt numCorners = 4; 993 const PetscInt numCells = out->numberoftetrahedra; 994 const PetscInt numVertices = out->numberofpoints; 995 double *meshCoords; 996 int *cells = out->tetrahedronlist; 997 PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 998 999 if (sizeof (PetscReal) == sizeof (double)) { 1000 meshCoords = (double *) out->pointlist; 1001 } 1002 else { 1003 PetscInt i; 1004 1005 ierr = PetscMalloc1(3 * numVertices,&meshCoords);CHKERRQ(ierr); 1006 for (i = 0; i < 3 * numVertices; i++) { 1007 meshCoords[i] = (PetscReal) out->pointlist[i]; 1008 } 1009 } 1010 1011 ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr); 1012 ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); 1013 if (sizeof (PetscReal) != sizeof (double)) { 1014 ierr = PetscFree(meshCoords);CHKERRQ(ierr); 1015 } 1016 if (label) {ierr = DMCreateLabel(*dmRefined, labelName); ierr = DMGetLabel(*dmRefined, labelName, &rlabel);} 1017 /* Set labels */ 1018 for (v = 0; v < numVertices; ++v) { 1019 if (out->pointmarkerlist[v]) { 1020 if (rlabel) {ierr = DMLabelSetValue(rlabel, v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr);} 1021 } 1022 } 1023 if (interpolate) { 1024 PetscInt e, f; 1025 1026 for (e = 0; e < out->numberofedges; e++) { 1027 if (out->edgemarkerlist[e]) { 1028 const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 1029 const PetscInt *edges; 1030 PetscInt numEdges; 1031 1032 ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 1033 if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 1034 if (rlabel) {ierr = DMLabelSetValue(rlabel, edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr);} 1035 ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 1036 } 1037 } 1038 for (f = 0; f < out->numberoftrifaces; f++) { 1039 if (out->trifacemarkerlist[f]) { 1040 const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 1041 const PetscInt *faces; 1042 PetscInt numFaces; 1043 1044 ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 1045 if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 1046 if (rlabel) {ierr = DMLabelSetValue(rlabel, faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr);} 1047 ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 1048 } 1049 } 1050 } 1051 ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 1052 } 1053 ierr = PLCDestroy(&in);CHKERRQ(ierr); 1054 ierr = PLCDestroy(&out);CHKERRQ(ierr); 1055 PetscFunctionReturn(0); 1056 } 1057 #endif /* PETSC_HAVE_CTETGEN */ 1058 1059 #undef __FUNCT__ 1060 #define __FUNCT__ "DMPlexGenerate" 1061 /*@C 1062 DMPlexGenerate - Generates a mesh. 1063 1064 Not Collective 1065 1066 Input Parameters: 1067 + boundary - The DMPlex boundary object 1068 . name - The mesh generation package name 1069 - interpolate - Flag to create intermediate mesh elements 1070 1071 Output Parameter: 1072 . mesh - The DMPlex object 1073 1074 Level: intermediate 1075 1076 .keywords: mesh, elements 1077 .seealso: DMPlexCreate(), DMRefine() 1078 @*/ 1079 PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 1080 { 1081 PetscInt dim; 1082 char genname[1024]; 1083 PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 1084 PetscErrorCode ierr; 1085 1086 PetscFunctionBegin; 1087 PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 1088 PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 1089 ierr = DMGetDimension(boundary, &dim);CHKERRQ(ierr); 1090 ierr = PetscOptionsGetString(((PetscObject) boundary)->options,((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 1091 if (flg) name = genname; 1092 if (name) { 1093 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 1094 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 1095 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 1096 } 1097 switch (dim) { 1098 case 1: 1099 if (!name || isTriangle) { 1100 #if defined(PETSC_HAVE_TRIANGLE) 1101 ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 1102 #else 1103 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 1104 #endif 1105 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 1106 break; 1107 case 2: 1108 if (!name || isCTetgen) { 1109 #if defined(PETSC_HAVE_CTETGEN) 1110 ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 1111 #else 1112 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 1113 #endif 1114 } else if (isTetgen) { 1115 #if defined(PETSC_HAVE_TETGEN) 1116 ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 1117 #else 1118 SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --download-tetgen."); 1119 #endif 1120 } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 1121 break; 1122 default: 1123 SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 1124 } 1125 PetscFunctionReturn(0); 1126 } 1127 1128 #undef __FUNCT__ 1129 #define __FUNCT__ "DMRefine_Plex" 1130 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 1131 { 1132 PetscErrorCode (*refinementFunc)(const PetscReal [], PetscReal *); 1133 PetscReal refinementLimit; 1134 PetscInt dim, cStart, cEnd; 1135 char genname[1024], *name = NULL; 1136 PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg, localized; 1137 PetscErrorCode ierr; 1138 1139 PetscFunctionBegin; 1140 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 1141 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 1142 if (isUniform) { 1143 CellRefiner cellRefiner; 1144 1145 ierr = DMPlexGetCellRefiner_Internal(dm, &cellRefiner);CHKERRQ(ierr); 1146 ierr = DMPlexRefineUniform_Internal(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 1147 ierr = DMCopyBoundary(dm, *dmRefined);CHKERRQ(ierr); 1148 if (localized) { 1149 ierr = DMLocalizeCoordinates(*dmRefined);CHKERRQ(ierr); 1150 } 1151 PetscFunctionReturn(0); 1152 } 1153 ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 1154 ierr = DMPlexGetRefinementFunction(dm, &refinementFunc);CHKERRQ(ierr); 1155 if (refinementLimit == 0.0 && !refinementFunc) PetscFunctionReturn(0); 1156 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1157 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1158 ierr = PetscOptionsGetString(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 1159 if (flg) name = genname; 1160 if (name) { 1161 ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 1162 ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 1163 ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 1164 } 1165 switch (dim) { 1166 case 2: 1167 if (!name || isTriangle) { 1168 #if defined(PETSC_HAVE_TRIANGLE) 1169 double *maxVolumes; 1170 PetscInt c; 1171 1172 ierr = PetscMalloc1(cEnd - cStart, &maxVolumes);CHKERRQ(ierr); 1173 if (refinementFunc) { 1174 for (c = cStart; c < cEnd; ++c) { 1175 PetscReal vol, centroid[3]; 1176 PetscReal maxVol; 1177 1178 ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol, centroid, NULL);CHKERRQ(ierr); 1179 ierr = (*refinementFunc)(centroid, &maxVol);CHKERRQ(ierr); 1180 maxVolumes[c - cStart] = (double) maxVol; 1181 } 1182 } else { 1183 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 1184 } 1185 ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 1186 ierr = PetscFree(maxVolumes);CHKERRQ(ierr); 1187 #else 1188 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 1189 #endif 1190 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 1191 break; 1192 case 3: 1193 if (!name || isCTetgen) { 1194 #if defined(PETSC_HAVE_CTETGEN) 1195 PetscReal *maxVolumes; 1196 PetscInt c; 1197 1198 ierr = PetscMalloc1(cEnd - cStart, &maxVolumes);CHKERRQ(ierr); 1199 if (refinementFunc) { 1200 for (c = cStart; c < cEnd; ++c) { 1201 PetscReal vol, centroid[3]; 1202 1203 ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol, centroid, NULL);CHKERRQ(ierr); 1204 ierr = (*refinementFunc)(centroid, &maxVolumes[c-cStart]);CHKERRQ(ierr); 1205 } 1206 } else { 1207 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 1208 } 1209 ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 1210 #else 1211 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 1212 #endif 1213 } else if (isTetgen) { 1214 #if defined(PETSC_HAVE_TETGEN) 1215 double *maxVolumes; 1216 PetscInt c; 1217 1218 ierr = PetscMalloc1(cEnd - cStart, &maxVolumes);CHKERRQ(ierr); 1219 if (refinementFunc) { 1220 for (c = cStart; c < cEnd; ++c) { 1221 PetscReal vol, centroid[3]; 1222 1223 ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol, centroid, NULL);CHKERRQ(ierr); 1224 ierr = (*refinementFunc)(centroid, &maxVolumes[c-cStart]);CHKERRQ(ierr); 1225 } 1226 } else { 1227 for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit; 1228 } 1229 ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 1230 #else 1231 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 1232 #endif 1233 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 1234 break; 1235 default: 1236 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 1237 } 1238 ierr = DMCopyBoundary(dm, *dmRefined);CHKERRQ(ierr); 1239 if (localized) { 1240 ierr = DMLocalizeCoordinates(*dmRefined);CHKERRQ(ierr); 1241 } 1242 PetscFunctionReturn(0); 1243 } 1244 1245 #undef __FUNCT__ 1246 #define __FUNCT__ "DMRefineHierarchy_Plex" 1247 PetscErrorCode DMRefineHierarchy_Plex(DM dm, PetscInt nlevels, DM dmRefined[]) 1248 { 1249 DM cdm = dm; 1250 PetscInt r; 1251 PetscBool isUniform, localized; 1252 PetscErrorCode ierr; 1253 1254 PetscFunctionBegin; 1255 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 1256 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 1257 if (!isUniform) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Non-uniform refinement is incompatible with the hierarchy"); 1258 for (r = 0; r < nlevels; ++r) { 1259 CellRefiner cellRefiner; 1260 1261 ierr = DMPlexGetCellRefiner_Internal(cdm, &cellRefiner);CHKERRQ(ierr); 1262 ierr = DMPlexRefineUniform_Internal(cdm, cellRefiner, &dmRefined[r]);CHKERRQ(ierr); 1263 ierr = DMCopyBoundary(cdm, dmRefined[r]);CHKERRQ(ierr); 1264 if (localized) { 1265 ierr = DMLocalizeCoordinates(dmRefined[r]);CHKERRQ(ierr); 1266 } 1267 ierr = DMSetCoarseDM(dmRefined[r], cdm);CHKERRQ(ierr); 1268 ierr = DMPlexSetRegularRefinement(dmRefined[r], PETSC_TRUE);CHKERRQ(ierr); 1269 cdm = dmRefined[r]; 1270 } 1271 PetscFunctionReturn(0); 1272 } 1273