1 #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <petsc/private/dmlabelimpl.h> /*I "petscdmlabel.h" I*/ 3 #include <petscsf.h> 4 5 static PetscErrorCode DMPlexCellIsHybrid_Internal(DM dm, PetscInt p, PetscBool *isHybrid) 6 { 7 DMPolytopeType ct; 8 PetscErrorCode ierr; 9 10 PetscFunctionBegin; 11 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 12 switch (ct) { 13 case DM_POLYTOPE_POINT_PRISM_TENSOR: 14 case DM_POLYTOPE_SEG_PRISM_TENSOR: 15 case DM_POLYTOPE_TRI_PRISM_TENSOR: 16 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 17 *isHybrid = PETSC_TRUE; 18 default: *isHybrid = PETSC_FALSE; 19 } 20 PetscFunctionReturn(0); 21 } 22 23 static PetscErrorCode DMPlexGetTensorPrismBounds_Internal(DM dm, PetscInt dim, PetscInt *cStart, PetscInt *cEnd) 24 { 25 DMLabel ctLabel; 26 PetscErrorCode ierr; 27 28 PetscFunctionBegin; 29 if (cStart) *cStart = -1; 30 if (cEnd) *cEnd = -1; 31 ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr); 32 switch (dim) { 33 case 1: ierr = DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_POINT_PRISM_TENSOR, cStart, cEnd);CHKERRQ(ierr);break; 34 case 2: ierr = DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_SEG_PRISM_TENSOR, cStart, cEnd);CHKERRQ(ierr);break; 35 case 3: 36 ierr = DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_TRI_PRISM_TENSOR, cStart, cEnd);CHKERRQ(ierr); 37 if (*cStart < 0) {ierr = DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_QUAD_PRISM_TENSOR, cStart, cEnd);CHKERRQ(ierr);} 38 break; 39 default: PetscFunctionReturn(0); 40 } 41 PetscFunctionReturn(0); 42 } 43 44 static PetscErrorCode DMPlexMarkBoundaryFaces_Internal(DM dm, PetscInt val, PetscInt cellHeight, DMLabel label) 45 { 46 PetscInt fStart, fEnd, f; 47 PetscErrorCode ierr; 48 49 PetscFunctionBegin; 50 ierr = DMPlexGetHeightStratum(dm, cellHeight+1, &fStart, &fEnd);CHKERRQ(ierr); 51 for (f = fStart; f < fEnd; ++f) { 52 PetscInt supportSize; 53 54 ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 55 if (supportSize == 1) { 56 if (val < 0) { 57 PetscInt *closure = NULL; 58 PetscInt clSize, cl, cval; 59 60 ierr = DMPlexGetTransitiveClosure(dm, f, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 61 for (cl = 0; cl < clSize*2; cl += 2) { 62 ierr = DMLabelGetValue(label, closure[cl], &cval);CHKERRQ(ierr); 63 if (cval < 0) continue; 64 ierr = DMLabelSetValue(label, f, cval);CHKERRQ(ierr); 65 break; 66 } 67 if (cl == clSize*2) {ierr = DMLabelSetValue(label, f, 1);CHKERRQ(ierr);} 68 ierr = DMPlexRestoreTransitiveClosure(dm, f, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 69 } else { 70 ierr = DMLabelSetValue(label, f, val);CHKERRQ(ierr); 71 } 72 } 73 } 74 PetscFunctionReturn(0); 75 } 76 77 /*@ 78 DMPlexMarkBoundaryFaces - Mark all faces on the boundary 79 80 Not Collective 81 82 Input Parameters: 83 + dm - The original DM 84 - val - The marker value, or PETSC_DETERMINE to use some value in the closure (or 1 if none are found) 85 86 Output Parameter: 87 . label - The DMLabel marking boundary faces with the given value 88 89 Level: developer 90 91 .seealso: DMLabelCreate(), DMCreateLabel() 92 @*/ 93 PetscErrorCode DMPlexMarkBoundaryFaces(DM dm, PetscInt val, DMLabel label) 94 { 95 DMPlexInterpolatedFlag flg; 96 PetscErrorCode ierr; 97 98 PetscFunctionBegin; 99 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 100 ierr = DMPlexIsInterpolated(dm, &flg);CHKERRQ(ierr); 101 if (flg != DMPLEX_INTERPOLATED_FULL) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not fully interpolated on this rank"); 102 ierr = DMPlexMarkBoundaryFaces_Internal(dm, val, 0, label);CHKERRQ(ierr); 103 PetscFunctionReturn(0); 104 } 105 106 static PetscErrorCode DMPlexLabelComplete_Internal(DM dm, DMLabel label, PetscBool completeCells) 107 { 108 IS valueIS; 109 PetscSF sfPoint; 110 const PetscInt *values; 111 PetscInt numValues, v, cStart, cEnd, nroots; 112 PetscErrorCode ierr; 113 114 PetscFunctionBegin; 115 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 116 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 117 ierr = DMPlexGetHeightStratum(dm,0,&cStart,&cEnd);CHKERRQ(ierr); 118 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 119 for (v = 0; v < numValues; ++v) { 120 IS pointIS; 121 const PetscInt *points; 122 PetscInt numPoints, p; 123 124 ierr = DMLabelGetStratumSize(label, values[v], &numPoints);CHKERRQ(ierr); 125 ierr = DMLabelGetStratumIS(label, values[v], &pointIS);CHKERRQ(ierr); 126 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 127 for (p = 0; p < numPoints; ++p) { 128 PetscInt q = points[p]; 129 PetscInt *closure = NULL; 130 PetscInt closureSize, c; 131 132 if (cStart <= q && q < cEnd && !completeCells) { /* skip cells */ 133 continue; 134 } 135 ierr = DMPlexGetTransitiveClosure(dm, q, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 136 for (c = 0; c < closureSize*2; c += 2) { 137 ierr = DMLabelSetValue(label, closure[c], values[v]);CHKERRQ(ierr); 138 } 139 ierr = DMPlexRestoreTransitiveClosure(dm, q, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 140 } 141 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 142 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 143 } 144 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 145 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 146 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 147 ierr = PetscSFGetGraph(sfPoint, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 148 if (nroots >= 0) { 149 DMLabel lblRoots, lblLeaves; 150 IS valueIS, pointIS; 151 const PetscInt *values; 152 PetscInt numValues, v; 153 PetscErrorCode ierr; 154 155 /* Pull point contributions from remote leaves into local roots */ 156 ierr = DMLabelGather(label, sfPoint, &lblLeaves);CHKERRQ(ierr); 157 ierr = DMLabelGetValueIS(lblLeaves, &valueIS);CHKERRQ(ierr); 158 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 159 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 160 for (v = 0; v < numValues; ++v) { 161 const PetscInt value = values[v]; 162 163 ierr = DMLabelGetStratumIS(lblLeaves, value, &pointIS);CHKERRQ(ierr); 164 ierr = DMLabelInsertIS(label, pointIS, value);CHKERRQ(ierr); 165 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 166 } 167 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 168 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 169 ierr = DMLabelDestroy(&lblLeaves);CHKERRQ(ierr); 170 /* Push point contributions from roots into remote leaves */ 171 ierr = DMLabelDistribute(label, sfPoint, &lblRoots);CHKERRQ(ierr); 172 ierr = DMLabelGetValueIS(lblRoots, &valueIS);CHKERRQ(ierr); 173 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 174 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 175 for (v = 0; v < numValues; ++v) { 176 const PetscInt value = values[v]; 177 178 ierr = DMLabelGetStratumIS(lblRoots, value, &pointIS);CHKERRQ(ierr); 179 ierr = DMLabelInsertIS(label, pointIS, value);CHKERRQ(ierr); 180 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 181 } 182 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 183 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 184 ierr = DMLabelDestroy(&lblRoots);CHKERRQ(ierr); 185 } 186 PetscFunctionReturn(0); 187 } 188 189 /*@ 190 DMPlexLabelComplete - Starting with a label marking points on a surface, we add the transitive closure to the surface 191 192 Input Parameters: 193 + dm - The DM 194 - label - A DMLabel marking the surface points 195 196 Output Parameter: 197 . label - A DMLabel marking all surface points in the transitive closure 198 199 Level: developer 200 201 .seealso: DMPlexLabelCohesiveComplete() 202 @*/ 203 PetscErrorCode DMPlexLabelComplete(DM dm, DMLabel label) 204 { 205 PetscErrorCode ierr; 206 207 PetscFunctionBegin; 208 ierr = DMPlexLabelComplete_Internal(dm, label, PETSC_TRUE);CHKERRQ(ierr); 209 PetscFunctionReturn(0); 210 } 211 212 /*@ 213 DMPlexLabelAddCells - Starting with a label marking points on a surface, we add a cell for each point 214 215 Input Parameters: 216 + dm - The DM 217 - label - A DMLabel marking the surface points 218 219 Output Parameter: 220 . label - A DMLabel incorporating cells 221 222 Level: developer 223 224 Note: The cells allow FEM boundary conditions to be applied using the cell geometry 225 226 .seealso: DMPlexLabelAddFaceCells(), DMPlexLabelComplete(), DMPlexLabelCohesiveComplete() 227 @*/ 228 PetscErrorCode DMPlexLabelAddCells(DM dm, DMLabel label) 229 { 230 IS valueIS; 231 const PetscInt *values; 232 PetscInt numValues, v, cStart, cEnd; 233 PetscErrorCode ierr; 234 235 PetscFunctionBegin; 236 ierr = DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 237 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 238 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 239 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 240 for (v = 0; v < numValues; ++v) { 241 IS pointIS; 242 const PetscInt *points; 243 PetscInt numPoints, p; 244 245 ierr = DMLabelGetStratumSize(label, values[v], &numPoints);CHKERRQ(ierr); 246 ierr = DMLabelGetStratumIS(label, values[v], &pointIS);CHKERRQ(ierr); 247 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 248 for (p = 0; p < numPoints; ++p) { 249 PetscInt *closure = NULL; 250 PetscInt closureSize, cl; 251 252 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closure);CHKERRQ(ierr); 253 for (cl = closureSize-1; cl > 0; --cl) { 254 const PetscInt cell = closure[cl*2]; 255 if ((cell >= cStart) && (cell < cEnd)) {ierr = DMLabelSetValue(label, cell, values[v]);CHKERRQ(ierr); break;} 256 } 257 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closure);CHKERRQ(ierr); 258 } 259 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 260 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 261 } 262 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 263 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 264 PetscFunctionReturn(0); 265 } 266 267 /*@ 268 DMPlexLabelAddFaceCells - Starting with a label marking faces on a surface, we add a cell for each face 269 270 Input Parameters: 271 + dm - The DM 272 - label - A DMLabel marking the surface points 273 274 Output Parameter: 275 . label - A DMLabel incorporating cells 276 277 Level: developer 278 279 Note: The cells allow FEM boundary conditions to be applied using the cell geometry 280 281 .seealso: DMPlexLabelAddCells(), DMPlexLabelComplete(), DMPlexLabelCohesiveComplete() 282 @*/ 283 PetscErrorCode DMPlexLabelAddFaceCells(DM dm, DMLabel label) 284 { 285 IS valueIS; 286 const PetscInt *values; 287 PetscInt numValues, v, cStart, cEnd, fStart, fEnd; 288 PetscErrorCode ierr; 289 290 PetscFunctionBegin; 291 ierr = DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 292 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 293 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 294 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 295 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 296 for (v = 0; v < numValues; ++v) { 297 IS pointIS; 298 const PetscInt *points; 299 PetscInt numPoints, p; 300 301 ierr = DMLabelGetStratumSize(label, values[v], &numPoints);CHKERRQ(ierr); 302 ierr = DMLabelGetStratumIS(label, values[v], &pointIS);CHKERRQ(ierr); 303 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 304 for (p = 0; p < numPoints; ++p) { 305 const PetscInt face = points[p]; 306 PetscInt *closure = NULL; 307 PetscInt closureSize, cl; 308 309 if ((face < fStart) || (face >= fEnd)) continue; 310 ierr = DMPlexGetTransitiveClosure(dm, face, PETSC_FALSE, &closureSize, &closure);CHKERRQ(ierr); 311 for (cl = closureSize-1; cl > 0; --cl) { 312 const PetscInt cell = closure[cl*2]; 313 if ((cell >= cStart) && (cell < cEnd)) {ierr = DMLabelSetValue(label, cell, values[v]);CHKERRQ(ierr); break;} 314 } 315 ierr = DMPlexRestoreTransitiveClosure(dm, face, PETSC_FALSE, &closureSize, &closure);CHKERRQ(ierr); 316 } 317 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 318 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 319 } 320 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 321 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 322 PetscFunctionReturn(0); 323 } 324 325 /*@ 326 DMPlexLabelClearCells - Remove cells from a label 327 328 Input Parameters: 329 + dm - The DM 330 - label - A DMLabel marking surface points and their adjacent cells 331 332 Output Parameter: 333 . label - A DMLabel without cells 334 335 Level: developer 336 337 Note: This undoes DMPlexLabelAddCells() or DMPlexLabelAddFaceCells() 338 339 .seealso: DMPlexLabelComplete(), DMPlexLabelCohesiveComplete(), DMPlexLabelAddCells() 340 @*/ 341 PetscErrorCode DMPlexLabelClearCells(DM dm, DMLabel label) 342 { 343 IS valueIS; 344 const PetscInt *values; 345 PetscInt numValues, v, cStart, cEnd; 346 PetscErrorCode ierr; 347 348 PetscFunctionBegin; 349 ierr = DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 350 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 351 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 352 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 353 for (v = 0; v < numValues; ++v) { 354 IS pointIS; 355 const PetscInt *points; 356 PetscInt numPoints, p; 357 358 ierr = DMLabelGetStratumSize(label, values[v], &numPoints);CHKERRQ(ierr); 359 ierr = DMLabelGetStratumIS(label, values[v], &pointIS);CHKERRQ(ierr); 360 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 361 for (p = 0; p < numPoints; ++p) { 362 PetscInt point = points[p]; 363 364 if (point >= cStart && point < cEnd) { 365 ierr = DMLabelClearValue(label,point,values[v]);CHKERRQ(ierr); 366 } 367 } 368 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 369 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 370 } 371 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 372 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 373 PetscFunctionReturn(0); 374 } 375 376 /* take (oldEnd, added) pairs, ordered by height and convert them to (oldstart, newstart) pairs, ordered by ascending 377 * index (skipping first, which is (0,0)) */ 378 PETSC_STATIC_INLINE PetscErrorCode DMPlexShiftPointSetUp_Internal(PetscInt depth, PetscInt depthShift[]) 379 { 380 PetscInt d, off = 0; 381 382 PetscFunctionBegin; 383 /* sort by (oldend): yes this is an O(n^2) sort, we expect depth <= 3 */ 384 for (d = 0; d < depth; d++) { 385 PetscInt firstd = d; 386 PetscInt firstStart = depthShift[2*d]; 387 PetscInt e; 388 389 for (e = d+1; e <= depth; e++) { 390 if (depthShift[2*e] < firstStart) { 391 firstd = e; 392 firstStart = depthShift[2*d]; 393 } 394 } 395 if (firstd != d) { 396 PetscInt swap[2]; 397 398 e = firstd; 399 swap[0] = depthShift[2*d]; 400 swap[1] = depthShift[2*d+1]; 401 depthShift[2*d] = depthShift[2*e]; 402 depthShift[2*d+1] = depthShift[2*e+1]; 403 depthShift[2*e] = swap[0]; 404 depthShift[2*e+1] = swap[1]; 405 } 406 } 407 /* convert (oldstart, added) to (oldstart, newstart) */ 408 for (d = 0; d <= depth; d++) { 409 off += depthShift[2*d+1]; 410 depthShift[2*d+1] = depthShift[2*d] + off; 411 } 412 PetscFunctionReturn(0); 413 } 414 415 /* depthShift is a list of (old, new) pairs */ 416 PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Internal(PetscInt p, PetscInt depth, PetscInt depthShift[]) 417 { 418 PetscInt d; 419 PetscInt newOff = 0; 420 421 for (d = 0; d <= depth; d++) { 422 if (p < depthShift[2*d]) return p + newOff; 423 else newOff = depthShift[2*d+1] - depthShift[2*d]; 424 } 425 return p + newOff; 426 } 427 428 /* depthShift is a list of (old, new) pairs */ 429 PETSC_STATIC_INLINE PetscInt DMPlexShiftPointInverse_Internal(PetscInt p, PetscInt depth, PetscInt depthShift[]) 430 { 431 PetscInt d; 432 PetscInt newOff = 0; 433 434 for (d = 0; d <= depth; d++) { 435 if (p < depthShift[2*d+1]) return p + newOff; 436 else newOff = depthShift[2*d] - depthShift[2*d+1]; 437 } 438 return p + newOff; 439 } 440 441 static PetscErrorCode DMPlexShiftSizes_Internal(DM dm, PetscInt depthShift[], DM dmNew) 442 { 443 PetscInt depth = 0, d, pStart, pEnd, p; 444 DMLabel depthLabel; 445 PetscErrorCode ierr; 446 447 PetscFunctionBegin; 448 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 449 if (depth < 0) PetscFunctionReturn(0); 450 /* Step 1: Expand chart */ 451 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 452 pEnd = DMPlexShiftPoint_Internal(pEnd,depth,depthShift); 453 ierr = DMPlexSetChart(dmNew, pStart, pEnd);CHKERRQ(ierr); 454 ierr = DMCreateLabel(dmNew,"depth");CHKERRQ(ierr); 455 ierr = DMPlexGetDepthLabel(dmNew,&depthLabel);CHKERRQ(ierr); 456 ierr = DMCreateLabel(dmNew, "celltype");CHKERRQ(ierr); 457 /* Step 2: Set cone and support sizes */ 458 for (d = 0; d <= depth; ++d) { 459 PetscInt pStartNew, pEndNew; 460 IS pIS; 461 462 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 463 pStartNew = DMPlexShiftPoint_Internal(pStart, depth, depthShift); 464 pEndNew = DMPlexShiftPoint_Internal(pEnd, depth, depthShift); 465 ierr = ISCreateStride(PETSC_COMM_SELF, pEndNew - pStartNew, pStartNew, 1, &pIS);CHKERRQ(ierr); 466 ierr = DMLabelSetStratumIS(depthLabel, d, pIS);CHKERRQ(ierr); 467 ierr = ISDestroy(&pIS);CHKERRQ(ierr); 468 for (p = pStart; p < pEnd; ++p) { 469 PetscInt newp = DMPlexShiftPoint_Internal(p, depth, depthShift); 470 PetscInt size; 471 DMPolytopeType ct; 472 473 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 474 ierr = DMPlexSetConeSize(dmNew, newp, size);CHKERRQ(ierr); 475 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 476 ierr = DMPlexSetSupportSize(dmNew, newp, size);CHKERRQ(ierr); 477 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 478 ierr = DMPlexSetCellType(dmNew, newp, ct);CHKERRQ(ierr); 479 } 480 } 481 PetscFunctionReturn(0); 482 } 483 484 static PetscErrorCode DMPlexShiftPoints_Internal(DM dm, PetscInt depthShift[], DM dmNew) 485 { 486 PetscInt *newpoints; 487 PetscInt depth = 0, maxConeSize, maxSupportSize, maxConeSizeNew, maxSupportSizeNew, pStart, pEnd, p; 488 PetscErrorCode ierr; 489 490 PetscFunctionBegin; 491 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 492 if (depth < 0) PetscFunctionReturn(0); 493 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 494 ierr = DMPlexGetMaxSizes(dmNew, &maxConeSizeNew, &maxSupportSizeNew);CHKERRQ(ierr); 495 ierr = PetscMalloc1(PetscMax(PetscMax(maxConeSize, maxSupportSize), PetscMax(maxConeSizeNew, maxSupportSizeNew)),&newpoints);CHKERRQ(ierr); 496 /* Step 5: Set cones and supports */ 497 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 498 for (p = pStart; p < pEnd; ++p) { 499 const PetscInt *points = NULL, *orientations = NULL; 500 PetscInt size,sizeNew, i, newp = DMPlexShiftPoint_Internal(p, depth, depthShift); 501 502 ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 503 ierr = DMPlexGetCone(dm, p, &points);CHKERRQ(ierr); 504 ierr = DMPlexGetConeOrientation(dm, p, &orientations);CHKERRQ(ierr); 505 for (i = 0; i < size; ++i) { 506 newpoints[i] = DMPlexShiftPoint_Internal(points[i], depth, depthShift); 507 } 508 ierr = DMPlexSetCone(dmNew, newp, newpoints);CHKERRQ(ierr); 509 ierr = DMPlexSetConeOrientation(dmNew, newp, orientations);CHKERRQ(ierr); 510 ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 511 ierr = DMPlexGetSupportSize(dmNew, newp, &sizeNew);CHKERRQ(ierr); 512 ierr = DMPlexGetSupport(dm, p, &points);CHKERRQ(ierr); 513 for (i = 0; i < size; ++i) { 514 newpoints[i] = DMPlexShiftPoint_Internal(points[i], depth, depthShift); 515 } 516 for (i = size; i < sizeNew; ++i) newpoints[i] = 0; 517 ierr = DMPlexSetSupport(dmNew, newp, newpoints);CHKERRQ(ierr); 518 } 519 ierr = PetscFree(newpoints);CHKERRQ(ierr); 520 PetscFunctionReturn(0); 521 } 522 523 static PetscErrorCode DMPlexShiftCoordinates_Internal(DM dm, PetscInt depthShift[], DM dmNew) 524 { 525 PetscSection coordSection, newCoordSection; 526 Vec coordinates, newCoordinates; 527 PetscScalar *coords, *newCoords; 528 PetscInt coordSize, sStart, sEnd; 529 PetscInt dim, depth = 0, cStart, cEnd, cStartNew, cEndNew, c, vStart, vEnd, vStartNew, vEndNew, v; 530 PetscBool hasCells; 531 PetscErrorCode ierr; 532 533 PetscFunctionBegin; 534 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 535 ierr = DMSetCoordinateDim(dmNew, dim);CHKERRQ(ierr); 536 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 537 /* Step 8: Convert coordinates */ 538 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 539 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 540 ierr = DMPlexGetDepthStratum(dmNew, 0, &vStartNew, &vEndNew);CHKERRQ(ierr); 541 ierr = DMPlexGetHeightStratum(dmNew, 0, &cStartNew, &cEndNew);CHKERRQ(ierr); 542 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 543 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &newCoordSection);CHKERRQ(ierr); 544 ierr = PetscSectionSetNumFields(newCoordSection, 1);CHKERRQ(ierr); 545 ierr = PetscSectionSetFieldComponents(newCoordSection, 0, dim);CHKERRQ(ierr); 546 ierr = PetscSectionGetChart(coordSection, &sStart, &sEnd);CHKERRQ(ierr); 547 hasCells = sStart == cStart ? PETSC_TRUE : PETSC_FALSE; 548 ierr = PetscSectionSetChart(newCoordSection, hasCells ? cStartNew : vStartNew, vEndNew);CHKERRQ(ierr); 549 if (hasCells) { 550 for (c = cStart; c < cEnd; ++c) { 551 PetscInt cNew = DMPlexShiftPoint_Internal(c, depth, depthShift), dof; 552 553 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 554 ierr = PetscSectionSetDof(newCoordSection, cNew, dof);CHKERRQ(ierr); 555 ierr = PetscSectionSetFieldDof(newCoordSection, cNew, 0, dof);CHKERRQ(ierr); 556 } 557 } 558 for (v = vStartNew; v < vEndNew; ++v) { 559 ierr = PetscSectionSetDof(newCoordSection, v, dim);CHKERRQ(ierr); 560 ierr = PetscSectionSetFieldDof(newCoordSection, v, 0, dim);CHKERRQ(ierr); 561 } 562 ierr = PetscSectionSetUp(newCoordSection);CHKERRQ(ierr); 563 ierr = DMSetCoordinateSection(dmNew, PETSC_DETERMINE, newCoordSection);CHKERRQ(ierr); 564 ierr = PetscSectionGetStorageSize(newCoordSection, &coordSize);CHKERRQ(ierr); 565 ierr = VecCreate(PETSC_COMM_SELF, &newCoordinates);CHKERRQ(ierr); 566 ierr = PetscObjectSetName((PetscObject) newCoordinates, "coordinates");CHKERRQ(ierr); 567 ierr = VecSetSizes(newCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 568 ierr = VecSetBlockSize(newCoordinates, dim);CHKERRQ(ierr); 569 ierr = VecSetType(newCoordinates,VECSTANDARD);CHKERRQ(ierr); 570 ierr = DMSetCoordinatesLocal(dmNew, newCoordinates);CHKERRQ(ierr); 571 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 572 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 573 ierr = VecGetArray(newCoordinates, &newCoords);CHKERRQ(ierr); 574 if (hasCells) { 575 for (c = cStart; c < cEnd; ++c) { 576 PetscInt cNew = DMPlexShiftPoint_Internal(c, depth, depthShift), dof, off, noff, d; 577 578 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 579 ierr = PetscSectionGetOffset(coordSection, c, &off);CHKERRQ(ierr); 580 ierr = PetscSectionGetOffset(newCoordSection, cNew, &noff);CHKERRQ(ierr); 581 for (d = 0; d < dof; ++d) newCoords[noff+d] = coords[off+d]; 582 } 583 } 584 for (v = vStart; v < vEnd; ++v) { 585 PetscInt dof, off, noff, d; 586 587 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 588 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 589 ierr = PetscSectionGetOffset(newCoordSection, DMPlexShiftPoint_Internal(v, depth, depthShift), &noff);CHKERRQ(ierr); 590 for (d = 0; d < dof; ++d) newCoords[noff+d] = coords[off+d]; 591 } 592 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 593 ierr = VecRestoreArray(newCoordinates, &newCoords);CHKERRQ(ierr); 594 ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 595 ierr = PetscSectionDestroy(&newCoordSection);CHKERRQ(ierr); 596 PetscFunctionReturn(0); 597 } 598 599 static PetscErrorCode DMPlexShiftSF_Single(DM dm, PetscInt depthShift[], PetscSF sf, PetscSF sfNew) 600 { 601 const PetscSFNode *remotePoints; 602 PetscSFNode *gremotePoints; 603 const PetscInt *localPoints; 604 PetscInt *glocalPoints, *newLocation, *newRemoteLocation; 605 PetscInt numRoots, numLeaves, l, pStart, pEnd, depth = 0, totShift = 0; 606 PetscErrorCode ierr; 607 608 PetscFunctionBegin; 609 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 610 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 611 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 612 totShift = DMPlexShiftPoint_Internal(pEnd, depth, depthShift) - pEnd; 613 if (numRoots >= 0) { 614 ierr = PetscMalloc2(numRoots, &newLocation, pEnd-pStart, &newRemoteLocation);CHKERRQ(ierr); 615 for (l = 0; l < numRoots; ++l) newLocation[l] = DMPlexShiftPoint_Internal(l, depth, depthShift); 616 ierr = PetscSFBcastBegin(sf, MPIU_INT, newLocation, newRemoteLocation, MPI_REPLACE);CHKERRQ(ierr); 617 ierr = PetscSFBcastEnd(sf, MPIU_INT, newLocation, newRemoteLocation, MPI_REPLACE);CHKERRQ(ierr); 618 ierr = PetscMalloc1(numLeaves, &glocalPoints);CHKERRQ(ierr); 619 ierr = PetscMalloc1(numLeaves, &gremotePoints);CHKERRQ(ierr); 620 for (l = 0; l < numLeaves; ++l) { 621 glocalPoints[l] = DMPlexShiftPoint_Internal(localPoints[l], depth, depthShift); 622 gremotePoints[l].rank = remotePoints[l].rank; 623 gremotePoints[l].index = newRemoteLocation[localPoints[l]]; 624 } 625 ierr = PetscFree2(newLocation, newRemoteLocation);CHKERRQ(ierr); 626 ierr = PetscSFSetGraph(sfNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 627 } 628 PetscFunctionReturn(0); 629 } 630 631 static PetscErrorCode DMPlexShiftSF_Internal(DM dm, PetscInt depthShift[], DM dmNew) 632 { 633 PetscSF sfPoint, sfPointNew; 634 PetscBool useNatural; 635 PetscErrorCode ierr; 636 637 PetscFunctionBegin; 638 /* Step 9: Convert pointSF */ 639 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 640 ierr = DMGetPointSF(dmNew, &sfPointNew);CHKERRQ(ierr); 641 ierr = DMPlexShiftSF_Single(dm, depthShift, sfPoint, sfPointNew);CHKERRQ(ierr); 642 /* Step 9b: Convert naturalSF */ 643 ierr = DMGetUseNatural(dm, &useNatural);CHKERRQ(ierr); 644 if (useNatural) { 645 PetscSF sfNat, sfNatNew; 646 647 ierr = DMSetUseNatural(dmNew, useNatural);CHKERRQ(ierr); 648 ierr = DMGetNaturalSF(dm, &sfNat);CHKERRQ(ierr); 649 ierr = DMGetNaturalSF(dmNew, &sfNatNew);CHKERRQ(ierr); 650 ierr = DMPlexShiftSF_Single(dm, depthShift, sfNat, sfNatNew);CHKERRQ(ierr); 651 } 652 PetscFunctionReturn(0); 653 } 654 655 static PetscErrorCode DMPlexShiftLabels_Internal(DM dm, PetscInt depthShift[], DM dmNew) 656 { 657 PetscSF sfPoint; 658 DMLabel vtkLabel, ghostLabel; 659 const PetscSFNode *leafRemote; 660 const PetscInt *leafLocal; 661 PetscInt depth = 0, numLeaves, numLabels, l, cStart, cEnd, c, fStart, fEnd, f; 662 PetscMPIInt rank; 663 PetscErrorCode ierr; 664 665 PetscFunctionBegin; 666 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 667 /* Step 10: Convert labels */ 668 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 669 for (l = 0; l < numLabels; ++l) { 670 DMLabel label, newlabel; 671 const char *lname; 672 PetscBool isDepth, isDim; 673 IS valueIS; 674 const PetscInt *values; 675 PetscInt numValues, val; 676 677 ierr = DMGetLabelName(dm, l, &lname);CHKERRQ(ierr); 678 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 679 if (isDepth) continue; 680 ierr = PetscStrcmp(lname, "dim", &isDim);CHKERRQ(ierr); 681 if (isDim) continue; 682 ierr = DMCreateLabel(dmNew, lname);CHKERRQ(ierr); 683 ierr = DMGetLabel(dm, lname, &label);CHKERRQ(ierr); 684 ierr = DMGetLabel(dmNew, lname, &newlabel);CHKERRQ(ierr); 685 ierr = DMLabelGetDefaultValue(label,&val);CHKERRQ(ierr); 686 ierr = DMLabelSetDefaultValue(newlabel,val);CHKERRQ(ierr); 687 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 688 ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 689 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 690 for (val = 0; val < numValues; ++val) { 691 IS pointIS; 692 const PetscInt *points; 693 PetscInt numPoints, p; 694 695 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 696 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 697 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 698 for (p = 0; p < numPoints; ++p) { 699 const PetscInt newpoint = DMPlexShiftPoint_Internal(points[p], depth, depthShift); 700 701 ierr = DMLabelSetValue(newlabel, newpoint, values[val]);CHKERRQ(ierr); 702 } 703 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 704 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 705 } 706 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 707 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 708 } 709 /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */ 710 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRMPI(ierr); 711 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 712 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 713 ierr = PetscSFGetGraph(sfPoint, NULL, &numLeaves, &leafLocal, &leafRemote);CHKERRQ(ierr); 714 ierr = DMCreateLabel(dmNew, "vtk");CHKERRQ(ierr); 715 ierr = DMCreateLabel(dmNew, "ghost");CHKERRQ(ierr); 716 ierr = DMGetLabel(dmNew, "vtk", &vtkLabel);CHKERRQ(ierr); 717 ierr = DMGetLabel(dmNew, "ghost", &ghostLabel);CHKERRQ(ierr); 718 for (l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) { 719 for (; c < leafLocal[l] && c < cEnd; ++c) { 720 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 721 } 722 if (leafLocal[l] >= cEnd) break; 723 if (leafRemote[l].rank == rank) { 724 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 725 } else { 726 ierr = DMLabelSetValue(ghostLabel, c, 2);CHKERRQ(ierr); 727 } 728 } 729 for (; c < cEnd; ++c) { 730 ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 731 } 732 ierr = DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 733 for (f = fStart; f < fEnd; ++f) { 734 PetscInt numCells; 735 736 ierr = DMPlexGetSupportSize(dmNew, f, &numCells);CHKERRQ(ierr); 737 if (numCells < 2) { 738 ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr); 739 } else { 740 const PetscInt *cells = NULL; 741 PetscInt vA, vB; 742 743 ierr = DMPlexGetSupport(dmNew, f, &cells);CHKERRQ(ierr); 744 ierr = DMLabelGetValue(vtkLabel, cells[0], &vA);CHKERRQ(ierr); 745 ierr = DMLabelGetValue(vtkLabel, cells[1], &vB);CHKERRQ(ierr); 746 if (vA != 1 && vB != 1) {ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr);} 747 } 748 } 749 PetscFunctionReturn(0); 750 } 751 752 static PetscErrorCode DMPlexShiftTree_Internal(DM dm, PetscInt depthShift[], DM dmNew) 753 { 754 DM refTree; 755 PetscSection pSec; 756 PetscInt *parents, *childIDs; 757 PetscErrorCode ierr; 758 759 PetscFunctionBegin; 760 ierr = DMPlexGetReferenceTree(dm,&refTree);CHKERRQ(ierr); 761 ierr = DMPlexSetReferenceTree(dmNew,refTree);CHKERRQ(ierr); 762 ierr = DMPlexGetTree(dm,&pSec,&parents,&childIDs,NULL,NULL);CHKERRQ(ierr); 763 if (pSec) { 764 PetscInt p, pStart, pEnd, *parentsShifted, pStartShifted, pEndShifted, depth; 765 PetscInt *childIDsShifted; 766 PetscSection pSecShifted; 767 768 ierr = PetscSectionGetChart(pSec,&pStart,&pEnd);CHKERRQ(ierr); 769 ierr = DMPlexGetDepth(dm,&depth);CHKERRQ(ierr); 770 pStartShifted = DMPlexShiftPoint_Internal(pStart,depth,depthShift); 771 pEndShifted = DMPlexShiftPoint_Internal(pEnd,depth,depthShift); 772 ierr = PetscMalloc2(pEndShifted - pStartShifted,&parentsShifted,pEndShifted-pStartShifted,&childIDsShifted);CHKERRQ(ierr); 773 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dmNew),&pSecShifted);CHKERRQ(ierr); 774 ierr = PetscSectionSetChart(pSecShifted,pStartShifted,pEndShifted);CHKERRQ(ierr); 775 for (p = pStartShifted; p < pEndShifted; p++) { 776 /* start off assuming no children */ 777 ierr = PetscSectionSetDof(pSecShifted,p,0);CHKERRQ(ierr); 778 } 779 for (p = pStart; p < pEnd; p++) { 780 PetscInt dof; 781 PetscInt pNew = DMPlexShiftPoint_Internal(p,depth,depthShift); 782 783 ierr = PetscSectionGetDof(pSec,p,&dof);CHKERRQ(ierr); 784 ierr = PetscSectionSetDof(pSecShifted,pNew,dof);CHKERRQ(ierr); 785 } 786 ierr = PetscSectionSetUp(pSecShifted);CHKERRQ(ierr); 787 for (p = pStart; p < pEnd; p++) { 788 PetscInt dof; 789 PetscInt pNew = DMPlexShiftPoint_Internal(p,depth,depthShift); 790 791 ierr = PetscSectionGetDof(pSec,p,&dof);CHKERRQ(ierr); 792 if (dof) { 793 PetscInt off, offNew; 794 795 ierr = PetscSectionGetOffset(pSec,p,&off);CHKERRQ(ierr); 796 ierr = PetscSectionGetOffset(pSecShifted,pNew,&offNew);CHKERRQ(ierr); 797 parentsShifted[offNew] = DMPlexShiftPoint_Internal(parents[off],depth,depthShift); 798 childIDsShifted[offNew] = childIDs[off]; 799 } 800 } 801 ierr = DMPlexSetTree(dmNew,pSecShifted,parentsShifted,childIDsShifted);CHKERRQ(ierr); 802 ierr = PetscFree2(parentsShifted,childIDsShifted);CHKERRQ(ierr); 803 ierr = PetscSectionDestroy(&pSecShifted);CHKERRQ(ierr); 804 } 805 PetscFunctionReturn(0); 806 } 807 808 static PetscErrorCode DMPlexConstructGhostCells_Internal(DM dm, DMLabel label, PetscInt *numGhostCells, DM gdm) 809 { 810 PetscSF sf; 811 IS valueIS; 812 const PetscInt *values, *leaves; 813 PetscInt *depthShift; 814 PetscInt d, depth = 0, nleaves, loc, Ng, numFS, fs, fStart, fEnd, ghostCell, cEnd, c; 815 PetscBool isper; 816 const PetscReal *maxCell, *L; 817 const DMBoundaryType *bd; 818 PetscErrorCode ierr; 819 820 PetscFunctionBegin; 821 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 822 ierr = PetscSFGetGraph(sf, NULL, &nleaves, &leaves, NULL);CHKERRQ(ierr); 823 nleaves = PetscMax(0, nleaves); 824 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 825 /* Count ghost cells */ 826 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 827 ierr = ISGetLocalSize(valueIS, &numFS);CHKERRQ(ierr); 828 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 829 Ng = 0; 830 for (fs = 0; fs < numFS; ++fs) { 831 IS faceIS; 832 const PetscInt *faces; 833 PetscInt numFaces, f, numBdFaces = 0; 834 835 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 836 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 837 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 838 for (f = 0; f < numFaces; ++f) { 839 PetscInt numChildren; 840 841 ierr = PetscFindInt(faces[f], nleaves, leaves, &loc);CHKERRQ(ierr); 842 ierr = DMPlexGetTreeChildren(dm,faces[f],&numChildren,NULL);CHKERRQ(ierr); 843 /* non-local and ancestors points don't get to register ghosts */ 844 if (loc >= 0 || numChildren) continue; 845 if ((faces[f] >= fStart) && (faces[f] < fEnd)) ++numBdFaces; 846 } 847 Ng += numBdFaces; 848 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 849 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 850 } 851 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 852 ierr = PetscMalloc1(2*(depth+1), &depthShift);CHKERRQ(ierr); 853 for (d = 0; d <= depth; d++) { 854 PetscInt dEnd; 855 856 ierr = DMPlexGetDepthStratum(dm,d,NULL,&dEnd);CHKERRQ(ierr); 857 depthShift[2*d] = dEnd; 858 depthShift[2*d+1] = 0; 859 } 860 if (depth >= 0) depthShift[2*depth+1] = Ng; 861 ierr = DMPlexShiftPointSetUp_Internal(depth,depthShift);CHKERRQ(ierr); 862 ierr = DMPlexShiftSizes_Internal(dm, depthShift, gdm);CHKERRQ(ierr); 863 /* Step 3: Set cone/support sizes for new points */ 864 ierr = DMPlexGetHeightStratum(dm, 0, NULL, &cEnd);CHKERRQ(ierr); 865 for (c = cEnd; c < cEnd + Ng; ++c) { 866 ierr = DMPlexSetConeSize(gdm, c, 1);CHKERRQ(ierr); 867 } 868 for (fs = 0; fs < numFS; ++fs) { 869 IS faceIS; 870 const PetscInt *faces; 871 PetscInt numFaces, f; 872 873 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 874 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 875 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 876 for (f = 0; f < numFaces; ++f) { 877 PetscInt size, numChildren; 878 879 ierr = PetscFindInt(faces[f], nleaves, leaves, &loc);CHKERRQ(ierr); 880 ierr = DMPlexGetTreeChildren(dm,faces[f],&numChildren,NULL);CHKERRQ(ierr); 881 if (loc >= 0 || numChildren) continue; 882 if ((faces[f] < fStart) || (faces[f] >= fEnd)) continue; 883 ierr = DMPlexGetSupportSize(dm, faces[f], &size);CHKERRQ(ierr); 884 if (size != 1) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM has boundary face %d with %d support cells", faces[f], size); 885 ierr = DMPlexSetSupportSize(gdm, faces[f] + Ng, 2);CHKERRQ(ierr); 886 } 887 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 888 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 889 } 890 /* Step 4: Setup ghosted DM */ 891 ierr = DMSetUp(gdm);CHKERRQ(ierr); 892 ierr = DMPlexShiftPoints_Internal(dm, depthShift, gdm);CHKERRQ(ierr); 893 /* Step 6: Set cones and supports for new points */ 894 ghostCell = cEnd; 895 for (fs = 0; fs < numFS; ++fs) { 896 IS faceIS; 897 const PetscInt *faces; 898 PetscInt numFaces, f; 899 900 ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 901 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 902 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 903 for (f = 0; f < numFaces; ++f) { 904 PetscInt newFace = faces[f] + Ng, numChildren; 905 906 ierr = PetscFindInt(faces[f], nleaves, leaves, &loc);CHKERRQ(ierr); 907 ierr = DMPlexGetTreeChildren(dm,faces[f],&numChildren,NULL);CHKERRQ(ierr); 908 if (loc >= 0 || numChildren) continue; 909 if ((faces[f] < fStart) || (faces[f] >= fEnd)) continue; 910 ierr = DMPlexSetCone(gdm, ghostCell, &newFace);CHKERRQ(ierr); 911 ierr = DMPlexInsertSupport(gdm, newFace, 1, ghostCell);CHKERRQ(ierr); 912 ++ghostCell; 913 } 914 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 915 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 916 } 917 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 918 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 919 ierr = DMPlexShiftCoordinates_Internal(dm, depthShift, gdm);CHKERRQ(ierr); 920 ierr = DMPlexShiftSF_Internal(dm, depthShift, gdm);CHKERRQ(ierr); 921 ierr = DMPlexShiftLabels_Internal(dm, depthShift, gdm);CHKERRQ(ierr); 922 ierr = DMPlexShiftTree_Internal(dm, depthShift, gdm);CHKERRQ(ierr); 923 ierr = PetscFree(depthShift);CHKERRQ(ierr); 924 for (c = cEnd; c < cEnd + Ng; ++c) { 925 ierr = DMPlexSetCellType(gdm, c, DM_POLYTOPE_FV_GHOST);CHKERRQ(ierr); 926 } 927 /* Step 7: Periodicity */ 928 ierr = DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);CHKERRQ(ierr); 929 ierr = DMSetPeriodicity(gdm, isper, maxCell, L, bd);CHKERRQ(ierr); 930 if (numGhostCells) *numGhostCells = Ng; 931 PetscFunctionReturn(0); 932 } 933 934 /*@C 935 DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 936 937 Collective on dm 938 939 Input Parameters: 940 + dm - The original DM 941 - labelName - The label specifying the boundary faces, or "Face Sets" if this is NULL 942 943 Output Parameters: 944 + numGhostCells - The number of ghost cells added to the DM 945 - dmGhosted - The new DM 946 947 Note: If no label exists of that name, one will be created marking all boundary faces 948 949 Level: developer 950 951 .seealso: DMCreate() 952 @*/ 953 PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted) 954 { 955 DM gdm; 956 DMLabel label; 957 const char *name = labelName ? labelName : "Face Sets"; 958 PetscInt dim, Ng = 0; 959 PetscBool useCone, useClosure; 960 PetscErrorCode ierr; 961 962 PetscFunctionBegin; 963 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 964 if (numGhostCells) PetscValidPointer(numGhostCells, 3); 965 PetscValidPointer(dmGhosted, 4); 966 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &gdm);CHKERRQ(ierr); 967 ierr = DMSetType(gdm, DMPLEX);CHKERRQ(ierr); 968 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 969 ierr = DMSetDimension(gdm, dim);CHKERRQ(ierr); 970 ierr = DMGetBasicAdjacency(dm, &useCone, &useClosure);CHKERRQ(ierr); 971 ierr = DMSetBasicAdjacency(gdm, useCone, useClosure);CHKERRQ(ierr); 972 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 973 if (!label) { 974 /* Get label for boundary faces */ 975 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 976 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 977 ierr = DMPlexMarkBoundaryFaces(dm, 1, label);CHKERRQ(ierr); 978 } 979 ierr = DMPlexConstructGhostCells_Internal(dm, label, &Ng, gdm);CHKERRQ(ierr); 980 ierr = DMCopyDisc(dm, gdm);CHKERRQ(ierr); 981 gdm->setfromoptionscalled = dm->setfromoptionscalled; 982 if (numGhostCells) *numGhostCells = Ng; 983 *dmGhosted = gdm; 984 PetscFunctionReturn(0); 985 } 986 987 /* 988 We are adding three kinds of points here: 989 Replicated: Copies of points which exist in the mesh, such as vertices identified across a fault 990 Non-replicated: Points which exist on the fault, but are not replicated 991 Hybrid: Entirely new points, such as cohesive cells 992 993 When creating subsequent cohesive cells, we shift the old hybrid cells to the end of the numbering at 994 each depth so that the new split/hybrid points can be inserted as a block. 995 */ 996 static PetscErrorCode DMPlexConstructCohesiveCells_Internal(DM dm, DMLabel label, DMLabel splitLabel, DM sdm) 997 { 998 MPI_Comm comm; 999 IS valueIS; 1000 PetscInt numSP = 0; /* The number of depths for which we have replicated points */ 1001 const PetscInt *values; /* List of depths for which we have replicated points */ 1002 IS *splitIS; 1003 IS *unsplitIS; 1004 PetscInt *numSplitPoints; /* The number of replicated points at each depth */ 1005 PetscInt *numUnsplitPoints; /* The number of non-replicated points at each depth which still give rise to hybrid points */ 1006 PetscInt *numHybridPoints; /* The number of new hybrid points at each depth */ 1007 PetscInt *numHybridPointsOld; /* The number of existing hybrid points at each depth */ 1008 const PetscInt **splitPoints; /* Replicated points for each depth */ 1009 const PetscInt **unsplitPoints; /* Non-replicated points for each depth */ 1010 PetscSection coordSection; 1011 Vec coordinates; 1012 PetscScalar *coords; 1013 PetscInt *depthMax; /* The first hybrid point at each depth in the original mesh */ 1014 PetscInt *depthEnd; /* The point limit at each depth in the original mesh */ 1015 PetscInt *depthShift; /* Number of replicated+hybrid points at each depth */ 1016 PetscInt *pMaxNew; /* The first replicated point at each depth in the new mesh, hybrids come after this */ 1017 PetscInt *coneNew, *coneONew, *supportNew; 1018 PetscInt shift = 100, shift2 = 200, depth = 0, dep, dim, d, sp, maxConeSize, maxSupportSize, maxConeSizeNew, maxSupportSizeNew, numLabels, vStart, vEnd, pEnd, p, v; 1019 PetscErrorCode ierr; 1020 1021 PetscFunctionBegin; 1022 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 1023 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1024 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1025 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1026 /* We do not want this label automatically computed, instead we compute it here */ 1027 ierr = DMCreateLabel(sdm, "celltype");CHKERRQ(ierr); 1028 /* Count split points and add cohesive cells */ 1029 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 1030 ierr = PetscMalloc5(depth+1,&depthMax,depth+1,&depthEnd,2*(depth+1),&depthShift,depth+1,&pMaxNew,depth+1,&numHybridPointsOld);CHKERRQ(ierr); 1031 ierr = PetscMalloc7(depth+1,&splitIS,depth+1,&unsplitIS,depth+1,&numSplitPoints,depth+1,&numUnsplitPoints,depth+1,&numHybridPoints,depth+1,&splitPoints,depth+1,&unsplitPoints);CHKERRQ(ierr); 1032 for (d = 0; d <= depth; ++d) { 1033 ierr = DMPlexGetDepthStratum(dm, d, NULL, &pMaxNew[d]);CHKERRQ(ierr); 1034 ierr = DMPlexGetTensorPrismBounds_Internal(dm, d, &depthMax[d], NULL);CHKERRQ(ierr); 1035 depthEnd[d] = pMaxNew[d]; 1036 depthMax[d] = depthMax[d] < 0 ? depthEnd[d] : depthMax[d]; 1037 numSplitPoints[d] = 0; 1038 numUnsplitPoints[d] = 0; 1039 numHybridPoints[d] = 0; 1040 numHybridPointsOld[d] = depthMax[d] < 0 ? 0 : depthEnd[d] - depthMax[d]; 1041 splitPoints[d] = NULL; 1042 unsplitPoints[d] = NULL; 1043 splitIS[d] = NULL; 1044 unsplitIS[d] = NULL; 1045 /* we are shifting the existing hybrid points with the stratum behind them, so 1046 * the split comes at the end of the normal points, i.e., at depthMax[d] */ 1047 depthShift[2*d] = depthMax[d]; 1048 depthShift[2*d+1] = 0; 1049 } 1050 if (label) { 1051 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 1052 ierr = ISGetLocalSize(valueIS, &numSP);CHKERRQ(ierr); 1053 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 1054 } 1055 for (sp = 0; sp < numSP; ++sp) { 1056 const PetscInt dep = values[sp]; 1057 1058 if ((dep < 0) || (dep > depth)) continue; 1059 ierr = DMLabelGetStratumIS(label, dep, &splitIS[dep]);CHKERRQ(ierr); 1060 if (splitIS[dep]) { 1061 ierr = ISGetLocalSize(splitIS[dep], &numSplitPoints[dep]);CHKERRQ(ierr); 1062 ierr = ISGetIndices(splitIS[dep], &splitPoints[dep]);CHKERRQ(ierr); 1063 } 1064 ierr = DMLabelGetStratumIS(label, shift2+dep, &unsplitIS[dep]);CHKERRQ(ierr); 1065 if (unsplitIS[dep]) { 1066 ierr = ISGetLocalSize(unsplitIS[dep], &numUnsplitPoints[dep]);CHKERRQ(ierr); 1067 ierr = ISGetIndices(unsplitIS[dep], &unsplitPoints[dep]);CHKERRQ(ierr); 1068 } 1069 } 1070 /* Calculate number of hybrid points */ 1071 for (d = 1; d <= depth; ++d) numHybridPoints[d] = numSplitPoints[d-1] + numUnsplitPoints[d-1]; /* There is a hybrid cell/face/edge for every split face/edge/vertex */ 1072 for (d = 0; d <= depth; ++d) depthShift[2*d+1] = numSplitPoints[d] + numHybridPoints[d]; 1073 ierr = DMPlexShiftPointSetUp_Internal(depth,depthShift);CHKERRQ(ierr); 1074 /* the end of the points in this stratum that come before the new points: 1075 * shifting pMaxNew[d] gets the new start of the next stratum, then count back the old hybrid points and the newly 1076 * added points */ 1077 for (d = 0; d <= depth; ++d) pMaxNew[d] = DMPlexShiftPoint_Internal(pMaxNew[d],depth,depthShift) - (numHybridPointsOld[d] + numSplitPoints[d] + numHybridPoints[d]); 1078 ierr = DMPlexShiftSizes_Internal(dm, depthShift, sdm);CHKERRQ(ierr); 1079 /* Step 3: Set cone/support sizes for new points */ 1080 for (dep = 0; dep <= depth; ++dep) { 1081 for (p = 0; p < numSplitPoints[dep]; ++p) { 1082 const PetscInt oldp = splitPoints[dep][p]; 1083 const PetscInt newp = DMPlexShiftPoint_Internal(oldp, depth, depthShift) /*oldp + depthOffset[dep]*/; 1084 const PetscInt splitp = p + pMaxNew[dep]; 1085 const PetscInt *support; 1086 DMPolytopeType ct; 1087 PetscInt coneSize, supportSize, qf, qn, qp, e; 1088 1089 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 1090 ierr = DMPlexSetConeSize(sdm, splitp, coneSize);CHKERRQ(ierr); 1091 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 1092 ierr = DMPlexSetSupportSize(sdm, splitp, supportSize);CHKERRQ(ierr); 1093 ierr = DMPlexGetCellType(dm, oldp, &ct);CHKERRQ(ierr); 1094 ierr = DMPlexSetCellType(sdm, splitp, ct);CHKERRQ(ierr); 1095 if (dep == depth-1) { 1096 const PetscInt hybcell = p + pMaxNew[dep+1] + numSplitPoints[dep+1]; 1097 1098 /* Add cohesive cells, they are prisms */ 1099 ierr = DMPlexSetConeSize(sdm, hybcell, 2 + coneSize);CHKERRQ(ierr); 1100 switch (coneSize) { 1101 case 2: ierr = DMPlexSetCellType(sdm, hybcell, DM_POLYTOPE_SEG_PRISM_TENSOR);CHKERRQ(ierr);break; 1102 case 3: ierr = DMPlexSetCellType(sdm, hybcell, DM_POLYTOPE_TRI_PRISM_TENSOR);CHKERRQ(ierr);break; 1103 case 4: ierr = DMPlexSetCellType(sdm, hybcell, DM_POLYTOPE_QUAD_PRISM_TENSOR);CHKERRQ(ierr);break; 1104 } 1105 } else if (dep == 0) { 1106 const PetscInt hybedge = p + pMaxNew[dep+1] + numSplitPoints[dep+1]; 1107 1108 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 1109 for (e = 0, qn = 0, qp = 0, qf = 0; e < supportSize; ++e) { 1110 PetscInt val; 1111 1112 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 1113 if (val == 1) ++qf; 1114 if ((val == 1) || (val == (shift + 1))) ++qn; 1115 if ((val == 1) || (val == -(shift + 1))) ++qp; 1116 } 1117 /* Split old vertex: Edges into original vertex and new cohesive edge */ 1118 ierr = DMPlexSetSupportSize(sdm, newp, qn+1);CHKERRQ(ierr); 1119 /* Split new vertex: Edges into split vertex and new cohesive edge */ 1120 ierr = DMPlexSetSupportSize(sdm, splitp, qp+1);CHKERRQ(ierr); 1121 /* Add hybrid edge */ 1122 ierr = DMPlexSetConeSize(sdm, hybedge, 2);CHKERRQ(ierr); 1123 ierr = DMPlexSetSupportSize(sdm, hybedge, qf);CHKERRQ(ierr); 1124 ierr = DMPlexSetCellType(sdm, hybedge, DM_POLYTOPE_POINT_PRISM_TENSOR);CHKERRQ(ierr); 1125 } else if (dep == dim-2) { 1126 const PetscInt hybface = p + pMaxNew[dep+1] + numSplitPoints[dep+1]; 1127 1128 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 1129 for (e = 0, qn = 0, qp = 0, qf = 0; e < supportSize; ++e) { 1130 PetscInt val; 1131 1132 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 1133 if (val == dim-1) ++qf; 1134 if ((val == dim-1) || (val == (shift + dim-1))) ++qn; 1135 if ((val == dim-1) || (val == -(shift + dim-1))) ++qp; 1136 } 1137 /* Split old edge: Faces into original edge and cohesive face (positive side?) */ 1138 ierr = DMPlexSetSupportSize(sdm, newp, qn+1);CHKERRQ(ierr); 1139 /* Split new edge: Faces into split edge and cohesive face (negative side?) */ 1140 ierr = DMPlexSetSupportSize(sdm, splitp, qp+1);CHKERRQ(ierr); 1141 /* Add hybrid face */ 1142 ierr = DMPlexSetConeSize(sdm, hybface, 4);CHKERRQ(ierr); 1143 ierr = DMPlexSetSupportSize(sdm, hybface, qf);CHKERRQ(ierr); 1144 ierr = DMPlexSetCellType(sdm, hybface, DM_POLYTOPE_SEG_PRISM_TENSOR);CHKERRQ(ierr); 1145 } 1146 } 1147 } 1148 for (dep = 0; dep <= depth; ++dep) { 1149 for (p = 0; p < numUnsplitPoints[dep]; ++p) { 1150 const PetscInt oldp = unsplitPoints[dep][p]; 1151 const PetscInt newp = DMPlexShiftPoint_Internal(oldp, depth, depthShift) /*oldp + depthOffset[dep]*/; 1152 const PetscInt *support; 1153 PetscInt coneSize, supportSize, qf, e, s; 1154 1155 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 1156 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 1157 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 1158 if (dep == 0) { 1159 const PetscInt hybedge = p + pMaxNew[dep+1] + numSplitPoints[dep+1] + numSplitPoints[dep]; 1160 1161 /* Unsplit vertex: Edges into original vertex, split edges, and new cohesive edge twice */ 1162 for (s = 0, qf = 0; s < supportSize; ++s, ++qf) { 1163 ierr = PetscFindInt(support[s], numSplitPoints[dep+1], splitPoints[dep+1], &e);CHKERRQ(ierr); 1164 if (e >= 0) ++qf; 1165 } 1166 ierr = DMPlexSetSupportSize(sdm, newp, qf+2);CHKERRQ(ierr); 1167 /* Add hybrid edge */ 1168 ierr = DMPlexSetConeSize(sdm, hybedge, 2);CHKERRQ(ierr); 1169 for (e = 0, qf = 0; e < supportSize; ++e) { 1170 PetscInt val; 1171 1172 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 1173 /* Split and unsplit edges produce hybrid faces */ 1174 if (val == 1) ++qf; 1175 if (val == (shift2 + 1)) ++qf; 1176 } 1177 ierr = DMPlexSetSupportSize(sdm, hybedge, qf);CHKERRQ(ierr); 1178 ierr = DMPlexSetCellType(sdm, hybedge, DM_POLYTOPE_POINT_PRISM_TENSOR);CHKERRQ(ierr); 1179 } else if (dep == dim-2) { 1180 const PetscInt hybface = p + pMaxNew[dep+1] + numSplitPoints[dep+1] + numSplitPoints[dep]; 1181 PetscInt val; 1182 1183 for (e = 0, qf = 0; e < supportSize; ++e) { 1184 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 1185 if (val == dim-1) qf += 2; 1186 else ++qf; 1187 } 1188 /* Unsplit edge: Faces into original edge, split face, and cohesive face twice */ 1189 ierr = DMPlexSetSupportSize(sdm, newp, qf+2);CHKERRQ(ierr); 1190 /* Add hybrid face */ 1191 for (e = 0, qf = 0; e < supportSize; ++e) { 1192 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 1193 if (val == dim-1) ++qf; 1194 } 1195 ierr = DMPlexSetConeSize(sdm, hybface, 4);CHKERRQ(ierr); 1196 ierr = DMPlexSetSupportSize(sdm, hybface, qf);CHKERRQ(ierr); 1197 ierr = DMPlexSetCellType(sdm, hybface, DM_POLYTOPE_SEG_PRISM_TENSOR);CHKERRQ(ierr); 1198 } 1199 } 1200 } 1201 /* Step 4: Setup split DM */ 1202 ierr = DMSetUp(sdm);CHKERRQ(ierr); 1203 ierr = DMPlexShiftPoints_Internal(dm, depthShift, sdm);CHKERRQ(ierr); 1204 ierr = DMPlexGetMaxSizes(sdm, &maxConeSizeNew, &maxSupportSizeNew);CHKERRQ(ierr); 1205 ierr = PetscMalloc3(PetscMax(maxConeSize, maxConeSizeNew)*3,&coneNew,PetscMax(maxConeSize, maxConeSizeNew)*3,&coneONew,PetscMax(maxSupportSize, maxSupportSizeNew),&supportNew);CHKERRQ(ierr); 1206 /* Step 6: Set cones and supports for new points */ 1207 for (dep = 0; dep <= depth; ++dep) { 1208 for (p = 0; p < numSplitPoints[dep]; ++p) { 1209 const PetscInt oldp = splitPoints[dep][p]; 1210 const PetscInt newp = DMPlexShiftPoint_Internal(oldp, depth, depthShift) /*oldp + depthOffset[dep]*/; 1211 const PetscInt splitp = p + pMaxNew[dep]; 1212 const PetscInt *cone, *support, *ornt; 1213 DMPolytopeType ct; 1214 PetscInt coneSize, supportSize, q, qf, qn, qp, v, e, s; 1215 1216 ierr = DMPlexGetCellType(dm, oldp, &ct);CHKERRQ(ierr); 1217 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 1218 ierr = DMPlexGetCone(dm, oldp, &cone);CHKERRQ(ierr); 1219 ierr = DMPlexGetConeOrientation(dm, oldp, &ornt);CHKERRQ(ierr); 1220 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 1221 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 1222 if (dep == depth-1) { 1223 PetscBool hasUnsplit = PETSC_FALSE; 1224 const PetscInt hybcell = p + pMaxNew[dep+1] + numSplitPoints[dep+1]; 1225 const PetscInt *supportF; 1226 1227 /* Split face: copy in old face to new face to start */ 1228 ierr = DMPlexGetSupport(sdm, newp, &supportF);CHKERRQ(ierr); 1229 ierr = DMPlexSetSupport(sdm, splitp, supportF);CHKERRQ(ierr); 1230 /* Split old face: old vertices/edges in cone so no change */ 1231 /* Split new face: new vertices/edges in cone */ 1232 for (q = 0; q < coneSize; ++q) { 1233 ierr = PetscFindInt(cone[q], numSplitPoints[dep-1], splitPoints[dep-1], &v);CHKERRQ(ierr); 1234 if (v < 0) { 1235 ierr = PetscFindInt(cone[q], numUnsplitPoints[dep-1], unsplitPoints[dep-1], &v);CHKERRQ(ierr); 1236 if (v < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not locate point %d in split or unsplit points of depth %d", cone[q], dep-1); 1237 coneNew[2+q] = DMPlexShiftPoint_Internal(cone[q], depth, depthShift) /*cone[q] + depthOffset[dep-1]*/; 1238 hasUnsplit = PETSC_TRUE; 1239 } else { 1240 coneNew[2+q] = v + pMaxNew[dep-1]; 1241 if (dep > 1) { 1242 const PetscInt *econe; 1243 PetscInt econeSize, r, vs, vu; 1244 1245 ierr = DMPlexGetConeSize(dm, cone[q], &econeSize);CHKERRQ(ierr); 1246 ierr = DMPlexGetCone(dm, cone[q], &econe);CHKERRQ(ierr); 1247 for (r = 0; r < econeSize; ++r) { 1248 ierr = PetscFindInt(econe[r], numSplitPoints[dep-2], splitPoints[dep-2], &vs);CHKERRQ(ierr); 1249 ierr = PetscFindInt(econe[r], numUnsplitPoints[dep-2], unsplitPoints[dep-2], &vu);CHKERRQ(ierr); 1250 if (vs >= 0) continue; 1251 if (vu < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not locate point %d in split or unsplit points of depth %d", econe[r], dep-2); 1252 hasUnsplit = PETSC_TRUE; 1253 } 1254 } 1255 } 1256 } 1257 ierr = DMPlexSetCone(sdm, splitp, &coneNew[2]);CHKERRQ(ierr); 1258 ierr = DMPlexSetConeOrientation(sdm, splitp, ornt);CHKERRQ(ierr); 1259 /* Face support */ 1260 for (s = 0; s < supportSize; ++s) { 1261 PetscInt val; 1262 1263 ierr = DMLabelGetValue(label, support[s], &val);CHKERRQ(ierr); 1264 if (val < 0) { 1265 /* Split old face: Replace negative side cell with cohesive cell */ 1266 ierr = DMPlexInsertSupport(sdm, newp, s, hybcell);CHKERRQ(ierr); 1267 } else { 1268 /* Split new face: Replace positive side cell with cohesive cell */ 1269 ierr = DMPlexInsertSupport(sdm, splitp, s, hybcell);CHKERRQ(ierr); 1270 /* Get orientation for cohesive face */ 1271 { 1272 const PetscInt *ncone, *nconeO; 1273 PetscInt nconeSize, nc; 1274 1275 ierr = DMPlexGetConeSize(dm, support[s], &nconeSize);CHKERRQ(ierr); 1276 ierr = DMPlexGetCone(dm, support[s], &ncone);CHKERRQ(ierr); 1277 ierr = DMPlexGetConeOrientation(dm, support[s], &nconeO);CHKERRQ(ierr); 1278 for (nc = 0; nc < nconeSize; ++nc) { 1279 if (ncone[nc] == oldp) { 1280 coneONew[0] = nconeO[nc]; 1281 break; 1282 } 1283 } 1284 if (nc >= nconeSize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not locate face %d in neighboring cell %d", oldp, support[s]); 1285 } 1286 } 1287 } 1288 /* Cohesive cell: Old and new split face, then new cohesive faces */ 1289 const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, coneONew[0]); 1290 1291 coneNew[0] = newp; /* Extracted negative side orientation above */ 1292 coneNew[1] = splitp; 1293 coneONew[1] = coneONew[0]; 1294 for (q = 0; q < coneSize; ++q) { 1295 /* Hybrid faces must follow order from oriented end face */ 1296 const PetscInt qa = arr[q*2+0]; 1297 const PetscInt qo = arr[q*2+1]; 1298 DMPolytopeType ft = dep == 2 ? DM_POLYTOPE_SEGMENT : DM_POLYTOPE_POINT; 1299 1300 ierr = PetscFindInt(cone[qa], numSplitPoints[dep-1], splitPoints[dep-1], &v);CHKERRQ(ierr); 1301 if (v < 0) { 1302 ierr = PetscFindInt(cone[qa], numUnsplitPoints[dep-1], unsplitPoints[dep-1], &v);CHKERRQ(ierr); 1303 coneNew[2+q] = v + pMaxNew[dep] + numSplitPoints[dep] + numSplitPoints[dep-1]; 1304 } else { 1305 coneNew[2+q] = v + pMaxNew[dep] + numSplitPoints[dep]; 1306 } 1307 coneONew[2+q] = DMPolytopeTypeComposeOrientation(ft, qo, ornt[qa]); 1308 } 1309 ierr = DMPlexSetCone(sdm, hybcell, coneNew);CHKERRQ(ierr); 1310 ierr = DMPlexSetConeOrientation(sdm, hybcell, coneONew);CHKERRQ(ierr); 1311 /* Label the hybrid cells on the boundary of the split */ 1312 if (hasUnsplit) {ierr = DMLabelSetValue(label, -hybcell, dim);CHKERRQ(ierr);} 1313 } else if (dep == 0) { 1314 const PetscInt hybedge = p + pMaxNew[dep+1] + numSplitPoints[dep+1]; 1315 1316 /* Split old vertex: Edges in old split faces and new cohesive edge */ 1317 for (e = 0, qn = 0; e < supportSize; ++e) { 1318 PetscInt val; 1319 1320 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 1321 if ((val == 1) || (val == (shift + 1))) { 1322 supportNew[qn++] = DMPlexShiftPoint_Internal(support[e], depth, depthShift) /*support[e] + depthOffset[dep+1]*/; 1323 } 1324 } 1325 supportNew[qn] = hybedge; 1326 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 1327 /* Split new vertex: Edges in new split faces and new cohesive edge */ 1328 for (e = 0, qp = 0; e < supportSize; ++e) { 1329 PetscInt val, edge; 1330 1331 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 1332 if (val == 1) { 1333 ierr = PetscFindInt(support[e], numSplitPoints[dep+1], splitPoints[dep+1], &edge);CHKERRQ(ierr); 1334 if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a split edge", support[e]); 1335 supportNew[qp++] = edge + pMaxNew[dep+1]; 1336 } else if (val == -(shift + 1)) { 1337 supportNew[qp++] = DMPlexShiftPoint_Internal(support[e], depth, depthShift) /*support[e] + depthOffset[dep+1]*/; 1338 } 1339 } 1340 supportNew[qp] = hybedge; 1341 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 1342 /* Hybrid edge: Old and new split vertex */ 1343 coneNew[0] = newp; 1344 coneNew[1] = splitp; 1345 ierr = DMPlexSetCone(sdm, hybedge, coneNew);CHKERRQ(ierr); 1346 for (e = 0, qf = 0; e < supportSize; ++e) { 1347 PetscInt val, edge; 1348 1349 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 1350 if (val == 1) { 1351 ierr = PetscFindInt(support[e], numSplitPoints[dep+1], splitPoints[dep+1], &edge);CHKERRQ(ierr); 1352 if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a split edge", support[e]); 1353 supportNew[qf++] = edge + pMaxNew[dep+2] + numSplitPoints[dep+2]; 1354 } 1355 } 1356 ierr = DMPlexSetSupport(sdm, hybedge, supportNew);CHKERRQ(ierr); 1357 } else if (dep == dim-2) { 1358 const PetscInt hybface = p + pMaxNew[dep+1] + numSplitPoints[dep+1]; 1359 1360 /* Split old edge: old vertices in cone so no change */ 1361 /* Split new edge: new vertices in cone */ 1362 for (q = 0; q < coneSize; ++q) { 1363 ierr = PetscFindInt(cone[q], numSplitPoints[dep-1], splitPoints[dep-1], &v);CHKERRQ(ierr); 1364 if (v < 0) { 1365 ierr = PetscFindInt(cone[q], numUnsplitPoints[dep-1], unsplitPoints[dep-1], &v);CHKERRQ(ierr); 1366 if (v < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not locate point %d in split or unsplit points of depth %d", cone[q], dep-1); 1367 coneNew[q] = DMPlexShiftPoint_Internal(cone[q], depth, depthShift) /*cone[q] + depthOffset[dep-1]*/; 1368 } else { 1369 coneNew[q] = v + pMaxNew[dep-1]; 1370 } 1371 } 1372 ierr = DMPlexSetCone(sdm, splitp, coneNew);CHKERRQ(ierr); 1373 /* Split old edge: Faces in positive side cells and old split faces */ 1374 for (e = 0, q = 0; e < supportSize; ++e) { 1375 PetscInt val; 1376 1377 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 1378 if (val == dim-1) { 1379 supportNew[q++] = DMPlexShiftPoint_Internal(support[e], depth, depthShift) /*support[e] + depthOffset[dep+1]*/; 1380 } else if (val == (shift + dim-1)) { 1381 supportNew[q++] = DMPlexShiftPoint_Internal(support[e], depth, depthShift) /*support[e] + depthOffset[dep+1]*/; 1382 } 1383 } 1384 supportNew[q++] = p + pMaxNew[dep+1] + numSplitPoints[dep+1]; 1385 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 1386 /* Split new edge: Faces in negative side cells and new split faces */ 1387 for (e = 0, q = 0; e < supportSize; ++e) { 1388 PetscInt val, face; 1389 1390 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 1391 if (val == dim-1) { 1392 ierr = PetscFindInt(support[e], numSplitPoints[dep+1], splitPoints[dep+1], &face);CHKERRQ(ierr); 1393 if (face < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Face %d is not a split face", support[e]); 1394 supportNew[q++] = face + pMaxNew[dep+1]; 1395 } else if (val == -(shift + dim-1)) { 1396 supportNew[q++] = DMPlexShiftPoint_Internal(support[e], depth, depthShift) /*support[e] + depthOffset[dep+1]*/; 1397 } 1398 } 1399 supportNew[q++] = p + pMaxNew[dep+1] + numSplitPoints[dep+1]; 1400 ierr = DMPlexSetSupport(sdm, splitp, supportNew);CHKERRQ(ierr); 1401 /* Hybrid face */ 1402 coneNew[0] = newp; 1403 coneNew[1] = splitp; 1404 for (v = 0; v < coneSize; ++v) { 1405 PetscInt vertex; 1406 ierr = PetscFindInt(cone[v], numSplitPoints[dep-1], splitPoints[dep-1], &vertex);CHKERRQ(ierr); 1407 if (vertex < 0) { 1408 ierr = PetscFindInt(cone[v], numUnsplitPoints[dep-1], unsplitPoints[dep-1], &vertex);CHKERRQ(ierr); 1409 if (vertex < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not locate point %d in split or unsplit points of depth %d", cone[v], dep-1); 1410 coneNew[2+v] = vertex + pMaxNew[dep] + numSplitPoints[dep] + numSplitPoints[dep-1]; 1411 } else { 1412 coneNew[2+v] = vertex + pMaxNew[dep] + numSplitPoints[dep]; 1413 } 1414 } 1415 ierr = DMPlexSetCone(sdm, hybface, coneNew);CHKERRQ(ierr); 1416 for (e = 0, qf = 0; e < supportSize; ++e) { 1417 PetscInt val, face; 1418 1419 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 1420 if (val == dim-1) { 1421 ierr = PetscFindInt(support[e], numSplitPoints[dep+1], splitPoints[dep+1], &face);CHKERRQ(ierr); 1422 if (face < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Face %d is not a split face", support[e]); 1423 supportNew[qf++] = face + pMaxNew[dep+2] + numSplitPoints[dep+2]; 1424 } 1425 } 1426 ierr = DMPlexSetSupport(sdm, hybface, supportNew);CHKERRQ(ierr); 1427 } 1428 } 1429 } 1430 for (dep = 0; dep <= depth; ++dep) { 1431 for (p = 0; p < numUnsplitPoints[dep]; ++p) { 1432 const PetscInt oldp = unsplitPoints[dep][p]; 1433 const PetscInt newp = DMPlexShiftPoint_Internal(oldp, depth, depthShift) /*oldp + depthOffset[dep]*/; 1434 const PetscInt *cone, *support; 1435 PetscInt coneSize, supportSize, supportSizeNew, q, qf, e, f, s; 1436 1437 ierr = DMPlexGetConeSize(dm, oldp, &coneSize);CHKERRQ(ierr); 1438 ierr = DMPlexGetCone(dm, oldp, &cone);CHKERRQ(ierr); 1439 ierr = DMPlexGetSupportSize(dm, oldp, &supportSize);CHKERRQ(ierr); 1440 ierr = DMPlexGetSupport(dm, oldp, &support);CHKERRQ(ierr); 1441 if (dep == 0) { 1442 const PetscInt hybedge = p + pMaxNew[dep+1] + numSplitPoints[dep+1] + numSplitPoints[dep]; 1443 1444 /* Unsplit vertex */ 1445 ierr = DMPlexGetSupportSize(sdm, newp, &supportSizeNew);CHKERRQ(ierr); 1446 for (s = 0, q = 0; s < supportSize; ++s) { 1447 supportNew[q++] = DMPlexShiftPoint_Internal(support[s], depth, depthShift) /*support[s] + depthOffset[dep+1]*/; 1448 ierr = PetscFindInt(support[s], numSplitPoints[dep+1], splitPoints[dep+1], &e);CHKERRQ(ierr); 1449 if (e >= 0) { 1450 supportNew[q++] = e + pMaxNew[dep+1]; 1451 } 1452 } 1453 supportNew[q++] = hybedge; 1454 supportNew[q++] = hybedge; 1455 if (q != supportSizeNew) SETERRQ3(comm, PETSC_ERR_ARG_WRONG, "Support size %d != %d for vertex %d", q, supportSizeNew, newp); 1456 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 1457 /* Hybrid edge */ 1458 coneNew[0] = newp; 1459 coneNew[1] = newp; 1460 ierr = DMPlexSetCone(sdm, hybedge, coneNew);CHKERRQ(ierr); 1461 for (e = 0, qf = 0; e < supportSize; ++e) { 1462 PetscInt val, edge; 1463 1464 ierr = DMLabelGetValue(label, support[e], &val);CHKERRQ(ierr); 1465 if (val == 1) { 1466 ierr = PetscFindInt(support[e], numSplitPoints[dep+1], splitPoints[dep+1], &edge);CHKERRQ(ierr); 1467 if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a split edge", support[e]); 1468 supportNew[qf++] = edge + pMaxNew[dep+2] + numSplitPoints[dep+2]; 1469 } else if (val == (shift2 + 1)) { 1470 ierr = PetscFindInt(support[e], numUnsplitPoints[dep+1], unsplitPoints[dep+1], &edge);CHKERRQ(ierr); 1471 if (edge < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Edge %d is not a unsplit edge", support[e]); 1472 supportNew[qf++] = edge + pMaxNew[dep+2] + numSplitPoints[dep+2] + numSplitPoints[dep+1]; 1473 } 1474 } 1475 ierr = DMPlexSetSupport(sdm, hybedge, supportNew);CHKERRQ(ierr); 1476 } else if (dep == dim-2) { 1477 const PetscInt hybface = p + pMaxNew[dep+1] + numSplitPoints[dep+1] + numSplitPoints[dep]; 1478 1479 /* Unsplit edge: Faces into original edge, split face, and hybrid face twice */ 1480 for (f = 0, qf = 0; f < supportSize; ++f) { 1481 PetscInt val, face; 1482 1483 ierr = DMLabelGetValue(label, support[f], &val);CHKERRQ(ierr); 1484 if (val == dim-1) { 1485 ierr = PetscFindInt(support[f], numSplitPoints[dep+1], splitPoints[dep+1], &face);CHKERRQ(ierr); 1486 if (face < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Face %d is not a split face", support[f]); 1487 supportNew[qf++] = DMPlexShiftPoint_Internal(support[f], depth, depthShift) /*support[f] + depthOffset[dep+1]*/; 1488 supportNew[qf++] = face + pMaxNew[dep+1]; 1489 } else { 1490 supportNew[qf++] = DMPlexShiftPoint_Internal(support[f], depth, depthShift) /*support[f] + depthOffset[dep+1]*/; 1491 } 1492 } 1493 supportNew[qf++] = hybface; 1494 supportNew[qf++] = hybface; 1495 ierr = DMPlexGetSupportSize(sdm, newp, &supportSizeNew);CHKERRQ(ierr); 1496 if (qf != supportSizeNew) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Support size for unsplit edge %d is %d != %d", newp, qf, supportSizeNew); 1497 ierr = DMPlexSetSupport(sdm, newp, supportNew);CHKERRQ(ierr); 1498 /* Add hybrid face */ 1499 coneNew[0] = newp; 1500 coneNew[1] = newp; 1501 ierr = PetscFindInt(cone[0], numUnsplitPoints[dep-1], unsplitPoints[dep-1], &v);CHKERRQ(ierr); 1502 if (v < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Vertex %d is not an unsplit vertex", cone[0]); 1503 coneNew[2] = v + pMaxNew[dep] + numSplitPoints[dep] + numSplitPoints[dep-1]; 1504 ierr = PetscFindInt(cone[1], numUnsplitPoints[dep-1], unsplitPoints[dep-1], &v);CHKERRQ(ierr); 1505 if (v < 0) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Vertex %d is not an unsplit vertex", cone[1]); 1506 coneNew[3] = v + pMaxNew[dep] + numSplitPoints[dep] + numSplitPoints[dep-1]; 1507 ierr = DMPlexSetCone(sdm, hybface, coneNew);CHKERRQ(ierr); 1508 for (f = 0, qf = 0; f < supportSize; ++f) { 1509 PetscInt val, face; 1510 1511 ierr = DMLabelGetValue(label, support[f], &val);CHKERRQ(ierr); 1512 if (val == dim-1) { 1513 ierr = PetscFindInt(support[f], numSplitPoints[dep+1], splitPoints[dep+1], &face);CHKERRQ(ierr); 1514 supportNew[qf++] = face + pMaxNew[dep+2] + numSplitPoints[dep+2]; 1515 } 1516 } 1517 ierr = DMPlexGetSupportSize(sdm, hybface, &supportSizeNew);CHKERRQ(ierr); 1518 if (qf != supportSizeNew) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Support size for hybrid face %d is %d != %d", hybface, qf, supportSizeNew); 1519 ierr = DMPlexSetSupport(sdm, hybface, supportNew);CHKERRQ(ierr); 1520 } 1521 } 1522 } 1523 /* Step 6b: Replace split points in negative side cones */ 1524 for (sp = 0; sp < numSP; ++sp) { 1525 PetscInt dep = values[sp]; 1526 IS pIS; 1527 PetscInt numPoints; 1528 const PetscInt *points; 1529 1530 if (dep >= 0) continue; 1531 ierr = DMLabelGetStratumIS(label, dep, &pIS);CHKERRQ(ierr); 1532 if (!pIS) continue; 1533 dep = -dep - shift; 1534 ierr = ISGetLocalSize(pIS, &numPoints);CHKERRQ(ierr); 1535 ierr = ISGetIndices(pIS, &points);CHKERRQ(ierr); 1536 for (p = 0; p < numPoints; ++p) { 1537 const PetscInt oldp = points[p]; 1538 const PetscInt newp = DMPlexShiftPoint_Internal(oldp, depth, depthShift) /*depthOffset[dep] + oldp*/; 1539 const PetscInt *cone; 1540 PetscInt coneSize, c; 1541 /* PetscBool replaced = PETSC_FALSE; */ 1542 1543 /* Negative edge: replace split vertex */ 1544 /* Negative cell: replace split face */ 1545 ierr = DMPlexGetConeSize(sdm, newp, &coneSize);CHKERRQ(ierr); 1546 ierr = DMPlexGetCone(sdm, newp, &cone);CHKERRQ(ierr); 1547 for (c = 0; c < coneSize; ++c) { 1548 const PetscInt coldp = DMPlexShiftPointInverse_Internal(cone[c],depth,depthShift); 1549 PetscInt csplitp, cp, val; 1550 1551 ierr = DMLabelGetValue(label, coldp, &val);CHKERRQ(ierr); 1552 if (val == dep-1) { 1553 ierr = PetscFindInt(coldp, numSplitPoints[dep-1], splitPoints[dep-1], &cp);CHKERRQ(ierr); 1554 if (cp < 0) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "Point %d is not a split point of dimension %d", oldp, dep-1); 1555 csplitp = pMaxNew[dep-1] + cp; 1556 ierr = DMPlexInsertCone(sdm, newp, c, csplitp);CHKERRQ(ierr); 1557 /* replaced = PETSC_TRUE; */ 1558 } 1559 } 1560 /* Cells with only a vertex or edge on the submesh have no replacement */ 1561 /* if (!replaced) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "The cone of point %d does not contain split points", oldp); */ 1562 } 1563 ierr = ISRestoreIndices(pIS, &points);CHKERRQ(ierr); 1564 ierr = ISDestroy(&pIS);CHKERRQ(ierr); 1565 } 1566 /* Step 7: Coordinates */ 1567 ierr = DMPlexShiftCoordinates_Internal(dm, depthShift, sdm);CHKERRQ(ierr); 1568 ierr = DMGetCoordinateSection(sdm, &coordSection);CHKERRQ(ierr); 1569 ierr = DMGetCoordinatesLocal(sdm, &coordinates);CHKERRQ(ierr); 1570 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 1571 for (v = 0; v < (numSplitPoints ? numSplitPoints[0] : 0); ++v) { 1572 const PetscInt newp = DMPlexShiftPoint_Internal(splitPoints[0][v], depth, depthShift) /*depthOffset[0] + splitPoints[0][v]*/; 1573 const PetscInt splitp = pMaxNew[0] + v; 1574 PetscInt dof, off, soff, d; 1575 1576 ierr = PetscSectionGetDof(coordSection, newp, &dof);CHKERRQ(ierr); 1577 ierr = PetscSectionGetOffset(coordSection, newp, &off);CHKERRQ(ierr); 1578 ierr = PetscSectionGetOffset(coordSection, splitp, &soff);CHKERRQ(ierr); 1579 for (d = 0; d < dof; ++d) coords[soff+d] = coords[off+d]; 1580 } 1581 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 1582 /* Step 8: SF, if I can figure this out we can split the mesh in parallel */ 1583 ierr = DMPlexShiftSF_Internal(dm, depthShift, sdm);CHKERRQ(ierr); 1584 /* Step 9: Labels */ 1585 ierr = DMPlexShiftLabels_Internal(dm, depthShift, sdm);CHKERRQ(ierr); 1586 ierr = DMGetNumLabels(sdm, &numLabels);CHKERRQ(ierr); 1587 for (dep = 0; dep <= depth; ++dep) { 1588 for (p = 0; p < numSplitPoints[dep]; ++p) { 1589 const PetscInt newp = DMPlexShiftPoint_Internal(splitPoints[dep][p], depth, depthShift) /*depthOffset[dep] + splitPoints[dep][p]*/; 1590 const PetscInt splitp = pMaxNew[dep] + p; 1591 PetscInt l; 1592 1593 if (splitLabel) { 1594 const PetscInt val = 100 + dep; 1595 1596 ierr = DMLabelSetValue(splitLabel, newp, val);CHKERRQ(ierr); 1597 ierr = DMLabelSetValue(splitLabel, splitp, -val);CHKERRQ(ierr); 1598 } 1599 for (l = 0; l < numLabels; ++l) { 1600 DMLabel mlabel; 1601 const char *lname; 1602 PetscInt val; 1603 PetscBool isDepth; 1604 1605 ierr = DMGetLabelName(sdm, l, &lname);CHKERRQ(ierr); 1606 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 1607 if (isDepth) continue; 1608 ierr = DMGetLabel(sdm, lname, &mlabel);CHKERRQ(ierr); 1609 ierr = DMLabelGetValue(mlabel, newp, &val);CHKERRQ(ierr); 1610 if (val >= 0) { 1611 ierr = DMLabelSetValue(mlabel, splitp, val);CHKERRQ(ierr); 1612 } 1613 } 1614 } 1615 } 1616 for (sp = 0; sp < numSP; ++sp) { 1617 const PetscInt dep = values[sp]; 1618 1619 if ((dep < 0) || (dep > depth)) continue; 1620 if (splitIS[dep]) {ierr = ISRestoreIndices(splitIS[dep], &splitPoints[dep]);CHKERRQ(ierr);} 1621 ierr = ISDestroy(&splitIS[dep]);CHKERRQ(ierr); 1622 if (unsplitIS[dep]) {ierr = ISRestoreIndices(unsplitIS[dep], &unsplitPoints[dep]);CHKERRQ(ierr);} 1623 ierr = ISDestroy(&unsplitIS[dep]);CHKERRQ(ierr); 1624 } 1625 if (label) { 1626 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 1627 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 1628 } 1629 for (d = 0; d <= depth; ++d) { 1630 ierr = DMPlexGetDepthStratum(sdm, d, NULL, &pEnd);CHKERRQ(ierr); 1631 pMaxNew[d] = pEnd - numHybridPoints[d] - numHybridPointsOld[d]; 1632 } 1633 ierr = PetscFree3(coneNew, coneONew, supportNew);CHKERRQ(ierr); 1634 ierr = PetscFree5(depthMax, depthEnd, depthShift, pMaxNew, numHybridPointsOld);CHKERRQ(ierr); 1635 ierr = PetscFree7(splitIS, unsplitIS, numSplitPoints, numUnsplitPoints, numHybridPoints, splitPoints, unsplitPoints);CHKERRQ(ierr); 1636 PetscFunctionReturn(0); 1637 } 1638 1639 /*@C 1640 DMPlexConstructCohesiveCells - Construct cohesive cells which split the face along an internal interface 1641 1642 Collective on dm 1643 1644 Input Parameters: 1645 + dm - The original DM 1646 - label - The label specifying the boundary faces (this could be auto-generated) 1647 1648 Output Parameters: 1649 + splitLabel - The label containing the split points, or NULL if no output is desired 1650 - dmSplit - The new DM 1651 1652 Level: developer 1653 1654 .seealso: DMCreate(), DMPlexLabelCohesiveComplete() 1655 @*/ 1656 PetscErrorCode DMPlexConstructCohesiveCells(DM dm, DMLabel label, DMLabel splitLabel, DM *dmSplit) 1657 { 1658 DM sdm; 1659 PetscInt dim; 1660 PetscErrorCode ierr; 1661 1662 PetscFunctionBegin; 1663 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1664 PetscValidPointer(dmSplit, 4); 1665 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &sdm);CHKERRQ(ierr); 1666 ierr = DMSetType(sdm, DMPLEX);CHKERRQ(ierr); 1667 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1668 ierr = DMSetDimension(sdm, dim);CHKERRQ(ierr); 1669 switch (dim) { 1670 case 2: 1671 case 3: 1672 ierr = DMPlexConstructCohesiveCells_Internal(dm, label, splitLabel, sdm);CHKERRQ(ierr); 1673 break; 1674 default: 1675 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct cohesive cells for dimension %d", dim); 1676 } 1677 *dmSplit = sdm; 1678 PetscFunctionReturn(0); 1679 } 1680 1681 /* Returns the side of the surface for a given cell with a face on the surface */ 1682 static PetscErrorCode GetSurfaceSide_Static(DM dm, DM subdm, PetscInt numSubpoints, const PetscInt *subpoints, PetscInt cell, PetscInt face, PetscBool *pos) 1683 { 1684 const PetscInt *cone, *ornt; 1685 PetscInt dim, coneSize, c; 1686 PetscErrorCode ierr; 1687 1688 PetscFunctionBegin; 1689 *pos = PETSC_TRUE; 1690 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1691 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 1692 ierr = DMPlexGetCone(dm, cell, &cone);CHKERRQ(ierr); 1693 ierr = DMPlexGetConeOrientation(dm, cell, &ornt);CHKERRQ(ierr); 1694 for (c = 0; c < coneSize; ++c) { 1695 if (cone[c] == face) { 1696 PetscInt o = ornt[c]; 1697 1698 if (subdm) { 1699 const PetscInt *subcone, *subornt; 1700 PetscInt subpoint, subface, subconeSize, sc; 1701 1702 ierr = PetscFindInt(cell, numSubpoints, subpoints, &subpoint);CHKERRQ(ierr); 1703 ierr = PetscFindInt(face, numSubpoints, subpoints, &subface);CHKERRQ(ierr); 1704 ierr = DMPlexGetConeSize(subdm, subpoint, &subconeSize);CHKERRQ(ierr); 1705 ierr = DMPlexGetCone(subdm, subpoint, &subcone);CHKERRQ(ierr); 1706 ierr = DMPlexGetConeOrientation(subdm, subpoint, &subornt);CHKERRQ(ierr); 1707 for (sc = 0; sc < subconeSize; ++sc) { 1708 if (subcone[sc] == subface) { 1709 o = subornt[0]; 1710 break; 1711 } 1712 } 1713 if (sc >= subconeSize) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find subpoint %d (%d) in cone for subpoint %d (%d)", subface, face, subpoint, cell); 1714 } 1715 if (o >= 0) *pos = PETSC_TRUE; 1716 else *pos = PETSC_FALSE; 1717 break; 1718 } 1719 } 1720 if (c == coneSize) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cell %d in split face %d support does not have it in the cone", cell, face); 1721 PetscFunctionReturn(0); 1722 } 1723 1724 /*@ 1725 DMPlexLabelCohesiveComplete - Starting with a label marking points on an internal surface, we add all other mesh pieces 1726 to complete the surface 1727 1728 Input Parameters: 1729 + dm - The DM 1730 . label - A DMLabel marking the surface 1731 . blabel - A DMLabel marking the vertices on the boundary which will not be duplicated, or NULL to find them automatically 1732 . flip - Flag to flip the submesh normal and replace points on the other side 1733 - subdm - The subDM associated with the label, or NULL 1734 1735 Output Parameter: 1736 . label - A DMLabel marking all surface points 1737 1738 Note: The vertices in blabel are called "unsplit" in the terminology from hybrid cell creation. 1739 1740 Level: developer 1741 1742 .seealso: DMPlexConstructCohesiveCells(), DMPlexLabelComplete() 1743 @*/ 1744 PetscErrorCode DMPlexLabelCohesiveComplete(DM dm, DMLabel label, DMLabel blabel, PetscBool flip, DM subdm) 1745 { 1746 DMLabel depthLabel; 1747 IS dimIS, subpointIS = NULL, facePosIS, faceNegIS, crossEdgeIS = NULL; 1748 const PetscInt *points, *subpoints; 1749 const PetscInt rev = flip ? -1 : 1; 1750 PetscInt shift = 100, shift2 = 200, dim, depth, dep, cStart, cEnd, vStart, vEnd, numPoints, numSubpoints, p, val; 1751 PetscErrorCode ierr; 1752 1753 PetscFunctionBegin; 1754 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1755 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1756 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 1757 if (subdm) { 1758 ierr = DMPlexGetSubpointIS(subdm, &subpointIS);CHKERRQ(ierr); 1759 if (subpointIS) { 1760 ierr = ISGetLocalSize(subpointIS, &numSubpoints);CHKERRQ(ierr); 1761 ierr = ISGetIndices(subpointIS, &subpoints);CHKERRQ(ierr); 1762 } 1763 } 1764 /* Mark cell on the fault, and its faces which touch the fault: cell orientation for face gives the side of the fault */ 1765 ierr = DMLabelGetStratumIS(label, dim-1, &dimIS);CHKERRQ(ierr); 1766 if (!dimIS) PetscFunctionReturn(0); 1767 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 1768 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 1769 for (p = 0; p < numPoints; ++p) { /* Loop over fault faces */ 1770 const PetscInt *support; 1771 PetscInt supportSize, s; 1772 1773 ierr = DMPlexGetSupportSize(dm, points[p], &supportSize);CHKERRQ(ierr); 1774 #if 0 1775 if (supportSize != 2) { 1776 const PetscInt *lp; 1777 PetscInt Nlp, pind; 1778 1779 /* Check that for a cell with a single support face, that face is in the SF */ 1780 /* THis check only works for the remote side. We would need root side information */ 1781 ierr = PetscSFGetGraph(dm->sf, NULL, &Nlp, &lp, NULL);CHKERRQ(ierr); 1782 ierr = PetscFindInt(points[p], Nlp, lp, &pind);CHKERRQ(ierr); 1783 if (pind < 0) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Split face %d has %d != 2 supports, and the face is not shared with another process", points[p], supportSize); 1784 } 1785 #endif 1786 ierr = DMPlexGetSupport(dm, points[p], &support);CHKERRQ(ierr); 1787 for (s = 0; s < supportSize; ++s) { 1788 const PetscInt *cone; 1789 PetscInt coneSize, c; 1790 PetscBool pos; 1791 1792 ierr = GetSurfaceSide_Static(dm, subdm, numSubpoints, subpoints, support[s], points[p], &pos);CHKERRQ(ierr); 1793 if (pos) {ierr = DMLabelSetValue(label, support[s], rev*(shift+dim));CHKERRQ(ierr);} 1794 else {ierr = DMLabelSetValue(label, support[s], -rev*(shift+dim));CHKERRQ(ierr);} 1795 if (rev < 0) pos = !pos ? PETSC_TRUE : PETSC_FALSE; 1796 /* Put faces touching the fault in the label */ 1797 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 1798 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 1799 for (c = 0; c < coneSize; ++c) { 1800 const PetscInt point = cone[c]; 1801 1802 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 1803 if (val == -1) { 1804 PetscInt *closure = NULL; 1805 PetscInt closureSize, cl; 1806 1807 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1808 for (cl = 0; cl < closureSize*2; cl += 2) { 1809 const PetscInt clp = closure[cl]; 1810 PetscInt bval = -1; 1811 1812 ierr = DMLabelGetValue(label, clp, &val);CHKERRQ(ierr); 1813 if (blabel) {ierr = DMLabelGetValue(blabel, clp, &bval);CHKERRQ(ierr);} 1814 if ((val >= 0) && (val < dim-1) && (bval < 0)) { 1815 ierr = DMLabelSetValue(label, point, pos == PETSC_TRUE ? shift+dim-1 : -(shift+dim-1));CHKERRQ(ierr); 1816 break; 1817 } 1818 } 1819 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1820 } 1821 } 1822 } 1823 } 1824 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 1825 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 1826 if (subpointIS) {ierr = ISRestoreIndices(subpointIS, &subpoints);CHKERRQ(ierr);} 1827 /* Mark boundary points as unsplit */ 1828 if (blabel) { 1829 ierr = DMLabelGetStratumIS(blabel, 1, &dimIS);CHKERRQ(ierr); 1830 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 1831 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 1832 for (p = 0; p < numPoints; ++p) { 1833 const PetscInt point = points[p]; 1834 PetscInt val, bval; 1835 1836 ierr = DMLabelGetValue(blabel, point, &bval);CHKERRQ(ierr); 1837 if (bval >= 0) { 1838 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 1839 if ((val < 0) || (val > dim)) { 1840 /* This could be a point added from splitting a vertex on an adjacent fault, otherwise its just wrong */ 1841 ierr = DMLabelClearValue(blabel, point, bval);CHKERRQ(ierr); 1842 } 1843 } 1844 } 1845 for (p = 0; p < numPoints; ++p) { 1846 const PetscInt point = points[p]; 1847 PetscInt val, bval; 1848 1849 ierr = DMLabelGetValue(blabel, point, &bval);CHKERRQ(ierr); 1850 if (bval >= 0) { 1851 const PetscInt *cone, *support; 1852 PetscInt coneSize, supportSize, s, valA, valB, valE; 1853 1854 /* Mark as unsplit */ 1855 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 1856 if ((val < 0) || (val > dim)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d has label value %d, should be part of the fault", point, val); 1857 ierr = DMLabelClearValue(label, point, val);CHKERRQ(ierr); 1858 ierr = DMLabelSetValue(label, point, shift2+val);CHKERRQ(ierr); 1859 /* Check for cross-edge 1860 A cross-edge has endpoints which are both on the boundary of the surface, but the edge itself is not. */ 1861 if (val != 0) continue; 1862 ierr = DMPlexGetSupport(dm, point, &support);CHKERRQ(ierr); 1863 ierr = DMPlexGetSupportSize(dm, point, &supportSize);CHKERRQ(ierr); 1864 for (s = 0; s < supportSize; ++s) { 1865 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 1866 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 1867 if (coneSize != 2) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Edge %D has %D vertices != 2", support[s], coneSize); 1868 ierr = DMLabelGetValue(blabel, cone[0], &valA);CHKERRQ(ierr); 1869 ierr = DMLabelGetValue(blabel, cone[1], &valB);CHKERRQ(ierr); 1870 ierr = DMLabelGetValue(blabel, support[s], &valE);CHKERRQ(ierr); 1871 if ((valE < 0) && (valA >= 0) && (valB >= 0) && (cone[0] != cone[1])) {ierr = DMLabelSetValue(blabel, support[s], 2);CHKERRQ(ierr);} 1872 } 1873 } 1874 } 1875 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 1876 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 1877 } 1878 /* Search for other cells/faces/edges connected to the fault by a vertex */ 1879 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1880 ierr = DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1881 ierr = DMLabelGetStratumIS(label, 0, &dimIS);CHKERRQ(ierr); 1882 if (blabel) {ierr = DMLabelGetStratumIS(blabel, 2, &crossEdgeIS);CHKERRQ(ierr);} 1883 if (dimIS && crossEdgeIS) { 1884 IS vertIS = dimIS; 1885 1886 ierr = ISExpand(vertIS, crossEdgeIS, &dimIS);CHKERRQ(ierr); 1887 ierr = ISDestroy(&crossEdgeIS);CHKERRQ(ierr); 1888 ierr = ISDestroy(&vertIS);CHKERRQ(ierr); 1889 } 1890 if (!dimIS) { 1891 PetscFunctionReturn(0); 1892 } 1893 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 1894 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 1895 for (p = 0; p < numPoints; ++p) { /* Loop over fault vertices */ 1896 PetscInt *star = NULL; 1897 PetscInt starSize, s; 1898 PetscInt again = 1; /* 0: Finished 1: Keep iterating after a change 2: No change */ 1899 1900 /* All points connected to the fault are inside a cell, so at the top level we will only check cells */ 1901 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 1902 while (again) { 1903 if (again > 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Could not classify all cells connected to the fault"); 1904 again = 0; 1905 for (s = 0; s < starSize*2; s += 2) { 1906 const PetscInt point = star[s]; 1907 const PetscInt *cone; 1908 PetscInt coneSize, c; 1909 1910 if ((point < cStart) || (point >= cEnd)) continue; 1911 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 1912 if (val != -1) continue; 1913 again = again == 1 ? 1 : 2; 1914 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 1915 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 1916 for (c = 0; c < coneSize; ++c) { 1917 ierr = DMLabelGetValue(label, cone[c], &val);CHKERRQ(ierr); 1918 if (val != -1) { 1919 const PetscInt *ccone; 1920 PetscInt cconeSize, cc, side; 1921 1922 if (PetscAbs(val) < shift) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Face %d on cell %d has an invalid label %d", cone[c], point, val); 1923 if (val > 0) side = 1; 1924 else side = -1; 1925 ierr = DMLabelSetValue(label, point, side*(shift+dim));CHKERRQ(ierr); 1926 /* Mark cell faces which touch the fault */ 1927 ierr = DMPlexGetConeSize(dm, point, &cconeSize);CHKERRQ(ierr); 1928 ierr = DMPlexGetCone(dm, point, &ccone);CHKERRQ(ierr); 1929 for (cc = 0; cc < cconeSize; ++cc) { 1930 PetscInt *closure = NULL; 1931 PetscInt closureSize, cl; 1932 1933 ierr = DMLabelGetValue(label, ccone[cc], &val);CHKERRQ(ierr); 1934 if (val != -1) continue; 1935 ierr = DMPlexGetTransitiveClosure(dm, ccone[cc], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1936 for (cl = 0; cl < closureSize*2; cl += 2) { 1937 const PetscInt clp = closure[cl]; 1938 1939 ierr = DMLabelGetValue(label, clp, &val);CHKERRQ(ierr); 1940 if (val == -1) continue; 1941 ierr = DMLabelSetValue(label, ccone[cc], side*(shift+dim-1));CHKERRQ(ierr); 1942 break; 1943 } 1944 ierr = DMPlexRestoreTransitiveClosure(dm, ccone[cc], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1945 } 1946 again = 1; 1947 break; 1948 } 1949 } 1950 } 1951 } 1952 /* Classify the rest by cell membership */ 1953 for (s = 0; s < starSize*2; s += 2) { 1954 const PetscInt point = star[s]; 1955 1956 ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr); 1957 if (val == -1) { 1958 PetscInt *sstar = NULL; 1959 PetscInt sstarSize, ss; 1960 PetscBool marked = PETSC_FALSE, isHybrid; 1961 1962 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 1963 for (ss = 0; ss < sstarSize*2; ss += 2) { 1964 const PetscInt spoint = sstar[ss]; 1965 1966 if ((spoint < cStart) || (spoint >= cEnd)) continue; 1967 ierr = DMLabelGetValue(label, spoint, &val);CHKERRQ(ierr); 1968 if (val == -1) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Cell %d in star of %d does not have a valid label", spoint, point); 1969 ierr = DMLabelGetValue(depthLabel, point, &dep);CHKERRQ(ierr); 1970 if (val > 0) { 1971 ierr = DMLabelSetValue(label, point, shift+dep);CHKERRQ(ierr); 1972 } else { 1973 ierr = DMLabelSetValue(label, point, -(shift+dep));CHKERRQ(ierr); 1974 } 1975 marked = PETSC_TRUE; 1976 break; 1977 } 1978 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_FALSE, &sstarSize, &sstar);CHKERRQ(ierr); 1979 ierr = DMPlexCellIsHybrid_Internal(dm, point, &isHybrid);CHKERRQ(ierr); 1980 if (!isHybrid && !marked) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d could not be classified", point); 1981 } 1982 } 1983 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 1984 } 1985 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 1986 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 1987 /* If any faces touching the fault divide cells on either side, split them */ 1988 ierr = DMLabelGetStratumIS(label, shift+dim-1, &facePosIS);CHKERRQ(ierr); 1989 ierr = DMLabelGetStratumIS(label, -(shift+dim-1), &faceNegIS);CHKERRQ(ierr); 1990 ierr = ISExpand(facePosIS, faceNegIS, &dimIS);CHKERRQ(ierr); 1991 ierr = ISDestroy(&facePosIS);CHKERRQ(ierr); 1992 ierr = ISDestroy(&faceNegIS);CHKERRQ(ierr); 1993 ierr = ISGetLocalSize(dimIS, &numPoints);CHKERRQ(ierr); 1994 ierr = ISGetIndices(dimIS, &points);CHKERRQ(ierr); 1995 for (p = 0; p < numPoints; ++p) { 1996 const PetscInt point = points[p]; 1997 const PetscInt *support; 1998 PetscInt supportSize, valA, valB; 1999 2000 ierr = DMPlexGetSupportSize(dm, point, &supportSize);CHKERRQ(ierr); 2001 if (supportSize != 2) continue; 2002 ierr = DMPlexGetSupport(dm, point, &support);CHKERRQ(ierr); 2003 ierr = DMLabelGetValue(label, support[0], &valA);CHKERRQ(ierr); 2004 ierr = DMLabelGetValue(label, support[1], &valB);CHKERRQ(ierr); 2005 if ((valA == -1) || (valB == -1)) continue; 2006 if (valA*valB > 0) continue; 2007 /* Split the face */ 2008 ierr = DMLabelGetValue(label, point, &valA);CHKERRQ(ierr); 2009 ierr = DMLabelClearValue(label, point, valA);CHKERRQ(ierr); 2010 ierr = DMLabelSetValue(label, point, dim-1);CHKERRQ(ierr); 2011 /* Label its closure: 2012 unmarked: label as unsplit 2013 incident: relabel as split 2014 split: do nothing 2015 */ 2016 { 2017 PetscInt *closure = NULL; 2018 PetscInt closureSize, cl; 2019 2020 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2021 for (cl = 0; cl < closureSize*2; cl += 2) { 2022 ierr = DMLabelGetValue(label, closure[cl], &valA);CHKERRQ(ierr); 2023 if (valA == -1) { /* Mark as unsplit */ 2024 ierr = DMLabelGetValue(depthLabel, closure[cl], &dep);CHKERRQ(ierr); 2025 ierr = DMLabelSetValue(label, closure[cl], shift2+dep);CHKERRQ(ierr); 2026 } else if (((valA >= shift) && (valA < shift2)) || ((valA <= -shift) && (valA > -shift2))) { 2027 ierr = DMLabelGetValue(depthLabel, closure[cl], &dep);CHKERRQ(ierr); 2028 ierr = DMLabelClearValue(label, closure[cl], valA);CHKERRQ(ierr); 2029 ierr = DMLabelSetValue(label, closure[cl], dep);CHKERRQ(ierr); 2030 } 2031 } 2032 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2033 } 2034 } 2035 ierr = ISRestoreIndices(dimIS, &points);CHKERRQ(ierr); 2036 ierr = ISDestroy(&dimIS);CHKERRQ(ierr); 2037 PetscFunctionReturn(0); 2038 } 2039 2040 /* Check that no cell have all vertices on the fault */ 2041 PetscErrorCode DMPlexCheckValidSubmesh_Private(DM dm, DMLabel label, DM subdm) 2042 { 2043 IS subpointIS; 2044 const PetscInt *dmpoints; 2045 PetscInt defaultValue, cStart, cEnd, c, vStart, vEnd; 2046 PetscErrorCode ierr; 2047 2048 PetscFunctionBegin; 2049 if (!label) PetscFunctionReturn(0); 2050 ierr = DMLabelGetDefaultValue(label, &defaultValue);CHKERRQ(ierr); 2051 ierr = DMPlexGetSubpointIS(subdm, &subpointIS);CHKERRQ(ierr); 2052 if (!subpointIS) PetscFunctionReturn(0); 2053 ierr = DMPlexGetHeightStratum(subdm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2054 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 2055 ierr = ISGetIndices(subpointIS, &dmpoints);CHKERRQ(ierr); 2056 for (c = cStart; c < cEnd; ++c) { 2057 PetscBool invalidCell = PETSC_TRUE; 2058 PetscInt *closure = NULL; 2059 PetscInt closureSize, cl; 2060 2061 ierr = DMPlexGetTransitiveClosure(dm, dmpoints[c], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2062 for (cl = 0; cl < closureSize*2; cl += 2) { 2063 PetscInt value = 0; 2064 2065 if ((closure[cl] < vStart) || (closure[cl] >= vEnd)) continue; 2066 ierr = DMLabelGetValue(label, closure[cl], &value);CHKERRQ(ierr); 2067 if (value == defaultValue) {invalidCell = PETSC_FALSE; break;} 2068 } 2069 ierr = DMPlexRestoreTransitiveClosure(dm, dmpoints[c], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2070 if (invalidCell) { 2071 ierr = ISRestoreIndices(subpointIS, &dmpoints);CHKERRQ(ierr); 2072 ierr = ISDestroy(&subpointIS);CHKERRQ(ierr); 2073 ierr = DMDestroy(&subdm);CHKERRQ(ierr); 2074 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Ambiguous submesh. Cell %D has all of its vertices on the submesh.", dmpoints[c]); 2075 } 2076 } 2077 ierr = ISRestoreIndices(subpointIS, &dmpoints);CHKERRQ(ierr); 2078 PetscFunctionReturn(0); 2079 } 2080 2081 /*@ 2082 DMPlexCreateHybridMesh - Create a mesh with hybrid cells along an internal interface 2083 2084 Collective on dm 2085 2086 Input Parameters: 2087 + dm - The original DM 2088 . label - The label specifying the interface vertices 2089 - bdlabel - The optional label specifying the interface boundary vertices 2090 2091 Output Parameters: 2092 + hybridLabel - The label fully marking the interface, or NULL if no output is desired 2093 . splitLabel - The label containing the split points, or NULL if no output is desired 2094 . dmInterface - The new interface DM, or NULL 2095 - dmHybrid - The new DM with cohesive cells 2096 2097 Note: The hybridLabel indicates what parts of the original mesh impinged on the on division surface. For points 2098 directly on the division surface, they are labeled with their dimension, so an edge 7 on the division surface would be 2099 7 (1) in hybridLabel. For points that impinge from the positive side, they are labeled with 100+dim, so an edge 6 with 2100 one vertex 3 on the surface would be 6 (101) and 3 (0) in hybridLabel. If an edge 9 from the negative side of the 2101 surface also hits vertex 3, it would be 9 (-101) in hybridLabel. 2102 2103 The splitLabel indicates what points in the new hybrid mesh were the result of splitting points in the original 2104 mesh. The label value is +=100+dim for each point. For example, if two edges 10 and 14 in the hybrid resulting from 2105 splitting an edge in the original mesh, you would have 10 (101) and 14 (-101) in the splitLabel. 2106 2107 The dmInterface is a DM built from the original division surface. It has a label which can be retrieved using 2108 DMPlexGetSubpointMap() which maps each point back to the point in the surface of the original mesh. 2109 2110 Level: developer 2111 2112 .seealso: DMPlexConstructCohesiveCells(), DMPlexLabelCohesiveComplete(), DMPlexGetSubpointMap(), DMCreate() 2113 @*/ 2114 PetscErrorCode DMPlexCreateHybridMesh(DM dm, DMLabel label, DMLabel bdlabel, DMLabel *hybridLabel, DMLabel *splitLabel, DM *dmInterface, DM *dmHybrid) 2115 { 2116 DM idm; 2117 DMLabel subpointMap, hlabel, slabel = NULL; 2118 PetscInt dim; 2119 PetscErrorCode ierr; 2120 2121 PetscFunctionBegin; 2122 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2123 if (bdlabel) PetscValidPointer(bdlabel, 3); 2124 if (hybridLabel) PetscValidPointer(hybridLabel, 4); 2125 if (splitLabel) PetscValidPointer(splitLabel, 5); 2126 if (dmInterface) PetscValidPointer(dmInterface, 6); 2127 PetscValidPointer(dmHybrid, 7); 2128 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 2129 ierr = DMPlexCreateSubmesh(dm, label, 1, PETSC_FALSE, &idm);CHKERRQ(ierr); 2130 ierr = DMPlexCheckValidSubmesh_Private(dm, label, idm);CHKERRQ(ierr); 2131 ierr = DMPlexOrient(idm);CHKERRQ(ierr); 2132 ierr = DMPlexGetSubpointMap(idm, &subpointMap);CHKERRQ(ierr); 2133 ierr = DMLabelDuplicate(subpointMap, &hlabel);CHKERRQ(ierr); 2134 ierr = DMLabelClearStratum(hlabel, dim);CHKERRQ(ierr); 2135 if (splitLabel) { 2136 const char *name; 2137 char sname[PETSC_MAX_PATH_LEN]; 2138 2139 ierr = PetscObjectGetName((PetscObject) hlabel, &name);CHKERRQ(ierr); 2140 ierr = PetscStrncpy(sname, name, PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 2141 ierr = PetscStrcat(sname, " split");CHKERRQ(ierr); 2142 ierr = DMLabelCreate(PETSC_COMM_SELF, sname, &slabel);CHKERRQ(ierr); 2143 } 2144 ierr = DMPlexLabelCohesiveComplete(dm, hlabel, bdlabel, PETSC_FALSE, idm);CHKERRQ(ierr); 2145 if (dmInterface) {*dmInterface = idm;} 2146 else {ierr = DMDestroy(&idm);CHKERRQ(ierr);} 2147 ierr = DMPlexConstructCohesiveCells(dm, hlabel, slabel, dmHybrid);CHKERRQ(ierr); 2148 if (hybridLabel) *hybridLabel = hlabel; 2149 else {ierr = DMLabelDestroy(&hlabel);CHKERRQ(ierr);} 2150 if (splitLabel) *splitLabel = slabel; 2151 { 2152 DM cdm; 2153 DMLabel ctLabel; 2154 2155 /* We need to somehow share the celltype label with the coordinate dm */ 2156 ierr = DMGetCoordinateDM(*dmHybrid, &cdm);CHKERRQ(ierr); 2157 ierr = DMPlexGetCellTypeLabel(*dmHybrid, &ctLabel);CHKERRQ(ierr); 2158 ierr = DMSetLabel(cdm, ctLabel);CHKERRQ(ierr); 2159 } 2160 PetscFunctionReturn(0); 2161 } 2162 2163 /* Here we need the explicit assumption that: 2164 2165 For any marked cell, the marked vertices constitute a single face 2166 */ 2167 static PetscErrorCode DMPlexMarkSubmesh_Uninterpolated(DM dm, DMLabel vertexLabel, PetscInt value, DMLabel subpointMap, PetscInt *numFaces, PetscInt *nFV, DM subdm) 2168 { 2169 IS subvertexIS = NULL; 2170 const PetscInt *subvertices; 2171 PetscInt *pStart, *pEnd, pSize; 2172 PetscInt depth, dim, d, numSubVerticesInitial = 0, v; 2173 PetscErrorCode ierr; 2174 2175 PetscFunctionBegin; 2176 *numFaces = 0; 2177 *nFV = 0; 2178 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2179 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 2180 pSize = PetscMax(depth, dim) + 1; 2181 ierr = PetscMalloc2(pSize, &pStart, pSize, &pEnd);CHKERRQ(ierr); 2182 for (d = 0; d <= depth; ++d) { 2183 ierr = DMPlexGetSimplexOrBoxCells(dm, depth-d, &pStart[d], &pEnd[d]);CHKERRQ(ierr); 2184 } 2185 /* Loop over initial vertices and mark all faces in the collective star() */ 2186 if (vertexLabel) {ierr = DMLabelGetStratumIS(vertexLabel, value, &subvertexIS);CHKERRQ(ierr);} 2187 if (subvertexIS) { 2188 ierr = ISGetSize(subvertexIS, &numSubVerticesInitial);CHKERRQ(ierr); 2189 ierr = ISGetIndices(subvertexIS, &subvertices);CHKERRQ(ierr); 2190 } 2191 for (v = 0; v < numSubVerticesInitial; ++v) { 2192 const PetscInt vertex = subvertices[v]; 2193 PetscInt *star = NULL; 2194 PetscInt starSize, s, numCells = 0, c; 2195 2196 ierr = DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 2197 for (s = 0; s < starSize*2; s += 2) { 2198 const PetscInt point = star[s]; 2199 if ((point >= pStart[depth]) && (point < pEnd[depth])) star[numCells++] = point; 2200 } 2201 for (c = 0; c < numCells; ++c) { 2202 const PetscInt cell = star[c]; 2203 PetscInt *closure = NULL; 2204 PetscInt closureSize, cl; 2205 PetscInt cellLoc, numCorners = 0, faceSize = 0; 2206 2207 ierr = DMLabelGetValue(subpointMap, cell, &cellLoc);CHKERRQ(ierr); 2208 if (cellLoc == 2) continue; 2209 if (cellLoc >= 0) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Cell %d has dimension %d in the surface label", cell, cellLoc); 2210 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2211 for (cl = 0; cl < closureSize*2; cl += 2) { 2212 const PetscInt point = closure[cl]; 2213 PetscInt vertexLoc; 2214 2215 if ((point >= pStart[0]) && (point < pEnd[0])) { 2216 ++numCorners; 2217 ierr = DMLabelGetValue(vertexLabel, point, &vertexLoc);CHKERRQ(ierr); 2218 if (vertexLoc == value) closure[faceSize++] = point; 2219 } 2220 } 2221 if (!(*nFV)) {ierr = DMPlexGetNumFaceVertices(dm, dim, numCorners, nFV);CHKERRQ(ierr);} 2222 if (faceSize > *nFV) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 2223 if (faceSize == *nFV) { 2224 const PetscInt *cells = NULL; 2225 PetscInt numCells, nc; 2226 2227 ++(*numFaces); 2228 for (cl = 0; cl < faceSize; ++cl) { 2229 ierr = DMLabelSetValue(subpointMap, closure[cl], 0);CHKERRQ(ierr); 2230 } 2231 ierr = DMPlexGetJoin(dm, faceSize, closure, &numCells, &cells);CHKERRQ(ierr); 2232 for (nc = 0; nc < numCells; ++nc) { 2233 ierr = DMLabelSetValue(subpointMap, cells[nc], 2);CHKERRQ(ierr); 2234 } 2235 ierr = DMPlexRestoreJoin(dm, faceSize, closure, &numCells, &cells);CHKERRQ(ierr); 2236 } 2237 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2238 } 2239 ierr = DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 2240 } 2241 if (subvertexIS) { 2242 ierr = ISRestoreIndices(subvertexIS, &subvertices);CHKERRQ(ierr); 2243 } 2244 ierr = ISDestroy(&subvertexIS);CHKERRQ(ierr); 2245 ierr = PetscFree2(pStart, pEnd);CHKERRQ(ierr); 2246 PetscFunctionReturn(0); 2247 } 2248 2249 static PetscErrorCode DMPlexMarkSubmesh_Interpolated(DM dm, DMLabel vertexLabel, PetscInt value, PetscBool markedFaces, DMLabel subpointMap, DM subdm) 2250 { 2251 IS subvertexIS = NULL; 2252 const PetscInt *subvertices; 2253 PetscInt *pStart, *pEnd; 2254 PetscInt dim, d, numSubVerticesInitial = 0, v; 2255 PetscErrorCode ierr; 2256 2257 PetscFunctionBegin; 2258 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 2259 ierr = PetscMalloc2(dim+1, &pStart, dim+1, &pEnd);CHKERRQ(ierr); 2260 for (d = 0; d <= dim; ++d) { 2261 ierr = DMPlexGetSimplexOrBoxCells(dm, dim-d, &pStart[d], &pEnd[d]);CHKERRQ(ierr); 2262 } 2263 /* Loop over initial vertices and mark all faces in the collective star() */ 2264 if (vertexLabel) { 2265 ierr = DMLabelGetStratumIS(vertexLabel, value, &subvertexIS);CHKERRQ(ierr); 2266 if (subvertexIS) { 2267 ierr = ISGetSize(subvertexIS, &numSubVerticesInitial);CHKERRQ(ierr); 2268 ierr = ISGetIndices(subvertexIS, &subvertices);CHKERRQ(ierr); 2269 } 2270 } 2271 for (v = 0; v < numSubVerticesInitial; ++v) { 2272 const PetscInt vertex = subvertices[v]; 2273 PetscInt *star = NULL; 2274 PetscInt starSize, s, numFaces = 0, f; 2275 2276 ierr = DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 2277 for (s = 0; s < starSize*2; s += 2) { 2278 const PetscInt point = star[s]; 2279 PetscInt faceLoc; 2280 2281 if ((point >= pStart[dim-1]) && (point < pEnd[dim-1])) { 2282 if (markedFaces) { 2283 ierr = DMLabelGetValue(vertexLabel, point, &faceLoc);CHKERRQ(ierr); 2284 if (faceLoc < 0) continue; 2285 } 2286 star[numFaces++] = point; 2287 } 2288 } 2289 for (f = 0; f < numFaces; ++f) { 2290 const PetscInt face = star[f]; 2291 PetscInt *closure = NULL; 2292 PetscInt closureSize, c; 2293 PetscInt faceLoc; 2294 2295 ierr = DMLabelGetValue(subpointMap, face, &faceLoc);CHKERRQ(ierr); 2296 if (faceLoc == dim-1) continue; 2297 if (faceLoc >= 0) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Face %d has dimension %d in the surface label", face, faceLoc); 2298 ierr = DMPlexGetTransitiveClosure(dm, face, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2299 for (c = 0; c < closureSize*2; c += 2) { 2300 const PetscInt point = closure[c]; 2301 PetscInt vertexLoc; 2302 2303 if ((point >= pStart[0]) && (point < pEnd[0])) { 2304 ierr = DMLabelGetValue(vertexLabel, point, &vertexLoc);CHKERRQ(ierr); 2305 if (vertexLoc != value) break; 2306 } 2307 } 2308 if (c == closureSize*2) { 2309 const PetscInt *support; 2310 PetscInt supportSize, s; 2311 2312 for (c = 0; c < closureSize*2; c += 2) { 2313 const PetscInt point = closure[c]; 2314 2315 for (d = 0; d < dim; ++d) { 2316 if ((point >= pStart[d]) && (point < pEnd[d])) { 2317 ierr = DMLabelSetValue(subpointMap, point, d);CHKERRQ(ierr); 2318 break; 2319 } 2320 } 2321 } 2322 ierr = DMPlexGetSupportSize(dm, face, &supportSize);CHKERRQ(ierr); 2323 ierr = DMPlexGetSupport(dm, face, &support);CHKERRQ(ierr); 2324 for (s = 0; s < supportSize; ++s) { 2325 ierr = DMLabelSetValue(subpointMap, support[s], dim);CHKERRQ(ierr); 2326 } 2327 } 2328 ierr = DMPlexRestoreTransitiveClosure(dm, face, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2329 } 2330 ierr = DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 2331 } 2332 if (subvertexIS) {ierr = ISRestoreIndices(subvertexIS, &subvertices);CHKERRQ(ierr);} 2333 ierr = ISDestroy(&subvertexIS);CHKERRQ(ierr); 2334 ierr = PetscFree2(pStart, pEnd);CHKERRQ(ierr); 2335 PetscFunctionReturn(0); 2336 } 2337 2338 static PetscErrorCode DMPlexMarkCohesiveSubmesh_Uninterpolated(DM dm, PetscBool hasLagrange, const char labelname[], PetscInt value, DMLabel subpointMap, PetscInt *numFaces, PetscInt *nFV, PetscInt *subCells[], DM subdm) 2339 { 2340 DMLabel label = NULL; 2341 const PetscInt *cone; 2342 PetscInt dim, cMax, cEnd, c, subc = 0, p, coneSize = -1; 2343 PetscErrorCode ierr; 2344 2345 PetscFunctionBegin; 2346 *numFaces = 0; 2347 *nFV = 0; 2348 if (labelname) {ierr = DMGetLabel(dm, labelname, &label);CHKERRQ(ierr);} 2349 *subCells = NULL; 2350 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 2351 ierr = DMPlexGetTensorPrismBounds_Internal(dm, dim, &cMax, &cEnd);CHKERRQ(ierr); 2352 if (cMax < 0) PetscFunctionReturn(0); 2353 if (label) { 2354 for (c = cMax; c < cEnd; ++c) { 2355 PetscInt val; 2356 2357 ierr = DMLabelGetValue(label, c, &val);CHKERRQ(ierr); 2358 if (val == value) { 2359 ++(*numFaces); 2360 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 2361 } 2362 } 2363 } else { 2364 *numFaces = cEnd - cMax; 2365 ierr = DMPlexGetConeSize(dm, cMax, &coneSize);CHKERRQ(ierr); 2366 } 2367 ierr = PetscMalloc1(*numFaces *2, subCells);CHKERRQ(ierr); 2368 if (!(*numFaces)) PetscFunctionReturn(0); 2369 *nFV = hasLagrange ? coneSize/3 : coneSize/2; 2370 for (c = cMax; c < cEnd; ++c) { 2371 const PetscInt *cells; 2372 PetscInt numCells; 2373 2374 if (label) { 2375 PetscInt val; 2376 2377 ierr = DMLabelGetValue(label, c, &val);CHKERRQ(ierr); 2378 if (val != value) continue; 2379 } 2380 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 2381 for (p = 0; p < *nFV; ++p) { 2382 ierr = DMLabelSetValue(subpointMap, cone[p], 0);CHKERRQ(ierr); 2383 } 2384 /* Negative face */ 2385 ierr = DMPlexGetJoin(dm, *nFV, cone, &numCells, &cells);CHKERRQ(ierr); 2386 /* Not true in parallel 2387 if (numCells != 2) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cohesive cells should separate two cells"); */ 2388 for (p = 0; p < numCells; ++p) { 2389 ierr = DMLabelSetValue(subpointMap, cells[p], 2);CHKERRQ(ierr); 2390 (*subCells)[subc++] = cells[p]; 2391 } 2392 ierr = DMPlexRestoreJoin(dm, *nFV, cone, &numCells, &cells);CHKERRQ(ierr); 2393 /* Positive face is not included */ 2394 } 2395 PetscFunctionReturn(0); 2396 } 2397 2398 static PetscErrorCode DMPlexMarkCohesiveSubmesh_Interpolated(DM dm, DMLabel label, PetscInt value, DMLabel subpointMap, DM subdm) 2399 { 2400 PetscInt *pStart, *pEnd; 2401 PetscInt dim, cMax, cEnd, c, d; 2402 PetscErrorCode ierr; 2403 2404 PetscFunctionBegin; 2405 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 2406 ierr = DMPlexGetTensorPrismBounds_Internal(dm, dim, &cMax, &cEnd);CHKERRQ(ierr); 2407 if (cMax < 0) PetscFunctionReturn(0); 2408 ierr = PetscMalloc2(dim+1,&pStart,dim+1,&pEnd);CHKERRQ(ierr); 2409 for (d = 0; d <= dim; ++d) {ierr = DMPlexGetDepthStratum(dm, d, &pStart[d], &pEnd[d]);CHKERRQ(ierr);} 2410 for (c = cMax; c < cEnd; ++c) { 2411 const PetscInt *cone; 2412 PetscInt *closure = NULL; 2413 PetscInt fconeSize, coneSize, closureSize, cl, val; 2414 2415 if (label) { 2416 ierr = DMLabelGetValue(label, c, &val);CHKERRQ(ierr); 2417 if (val != value) continue; 2418 } 2419 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 2420 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 2421 ierr = DMPlexGetConeSize(dm, cone[0], &fconeSize);CHKERRQ(ierr); 2422 if (coneSize != (fconeSize ? fconeSize : 1) + 2) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cohesive cells should separate two cells"); 2423 /* Negative face */ 2424 ierr = DMPlexGetTransitiveClosure(dm, cone[0], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2425 for (cl = 0; cl < closureSize*2; cl += 2) { 2426 const PetscInt point = closure[cl]; 2427 2428 for (d = 0; d <= dim; ++d) { 2429 if ((point >= pStart[d]) && (point < pEnd[d])) { 2430 ierr = DMLabelSetValue(subpointMap, point, d);CHKERRQ(ierr); 2431 break; 2432 } 2433 } 2434 } 2435 ierr = DMPlexRestoreTransitiveClosure(dm, cone[0], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2436 /* Cells -- positive face is not included */ 2437 for (cl = 0; cl < 1; ++cl) { 2438 const PetscInt *support; 2439 PetscInt supportSize, s; 2440 2441 ierr = DMPlexGetSupportSize(dm, cone[cl], &supportSize);CHKERRQ(ierr); 2442 /* if (supportSize != 2) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cohesive faces should separate two cells"); */ 2443 ierr = DMPlexGetSupport(dm, cone[cl], &support);CHKERRQ(ierr); 2444 for (s = 0; s < supportSize; ++s) { 2445 ierr = DMLabelSetValue(subpointMap, support[s], dim);CHKERRQ(ierr); 2446 } 2447 } 2448 } 2449 ierr = PetscFree2(pStart, pEnd);CHKERRQ(ierr); 2450 PetscFunctionReturn(0); 2451 } 2452 2453 static PetscErrorCode DMPlexGetFaceOrientation(DM dm, PetscInt cell, PetscInt numCorners, PetscInt indices[], PetscInt oppositeVertex, PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 2454 { 2455 MPI_Comm comm; 2456 PetscBool posOrient = PETSC_FALSE; 2457 const PetscInt debug = 0; 2458 PetscInt cellDim, faceSize, f; 2459 PetscErrorCode ierr; 2460 2461 PetscFunctionBegin; 2462 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2463 ierr = DMGetDimension(dm, &cellDim);CHKERRQ(ierr); 2464 if (debug) {ierr = PetscPrintf(comm, "cellDim: %d numCorners: %d\n", cellDim, numCorners);CHKERRQ(ierr);} 2465 2466 if (cellDim == 1 && numCorners == 2) { 2467 /* Triangle */ 2468 faceSize = numCorners-1; 2469 posOrient = !(oppositeVertex%2) ? PETSC_TRUE : PETSC_FALSE; 2470 } else if (cellDim == 2 && numCorners == 3) { 2471 /* Triangle */ 2472 faceSize = numCorners-1; 2473 posOrient = !(oppositeVertex%2) ? PETSC_TRUE : PETSC_FALSE; 2474 } else if (cellDim == 3 && numCorners == 4) { 2475 /* Tetrahedron */ 2476 faceSize = numCorners-1; 2477 posOrient = (oppositeVertex%2) ? PETSC_TRUE : PETSC_FALSE; 2478 } else if (cellDim == 1 && numCorners == 3) { 2479 /* Quadratic line */ 2480 faceSize = 1; 2481 posOrient = PETSC_TRUE; 2482 } else if (cellDim == 2 && numCorners == 4) { 2483 /* Quads */ 2484 faceSize = 2; 2485 if ((indices[1] > indices[0]) && (indices[1] - indices[0] == 1)) { 2486 posOrient = PETSC_TRUE; 2487 } else if ((indices[0] == 3) && (indices[1] == 0)) { 2488 posOrient = PETSC_TRUE; 2489 } else { 2490 if (((indices[0] > indices[1]) && (indices[0] - indices[1] == 1)) || ((indices[0] == 0) && (indices[1] == 3))) { 2491 posOrient = PETSC_FALSE; 2492 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossedge"); 2493 } 2494 } else if (cellDim == 2 && numCorners == 6) { 2495 /* Quadratic triangle (I hate this) */ 2496 /* Edges are determined by the first 2 vertices (corners of edges) */ 2497 const PetscInt faceSizeTri = 3; 2498 PetscInt sortedIndices[3], i, iFace; 2499 PetscBool found = PETSC_FALSE; 2500 PetscInt faceVerticesTriSorted[9] = { 2501 0, 3, 4, /* bottom */ 2502 1, 4, 5, /* right */ 2503 2, 3, 5, /* left */ 2504 }; 2505 PetscInt faceVerticesTri[9] = { 2506 0, 3, 4, /* bottom */ 2507 1, 4, 5, /* right */ 2508 2, 5, 3, /* left */ 2509 }; 2510 2511 for (i = 0; i < faceSizeTri; ++i) sortedIndices[i] = indices[i]; 2512 ierr = PetscSortInt(faceSizeTri, sortedIndices);CHKERRQ(ierr); 2513 for (iFace = 0; iFace < 3; ++iFace) { 2514 const PetscInt ii = iFace*faceSizeTri; 2515 PetscInt fVertex, cVertex; 2516 2517 if ((sortedIndices[0] == faceVerticesTriSorted[ii+0]) && 2518 (sortedIndices[1] == faceVerticesTriSorted[ii+1])) { 2519 for (fVertex = 0; fVertex < faceSizeTri; ++fVertex) { 2520 for (cVertex = 0; cVertex < faceSizeTri; ++cVertex) { 2521 if (indices[cVertex] == faceVerticesTri[ii+fVertex]) { 2522 faceVertices[fVertex] = origVertices[cVertex]; 2523 break; 2524 } 2525 } 2526 } 2527 found = PETSC_TRUE; 2528 break; 2529 } 2530 } 2531 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tri crossface"); 2532 if (posOriented) *posOriented = PETSC_TRUE; 2533 PetscFunctionReturn(0); 2534 } else if (cellDim == 2 && numCorners == 9) { 2535 /* Quadratic quad (I hate this) */ 2536 /* Edges are determined by the first 2 vertices (corners of edges) */ 2537 const PetscInt faceSizeQuad = 3; 2538 PetscInt sortedIndices[3], i, iFace; 2539 PetscBool found = PETSC_FALSE; 2540 PetscInt faceVerticesQuadSorted[12] = { 2541 0, 1, 4, /* bottom */ 2542 1, 2, 5, /* right */ 2543 2, 3, 6, /* top */ 2544 0, 3, 7, /* left */ 2545 }; 2546 PetscInt faceVerticesQuad[12] = { 2547 0, 1, 4, /* bottom */ 2548 1, 2, 5, /* right */ 2549 2, 3, 6, /* top */ 2550 3, 0, 7, /* left */ 2551 }; 2552 2553 for (i = 0; i < faceSizeQuad; ++i) sortedIndices[i] = indices[i]; 2554 ierr = PetscSortInt(faceSizeQuad, sortedIndices);CHKERRQ(ierr); 2555 for (iFace = 0; iFace < 4; ++iFace) { 2556 const PetscInt ii = iFace*faceSizeQuad; 2557 PetscInt fVertex, cVertex; 2558 2559 if ((sortedIndices[0] == faceVerticesQuadSorted[ii+0]) && 2560 (sortedIndices[1] == faceVerticesQuadSorted[ii+1])) { 2561 for (fVertex = 0; fVertex < faceSizeQuad; ++fVertex) { 2562 for (cVertex = 0; cVertex < faceSizeQuad; ++cVertex) { 2563 if (indices[cVertex] == faceVerticesQuad[ii+fVertex]) { 2564 faceVertices[fVertex] = origVertices[cVertex]; 2565 break; 2566 } 2567 } 2568 } 2569 found = PETSC_TRUE; 2570 break; 2571 } 2572 } 2573 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossface"); 2574 if (posOriented) *posOriented = PETSC_TRUE; 2575 PetscFunctionReturn(0); 2576 } else if (cellDim == 3 && numCorners == 8) { 2577 /* Hexes 2578 A hex is two oriented quads with the normal of the first 2579 pointing up at the second. 2580 2581 7---6 2582 /| /| 2583 4---5 | 2584 | 1-|-2 2585 |/ |/ 2586 0---3 2587 2588 Faces are determined by the first 4 vertices (corners of faces) */ 2589 const PetscInt faceSizeHex = 4; 2590 PetscInt sortedIndices[4], i, iFace; 2591 PetscBool found = PETSC_FALSE; 2592 PetscInt faceVerticesHexSorted[24] = { 2593 0, 1, 2, 3, /* bottom */ 2594 4, 5, 6, 7, /* top */ 2595 0, 3, 4, 5, /* front */ 2596 2, 3, 5, 6, /* right */ 2597 1, 2, 6, 7, /* back */ 2598 0, 1, 4, 7, /* left */ 2599 }; 2600 PetscInt faceVerticesHex[24] = { 2601 1, 2, 3, 0, /* bottom */ 2602 4, 5, 6, 7, /* top */ 2603 0, 3, 5, 4, /* front */ 2604 3, 2, 6, 5, /* right */ 2605 2, 1, 7, 6, /* back */ 2606 1, 0, 4, 7, /* left */ 2607 }; 2608 2609 for (i = 0; i < faceSizeHex; ++i) sortedIndices[i] = indices[i]; 2610 ierr = PetscSortInt(faceSizeHex, sortedIndices);CHKERRQ(ierr); 2611 for (iFace = 0; iFace < 6; ++iFace) { 2612 const PetscInt ii = iFace*faceSizeHex; 2613 PetscInt fVertex, cVertex; 2614 2615 if ((sortedIndices[0] == faceVerticesHexSorted[ii+0]) && 2616 (sortedIndices[1] == faceVerticesHexSorted[ii+1]) && 2617 (sortedIndices[2] == faceVerticesHexSorted[ii+2]) && 2618 (sortedIndices[3] == faceVerticesHexSorted[ii+3])) { 2619 for (fVertex = 0; fVertex < faceSizeHex; ++fVertex) { 2620 for (cVertex = 0; cVertex < faceSizeHex; ++cVertex) { 2621 if (indices[cVertex] == faceVerticesHex[ii+fVertex]) { 2622 faceVertices[fVertex] = origVertices[cVertex]; 2623 break; 2624 } 2625 } 2626 } 2627 found = PETSC_TRUE; 2628 break; 2629 } 2630 } 2631 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 2632 if (posOriented) *posOriented = PETSC_TRUE; 2633 PetscFunctionReturn(0); 2634 } else if (cellDim == 3 && numCorners == 10) { 2635 /* Quadratic tet */ 2636 /* Faces are determined by the first 3 vertices (corners of faces) */ 2637 const PetscInt faceSizeTet = 6; 2638 PetscInt sortedIndices[6], i, iFace; 2639 PetscBool found = PETSC_FALSE; 2640 PetscInt faceVerticesTetSorted[24] = { 2641 0, 1, 2, 6, 7, 8, /* bottom */ 2642 0, 3, 4, 6, 7, 9, /* front */ 2643 1, 4, 5, 7, 8, 9, /* right */ 2644 2, 3, 5, 6, 8, 9, /* left */ 2645 }; 2646 PetscInt faceVerticesTet[24] = { 2647 0, 1, 2, 6, 7, 8, /* bottom */ 2648 0, 4, 3, 6, 7, 9, /* front */ 2649 1, 5, 4, 7, 8, 9, /* right */ 2650 2, 3, 5, 8, 6, 9, /* left */ 2651 }; 2652 2653 for (i = 0; i < faceSizeTet; ++i) sortedIndices[i] = indices[i]; 2654 ierr = PetscSortInt(faceSizeTet, sortedIndices);CHKERRQ(ierr); 2655 for (iFace=0; iFace < 4; ++iFace) { 2656 const PetscInt ii = iFace*faceSizeTet; 2657 PetscInt fVertex, cVertex; 2658 2659 if ((sortedIndices[0] == faceVerticesTetSorted[ii+0]) && 2660 (sortedIndices[1] == faceVerticesTetSorted[ii+1]) && 2661 (sortedIndices[2] == faceVerticesTetSorted[ii+2]) && 2662 (sortedIndices[3] == faceVerticesTetSorted[ii+3])) { 2663 for (fVertex = 0; fVertex < faceSizeTet; ++fVertex) { 2664 for (cVertex = 0; cVertex < faceSizeTet; ++cVertex) { 2665 if (indices[cVertex] == faceVerticesTet[ii+fVertex]) { 2666 faceVertices[fVertex] = origVertices[cVertex]; 2667 break; 2668 } 2669 } 2670 } 2671 found = PETSC_TRUE; 2672 break; 2673 } 2674 } 2675 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tet crossface"); 2676 if (posOriented) *posOriented = PETSC_TRUE; 2677 PetscFunctionReturn(0); 2678 } else if (cellDim == 3 && numCorners == 27) { 2679 /* Quadratic hexes (I hate this) 2680 A hex is two oriented quads with the normal of the first 2681 pointing up at the second. 2682 2683 7---6 2684 /| /| 2685 4---5 | 2686 | 3-|-2 2687 |/ |/ 2688 0---1 2689 2690 Faces are determined by the first 4 vertices (corners of faces) */ 2691 const PetscInt faceSizeQuadHex = 9; 2692 PetscInt sortedIndices[9], i, iFace; 2693 PetscBool found = PETSC_FALSE; 2694 PetscInt faceVerticesQuadHexSorted[54] = { 2695 0, 1, 2, 3, 8, 9, 10, 11, 24, /* bottom */ 2696 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 2697 0, 1, 4, 5, 8, 12, 16, 17, 22, /* front */ 2698 1, 2, 5, 6, 9, 13, 17, 18, 21, /* right */ 2699 2, 3, 6, 7, 10, 14, 18, 19, 23, /* back */ 2700 0, 3, 4, 7, 11, 15, 16, 19, 20, /* left */ 2701 }; 2702 PetscInt faceVerticesQuadHex[54] = { 2703 3, 2, 1, 0, 10, 9, 8, 11, 24, /* bottom */ 2704 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 2705 0, 1, 5, 4, 8, 17, 12, 16, 22, /* front */ 2706 1, 2, 6, 5, 9, 18, 13, 17, 21, /* right */ 2707 2, 3, 7, 6, 10, 19, 14, 18, 23, /* back */ 2708 3, 0, 4, 7, 11, 16, 15, 19, 20 /* left */ 2709 }; 2710 2711 for (i = 0; i < faceSizeQuadHex; ++i) sortedIndices[i] = indices[i]; 2712 ierr = PetscSortInt(faceSizeQuadHex, sortedIndices);CHKERRQ(ierr); 2713 for (iFace = 0; iFace < 6; ++iFace) { 2714 const PetscInt ii = iFace*faceSizeQuadHex; 2715 PetscInt fVertex, cVertex; 2716 2717 if ((sortedIndices[0] == faceVerticesQuadHexSorted[ii+0]) && 2718 (sortedIndices[1] == faceVerticesQuadHexSorted[ii+1]) && 2719 (sortedIndices[2] == faceVerticesQuadHexSorted[ii+2]) && 2720 (sortedIndices[3] == faceVerticesQuadHexSorted[ii+3])) { 2721 for (fVertex = 0; fVertex < faceSizeQuadHex; ++fVertex) { 2722 for (cVertex = 0; cVertex < faceSizeQuadHex; ++cVertex) { 2723 if (indices[cVertex] == faceVerticesQuadHex[ii+fVertex]) { 2724 faceVertices[fVertex] = origVertices[cVertex]; 2725 break; 2726 } 2727 } 2728 } 2729 found = PETSC_TRUE; 2730 break; 2731 } 2732 } 2733 if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 2734 if (posOriented) *posOriented = PETSC_TRUE; 2735 PetscFunctionReturn(0); 2736 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unknown cell type for faceOrientation()."); 2737 if (!posOrient) { 2738 if (debug) {ierr = PetscPrintf(comm, " Reversing initial face orientation\n");CHKERRQ(ierr);} 2739 for (f = 0; f < faceSize; ++f) faceVertices[f] = origVertices[faceSize-1 - f]; 2740 } else { 2741 if (debug) {ierr = PetscPrintf(comm, " Keeping initial face orientation\n");CHKERRQ(ierr);} 2742 for (f = 0; f < faceSize; ++f) faceVertices[f] = origVertices[f]; 2743 } 2744 if (posOriented) *posOriented = posOrient; 2745 PetscFunctionReturn(0); 2746 } 2747 2748 /*@ 2749 DMPlexGetOrientedFace - Given a cell and a face, as a set of vertices, return the oriented face, as a set of vertices, 2750 in faceVertices. The orientation is such that the face normal points out of the cell 2751 2752 Not collective 2753 2754 Input Parameters: 2755 + dm - The original mesh 2756 . cell - The cell mesh point 2757 . faceSize - The number of vertices on the face 2758 . face - The face vertices 2759 . numCorners - The number of vertices on the cell 2760 . indices - Local numbering of face vertices in cell cone 2761 - origVertices - Original face vertices 2762 2763 Output Parameters: 2764 + faceVertices - The face vertices properly oriented 2765 - posOriented - PETSC_TRUE if the face was oriented with outward normal 2766 2767 Level: developer 2768 2769 .seealso: DMPlexGetCone() 2770 @*/ 2771 PetscErrorCode DMPlexGetOrientedFace(DM dm, PetscInt cell, PetscInt faceSize, const PetscInt face[], PetscInt numCorners, PetscInt indices[], PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 2772 { 2773 const PetscInt *cone = NULL; 2774 PetscInt coneSize, v, f, v2; 2775 PetscInt oppositeVertex = -1; 2776 PetscErrorCode ierr; 2777 2778 PetscFunctionBegin; 2779 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 2780 ierr = DMPlexGetCone(dm, cell, &cone);CHKERRQ(ierr); 2781 for (v = 0, v2 = 0; v < coneSize; ++v) { 2782 PetscBool found = PETSC_FALSE; 2783 2784 for (f = 0; f < faceSize; ++f) { 2785 if (face[f] == cone[v]) { 2786 found = PETSC_TRUE; break; 2787 } 2788 } 2789 if (found) { 2790 indices[v2] = v; 2791 origVertices[v2] = cone[v]; 2792 ++v2; 2793 } else { 2794 oppositeVertex = v; 2795 } 2796 } 2797 ierr = DMPlexGetFaceOrientation(dm, cell, numCorners, indices, oppositeVertex, origVertices, faceVertices, posOriented);CHKERRQ(ierr); 2798 PetscFunctionReturn(0); 2799 } 2800 2801 /* 2802 DMPlexInsertFace_Internal - Puts a face into the mesh 2803 2804 Not collective 2805 2806 Input Parameters: 2807 + dm - The DMPlex 2808 . numFaceVertex - The number of vertices in the face 2809 . faceVertices - The vertices in the face for dm 2810 . subfaceVertices - The vertices in the face for subdm 2811 . numCorners - The number of vertices in the cell 2812 . cell - A cell in dm containing the face 2813 . subcell - A cell in subdm containing the face 2814 . firstFace - First face in the mesh 2815 - newFacePoint - Next face in the mesh 2816 2817 Output Parameters: 2818 . newFacePoint - Contains next face point number on input, updated on output 2819 2820 Level: developer 2821 */ 2822 static PetscErrorCode DMPlexInsertFace_Internal(DM dm, DM subdm, PetscInt numFaceVertices, const PetscInt faceVertices[], const PetscInt subfaceVertices[], PetscInt numCorners, PetscInt cell, PetscInt subcell, PetscInt firstFace, PetscInt *newFacePoint) 2823 { 2824 MPI_Comm comm; 2825 DM_Plex *submesh = (DM_Plex*) subdm->data; 2826 const PetscInt *faces; 2827 PetscInt numFaces, coneSize; 2828 PetscErrorCode ierr; 2829 2830 PetscFunctionBegin; 2831 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2832 ierr = DMPlexGetConeSize(subdm, subcell, &coneSize);CHKERRQ(ierr); 2833 if (coneSize != 1) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size of cell %d is %d != 1", cell, coneSize); 2834 #if 0 2835 /* Cannot use this because support() has not been constructed yet */ 2836 ierr = DMPlexGetJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 2837 #else 2838 { 2839 PetscInt f; 2840 2841 numFaces = 0; 2842 ierr = DMGetWorkArray(subdm, 1, MPIU_INT, (void **) &faces);CHKERRQ(ierr); 2843 for (f = firstFace; f < *newFacePoint; ++f) { 2844 PetscInt dof, off, d; 2845 2846 ierr = PetscSectionGetDof(submesh->coneSection, f, &dof);CHKERRQ(ierr); 2847 ierr = PetscSectionGetOffset(submesh->coneSection, f, &off);CHKERRQ(ierr); 2848 /* Yes, I know this is quadratic, but I expect the sizes to be <5 */ 2849 for (d = 0; d < dof; ++d) { 2850 const PetscInt p = submesh->cones[off+d]; 2851 PetscInt v; 2852 2853 for (v = 0; v < numFaceVertices; ++v) { 2854 if (subfaceVertices[v] == p) break; 2855 } 2856 if (v == numFaceVertices) break; 2857 } 2858 if (d == dof) { 2859 numFaces = 1; 2860 ((PetscInt*) faces)[0] = f; 2861 } 2862 } 2863 } 2864 #endif 2865 if (numFaces > 1) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Vertex set had %d faces, not one", numFaces); 2866 else if (numFaces == 1) { 2867 /* Add the other cell neighbor for this face */ 2868 ierr = DMPlexSetCone(subdm, subcell, faces);CHKERRQ(ierr); 2869 } else { 2870 PetscInt *indices, *origVertices, *orientedVertices, *orientedSubVertices, v, ov; 2871 PetscBool posOriented; 2872 2873 ierr = DMGetWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), MPIU_INT, &orientedVertices);CHKERRQ(ierr); 2874 origVertices = &orientedVertices[numFaceVertices]; 2875 indices = &orientedVertices[numFaceVertices*2]; 2876 orientedSubVertices = &orientedVertices[numFaceVertices*3]; 2877 ierr = DMPlexGetOrientedFace(dm, cell, numFaceVertices, faceVertices, numCorners, indices, origVertices, orientedVertices, &posOriented);CHKERRQ(ierr); 2878 /* TODO: I know that routine should return a permutation, not the indices */ 2879 for (v = 0; v < numFaceVertices; ++v) { 2880 const PetscInt vertex = faceVertices[v], subvertex = subfaceVertices[v]; 2881 for (ov = 0; ov < numFaceVertices; ++ov) { 2882 if (orientedVertices[ov] == vertex) { 2883 orientedSubVertices[ov] = subvertex; 2884 break; 2885 } 2886 } 2887 if (ov == numFaceVertices) SETERRQ1(comm, PETSC_ERR_PLIB, "Could not find face vertex %d in orientated set", vertex); 2888 } 2889 ierr = DMPlexSetCone(subdm, *newFacePoint, orientedSubVertices);CHKERRQ(ierr); 2890 ierr = DMPlexSetCone(subdm, subcell, newFacePoint);CHKERRQ(ierr); 2891 ierr = DMRestoreWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), MPIU_INT, &orientedVertices);CHKERRQ(ierr); 2892 ++(*newFacePoint); 2893 } 2894 #if 0 2895 ierr = DMPlexRestoreJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 2896 #else 2897 ierr = DMRestoreWorkArray(subdm, 1, MPIU_INT, (void **) &faces);CHKERRQ(ierr); 2898 #endif 2899 PetscFunctionReturn(0); 2900 } 2901 2902 static PetscErrorCode DMPlexCreateSubmesh_Uninterpolated(DM dm, DMLabel vertexLabel, PetscInt value, DM subdm) 2903 { 2904 MPI_Comm comm; 2905 DMLabel subpointMap; 2906 IS subvertexIS, subcellIS; 2907 const PetscInt *subVertices, *subCells; 2908 PetscInt numSubVertices, firstSubVertex, numSubCells; 2909 PetscInt *subface, maxConeSize, numSubFaces = 0, firstSubFace, newFacePoint, nFV = 0; 2910 PetscInt vStart, vEnd, c, f; 2911 PetscErrorCode ierr; 2912 2913 PetscFunctionBegin; 2914 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2915 /* Create subpointMap which marks the submesh */ 2916 ierr = DMLabelCreate(PETSC_COMM_SELF, "subpoint_map", &subpointMap);CHKERRQ(ierr); 2917 ierr = DMPlexSetSubpointMap(subdm, subpointMap);CHKERRQ(ierr); 2918 ierr = DMLabelDestroy(&subpointMap);CHKERRQ(ierr); 2919 if (vertexLabel) {ierr = DMPlexMarkSubmesh_Uninterpolated(dm, vertexLabel, value, subpointMap, &numSubFaces, &nFV, subdm);CHKERRQ(ierr);} 2920 /* Setup chart */ 2921 ierr = DMLabelGetStratumSize(subpointMap, 0, &numSubVertices);CHKERRQ(ierr); 2922 ierr = DMLabelGetStratumSize(subpointMap, 2, &numSubCells);CHKERRQ(ierr); 2923 ierr = DMPlexSetChart(subdm, 0, numSubCells+numSubFaces+numSubVertices);CHKERRQ(ierr); 2924 ierr = DMPlexSetVTKCellHeight(subdm, 1);CHKERRQ(ierr); 2925 /* Set cone sizes */ 2926 firstSubVertex = numSubCells; 2927 firstSubFace = numSubCells+numSubVertices; 2928 newFacePoint = firstSubFace; 2929 ierr = DMLabelGetStratumIS(subpointMap, 0, &subvertexIS);CHKERRQ(ierr); 2930 if (subvertexIS) {ierr = ISGetIndices(subvertexIS, &subVertices);CHKERRQ(ierr);} 2931 ierr = DMLabelGetStratumIS(subpointMap, 2, &subcellIS);CHKERRQ(ierr); 2932 if (subcellIS) {ierr = ISGetIndices(subcellIS, &subCells);CHKERRQ(ierr);} 2933 for (c = 0; c < numSubCells; ++c) { 2934 ierr = DMPlexSetConeSize(subdm, c, 1);CHKERRQ(ierr); 2935 } 2936 for (f = firstSubFace; f < firstSubFace+numSubFaces; ++f) { 2937 ierr = DMPlexSetConeSize(subdm, f, nFV);CHKERRQ(ierr); 2938 } 2939 ierr = DMSetUp(subdm);CHKERRQ(ierr); 2940 /* Create face cones */ 2941 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 2942 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, NULL);CHKERRQ(ierr); 2943 ierr = DMGetWorkArray(subdm, maxConeSize, MPIU_INT, (void**) &subface);CHKERRQ(ierr); 2944 for (c = 0; c < numSubCells; ++c) { 2945 const PetscInt cell = subCells[c]; 2946 const PetscInt subcell = c; 2947 PetscInt *closure = NULL; 2948 PetscInt closureSize, cl, numCorners = 0, faceSize = 0; 2949 2950 ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2951 for (cl = 0; cl < closureSize*2; cl += 2) { 2952 const PetscInt point = closure[cl]; 2953 PetscInt subVertex; 2954 2955 if ((point >= vStart) && (point < vEnd)) { 2956 ++numCorners; 2957 ierr = PetscFindInt(point, numSubVertices, subVertices, &subVertex);CHKERRQ(ierr); 2958 if (subVertex >= 0) { 2959 closure[faceSize] = point; 2960 subface[faceSize] = firstSubVertex+subVertex; 2961 ++faceSize; 2962 } 2963 } 2964 } 2965 if (faceSize > nFV) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 2966 if (faceSize == nFV) { 2967 ierr = DMPlexInsertFace_Internal(dm, subdm, faceSize, closure, subface, numCorners, cell, subcell, firstSubFace, &newFacePoint);CHKERRQ(ierr); 2968 } 2969 ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2970 } 2971 ierr = DMRestoreWorkArray(subdm, maxConeSize, MPIU_INT, (void**) &subface);CHKERRQ(ierr); 2972 ierr = DMPlexSymmetrize(subdm);CHKERRQ(ierr); 2973 ierr = DMPlexStratify(subdm);CHKERRQ(ierr); 2974 /* Build coordinates */ 2975 { 2976 PetscSection coordSection, subCoordSection; 2977 Vec coordinates, subCoordinates; 2978 PetscScalar *coords, *subCoords; 2979 PetscInt numComp, coordSize, v; 2980 const char *name; 2981 2982 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 2983 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 2984 ierr = DMGetCoordinateSection(subdm, &subCoordSection);CHKERRQ(ierr); 2985 ierr = PetscSectionSetNumFields(subCoordSection, 1);CHKERRQ(ierr); 2986 ierr = PetscSectionGetFieldComponents(coordSection, 0, &numComp);CHKERRQ(ierr); 2987 ierr = PetscSectionSetFieldComponents(subCoordSection, 0, numComp);CHKERRQ(ierr); 2988 ierr = PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex+numSubVertices);CHKERRQ(ierr); 2989 for (v = 0; v < numSubVertices; ++v) { 2990 const PetscInt vertex = subVertices[v]; 2991 const PetscInt subvertex = firstSubVertex+v; 2992 PetscInt dof; 2993 2994 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 2995 ierr = PetscSectionSetDof(subCoordSection, subvertex, dof);CHKERRQ(ierr); 2996 ierr = PetscSectionSetFieldDof(subCoordSection, subvertex, 0, dof);CHKERRQ(ierr); 2997 } 2998 ierr = PetscSectionSetUp(subCoordSection);CHKERRQ(ierr); 2999 ierr = PetscSectionGetStorageSize(subCoordSection, &coordSize);CHKERRQ(ierr); 3000 ierr = VecCreate(PETSC_COMM_SELF, &subCoordinates);CHKERRQ(ierr); 3001 ierr = PetscObjectGetName((PetscObject)coordinates,&name);CHKERRQ(ierr); 3002 ierr = PetscObjectSetName((PetscObject)subCoordinates,name);CHKERRQ(ierr); 3003 ierr = VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 3004 ierr = VecSetType(subCoordinates,VECSTANDARD);CHKERRQ(ierr); 3005 if (coordSize) { 3006 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 3007 ierr = VecGetArray(subCoordinates, &subCoords);CHKERRQ(ierr); 3008 for (v = 0; v < numSubVertices; ++v) { 3009 const PetscInt vertex = subVertices[v]; 3010 const PetscInt subvertex = firstSubVertex+v; 3011 PetscInt dof, off, sdof, soff, d; 3012 3013 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 3014 ierr = PetscSectionGetOffset(coordSection, vertex, &off);CHKERRQ(ierr); 3015 ierr = PetscSectionGetDof(subCoordSection, subvertex, &sdof);CHKERRQ(ierr); 3016 ierr = PetscSectionGetOffset(subCoordSection, subvertex, &soff);CHKERRQ(ierr); 3017 if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subvertex, vertex, dof); 3018 for (d = 0; d < dof; ++d) subCoords[soff+d] = coords[off+d]; 3019 } 3020 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 3021 ierr = VecRestoreArray(subCoordinates, &subCoords);CHKERRQ(ierr); 3022 } 3023 ierr = DMSetCoordinatesLocal(subdm, subCoordinates);CHKERRQ(ierr); 3024 ierr = VecDestroy(&subCoordinates);CHKERRQ(ierr); 3025 } 3026 /* Cleanup */ 3027 if (subvertexIS) {ierr = ISRestoreIndices(subvertexIS, &subVertices);CHKERRQ(ierr);} 3028 ierr = ISDestroy(&subvertexIS);CHKERRQ(ierr); 3029 if (subcellIS) {ierr = ISRestoreIndices(subcellIS, &subCells);CHKERRQ(ierr);} 3030 ierr = ISDestroy(&subcellIS);CHKERRQ(ierr); 3031 PetscFunctionReturn(0); 3032 } 3033 3034 PETSC_STATIC_INLINE PetscInt DMPlexFilterPoint_Internal(PetscInt point, PetscInt firstSubPoint, PetscInt numSubPoints, const PetscInt subPoints[]) 3035 { 3036 PetscInt subPoint; 3037 PetscErrorCode ierr; 3038 3039 ierr = PetscFindInt(point, numSubPoints, subPoints, &subPoint); if (ierr < 0) return ierr; 3040 return subPoint < 0 ? subPoint : firstSubPoint+subPoint; 3041 } 3042 3043 static PetscErrorCode DMPlexCreateSubmeshGeneric_Interpolated(DM dm, DMLabel label, PetscInt value, PetscBool markedFaces, PetscBool isCohesive, PetscInt cellHeight, DM subdm) 3044 { 3045 MPI_Comm comm; 3046 DMLabel subpointMap; 3047 IS *subpointIS; 3048 const PetscInt **subpoints; 3049 PetscInt *numSubPoints, *firstSubPoint, *coneNew, *orntNew; 3050 PetscInt totSubPoints = 0, maxConeSize, dim, p, d, v; 3051 PetscMPIInt rank; 3052 PetscErrorCode ierr; 3053 3054 PetscFunctionBegin; 3055 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 3056 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 3057 /* Create subpointMap which marks the submesh */ 3058 ierr = DMLabelCreate(PETSC_COMM_SELF, "subpoint_map", &subpointMap);CHKERRQ(ierr); 3059 ierr = DMPlexSetSubpointMap(subdm, subpointMap);CHKERRQ(ierr); 3060 if (cellHeight) { 3061 if (isCohesive) {ierr = DMPlexMarkCohesiveSubmesh_Interpolated(dm, label, value, subpointMap, subdm);CHKERRQ(ierr);} 3062 else {ierr = DMPlexMarkSubmesh_Interpolated(dm, label, value, markedFaces, subpointMap, subdm);CHKERRQ(ierr);} 3063 } else { 3064 DMLabel depth; 3065 IS pointIS; 3066 const PetscInt *points; 3067 PetscInt numPoints=0; 3068 3069 ierr = DMPlexGetDepthLabel(dm, &depth);CHKERRQ(ierr); 3070 ierr = DMLabelGetStratumIS(label, value, &pointIS);CHKERRQ(ierr); 3071 if (pointIS) { 3072 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 3073 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 3074 } 3075 for (p = 0; p < numPoints; ++p) { 3076 PetscInt *closure = NULL; 3077 PetscInt closureSize, c, pdim; 3078 3079 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3080 for (c = 0; c < closureSize*2; c += 2) { 3081 ierr = DMLabelGetValue(depth, closure[c], &pdim);CHKERRQ(ierr); 3082 ierr = DMLabelSetValue(subpointMap, closure[c], pdim);CHKERRQ(ierr); 3083 } 3084 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3085 } 3086 if (pointIS) {ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr);} 3087 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 3088 } 3089 /* Setup chart */ 3090 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3091 ierr = PetscMalloc4(dim+1,&numSubPoints,dim+1,&firstSubPoint,dim+1,&subpointIS,dim+1,&subpoints);CHKERRQ(ierr); 3092 for (d = 0; d <= dim; ++d) { 3093 ierr = DMLabelGetStratumSize(subpointMap, d, &numSubPoints[d]);CHKERRQ(ierr); 3094 totSubPoints += numSubPoints[d]; 3095 } 3096 ierr = DMPlexSetChart(subdm, 0, totSubPoints);CHKERRQ(ierr); 3097 ierr = DMPlexSetVTKCellHeight(subdm, cellHeight);CHKERRQ(ierr); 3098 /* Set cone sizes */ 3099 firstSubPoint[dim] = 0; 3100 firstSubPoint[0] = firstSubPoint[dim] + numSubPoints[dim]; 3101 if (dim > 1) {firstSubPoint[dim-1] = firstSubPoint[0] + numSubPoints[0];} 3102 if (dim > 2) {firstSubPoint[dim-2] = firstSubPoint[dim-1] + numSubPoints[dim-1];} 3103 for (d = 0; d <= dim; ++d) { 3104 ierr = DMLabelGetStratumIS(subpointMap, d, &subpointIS[d]);CHKERRQ(ierr); 3105 if (subpointIS[d]) {ierr = ISGetIndices(subpointIS[d], &subpoints[d]);CHKERRQ(ierr);} 3106 } 3107 /* We do not want this label automatically computed, instead we compute it here */ 3108 ierr = DMCreateLabel(subdm, "celltype");CHKERRQ(ierr); 3109 for (d = 0; d <= dim; ++d) { 3110 for (p = 0; p < numSubPoints[d]; ++p) { 3111 const PetscInt point = subpoints[d][p]; 3112 const PetscInt subpoint = firstSubPoint[d] + p; 3113 const PetscInt *cone; 3114 PetscInt coneSize, coneSizeNew, c, val; 3115 DMPolytopeType ct; 3116 3117 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 3118 ierr = DMPlexSetConeSize(subdm, subpoint, coneSize);CHKERRQ(ierr); 3119 ierr = DMPlexGetCellType(dm, point, &ct);CHKERRQ(ierr); 3120 ierr = DMPlexSetCellType(subdm, subpoint, ct);CHKERRQ(ierr); 3121 if (cellHeight && (d == dim)) { 3122 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3123 for (c = 0, coneSizeNew = 0; c < coneSize; ++c) { 3124 ierr = DMLabelGetValue(subpointMap, cone[c], &val);CHKERRQ(ierr); 3125 if (val >= 0) coneSizeNew++; 3126 } 3127 ierr = DMPlexSetConeSize(subdm, subpoint, coneSizeNew);CHKERRQ(ierr); 3128 ierr = DMPlexSetCellType(subdm, subpoint, DM_POLYTOPE_FV_GHOST);CHKERRQ(ierr); 3129 } 3130 } 3131 } 3132 ierr = DMLabelDestroy(&subpointMap);CHKERRQ(ierr); 3133 ierr = DMSetUp(subdm);CHKERRQ(ierr); 3134 /* Set cones */ 3135 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, NULL);CHKERRQ(ierr); 3136 ierr = PetscMalloc2(maxConeSize,&coneNew,maxConeSize,&orntNew);CHKERRQ(ierr); 3137 for (d = 0; d <= dim; ++d) { 3138 for (p = 0; p < numSubPoints[d]; ++p) { 3139 const PetscInt point = subpoints[d][p]; 3140 const PetscInt subpoint = firstSubPoint[d] + p; 3141 const PetscInt *cone, *ornt; 3142 PetscInt coneSize, subconeSize, coneSizeNew, c, subc, fornt = 0; 3143 3144 if (d == dim-1) { 3145 const PetscInt *support, *cone, *ornt; 3146 PetscInt supportSize, coneSize, s, subc; 3147 3148 ierr = DMPlexGetSupport(dm, point, &support);CHKERRQ(ierr); 3149 ierr = DMPlexGetSupportSize(dm, point, &supportSize);CHKERRQ(ierr); 3150 for (s = 0; s < supportSize; ++s) { 3151 PetscBool isHybrid; 3152 3153 ierr = DMPlexCellIsHybrid_Internal(dm, support[s], &isHybrid);CHKERRQ(ierr); 3154 if (!isHybrid) continue; 3155 ierr = PetscFindInt(support[s], numSubPoints[d+1], subpoints[d+1], &subc);CHKERRQ(ierr); 3156 if (subc >= 0) { 3157 const PetscInt ccell = subpoints[d+1][subc]; 3158 3159 ierr = DMPlexGetCone(dm, ccell, &cone);CHKERRQ(ierr); 3160 ierr = DMPlexGetConeSize(dm, ccell, &coneSize);CHKERRQ(ierr); 3161 ierr = DMPlexGetConeOrientation(dm, ccell, &ornt);CHKERRQ(ierr); 3162 for (c = 0; c < coneSize; ++c) { 3163 if (cone[c] == point) { 3164 fornt = ornt[c]; 3165 break; 3166 } 3167 } 3168 break; 3169 } 3170 } 3171 } 3172 ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr); 3173 ierr = DMPlexGetConeSize(subdm, subpoint, &subconeSize);CHKERRQ(ierr); 3174 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3175 ierr = DMPlexGetConeOrientation(dm, point, &ornt);CHKERRQ(ierr); 3176 for (c = 0, coneSizeNew = 0; c < coneSize; ++c) { 3177 ierr = PetscFindInt(cone[c], numSubPoints[d-1], subpoints[d-1], &subc);CHKERRQ(ierr); 3178 if (subc >= 0) { 3179 coneNew[coneSizeNew] = firstSubPoint[d-1] + subc; 3180 orntNew[coneSizeNew] = ornt[c]; 3181 ++coneSizeNew; 3182 } 3183 } 3184 if (coneSizeNew != subconeSize) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of cone points located %d does not match subcone size %d", coneSizeNew, subconeSize); 3185 ierr = DMPlexSetCone(subdm, subpoint, coneNew);CHKERRQ(ierr); 3186 ierr = DMPlexSetConeOrientation(subdm, subpoint, orntNew);CHKERRQ(ierr); 3187 if (fornt < 0) {ierr = DMPlexOrientPoint(subdm, subpoint, fornt);CHKERRQ(ierr);} 3188 } 3189 } 3190 ierr = PetscFree2(coneNew,orntNew);CHKERRQ(ierr); 3191 ierr = DMPlexSymmetrize(subdm);CHKERRQ(ierr); 3192 ierr = DMPlexStratify(subdm);CHKERRQ(ierr); 3193 /* Build coordinates */ 3194 { 3195 PetscSection coordSection, subCoordSection; 3196 Vec coordinates, subCoordinates; 3197 PetscScalar *coords, *subCoords; 3198 PetscInt cdim, numComp, coordSize; 3199 const char *name; 3200 3201 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 3202 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3203 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3204 ierr = DMGetCoordinateSection(subdm, &subCoordSection);CHKERRQ(ierr); 3205 ierr = PetscSectionSetNumFields(subCoordSection, 1);CHKERRQ(ierr); 3206 ierr = PetscSectionGetFieldComponents(coordSection, 0, &numComp);CHKERRQ(ierr); 3207 ierr = PetscSectionSetFieldComponents(subCoordSection, 0, numComp);CHKERRQ(ierr); 3208 ierr = PetscSectionSetChart(subCoordSection, firstSubPoint[0], firstSubPoint[0]+numSubPoints[0]);CHKERRQ(ierr); 3209 for (v = 0; v < numSubPoints[0]; ++v) { 3210 const PetscInt vertex = subpoints[0][v]; 3211 const PetscInt subvertex = firstSubPoint[0]+v; 3212 PetscInt dof; 3213 3214 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 3215 ierr = PetscSectionSetDof(subCoordSection, subvertex, dof);CHKERRQ(ierr); 3216 ierr = PetscSectionSetFieldDof(subCoordSection, subvertex, 0, dof);CHKERRQ(ierr); 3217 } 3218 ierr = PetscSectionSetUp(subCoordSection);CHKERRQ(ierr); 3219 ierr = PetscSectionGetStorageSize(subCoordSection, &coordSize);CHKERRQ(ierr); 3220 ierr = VecCreate(PETSC_COMM_SELF, &subCoordinates);CHKERRQ(ierr); 3221 ierr = PetscObjectGetName((PetscObject)coordinates,&name);CHKERRQ(ierr); 3222 ierr = PetscObjectSetName((PetscObject)subCoordinates,name);CHKERRQ(ierr); 3223 ierr = VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 3224 ierr = VecSetBlockSize(subCoordinates, cdim);CHKERRQ(ierr); 3225 ierr = VecSetType(subCoordinates,VECSTANDARD);CHKERRQ(ierr); 3226 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 3227 ierr = VecGetArray(subCoordinates, &subCoords);CHKERRQ(ierr); 3228 for (v = 0; v < numSubPoints[0]; ++v) { 3229 const PetscInt vertex = subpoints[0][v]; 3230 const PetscInt subvertex = firstSubPoint[0]+v; 3231 PetscInt dof, off, sdof, soff, d; 3232 3233 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 3234 ierr = PetscSectionGetOffset(coordSection, vertex, &off);CHKERRQ(ierr); 3235 ierr = PetscSectionGetDof(subCoordSection, subvertex, &sdof);CHKERRQ(ierr); 3236 ierr = PetscSectionGetOffset(subCoordSection, subvertex, &soff);CHKERRQ(ierr); 3237 if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subvertex, vertex, dof); 3238 for (d = 0; d < dof; ++d) subCoords[soff+d] = coords[off+d]; 3239 } 3240 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 3241 ierr = VecRestoreArray(subCoordinates, &subCoords);CHKERRQ(ierr); 3242 ierr = DMSetCoordinatesLocal(subdm, subCoordinates);CHKERRQ(ierr); 3243 ierr = VecDestroy(&subCoordinates);CHKERRQ(ierr); 3244 } 3245 /* Build SF: We need this complexity because subpoints might not be selected on the owning process */ 3246 { 3247 PetscSF sfPoint, sfPointSub; 3248 IS subpIS; 3249 const PetscSFNode *remotePoints; 3250 PetscSFNode *sremotePoints, *newLocalPoints, *newOwners; 3251 const PetscInt *localPoints, *subpoints; 3252 PetscInt *slocalPoints; 3253 PetscInt numRoots, numLeaves, numSubpoints = 0, numSubroots, numSubleaves = 0, l, sl, ll, pStart, pEnd, p; 3254 PetscMPIInt rank; 3255 3256 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 3257 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3258 ierr = DMGetPointSF(subdm, &sfPointSub);CHKERRQ(ierr); 3259 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3260 ierr = DMPlexGetChart(subdm, NULL, &numSubroots);CHKERRQ(ierr); 3261 ierr = DMPlexGetSubpointIS(subdm, &subpIS);CHKERRQ(ierr); 3262 if (subpIS) { 3263 ierr = ISGetIndices(subpIS, &subpoints);CHKERRQ(ierr); 3264 ierr = ISGetLocalSize(subpIS, &numSubpoints);CHKERRQ(ierr); 3265 } 3266 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3267 if (numRoots >= 0) { 3268 ierr = PetscMalloc2(pEnd-pStart,&newLocalPoints,numRoots,&newOwners);CHKERRQ(ierr); 3269 for (p = 0; p < pEnd-pStart; ++p) { 3270 newLocalPoints[p].rank = -2; 3271 newLocalPoints[p].index = -2; 3272 } 3273 /* Set subleaves */ 3274 for (l = 0; l < numLeaves; ++l) { 3275 const PetscInt point = localPoints[l]; 3276 const PetscInt subpoint = DMPlexFilterPoint_Internal(point, 0, numSubpoints, subpoints); 3277 3278 if (subpoint < 0) continue; 3279 newLocalPoints[point-pStart].rank = rank; 3280 newLocalPoints[point-pStart].index = subpoint; 3281 ++numSubleaves; 3282 } 3283 /* Must put in owned subpoints */ 3284 for (p = pStart; p < pEnd; ++p) { 3285 const PetscInt subpoint = DMPlexFilterPoint_Internal(p, 0, numSubpoints, subpoints); 3286 3287 if (subpoint < 0) { 3288 newOwners[p-pStart].rank = -3; 3289 newOwners[p-pStart].index = -3; 3290 } else { 3291 newOwners[p-pStart].rank = rank; 3292 newOwners[p-pStart].index = subpoint; 3293 } 3294 } 3295 ierr = PetscSFReduceBegin(sfPoint, MPIU_2INT, newLocalPoints, newOwners, MPI_MAXLOC);CHKERRQ(ierr); 3296 ierr = PetscSFReduceEnd(sfPoint, MPIU_2INT, newLocalPoints, newOwners, MPI_MAXLOC);CHKERRQ(ierr); 3297 ierr = PetscSFBcastBegin(sfPoint, MPIU_2INT, newOwners, newLocalPoints,MPI_REPLACE);CHKERRQ(ierr); 3298 ierr = PetscSFBcastEnd(sfPoint, MPIU_2INT, newOwners, newLocalPoints,MPI_REPLACE);CHKERRQ(ierr); 3299 ierr = PetscMalloc1(numSubleaves, &slocalPoints);CHKERRQ(ierr); 3300 ierr = PetscMalloc1(numSubleaves, &sremotePoints);CHKERRQ(ierr); 3301 for (l = 0, sl = 0, ll = 0; l < numLeaves; ++l) { 3302 const PetscInt point = localPoints[l]; 3303 const PetscInt subpoint = DMPlexFilterPoint_Internal(point, 0, numSubpoints, subpoints); 3304 3305 if (subpoint < 0) continue; 3306 if (newLocalPoints[point].rank == rank) {++ll; continue;} 3307 slocalPoints[sl] = subpoint; 3308 sremotePoints[sl].rank = newLocalPoints[point].rank; 3309 sremotePoints[sl].index = newLocalPoints[point].index; 3310 if (sremotePoints[sl].rank < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid remote rank for local point %d", point); 3311 if (sremotePoints[sl].index < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid remote subpoint for local point %d", point); 3312 ++sl; 3313 } 3314 if (sl + ll != numSubleaves) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatch in number of subleaves %d + %d != %d", sl, ll, numSubleaves); 3315 ierr = PetscFree2(newLocalPoints,newOwners);CHKERRQ(ierr); 3316 ierr = PetscSFSetGraph(sfPointSub, numSubroots, sl, slocalPoints, PETSC_OWN_POINTER, sremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3317 } 3318 if (subpIS) { 3319 ierr = ISRestoreIndices(subpIS, &subpoints);CHKERRQ(ierr); 3320 } 3321 } 3322 /* Cleanup */ 3323 for (d = 0; d <= dim; ++d) { 3324 if (subpointIS[d]) {ierr = ISRestoreIndices(subpointIS[d], &subpoints[d]);CHKERRQ(ierr);} 3325 ierr = ISDestroy(&subpointIS[d]);CHKERRQ(ierr); 3326 } 3327 ierr = PetscFree4(numSubPoints,firstSubPoint,subpointIS,subpoints);CHKERRQ(ierr); 3328 PetscFunctionReturn(0); 3329 } 3330 3331 static PetscErrorCode DMPlexCreateSubmesh_Interpolated(DM dm, DMLabel vertexLabel, PetscInt value, PetscBool markedFaces, DM subdm) 3332 { 3333 PetscErrorCode ierr; 3334 3335 PetscFunctionBegin; 3336 ierr = DMPlexCreateSubmeshGeneric_Interpolated(dm, vertexLabel, value, markedFaces, PETSC_FALSE, 1, subdm);CHKERRQ(ierr); 3337 PetscFunctionReturn(0); 3338 } 3339 3340 /*@ 3341 DMPlexCreateSubmesh - Extract a hypersurface from the mesh using vertices defined by a label 3342 3343 Input Parameters: 3344 + dm - The original mesh 3345 . vertexLabel - The DMLabel marking points contained in the surface 3346 . value - The label value to use 3347 - markedFaces - PETSC_TRUE if surface faces are marked in addition to vertices, PETSC_FALSE if only vertices are marked 3348 3349 Output Parameter: 3350 . subdm - The surface mesh 3351 3352 Note: This function produces a DMLabel mapping original points in the submesh to their depth. This can be obtained using DMPlexGetSubpointMap(). 3353 3354 Level: developer 3355 3356 .seealso: DMPlexGetSubpointMap(), DMGetLabel(), DMLabelSetValue() 3357 @*/ 3358 PetscErrorCode DMPlexCreateSubmesh(DM dm, DMLabel vertexLabel, PetscInt value, PetscBool markedFaces, DM *subdm) 3359 { 3360 DMPlexInterpolatedFlag interpolated; 3361 PetscInt dim, cdim; 3362 PetscErrorCode ierr; 3363 3364 PetscFunctionBegin; 3365 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3366 PetscValidPointer(subdm, 5); 3367 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3368 ierr = DMCreate(PetscObjectComm((PetscObject)dm), subdm);CHKERRQ(ierr); 3369 ierr = DMSetType(*subdm, DMPLEX);CHKERRQ(ierr); 3370 ierr = DMSetDimension(*subdm, dim-1);CHKERRQ(ierr); 3371 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 3372 ierr = DMSetCoordinateDim(*subdm, cdim);CHKERRQ(ierr); 3373 ierr = DMPlexIsInterpolated(dm, &interpolated);CHKERRQ(ierr); 3374 if (interpolated == DMPLEX_INTERPOLATED_PARTIAL) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not for partially interpolated meshes"); 3375 if (interpolated) { 3376 ierr = DMPlexCreateSubmesh_Interpolated(dm, vertexLabel, value, markedFaces, *subdm);CHKERRQ(ierr); 3377 } else { 3378 ierr = DMPlexCreateSubmesh_Uninterpolated(dm, vertexLabel, value, *subdm);CHKERRQ(ierr); 3379 } 3380 PetscFunctionReturn(0); 3381 } 3382 3383 static PetscErrorCode DMPlexCreateCohesiveSubmesh_Uninterpolated(DM dm, PetscBool hasLagrange, const char label[], PetscInt value, DM subdm) 3384 { 3385 MPI_Comm comm; 3386 DMLabel subpointMap; 3387 IS subvertexIS; 3388 const PetscInt *subVertices; 3389 PetscInt numSubVertices, firstSubVertex, numSubCells, *subCells = NULL; 3390 PetscInt *subface, maxConeSize, numSubFaces, firstSubFace, newFacePoint, nFV; 3391 PetscInt c, f; 3392 PetscErrorCode ierr; 3393 3394 PetscFunctionBegin; 3395 ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr); 3396 /* Create subpointMap which marks the submesh */ 3397 ierr = DMLabelCreate(PETSC_COMM_SELF, "subpoint_map", &subpointMap);CHKERRQ(ierr); 3398 ierr = DMPlexSetSubpointMap(subdm, subpointMap);CHKERRQ(ierr); 3399 ierr = DMLabelDestroy(&subpointMap);CHKERRQ(ierr); 3400 ierr = DMPlexMarkCohesiveSubmesh_Uninterpolated(dm, hasLagrange, label, value, subpointMap, &numSubFaces, &nFV, &subCells, subdm);CHKERRQ(ierr); 3401 /* Setup chart */ 3402 ierr = DMLabelGetStratumSize(subpointMap, 0, &numSubVertices);CHKERRQ(ierr); 3403 ierr = DMLabelGetStratumSize(subpointMap, 2, &numSubCells);CHKERRQ(ierr); 3404 ierr = DMPlexSetChart(subdm, 0, numSubCells+numSubFaces+numSubVertices);CHKERRQ(ierr); 3405 ierr = DMPlexSetVTKCellHeight(subdm, 1);CHKERRQ(ierr); 3406 /* Set cone sizes */ 3407 firstSubVertex = numSubCells; 3408 firstSubFace = numSubCells+numSubVertices; 3409 newFacePoint = firstSubFace; 3410 ierr = DMLabelGetStratumIS(subpointMap, 0, &subvertexIS);CHKERRQ(ierr); 3411 if (subvertexIS) {ierr = ISGetIndices(subvertexIS, &subVertices);CHKERRQ(ierr);} 3412 for (c = 0; c < numSubCells; ++c) { 3413 ierr = DMPlexSetConeSize(subdm, c, 1);CHKERRQ(ierr); 3414 } 3415 for (f = firstSubFace; f < firstSubFace+numSubFaces; ++f) { 3416 ierr = DMPlexSetConeSize(subdm, f, nFV);CHKERRQ(ierr); 3417 } 3418 ierr = DMSetUp(subdm);CHKERRQ(ierr); 3419 /* Create face cones */ 3420 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, NULL);CHKERRQ(ierr); 3421 ierr = DMGetWorkArray(subdm, maxConeSize, MPIU_INT, (void**) &subface);CHKERRQ(ierr); 3422 for (c = 0; c < numSubCells; ++c) { 3423 const PetscInt cell = subCells[c]; 3424 const PetscInt subcell = c; 3425 const PetscInt *cone, *cells; 3426 PetscBool isHybrid; 3427 PetscInt numCells, subVertex, p, v; 3428 3429 ierr = DMPlexCellIsHybrid_Internal(dm, cell, &isHybrid);CHKERRQ(ierr); 3430 if (!isHybrid) continue; 3431 ierr = DMPlexGetCone(dm, cell, &cone);CHKERRQ(ierr); 3432 for (v = 0; v < nFV; ++v) { 3433 ierr = PetscFindInt(cone[v], numSubVertices, subVertices, &subVertex);CHKERRQ(ierr); 3434 subface[v] = firstSubVertex+subVertex; 3435 } 3436 ierr = DMPlexSetCone(subdm, newFacePoint, subface);CHKERRQ(ierr); 3437 ierr = DMPlexSetCone(subdm, subcell, &newFacePoint);CHKERRQ(ierr); 3438 ierr = DMPlexGetJoin(dm, nFV, cone, &numCells, &cells);CHKERRQ(ierr); 3439 /* Not true in parallel 3440 if (numCells != 2) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cohesive cells should separate two cells"); */ 3441 for (p = 0; p < numCells; ++p) { 3442 PetscInt negsubcell; 3443 PetscBool isHybrid; 3444 3445 ierr = DMPlexCellIsHybrid_Internal(dm, cells[p], &isHybrid);CHKERRQ(ierr); 3446 if (isHybrid) continue; 3447 /* I know this is a crap search */ 3448 for (negsubcell = 0; negsubcell < numSubCells; ++negsubcell) { 3449 if (subCells[negsubcell] == cells[p]) break; 3450 } 3451 if (negsubcell == numSubCells) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find negative face neighbor for cohesive cell %d", cell); 3452 ierr = DMPlexSetCone(subdm, negsubcell, &newFacePoint);CHKERRQ(ierr); 3453 } 3454 ierr = DMPlexRestoreJoin(dm, nFV, cone, &numCells, &cells);CHKERRQ(ierr); 3455 ++newFacePoint; 3456 } 3457 ierr = DMRestoreWorkArray(subdm, maxConeSize, MPIU_INT, (void**) &subface);CHKERRQ(ierr); 3458 ierr = DMPlexSymmetrize(subdm);CHKERRQ(ierr); 3459 ierr = DMPlexStratify(subdm);CHKERRQ(ierr); 3460 /* Build coordinates */ 3461 { 3462 PetscSection coordSection, subCoordSection; 3463 Vec coordinates, subCoordinates; 3464 PetscScalar *coords, *subCoords; 3465 PetscInt cdim, numComp, coordSize, v; 3466 const char *name; 3467 3468 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 3469 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3470 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3471 ierr = DMGetCoordinateSection(subdm, &subCoordSection);CHKERRQ(ierr); 3472 ierr = PetscSectionSetNumFields(subCoordSection, 1);CHKERRQ(ierr); 3473 ierr = PetscSectionGetFieldComponents(coordSection, 0, &numComp);CHKERRQ(ierr); 3474 ierr = PetscSectionSetFieldComponents(subCoordSection, 0, numComp);CHKERRQ(ierr); 3475 ierr = PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex+numSubVertices);CHKERRQ(ierr); 3476 for (v = 0; v < numSubVertices; ++v) { 3477 const PetscInt vertex = subVertices[v]; 3478 const PetscInt subvertex = firstSubVertex+v; 3479 PetscInt dof; 3480 3481 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 3482 ierr = PetscSectionSetDof(subCoordSection, subvertex, dof);CHKERRQ(ierr); 3483 ierr = PetscSectionSetFieldDof(subCoordSection, subvertex, 0, dof);CHKERRQ(ierr); 3484 } 3485 ierr = PetscSectionSetUp(subCoordSection);CHKERRQ(ierr); 3486 ierr = PetscSectionGetStorageSize(subCoordSection, &coordSize);CHKERRQ(ierr); 3487 ierr = VecCreate(PETSC_COMM_SELF, &subCoordinates);CHKERRQ(ierr); 3488 ierr = PetscObjectGetName((PetscObject)coordinates,&name);CHKERRQ(ierr); 3489 ierr = PetscObjectSetName((PetscObject)subCoordinates,name);CHKERRQ(ierr); 3490 ierr = VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 3491 ierr = VecSetBlockSize(subCoordinates, cdim);CHKERRQ(ierr); 3492 ierr = VecSetType(subCoordinates,VECSTANDARD);CHKERRQ(ierr); 3493 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 3494 ierr = VecGetArray(subCoordinates, &subCoords);CHKERRQ(ierr); 3495 for (v = 0; v < numSubVertices; ++v) { 3496 const PetscInt vertex = subVertices[v]; 3497 const PetscInt subvertex = firstSubVertex+v; 3498 PetscInt dof, off, sdof, soff, d; 3499 3500 ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 3501 ierr = PetscSectionGetOffset(coordSection, vertex, &off);CHKERRQ(ierr); 3502 ierr = PetscSectionGetDof(subCoordSection, subvertex, &sdof);CHKERRQ(ierr); 3503 ierr = PetscSectionGetOffset(subCoordSection, subvertex, &soff);CHKERRQ(ierr); 3504 if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subvertex, vertex, dof); 3505 for (d = 0; d < dof; ++d) subCoords[soff+d] = coords[off+d]; 3506 } 3507 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 3508 ierr = VecRestoreArray(subCoordinates, &subCoords);CHKERRQ(ierr); 3509 ierr = DMSetCoordinatesLocal(subdm, subCoordinates);CHKERRQ(ierr); 3510 ierr = VecDestroy(&subCoordinates);CHKERRQ(ierr); 3511 } 3512 /* Build SF */ 3513 CHKMEMQ; 3514 { 3515 PetscSF sfPoint, sfPointSub; 3516 const PetscSFNode *remotePoints; 3517 PetscSFNode *sremotePoints, *newLocalPoints, *newOwners; 3518 const PetscInt *localPoints; 3519 PetscInt *slocalPoints; 3520 PetscInt numRoots, numLeaves, numSubRoots = numSubCells+numSubFaces+numSubVertices, numSubLeaves = 0, l, sl, ll, pStart, pEnd, p, vStart, vEnd; 3521 PetscMPIInt rank; 3522 3523 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 3524 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3525 ierr = DMGetPointSF(subdm, &sfPointSub);CHKERRQ(ierr); 3526 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3527 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3528 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3529 if (numRoots >= 0) { 3530 /* Only vertices should be shared */ 3531 ierr = PetscMalloc2(pEnd-pStart,&newLocalPoints,numRoots,&newOwners);CHKERRQ(ierr); 3532 for (p = 0; p < pEnd-pStart; ++p) { 3533 newLocalPoints[p].rank = -2; 3534 newLocalPoints[p].index = -2; 3535 } 3536 /* Set subleaves */ 3537 for (l = 0; l < numLeaves; ++l) { 3538 const PetscInt point = localPoints[l]; 3539 const PetscInt subPoint = DMPlexFilterPoint_Internal(point, firstSubVertex, numSubVertices, subVertices); 3540 3541 if ((point < vStart) && (point >= vEnd)) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Should not be mapping anything but vertices, %d", point); 3542 if (subPoint < 0) continue; 3543 newLocalPoints[point-pStart].rank = rank; 3544 newLocalPoints[point-pStart].index = subPoint; 3545 ++numSubLeaves; 3546 } 3547 /* Must put in owned subpoints */ 3548 for (p = pStart; p < pEnd; ++p) { 3549 const PetscInt subPoint = DMPlexFilterPoint_Internal(p, firstSubVertex, numSubVertices, subVertices); 3550 3551 if (subPoint < 0) { 3552 newOwners[p-pStart].rank = -3; 3553 newOwners[p-pStart].index = -3; 3554 } else { 3555 newOwners[p-pStart].rank = rank; 3556 newOwners[p-pStart].index = subPoint; 3557 } 3558 } 3559 ierr = PetscSFReduceBegin(sfPoint, MPIU_2INT, newLocalPoints, newOwners, MPI_MAXLOC);CHKERRQ(ierr); 3560 ierr = PetscSFReduceEnd(sfPoint, MPIU_2INT, newLocalPoints, newOwners, MPI_MAXLOC);CHKERRQ(ierr); 3561 ierr = PetscSFBcastBegin(sfPoint, MPIU_2INT, newOwners, newLocalPoints,MPI_REPLACE);CHKERRQ(ierr); 3562 ierr = PetscSFBcastEnd(sfPoint, MPIU_2INT, newOwners, newLocalPoints,MPI_REPLACE);CHKERRQ(ierr); 3563 ierr = PetscMalloc1(numSubLeaves, &slocalPoints);CHKERRQ(ierr); 3564 ierr = PetscMalloc1(numSubLeaves, &sremotePoints);CHKERRQ(ierr); 3565 for (l = 0, sl = 0, ll = 0; l < numLeaves; ++l) { 3566 const PetscInt point = localPoints[l]; 3567 const PetscInt subPoint = DMPlexFilterPoint_Internal(point, firstSubVertex, numSubVertices, subVertices); 3568 3569 if (subPoint < 0) continue; 3570 if (newLocalPoints[point].rank == rank) {++ll; continue;} 3571 slocalPoints[sl] = subPoint; 3572 sremotePoints[sl].rank = newLocalPoints[point].rank; 3573 sremotePoints[sl].index = newLocalPoints[point].index; 3574 if (sremotePoints[sl].rank < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid remote rank for local point %d", point); 3575 if (sremotePoints[sl].index < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid remote subpoint for local point %d", point); 3576 ++sl; 3577 } 3578 ierr = PetscFree2(newLocalPoints,newOwners);CHKERRQ(ierr); 3579 if (sl + ll != numSubLeaves) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Mismatch in number of subleaves %d + %d != %d", sl, ll, numSubLeaves); 3580 ierr = PetscSFSetGraph(sfPointSub, numSubRoots, sl, slocalPoints, PETSC_OWN_POINTER, sremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3581 } 3582 } 3583 CHKMEMQ; 3584 /* Cleanup */ 3585 if (subvertexIS) {ierr = ISRestoreIndices(subvertexIS, &subVertices);CHKERRQ(ierr);} 3586 ierr = ISDestroy(&subvertexIS);CHKERRQ(ierr); 3587 ierr = PetscFree(subCells);CHKERRQ(ierr); 3588 PetscFunctionReturn(0); 3589 } 3590 3591 static PetscErrorCode DMPlexCreateCohesiveSubmesh_Interpolated(DM dm, const char labelname[], PetscInt value, DM subdm) 3592 { 3593 DMLabel label = NULL; 3594 PetscErrorCode ierr; 3595 3596 PetscFunctionBegin; 3597 if (labelname) {ierr = DMGetLabel(dm, labelname, &label);CHKERRQ(ierr);} 3598 ierr = DMPlexCreateSubmeshGeneric_Interpolated(dm, label, value, PETSC_FALSE, PETSC_TRUE, 1, subdm);CHKERRQ(ierr); 3599 PetscFunctionReturn(0); 3600 } 3601 3602 /*@C 3603 DMPlexCreateCohesiveSubmesh - Extract from a mesh with cohesive cells the hypersurface defined by one face of the cells. Optionally, a Label an be given to restrict the cells. 3604 3605 Input Parameters: 3606 + dm - The original mesh 3607 . hasLagrange - The mesh has Lagrange unknowns in the cohesive cells 3608 . label - A label name, or NULL 3609 - value - A label value 3610 3611 Output Parameter: 3612 . subdm - The surface mesh 3613 3614 Note: This function produces a DMLabel mapping original points in the submesh to their depth. This can be obtained using DMPlexGetSubpointMap(). 3615 3616 Level: developer 3617 3618 .seealso: DMPlexGetSubpointMap(), DMPlexCreateSubmesh() 3619 @*/ 3620 PetscErrorCode DMPlexCreateCohesiveSubmesh(DM dm, PetscBool hasLagrange, const char label[], PetscInt value, DM *subdm) 3621 { 3622 PetscInt dim, cdim, depth; 3623 PetscErrorCode ierr; 3624 3625 PetscFunctionBegin; 3626 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3627 PetscValidPointer(subdm, 5); 3628 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3629 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3630 ierr = DMCreate(PetscObjectComm((PetscObject)dm), subdm);CHKERRQ(ierr); 3631 ierr = DMSetType(*subdm, DMPLEX);CHKERRQ(ierr); 3632 ierr = DMSetDimension(*subdm, dim-1);CHKERRQ(ierr); 3633 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 3634 ierr = DMSetCoordinateDim(*subdm, cdim);CHKERRQ(ierr); 3635 if (depth == dim) { 3636 ierr = DMPlexCreateCohesiveSubmesh_Interpolated(dm, label, value, *subdm);CHKERRQ(ierr); 3637 } else { 3638 ierr = DMPlexCreateCohesiveSubmesh_Uninterpolated(dm, hasLagrange, label, value, *subdm);CHKERRQ(ierr); 3639 } 3640 PetscFunctionReturn(0); 3641 } 3642 3643 /*@ 3644 DMPlexFilter - Extract a subset of mesh cells defined by a label as a separate mesh 3645 3646 Input Parameters: 3647 + dm - The original mesh 3648 . cellLabel - The DMLabel marking cells contained in the new mesh 3649 - value - The label value to use 3650 3651 Output Parameter: 3652 . subdm - The new mesh 3653 3654 Note: This function produces a DMLabel mapping original points in the submesh to their depth. This can be obtained using DMPlexGetSubpointMap(). 3655 3656 Level: developer 3657 3658 .seealso: DMPlexGetSubpointMap(), DMGetLabel(), DMLabelSetValue() 3659 @*/ 3660 PetscErrorCode DMPlexFilter(DM dm, DMLabel cellLabel, PetscInt value, DM *subdm) 3661 { 3662 PetscInt dim; 3663 PetscErrorCode ierr; 3664 3665 PetscFunctionBegin; 3666 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3667 PetscValidPointer(subdm, 4); 3668 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3669 ierr = DMCreate(PetscObjectComm((PetscObject) dm), subdm);CHKERRQ(ierr); 3670 ierr = DMSetType(*subdm, DMPLEX);CHKERRQ(ierr); 3671 ierr = DMSetDimension(*subdm, dim);CHKERRQ(ierr); 3672 /* Extract submesh in place, could be empty on some procs, could have inconsistency if procs do not both extract a shared cell */ 3673 ierr = DMPlexCreateSubmeshGeneric_Interpolated(dm, cellLabel, value, PETSC_FALSE, PETSC_FALSE, 0, *subdm);CHKERRQ(ierr); 3674 PetscFunctionReturn(0); 3675 } 3676 3677 /*@ 3678 DMPlexGetSubpointMap - Returns a DMLabel with point dimension as values 3679 3680 Input Parameter: 3681 . dm - The submesh DM 3682 3683 Output Parameter: 3684 . subpointMap - The DMLabel of all the points from the original mesh in this submesh, or NULL if this is not a submesh 3685 3686 Level: developer 3687 3688 .seealso: DMPlexCreateSubmesh(), DMPlexGetSubpointIS() 3689 @*/ 3690 PetscErrorCode DMPlexGetSubpointMap(DM dm, DMLabel *subpointMap) 3691 { 3692 PetscFunctionBegin; 3693 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3694 PetscValidPointer(subpointMap, 2); 3695 *subpointMap = ((DM_Plex*) dm->data)->subpointMap; 3696 PetscFunctionReturn(0); 3697 } 3698 3699 /*@ 3700 DMPlexSetSubpointMap - Sets the DMLabel with point dimension as values 3701 3702 Input Parameters: 3703 + dm - The submesh DM 3704 - subpointMap - The DMLabel of all the points from the original mesh in this submesh 3705 3706 Note: Should normally not be called by the user, since it is set in DMPlexCreateSubmesh() 3707 3708 Level: developer 3709 3710 .seealso: DMPlexCreateSubmesh(), DMPlexGetSubpointIS() 3711 @*/ 3712 PetscErrorCode DMPlexSetSubpointMap(DM dm, DMLabel subpointMap) 3713 { 3714 DM_Plex *mesh = (DM_Plex *) dm->data; 3715 DMLabel tmp; 3716 PetscErrorCode ierr; 3717 3718 PetscFunctionBegin; 3719 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3720 tmp = mesh->subpointMap; 3721 mesh->subpointMap = subpointMap; 3722 ierr = PetscObjectReference((PetscObject) mesh->subpointMap);CHKERRQ(ierr); 3723 ierr = DMLabelDestroy(&tmp);CHKERRQ(ierr); 3724 PetscFunctionReturn(0); 3725 } 3726 3727 static PetscErrorCode DMPlexCreateSubpointIS_Internal(DM dm, IS *subpointIS) 3728 { 3729 DMLabel spmap; 3730 PetscInt depth, d; 3731 PetscErrorCode ierr; 3732 3733 PetscFunctionBegin; 3734 ierr = DMPlexGetSubpointMap(dm, &spmap);CHKERRQ(ierr); 3735 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3736 if (spmap && depth >= 0) { 3737 DM_Plex *mesh = (DM_Plex *) dm->data; 3738 PetscInt *points, *depths; 3739 PetscInt pStart, pEnd, p, off; 3740 3741 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3742 if (pStart) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Submeshes must start the point numbering at 0, not %d", pStart); 3743 ierr = PetscMalloc1(pEnd, &points);CHKERRQ(ierr); 3744 ierr = DMGetWorkArray(dm, depth+1, MPIU_INT, &depths);CHKERRQ(ierr); 3745 depths[0] = depth; 3746 depths[1] = 0; 3747 for (d = 2; d <= depth; ++d) {depths[d] = depth+1 - d;} 3748 for (d = 0, off = 0; d <= depth; ++d) { 3749 const PetscInt dep = depths[d]; 3750 PetscInt depStart, depEnd, n; 3751 3752 ierr = DMPlexGetDepthStratum(dm, dep, &depStart, &depEnd);CHKERRQ(ierr); 3753 ierr = DMLabelGetStratumSize(spmap, dep, &n);CHKERRQ(ierr); 3754 if (((d < 2) && (depth > 1)) || (d == 1)) { /* Only check vertices and cells for now since the map is broken for others */ 3755 if (n != depEnd-depStart) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of mapped submesh points %d at depth %d should be %d", n, dep, depEnd-depStart); 3756 } else { 3757 if (!n) { 3758 if (d == 0) { 3759 /* Missing cells */ 3760 for (p = 0; p < depEnd-depStart; ++p, ++off) points[off] = -1; 3761 } else { 3762 /* Missing faces */ 3763 for (p = 0; p < depEnd-depStart; ++p, ++off) points[off] = PETSC_MAX_INT; 3764 } 3765 } 3766 } 3767 if (n) { 3768 IS is; 3769 const PetscInt *opoints; 3770 3771 ierr = DMLabelGetStratumIS(spmap, dep, &is);CHKERRQ(ierr); 3772 ierr = ISGetIndices(is, &opoints);CHKERRQ(ierr); 3773 for (p = 0; p < n; ++p, ++off) points[off] = opoints[p]; 3774 ierr = ISRestoreIndices(is, &opoints);CHKERRQ(ierr); 3775 ierr = ISDestroy(&is);CHKERRQ(ierr); 3776 } 3777 } 3778 ierr = DMRestoreWorkArray(dm, depth+1, MPIU_INT, &depths);CHKERRQ(ierr); 3779 if (off != pEnd) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of mapped submesh points %d should be %d", off, pEnd); 3780 ierr = ISCreateGeneral(PETSC_COMM_SELF, pEnd, points, PETSC_OWN_POINTER, subpointIS);CHKERRQ(ierr); 3781 ierr = PetscObjectStateGet((PetscObject) spmap, &mesh->subpointState);CHKERRQ(ierr); 3782 } 3783 PetscFunctionReturn(0); 3784 } 3785 3786 /*@ 3787 DMPlexGetSubpointIS - Returns an IS covering the entire subdm chart with the original points as data 3788 3789 Input Parameter: 3790 . dm - The submesh DM 3791 3792 Output Parameter: 3793 . subpointIS - The IS of all the points from the original mesh in this submesh, or NULL if this is not a submesh 3794 3795 Note: This IS is guaranteed to be sorted by the construction of the submesh 3796 3797 Level: developer 3798 3799 .seealso: DMPlexCreateSubmesh(), DMPlexGetSubpointMap() 3800 @*/ 3801 PetscErrorCode DMPlexGetSubpointIS(DM dm, IS *subpointIS) 3802 { 3803 DM_Plex *mesh = (DM_Plex *) dm->data; 3804 DMLabel spmap; 3805 PetscObjectState state; 3806 PetscErrorCode ierr; 3807 3808 PetscFunctionBegin; 3809 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3810 PetscValidPointer(subpointIS, 2); 3811 ierr = DMPlexGetSubpointMap(dm, &spmap);CHKERRQ(ierr); 3812 ierr = PetscObjectStateGet((PetscObject) spmap, &state);CHKERRQ(ierr); 3813 if (state != mesh->subpointState || !mesh->subpointIS) {ierr = DMPlexCreateSubpointIS_Internal(dm, &mesh->subpointIS);CHKERRQ(ierr);} 3814 *subpointIS = mesh->subpointIS; 3815 PetscFunctionReturn(0); 3816 } 3817 3818 /*@ 3819 DMGetEnclosureRelation - Get the relationship between dmA and dmB 3820 3821 Input Parameters: 3822 + dmA - The first DM 3823 - dmB - The second DM 3824 3825 Output Parameter: 3826 . rel - The relation of dmA to dmB 3827 3828 Level: intermediate 3829 3830 .seealso: DMGetEnclosurePoint() 3831 @*/ 3832 PetscErrorCode DMGetEnclosureRelation(DM dmA, DM dmB, DMEnclosureType *rel) 3833 { 3834 DM plexA, plexB, sdm; 3835 DMLabel spmap; 3836 PetscInt pStartA, pEndA, pStartB, pEndB, NpA, NpB; 3837 PetscErrorCode ierr; 3838 3839 PetscFunctionBegin; 3840 PetscValidPointer(rel, 3); 3841 *rel = DM_ENC_NONE; 3842 if (!dmA || !dmB) PetscFunctionReturn(0); 3843 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 3844 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 3845 if (dmA == dmB) {*rel = DM_ENC_EQUALITY; PetscFunctionReturn(0);} 3846 ierr = DMConvert(dmA, DMPLEX, &plexA);CHKERRQ(ierr); 3847 ierr = DMConvert(dmB, DMPLEX, &plexB);CHKERRQ(ierr); 3848 ierr = DMPlexGetChart(plexA, &pStartA, &pEndA);CHKERRQ(ierr); 3849 ierr = DMPlexGetChart(plexB, &pStartB, &pEndB);CHKERRQ(ierr); 3850 /* Assumption 1: subDMs have smaller charts than the DMs that they originate from 3851 - The degenerate case of a subdomain which includes all of the domain on some process can be treated as equality */ 3852 if ((pStartA == pStartB) && (pEndA == pEndB)) { 3853 *rel = DM_ENC_EQUALITY; 3854 goto end; 3855 } 3856 NpA = pEndA - pStartA; 3857 NpB = pEndB - pStartB; 3858 if (NpA == NpB) goto end; 3859 sdm = NpA > NpB ? plexB : plexA; /* The other is the original, enclosing dm */ 3860 ierr = DMPlexGetSubpointMap(sdm, &spmap);CHKERRQ(ierr); 3861 if (!spmap) goto end; 3862 /* TODO Check the space mapped to by subpointMap is same size as dm */ 3863 if (NpA > NpB) { 3864 *rel = DM_ENC_SUPERMESH; 3865 } else { 3866 *rel = DM_ENC_SUBMESH; 3867 } 3868 end: 3869 ierr = DMDestroy(&plexA);CHKERRQ(ierr); 3870 ierr = DMDestroy(&plexB);CHKERRQ(ierr); 3871 PetscFunctionReturn(0); 3872 } 3873 3874 /*@ 3875 DMGetEnclosurePoint - Get the point pA in dmA which corresponds to the point pB in dmB 3876 3877 Input Parameters: 3878 + dmA - The first DM 3879 . dmB - The second DM 3880 . etype - The type of enclosure relation that dmA has to dmB 3881 - pB - A point of dmB 3882 3883 Output Parameter: 3884 . pA - The corresponding point of dmA 3885 3886 Level: intermediate 3887 3888 .seealso: DMGetEnclosureRelation() 3889 @*/ 3890 PetscErrorCode DMGetEnclosurePoint(DM dmA, DM dmB, DMEnclosureType etype, PetscInt pB, PetscInt *pA) 3891 { 3892 DM sdm; 3893 IS subpointIS; 3894 const PetscInt *subpoints; 3895 PetscInt numSubpoints; 3896 PetscErrorCode ierr; 3897 3898 PetscFunctionBegin; 3899 /* TODO Cache the IS, making it look like an index */ 3900 switch (etype) { 3901 case DM_ENC_SUPERMESH: 3902 sdm = dmB; 3903 ierr = DMPlexGetSubpointIS(sdm, &subpointIS);CHKERRQ(ierr); 3904 ierr = ISGetIndices(subpointIS, &subpoints);CHKERRQ(ierr); 3905 *pA = subpoints[pB]; 3906 ierr = ISRestoreIndices(subpointIS, &subpoints);CHKERRQ(ierr); 3907 break; 3908 case DM_ENC_SUBMESH: 3909 sdm = dmA; 3910 ierr = DMPlexGetSubpointIS(sdm, &subpointIS);CHKERRQ(ierr); 3911 ierr = ISGetLocalSize(subpointIS, &numSubpoints);CHKERRQ(ierr); 3912 ierr = ISGetIndices(subpointIS, &subpoints);CHKERRQ(ierr); 3913 ierr = PetscFindInt(pB, numSubpoints, subpoints, pA);CHKERRQ(ierr); 3914 if (*pA < 0) { 3915 ierr = DMViewFromOptions(dmA, NULL, "-dm_enc_A_view");CHKERRQ(ierr); 3916 ierr = DMViewFromOptions(dmB, NULL, "-dm_enc_B_view");CHKERRQ(ierr); 3917 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %d not found in submesh", pB); 3918 } 3919 ierr = ISRestoreIndices(subpointIS, &subpoints);CHKERRQ(ierr); 3920 break; 3921 case DM_ENC_EQUALITY: 3922 case DM_ENC_NONE: 3923 *pA = pB;break; 3924 case DM_ENC_UNKNOWN: 3925 { 3926 DMEnclosureType enc; 3927 3928 ierr = DMGetEnclosureRelation(dmA, dmB, &enc);CHKERRQ(ierr); 3929 ierr = DMGetEnclosurePoint(dmA, dmB, enc, pB, pA);CHKERRQ(ierr); 3930 } 3931 break; 3932 default: SETERRQ1(PetscObjectComm((PetscObject) dmA), PETSC_ERR_ARG_OUTOFRANGE, "Invalid enclosure type %d", (int) etype); 3933 } 3934 PetscFunctionReturn(0); 3935 } 3936