1 #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <petsc/private/petscfeimpl.h> /* For PetscFEInterpolate_Static() */ 3 #include <petscsf.h> 4 5 PetscBool SBRcite = PETSC_FALSE; 6 const char SBRCitation[] = "@article{PlazaCarey2000,\n" 7 " title = {Local refinement of simplicial grids based on the skeleton},\n" 8 " journal = {Applied Numerical Mathematics},\n" 9 " author = {A. Plaza and Graham F. Carey},\n" 10 " volume = {32},\n" 11 " number = {3},\n" 12 " pages = {195--218},\n" 13 " doi = {10.1016/S0168-9274(99)00022-7},\n" 14 " year = {2000}\n}\n"; 15 16 const char * const DMPlexCellRefinerTypes[] = {"Regular", "ToBox", "ToSimplex", "Alfeld2D", "Alfeld3D", "PowellSabin", "BoundaryLayer", "SBR", "DMPlexCellRefinerTypes", "DM_REFINER_", NULL}; 17 18 /* 19 Note that j and invj are non-square: 20 v0 + j x_face = x_cell 21 invj (x_cell - v0) = x_face 22 */ 23 static PetscErrorCode DMPlexCellRefinerGetAffineFaceTransforms_Regular(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nf, PetscReal *v0[], PetscReal *J[], PetscReal *invJ[], PetscReal *detJ[]) 24 { 25 /* 26 2 27 |\ 28 | \ 29 | \ 30 | \ 31 | \ 32 | \ 33 | \ 34 2 1 35 | \ 36 | \ 37 | \ 38 0---0-------1 39 v0[Nf][dc]: 3 x 2 40 J[Nf][df][dc]: 3 x 1 x 2 41 invJ[Nf][dc][df]: 3 x 2 x 1 42 detJ[Nf]: 3 43 */ 44 static PetscReal tri_v0[] = {0.0, -1.0, 0.0, 0.0, -1.0, 0.0}; 45 static PetscReal tri_J[] = {1.0, 0.0, -1.0, 1.0, 0.0, -1.0}; 46 static PetscReal tri_invJ[] = {1.0, 0.0, -0.5, 0.5, 0.0, -1.0}; 47 static PetscReal tri_detJ[] = {1.0, 1.414213562373095, 1.0}; 48 /* 49 3---------2---------2 50 | | 51 | | 52 | | 53 3 1 54 | | 55 | | 56 | | 57 0---------0---------1 58 59 v0[Nf][dc]: 4 x 2 60 J[Nf][df][dc]: 4 x 1 x 2 61 invJ[Nf][dc][df]: 4 x 2 x 1 62 detJ[Nf]: 4 63 */ 64 static PetscReal quad_v0[] = {0.0, -1.0, 1.0, 0.0, 0.0, 1.0 -1.0, 0.0}; 65 static PetscReal quad_J[] = {1.0, 0.0, 0.0, 1.0, -1.0, 0.0, 0.0, -1.0}; 66 static PetscReal quad_invJ[] = {1.0, 0.0, 0.0, 1.0, -1.0, 0.0, 0.0, -1.0}; 67 static PetscReal quad_detJ[] = {1.0, 1.0, 1.0, 1.0}; 68 69 PetscFunctionBegin; 70 switch (ct) { 71 case DM_POLYTOPE_TRIANGLE: if (Nf) *Nf = 3; if (v0) *v0 = tri_v0; if (J) *J = tri_J; if (invJ) *invJ = tri_invJ; if (detJ) *detJ = tri_detJ; break; 72 case DM_POLYTOPE_QUADRILATERAL: if (Nf) *Nf = 4; if (v0) *v0 = quad_v0; if (J) *J = quad_J; if (invJ) *invJ = quad_invJ; if (detJ) *detJ = quad_detJ; break; 73 default: 74 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]); 75 } 76 PetscFunctionReturn(0); 77 } 78 79 /* Gets the affine map from the original cell to each subcell */ 80 static PetscErrorCode DMPlexCellRefinerGetAffineTransforms_Regular(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nc, PetscReal *v0[], PetscReal *J[], PetscReal *invJ[]) 81 { 82 /* 83 2 84 |\ 85 | \ 86 | \ 87 | \ 88 | C \ 89 | \ 90 | \ 91 2---1---1 92 |\ D / \ 93 | 2 0 \ 94 |A \ / B \ 95 0---0-------1 96 */ 97 static PetscReal tri_v0[] = {-1.0, -1.0, 0.0, -1.0, -1.0, 0.0, 0.0, -1.0}; 98 static PetscReal tri_J[] = {0.5, 0.0, 99 0.0, 0.5, 100 101 0.5, 0.0, 102 0.0, 0.5, 103 104 0.5, 0.0, 105 0.0, 0.5, 106 107 0.0, -0.5, 108 0.5, 0.5}; 109 static PetscReal tri_invJ[] = {2.0, 0.0, 110 0.0, 2.0, 111 112 2.0, 0.0, 113 0.0, 2.0, 114 115 2.0, 0.0, 116 0.0, 2.0, 117 118 2.0, 2.0, 119 -2.0, 0.0}; 120 /* 121 3---------2---------2 122 | | | 123 | D 2 C | 124 | | | 125 3----3----0----1----1 126 | | | 127 | A 0 B | 128 | | | 129 0---------0---------1 130 */ 131 static PetscReal quad_v0[] = {-1.0, -1.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0}; 132 static PetscReal quad_J[] = {0.5, 0.0, 133 0.0, 0.5, 134 135 0.5, 0.0, 136 0.0, 0.5, 137 138 0.5, 0.0, 139 0.0, 0.5, 140 141 0.5, 0.0, 142 0.0, 0.5}; 143 static PetscReal quad_invJ[] = {2.0, 0.0, 144 0.0, 2.0, 145 146 2.0, 0.0, 147 0.0, 2.0, 148 149 2.0, 0.0, 150 0.0, 2.0, 151 152 2.0, 0.0, 153 0.0, 2.0}; 154 /* 155 Bottom (viewed from top) Top 156 1---------2---------2 7---------2---------6 157 | | | | | | 158 | B 2 C | | H 2 G | 159 | | | | | | 160 3----3----0----1----1 3----3----0----1----1 161 | | | | | | 162 | A 0 D | | E 0 F | 163 | | | | | | 164 0---------0---------3 4---------0---------5 165 */ 166 static PetscReal hex_v0[] = {-1.0, -1.0, -1.0, -1.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, -1.0, -1.0, 167 -1.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0}; 168 static PetscReal hex_J[] = {0.5, 0.0, 0.0, 169 0.0, 0.5, 0.0, 170 0.0, 0.0, 0.5, 171 172 0.5, 0.0, 0.0, 173 0.0, 0.5, 0.0, 174 0.0, 0.0, 0.5, 175 176 0.5, 0.0, 0.0, 177 0.0, 0.5, 0.0, 178 0.0, 0.0, 0.5, 179 180 0.5, 0.0, 0.0, 181 0.0, 0.5, 0.0, 182 0.0, 0.0, 0.5, 183 184 0.5, 0.0, 0.0, 185 0.0, 0.5, 0.0, 186 0.0, 0.0, 0.5, 187 188 0.5, 0.0, 0.0, 189 0.0, 0.5, 0.0, 190 0.0, 0.0, 0.5, 191 192 0.5, 0.0, 0.0, 193 0.0, 0.5, 0.0, 194 0.0, 0.0, 0.5, 195 196 0.5, 0.0, 0.0, 197 0.0, 0.5, 0.0, 198 0.0, 0.0, 0.5}; 199 static PetscReal hex_invJ[] = {2.0, 0.0, 0.0, 200 0.0, 2.0, 0.0, 201 0.0, 0.0, 2.0, 202 203 2.0, 0.0, 0.0, 204 0.0, 2.0, 0.0, 205 0.0, 0.0, 2.0, 206 207 2.0, 0.0, 0.0, 208 0.0, 2.0, 0.0, 209 0.0, 0.0, 2.0, 210 211 2.0, 0.0, 0.0, 212 0.0, 2.0, 0.0, 213 0.0, 0.0, 2.0, 214 215 2.0, 0.0, 0.0, 216 0.0, 2.0, 0.0, 217 0.0, 0.0, 2.0, 218 219 2.0, 0.0, 0.0, 220 0.0, 2.0, 0.0, 221 0.0, 0.0, 2.0, 222 223 2.0, 0.0, 0.0, 224 0.0, 2.0, 0.0, 225 0.0, 0.0, 2.0, 226 227 2.0, 0.0, 0.0, 228 0.0, 2.0, 0.0, 229 0.0, 0.0, 2.0}; 230 231 PetscFunctionBegin; 232 switch (ct) { 233 case DM_POLYTOPE_TRIANGLE: if (Nc) *Nc = 4; if (v0) *v0 = tri_v0; if (J) *J = tri_J; if (invJ) *invJ = tri_invJ; break; 234 case DM_POLYTOPE_QUADRILATERAL: if (Nc) *Nc = 4; if (v0) *v0 = quad_v0; if (J) *J = quad_J; if (invJ) *invJ = quad_invJ; break; 235 case DM_POLYTOPE_HEXAHEDRON: if (Nc) *Nc = 8; if (v0) *v0 = hex_v0; if (J) *J = hex_J; if (invJ) *invJ = hex_invJ; break; 236 default: 237 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]); 238 } 239 PetscFunctionReturn(0); 240 } 241 242 /* Should this be here or in the DualSpace somehow? */ 243 PetscErrorCode CellRefinerInCellTest_Internal(DMPolytopeType ct, const PetscReal point[], PetscBool *inside) 244 { 245 PetscReal sum = 0.0; 246 PetscInt d; 247 248 PetscFunctionBegin; 249 *inside = PETSC_TRUE; 250 switch (ct) { 251 case DM_POLYTOPE_TRIANGLE: 252 case DM_POLYTOPE_TETRAHEDRON: 253 for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d) { 254 if (point[d] < -1.0) {*inside = PETSC_FALSE; break;} 255 sum += point[d]; 256 } 257 if (sum > PETSC_SMALL) {*inside = PETSC_FALSE; break;} 258 break; 259 case DM_POLYTOPE_QUADRILATERAL: 260 case DM_POLYTOPE_HEXAHEDRON: 261 for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d) 262 if (PetscAbsReal(point[d]) > 1.+PETSC_SMALL) {*inside = PETSC_FALSE; break;} 263 break; 264 default: 265 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]); 266 } 267 PetscFunctionReturn(0); 268 } 269 270 /* Regular Refinment of Hybrid Meshes 271 272 We would like to express regular refinement as a small set of rules that can be applied on every point of the Plex 273 to automatically generate a refined Plex. In fact, we would like these rules to be general enough to encompass other 274 transformations, such as changing from one type of cell to another, as simplex to hex. 275 276 To start, we can create a function that takes an original cell type and returns the number of new cells replacing it 277 and the types of the new cells. 278 279 We need the group multiplication table for group actions from the dihedral group for each cell type. 280 281 We need an operator which takes in a cell, and produces a new set of cells with new faces and correct orientations. I think 282 we can just write this operator for faces with identity, and then compose the face orientation actions to get the actual 283 (face, orient) pairs for each subcell. 284 */ 285 286 /* 287 Input Parameters: 288 + ct - The type of the input cell 289 . co - The orientation of this cell in its parent 290 - cp - The requested cone point of this cell assuming orientation 0 291 292 Output Parameters: 293 . cpnew - The new cone point, taking into account the orientation co 294 */ 295 PETSC_STATIC_INLINE PetscErrorCode DMPolytopeMapCell(DMPolytopeType ct, PetscInt co, PetscInt cp, PetscInt *cpnew) 296 { 297 const PetscInt csize = DMPolytopeTypeGetConeSize(ct); 298 299 PetscFunctionBeginHot; 300 if (ct == DM_POLYTOPE_POINT) {*cpnew = cp;} 301 else {*cpnew = (co < 0 ? -(co+1)-cp+csize : co+cp)%csize;} 302 PetscFunctionReturn(0); 303 } 304 305 static PetscErrorCode DMPlexCellRefinerGetCellVertices_Regular(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nv, PetscReal *subcellV[]) 306 { 307 static PetscReal seg_v[] = {-1.0, 0.0, 1.0}; 308 static PetscReal tri_v[] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0}; 309 static PetscReal quad_v[] = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 0.0, -1.0, 1.0, 0.0, 0.0, 1.0, -1.0, 0.0, 0.0, 0.0}; 310 static PetscReal tet_v[] = {-1.0, -1.0, -1.0, 0.0, -1.0, -1.0, 1.0, -1.0, -1.0, 311 -1.0, 0.0, -1.0, 0.0, 0.0, -1.0, -1.0, 1.0, -1.0, 312 -1.0, -1.0, 0.0, 0.0, -1.0, 0.0, -1.0, 0.0, 0.0, -1.0, -1.0, 1.0}; 313 static PetscReal hex_v[] = {-1.0, -1.0, -1.0, 0.0, -1.0, -1.0, 1.0, -1.0, -1.0, 314 -1.0, 0.0, -1.0, 0.0, 0.0, -1.0, 1.0, 0.0, -1.0, 315 -1.0, 1.0, -1.0, 0.0, 1.0, -1.0, 1.0, 1.0, -1.0, 316 -1.0, -1.0, 0.0, 0.0, -1.0, 0.0, 1.0, -1.0, 0.0, 317 -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 318 -1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 319 -1.0, -1.0, 1.0, 0.0, -1.0, 1.0, 1.0, -1.0, 1.0, 320 -1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 321 -1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0}; 322 323 PetscFunctionBegin; 324 switch (ct) { 325 case DM_POLYTOPE_SEGMENT: *Nv = 3; *subcellV = seg_v; break; 326 case DM_POLYTOPE_TRIANGLE: *Nv = 6; *subcellV = tri_v; break; 327 case DM_POLYTOPE_QUADRILATERAL: *Nv = 9; *subcellV = quad_v; break; 328 case DM_POLYTOPE_TETRAHEDRON: *Nv = 10; *subcellV = tet_v; break; 329 case DM_POLYTOPE_HEXAHEDRON: *Nv = 27; *subcellV = hex_v; break; 330 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No subcell vertices for cell type %s", DMPolytopeTypes[ct]); 331 } 332 PetscFunctionReturn(0); 333 } 334 335 static PetscErrorCode DMPlexCellRefinerGetCellVertices_ToBox(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nv, PetscReal *subcellV[]) 336 { 337 static PetscReal tri_v[] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, -1.0/3.0, -1.0/3.0}; 338 static PetscReal tet_v[] = {-1.0, -1.0, -1.0, 0.0, -1.0, -1.0, 1.0, -1.0, -1.0, 339 -1.0, 0.0, -1.0, -1.0/3.0, -1.0/3.0, -1.0, 0.0, 0.0, -1.0, -1.0, 1.0, -1.0, 340 -1.0, -1.0, 0.0, -1.0/3.0, -1.0, -1.0/3.0, 0.0, -1.0, 0.0, 341 -1.0, -1.0/3.0, -1.0/3.0, -1.0/3.0, -1.0/3.0, -1.0/3.0, -1.0, 0.0, 0.0, 342 -1.0, -1.0, 1.0, -0.5, -0.5, -0.5}; 343 PetscErrorCode ierr; 344 345 PetscFunctionBegin; 346 switch (ct) { 347 case DM_POLYTOPE_SEGMENT: 348 case DM_POLYTOPE_QUADRILATERAL: 349 case DM_POLYTOPE_HEXAHEDRON: 350 ierr = DMPlexCellRefinerGetCellVertices_Regular(cr, ct, Nv, subcellV);CHKERRQ(ierr);break; 351 case DM_POLYTOPE_TRIANGLE: *Nv = 7; *subcellV = tri_v; break; 352 case DM_POLYTOPE_TETRAHEDRON: *Nv = 15; *subcellV = tet_v; break; 353 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No subcell vertices for cell type %s", DMPolytopeTypes[ct]); 354 } 355 PetscFunctionReturn(0); 356 } 357 358 /* 359 DMPlexCellRefinerGetCellVertices - Get the set of refined vertices lying in the closure of a reference cell of given type 360 361 Input Parameters: 362 + cr - The DMPlexCellRefiner object 363 - ct - The cell type 364 365 Output Parameters: 366 + Nv - The number of refined vertices in the closure of the reference cell of given type 367 - subcellV - The coordinates of these vertices in the reference cell 368 369 Level: developer 370 371 .seealso: DMPlexCellRefinerGetSubcellVertices() 372 */ 373 static PetscErrorCode DMPlexCellRefinerGetCellVertices(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nv, PetscReal *subcellV[]) 374 { 375 PetscErrorCode ierr; 376 377 PetscFunctionBegin; 378 if (!cr->ops->getcellvertices) SETERRQ1(PetscObjectComm((PetscObject)cr),PETSC_ERR_SUP,"Not for refiner type %s",DMPlexCellRefinerTypes[cr->type]); 379 ierr = (*cr->ops->getcellvertices)(cr, ct, Nv, subcellV);CHKERRQ(ierr); 380 PetscFunctionReturn(0); 381 } 382 383 static PetscErrorCode DMPlexCellRefinerGetSubcellVertices_Regular(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType rct, PetscInt r, PetscInt *Nv, PetscInt *subcellV[]) 384 { 385 static PetscInt seg_v[] = {0, 1, 1, 2}; 386 static PetscInt tri_v[] = {0, 3, 5, 3, 1, 4, 5, 4, 2, 3, 4, 5}; 387 static PetscInt quad_v[] = {0, 4, 8, 7, 4, 1, 5, 8, 8, 5, 2, 6, 7, 8, 6, 3}; 388 static PetscInt tet_v[] = {0, 3, 1, 6, 3, 2, 4, 8, 1, 4, 5, 7, 6, 8, 7, 9, 389 1, 6, 3, 7, 8, 4, 3, 7, 7, 3, 1, 4, 7, 3, 8, 6}; 390 static PetscInt hex_v[] = {0, 3, 4, 1, 9, 10, 13, 12, 3, 6, 7, 4, 12, 13, 16, 15, 4, 7, 8, 5, 13, 14, 17, 16, 1, 4 , 5 , 2, 10, 11, 14, 13, 391 9, 12, 13, 10, 18, 19, 22, 21, 10, 13, 14, 11, 19, 20, 23, 22, 13, 16, 17, 14, 22, 23, 26, 25, 12, 15, 16, 13, 21, 22, 25, 24}; 392 393 PetscFunctionBegin; 394 if (ct != rct) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Cell type %s does not produce %s", DMPolytopeTypes[ct], DMPolytopeTypes[rct]); 395 switch (ct) { 396 case DM_POLYTOPE_SEGMENT: *Nv = 2; *subcellV = &seg_v[r*(*Nv)]; break; 397 case DM_POLYTOPE_TRIANGLE: *Nv = 3; *subcellV = &tri_v[r*(*Nv)]; break; 398 case DM_POLYTOPE_QUADRILATERAL: *Nv = 4; *subcellV = &quad_v[r*(*Nv)]; break; 399 case DM_POLYTOPE_TETRAHEDRON: *Nv = 4; *subcellV = &tet_v[r*(*Nv)]; break; 400 case DM_POLYTOPE_HEXAHEDRON: *Nv = 8; *subcellV = &hex_v[r*(*Nv)]; break; 401 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No subcell vertices for cell type %s", DMPolytopeTypes[ct]); 402 } 403 PetscFunctionReturn(0); 404 } 405 406 static PetscErrorCode DMPlexCellRefinerGetSubcellVertices_ToBox(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType rct, PetscInt r, PetscInt *Nv, PetscInt *subcellV[]) 407 { 408 static PetscInt tri_v[] = {0, 3, 6, 5, 3, 1, 4, 6, 5, 6, 4, 2}; 409 static PetscInt tet_v[] = {0, 3, 4, 1, 7, 8, 14, 10, 6, 12, 11, 5, 3, 4, 14, 10, 2, 5, 11, 9, 1, 8, 14, 4, 13, 12 , 10, 7, 9, 8, 14, 11}; 410 PetscErrorCode ierr; 411 412 PetscFunctionBegin; 413 switch (ct) { 414 case DM_POLYTOPE_SEGMENT: 415 case DM_POLYTOPE_QUADRILATERAL: 416 case DM_POLYTOPE_HEXAHEDRON: 417 ierr = DMPlexCellRefinerGetSubcellVertices_Regular(cr, ct, rct, r, Nv, subcellV);CHKERRQ(ierr);break; 418 case DM_POLYTOPE_TRIANGLE: 419 if (rct != DM_POLYTOPE_QUADRILATERAL) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Cell type %s does not produce %s", DMPolytopeTypes[ct], DMPolytopeTypes[rct]); 420 *Nv = 4; *subcellV = &tri_v[r*(*Nv)]; break; 421 case DM_POLYTOPE_TETRAHEDRON: 422 if (rct != DM_POLYTOPE_HEXAHEDRON) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Cell type %s does not produce %s", DMPolytopeTypes[ct], DMPolytopeTypes[rct]); 423 *Nv = 8; *subcellV = &tet_v[r*(*Nv)]; break; 424 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No subcell vertices for cell type %s", DMPolytopeTypes[ct]); 425 } 426 PetscFunctionReturn(0); 427 } 428 429 /* 430 DMPlexCellRefinerGetSubcellVertices - Get the set of refined vertices defining a subcell in the reference cell of given type 431 432 Input Parameters: 433 + cr - The DMPlexCellRefiner object 434 . ct - The cell type 435 . rct - The type of subcell 436 - r - The subcell index 437 438 Output Parameters: 439 + Nv - The number of refined vertices in the subcell 440 - subcellV - The indices of these vertices in the set of vertices returned by DMPlexCellRefinerGetCellVertices() 441 442 Level: developer 443 444 .seealso: DMPlexCellRefinerGetCellVertices() 445 */ 446 static PetscErrorCode DMPlexCellRefinerGetSubcellVertices(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType rct, PetscInt r, PetscInt *Nv, PetscInt *subcellV[]) 447 { 448 PetscErrorCode ierr; 449 450 PetscFunctionBegin; 451 if (!cr->ops->getsubcellvertices) SETERRQ1(PetscObjectComm((PetscObject)cr),PETSC_ERR_SUP,"Not for refiner type %s",DMPlexCellRefinerTypes[cr->type]); 452 ierr = (*cr->ops->getsubcellvertices)(cr, ct, rct, r, Nv, subcellV);CHKERRQ(ierr); 453 PetscFunctionReturn(0); 454 } 455 456 /* 457 Input Parameters: 458 + cr - The DMPlexCellRefiner 459 . pct - The cell type of the parent, from whom the new cell is being produced 460 . ct - The type being produced 461 . r - The replica number requested for the produced cell type 462 . Nv - Number of vertices in the closure of the parent cell 463 . dE - Spatial dimension 464 - in - array of size Nv*dE, holding coordinates of the vertices in the closure of the parent cell 465 466 Output Parameters: 467 . out - The coordinates of the new vertices 468 */ 469 static PetscErrorCode DMPlexCellRefinerMapCoordinates(DMPlexCellRefiner cr, DMPolytopeType pct, DMPolytopeType ct, PetscInt r, PetscInt Nv, PetscInt dE, const PetscScalar in[], PetscScalar out[]) 470 { 471 PetscErrorCode ierr; 472 473 PetscFunctionBeginHot; 474 if (!cr->ops->mapcoords) SETERRQ1(PetscObjectComm((PetscObject)cr),PETSC_ERR_SUP,"Not for refiner type %s",DMPlexCellRefinerTypes[cr->type]); 475 ierr = (*cr->ops->mapcoords)(cr, pct, ct, r, Nv, dE, in, out);CHKERRQ(ierr); 476 PetscFunctionReturn(0); 477 } 478 479 /* Computes new vertex as the barycenter */ 480 static PetscErrorCode DMPlexCellRefinerMapCoordinates_Barycenter(DMPlexCellRefiner cr, DMPolytopeType pct, DMPolytopeType ct, PetscInt r, PetscInt Nv, PetscInt dE, const PetscScalar in[], PetscScalar out[]) 481 { 482 PetscInt v,d; 483 484 PetscFunctionBeginHot; 485 if (ct != DM_POLYTOPE_POINT) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for refined point type %s",DMPolytopeTypes[ct]); 486 for (d = 0; d < dE; ++d) out[d] = 0.0; 487 for (v = 0; v < Nv; ++v) for (d = 0; d < dE; ++d) out[d] += in[v*dE+d]; 488 for (d = 0; d < dE; ++d) out[d] /= Nv; 489 PetscFunctionReturn(0); 490 } 491 492 /* 493 Input Parameters: 494 + cr - The DMPlexCellRefiner 495 . pct - The cell type of the parent, from whom the new cell is being produced 496 . pp - The parent cell 497 . po - The orientation of the parent cell in its enclosing parent 498 . ct - The type being produced 499 . r - The replica number requested for the produced cell type 500 - o - The relative orientation of the replica 501 502 Output Parameters: 503 + rnew - The replica number, given the orientation of the parent 504 - onew - The replica orientation, given the orientation of the parent 505 */ 506 static PetscErrorCode DMPlexCellRefinerMapSubcells(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt pp, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew) 507 { 508 PetscErrorCode ierr; 509 510 PetscFunctionBeginHot; 511 if (!cr->ops->mapsubcells) SETERRQ1(PetscObjectComm((PetscObject)cr),PETSC_ERR_SUP,"Not for refiner type %s",DMPlexCellRefinerTypes[cr->type]); 512 ierr = (*cr->ops->mapsubcells)(cr, pct, pp, po, ct, r, o, rnew, onew);CHKERRQ(ierr); 513 PetscFunctionReturn(0); 514 } 515 516 /* 517 This is the group multiplication table for the dihedral group of the cell. 518 */ 519 static PetscErrorCode ComposeOrientation_Private(PetscInt n, PetscInt o1, PetscInt o2, PetscInt *o) 520 { 521 PetscFunctionBeginHot; 522 if (!n) {*o = 0;} 523 else if (o1 >= 0 && o2 >= 0) {*o = ( o1 + o2) % n;} 524 else if (o1 < 0 && o2 < 0) {*o = (-o1 - o2) % n;} 525 else if (o1 < 0) {*o = -((-(o1+1) + o2) % n + 1);} 526 else if (o2 < 0) {*o = -((-(o2+1) + o1) % n + 1);} 527 PetscFunctionReturn(0); 528 } 529 530 static PetscErrorCode DMPlexCellRefinerMapSubcells_None(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt pp, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew) 531 { 532 PetscErrorCode ierr; 533 534 PetscFunctionBeginHot; 535 *rnew = r; 536 ierr = ComposeOrientation_Private(DMPolytopeTypeGetConeSize(ct), po, o, onew);CHKERRQ(ierr); 537 PetscFunctionReturn(0); 538 } 539 540 static PetscErrorCode DMPlexCellRefinerMapSubcells_Regular(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt pp, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew) 541 { 542 /* We shift any input orientation in order to make it non-negative 543 The orientation array o[po][o] gives the orientation the new replica rnew has to have in order to reproduce the face sequence from (r, o) 544 The replica array r[po][r] gives the new replica number rnew given that the parent point has orientation po 545 Overall, replica (r, o) in a parent with orientation 0 matches replica (rnew, onew) in a parent with orientation po 546 */ 547 PetscInt tri_seg_o[] = {-2, 0, 548 -2, 0, 549 -2, 0, 550 0, -2, 551 0, -2, 552 0, -2}; 553 PetscInt tri_seg_r[] = {1, 0, 2, 554 0, 2, 1, 555 2, 1, 0, 556 0, 1, 2, 557 1, 2, 0, 558 2, 0, 1}; 559 PetscInt tri_tri_o[] = {0, 1, 2, -3, -2, -1, 560 2, 0, 1, -2, -1, -3, 561 1, 2, 0, -1, -3, -2, 562 -3, -2, -1, 0, 1, 2, 563 -1, -3, -2, 1, 2, 0, 564 -2, -1, -3, 2, 0, 1}; 565 /* orientation if the replica is the center triangle */ 566 PetscInt tri_tri_o_c[] = {2, 0, 1, -2, -1, -3, 567 1, 2, 0, -1, -3, -2, 568 0, 1, 2, -3, -2, -1, 569 -3, -2, -1, 0, 1, 2, 570 -1, -3, -2, 1, 2, 0, 571 -2, -1, -3, 2, 0, 1}; 572 PetscInt tri_tri_r[] = {0, 2, 1, 3, 573 2, 1, 0, 3, 574 1, 0, 2, 3, 575 0, 1, 2, 3, 576 1, 2, 0, 3, 577 2, 0, 1, 3}; 578 PetscInt quad_seg_r[] = {3, 2, 1, 0, 579 2, 1, 0, 3, 580 1, 0, 3, 2, 581 0, 3, 2, 1, 582 0, 1, 2, 3, 583 1, 2, 3, 0, 584 2, 3, 0, 1, 585 3, 0, 1, 2}; 586 PetscInt quad_quad_o[] = { 0, 1, 2, 3, -4, -3, -2, -1, 587 4, 0, 1, 2, -3, -2, -1, -4, 588 3, 4, 0, 1, -2, -1, -4, -3, 589 2, 3, 4, 0, -1, -4, -3, -2, 590 -4, -3, -2, -1, 0, 1, 2, 3, 591 -1, -4, -3, -2, 1, 2, 3, 0, 592 -2, -1, -4, -3, 2, 3, 0, 1, 593 -3, -2, -1, -4, 3, 0, 1, 2}; 594 PetscInt quad_quad_r[] = {0, 3, 2, 1, 595 3, 2, 1, 0, 596 2, 1, 0, 3, 597 1, 0, 3, 2, 598 0, 1, 2, 3, 599 1, 2, 3, 0, 600 2, 3, 0, 1, 601 3, 0, 1, 2}; 602 PetscInt tquad_tquad_o[] = { 0, 1, -2, -1, 603 1, 0, -1, -2, 604 -2, -1, 0, 1, 605 -1, -2, 1, 0}; 606 PetscInt tquad_tquad_r[] = {1, 0, 607 1, 0, 608 0, 1, 609 0, 1}; 610 611 PetscFunctionBeginHot; 612 /* The default is no transformation */ 613 *rnew = r; 614 *onew = o; 615 switch (pct) { 616 case DM_POLYTOPE_SEGMENT: 617 if (ct == DM_POLYTOPE_SEGMENT) { 618 if (po == 0 || po == -1) {*rnew = r; *onew = o;} 619 else if (po == 1 || po == -2) {*rnew = (r+1)%2; *onew = (o == 0 || o == -1) ? -2 : 0;} 620 else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid orientation %D for segment", po); 621 } 622 break; 623 case DM_POLYTOPE_TRIANGLE: 624 switch (ct) { 625 case DM_POLYTOPE_SEGMENT: 626 if (o == -1) o = 0; 627 if (o == -2) o = 1; 628 *onew = tri_seg_o[(po+3)*2+o]; 629 *rnew = tri_seg_r[(po+3)*3+r]; 630 break; 631 case DM_POLYTOPE_TRIANGLE: 632 *onew = r == 3 && po < 0 ? tri_tri_o_c[((po+3)%3)*6+o+3] : tri_tri_o[(po+3)*6+o+3]; 633 *rnew = tri_tri_r[(po+3)*4+r]; 634 break; 635 default: break; 636 } 637 break; 638 case DM_POLYTOPE_QUADRILATERAL: 639 switch (ct) { 640 case DM_POLYTOPE_SEGMENT: 641 *onew = o; 642 *rnew = quad_seg_r[(po+4)*4+r]; 643 break; 644 case DM_POLYTOPE_QUADRILATERAL: 645 *onew = quad_quad_o[(po+4)*8+o+4]; 646 *rnew = quad_quad_r[(po+4)*4+r]; 647 break; 648 default: break; 649 } 650 break; 651 case DM_POLYTOPE_SEG_PRISM_TENSOR: 652 switch (ct) { 653 /* DM_POLYTOPE_POINT_PRISM_TENSOR does not change */ 654 case DM_POLYTOPE_SEG_PRISM_TENSOR: 655 *onew = tquad_tquad_o[(po+2)*4+o+2]; 656 *rnew = tquad_tquad_r[(po+2)*2+r]; 657 break; 658 default: break; 659 } 660 break; 661 default: break; 662 } 663 PetscFunctionReturn(0); 664 } 665 666 static PetscErrorCode DMPlexCellRefinerMapSubcells_ToBox(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt pp, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew) 667 { 668 PetscErrorCode ierr; 669 /* We shift any input orientation in order to make it non-negative 670 The orientation array o[po][o] gives the orientation the new replica rnew has to have in order to reproduce the face sequence from (r, o) 671 The replica array r[po][r] gives the new replica number rnew given that the parent point has orientation po 672 Overall, replica (r, o) in a parent with orientation 0 matches replica (rnew, onew) in a parent with orientation po 673 */ 674 PetscInt tri_seg_o[] = {0, -2, 675 0, -2, 676 0, -2, 677 0, -2, 678 0, -2, 679 0, -2}; 680 PetscInt tri_seg_r[] = {2, 1, 0, 681 1, 0, 2, 682 0, 2, 1, 683 0, 1, 2, 684 1, 2, 0, 685 2, 0, 1}; 686 PetscInt tri_tri_o[] = {0, 1, 2, 3, -4, -3, -2, -1, 687 3, 0, 1, 2, -3, -2, -1, -4, 688 1, 2, 3, 0, -1, -4, -3, -2, 689 -4, -3, -2, -1, 0, 1, 2, 3, 690 -1, -4, -3, -2, 1, 2, 3, 0, 691 -3, -2, -1, -4, 3, 0, 1, 2}; 692 PetscInt tri_tri_r[] = {0, 2, 1, 693 2, 1, 0, 694 1, 0, 2, 695 0, 1, 2, 696 1, 2, 0, 697 2, 0, 1}; 698 PetscInt tquad_tquad_o[] = { 0, 1, -2, -1, 699 1, 0, -1, -2, 700 -2, -1, 0, 1, 701 -1, -2, 1, 0}; 702 PetscInt tquad_tquad_r[] = {1, 0, 703 1, 0, 704 0, 1, 705 0, 1}; 706 PetscInt tquad_quad_o[] = {-2, -1, -4, -3, 2, 3, 0, 1, 707 1, 2, 3, 0, -1, -4, -3, -2, 708 -4, -3, -2, -1, 0, 1, 2, 3, 709 1, 0, 3, 2, -3, -4, -1, -2}; 710 711 PetscFunctionBeginHot; 712 *rnew = r; 713 *onew = o; 714 switch (pct) { 715 case DM_POLYTOPE_TRIANGLE: 716 switch (ct) { 717 case DM_POLYTOPE_SEGMENT: 718 if (o == -1) o = 0; 719 if (o == -2) o = 1; 720 *onew = tri_seg_o[(po+3)*2+o]; 721 *rnew = tri_seg_r[(po+3)*3+r]; 722 break; 723 case DM_POLYTOPE_QUADRILATERAL: 724 *onew = tri_tri_o[(po+3)*8+o+4]; 725 /* TODO See sheet, for fixing po == 1 and 2 */ 726 if (po == 2 && r == 2 && o >= 0) *onew = tri_tri_o[(po+3)*8+((o+3)%4)+4]; 727 if (po == 2 && r == 2 && o < 0) *onew = tri_tri_o[(po+3)*8+((o+5)%4)]; 728 if (po == 1 && r == 1 && o >= 0) *onew = tri_tri_o[(po+3)*8+((o+1)%4)+4]; 729 if (po == 1 && r == 1 && o < 0) *onew = tri_tri_o[(po+3)*8+((o+7)%4)]; 730 if (po == -1 && r == 2 && o >= 0) *onew = tri_tri_o[(po+3)*8+((o+3)%4)+4]; 731 if (po == -1 && r == 2 && o < 0) *onew = tri_tri_o[(po+3)*8+((o+5)%4)]; 732 if (po == -2 && r == 1 && o >= 0) *onew = tri_tri_o[(po+3)*8+((o+1)%4)+4]; 733 if (po == -2 && r == 1 && o < 0) *onew = tri_tri_o[(po+3)*8+((o+7)%4)]; 734 *rnew = tri_tri_r[(po+3)*3+r]; 735 break; 736 default: break; 737 } 738 break; 739 case DM_POLYTOPE_SEG_PRISM_TENSOR: 740 switch (ct) { 741 /* DM_POLYTOPE_POINT_PRISM_TENSOR does not change */ 742 case DM_POLYTOPE_SEG_PRISM_TENSOR: 743 *onew = tquad_tquad_o[(po+2)*4+o+2]; 744 *rnew = tquad_tquad_r[(po+2)*2+r]; 745 break; 746 case DM_POLYTOPE_QUADRILATERAL: 747 *onew = tquad_quad_o[(po+2)*8+o+4]; 748 *rnew = tquad_tquad_r[(po+2)*2+r]; 749 break; 750 default: break; 751 } 752 break; 753 default: 754 ierr = DMPlexCellRefinerMapSubcells_Regular(cr, pct, pp, po, ct, r, o, rnew, onew);CHKERRQ(ierr); 755 } 756 PetscFunctionReturn(0); 757 } 758 759 static PetscErrorCode DMPlexCellRefinerMapSubcells_ToSimplex(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt pp, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew) 760 { 761 return DMPlexCellRefinerMapSubcells_Regular(cr, pct, pp, po, ct, r, o, rnew, onew); 762 } 763 764 /*@ 765 DMPlexCellRefinerRefine - Return a description of the refinement for a given cell type 766 767 Input Parameters: 768 + source - The cell type for a source point 769 - p - The source point, or PETSC_DETERMINE if the refine is homogeneous 770 771 Output Parameters: 772 + rt - The refine type for this cell 773 . Nt - The number of cell types generated by refinement 774 . target - The cell types generated 775 . size - The number of subcells of each type, ordered by dimension 776 . cone - A list of the faces for each subcell of the same type as source 777 - ornt - A list of the face orientations for each subcell of the same type as source 778 779 Note: The cone array gives the cone of each subcell listed by the first three outputs. For each cone point, we 780 need the cell type, point identifier, and orientation within the subcell. The orientation is with respect to the canonical 781 division (described in these outputs) of the cell in the original mesh. The point identifier is given by 782 $ the number of cones to be taken, or 0 for the current cell 783 $ the cell cone point number at each level from which it is subdivided 784 $ the replica number r of the subdivision. 785 The orientation is with respect to the canonical cone orientation. For example, the prescription for edge division is 786 $ Nt = 2 787 $ target = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT} 788 $ size = {1, 2} 789 $ cone = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0, DM_POLYTOPE_POINT, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0} 790 $ ornt = { 0, 0, 0, 0} 791 792 Level: developer 793 794 .seealso: DMPlexCellRefinerCreate(), DMPlexRefineUniform() 795 @*/ 796 PetscErrorCode DMPlexCellRefinerRefine(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[]) 797 { 798 PetscErrorCode ierr; 799 800 PetscFunctionBeginHot; 801 if (!cr->ops->refine) SETERRQ1(PetscObjectComm((PetscObject)cr),PETSC_ERR_SUP,"Not for refiner type %s",DMPlexCellRefinerTypes[cr->type]); 802 ierr = (*cr->ops->refine)(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr); 803 PetscFunctionReturn(0); 804 } 805 806 static PetscErrorCode DMPlexCellRefinerRefine_None(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[]) 807 { 808 static DMPolytopeType vertexT[] = {DM_POLYTOPE_POINT}; 809 static PetscInt vertexS[] = {1}; 810 static PetscInt vertexC[] = {0}; 811 static PetscInt vertexO[] = {0}; 812 static DMPolytopeType edgeT[] = {DM_POLYTOPE_SEGMENT}; 813 static PetscInt edgeS[] = {1}; 814 static PetscInt edgeC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0}; 815 static PetscInt edgeO[] = {0, 0}; 816 static DMPolytopeType tedgeT[] = {DM_POLYTOPE_POINT_PRISM_TENSOR}; 817 static PetscInt tedgeS[] = {1}; 818 static PetscInt tedgeC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0}; 819 static PetscInt tedgeO[] = {0, 0}; 820 static DMPolytopeType triT[] = {DM_POLYTOPE_TRIANGLE}; 821 static PetscInt triS[] = {1}; 822 static PetscInt triC[] = {DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0}; 823 static PetscInt triO[] = {0, 0, 0}; 824 static DMPolytopeType quadT[] = {DM_POLYTOPE_QUADRILATERAL}; 825 static PetscInt quadS[] = {1}; 826 static PetscInt quadC[] = {DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 1, 3, 0}; 827 static PetscInt quadO[] = {0, 0, 0, 0}; 828 static DMPolytopeType tquadT[] = {DM_POLYTOPE_SEG_PRISM_TENSOR}; 829 static PetscInt tquadS[] = {1}; 830 static PetscInt tquadC[] = {DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 3, 0}; 831 static PetscInt tquadO[] = {0, 0, 0, 0}; 832 static DMPolytopeType tetT[] = {DM_POLYTOPE_TETRAHEDRON}; 833 static PetscInt tetS[] = {1}; 834 static PetscInt tetC[] = {DM_POLYTOPE_TRIANGLE, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0, DM_POLYTOPE_TRIANGLE, 1, 2, 0, DM_POLYTOPE_TRIANGLE, 1, 3, 0}; 835 static PetscInt tetO[] = {0, 0, 0, 0}; 836 static DMPolytopeType hexT[] = {DM_POLYTOPE_HEXAHEDRON}; 837 static PetscInt hexS[] = {1}; 838 static PetscInt hexC[] = {DM_POLYTOPE_QUADRILATERAL, 1, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 1, 0, DM_POLYTOPE_QUADRILATERAL, 1, 2, 0, 839 DM_POLYTOPE_QUADRILATERAL, 1, 3, 0, DM_POLYTOPE_QUADRILATERAL, 1, 4, 0, DM_POLYTOPE_QUADRILATERAL, 1, 5, 0}; 840 static PetscInt hexO[] = {0, 0, 0, 0, 0, 0}; 841 static DMPolytopeType tripT[] = {DM_POLYTOPE_TRI_PRISM}; 842 static PetscInt tripS[] = {1}; 843 static PetscInt tripC[] = {DM_POLYTOPE_TRIANGLE, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0, 844 DM_POLYTOPE_QUADRILATERAL, 1, 2, 0, DM_POLYTOPE_QUADRILATERAL, 1, 3, 0, DM_POLYTOPE_QUADRILATERAL, 1, 4, 0}; 845 static PetscInt tripO[] = {0, 0, 0, 0, 0}; 846 static DMPolytopeType ttripT[] = {DM_POLYTOPE_TRI_PRISM_TENSOR}; 847 static PetscInt ttripS[] = {1}; 848 static PetscInt ttripC[] = {DM_POLYTOPE_TRIANGLE, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0, 849 DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 3, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 4, 0}; 850 static PetscInt ttripO[] = {0, 0, 0, 0, 0}; 851 static DMPolytopeType tquadpT[] = {DM_POLYTOPE_QUAD_PRISM_TENSOR}; 852 static PetscInt tquadpS[] = {1}; 853 static PetscInt tquadpC[] = {DM_POLYTOPE_QUADRILATERAL, 1, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 1, 0, 854 DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 3, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 4, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 5, 0}; 855 static PetscInt tquadpO[] = {0, 0, 0, 0, 0, 0}; 856 static DMPolytopeType pyrT[] = {DM_POLYTOPE_PYRAMID}; 857 static PetscInt pyrS[] = {1}; 858 static PetscInt pyrC[] = {DM_POLYTOPE_QUADRILATERAL, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0, 859 DM_POLYTOPE_TRIANGLE, 1, 2, 0, DM_POLYTOPE_TRIANGLE, 1, 3, 0, DM_POLYTOPE_TRIANGLE, 1, 4, 0}; 860 static PetscInt pyrO[] = {0, 0, 0, 0, 0}; 861 862 PetscFunctionBegin; 863 if (rt) *rt = 0; 864 switch (source) { 865 case DM_POLYTOPE_POINT: *Nt = 1; *target = vertexT; *size = vertexS; *cone = vertexC; *ornt = vertexO; break; 866 case DM_POLYTOPE_SEGMENT: *Nt = 1; *target = edgeT; *size = edgeS; *cone = edgeC; *ornt = edgeO; break; 867 case DM_POLYTOPE_POINT_PRISM_TENSOR: *Nt = 1; *target = tedgeT; *size = tedgeS; *cone = tedgeC; *ornt = tedgeO; break; 868 case DM_POLYTOPE_TRIANGLE: *Nt = 1; *target = triT; *size = triS; *cone = triC; *ornt = triO; break; 869 case DM_POLYTOPE_QUADRILATERAL: *Nt = 1; *target = quadT; *size = quadS; *cone = quadC; *ornt = quadO; break; 870 case DM_POLYTOPE_SEG_PRISM_TENSOR: *Nt = 1; *target = tquadT; *size = tquadS; *cone = tquadC; *ornt = tquadO; break; 871 case DM_POLYTOPE_TETRAHEDRON: *Nt = 1; *target = tetT; *size = tetS; *cone = tetC; *ornt = tetO; break; 872 case DM_POLYTOPE_HEXAHEDRON: *Nt = 1; *target = hexT; *size = hexS; *cone = hexC; *ornt = hexO; break; 873 case DM_POLYTOPE_TRI_PRISM: *Nt = 1; *target = tripT; *size = tripS; *cone = tripC; *ornt = tripO; break; 874 case DM_POLYTOPE_TRI_PRISM_TENSOR: *Nt = 1; *target = ttripT; *size = ttripS; *cone = ttripC; *ornt = ttripO; break; 875 case DM_POLYTOPE_QUAD_PRISM_TENSOR: *Nt = 1; *target = tquadpT; *size = tquadpS; *cone = tquadpC; *ornt = tquadpO; break; 876 case DM_POLYTOPE_PYRAMID: *Nt = 1; *target = pyrT; *size = pyrS; *cone = pyrC; *ornt = pyrO; break; 877 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]); 878 } 879 PetscFunctionReturn(0); 880 } 881 882 static PetscErrorCode DMPlexCellRefinerRefine_Regular(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[]) 883 { 884 /* All vertices remain in the refined mesh */ 885 static DMPolytopeType vertexT[] = {DM_POLYTOPE_POINT}; 886 static PetscInt vertexS[] = {1}; 887 static PetscInt vertexC[] = {0}; 888 static PetscInt vertexO[] = {0}; 889 /* Split all edges with a new vertex, making two new 2 edges 890 0--0--0--1--1 891 */ 892 static DMPolytopeType edgeT[] = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT}; 893 static PetscInt edgeS[] = {1, 2}; 894 static PetscInt edgeC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0, DM_POLYTOPE_POINT, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0}; 895 static PetscInt edgeO[] = { 0, 0, 0, 0}; 896 /* Do not split tensor edges */ 897 static DMPolytopeType tedgeT[] = {DM_POLYTOPE_POINT_PRISM_TENSOR}; 898 static PetscInt tedgeS[] = {1}; 899 static PetscInt tedgeC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0}; 900 static PetscInt tedgeO[] = { 0, 0}; 901 /* Add 3 edges inside every triangle, making 4 new triangles. 902 2 903 |\ 904 | \ 905 | \ 906 0 1 907 | C \ 908 | \ 909 | \ 910 2---1---1 911 |\ D / \ 912 1 2 0 0 913 |A \ / B \ 914 0-0-0---1---1 915 */ 916 static DMPolytopeType triT[] = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE}; 917 static PetscInt triS[] = {3, 4}; 918 static PetscInt triC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0, 919 DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 1, 2, 0, 920 DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 1, 0, 0, 921 DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 1, 2, 1, 922 DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0, 0, 923 DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0, 924 DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 0, 2}; 925 static PetscInt triO[] = {0, 0, 926 0, 0, 927 0, 0, 928 0, -2, 0, 929 0, 0, -2, 930 -2, 0, 0, 931 0, 0, 0}; 932 /* Add a vertex in the center of each quadrilateral, and 4 edges inside, making 4 new quads. 933 3----1----2----0----2 934 | | | 935 0 D 2 C 1 936 | | | 937 3----3----0----1----1 938 | | | 939 1 A 0 B 0 940 | | | 941 0----0----0----1----1 942 */ 943 static DMPolytopeType quadT[] = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL}; 944 static PetscInt quadS[] = {1, 4, 4}; 945 static PetscInt quadC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0, 946 DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0, 0, 947 DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0, 0, 948 DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 0, 0, 949 DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 3, DM_POLYTOPE_SEGMENT, 1, 3, 1, 950 DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 0, 0, 951 DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0, 2, 952 DM_POLYTOPE_SEGMENT, 0, 3, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 3, 0}; 953 static PetscInt quadO[] = {0, 0, 954 0, 0, 955 0, 0, 956 0, 0, 957 0, 0, -2, 0, 958 0, 0, 0, -2, 959 -2, 0, 0, 0, 960 0, -2, 0, 0}; 961 /* Add 1 edge inside every tensor quad, making 2 new tensor quads 962 2----2----1----3----3 963 | | | 964 | | | 965 | | | 966 4 A 6 B 5 967 | | | 968 | | | 969 | | | 970 0----0----0----1----1 971 */ 972 static DMPolytopeType tquadT[] = {DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR}; 973 static PetscInt tquadS[] = {1, 2}; 974 static PetscInt tquadC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0, 975 DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 0, 0, 976 DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_POINT_PRISM_TENSOR, 0, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 3, 0}; 977 static PetscInt tquadO[] = {0, 0, 978 0, 0, 0, 0, 979 0, 0, 0, 0}; 980 /* Add 1 edge and 8 triangles inside every cell, making 8 new tets 981 The vertices of our reference tet are [(-1, -1, -1), (-1, 1, -1), (1, -1, -1), (-1, -1, 1)], which we call [v0, v1, v2, v3]. The first 982 three edges are [v0, v1], [v1, v2], [v2, v0] called e0, e1, and e2, and then three edges to the top point [v0, v3], [v1, v3], [v2, v3] 983 called e3, e4, and e5. The faces of a tet, given in DMPlexGetRawFaces_Internal() are 984 [v0, v1, v2], [v0, v3, v1], [v0, v2, v3], [v2, v1, v3] 985 The first four tets just cut off the corners, using the replica notation for new vertices, 986 [v0, (e0, 0), (e2, 0), (e3, 0)] 987 [(e0, 0), v1, (e1, 0), (e4, 0)] 988 [(e2, 0), (e1, 0), v2, (e5, 0)] 989 [(e3, 0), (e4, 0), (e5, 0), v3 ] 990 The next four tets match a vertex to the newly created faces from cutting off those first tets. 991 [(e2, 0), (e3, 0), (e0, 0), (e5, 0)] 992 [(e4, 0), (e1, 0), (e0, 0), (e5, 0)] 993 [(e5, 0), (e0, 0), (e2, 0), (e1, 0)] 994 [(e5, 0), (e0, 0), (e4, 0), (e3, 0)] 995 We can see that a new edge is introduced in the cell [(e0, 0), (e5, 0)] which we call (-1, 0). The first four faces created are 996 [(e2, 0), (e0, 0), (e3, 0)] 997 [(e0, 0), (e1, 0), (e4, 0)] 998 [(e2, 0), (e5, 0), (e1, 0)] 999 [(e3, 0), (e4, 0), (e5, 0)] 1000 The next four, from the second group of tets, are 1001 [(e2, 0), (e0, 0), (e5, 0)] 1002 [(e4, 0), (e0, 0), (e5, 0)] 1003 [(e0, 0), (e1, 0), (e5, 0)] 1004 [(e5, 0), (e3, 0), (e0, 0)] 1005 I could write a program to generate these orientations by comparing the faces from GetRawFaces() with my existing table. 1006 */ 1007 static DMPolytopeType tetT[] = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE, DM_POLYTOPE_TETRAHEDRON}; 1008 static PetscInt tetS[] = {1, 8, 8}; 1009 static PetscInt tetC[] = {DM_POLYTOPE_POINT, 2, 0, 0, 0, DM_POLYTOPE_POINT, 2, 2, 1, 0, 1010 DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 2, 2, 1011 DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 1, 1, 1, 1012 DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 1, 0, 1, 1013 DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 2, 1, 1014 DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0, 1015 DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 1, 3, 1, 1016 DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 0, 0, 1017 DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 0, 0, 1018 DM_POLYTOPE_TRIANGLE, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0, DM_POLYTOPE_TRIANGLE, 1, 2, 0, DM_POLYTOPE_TRIANGLE, 0, 0, 1019 DM_POLYTOPE_TRIANGLE, 1, 0, 1, DM_POLYTOPE_TRIANGLE, 1, 1, 2, DM_POLYTOPE_TRIANGLE, 0, 1, DM_POLYTOPE_TRIANGLE, 1, 3, 1, 1020 DM_POLYTOPE_TRIANGLE, 1, 0, 2, DM_POLYTOPE_TRIANGLE, 0, 2, DM_POLYTOPE_TRIANGLE, 1, 2, 1, DM_POLYTOPE_TRIANGLE, 1, 3, 0, 1021 DM_POLYTOPE_TRIANGLE, 0, 3, DM_POLYTOPE_TRIANGLE, 1, 1, 1, DM_POLYTOPE_TRIANGLE, 1, 2, 2, DM_POLYTOPE_TRIANGLE, 1, 3, 2, 1022 DM_POLYTOPE_TRIANGLE, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 2, 3, DM_POLYTOPE_TRIANGLE, 0, 4, DM_POLYTOPE_TRIANGLE, 0, 7, 1023 DM_POLYTOPE_TRIANGLE, 0, 1, DM_POLYTOPE_TRIANGLE, 1, 3, 3, DM_POLYTOPE_TRIANGLE, 0, 5, DM_POLYTOPE_TRIANGLE, 0, 6, 1024 DM_POLYTOPE_TRIANGLE, 0, 4, DM_POLYTOPE_TRIANGLE, 0, 6, DM_POLYTOPE_TRIANGLE, 0, 2, DM_POLYTOPE_TRIANGLE, 1, 0, 3, 1025 DM_POLYTOPE_TRIANGLE, 0, 5, DM_POLYTOPE_TRIANGLE, 0, 7, DM_POLYTOPE_TRIANGLE, 0, 3, DM_POLYTOPE_TRIANGLE, 1, 1, 3}; 1026 static PetscInt tetO[] = {0, 0, 1027 0, 0, 0, 1028 0, 0, 0, 1029 0, 0, 0, 1030 0, 0, 0, 1031 0, 0, -2, 1032 0, 0, -2, 1033 0, -2, -2, 1034 0, -2, 0, 1035 0, 0, 0, 0, 1036 0, 0, 0, 0, 1037 0, 0, 0, 0, 1038 0, 0, 0, 0, 1039 -3, 0, 0, -2, 1040 -2, 1, 0, 0, 1041 -2, -2, -1, 2, 1042 -2, 0, -2, 1}; 1043 /* Add a vertex in the center of each cell, add 6 edges and 12 quads inside every cell, making 8 new hexes 1044 The vertices of our reference hex are (-1, -1, -1), (-1, 1, -1), (1, 1, -1), (1, -1, -1), (-1, -1, 1), (1, -1, 1), (1, 1, 1), (-1, 1, 1) which we call [v0, v1, v2, v3, v4, v5, v6, v7]. The fours edges around the bottom [v0, v1], [v1, v2], [v2, v3], [v3, v0] are [e0, e1, e2, e3], and likewise around the top [v4, v5], [v5, v6], [v6, v7], [v7, v4] are [e4, e5, e6, e7]. Finally [v0, v4], [v1, v7], [v2, v6], [v3, v5] are [e9, e10, e11, e8]. The faces of a hex, given in DMPlexGetRawFaces_Internal(), oriented with outward normals, are 1045 [v0, v1, v2, v3] f0 bottom 1046 [v4, v5, v6, v7] f1 top 1047 [v0, v3, v5, v4] f2 front 1048 [v2, v1, v7, v6] f3 back 1049 [v3, v2, v6, v5] f4 right 1050 [v0, v4, v7, v1] f5 left 1051 The eight hexes are divided into four on the bottom, and four on the top, 1052 [v0, (e0, 0), (f0, 0), (e3, 0), (e9, 0), (f2, 0), (c0, 0), (f5, 0)] 1053 [(e0, 0), v1, (e1, 0), (f0, 0), (f5, 0), (c0, 0), (f3, 0), (e10, 0)] 1054 [(f0, 0), (e1, 0), v2, (e2, 0), (c0, 0), (f4, 0), (e11, 0), (f3, 0)] 1055 [(e3, 0), (f0, 0), (e2, 0), v3, (f2, 0), (e8, 0), (f4, 0), (c0, 0)] 1056 [(e9, 0), (f5, 0), (c0, 0), (f2, 0), v4, (e4, 0), (f1, 0), (e7, 0)] 1057 [(f2, 0), (c0, 0), (f4, 0), (e8, 0), (e4, 0), v5, (e5, 0), (f1, 0)] 1058 [(c0, 0), (f3, 0), (e11, 0), (f4, 0), (f1, 0), (e5, 0), v6, (e6, 0)] 1059 [(f5, 0), (e10, 0), (f3, 0), (c0, 0), (e7, 0), (f1, 0), (e6, 0), v7] 1060 The 6 internal edges will go from the faces to the central vertex. The 12 internal faces can be divided into groups of 4 by the plane on which they sit. First the faces on the x-y plane are, 1061 [(e9, 0), (f2, 0), (c0, 0), (f5, 0)] 1062 [(f5, 0), (c0, 0), (f3, 0), (e10, 0)] 1063 [(c0, 0), (f4, 0), (e11, 0), (f3, 0)] 1064 [(f2, 0), (e8, 0), (f4, 0), (c0, 0)] 1065 and on the x-z plane, 1066 [(f0, 0), (e0, 0), (f5, 0), (c0, 0)] 1067 [(c0, 0), (f5, 0), (e7, 0), (f1, 0)] 1068 [(f4, 0), (c0, 0), (f1, 0), (e5, 0)] 1069 [(e2, 0), (f0, 0), (c0, 0), (f4, 0)] 1070 and on the y-z plane, 1071 [(e3, 0), (f2, 0), (c0, 0), (f0, 0)] 1072 [(f2, 0), (e4, 0), (f1, 0), (c0, 0)] 1073 [(c0, 0), (f1, 0), (e6, 0), (f3, 0)] 1074 [(f0, 0), (c0, 0), (f3, 0), (e1, 0)] 1075 */ 1076 static DMPolytopeType hexT[] = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_HEXAHEDRON}; 1077 static PetscInt hexS[] = {1, 6, 12, 8}; 1078 static PetscInt hexC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0, 1079 DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0, 0, 1080 DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0, 0, 1081 DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 0, 0, 1082 DM_POLYTOPE_POINT, 1, 4, 0, DM_POLYTOPE_POINT, 0, 0, 1083 DM_POLYTOPE_POINT, 1, 5, 0, DM_POLYTOPE_POINT, 0, 0, 1084 DM_POLYTOPE_SEGMENT, 1, 2, 3, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 0, 5, DM_POLYTOPE_SEGMENT, 1, 5, 0, 1085 DM_POLYTOPE_SEGMENT, 0, 5, DM_POLYTOPE_SEGMENT, 0, 3, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 5, 2, 1086 DM_POLYTOPE_SEGMENT, 0, 4, DM_POLYTOPE_SEGMENT, 1, 4, 1, DM_POLYTOPE_SEGMENT, 1, 3, 3, DM_POLYTOPE_SEGMENT, 0, 3, 1087 DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 4, 3, DM_POLYTOPE_SEGMENT, 0, 4, DM_POLYTOPE_SEGMENT, 0, 2, 1088 DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 5, 3, DM_POLYTOPE_SEGMENT, 0, 5, DM_POLYTOPE_SEGMENT, 0, 0, 1089 DM_POLYTOPE_SEGMENT, 0, 5, DM_POLYTOPE_SEGMENT, 1, 5, 1, DM_POLYTOPE_SEGMENT, 1, 1, 3, DM_POLYTOPE_SEGMENT, 0, 1, 1090 DM_POLYTOPE_SEGMENT, 0, 4, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 4, 2, 1091 DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 4, DM_POLYTOPE_SEGMENT, 1, 4, 0, 1092 DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 1, 0, 3, 1093 DM_POLYTOPE_SEGMENT, 1, 2, 2, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 0, 2, 1094 DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 0, 3, 1095 DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 3, DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 1, 0, 1, 1096 DM_POLYTOPE_QUADRILATERAL, 1, 0, 0, DM_POLYTOPE_QUADRILATERAL, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 2, 0, DM_POLYTOPE_QUADRILATERAL, 0, 4, DM_POLYTOPE_QUADRILATERAL, 0, 8, DM_POLYTOPE_QUADRILATERAL, 1, 5, 0, 1097 DM_POLYTOPE_QUADRILATERAL, 1, 0, 1, DM_POLYTOPE_QUADRILATERAL, 0, 1, DM_POLYTOPE_QUADRILATERAL, 0, 4, DM_POLYTOPE_QUADRILATERAL, 1, 3, 1, DM_POLYTOPE_QUADRILATERAL, 0, 11, DM_POLYTOPE_QUADRILATERAL, 1, 5, 3, 1098 DM_POLYTOPE_QUADRILATERAL, 1, 0, 2, DM_POLYTOPE_QUADRILATERAL, 0, 2, DM_POLYTOPE_QUADRILATERAL, 0, 7, DM_POLYTOPE_QUADRILATERAL, 1, 3, 0, DM_POLYTOPE_QUADRILATERAL, 1, 4, 1, DM_POLYTOPE_QUADRILATERAL, 0, 11, 1099 DM_POLYTOPE_QUADRILATERAL, 1, 0, 3, DM_POLYTOPE_QUADRILATERAL, 0, 3, DM_POLYTOPE_QUADRILATERAL, 1, 2, 1, DM_POLYTOPE_QUADRILATERAL, 0, 7, DM_POLYTOPE_QUADRILATERAL, 1, 4, 0, DM_POLYTOPE_QUADRILATERAL, 0, 8, 1100 DM_POLYTOPE_QUADRILATERAL, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 1, 0, DM_POLYTOPE_QUADRILATERAL, 1, 2, 3, DM_POLYTOPE_QUADRILATERAL, 0, 5, DM_POLYTOPE_QUADRILATERAL, 0, 9, DM_POLYTOPE_QUADRILATERAL, 1, 5, 1, 1101 DM_POLYTOPE_QUADRILATERAL, 0, 3, DM_POLYTOPE_QUADRILATERAL, 1, 1, 1, DM_POLYTOPE_QUADRILATERAL, 1, 2, 2, DM_POLYTOPE_QUADRILATERAL, 0, 6, DM_POLYTOPE_QUADRILATERAL, 1, 4, 3, DM_POLYTOPE_QUADRILATERAL, 0, 9, 1102 DM_POLYTOPE_QUADRILATERAL, 0, 2, DM_POLYTOPE_QUADRILATERAL, 1, 1, 2, DM_POLYTOPE_QUADRILATERAL, 0, 6, DM_POLYTOPE_QUADRILATERAL, 1, 3, 3, DM_POLYTOPE_QUADRILATERAL, 1, 4, 2, DM_POLYTOPE_QUADRILATERAL, 0, 10, 1103 DM_POLYTOPE_QUADRILATERAL, 0, 1, DM_POLYTOPE_QUADRILATERAL, 1, 1, 3, DM_POLYTOPE_QUADRILATERAL, 0, 5, DM_POLYTOPE_QUADRILATERAL, 1, 3, 2, DM_POLYTOPE_QUADRILATERAL, 0, 10, DM_POLYTOPE_QUADRILATERAL, 1, 5, 2}; 1104 static PetscInt hexO[] = {0, 0, 1105 0, 0, 1106 0, 0, 1107 0, 0, 1108 0, 0, 1109 0, 0, 1110 0, 0, -2, -2, 1111 0, -2, -2, 0, 1112 -2, -2, 0, 0, 1113 -2, 0, 0, -2, 1114 -2, 0, 0, -2, 1115 -2, -2, 0, 0, 1116 0, -2, -2, 0, 1117 0, 0, -2, -2, 1118 0, 0, -2, -2, 1119 -2, 0, 0, -2, 1120 -2, -2, 0, 0, 1121 0, -2, -2, 0, 1122 0, 0, 0, 0, -4, 0, 1123 0, 0, -1, 0, -4, 0, 1124 0, 0, -1, 0, 0, 0, 1125 0, 0, 0, 0, 0, 0, 1126 -4, 0, 0, 0, -4, 0, 1127 -4, 0, 0, 0, 0, 0, 1128 -4, 0, -1, 0, 0, 0, 1129 -4, 0, -1, 0, -4, 0}; 1130 /* Add 3 quads inside every triangular prism, making 4 new prisms. */ 1131 static DMPolytopeType tripT[] = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_TRI_PRISM}; 1132 static PetscInt tripS[] = {3, 4, 6, 8}; 1133 static PetscInt tripC[] = {DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 1, 3, 0, 1134 DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 1, 4, 0, 1135 DM_POLYTOPE_POINT, 1, 4, 0, DM_POLYTOPE_POINT, 1, 2, 0, 1136 DM_POLYTOPE_SEGMENT, 1, 2, 3, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 1, 4, 1, 1137 DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 3, 3, DM_POLYTOPE_SEGMENT, 0, 0, 1138 DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 4, 3, 1139 DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 0, 2, 1140 DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0, 1141 DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 4, 0, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 1, 3, 0, 1142 DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 1, 4, 0, 1143 DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 2, 1144 DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 1, 4, 2, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 3, 2, 1145 DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 1, 2, 2, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 4, 2, 1146 DM_POLYTOPE_TRIANGLE, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 2, 0, DM_POLYTOPE_QUADRILATERAL, 0, 2, DM_POLYTOPE_QUADRILATERAL, 1, 4, 1, 1147 DM_POLYTOPE_TRIANGLE, 1, 0, 2, DM_POLYTOPE_TRIANGLE, 0, 1, DM_POLYTOPE_QUADRILATERAL, 1, 2, 1, DM_POLYTOPE_QUADRILATERAL, 1, 3, 0, DM_POLYTOPE_QUADRILATERAL, 0, 0, 1148 DM_POLYTOPE_TRIANGLE, 1, 0, 1, DM_POLYTOPE_TRIANGLE, 0, 2, DM_POLYTOPE_QUADRILATERAL, 0, 1, DM_POLYTOPE_QUADRILATERAL, 1, 3, 1, DM_POLYTOPE_QUADRILATERAL, 1, 4, 0, 1149 DM_POLYTOPE_TRIANGLE, 1, 0, 3, DM_POLYTOPE_TRIANGLE, 0, 3, DM_POLYTOPE_QUADRILATERAL, 0, 0, DM_POLYTOPE_QUADRILATERAL, 0, 1, DM_POLYTOPE_QUADRILATERAL, 0, 2, 1150 DM_POLYTOPE_TRIANGLE, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0, DM_POLYTOPE_QUADRILATERAL, 1, 2, 3, DM_POLYTOPE_QUADRILATERAL, 0, 5, DM_POLYTOPE_QUADRILATERAL, 1, 4, 2, 1151 DM_POLYTOPE_TRIANGLE, 0, 1, DM_POLYTOPE_TRIANGLE, 1, 1, 1, DM_POLYTOPE_QUADRILATERAL, 1, 2, 2, DM_POLYTOPE_QUADRILATERAL, 1, 3, 3, DM_POLYTOPE_QUADRILATERAL, 0, 3, 1152 DM_POLYTOPE_TRIANGLE, 0, 2, DM_POLYTOPE_TRIANGLE, 1, 1, 2, DM_POLYTOPE_QUADRILATERAL, 0, 4, DM_POLYTOPE_QUADRILATERAL, 1, 3, 2, DM_POLYTOPE_QUADRILATERAL, 1, 4, 3, 1153 DM_POLYTOPE_TRIANGLE, 0, 3, DM_POLYTOPE_TRIANGLE, 1, 1, 3, DM_POLYTOPE_QUADRILATERAL, 0, 3, DM_POLYTOPE_QUADRILATERAL, 0, 4, DM_POLYTOPE_QUADRILATERAL, 0, 5}; 1154 static PetscInt tripO[] = {0, 0, 1155 0, 0, 1156 0, 0, 1157 0, -2, -2, 1158 -2, 0, -2, 1159 -2, -2, 0, 1160 0, 0, 0, 1161 -2, 0, -2, -2, 1162 -2, 0, -2, -2, 1163 -2, 0, -2, -2, 1164 0, -2, -2, 0, 1165 0, -2, -2, 0, 1166 0, -2, -2, 0, 1167 0, 0, 0, -1, 0, 1168 0, 0, 0, 0, -1, 1169 0, 0, -1, 0, 0, 1170 2, 0, 0, 0, 0, 1171 -3, 0, 0, -1, 0, 1172 -3, 0, 0, 0, -1, 1173 -3, 0, -1, 0, 0, 1174 -3, 0, 0, 0, 0}; 1175 /* Add 3 tensor quads inside every tensor triangular prism, making 4 new prisms. 1176 2 1177 |\ 1178 | \ 1179 | \ 1180 0---1 1181 1182 2 1183 1184 0 1 1185 1186 2 1187 |\ 1188 | \ 1189 | \ 1190 0---1 1191 */ 1192 static DMPolytopeType ttripT[] = {DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_TRI_PRISM_TENSOR}; 1193 static PetscInt ttripS[] = {3, 4}; 1194 static PetscInt ttripC[] = {DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 3, 0, 1195 DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 3, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 4, 0, 1196 DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 4, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 2, 0, 1197 DM_POLYTOPE_TRIANGLE, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 2, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 4, 1, 1198 DM_POLYTOPE_TRIANGLE, 1, 0, 1, DM_POLYTOPE_TRIANGLE, 1, 1, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 2, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 3, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 0, 1199 DM_POLYTOPE_TRIANGLE, 1, 0, 2, DM_POLYTOPE_TRIANGLE, 1, 1, 2, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 3, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 4, 0, 1200 DM_POLYTOPE_TRIANGLE, 1, 0, 3, DM_POLYTOPE_TRIANGLE, 1, 1, 3, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 2}; 1201 static PetscInt ttripO[] = {0, 0, 0, 0, 1202 0, 0, 0, 0, 1203 0, 0, 0, 0, 1204 0, 0, 0, -1, 0, 1205 0, 0, 0, 0, -1, 1206 0, 0, -1, 0, 0, 1207 0, 0, 0, 0, 0}; 1208 /* Add 1 edge and 4 tensor quads inside every tensor quad prism, making 4 new prisms. */ 1209 static DMPolytopeType tquadpT[] = {DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_QUAD_PRISM_TENSOR}; 1210 static PetscInt tquadpS[] = {1, 4, 4}; 1211 static PetscInt tquadpC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0, 1212 DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 0, 0, 1213 DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 3, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 0, 0, 1214 DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 4, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 0, 0, 1215 DM_POLYTOPE_SEGMENT, 1, 0, 3, DM_POLYTOPE_SEGMENT, 1, 1, 3, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 5, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 0, 0, 1216 DM_POLYTOPE_QUADRILATERAL, 1, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 1, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 3, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 5, 1, 1217 DM_POLYTOPE_QUADRILATERAL, 1, 0, 1, DM_POLYTOPE_QUADRILATERAL, 1, 1, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 2, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 3, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 0, 1218 DM_POLYTOPE_QUADRILATERAL, 1, 0, 2, DM_POLYTOPE_QUADRILATERAL, 1, 1, 2, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 3, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 4, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 2, 1219 DM_POLYTOPE_QUADRILATERAL, 1, 0, 3, DM_POLYTOPE_QUADRILATERAL, 1, 1, 3, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 3, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 2, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 4, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 5, 0}; 1220 static PetscInt tquadpO[] = {0, 0, 1221 0, 0, 0, 0, 1222 0, 0, 0, 0, 1223 0, 0, 0, 0, 1224 0, 0, 0, 0, 1225 0, 0, 0, 0, -1, 0, 1226 0, 0, 0, 0, 0, -1, 1227 0, 0, -1, 0, 0, 0, 1228 0, 0, 0, -1, 0, 0}; 1229 PetscErrorCode ierr; 1230 1231 PetscFunctionBegin; 1232 if (rt) *rt = 0; 1233 switch (source) { 1234 case DM_POLYTOPE_POINT: *Nt = 1; *target = vertexT; *size = vertexS; *cone = vertexC; *ornt = vertexO; break; 1235 case DM_POLYTOPE_SEGMENT: *Nt = 2; *target = edgeT; *size = edgeS; *cone = edgeC; *ornt = edgeO; break; 1236 case DM_POLYTOPE_POINT_PRISM_TENSOR: *Nt = 1; *target = tedgeT; *size = tedgeS; *cone = tedgeC; *ornt = tedgeO; break; 1237 case DM_POLYTOPE_TRIANGLE: *Nt = 2; *target = triT; *size = triS; *cone = triC; *ornt = triO; break; 1238 case DM_POLYTOPE_QUADRILATERAL: *Nt = 3; *target = quadT; *size = quadS; *cone = quadC; *ornt = quadO; break; 1239 case DM_POLYTOPE_SEG_PRISM_TENSOR: *Nt = 2; *target = tquadT; *size = tquadS; *cone = tquadC; *ornt = tquadO; break; 1240 case DM_POLYTOPE_TETRAHEDRON: *Nt = 3; *target = tetT; *size = tetS; *cone = tetC; *ornt = tetO; break; 1241 case DM_POLYTOPE_HEXAHEDRON: *Nt = 4; *target = hexT; *size = hexS; *cone = hexC; *ornt = hexO; break; 1242 case DM_POLYTOPE_TRI_PRISM: *Nt = 4; *target = tripT; *size = tripS; *cone = tripC; *ornt = tripO; break; 1243 case DM_POLYTOPE_TRI_PRISM_TENSOR: *Nt = 2; *target = ttripT; *size = ttripS; *cone = ttripC; *ornt = ttripO; break; 1244 case DM_POLYTOPE_QUAD_PRISM_TENSOR: *Nt = 3; *target = tquadpT; *size = tquadpS; *cone = tquadpC; *ornt = tquadpO; break; 1245 /* TODO Fix pyramids: For now, we just ignore them */ 1246 case DM_POLYTOPE_PYRAMID: 1247 ierr = DMPlexCellRefinerRefine_None(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr); 1248 break; 1249 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]); 1250 } 1251 PetscFunctionReturn(0); 1252 } 1253 1254 static PetscErrorCode DMPlexCellRefinerRefine_ToBox(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[]) 1255 { 1256 PetscErrorCode ierr; 1257 /* Change tensor edges to segments */ 1258 static DMPolytopeType tedgeT[] = {DM_POLYTOPE_SEGMENT}; 1259 static PetscInt tedgeS[] = {1}; 1260 static PetscInt tedgeC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0}; 1261 static PetscInt tedgeO[] = { 0, 0}; 1262 /* Add 1 vertex, 3 edges inside every triangle, making 3 new quadrilaterals. 1263 2 1264 |\ 1265 | \ 1266 | \ 1267 | \ 1268 0 1 1269 | \ 1270 | \ 1271 2 1 1272 |\ / \ 1273 | 2 1 \ 1274 | \ / \ 1275 1 | 0 1276 | 0 \ 1277 | | \ 1278 | | \ 1279 0-0-0-----1-----1 1280 */ 1281 static DMPolytopeType triT[] = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL}; 1282 static PetscInt triS[] = {1, 3, 3}; 1283 static PetscInt triC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0, 1284 DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0, 0, 1285 DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0, 0, 1286 DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 1, 2, 1, 1287 DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 0, 0, 1288 DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0}; 1289 static PetscInt triO[] = {0, 0, 1290 0, 0, 1291 0, 0, 1292 0, 0, -2, 0, 1293 0, 0, 0, -2, 1294 0, -2, 0, 0}; 1295 /* Add 1 edge inside every tensor quad, making 2 new quadrilaterals 1296 2----2----1----3----3 1297 | | | 1298 | | | 1299 | | | 1300 4 A 6 B 5 1301 | | | 1302 | | | 1303 | | | 1304 0----0----0----1----1 1305 */ 1306 static DMPolytopeType tquadT[] = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL}; 1307 static PetscInt tquadS[] = {1, 2}; 1308 static PetscInt tquadC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0, 1309 /* TODO Fix these */ 1310 DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0, 1311 DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 0, 0}; 1312 static PetscInt tquadO[] = {0, 0, 1313 0, 0, -2, -2, 1314 0, 0, -2, -2}; 1315 /* Add 6 triangles inside every cell, making 4 new hexs 1316 TODO: Need different SubcellMap(). Need to make a struct with the function pointers in it 1317 The vertices of our reference tet are [(-1, -1, -1), (-1, 1, -1), (1, -1, -1), (-1, -1, 1)], which we call [v0, v1, v2, v3]. The first 1318 three edges are [v0, v1], [v1, v2], [v2, v0] called e0, e1, and e2, and then three edges to the top point [v0, v3], [v1, v3], [v2, v3] 1319 called e3, e4, and e5. The faces of a tet, given in DMPlexGetRawFaces_Internal() are 1320 [v0, v1, v2], [v0, v3, v1], [v0, v2, v3], [v2, v1, v3] 1321 We make a new hex in each corner 1322 [v0, (e0, 0), (f0, 0), (e2, 0), (e3, 0), (f2, 0), (c0, 0), (f1, 0)] 1323 [v1, (e4, 0), (f3, 0), (e1, 0), (e0, 0), (f0, 0), (c0, 0), (f1, 0)] 1324 [v2, (e1, 0), (f3, 0), (e5, 0), (e2, 0), (f2, 0), (c0, 0), (f0, 0)] 1325 [v3, (e4, 0), (f1, 0), (e3, 0), (e5, 0), (f2, 0), (c0, 0), (f3, 0)] 1326 We create a new face for each edge 1327 [(e3, 0), (f2, 0), (c0, 0), (f1, 0)] 1328 [(f0, 0), (e0, 0), (f1, 0), (c0, 0)] 1329 [(e2, 0), (f0, 0), (c0, 0), (f2, 0)] 1330 [(f3, 0), (e4, 0), (f1, 0), (c0, 0)] 1331 [(e1, 0), (f3, 0), (c0, 0), (f0, 0)] 1332 [(e5, 0), (f3, 0), (c0, 0), (f2, 0)] 1333 I could write a program to generate these from the first hex by acting with the symmetry group to take one subcell into another. 1334 */ 1335 static DMPolytopeType tetT[] = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_HEXAHEDRON}; 1336 static PetscInt tetS[] = {1, 4, 6, 4}; 1337 static PetscInt tetC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0, 1338 DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0, 0, 1339 DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0, 0, 1340 DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 0, 0, 1341 DM_POLYTOPE_SEGMENT, 1, 2, 2, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, 1342 DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 0, 0, 1343 DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 1, 2, 0, 1344 DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 0, 3, 1345 DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 0, 3, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 1, 0, 1, 1346 DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 0, 3, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 1, 2, 1, 1347 DM_POLYTOPE_QUADRILATERAL, 1, 0, 0, DM_POLYTOPE_QUADRILATERAL, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 2, 0, DM_POLYTOPE_QUADRILATERAL, 0, 1, DM_POLYTOPE_QUADRILATERAL, 0, 2, DM_POLYTOPE_QUADRILATERAL, 1, 1, 0, 1348 DM_POLYTOPE_QUADRILATERAL, 1, 3, 1, DM_POLYTOPE_QUADRILATERAL, 0, 1, DM_POLYTOPE_QUADRILATERAL, 1, 0, 1, DM_POLYTOPE_QUADRILATERAL, 0, 3, DM_POLYTOPE_QUADRILATERAL, 0, 4, DM_POLYTOPE_QUADRILATERAL, 1, 1, 2, 1349 DM_POLYTOPE_QUADRILATERAL, 1, 3, 0, DM_POLYTOPE_QUADRILATERAL, 0, 2, DM_POLYTOPE_QUADRILATERAL, 1, 2, 1, DM_POLYTOPE_QUADRILATERAL, 0, 4, DM_POLYTOPE_QUADRILATERAL, 0, 5, DM_POLYTOPE_QUADRILATERAL, 1, 0, 2, 1350 DM_POLYTOPE_QUADRILATERAL, 1, 1, 1, DM_POLYTOPE_QUADRILATERAL, 0, 5, DM_POLYTOPE_QUADRILATERAL, 1, 2, 2, DM_POLYTOPE_QUADRILATERAL, 0, 3, DM_POLYTOPE_QUADRILATERAL, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 3, 2}; 1351 static PetscInt tetO[] = {0, 0, 1352 0, 0, 1353 0, 0, 1354 0, 0, 1355 0, 0, -2, -2, 1356 -2, 0, 0, -2, 1357 0, 0, -2, -2, 1358 -2, 0, 0, -2, 1359 0, 0, -2, -2, 1360 0, 0, -2, -2, 1361 0, 0, 0, 0, 0, 0, 1362 1, -1, 1, 0, 0, 3, 1363 0, -4, 1, -1, 0, 3, 1364 1, -4, 3, -2, -4, 3}; 1365 /* Add 3 quads inside every triangular prism, making 4 new prisms. */ 1366 static DMPolytopeType tripT[] = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_HEXAHEDRON}; 1367 static PetscInt tripS[] = {1, 5, 9, 6}; 1368 static PetscInt tripC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0, 1369 DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0, 0, 1370 DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0, 0, 1371 DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 0, 0, 1372 DM_POLYTOPE_POINT, 1, 4, 0, DM_POLYTOPE_POINT, 0, 0, 1373 DM_POLYTOPE_SEGMENT, 1, 2, 3, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 0, 4, DM_POLYTOPE_SEGMENT, 1, 4, 1, 1374 DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 3, 3, DM_POLYTOPE_SEGMENT, 0, 3, DM_POLYTOPE_SEGMENT, 0, 2, 1375 DM_POLYTOPE_SEGMENT, 0, 4, DM_POLYTOPE_SEGMENT, 0, 3, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 4, 3, 1376 DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 1, 2, 0, 1377 DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 3, DM_POLYTOPE_SEGMENT, 1, 3, 0, 1378 DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 4, DM_POLYTOPE_SEGMENT, 1, 4, 0, 1379 DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 2, 1380 DM_POLYTOPE_SEGMENT, 0, 3, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 3, 2, 1381 DM_POLYTOPE_SEGMENT, 0, 4, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 4, 2, 1382 DM_POLYTOPE_QUADRILATERAL, 1, 0, 0, DM_POLYTOPE_QUADRILATERAL, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 2, 0, DM_POLYTOPE_QUADRILATERAL, 0, 5, DM_POLYTOPE_QUADRILATERAL, 0, 3, DM_POLYTOPE_QUADRILATERAL, 1, 4, 1, 1383 DM_POLYTOPE_QUADRILATERAL, 1, 0, 2, DM_POLYTOPE_QUADRILATERAL, 0, 1, DM_POLYTOPE_QUADRILATERAL, 1, 2, 1, DM_POLYTOPE_QUADRILATERAL, 0, 4, DM_POLYTOPE_QUADRILATERAL, 1, 3, 0, DM_POLYTOPE_QUADRILATERAL, 0, 3, 1384 DM_POLYTOPE_QUADRILATERAL, 1, 0, 1, DM_POLYTOPE_QUADRILATERAL, 0, 2, DM_POLYTOPE_QUADRILATERAL, 0, 5, DM_POLYTOPE_QUADRILATERAL, 1, 3, 1, DM_POLYTOPE_QUADRILATERAL, 0, 4, DM_POLYTOPE_QUADRILATERAL, 1, 4, 0, 1385 DM_POLYTOPE_QUADRILATERAL, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 1, 0, DM_POLYTOPE_QUADRILATERAL, 1, 2, 3, DM_POLYTOPE_QUADRILATERAL, 0, 8, DM_POLYTOPE_QUADRILATERAL, 0, 6, DM_POLYTOPE_QUADRILATERAL, 1, 4, 2, 1386 DM_POLYTOPE_QUADRILATERAL, 0, 1, DM_POLYTOPE_QUADRILATERAL, 1, 1, 1, DM_POLYTOPE_QUADRILATERAL, 1, 2, 2, DM_POLYTOPE_QUADRILATERAL, 0, 7, DM_POLYTOPE_QUADRILATERAL, 1, 3, 3, DM_POLYTOPE_QUADRILATERAL, 0, 6, 1387 DM_POLYTOPE_QUADRILATERAL, 0, 2, DM_POLYTOPE_QUADRILATERAL, 1, 1, 2, DM_POLYTOPE_QUADRILATERAL, 0, 8, DM_POLYTOPE_QUADRILATERAL, 1, 3, 2, DM_POLYTOPE_QUADRILATERAL, 0, 7, DM_POLYTOPE_QUADRILATERAL, 1, 4, 3}; 1388 static PetscInt tripO[] = {0, 0, 1389 0, 0, 1390 0, 0, 1391 0, 0, 1392 0, 0, 1393 0, 0, -2, -2, 1394 -2, 0, 0, -2, 1395 0, -2, -2, 0, 1396 0, 0, -2, -2, 1397 0, 0, -2, -2, 1398 0, 0, -2, -2, 1399 0, -2, -2, 0, 1400 0, -2, -2, 0, 1401 0, -2, -2, 0, 1402 0, 0, 0, -1, 0, 1, 1403 0, 0, 0, 0, 0, -4, 1404 0, 0, 0, 0, -1, 1, 1405 -4, 0, 0, -1, 0, 1, 1406 -4, 0, 0, 0, 0, -4, 1407 -4, 0, 0, 0, -1, 1}; 1408 /* Add 3 tensor quads inside every tensor triangular prism, making 4 new tensor triangular prisms. 1409 2 1410 |\ 1411 | \ 1412 | \ 1413 0---1 1414 1415 2 1416 1417 0 1 1418 1419 2 1420 |\ 1421 | \ 1422 | \ 1423 0---1 1424 */ 1425 static DMPolytopeType ttripT[] = {DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_QUAD_PRISM_TENSOR}; 1426 static PetscInt ttripS[] = {1, 3, 3}; 1427 static PetscInt ttripC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0, 1428 DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 0, 0, 1429 DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 3, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 0, 0, 1430 DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 4, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 0, 0, 1431 DM_POLYTOPE_QUADRILATERAL, 1, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 1, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 2, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 4, 1, 1432 DM_POLYTOPE_QUADRILATERAL, 1, 0, 1, DM_POLYTOPE_QUADRILATERAL, 1, 1, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 2, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 3, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 0, 1433 DM_POLYTOPE_QUADRILATERAL, 1, 0, 2, DM_POLYTOPE_QUADRILATERAL, 1, 1, 2, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 2, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 3, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 4, 0}; 1434 static PetscInt ttripO[] = {0, 0, 1435 0, 0, 0, 0, 1436 0, 0, 0, 0, 1437 0, 0, 0, 0, 1438 0, 0, 0, 0, -1, 0, 1439 0, 0, 0, 0, 0, -1, 1440 0, 0, 0, -1, 0, 0}; 1441 /* TODO Add 3 quads inside every tensor triangular prism, making 4 new triangular prisms. 1442 2 1443 |\ 1444 | \ 1445 | \ 1446 0---1 1447 1448 2 1449 1450 0 1 1451 1452 2 1453 |\ 1454 | \ 1455 | \ 1456 0---1 1457 */ 1458 static DMPolytopeType ctripT[] = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_HEXAHEDRON}; 1459 static PetscInt ctripS[] = {1, 3, 3}; 1460 static PetscInt ctripC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0, 1461 DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0, 1462 DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 3, 0, 1463 DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 4, 0, 1464 DM_POLYTOPE_QUADRILATERAL, 1, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 1, 0, DM_POLYTOPE_QUADRILATERAL, 1, 2, 0, DM_POLYTOPE_QUADRILATERAL, 0, 2, DM_POLYTOPE_QUADRILATERAL, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 4, 1, 1465 DM_POLYTOPE_QUADRILATERAL, 1, 0, 1, DM_POLYTOPE_QUADRILATERAL, 1, 1, 1, DM_POLYTOPE_QUADRILATERAL, 1, 2, 1, DM_POLYTOPE_QUADRILATERAL, 0, 1, DM_POLYTOPE_QUADRILATERAL, 1, 3, 0, DM_POLYTOPE_QUADRILATERAL, 0, 0, 1466 DM_POLYTOPE_QUADRILATERAL, 1, 0, 2, DM_POLYTOPE_QUADRILATERAL, 1, 1, 2, DM_POLYTOPE_QUADRILATERAL, 0, 2, DM_POLYTOPE_QUADRILATERAL, 1, 3, 1, DM_POLYTOPE_QUADRILATERAL, 0, 1, DM_POLYTOPE_QUADRILATERAL, 1, 4, 0}; 1467 static PetscInt ctripO[] = {0, 0, 1468 0, 0, -2, -2, 1469 0, 0, -2, -2, 1470 0, 0, -2, -2, 1471 -4, 0, 0, -1, 0, 1, 1472 -4, 0, 0, 0, 0, -4, 1473 -4, 0, 0, 0, -1, 1}; 1474 /* Add 1 edge and 4 quads inside every tensor quad prism, making 4 new hexahedra. */ 1475 static DMPolytopeType tquadpT[] = {DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_QUAD_PRISM_TENSOR}; 1476 static PetscInt tquadpS[] = {1, 4, 4}; 1477 static PetscInt tquadpC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0, 1478 DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 0, 0, 1479 DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 3, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 0, 0, 1480 DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 4, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 0, 0, 1481 DM_POLYTOPE_SEGMENT, 1, 0, 3, DM_POLYTOPE_SEGMENT, 1, 1, 3, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 5, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 0, 0, 1482 DM_POLYTOPE_QUADRILATERAL, 1, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 1, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 3, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 5, 1, 1483 DM_POLYTOPE_QUADRILATERAL, 1, 0, 1, DM_POLYTOPE_QUADRILATERAL, 1, 1, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 2, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 3, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 0, 1484 DM_POLYTOPE_QUADRILATERAL, 1, 0, 2, DM_POLYTOPE_QUADRILATERAL, 1, 1, 2, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 3, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 4, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 2, 1485 DM_POLYTOPE_QUADRILATERAL, 1, 0, 3, DM_POLYTOPE_QUADRILATERAL, 1, 1, 3, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 3, DM_POLYTOPE_SEG_PRISM_TENSOR, 0, 2, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 4, 1, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 5, 0}; 1486 static PetscInt tquadpO[] = {0, 0, 1487 0, 0, 0, 0, 1488 0, 0, 0, 0, 1489 0, 0, 0, 0, 1490 0, 0, 0, 0, 1491 0, 0, 0, 0, -1, 0, 1492 0, 0, 0, 0, 0, -1, 1493 0, 0, -1, 0, 0, 0, 1494 0, 0, 0, -1, 0, 0}; 1495 PetscBool convertTensor = PETSC_TRUE; 1496 1497 PetscFunctionBeginHot; 1498 if (rt) *rt = 0; 1499 if (convertTensor) { 1500 switch (source) { 1501 case DM_POLYTOPE_POINT: 1502 case DM_POLYTOPE_SEGMENT: 1503 case DM_POLYTOPE_QUADRILATERAL: 1504 case DM_POLYTOPE_HEXAHEDRON: 1505 ierr = DMPlexCellRefinerRefine_Regular(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr); 1506 break; 1507 case DM_POLYTOPE_POINT_PRISM_TENSOR: *Nt = 1; *target = tedgeT; *size = tedgeS; *cone = tedgeC; *ornt = tedgeO; break; 1508 case DM_POLYTOPE_SEG_PRISM_TENSOR: *Nt = 2; *target = tquadT; *size = tquadS; *cone = tquadC; *ornt = tquadO; break; 1509 case DM_POLYTOPE_TRI_PRISM_TENSOR: *Nt = 3; *target = ctripT; *size = ctripS; *cone = ctripC; *ornt = ctripO; break; 1510 case DM_POLYTOPE_QUAD_PRISM_TENSOR: *Nt = 3; *target = tquadpT; *size = tquadpS; *cone = tquadpC; *ornt = tquadpO; break; 1511 case DM_POLYTOPE_TRIANGLE: *Nt = 3; *target = triT; *size = triS; *cone = triC; *ornt = triO; break; 1512 case DM_POLYTOPE_TETRAHEDRON: *Nt = 4; *target = tetT; *size = tetS; *cone = tetC; *ornt = tetO; break; 1513 case DM_POLYTOPE_TRI_PRISM: *Nt = 4; *target = tripT; *size = tripS; *cone = tripC; *ornt = tripO; break; 1514 /* TODO Fix pyramids: For now, we just ignore them */ 1515 case DM_POLYTOPE_PYRAMID: 1516 ierr = DMPlexCellRefinerRefine_None(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr); 1517 break; 1518 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]); 1519 } 1520 } else { 1521 switch (source) { 1522 case DM_POLYTOPE_POINT: 1523 case DM_POLYTOPE_POINT_PRISM_TENSOR: 1524 case DM_POLYTOPE_SEGMENT: 1525 case DM_POLYTOPE_QUADRILATERAL: 1526 case DM_POLYTOPE_SEG_PRISM_TENSOR: 1527 case DM_POLYTOPE_HEXAHEDRON: 1528 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 1529 ierr = DMPlexCellRefinerRefine_Regular(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr); 1530 break; 1531 case DM_POLYTOPE_TRIANGLE: *Nt = 3; *target = triT; *size = triS; *cone = triC; *ornt = triO; break; 1532 case DM_POLYTOPE_TETRAHEDRON: *Nt = 4; *target = tetT; *size = tetS; *cone = tetC; *ornt = tetO; break; 1533 case DM_POLYTOPE_TRI_PRISM: *Nt = 4; *target = tripT; *size = tripS; *cone = tripC; *ornt = tripO; break; 1534 case DM_POLYTOPE_TRI_PRISM_TENSOR: *Nt = 3; *target = ttripT; *size = ttripS; *cone = ttripC; *ornt = ttripO; break; 1535 /* TODO Fix pyramids: For now, we just ignore them */ 1536 case DM_POLYTOPE_PYRAMID: 1537 ierr = DMPlexCellRefinerRefine_None(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr); 1538 break; 1539 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]); 1540 } 1541 } 1542 PetscFunctionReturn(0); 1543 } 1544 1545 static PetscErrorCode DMPlexCellRefinerRefine_ToSimplex(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[]) 1546 { 1547 PetscErrorCode ierr; 1548 1549 PetscFunctionBeginHot; 1550 if (rt) *rt = 0; 1551 switch (source) { 1552 case DM_POLYTOPE_POINT: 1553 case DM_POLYTOPE_SEGMENT: 1554 case DM_POLYTOPE_POINT_PRISM_TENSOR: 1555 case DM_POLYTOPE_TRIANGLE: 1556 case DM_POLYTOPE_TETRAHEDRON: 1557 case DM_POLYTOPE_TRI_PRISM: 1558 case DM_POLYTOPE_TRI_PRISM_TENSOR: 1559 case DM_POLYTOPE_QUADRILATERAL: 1560 case DM_POLYTOPE_SEG_PRISM_TENSOR: 1561 case DM_POLYTOPE_HEXAHEDRON: 1562 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 1563 ierr = DMPlexCellRefinerRefine_Regular(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr); 1564 break; 1565 /* TODO Fix pyramids: For now, we just ignore them */ 1566 case DM_POLYTOPE_PYRAMID: 1567 ierr = DMPlexCellRefinerRefine_None(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr); 1568 break; 1569 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]); 1570 } 1571 PetscFunctionReturn(0); 1572 } 1573 1574 static PetscErrorCode DMPlexCellRefinerRefine_Alfeld2D(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[]) 1575 { 1576 PetscErrorCode ierr; 1577 /* Add 1 vertex, 3 edges inside every triangle, making 3 new triangles. 1578 2 1579 |\ 1580 |\\ 1581 | |\ 1582 | \ \ 1583 | | \ 1584 | \ \ 1585 | | \ 1586 2 \ \ 1587 | | 1 1588 | 2 \ 1589 | | \ 1590 | /\ \ 1591 | 0 1 | 1592 | / \ | 1593 |/ \| 1594 0---0----1 1595 */ 1596 static DMPolytopeType triT[] = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE}; 1597 static PetscInt triS[] = {1, 3, 3}; 1598 static PetscInt triC[] = {DM_POLYTOPE_POINT, 2, 0, 0, 0, DM_POLYTOPE_POINT, 0, 0, 1599 DM_POLYTOPE_POINT, 2, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0, 1600 DM_POLYTOPE_POINT, 2, 2, 0, 0, DM_POLYTOPE_POINT, 0, 0, 1601 DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 0, 0, 1602 DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 0, 1, 1603 DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 2}; 1604 static PetscInt triO[] = {0, 0, 1605 0, 0, 1606 0, 0, 1607 0, 0, -2, 1608 0, 0, -2, 1609 0, 0, -2}; 1610 1611 PetscFunctionBeginHot; 1612 if (rt) *rt = 0; 1613 switch (source) { 1614 case DM_POLYTOPE_POINT: 1615 case DM_POLYTOPE_SEGMENT: 1616 case DM_POLYTOPE_POINT_PRISM_TENSOR: 1617 case DM_POLYTOPE_QUADRILATERAL: 1618 case DM_POLYTOPE_SEG_PRISM_TENSOR: 1619 case DM_POLYTOPE_TETRAHEDRON: 1620 case DM_POLYTOPE_HEXAHEDRON: 1621 case DM_POLYTOPE_TRI_PRISM: 1622 case DM_POLYTOPE_TRI_PRISM_TENSOR: 1623 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 1624 case DM_POLYTOPE_PYRAMID: 1625 ierr = DMPlexCellRefinerRefine_None(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr); 1626 break; 1627 case DM_POLYTOPE_TRIANGLE: *Nt = 3; *target = triT; *size = triS; *cone = triC; *ornt = triO; break; 1628 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]); 1629 } 1630 PetscFunctionReturn(0); 1631 } 1632 1633 static PetscErrorCode DMPlexCellRefinerRefine_Alfeld3D(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[]) 1634 { 1635 PetscErrorCode ierr; 1636 /* Add 6 triangles inside every cell, making 4 new tets 1637 The vertices of our reference tet are [(-1, -1, -1), (-1, 1, -1), (1, -1, -1), (-1, -1, 1)], which we call [v0, v1, v2, v3]. The first 1638 three edges are [v0, v1], [v1, v2], [v2, v0] called e0, e1, and e2, and then three edges to the top point [v0, v3], [v1, v3], [v2, v3] 1639 called e3, e4, and e5. The faces of a tet, given in DMPlexGetRawFaces_Internal() are 1640 [v0, v1, v2], [v0, v3, v1], [v0, v2, v3], [v2, v1, v3] 1641 We make a new tet on each face 1642 [v0, v1, v2, (c0, 0)] 1643 [v0, v3, v1, (c0, 0)] 1644 [v0, v2, v3, (c0, 0)] 1645 [v2, v1, v3, (c0, 0)] 1646 We create a new face for each edge 1647 [v0, (c0, 0), v1 ] 1648 [v0, v2, (c0, 0)] 1649 [v2, v1, (c0, 0)] 1650 [v0, (c0, 0), v3 ] 1651 [v1, v3, (c0, 0)] 1652 [v3, v2, (c0, 0)] 1653 */ 1654 static DMPolytopeType tetT[] = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE, DM_POLYTOPE_TETRAHEDRON}; 1655 static PetscInt tetS[] = {1, 4, 6, 4}; 1656 static PetscInt tetC[] = {DM_POLYTOPE_POINT, 3, 0, 0, 0, 0, DM_POLYTOPE_POINT, 0, 0, 1657 DM_POLYTOPE_POINT, 3, 0, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0, 1658 DM_POLYTOPE_POINT, 3, 0, 2, 0, 0, DM_POLYTOPE_POINT, 0, 0, 1659 DM_POLYTOPE_POINT, 3, 1, 0, 1, 0, DM_POLYTOPE_POINT, 0, 0, 1660 DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 2, 0, 0, 0, 1661 DM_POLYTOPE_SEGMENT, 2, 0, 2, 0, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 0, 0, 1662 DM_POLYTOPE_SEGMENT, 2, 0, 1, 0, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 0, 2, 1663 DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 3, DM_POLYTOPE_SEGMENT, 2, 1, 0, 0, 1664 DM_POLYTOPE_SEGMENT, 2, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0, 3, DM_POLYTOPE_SEGMENT, 0, 1, 1665 DM_POLYTOPE_SEGMENT, 2, 2, 1, 0, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 0, 3, 1666 DM_POLYTOPE_TRIANGLE, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 0, 0, DM_POLYTOPE_TRIANGLE, 0, 1, DM_POLYTOPE_TRIANGLE, 0, 2, 1667 DM_POLYTOPE_TRIANGLE, 1, 1, 0, DM_POLYTOPE_TRIANGLE, 0, 3, DM_POLYTOPE_TRIANGLE, 0, 0, DM_POLYTOPE_TRIANGLE, 0, 4, 1668 DM_POLYTOPE_TRIANGLE, 1, 2, 0, DM_POLYTOPE_TRIANGLE, 0, 1, DM_POLYTOPE_TRIANGLE, 0, 3, DM_POLYTOPE_TRIANGLE, 0, 5, 1669 DM_POLYTOPE_TRIANGLE, 1, 3, 0, DM_POLYTOPE_TRIANGLE, 0, 2, DM_POLYTOPE_TRIANGLE, 0, 5, DM_POLYTOPE_TRIANGLE, 0, 4}; 1670 static PetscInt tetO[] = {0, 0, 1671 0, 0, 1672 0, 0, 1673 0, 0, 1674 0, -2, -2, 1675 -2, 0, -2, 1676 -2, 0, -2, 1677 0, -2, -2, 1678 -2, 0, -2, 1679 -2, 0, -2, 1680 0, 0, 0, 0, 1681 0, 0, -3, 0, 1682 0, -3, -3, 0, 1683 0, -3, -1, -1}; 1684 1685 PetscFunctionBeginHot; 1686 if (rt) *rt = 0; 1687 switch (source) { 1688 case DM_POLYTOPE_POINT: 1689 case DM_POLYTOPE_SEGMENT: 1690 case DM_POLYTOPE_POINT_PRISM_TENSOR: 1691 case DM_POLYTOPE_TRIANGLE: 1692 case DM_POLYTOPE_QUADRILATERAL: 1693 case DM_POLYTOPE_SEG_PRISM_TENSOR: 1694 case DM_POLYTOPE_HEXAHEDRON: 1695 case DM_POLYTOPE_TRI_PRISM: 1696 case DM_POLYTOPE_TRI_PRISM_TENSOR: 1697 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 1698 case DM_POLYTOPE_PYRAMID: 1699 ierr = DMPlexCellRefinerRefine_None(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr); 1700 break; 1701 case DM_POLYTOPE_TETRAHEDRON: *Nt = 4; *target = tetT; *size = tetS; *cone = tetC; *ornt = tetO; break; 1702 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]); 1703 } 1704 PetscFunctionReturn(0); 1705 } 1706 1707 typedef struct { 1708 PetscInt n; 1709 PetscReal r; 1710 PetscScalar *h; 1711 PetscInt *Nt; 1712 DMPolytopeType **target; 1713 PetscInt **size; 1714 PetscInt **cone; 1715 PetscInt **ornt; 1716 } PlexRefiner_BL; 1717 1718 static PetscErrorCode DMPlexCellRefinerSetUp_BL(DMPlexCellRefiner cr) 1719 { 1720 PlexRefiner_BL *crbl; 1721 PetscErrorCode ierr; 1722 PetscInt i,n; 1723 PetscReal r; 1724 PetscInt c1,c2,o1,o2; 1725 1726 PetscFunctionBegin; 1727 ierr = PetscNew(&crbl);CHKERRQ(ierr); 1728 cr->data = crbl; 1729 crbl->n = 1; /* 1 split -> 2 new cells */ 1730 crbl->r = 1; /* linear progression */ 1731 1732 /* TODO: add setfromoptions to the refiners? */ 1733 ierr = PetscOptionsGetInt(((PetscObject) cr->dm)->options,((PetscObject) cr->dm)->prefix, "-dm_plex_refine_boundarylayer_splits", &crbl->n, NULL);CHKERRQ(ierr); 1734 if (crbl->n < 1) SETERRQ1(PetscObjectComm((PetscObject)cr),PETSC_ERR_SUP,"Number of splits %D must be positive",crbl->n); 1735 ierr = PetscOptionsGetReal(((PetscObject) cr->dm)->options,((PetscObject) cr->dm)->prefix, "-dm_plex_refine_boundarylayer_progression", &crbl->r, NULL);CHKERRQ(ierr); 1736 n = crbl->n; 1737 r = crbl->r; 1738 1739 /* we only split DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_TRI_PRISM_TENSOR and DM_POLYTOPE_QUAD_PRISM_TENSOR */ 1740 ierr = PetscMalloc5(4,&crbl->Nt,4,&crbl->target,4,&crbl->size,4,&crbl->cone,4,&crbl->ornt);CHKERRQ(ierr); 1741 1742 /* progression */ 1743 ierr = PetscMalloc1(n,&crbl->h);CHKERRQ(ierr); 1744 if (r > 1) { 1745 PetscReal d = (r-1.)/(PetscPowRealInt(r,n+1)-1.); 1746 1747 crbl->h[0] = d; 1748 for (i = 1; i < n; i++) { 1749 d *= r; 1750 crbl->h[i] = crbl->h[i-1] + d; 1751 } 1752 } else { /* linear */ 1753 for (i = 0; i < n; i++) crbl->h[i] = (i + 1.)/(n+1); /* linear */ 1754 } 1755 1756 /* DM_POLYTOPE_POINT_PRISM_TENSOR produces n points and n+1 tensor segments */ 1757 c1 = 14+6*(n-1); 1758 o1 = 2*(n+1); 1759 crbl->Nt[0] = 2; 1760 1761 ierr = PetscMalloc4(crbl->Nt[0],&crbl->target[0],crbl->Nt[0],&crbl->size[0],c1,&crbl->cone[0],o1,&crbl->ornt[0]);CHKERRQ(ierr); 1762 1763 crbl->target[0][0] = DM_POLYTOPE_POINT; 1764 crbl->target[0][1] = DM_POLYTOPE_POINT_PRISM_TENSOR; 1765 1766 crbl->size[0][0] = n; 1767 crbl->size[0][1] = n+1; 1768 1769 /* the tensor segments */ 1770 crbl->cone[0][0] = DM_POLYTOPE_POINT; 1771 crbl->cone[0][1] = 1; 1772 crbl->cone[0][2] = 0; 1773 crbl->cone[0][3] = 0; 1774 crbl->cone[0][4] = DM_POLYTOPE_POINT; 1775 crbl->cone[0][5] = 0; 1776 crbl->cone[0][6] = 0; 1777 for (i = 0; i < n-1; i++) { 1778 crbl->cone[0][7+6*i+0] = DM_POLYTOPE_POINT; 1779 crbl->cone[0][7+6*i+1] = 0; 1780 crbl->cone[0][7+6*i+2] = i; 1781 crbl->cone[0][7+6*i+3] = DM_POLYTOPE_POINT; 1782 crbl->cone[0][7+6*i+4] = 0; 1783 crbl->cone[0][7+6*i+5] = i+1; 1784 } 1785 crbl->cone[0][7+6*(n-1)+0] = DM_POLYTOPE_POINT; 1786 crbl->cone[0][7+6*(n-1)+1] = 0; 1787 crbl->cone[0][7+6*(n-1)+2] = n-1; 1788 crbl->cone[0][7+6*(n-1)+3] = DM_POLYTOPE_POINT; 1789 crbl->cone[0][7+6*(n-1)+4] = 1; 1790 crbl->cone[0][7+6*(n-1)+5] = 1; 1791 crbl->cone[0][7+6*(n-1)+6] = 0; 1792 for (i = 0; i < o1; i++) crbl->ornt[0][i] = 0; 1793 1794 /* DM_POLYTOPE_SEG_PRISM_TENSOR produces n segments and n+1 tensor quads */ 1795 c1 = 8*n; 1796 c2 = 30+14*(n-1); 1797 o1 = 2*n; 1798 o2 = 4*(n+1); 1799 crbl->Nt[1] = 2; 1800 1801 ierr = PetscMalloc4(crbl->Nt[1],&crbl->target[1],crbl->Nt[1],&crbl->size[1],c1+c2,&crbl->cone[1],o1+o2,&crbl->ornt[1]);CHKERRQ(ierr); 1802 1803 crbl->target[1][0] = DM_POLYTOPE_SEGMENT; 1804 crbl->target[1][1] = DM_POLYTOPE_SEG_PRISM_TENSOR; 1805 1806 crbl->size[1][0] = n; 1807 crbl->size[1][1] = n+1; 1808 1809 /* the segments */ 1810 for (i = 0; i < n; i++) { 1811 crbl->cone[1][8*i+0] = DM_POLYTOPE_POINT; 1812 crbl->cone[1][8*i+1] = 1; 1813 crbl->cone[1][8*i+2] = 2; 1814 crbl->cone[1][8*i+3] = i; 1815 crbl->cone[1][8*i+4] = DM_POLYTOPE_POINT; 1816 crbl->cone[1][8*i+5] = 1; 1817 crbl->cone[1][8*i+6] = 3; 1818 crbl->cone[1][8*i+7] = i; 1819 } 1820 1821 /* the tensor quads */ 1822 crbl->cone[1][c1+ 0] = DM_POLYTOPE_SEGMENT; 1823 crbl->cone[1][c1+ 1] = 1; 1824 crbl->cone[1][c1+ 2] = 0; 1825 crbl->cone[1][c1+ 3] = 0; 1826 crbl->cone[1][c1+ 4] = DM_POLYTOPE_SEGMENT; 1827 crbl->cone[1][c1+ 5] = 0; 1828 crbl->cone[1][c1+ 6] = 0; 1829 crbl->cone[1][c1+ 7] = DM_POLYTOPE_POINT_PRISM_TENSOR; 1830 crbl->cone[1][c1+ 8] = 1; 1831 crbl->cone[1][c1+ 9] = 2; 1832 crbl->cone[1][c1+10] = 0; 1833 crbl->cone[1][c1+11] = DM_POLYTOPE_POINT_PRISM_TENSOR; 1834 crbl->cone[1][c1+12] = 1; 1835 crbl->cone[1][c1+13] = 3; 1836 crbl->cone[1][c1+14] = 0; 1837 for (i = 0; i < n-1; i++) { 1838 crbl->cone[1][c1+15+14*i+ 0] = DM_POLYTOPE_SEGMENT; 1839 crbl->cone[1][c1+15+14*i+ 1] = 0; 1840 crbl->cone[1][c1+15+14*i+ 2] = i; 1841 crbl->cone[1][c1+15+14*i+ 3] = DM_POLYTOPE_SEGMENT; 1842 crbl->cone[1][c1+15+14*i+ 4] = 0; 1843 crbl->cone[1][c1+15+14*i+ 5] = i+1; 1844 crbl->cone[1][c1+15+14*i+ 6] = DM_POLYTOPE_POINT_PRISM_TENSOR; 1845 crbl->cone[1][c1+15+14*i+ 7] = 1; 1846 crbl->cone[1][c1+15+14*i+ 8] = 2; 1847 crbl->cone[1][c1+15+14*i+ 9] = i+1; 1848 crbl->cone[1][c1+15+14*i+10] = DM_POLYTOPE_POINT_PRISM_TENSOR; 1849 crbl->cone[1][c1+15+14*i+11] = 1; 1850 crbl->cone[1][c1+15+14*i+12] = 3; 1851 crbl->cone[1][c1+15+14*i+13] = i+1; 1852 } 1853 crbl->cone[1][c1+15+14*(n-1)+ 0] = DM_POLYTOPE_SEGMENT; 1854 crbl->cone[1][c1+15+14*(n-1)+ 1] = 0; 1855 crbl->cone[1][c1+15+14*(n-1)+ 2] = n-1; 1856 crbl->cone[1][c1+15+14*(n-1)+ 3] = DM_POLYTOPE_SEGMENT; 1857 crbl->cone[1][c1+15+14*(n-1)+ 4] = 1; 1858 crbl->cone[1][c1+15+14*(n-1)+ 5] = 1; 1859 crbl->cone[1][c1+15+14*(n-1)+ 6] = 0; 1860 crbl->cone[1][c1+15+14*(n-1)+ 7] = DM_POLYTOPE_POINT_PRISM_TENSOR; 1861 crbl->cone[1][c1+15+14*(n-1)+ 8] = 1; 1862 crbl->cone[1][c1+15+14*(n-1)+ 9] = 2; 1863 crbl->cone[1][c1+15+14*(n-1)+10] = n; 1864 crbl->cone[1][c1+15+14*(n-1)+11] = DM_POLYTOPE_POINT_PRISM_TENSOR; 1865 crbl->cone[1][c1+15+14*(n-1)+12] = 1; 1866 crbl->cone[1][c1+15+14*(n-1)+13] = 3; 1867 crbl->cone[1][c1+15+14*(n-1)+14] = n; 1868 for (i = 0; i < o1+o2; i++) crbl->ornt[1][i] = 0; 1869 1870 /* DM_POLYTOPE_TRI_PRISM_TENSOR produces n triangles and n+1 tensor triangular prisms */ 1871 c1 = 12*n; 1872 c2 = 38+18*(n-1); 1873 o1 = 3*n; 1874 o2 = 5*(n+1); 1875 crbl->Nt[2] = 2; 1876 1877 ierr = PetscMalloc4(crbl->Nt[2],&crbl->target[2],crbl->Nt[2],&crbl->size[2],c1+c2,&crbl->cone[2],o1+o2,&crbl->ornt[2]);CHKERRQ(ierr); 1878 1879 crbl->target[2][0] = DM_POLYTOPE_TRIANGLE; 1880 crbl->target[2][1] = DM_POLYTOPE_TRI_PRISM_TENSOR; 1881 1882 crbl->size[2][0] = n; 1883 crbl->size[2][1] = n+1; 1884 1885 /* the triangles */ 1886 for (i = 0; i < n; i++) { 1887 crbl->cone[2][12*i+ 0] = DM_POLYTOPE_SEGMENT; 1888 crbl->cone[2][12*i+ 1] = 1; 1889 crbl->cone[2][12*i+ 2] = 2; 1890 crbl->cone[2][12*i+ 3] = i; 1891 crbl->cone[2][12*i+ 4] = DM_POLYTOPE_SEGMENT; 1892 crbl->cone[2][12*i+ 5] = 1; 1893 crbl->cone[2][12*i+ 6] = 3; 1894 crbl->cone[2][12*i+ 7] = i; 1895 crbl->cone[2][12*i+ 8] = DM_POLYTOPE_SEGMENT; 1896 crbl->cone[2][12*i+ 9] = 1; 1897 crbl->cone[2][12*i+10] = 4; 1898 crbl->cone[2][12*i+11] = i; 1899 } 1900 1901 /* the triangular prisms */ 1902 crbl->cone[2][c1+ 0] = DM_POLYTOPE_TRIANGLE; 1903 crbl->cone[2][c1+ 1] = 1; 1904 crbl->cone[2][c1+ 2] = 0; 1905 crbl->cone[2][c1+ 3] = 0; 1906 crbl->cone[2][c1+ 4] = DM_POLYTOPE_TRIANGLE; 1907 crbl->cone[2][c1+ 5] = 0; 1908 crbl->cone[2][c1+ 6] = 0; 1909 crbl->cone[2][c1+ 7] = DM_POLYTOPE_SEG_PRISM_TENSOR; 1910 crbl->cone[2][c1+ 8] = 1; 1911 crbl->cone[2][c1+ 9] = 2; 1912 crbl->cone[2][c1+10] = 0; 1913 crbl->cone[2][c1+11] = DM_POLYTOPE_SEG_PRISM_TENSOR; 1914 crbl->cone[2][c1+12] = 1; 1915 crbl->cone[2][c1+13] = 3; 1916 crbl->cone[2][c1+14] = 0; 1917 crbl->cone[2][c1+15] = DM_POLYTOPE_SEG_PRISM_TENSOR; 1918 crbl->cone[2][c1+16] = 1; 1919 crbl->cone[2][c1+17] = 4; 1920 crbl->cone[2][c1+18] = 0; 1921 for (i = 0; i < n-1; i++) { 1922 crbl->cone[2][c1+19+18*i+ 0] = DM_POLYTOPE_TRIANGLE; 1923 crbl->cone[2][c1+19+18*i+ 1] = 0; 1924 crbl->cone[2][c1+19+18*i+ 2] = i; 1925 crbl->cone[2][c1+19+18*i+ 3] = DM_POLYTOPE_TRIANGLE; 1926 crbl->cone[2][c1+19+18*i+ 4] = 0; 1927 crbl->cone[2][c1+19+18*i+ 5] = i+1; 1928 crbl->cone[2][c1+19+18*i+ 6] = DM_POLYTOPE_SEG_PRISM_TENSOR; 1929 crbl->cone[2][c1+19+18*i+ 7] = 1; 1930 crbl->cone[2][c1+19+18*i+ 8] = 2; 1931 crbl->cone[2][c1+19+18*i+ 9] = i+1; 1932 crbl->cone[2][c1+19+18*i+10] = DM_POLYTOPE_SEG_PRISM_TENSOR; 1933 crbl->cone[2][c1+19+18*i+11] = 1; 1934 crbl->cone[2][c1+19+18*i+12] = 3; 1935 crbl->cone[2][c1+19+18*i+13] = i+1; 1936 crbl->cone[2][c1+19+18*i+14] = DM_POLYTOPE_SEG_PRISM_TENSOR; 1937 crbl->cone[2][c1+19+18*i+15] = 1; 1938 crbl->cone[2][c1+19+18*i+16] = 4; 1939 crbl->cone[2][c1+19+18*i+17] = i+1; 1940 } 1941 crbl->cone[2][c1+19+18*(n-1)+ 0] = DM_POLYTOPE_TRIANGLE; 1942 crbl->cone[2][c1+19+18*(n-1)+ 1] = 0; 1943 crbl->cone[2][c1+19+18*(n-1)+ 2] = n-1; 1944 crbl->cone[2][c1+19+18*(n-1)+ 3] = DM_POLYTOPE_TRIANGLE; 1945 crbl->cone[2][c1+19+18*(n-1)+ 4] = 1; 1946 crbl->cone[2][c1+19+18*(n-1)+ 5] = 1; 1947 crbl->cone[2][c1+19+18*(n-1)+ 6] = 0; 1948 crbl->cone[2][c1+19+18*(n-1)+ 7] = DM_POLYTOPE_SEG_PRISM_TENSOR; 1949 crbl->cone[2][c1+19+18*(n-1)+ 8] = 1; 1950 crbl->cone[2][c1+19+18*(n-1)+ 9] = 2; 1951 crbl->cone[2][c1+19+18*(n-1)+10] = n; 1952 crbl->cone[2][c1+19+18*(n-1)+11] = DM_POLYTOPE_SEG_PRISM_TENSOR; 1953 crbl->cone[2][c1+19+18*(n-1)+12] = 1; 1954 crbl->cone[2][c1+19+18*(n-1)+13] = 3; 1955 crbl->cone[2][c1+19+18*(n-1)+14] = n; 1956 crbl->cone[2][c1+19+18*(n-1)+15] = DM_POLYTOPE_SEG_PRISM_TENSOR; 1957 crbl->cone[2][c1+19+18*(n-1)+16] = 1; 1958 crbl->cone[2][c1+19+18*(n-1)+17] = 4; 1959 crbl->cone[2][c1+19+18*(n-1)+18] = n; 1960 for (i = 0; i < o1+o2; i++) crbl->ornt[2][i] = 0; 1961 1962 /* DM_POLYTOPE_QUAD_PRISM_TENSOR produces n quads and n+1 tensor quad prisms */ 1963 c1 = 16*n; 1964 c2 = 46+22*(n-1); 1965 o1 = 4*n; 1966 o2 = 6*(n+1); 1967 crbl->Nt[3] = 2; 1968 1969 ierr = PetscMalloc4(crbl->Nt[3],&crbl->target[3],crbl->Nt[3],&crbl->size[3],c1+c2,&crbl->cone[3],o1+o2,&crbl->ornt[3]);CHKERRQ(ierr); 1970 1971 crbl->target[3][0] = DM_POLYTOPE_QUADRILATERAL; 1972 crbl->target[3][1] = DM_POLYTOPE_QUAD_PRISM_TENSOR; 1973 1974 crbl->size[3][0] = n; 1975 crbl->size[3][1] = n+1; 1976 1977 /* the quads */ 1978 for (i = 0; i < n; i++) { 1979 crbl->cone[3][16*i+ 0] = DM_POLYTOPE_SEGMENT; 1980 crbl->cone[3][16*i+ 1] = 1; 1981 crbl->cone[3][16*i+ 2] = 2; 1982 crbl->cone[3][16*i+ 3] = i; 1983 crbl->cone[3][16*i+ 4] = DM_POLYTOPE_SEGMENT; 1984 crbl->cone[3][16*i+ 5] = 1; 1985 crbl->cone[3][16*i+ 6] = 3; 1986 crbl->cone[3][16*i+ 7] = i; 1987 crbl->cone[3][16*i+ 8] = DM_POLYTOPE_SEGMENT; 1988 crbl->cone[3][16*i+ 9] = 1; 1989 crbl->cone[3][16*i+10] = 4; 1990 crbl->cone[3][16*i+11] = i; 1991 crbl->cone[3][16*i+12] = DM_POLYTOPE_SEGMENT; 1992 crbl->cone[3][16*i+13] = 1; 1993 crbl->cone[3][16*i+14] = 5; 1994 crbl->cone[3][16*i+15] = i; 1995 } 1996 1997 /* the quad prisms */ 1998 crbl->cone[3][c1+ 0] = DM_POLYTOPE_QUADRILATERAL; 1999 crbl->cone[3][c1+ 1] = 1; 2000 crbl->cone[3][c1+ 2] = 0; 2001 crbl->cone[3][c1+ 3] = 0; 2002 crbl->cone[3][c1+ 4] = DM_POLYTOPE_QUADRILATERAL; 2003 crbl->cone[3][c1+ 5] = 0; 2004 crbl->cone[3][c1+ 6] = 0; 2005 crbl->cone[3][c1+ 7] = DM_POLYTOPE_SEG_PRISM_TENSOR; 2006 crbl->cone[3][c1+ 8] = 1; 2007 crbl->cone[3][c1+ 9] = 2; 2008 crbl->cone[3][c1+10] = 0; 2009 crbl->cone[3][c1+11] = DM_POLYTOPE_SEG_PRISM_TENSOR; 2010 crbl->cone[3][c1+12] = 1; 2011 crbl->cone[3][c1+13] = 3; 2012 crbl->cone[3][c1+14] = 0; 2013 crbl->cone[3][c1+15] = DM_POLYTOPE_SEG_PRISM_TENSOR; 2014 crbl->cone[3][c1+16] = 1; 2015 crbl->cone[3][c1+17] = 4; 2016 crbl->cone[3][c1+18] = 0; 2017 crbl->cone[3][c1+19] = DM_POLYTOPE_SEG_PRISM_TENSOR; 2018 crbl->cone[3][c1+20] = 1; 2019 crbl->cone[3][c1+21] = 5; 2020 crbl->cone[3][c1+22] = 0; 2021 for (i = 0; i < n-1; i++) { 2022 crbl->cone[3][c1+23+22*i+ 0] = DM_POLYTOPE_QUADRILATERAL; 2023 crbl->cone[3][c1+23+22*i+ 1] = 0; 2024 crbl->cone[3][c1+23+22*i+ 2] = i; 2025 crbl->cone[3][c1+23+22*i+ 3] = DM_POLYTOPE_QUADRILATERAL; 2026 crbl->cone[3][c1+23+22*i+ 4] = 0; 2027 crbl->cone[3][c1+23+22*i+ 5] = i+1; 2028 crbl->cone[3][c1+23+22*i+ 6] = DM_POLYTOPE_SEG_PRISM_TENSOR; 2029 crbl->cone[3][c1+23+22*i+ 7] = 1; 2030 crbl->cone[3][c1+23+22*i+ 8] = 2; 2031 crbl->cone[3][c1+23+22*i+ 9] = i+1; 2032 crbl->cone[3][c1+23+22*i+10] = DM_POLYTOPE_SEG_PRISM_TENSOR; 2033 crbl->cone[3][c1+23+22*i+11] = 1; 2034 crbl->cone[3][c1+23+22*i+12] = 3; 2035 crbl->cone[3][c1+23+22*i+13] = i+1; 2036 crbl->cone[3][c1+23+22*i+14] = DM_POLYTOPE_SEG_PRISM_TENSOR; 2037 crbl->cone[3][c1+23+22*i+15] = 1; 2038 crbl->cone[3][c1+23+22*i+16] = 4; 2039 crbl->cone[3][c1+23+22*i+17] = i+1; 2040 crbl->cone[3][c1+23+22*i+18] = DM_POLYTOPE_SEG_PRISM_TENSOR; 2041 crbl->cone[3][c1+23+22*i+19] = 1; 2042 crbl->cone[3][c1+23+22*i+20] = 5; 2043 crbl->cone[3][c1+23+22*i+21] = i+1; 2044 } 2045 crbl->cone[3][c1+23+22*(n-1)+ 0] = DM_POLYTOPE_QUADRILATERAL; 2046 crbl->cone[3][c1+23+22*(n-1)+ 1] = 0; 2047 crbl->cone[3][c1+23+22*(n-1)+ 2] = n-1; 2048 crbl->cone[3][c1+23+22*(n-1)+ 3] = DM_POLYTOPE_QUADRILATERAL; 2049 crbl->cone[3][c1+23+22*(n-1)+ 4] = 1; 2050 crbl->cone[3][c1+23+22*(n-1)+ 5] = 1; 2051 crbl->cone[3][c1+23+22*(n-1)+ 6] = 0; 2052 crbl->cone[3][c1+23+22*(n-1)+ 7] = DM_POLYTOPE_SEG_PRISM_TENSOR; 2053 crbl->cone[3][c1+23+22*(n-1)+ 8] = 1; 2054 crbl->cone[3][c1+23+22*(n-1)+ 9] = 2; 2055 crbl->cone[3][c1+23+22*(n-1)+10] = n; 2056 crbl->cone[3][c1+23+22*(n-1)+11] = DM_POLYTOPE_SEG_PRISM_TENSOR; 2057 crbl->cone[3][c1+23+22*(n-1)+12] = 1; 2058 crbl->cone[3][c1+23+22*(n-1)+13] = 3; 2059 crbl->cone[3][c1+23+22*(n-1)+14] = n; 2060 crbl->cone[3][c1+23+22*(n-1)+15] = DM_POLYTOPE_SEG_PRISM_TENSOR; 2061 crbl->cone[3][c1+23+22*(n-1)+16] = 1; 2062 crbl->cone[3][c1+23+22*(n-1)+17] = 4; 2063 crbl->cone[3][c1+23+22*(n-1)+18] = n; 2064 crbl->cone[3][c1+23+22*(n-1)+19] = DM_POLYTOPE_SEG_PRISM_TENSOR; 2065 crbl->cone[3][c1+23+22*(n-1)+20] = 1; 2066 crbl->cone[3][c1+23+22*(n-1)+21] = 5; 2067 crbl->cone[3][c1+23+22*(n-1)+22] = n; 2068 for (i = 0; i < o1+o2; i++) crbl->ornt[3][i] = 0; 2069 PetscFunctionReturn(0); 2070 } 2071 2072 static PetscErrorCode DMPlexCellRefinerDestroy_BL(DMPlexCellRefiner cr) 2073 { 2074 PlexRefiner_BL *crbl = (PlexRefiner_BL *)cr->data; 2075 PetscErrorCode ierr; 2076 2077 PetscFunctionBegin; 2078 ierr = PetscFree4(crbl->target[0],crbl->size[0],crbl->cone[0],crbl->ornt[0]);CHKERRQ(ierr); 2079 ierr = PetscFree4(crbl->target[1],crbl->size[1],crbl->cone[1],crbl->ornt[1]);CHKERRQ(ierr); 2080 ierr = PetscFree4(crbl->target[2],crbl->size[2],crbl->cone[2],crbl->ornt[2]);CHKERRQ(ierr); 2081 ierr = PetscFree4(crbl->target[3],crbl->size[3],crbl->cone[3],crbl->ornt[3]);CHKERRQ(ierr); 2082 ierr = PetscFree5(crbl->Nt,crbl->target,crbl->size,crbl->cone,crbl->ornt);CHKERRQ(ierr); 2083 ierr = PetscFree(crbl->h);CHKERRQ(ierr); 2084 ierr = PetscFree(cr->data);CHKERRQ(ierr); 2085 PetscFunctionReturn(0); 2086 } 2087 2088 static PetscErrorCode DMPlexCellRefinerRefine_BL(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[]) 2089 { 2090 PlexRefiner_BL *crbl = (PlexRefiner_BL *)cr->data; 2091 PetscErrorCode ierr; 2092 2093 PetscFunctionBeginHot; 2094 if (rt) *rt = 0; 2095 switch (source) { 2096 case DM_POLYTOPE_POINT_PRISM_TENSOR: 2097 *Nt = crbl->Nt[0]; 2098 *target = crbl->target[0]; 2099 *size = crbl->size[0]; 2100 *cone = crbl->cone[0]; 2101 *ornt = crbl->ornt[0]; 2102 break; 2103 case DM_POLYTOPE_SEG_PRISM_TENSOR: 2104 *Nt = crbl->Nt[1]; 2105 *target = crbl->target[1]; 2106 *size = crbl->size[1]; 2107 *cone = crbl->cone[1]; 2108 *ornt = crbl->ornt[1]; 2109 break; 2110 case DM_POLYTOPE_TRI_PRISM_TENSOR: 2111 *Nt = crbl->Nt[2]; 2112 *target = crbl->target[2]; 2113 *size = crbl->size[2]; 2114 *cone = crbl->cone[2]; 2115 *ornt = crbl->ornt[2]; 2116 break; 2117 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 2118 *Nt = crbl->Nt[3]; 2119 *target = crbl->target[3]; 2120 *size = crbl->size[3]; 2121 *cone = crbl->cone[3]; 2122 *ornt = crbl->ornt[3]; 2123 break; 2124 default: 2125 ierr = DMPlexCellRefinerRefine_None(cr,source,p,rt,Nt,target,size,cone,ornt);CHKERRQ(ierr); 2126 } 2127 PetscFunctionReturn(0); 2128 } 2129 2130 static PetscErrorCode DMPlexCellRefinerMapSubcells_BL(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt pp, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew) 2131 { 2132 /* We shift any input orientation in order to make it non-negative 2133 The orientation array o[po][o] gives the orientation the new replica rnew has to have in order to reproduce the face sequence from (r, o) 2134 The replica array r[po][r] gives the new replica number rnew given that the parent point has orientation po 2135 Overall, replica (r, o) in a parent with orientation 0 matches replica (rnew, onew) in a parent with orientation po 2136 */ 2137 PetscInt tquad_seg_o[] = { 0, 1, -2, -1, 2138 0, 1, -2, -1, 2139 -2, -1, 0, 1, 2140 -2, -1, 0, 1}; 2141 PetscInt tquad_tquad_o[] = { 0, 1, -2, -1, 2142 1, 0, -1, -2, 2143 -2, -1, 0, 1, 2144 -1, -2, 1, 0}; 2145 PlexRefiner_BL *crbl = (PlexRefiner_BL *)cr->data; 2146 const PetscInt n = crbl->n; 2147 PetscErrorCode ierr; 2148 2149 PetscFunctionBeginHot; 2150 *rnew = r; 2151 *onew = o; 2152 switch (pct) { 2153 case DM_POLYTOPE_POINT_PRISM_TENSOR: 2154 if (ct == DM_POLYTOPE_POINT_PRISM_TENSOR) { 2155 if (po == 0 || po == -1) {*rnew = r; *onew = o;} 2156 else if (po == 1 || po == -2) {*rnew = n - r; *onew = (o == 0 || o == -1) ? -2 : 0;} 2157 else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid orientation %D for tensor segment", po); 2158 } 2159 break; 2160 case DM_POLYTOPE_SEG_PRISM_TENSOR: 2161 switch (ct) { 2162 case DM_POLYTOPE_SEGMENT: 2163 *onew = tquad_seg_o[(po+2)*4+o+2]; 2164 *rnew = r; 2165 break; 2166 case DM_POLYTOPE_SEG_PRISM_TENSOR: 2167 *onew = tquad_tquad_o[(po+2)*4+o+2]; 2168 *rnew = r; 2169 break; 2170 default: break; 2171 } 2172 break; 2173 default: 2174 ierr = DMPlexCellRefinerMapSubcells_None(cr, pct, pp, po, ct, r, o, rnew, onew);CHKERRQ(ierr); 2175 } 2176 PetscFunctionReturn(0); 2177 } 2178 2179 static PetscErrorCode DMPlexCellRefinerMapCoordinates_BL(DMPlexCellRefiner cr, DMPolytopeType pct, DMPolytopeType ct, PetscInt r, PetscInt Nv, PetscInt dE, const PetscScalar in[], PetscScalar out[]) 2180 { 2181 PlexRefiner_BL *crbl = (PlexRefiner_BL *)cr->data; 2182 PetscInt d; 2183 PetscErrorCode ierr; 2184 2185 PetscFunctionBeginHot; 2186 switch (pct) { 2187 case DM_POLYTOPE_POINT_PRISM_TENSOR: 2188 if (ct != DM_POLYTOPE_POINT) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for refined point type %s",DMPolytopeTypes[ct]); 2189 if (Nv != 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for parent vertices %D",Nv); 2190 if (r >= crbl->n || r < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Invalid replica %D, must be in [0,%D)",r,crbl->n); 2191 for (d = 0; d < dE; d++) out[d] = in[d] + crbl->h[r] * (in[d + dE] - in[d]); 2192 break; 2193 default: 2194 ierr = DMPlexCellRefinerMapCoordinates_Barycenter(cr,pct,ct,r,Nv,dE,in,out);CHKERRQ(ierr); 2195 } 2196 PetscFunctionReturn(0); 2197 } 2198 2199 typedef struct { 2200 DMLabel splitPoints; /* List of edges to be bisected (1) and cells to be divided (2) */ 2201 PetscSection secEdgeLen; /* Section for edge length field */ 2202 PetscReal *edgeLen; /* Storage for edge length field */ 2203 PetscInt *splitArray; /* Array for communication of split points label */ 2204 } PlexRefiner_SBR; 2205 2206 typedef struct _p_PointQueue *PointQueue; 2207 struct _p_PointQueue { 2208 PetscInt size; /* Size of the storage array */ 2209 PetscInt *points; /* Array of mesh points */ 2210 PetscInt front; /* Index of the front of the queue */ 2211 PetscInt back; /* Index of the back of the queue */ 2212 PetscInt num; /* Number of enqueued points */ 2213 }; 2214 2215 static PetscErrorCode PointQueueCreate(PetscInt size, PointQueue *queue) 2216 { 2217 PointQueue q; 2218 PetscErrorCode ierr; 2219 2220 PetscFunctionBegin; 2221 if (size < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Queue size %D must be non-negative", size); 2222 ierr = PetscCalloc1(1, &q);CHKERRQ(ierr); 2223 q->size = size; 2224 ierr = PetscMalloc1(q->size, &q->points);CHKERRQ(ierr); 2225 q->num = 0; 2226 q->front = 0; 2227 q->back = q->size-1; 2228 *queue = q; 2229 PetscFunctionReturn(0); 2230 } 2231 2232 static PetscErrorCode PointQueueDestroy(PointQueue *queue) 2233 { 2234 PointQueue q = *queue; 2235 PetscErrorCode ierr; 2236 2237 PetscFunctionBegin; 2238 ierr = PetscFree(q->points);CHKERRQ(ierr); 2239 ierr = PetscFree(q);CHKERRQ(ierr); 2240 *queue = NULL; 2241 PetscFunctionReturn(0); 2242 } 2243 2244 static PetscErrorCode PointQueueEnsureSize(PointQueue queue) 2245 { 2246 PetscErrorCode ierr; 2247 2248 PetscFunctionBegin; 2249 if (queue->num < queue->size) PetscFunctionReturn(0); 2250 queue->size *= 2; 2251 ierr = PetscRealloc(queue->size * sizeof(PetscInt), &queue->points);CHKERRQ(ierr); 2252 PetscFunctionReturn(0); 2253 } 2254 2255 static PetscErrorCode PointQueueEnqueue(PointQueue queue, PetscInt p) 2256 { 2257 PetscErrorCode ierr; 2258 2259 PetscFunctionBegin; 2260 ierr = PointQueueEnsureSize(queue);CHKERRQ(ierr); 2261 queue->back = (queue->back + 1) % queue->size; 2262 queue->points[queue->back] = p; 2263 ++queue->num; 2264 PetscFunctionReturn(0); 2265 } 2266 2267 static PetscErrorCode PointQueueDequeue(PointQueue queue, PetscInt *p) 2268 { 2269 PetscFunctionBegin; 2270 if (!queue->num) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot dequeue from an empty queue"); 2271 *p = queue->points[queue->front]; 2272 queue->front = (queue->front + 1) % queue->size; 2273 --queue->num; 2274 PetscFunctionReturn(0); 2275 } 2276 2277 #if 0 2278 static PetscErrorCode PointQueueFront(PointQueue queue, PetscInt *p) 2279 { 2280 PetscFunctionBegin; 2281 if (!queue->num) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot get the front of an empty queue"); 2282 *p = queue->points[queue->front]; 2283 PetscFunctionReturn(0); 2284 } 2285 2286 static PetscErrorCode PointQueueBack(PointQueue queue, PetscInt *p) 2287 { 2288 PetscFunctionBegin; 2289 if (!queue->num) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot get the back of an empty queue"); 2290 *p = queue->points[queue->back]; 2291 PetscFunctionReturn(0); 2292 } 2293 #endif 2294 2295 PETSC_STATIC_INLINE PetscBool PointQueueEmpty(PointQueue queue) 2296 { 2297 if (!queue->num) return PETSC_TRUE; 2298 return PETSC_FALSE; 2299 } 2300 2301 static PetscErrorCode SBRGetEdgeLen_Private(DMPlexCellRefiner cr, PetscInt edge, PetscReal *len) 2302 { 2303 PlexRefiner_SBR *sbr = (PlexRefiner_SBR *) cr->data; 2304 DM dm = cr->dm; 2305 PetscInt off; 2306 PetscErrorCode ierr; 2307 2308 PetscFunctionBeginHot; 2309 ierr = PetscSectionGetOffset(sbr->secEdgeLen, edge, &off);CHKERRQ(ierr); 2310 if (sbr->edgeLen[off] <= 0.0) { 2311 DM cdm; 2312 Vec coordsLocal; 2313 const PetscScalar *coords; 2314 const PetscInt *cone; 2315 PetscScalar *cA, *cB; 2316 PetscInt coneSize, cdim; 2317 2318 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 2319 ierr = DMPlexGetCone(dm, edge, &cone);CHKERRQ(ierr); 2320 ierr = DMPlexGetConeSize(dm, edge, &coneSize);CHKERRQ(ierr); 2321 if (coneSize != 2) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Edge %D cone size must be 2, not %D", edge, coneSize); 2322 ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr); 2323 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 2324 ierr = VecGetArrayRead(coordsLocal, &coords);CHKERRQ(ierr); 2325 ierr = DMPlexPointLocalRead(cdm, cone[0], coords, &cA);CHKERRQ(ierr); 2326 ierr = DMPlexPointLocalRead(cdm, cone[1], coords, &cB);CHKERRQ(ierr); 2327 sbr->edgeLen[off] = DMPlex_DistD_Internal(cdim, cA, cB); 2328 ierr = VecRestoreArrayRead(coordsLocal, &coords);CHKERRQ(ierr); 2329 } 2330 *len = sbr->edgeLen[off]; 2331 PetscFunctionReturn(0); 2332 } 2333 2334 /* Mark local edges that should be split */ 2335 /* TODO This will not work in 3D */ 2336 static PetscErrorCode SBRSplitLocalEdges_Private(DMPlexCellRefiner cr, PointQueue queue) 2337 { 2338 PlexRefiner_SBR *sbr = (PlexRefiner_SBR *) cr->data; 2339 DM dm = cr->dm; 2340 PetscErrorCode ierr; 2341 2342 PetscFunctionBegin; 2343 while (!PointQueueEmpty(queue)) { 2344 PetscInt p = -1; 2345 const PetscInt *support; 2346 PetscInt supportSize, s; 2347 2348 ierr = PointQueueDequeue(queue, &p);CHKERRQ(ierr); 2349 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 2350 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2351 for (s = 0; s < supportSize; ++s) { 2352 const PetscInt cell = support[s]; 2353 const PetscInt *cone; 2354 PetscInt coneSize, c; 2355 PetscInt cval, eval, maxedge; 2356 PetscReal len, maxlen; 2357 2358 ierr = DMLabelGetValue(sbr->splitPoints, cell, &cval);CHKERRQ(ierr); 2359 if (cval == 2) continue; 2360 ierr = DMPlexGetCone(dm, cell, &cone);CHKERRQ(ierr); 2361 ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 2362 ierr = SBRGetEdgeLen_Private(cr, cone[0], &maxlen);CHKERRQ(ierr); 2363 maxedge = cone[0]; 2364 for (c = 1; c < coneSize; ++c) { 2365 ierr = SBRGetEdgeLen_Private(cr, cone[c], &len);CHKERRQ(ierr); 2366 if (len > maxlen) {maxlen = len; maxedge = cone[c];} 2367 } 2368 ierr = DMLabelGetValue(sbr->splitPoints, maxedge, &eval);CHKERRQ(ierr); 2369 if (eval != 1) { 2370 ierr = DMLabelSetValue(sbr->splitPoints, maxedge, 1);CHKERRQ(ierr); 2371 ierr = PointQueueEnqueue(queue, maxedge);CHKERRQ(ierr); 2372 } 2373 ierr = DMLabelSetValue(sbr->splitPoints, cell, 2);CHKERRQ(ierr); 2374 } 2375 } 2376 PetscFunctionReturn(0); 2377 } 2378 2379 static PetscErrorCode SBRInitializeComm(DMPlexCellRefiner cr, PetscSF pointSF) 2380 { 2381 PlexRefiner_SBR *sbr = (PlexRefiner_SBR *) cr->data; 2382 DMLabel splitPoints = sbr->splitPoints; 2383 PetscInt *splitArray = sbr->splitArray; 2384 const PetscInt *degree; 2385 const PetscInt *points; 2386 PetscInt Nl, l, pStart, pEnd, p, val; 2387 PetscErrorCode ierr; 2388 2389 PetscFunctionBegin; 2390 /* Add in leaves */ 2391 ierr = PetscSFGetGraph(pointSF, NULL, &Nl, &points, NULL);CHKERRQ(ierr); 2392 for (l = 0; l < Nl; ++l) { 2393 ierr = DMLabelGetValue(splitPoints, points[l], &val);CHKERRQ(ierr); 2394 if (val > 0) splitArray[points[l]] = val; 2395 } 2396 /* Add in shared roots */ 2397 ierr = PetscSFComputeDegreeBegin(pointSF, °ree);CHKERRQ(ierr); 2398 ierr = PetscSFComputeDegreeEnd(pointSF, °ree);CHKERRQ(ierr); 2399 ierr = DMPlexGetChart(cr->dm, &pStart, &pEnd);CHKERRQ(ierr); 2400 for (p = pStart; p < pEnd; ++p) { 2401 if (degree[p]) { 2402 ierr = DMLabelGetValue(splitPoints, p, &val);CHKERRQ(ierr); 2403 if (val > 0) splitArray[p] = val; 2404 } 2405 } 2406 PetscFunctionReturn(0); 2407 } 2408 2409 static PetscErrorCode SBRFinalizeComm(DMPlexCellRefiner cr, PetscSF pointSF, PointQueue queue) 2410 { 2411 PlexRefiner_SBR *sbr = (PlexRefiner_SBR *) cr->data; 2412 DMLabel splitPoints = sbr->splitPoints; 2413 PetscInt *splitArray = sbr->splitArray; 2414 const PetscInt *degree; 2415 const PetscInt *points; 2416 PetscInt Nl, l, pStart, pEnd, p, val; 2417 PetscErrorCode ierr; 2418 2419 PetscFunctionBegin; 2420 /* Read out leaves */ 2421 ierr = PetscSFGetGraph(pointSF, NULL, &Nl, &points, NULL);CHKERRQ(ierr); 2422 for (l = 0; l < Nl; ++l) { 2423 const PetscInt p = points[l]; 2424 const PetscInt cval = splitArray[p]; 2425 2426 if (cval) { 2427 ierr = DMLabelGetValue(splitPoints, p, &val);CHKERRQ(ierr); 2428 if (val <= 0) { 2429 ierr = DMLabelSetValue(splitPoints, p, cval);CHKERRQ(ierr); 2430 ierr = PointQueueEnqueue(queue, p);CHKERRQ(ierr); 2431 } 2432 } 2433 } 2434 /* Read out shared roots */ 2435 ierr = PetscSFComputeDegreeBegin(pointSF, °ree);CHKERRQ(ierr); 2436 ierr = PetscSFComputeDegreeEnd(pointSF, °ree);CHKERRQ(ierr); 2437 ierr = DMPlexGetChart(cr->dm, &pStart, &pEnd);CHKERRQ(ierr); 2438 for (p = pStart; p < pEnd; ++p) { 2439 if (degree[p]) { 2440 const PetscInt cval = splitArray[p]; 2441 2442 if (cval) { 2443 ierr = DMLabelGetValue(splitPoints, p, &val);CHKERRQ(ierr); 2444 if (val <= 0) { 2445 ierr = DMLabelSetValue(splitPoints, p, cval);CHKERRQ(ierr); 2446 ierr = PointQueueEnqueue(queue, p);CHKERRQ(ierr); 2447 } 2448 } 2449 } 2450 } 2451 PetscFunctionReturn(0); 2452 } 2453 2454 static PetscErrorCode DMPlexCellRefinerSetUp_SBR(DMPlexCellRefiner cr) 2455 { 2456 PlexRefiner_SBR *sbr; 2457 PetscSF pointSF; 2458 PointQueue queue = NULL; 2459 IS refineIS; 2460 const PetscInt *refineCells; 2461 PetscMPIInt size; 2462 PetscInt pStart, pEnd, p, eStart, eEnd, e, edgeLenSize, Nc, c; 2463 PetscBool empty; 2464 PetscErrorCode ierr; 2465 2466 PetscFunctionBegin; 2467 ierr = PetscCitationsRegister(SBRCitation, &SBRcite);CHKERRQ(ierr); 2468 ierr = PetscNew(&sbr);CHKERRQ(ierr); 2469 cr->data = sbr; 2470 ierr = DMLabelCreate(PETSC_COMM_SELF, "Split Points", &sbr->splitPoints);CHKERRQ(ierr); 2471 /* Create edge lengths */ 2472 ierr = DMPlexGetDepthStratum(cr->dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 2473 ierr = PetscSectionCreate(PETSC_COMM_SELF, &sbr->secEdgeLen);CHKERRQ(ierr); 2474 ierr = PetscSectionSetChart(sbr->secEdgeLen, eStart, eEnd);CHKERRQ(ierr); 2475 for (e = eStart; e < eEnd; ++e) { 2476 ierr = PetscSectionSetDof(sbr->secEdgeLen, e, 1);CHKERRQ(ierr); 2477 } 2478 ierr = PetscSectionSetUp(sbr->secEdgeLen);CHKERRQ(ierr); 2479 ierr = PetscSectionGetStorageSize(sbr->secEdgeLen, &edgeLenSize);CHKERRQ(ierr); 2480 ierr = PetscCalloc1(edgeLenSize, &sbr->edgeLen);CHKERRQ(ierr); 2481 /* Add edges of cells that are marked for refinement to edge queue */ 2482 if (!cr->adaptLabel) SETERRQ(PetscObjectComm((PetscObject) cr), PETSC_ERR_ARG_WRONGSTATE, "CellRefiner must have an adaptation label in order to use SBR algorithm"); 2483 ierr = PointQueueCreate(1024, &queue);CHKERRQ(ierr); 2484 ierr = DMLabelGetStratumIS(cr->adaptLabel, DM_ADAPT_REFINE, &refineIS);CHKERRQ(ierr); 2485 ierr = DMLabelGetStratumSize(cr->adaptLabel, DM_ADAPT_REFINE, &Nc);CHKERRQ(ierr); 2486 if (refineIS) {ierr = ISGetIndices(refineIS, &refineCells);CHKERRQ(ierr);} 2487 for (c = 0; c < Nc; ++c) { 2488 PetscInt *closure = NULL; 2489 PetscInt Ncl, cl; 2490 2491 ierr = DMLabelSetValue(sbr->splitPoints, refineCells[c], 2);CHKERRQ(ierr); 2492 ierr = DMPlexGetTransitiveClosure(cr->dm, refineCells[c], PETSC_TRUE, &Ncl, &closure);CHKERRQ(ierr); 2493 for (cl = 0; cl < Ncl; cl += 2) { 2494 const PetscInt edge = closure[cl]; 2495 2496 if (edge >= eStart && edge < eEnd) { 2497 ierr = DMLabelSetValue(sbr->splitPoints, edge, 1);CHKERRQ(ierr); 2498 ierr = PointQueueEnqueue(queue, edge);CHKERRQ(ierr); 2499 } 2500 } 2501 ierr = DMPlexRestoreTransitiveClosure(cr->dm, refineCells[c], PETSC_TRUE, &Ncl, &closure);CHKERRQ(ierr); 2502 } 2503 if (refineIS) {ierr = ISRestoreIndices(refineIS, &refineCells);CHKERRQ(ierr);} 2504 ierr = ISDestroy(&refineIS);CHKERRQ(ierr); 2505 /* Setup communication */ 2506 ierr = MPI_Comm_size(PetscObjectComm((PetscObject) cr->dm), &size);CHKERRMPI(ierr); 2507 ierr = DMGetPointSF(cr->dm, &pointSF);CHKERRQ(ierr); 2508 if (size > 1) { 2509 PetscInt pStart, pEnd; 2510 2511 ierr = DMPlexGetChart(cr->dm, &pStart, &pEnd);CHKERRQ(ierr); 2512 ierr = PetscCalloc1(pEnd-pStart, &sbr->splitArray);CHKERRQ(ierr); 2513 } 2514 /* While edge queue is not empty: */ 2515 empty = PointQueueEmpty(queue); 2516 ierr = MPI_Allreduce(MPI_IN_PLACE, &empty, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject) cr->dm));CHKERRMPI(ierr); 2517 while (!empty) { 2518 ierr = SBRSplitLocalEdges_Private(cr, queue);CHKERRQ(ierr); 2519 /* Communicate marked edges 2520 An easy implementation is to allocate an array the size of the number of points. We put the splitPoints marks into the 2521 array, and then call PetscSFReduce()+PetscSFBcast() to make the marks consistent. 2522 2523 TODO: We could use in-place communication with a different SF 2524 We use MPI_SUM for the Reduce, and check the result against the rootdegree. If sum >= rootdegree+1, then the edge has 2525 already been marked. If not, it might have been handled on the process in this round, but we add it anyway. 2526 2527 In order to update the queue with the new edges from the label communication, we use BcastAnOp(MPI_SUM), so that new 2528 values will have 1+0=1 and old values will have 1+1=2. Loop over these, resetting the values to 1, and adding any new 2529 edge to the queue. 2530 */ 2531 if (size > 1) { 2532 ierr = SBRInitializeComm(cr, pointSF);CHKERRQ(ierr); 2533 ierr = PetscSFReduceBegin(pointSF, MPIU_INT, sbr->splitArray, sbr->splitArray, MPI_MAX);CHKERRQ(ierr); 2534 ierr = PetscSFReduceEnd(pointSF, MPIU_INT, sbr->splitArray, sbr->splitArray, MPI_MAX);CHKERRQ(ierr); 2535 ierr = PetscSFBcastBegin(pointSF, MPIU_INT, sbr->splitArray, sbr->splitArray,MPI_REPLACE);CHKERRQ(ierr); 2536 ierr = PetscSFBcastEnd(pointSF, MPIU_INT, sbr->splitArray, sbr->splitArray,MPI_REPLACE);CHKERRQ(ierr); 2537 ierr = SBRFinalizeComm(cr, pointSF, queue);CHKERRQ(ierr); 2538 } 2539 empty = PointQueueEmpty(queue); 2540 ierr = MPI_Allreduce(MPI_IN_PLACE, &empty, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject) cr->dm));CHKERRMPI(ierr); 2541 } 2542 ierr = PetscFree(sbr->splitArray);CHKERRQ(ierr); 2543 /* Calculate refineType for each cell */ 2544 ierr = DMLabelCreate(PETSC_COMM_SELF, "Refine Type", &cr->refineType);CHKERRQ(ierr); 2545 ierr = DMPlexGetChart(cr->dm, &pStart, &pEnd);CHKERRQ(ierr); 2546 for (p = pStart; p < pEnd; ++p) { 2547 DMPolytopeType ct; 2548 PetscInt val; 2549 2550 ierr = DMPlexGetCellType(cr->dm, p, &ct);CHKERRQ(ierr); 2551 switch (ct) { 2552 case DM_POLYTOPE_POINT: 2553 ierr = DMLabelSetValue(cr->refineType, p, 0);CHKERRQ(ierr);break; 2554 case DM_POLYTOPE_SEGMENT: 2555 ierr = DMLabelGetValue(sbr->splitPoints, p, &val);CHKERRQ(ierr); 2556 if (val == 1) {ierr = DMLabelSetValue(cr->refineType, p, 2);CHKERRQ(ierr);} 2557 else {ierr = DMLabelSetValue(cr->refineType, p, 1);CHKERRQ(ierr);} 2558 break; 2559 case DM_POLYTOPE_TRIANGLE: 2560 ierr = DMLabelGetValue(sbr->splitPoints, p, &val);CHKERRQ(ierr); 2561 if (val == 2) { 2562 const PetscInt *cone; 2563 PetscReal lens[3]; 2564 PetscInt vals[3], i; 2565 2566 ierr = DMPlexGetCone(cr->dm, p, &cone);CHKERRQ(ierr); 2567 for (i = 0; i < 3; ++i) { 2568 ierr = DMLabelGetValue(sbr->splitPoints, cone[i], &vals[i]);CHKERRQ(ierr); 2569 vals[i] = vals[i] < 0 ? 0 : vals[i]; 2570 ierr = SBRGetEdgeLen_Private(cr, cone[i], &lens[i]);CHKERRQ(ierr); 2571 } 2572 if (vals[0] && vals[1] && vals[2]) {ierr = DMLabelSetValue(cr->refineType, p, 4);CHKERRQ(ierr);} 2573 else if (vals[0] && vals[1]) {ierr = DMLabelSetValue(cr->refineType, p, lens[0] > lens[1] ? 5 : 6);CHKERRQ(ierr);} 2574 else if (vals[1] && vals[2]) {ierr = DMLabelSetValue(cr->refineType, p, lens[1] > lens[2] ? 7 : 8);CHKERRQ(ierr);} 2575 else if (vals[2] && vals[0]) {ierr = DMLabelSetValue(cr->refineType, p, lens[2] > lens[0] ? 9: 10);CHKERRQ(ierr);} 2576 else if (vals[0]) {ierr = DMLabelSetValue(cr->refineType, p, 11);CHKERRQ(ierr);} 2577 else if (vals[1]) {ierr = DMLabelSetValue(cr->refineType, p, 12);CHKERRQ(ierr);} 2578 else if (vals[2]) {ierr = DMLabelSetValue(cr->refineType, p, 13);CHKERRQ(ierr);} 2579 else SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Cell %D does not fit any refinement type (%D, %D, %D)", p, vals[0], vals[1], vals[2]); 2580 } else {ierr = DMLabelSetValue(cr->refineType, p, 3);CHKERRQ(ierr);} 2581 break; 2582 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle points of type %s", DMPolytopeTypes[ct]); 2583 } 2584 ierr = DMLabelGetValue(sbr->splitPoints, p, &val);CHKERRQ(ierr); 2585 } 2586 /* Cleanup */ 2587 ierr = PointQueueDestroy(&queue);CHKERRQ(ierr); 2588 PetscFunctionReturn(0); 2589 } 2590 2591 static PetscErrorCode DMPlexCellRefinerDestroy_SBR(DMPlexCellRefiner cr) 2592 { 2593 PlexRefiner_SBR *sbr = (PlexRefiner_SBR *) cr->data; 2594 PetscErrorCode ierr; 2595 2596 PetscFunctionBegin; 2597 ierr = PetscFree(sbr->edgeLen);CHKERRQ(ierr); 2598 ierr = PetscSectionDestroy(&sbr->secEdgeLen);CHKERRQ(ierr); 2599 ierr = DMLabelDestroy(&sbr->splitPoints);CHKERRQ(ierr); 2600 ierr = PetscFree(cr->data);CHKERRQ(ierr); 2601 PetscFunctionReturn(0); 2602 } 2603 2604 static PetscErrorCode DMPlexCellRefinerRefine_SBR(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[]) 2605 { 2606 /* Add 1 edge inside this triangle, making 2 new triangles. 2607 2 2608 |\ 2609 | \ 2610 | \ 2611 | \ 2612 | 1 2613 | \ 2614 | B \ 2615 2 1 2616 | / \ 2617 | ____/ 0 2618 |/ A \ 2619 0-----0-----1 2620 */ 2621 static DMPolytopeType triT10[] = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE}; 2622 static PetscInt triS10[] = {1, 2}; 2623 static PetscInt triC10[] = {DM_POLYTOPE_POINT, 2, 0, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0, 2624 DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0, 0, 2625 DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0, 0}; 2626 static PetscInt triO10[] = {0, 0, 2627 0, 0, -2, 2628 0, 0, 0}; 2629 /* Add 1 edge inside this triangle, making 2 new triangles. 2630 2 2631 |\ 2632 | \ 2633 | \ 2634 0 \ 2635 | \ 2636 | \ 2637 | \ 2638 2 A 1 2639 |\ \ 2640 1 ---\ \ 2641 | B ----\\ 2642 0-----0-----1 2643 */ 2644 static PetscInt triC11[] = {DM_POLYTOPE_POINT, 2, 1, 0, 0, DM_POLYTOPE_POINT, 1, 2, 0, 2645 DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0, 0, 2646 DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0, 0}; 2647 static PetscInt triO11[] = {0, 0, 2648 0, 0, -2, 2649 0, 0, 0}; 2650 /* Add 1 edge inside this triangle, making 2 new triangles. 2651 2 2652 |\ 2653 |\\ 2654 || \ 2655 | \ \ 2656 | | \ 2657 | | \ 2658 | | \ 2659 2 \ 1 2660 | A | \ 2661 | | B \ 2662 | \ \ 2663 0-----0-----1 2664 */ 2665 static PetscInt triC12[] = {DM_POLYTOPE_POINT, 2, 2, 0, 0, DM_POLYTOPE_POINT, 1, 0, 0, 2666 DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0, 0, 2667 DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0, 0}; 2668 static PetscInt triO12[] = {0, 0, 2669 0, 0, -2, 2670 0, 0, 0}; 2671 /* Add 2 edges inside this triangle, making 3 new triangles. 2672 2 2673 |\ 2674 | \ 2675 | \ 2676 0 \ 2677 | 1 2678 | \ 2679 | B \ 2680 2-------1 2681 | C / \ 2682 1 ____/ 0 2683 |/ A \ 2684 0-----0-----1 2685 */ 2686 static DMPolytopeType triT20[] = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE}; 2687 static PetscInt triS20[] = {2, 3}; 2688 static PetscInt triC20[] = {DM_POLYTOPE_POINT, 2, 0, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0, 2689 DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 1, 2, 0, 2690 DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0, 0, 2691 DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0, 1, 2692 DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 1}; 2693 static PetscInt triO20[] = {0, 0, 2694 0, 0, 2695 0, 0, -2, 2696 0, 0, -2, 2697 0, 0, 0}; 2698 /* Add 1 edge inside this triangle, making 2 new triangles. 2699 2 2700 |\ 2701 | \ 2702 | \ 2703 0 \ 2704 | 1 2705 | \ 2706 | B \ 2707 2 1 2708 | /|\ 2709 1 ____/ / 0 2710 |/ A / C \ 2711 0-----0-----1 2712 */ 2713 static PetscInt triC21[] = {DM_POLYTOPE_POINT, 2, 0, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0, 2714 DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 1, 0, 0, 2715 DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 0, 0, 2716 DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0, 0, 2717 DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0, 1}; 2718 static PetscInt triO21[] = {0, 0, 2719 0, 0, 2720 0, -2, -2, 2721 0, 0, 0, 2722 0, 0, 0}; 2723 /* Add 2 edges inside this triangle, making 3 new triangles. 2724 2 2725 |\ 2726 | \ 2727 | \ 2728 0 \ 2729 | \ 2730 | \ 2731 | \ 2732 2 A 1 2733 |\ \ 2734 1 ---\ \ 2735 |B \_C----\\ 2736 0-----0-----1 2737 */ 2738 static PetscInt triC22[] = {DM_POLYTOPE_POINT, 2, 1, 0, 0, DM_POLYTOPE_POINT, 1, 2, 0, 2739 DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 1, 0, 0, 2740 DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0, 0, 2741 DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0, 1, 2742 DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 1}; 2743 static PetscInt triO22[] = {0, 0, 2744 0, 0, 2745 0, 0, -2, 2746 0, 0, -2, 2747 0, 0, 0}; 2748 /* Add 1 edge inside this triangle, making 2 new triangles. 2749 2 2750 |\ 2751 | \ 2752 | \ 2753 0 \ 2754 | \ 2755 | C \ 2756 | \ 2757 2-------1 2758 |\ A \ 2759 1 ---\ \ 2760 | B ----\\ 2761 0-----0-----1 2762 */ 2763 static PetscInt triC23[] = {DM_POLYTOPE_POINT, 2, 1, 0, 0, DM_POLYTOPE_POINT, 1, 2, 0, 2764 DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 1, 1, 0, 2765 DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 0, 0, 2766 DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0, 0, 2767 DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0, 1}; 2768 static PetscInt triO23[] = {0, 0, 2769 0, 0, 2770 0, -2, -2, 2771 0, 0, 0, 2772 0, 0, 0}; 2773 /* Add 2 edges inside this triangle, making 3 new triangles. 2774 2 2775 |\ 2776 |\\ 2777 || \ 2778 | \ \ 2779 | | \ 2780 | | \ 2781 | | \ 2782 2 \ C 1 2783 | A | / \ 2784 | | |B \ 2785 | \/ \ 2786 0-----0-----1 2787 */ 2788 static PetscInt triC24[] = {DM_POLYTOPE_POINT, 2, 2, 0, 0, DM_POLYTOPE_POINT, 1, 0, 0, 2789 DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0, 2790 DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0, 0, 2791 DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0, 1, 2792 DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 1}; 2793 static PetscInt triO24[] = {0, 0, 2794 0, 0, 2795 0, 0, -2, 2796 0, 0, -2, 2797 0, 0, 0}; 2798 /* Add 1 edge inside this triangle, making 2 new triangles. 2799 2 2800 |\ 2801 |\\ 2802 || \ 2803 | \ \ 2804 | | \ 2805 | | \ 2806 | | \ 2807 2 A \ 1 2808 |\ | \ 2809 | \__| B \ 2810 | C \\ \ 2811 0-----0-----1 2812 */ 2813 static PetscInt triC25[] = {DM_POLYTOPE_POINT, 2, 2, 0, 0, DM_POLYTOPE_POINT, 1, 0, 0, 2814 DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 2, 0, 2815 DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 0, 0, 2816 DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0, 0, 2817 DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0, 1}; 2818 static PetscInt triO25[] = {0, 0, 2819 0, 0, 2820 0, -2, -2, 2821 0, 0, 0, 2822 0, 0, 0}; 2823 DMLabel rtype = cr->refineType; 2824 PetscInt val; 2825 PetscErrorCode ierr; 2826 2827 PetscFunctionBeginHot; 2828 if (p < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point argument is invalid"); 2829 ierr = DMLabelGetValue(rtype, p, &val);CHKERRQ(ierr); 2830 if (rt) *rt = val; 2831 switch (source) { 2832 case DM_POLYTOPE_POINT: 2833 case DM_POLYTOPE_POINT_PRISM_TENSOR: 2834 case DM_POLYTOPE_QUADRILATERAL: 2835 case DM_POLYTOPE_SEG_PRISM_TENSOR: 2836 case DM_POLYTOPE_TETRAHEDRON: 2837 case DM_POLYTOPE_HEXAHEDRON: 2838 case DM_POLYTOPE_TRI_PRISM: 2839 case DM_POLYTOPE_TRI_PRISM_TENSOR: 2840 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 2841 case DM_POLYTOPE_PYRAMID: 2842 ierr = DMPlexCellRefinerRefine_None(cr, source, p, NULL, Nt, target, size, cone, ornt);CHKERRQ(ierr); 2843 break; 2844 case DM_POLYTOPE_SEGMENT: 2845 if (val == 1) {ierr = DMPlexCellRefinerRefine_None(cr, source, p, NULL, Nt, target, size, cone, ornt);CHKERRQ(ierr);} 2846 else {ierr = DMPlexCellRefinerRefine_Regular(cr, source, p, NULL, Nt, target, size, cone, ornt);CHKERRQ(ierr);} 2847 break; 2848 case DM_POLYTOPE_TRIANGLE: 2849 switch (val) { 2850 case 12: *Nt = 2; *target = triT10; *size = triS10; *cone = triC10; *ornt = triO10; break; 2851 case 13: *Nt = 2; *target = triT10; *size = triS10; *cone = triC11; *ornt = triO11; break; 2852 case 11: *Nt = 2; *target = triT10; *size = triS10; *cone = triC12; *ornt = triO12; break; 2853 case 5: *Nt = 2; *target = triT20; *size = triS20; *cone = triC24; *ornt = triO24; break; 2854 case 6: *Nt = 2; *target = triT20; *size = triS20; *cone = triC21; *ornt = triO21; break; 2855 case 7: *Nt = 2; *target = triT20; *size = triS20; *cone = triC20; *ornt = triO20; break; 2856 case 8: *Nt = 2; *target = triT20; *size = triS20; *cone = triC23; *ornt = triO23; break; 2857 case 9: *Nt = 2; *target = triT20; *size = triS20; *cone = triC22; *ornt = triO22; break; 2858 case 10: *Nt = 2; *target = triT20; *size = triS20; *cone = triC25; *ornt = triO25; break; 2859 case 4: ierr = DMPlexCellRefinerRefine_Regular(cr, source, p, NULL, Nt, target, size, cone, ornt);CHKERRQ(ierr); break; 2860 default: ierr = DMPlexCellRefinerRefine_None(cr, source, p, NULL, Nt, target, size, cone, ornt);CHKERRQ(ierr); 2861 } 2862 break; 2863 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]); 2864 } 2865 PetscFunctionReturn(0); 2866 } 2867 2868 static PetscErrorCode DMPlexCellRefinerMapSubcells_SBR(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt pp, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew) 2869 { 2870 /* We shift any input orientation in order to make it non-negative 2871 The orientation array o[po][o] gives the orientation the new replica rnew has to have in order to reproduce the face sequence from (r, o) 2872 The replica array r[po][r] gives the new replica number rnew given that the parent point has orientation po 2873 Overall, replica (r, o) in a parent with orientation 0 matches replica (rnew, onew) in a parent with orientation po 2874 */ 2875 PetscInt rt; 2876 PetscErrorCode ierr; 2877 2878 PetscFunctionBeginHot; 2879 ierr = DMLabelGetValue(cr->refineType, pp, &rt);CHKERRQ(ierr); 2880 *rnew = r; 2881 *onew = o; 2882 switch (rt) { 2883 case 5: 2884 case 6: 2885 case 7: 2886 case 8: 2887 case 9: 2888 case 10: 2889 switch (ct) { 2890 case DM_POLYTOPE_SEGMENT: 2891 break; 2892 case DM_POLYTOPE_TRIANGLE: 2893 break; 2894 default: break; 2895 } 2896 break; 2897 case 11: 2898 case 12: 2899 case 13: 2900 switch (ct) { 2901 case DM_POLYTOPE_SEGMENT: 2902 break; 2903 case DM_POLYTOPE_TRIANGLE: 2904 *onew = po < 0 ? -(o+1) : o; 2905 *rnew = po < 0 ? (r+1)%2 : r; 2906 break; 2907 default: break; 2908 } 2909 break; 2910 case 2: 2911 case 4: 2912 ierr = DMPlexCellRefinerMapSubcells_Regular(cr, pct, pp, po, ct, r, o, rnew, onew);CHKERRQ(ierr); 2913 break; 2914 default: ierr = DMPlexCellRefinerMapSubcells_None(cr, pct, pp, po, ct, r, o, rnew, onew);CHKERRQ(ierr); 2915 } 2916 PetscFunctionReturn(0); 2917 } 2918 2919 static PetscErrorCode CellRefinerCreateOffset_Internal(DMPlexCellRefiner cr, PetscInt ctOrder[], PetscInt ctStart[], PetscInt **offset) 2920 { 2921 PetscInt c, cN, *off; 2922 PetscErrorCode ierr; 2923 2924 PetscFunctionBegin; 2925 if (cr->refineType) { 2926 IS rtIS; 2927 const PetscInt *reftypes; 2928 PetscInt Nrt, r; 2929 2930 ierr = DMLabelGetNumValues(cr->refineType, &Nrt);CHKERRQ(ierr); 2931 ierr = DMLabelGetValueIS(cr->refineType, &rtIS);CHKERRQ(ierr); 2932 ierr = ISGetIndices(rtIS, &reftypes);CHKERRQ(ierr); 2933 ierr = PetscCalloc1(Nrt*DM_NUM_POLYTOPES, &off);CHKERRQ(ierr); 2934 for (r = 0; r < Nrt; ++r) { 2935 const PetscInt rt = reftypes[r]; 2936 IS rtIS; 2937 const PetscInt *points; 2938 DMPolytopeType ct; 2939 PetscInt p; 2940 2941 ierr = DMLabelGetStratumIS(cr->refineType, rt, &rtIS);CHKERRQ(ierr); 2942 ierr = ISGetIndices(rtIS, &points);CHKERRQ(ierr); 2943 p = points[0]; 2944 ierr = ISRestoreIndices(rtIS, &points);CHKERRQ(ierr); 2945 ierr = ISDestroy(&rtIS);CHKERRQ(ierr); 2946 ierr = DMPlexGetCellType(cr->dm, p, &ct);CHKERRQ(ierr); 2947 for (cN = DM_POLYTOPE_POINT; cN < DM_NUM_POLYTOPES; ++cN) { 2948 const DMPolytopeType ctNew = (DMPolytopeType) cN; 2949 DMPolytopeType *rct; 2950 PetscInt *rsize, *cone, *ornt; 2951 PetscInt Nct, n, s; 2952 2953 if (DMPolytopeTypeGetDim(ct) < 0 || DMPolytopeTypeGetDim(ctNew) < 0) {off[r*DM_NUM_POLYTOPES+ctNew] = -1; break;} 2954 off[r*DM_NUM_POLYTOPES+ctNew] = 0; 2955 for (s = 0; s <= r; ++s) { 2956 const PetscInt st = reftypes[s]; 2957 DMPolytopeType sct; 2958 PetscInt q, qrt; 2959 2960 ierr = DMLabelGetStratumIS(cr->refineType, st, &rtIS);CHKERRQ(ierr); 2961 ierr = ISGetIndices(rtIS, &points);CHKERRQ(ierr); 2962 q = points[0]; 2963 ierr = ISRestoreIndices(rtIS, &points);CHKERRQ(ierr); 2964 ierr = ISDestroy(&rtIS);CHKERRQ(ierr); 2965 ierr = DMPlexGetCellType(cr->dm, q, &sct);CHKERRQ(ierr); 2966 ierr = DMPlexCellRefinerRefine(cr, sct, q, &qrt, &Nct, &rct, &rsize, &cone, &ornt);CHKERRQ(ierr); 2967 if (st != qrt) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Refine type %D of point %D does not match predicted type %D", qrt, q, st); 2968 if (st == rt) { 2969 for (n = 0; n < Nct; ++n) if (rct[n] == ctNew) break; 2970 if (n == Nct) off[r*DM_NUM_POLYTOPES+ctNew] = -1; 2971 break; 2972 } 2973 for (n = 0; n < Nct; ++n) { 2974 if (rct[n] == ctNew) { 2975 PetscInt sn; 2976 2977 ierr = DMLabelGetStratumSize(cr->refineType, st, &sn);CHKERRQ(ierr); 2978 off[r*DM_NUM_POLYTOPES+ctNew] += sn * rsize[n]; 2979 } 2980 } 2981 } 2982 } 2983 } 2984 #if 0 2985 { 2986 PetscInt cols = 8; 2987 PetscInt f, g; 2988 ierr = PetscPrintf(PETSC_COMM_SELF, "Offsets\n");CHKERRQ(ierr); 2989 ierr = PetscPrintf(PETSC_COMM_SELF, " ");CHKERRQ(ierr); 2990 for (g = 0; g < cols; ++g) { 2991 ierr = PetscPrintf(PETSC_COMM_SELF, " % 14s", DMPolytopeTypes[g]);CHKERRQ(ierr); 2992 } 2993 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 2994 for (f = 0; f < Nrt; ++f) { 2995 ierr = PetscPrintf(PETSC_COMM_SELF, "%2d |", reftypes[f]);CHKERRQ(ierr); 2996 for (g = 0; g < cols; ++g) { 2997 ierr = PetscPrintf(PETSC_COMM_SELF, " % 14d", PetscRealPart(off[f*DM_NUM_POLYTOPES+g]));CHKERRQ(ierr); 2998 } 2999 ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr); 3000 } 3001 } 3002 #endif 3003 ierr = ISRestoreIndices(rtIS, &reftypes);CHKERRQ(ierr); 3004 ierr = ISDestroy(&rtIS);CHKERRQ(ierr); 3005 } else { 3006 ierr = PetscCalloc1(DM_NUM_POLYTOPES*DM_NUM_POLYTOPES, &off);CHKERRQ(ierr); 3007 for (c = DM_POLYTOPE_POINT; c < DM_NUM_POLYTOPES; ++c) { 3008 const DMPolytopeType ct = (DMPolytopeType) c; 3009 for (cN = DM_POLYTOPE_POINT; cN < DM_NUM_POLYTOPES; ++cN) { 3010 const DMPolytopeType ctNew = (DMPolytopeType) cN; 3011 DMPolytopeType *rct; 3012 PetscInt *rsize, *cone, *ornt; 3013 PetscInt Nct, n, i; 3014 3015 if (DMPolytopeTypeGetDim(ct) < 0 || DMPolytopeTypeGetDim(ctNew) < 0) {off[ct*DM_NUM_POLYTOPES+ctNew] = -1; break;} 3016 off[ct*DM_NUM_POLYTOPES+ctNew] = 0; 3017 for (i = DM_POLYTOPE_POINT; i < DM_NUM_POLYTOPES; ++i) { 3018 const DMPolytopeType ict = (DMPolytopeType) ctOrder[i]; 3019 const DMPolytopeType ictn = (DMPolytopeType) ctOrder[i+1]; 3020 3021 ierr = DMPlexCellRefinerRefine(cr, ict, PETSC_DETERMINE, NULL, &Nct, &rct, &rsize, &cone, &ornt);CHKERRQ(ierr); 3022 if (ict == ct) { 3023 for (n = 0; n < Nct; ++n) if (rct[n] == ctNew) break; 3024 if (n == Nct) off[ct*DM_NUM_POLYTOPES+ctNew] = -1; 3025 break; 3026 } 3027 for (n = 0; n < Nct; ++n) if (rct[n] == ctNew) off[ct*DM_NUM_POLYTOPES+ctNew] += (ctStart[ictn]-ctStart[ict]) * rsize[n]; 3028 } 3029 } 3030 } 3031 } 3032 *offset = off; 3033 PetscFunctionReturn(0); 3034 } 3035 3036 static PetscErrorCode DMPlexCellRefinerSetStarts(DMPlexCellRefiner cr, const PetscInt ctStart[], const PetscInt ctStartNew[]) 3037 { 3038 const PetscInt ctSize = DM_NUM_POLYTOPES+1; 3039 PetscErrorCode ierr; 3040 3041 PetscFunctionBegin; 3042 if (cr->setupcalled) SETERRQ(PetscObjectComm((PetscObject) cr), PETSC_ERR_ARG_WRONGSTATE, "Must call this function before DMPlexCellRefinerSetUp()"); 3043 ierr = PetscCalloc2(ctSize, &cr->ctStart, ctSize, &cr->ctStartNew);CHKERRQ(ierr); 3044 ierr = PetscArraycpy(cr->ctStart, ctStart, ctSize);CHKERRQ(ierr); 3045 ierr = PetscArraycpy(cr->ctStartNew, ctStartNew, ctSize);CHKERRQ(ierr); 3046 PetscFunctionReturn(0); 3047 } 3048 3049 /* Construct cell type order since we must loop over cell types in depth order */ 3050 PetscErrorCode DMPlexCreateCellTypeOrder_Internal(DMPolytopeType ctCell, PetscInt *ctOrder[], PetscInt *ctOrderInv[]) 3051 { 3052 PetscInt *ctO, *ctOInv; 3053 PetscInt c, d, off = 0; 3054 PetscErrorCode ierr; 3055 3056 PetscFunctionBegin; 3057 ierr = PetscCalloc2(DM_NUM_POLYTOPES+1, &ctO, DM_NUM_POLYTOPES+1, &ctOInv);CHKERRQ(ierr); 3058 for (d = 3; d >= DMPolytopeTypeGetDim(ctCell); --d) { 3059 for (c = 0; c <= DM_NUM_POLYTOPES; ++c) { 3060 if (DMPolytopeTypeGetDim((DMPolytopeType) c) != d) continue; 3061 ctO[off++] = c; 3062 } 3063 } 3064 if (DMPolytopeTypeGetDim(ctCell) != 0) { 3065 for (c = 0; c <= DM_NUM_POLYTOPES; ++c) { 3066 if (DMPolytopeTypeGetDim((DMPolytopeType) c) != 0) continue; 3067 ctO[off++] = c; 3068 } 3069 } 3070 for (d = DMPolytopeTypeGetDim(ctCell)-1; d > 0; --d) { 3071 for (c = 0; c <= DM_NUM_POLYTOPES; ++c) { 3072 if (DMPolytopeTypeGetDim((DMPolytopeType) c) != d) continue; 3073 ctO[off++] = c; 3074 } 3075 } 3076 for (c = 0; c <= DM_NUM_POLYTOPES; ++c) { 3077 if (DMPolytopeTypeGetDim((DMPolytopeType) c) >= 0) continue; 3078 ctO[off++] = c; 3079 } 3080 if (off != DM_NUM_POLYTOPES+1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid offset %D for cell type order", off); 3081 for (c = 0; c <= DM_NUM_POLYTOPES; ++c) { 3082 ctOInv[ctO[c]] = c; 3083 } 3084 *ctOrder = ctO; 3085 *ctOrderInv = ctOInv; 3086 PetscFunctionReturn(0); 3087 } 3088 3089 PetscErrorCode DMPlexCellRefinerSetUp(DMPlexCellRefiner cr) 3090 { 3091 DM dm = cr->dm; 3092 DMPolytopeType ctCell; 3093 PetscInt pStart, pEnd, p, c; 3094 PetscErrorCode ierr; 3095 3096 PetscFunctionBegin; 3097 PetscValidHeader(cr, 1); 3098 if (cr->setupcalled) PetscFunctionReturn(0); 3099 if (cr->ops->setup) { 3100 ierr = (*cr->ops->setup)(cr);CHKERRQ(ierr); 3101 } 3102 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3103 if (pEnd > pStart) { 3104 ierr = DMPlexGetCellType(dm, 0, &ctCell);CHKERRQ(ierr); 3105 } else { 3106 PetscInt dim; 3107 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3108 switch (dim) { 3109 case 0: ctCell = DM_POLYTOPE_POINT;break; 3110 case 1: ctCell = DM_POLYTOPE_SEGMENT;break; 3111 case 2: ctCell = DM_POLYTOPE_TRIANGLE;break; 3112 case 3: ctCell = DM_POLYTOPE_TETRAHEDRON;break; 3113 default: ctCell = DM_POLYTOPE_UNKNOWN; 3114 } 3115 } 3116 ierr = DMPlexCreateCellTypeOrder_Internal(ctCell, &cr->ctOrder, &cr->ctOrderInv);CHKERRQ(ierr); 3117 /* Construct sizes and offsets for each cell type */ 3118 if (!cr->ctStart) { 3119 PetscInt *ctS, *ctSN, *ctC, *ctCN; 3120 3121 ierr = PetscCalloc2(DM_NUM_POLYTOPES+1, &ctS, DM_NUM_POLYTOPES+1, &ctSN);CHKERRQ(ierr); 3122 ierr = PetscCalloc2(DM_NUM_POLYTOPES+1, &ctC, DM_NUM_POLYTOPES+1, &ctCN);CHKERRQ(ierr); 3123 for (p = pStart; p < pEnd; ++p) { 3124 DMPolytopeType ct; 3125 DMPolytopeType *rct; 3126 PetscInt *rsize, *cone, *ornt; 3127 PetscInt Nct, n; 3128 3129 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 3130 if ((PetscInt) ct < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell type for point %D", p); 3131 ++ctC[ct]; 3132 ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &cone, &ornt);CHKERRQ(ierr); 3133 for (n = 0; n < Nct; ++n) ctCN[rct[n]] += rsize[n]; 3134 } 3135 for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 3136 const PetscInt ct = cr->ctOrder[c]; 3137 const PetscInt ctn = cr->ctOrder[c+1]; 3138 3139 ctS[ctn] = ctS[ct] + ctC[ct]; 3140 ctSN[ctn] = ctSN[ct] + ctCN[ct]; 3141 } 3142 ierr = PetscFree2(ctC, ctCN);CHKERRQ(ierr); 3143 cr->ctStart = ctS; 3144 cr->ctStartNew = ctSN; 3145 } 3146 ierr = CellRefinerCreateOffset_Internal(cr, cr->ctOrder, cr->ctStart, &cr->offset);CHKERRQ(ierr); 3147 cr->setupcalled = PETSC_TRUE; 3148 PetscFunctionReturn(0); 3149 } 3150 3151 static PetscErrorCode DMPlexCellRefinerView_Ascii(DMPlexCellRefiner cr, PetscViewer v) 3152 { 3153 PetscErrorCode ierr; 3154 3155 PetscFunctionBegin; 3156 ierr = PetscViewerASCIIPrintf(v, "Cell Refiner: %s\n", DMPlexCellRefinerTypes[cr->type]);CHKERRQ(ierr); 3157 PetscFunctionReturn(0); 3158 } 3159 3160 /* 3161 DMPlexCellRefinerView - Views a DMPlexCellRefiner object 3162 3163 Collective on cr 3164 3165 Input Parameters: 3166 + cr - The DMPlexCellRefiner object 3167 - viewer - The PetscViewer object 3168 3169 Level: beginner 3170 3171 .seealso: DMPlexCellRefinerCreate() 3172 */ 3173 static PetscErrorCode DMPlexCellRefinerView(DMPlexCellRefiner cr, PetscViewer viewer) 3174 { 3175 PetscBool iascii; 3176 PetscErrorCode ierr; 3177 3178 PetscFunctionBegin; 3179 PetscValidHeader(cr, 1); 3180 if (viewer) PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 3181 if (!viewer) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) cr), &viewer);CHKERRQ(ierr);} 3182 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 3183 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 3184 if (iascii) {ierr = DMPlexCellRefinerView_Ascii(cr, viewer);CHKERRQ(ierr);} 3185 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 3186 PetscFunctionReturn(0); 3187 } 3188 3189 PetscErrorCode DMPlexCellRefinerDestroy(DMPlexCellRefiner *cr) 3190 { 3191 PetscInt c; 3192 PetscErrorCode ierr; 3193 3194 PetscFunctionBegin; 3195 if (!*cr) PetscFunctionReturn(0); 3196 PetscValidHeaderSpecific(*cr, DM_CLASSID, 1); 3197 if ((*cr)->ops->destroy) { 3198 ierr = ((*cr)->ops->destroy)(*cr);CHKERRQ(ierr); 3199 } 3200 ierr = PetscObjectDereference((PetscObject) (*cr)->dm);CHKERRQ(ierr); 3201 ierr = DMLabelDestroy(&(*cr)->refineType);CHKERRQ(ierr); 3202 ierr = PetscFree2((*cr)->ctOrder, (*cr)->ctOrderInv);CHKERRQ(ierr); 3203 ierr = PetscFree2((*cr)->ctStart, (*cr)->ctStartNew);CHKERRQ(ierr); 3204 ierr = PetscFree((*cr)->offset);CHKERRQ(ierr); 3205 for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 3206 ierr = PetscFEDestroy(&(*cr)->coordFE[c]);CHKERRQ(ierr); 3207 ierr = PetscFEGeomDestroy(&(*cr)->refGeom[c]);CHKERRQ(ierr); 3208 } 3209 ierr = PetscFree2((*cr)->coordFE, (*cr)->refGeom);CHKERRQ(ierr); 3210 ierr = PetscHeaderDestroy(cr);CHKERRQ(ierr); 3211 PetscFunctionReturn(0); 3212 } 3213 3214 PetscErrorCode DMPlexCellRefinerCreate(DM dm, DMPlexCellRefiner *cr) 3215 { 3216 DMPlexCellRefiner tmp; 3217 PetscErrorCode ierr; 3218 3219 PetscFunctionBegin; 3220 PetscValidPointer(cr, 2); 3221 *cr = NULL; 3222 ierr = PetscHeaderCreate(tmp, DM_CLASSID, "DMPlexCellRefiner", "Cell Refiner", "DMPlexCellRefiner", PETSC_COMM_SELF, DMPlexCellRefinerDestroy, DMPlexCellRefinerView);CHKERRQ(ierr); 3223 tmp->setupcalled = PETSC_FALSE; 3224 3225 tmp->dm = dm; 3226 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); 3227 ierr = DMPlexGetCellRefinerType(dm, &tmp->type);CHKERRQ(ierr); 3228 switch (tmp->type) { 3229 case DM_REFINER_REGULAR: 3230 tmp->ops->refine = DMPlexCellRefinerRefine_Regular; 3231 tmp->ops->mapsubcells = DMPlexCellRefinerMapSubcells_Regular; 3232 tmp->ops->getcellvertices = DMPlexCellRefinerGetCellVertices_Regular; 3233 tmp->ops->getsubcellvertices = DMPlexCellRefinerGetSubcellVertices_Regular; 3234 tmp->ops->mapcoords = DMPlexCellRefinerMapCoordinates_Barycenter; 3235 tmp->ops->getaffinetransforms = DMPlexCellRefinerGetAffineTransforms_Regular; 3236 tmp->ops->getaffinefacetransforms = DMPlexCellRefinerGetAffineFaceTransforms_Regular; 3237 break; 3238 case DM_REFINER_TO_BOX: 3239 tmp->ops->refine = DMPlexCellRefinerRefine_ToBox; 3240 tmp->ops->mapsubcells = DMPlexCellRefinerMapSubcells_ToBox; 3241 tmp->ops->getcellvertices = DMPlexCellRefinerGetCellVertices_ToBox; 3242 tmp->ops->getsubcellvertices = DMPlexCellRefinerGetSubcellVertices_ToBox; 3243 tmp->ops->mapcoords = DMPlexCellRefinerMapCoordinates_Barycenter; 3244 break; 3245 case DM_REFINER_TO_SIMPLEX: 3246 tmp->ops->refine = DMPlexCellRefinerRefine_ToSimplex; 3247 tmp->ops->mapsubcells = DMPlexCellRefinerMapSubcells_ToSimplex; 3248 tmp->ops->mapcoords = DMPlexCellRefinerMapCoordinates_Barycenter; 3249 break; 3250 case DM_REFINER_ALFELD2D: 3251 tmp->ops->refine = DMPlexCellRefinerRefine_Alfeld2D; 3252 tmp->ops->mapsubcells = DMPlexCellRefinerMapSubcells_None; 3253 tmp->ops->mapcoords = DMPlexCellRefinerMapCoordinates_Barycenter; 3254 break; 3255 case DM_REFINER_ALFELD3D: 3256 tmp->ops->refine = DMPlexCellRefinerRefine_Alfeld3D; 3257 tmp->ops->mapsubcells = DMPlexCellRefinerMapSubcells_None; 3258 tmp->ops->mapcoords = DMPlexCellRefinerMapCoordinates_Barycenter; 3259 break; 3260 case DM_REFINER_BOUNDARYLAYER: 3261 tmp->ops->setup = DMPlexCellRefinerSetUp_BL; 3262 tmp->ops->destroy = DMPlexCellRefinerDestroy_BL; 3263 tmp->ops->refine = DMPlexCellRefinerRefine_BL; 3264 tmp->ops->mapsubcells = DMPlexCellRefinerMapSubcells_BL; 3265 tmp->ops->mapcoords = DMPlexCellRefinerMapCoordinates_BL; 3266 break; 3267 case DM_REFINER_SBR: 3268 tmp->ops->setup = DMPlexCellRefinerSetUp_SBR; 3269 tmp->ops->destroy = DMPlexCellRefinerDestroy_SBR; 3270 tmp->ops->refine = DMPlexCellRefinerRefine_SBR; 3271 tmp->ops->mapsubcells = DMPlexCellRefinerMapSubcells_SBR; 3272 tmp->ops->mapcoords = DMPlexCellRefinerMapCoordinates_Barycenter; 3273 break; 3274 default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Invalid cell refiner type %s", DMPlexCellRefinerTypes[tmp->type]); 3275 } 3276 ierr = PetscCalloc2(DM_NUM_POLYTOPES, &tmp->coordFE, DM_NUM_POLYTOPES, &tmp->refGeom);CHKERRQ(ierr); 3277 *cr = tmp; 3278 PetscFunctionReturn(0); 3279 } 3280 3281 /*@ 3282 DMPlexCellRefinerGetAffineTransforms - Gets the affine map from the reference cell to each subcell 3283 3284 Input Parameters: 3285 + cr - The DMPlexCellRefiner object 3286 - ct - The cell type 3287 3288 Output Parameters: 3289 + Nc - The number of subcells produced from this cell type 3290 . v0 - The translation of the first vertex for each subcell 3291 . J - The Jacobian for each subcell (map from reference cell to subcell) 3292 - invJ - The inverse Jacobian for each subcell 3293 3294 Level: developer 3295 3296 .seealso: DMPlexCellRefinerGetAffineFaceTransforms(), Create() 3297 @*/ 3298 PetscErrorCode DMPlexCellRefinerGetAffineTransforms(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nc, PetscReal *v0[], PetscReal *J[], PetscReal *invJ[]) 3299 { 3300 PetscErrorCode ierr; 3301 3302 PetscFunctionBegin; 3303 if (!cr->ops->getaffinetransforms) SETERRQ(PetscObjectComm((PetscObject) cr), PETSC_ERR_SUP, "No support for affine transforms from this refiner"); 3304 ierr = (*cr->ops->getaffinetransforms)(cr, ct, Nc, v0, J, invJ);CHKERRQ(ierr); 3305 PetscFunctionReturn(0); 3306 } 3307 3308 /*@ 3309 DMPlexCellRefinerGetAffineFaceTransforms - Gets the affine map from the reference face cell to each face in the given cell 3310 3311 Input Parameters: 3312 + cr - The DMPlexCellRefiner object 3313 - ct - The cell type 3314 3315 Output Parameters: 3316 + Nf - The number of faces for this cell type 3317 . v0 - The translation of the first vertex for each face 3318 . J - The Jacobian for each face (map from original cell to subcell) 3319 . invJ - The inverse Jacobian for each face 3320 - detJ - The determinant of the Jacobian for each face 3321 3322 Note: The Jacobian and inverse Jacboian will be rectangular, and the inverse is really a generalized inverse. 3323 3324 Level: developer 3325 3326 .seealso: DMPlexCellRefinerGetAffineTransforms(), Create() 3327 @*/ 3328 PetscErrorCode DMPlexCellRefinerGetAffineFaceTransforms(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nf, PetscReal *v0[], PetscReal *J[], PetscReal *invJ[], PetscReal *detJ[]) 3329 { 3330 PetscErrorCode ierr; 3331 3332 PetscFunctionBegin; 3333 if (!cr->ops->getaffinefacetransforms) SETERRQ(PetscObjectComm((PetscObject) cr), PETSC_ERR_SUP, "No support for affine face transforms from this refiner"); 3334 ierr = (*cr->ops->getaffinefacetransforms)(cr, ct, Nf, v0, J, invJ, detJ);CHKERRQ(ierr); 3335 PetscFunctionReturn(0); 3336 } 3337 3338 /* Numbering regularly refined meshes 3339 3340 We want the numbering of the new mesh to respect the same depth stratification as the old mesh. We first compute 3341 the number of new points at each depth. This means that offsets for each depth can be computed, making no assumptions 3342 about the order of different cell types. 3343 3344 However, when we want to order different depth strata, it will be very useful to make assumptions about contiguous 3345 numbering of different cell types, especially if we want to compute new numberings without communication. Therefore, we 3346 will require that cells are numbering contiguously for each cell type, and that those blocks come in the same order as 3347 the cell type enumeration within a given depth stratum. 3348 3349 Thus, at each depth, each cell type will add a certain number of points at that depth. To get the new point number, we 3350 start at the new depth offset, run through all prior cell types incrementing by the total addition from that type, then 3351 offset by the old cell type number and replica number for the insertion. 3352 */ 3353 3354 static PetscErrorCode DMPlexCellRefinerGetReducedPointNumber(DMPlexCellRefiner cr, PetscInt rt, PetscInt p, PetscInt *rp) 3355 { 3356 IS rtIS; 3357 const PetscInt *points; 3358 PetscInt n; 3359 PetscErrorCode ierr; 3360 3361 PetscFunctionBegin; 3362 /* TODO Move this inside the DMLabel so that I do not have to create the IS */ 3363 ierr = DMLabelGetStratumIS(cr->refineType, rt, &rtIS);CHKERRQ(ierr); 3364 ierr = ISGetLocalSize(rtIS, &n);CHKERRQ(ierr); 3365 ierr = ISGetIndices(rtIS, &points);CHKERRQ(ierr); 3366 ierr = PetscFindInt(p, n, points, rp);CHKERRQ(ierr); 3367 ierr = ISRestoreIndices(rtIS, &points);CHKERRQ(ierr); 3368 ierr = ISDestroy(&rtIS);CHKERRQ(ierr); 3369 PetscFunctionReturn(0); 3370 } 3371 3372 /* 3373 DMPlexCellRefinerGetNewPoint - Get the number of a point in the refined mesh based on information from the original mesh. 3374 3375 Not collective 3376 3377 Input Parameters: 3378 + cr - The cell refiner 3379 . ct - The type of the original point which produces the new point 3380 . ctNew - The type of the new point 3381 . p - The original point which produces the new point 3382 - r - The replica number of the new point, meaning it is the rth point of type ctNew produced from p 3383 3384 Output Parameters: 3385 . pNew - The new point number 3386 3387 Level: developer 3388 3389 .seealso: DMPlexCellRefinerRefine() 3390 */ 3391 PetscErrorCode DMPlexCellRefinerGetNewPoint(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType ctNew, PetscInt p, PetscInt r, PetscInt *pNew) 3392 { 3393 DMPolytopeType *rct; 3394 PetscInt *rsize, *cone, *ornt; 3395 PetscInt rt, Nct, n, off, rp; 3396 PetscInt ctS = cr->ctStart[ct], ctE = cr->ctStart[cr->ctOrder[cr->ctOrderInv[ct]+1]]; 3397 PetscInt ctSN = cr->ctStartNew[ctNew], ctEN = cr->ctStartNew[cr->ctOrder[cr->ctOrderInv[ctNew]+1]]; 3398 PetscInt newp = ctSN, cind; 3399 PetscErrorCode ierr; 3400 3401 PetscFunctionBeginHot; 3402 if ((p < ctS) || (p >= ctE)) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D is not a %s [%D, %D)", p, DMPolytopeTypes[ct], ctS, ctE); 3403 ierr = DMPlexCellRefinerRefine(cr, ct, p, &rt, &Nct, &rct, &rsize, &cone, &ornt);CHKERRQ(ierr); 3404 if (cr->refineType) { 3405 /* TODO Make this a function in DMLabel */ 3406 { 3407 IS rtIS; 3408 const PetscInt *reftypes; 3409 PetscInt Nrt; 3410 3411 ierr = DMLabelGetNumValues(cr->refineType, &Nrt);CHKERRQ(ierr); 3412 ierr = DMLabelGetValueIS(cr->refineType, &rtIS);CHKERRQ(ierr); 3413 ierr = ISGetIndices(rtIS, &reftypes);CHKERRQ(ierr); 3414 for (cind = 0; cind < Nrt; ++cind) if (reftypes[cind] == rt) break; 3415 if (cind >= Nrt) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unable to locate refine type %D", rt); 3416 ierr = ISRestoreIndices(rtIS, &reftypes);CHKERRQ(ierr); 3417 ierr = ISDestroy(&rtIS);CHKERRQ(ierr); 3418 } 3419 ierr = DMPlexCellRefinerGetReducedPointNumber(cr, rt, p, &rp);CHKERRQ(ierr); 3420 if (rp < 0) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s point %D does not have refine type %D", DMPolytopeTypes[ct], p, rt); 3421 } else { 3422 cind = ct; 3423 rp = p - ctS; 3424 } 3425 off = cr->offset[cind*DM_NUM_POLYTOPES + ctNew]; 3426 if (off < 0) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s (%D) of point %D does not produce type %s", DMPolytopeTypes[ct], rt, p, DMPolytopeTypes[ctNew]); 3427 newp += off; 3428 for (n = 0; n < Nct; ++n) { 3429 if (rct[n] == ctNew) { 3430 if (rsize[n] && r >= rsize[n]) 3431 SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Replica number %D should be in [0, %D) for subcell type %s in cell type %s", r, rsize[n], DMPolytopeTypes[rct[n]], DMPolytopeTypes[ct]); 3432 newp += rp * rsize[n] + r; 3433 break; 3434 } 3435 } 3436 3437 if ((newp < ctSN) || (newp >= ctEN)) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "New point %D is not a %s [%D, %D)", newp, DMPolytopeTypes[ctNew], ctSN, ctEN); 3438 *pNew = newp; 3439 PetscFunctionReturn(0); 3440 } 3441 3442 static PetscErrorCode DMPlexCellRefinerSetConeSizes(DMPlexCellRefiner cr, DM rdm) 3443 { 3444 DM dm = cr->dm; 3445 PetscInt pStart, pEnd, p, pNew; 3446 PetscErrorCode ierr; 3447 3448 PetscFunctionBegin; 3449 /* Must create the celltype label here so that we do not automatically try to compute the types */ 3450 ierr = DMCreateLabel(rdm, "celltype");CHKERRQ(ierr); 3451 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3452 for (p = pStart; p < pEnd; ++p) { 3453 DMPolytopeType ct; 3454 DMPolytopeType *rct; 3455 PetscInt *rsize, *rcone, *rornt; 3456 PetscInt Nct, n, r; 3457 3458 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 3459 ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 3460 for (n = 0; n < Nct; ++n) { 3461 for (r = 0; r < rsize[n]; ++r) { 3462 ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr); 3463 ierr = DMPlexSetConeSize(rdm, pNew, DMPolytopeTypeGetConeSize(rct[n]));CHKERRQ(ierr); 3464 ierr = DMPlexSetCellType(rdm, pNew, rct[n]);CHKERRQ(ierr); 3465 } 3466 } 3467 } 3468 { 3469 DMLabel ctLabel; 3470 DM_Plex *plex = (DM_Plex *) rdm->data; 3471 3472 ierr = DMPlexGetCellTypeLabel(rdm, &ctLabel);CHKERRQ(ierr); 3473 ierr = PetscObjectStateGet((PetscObject) ctLabel, &plex->celltypeState);CHKERRQ(ierr); 3474 } 3475 PetscFunctionReturn(0); 3476 } 3477 3478 static PetscErrorCode DMPlexCellRefinerSetCones(DMPlexCellRefiner cr, DM rdm) 3479 { 3480 DM dm = cr->dm; 3481 DMPolytopeType ct; 3482 PetscInt *coneNew, *orntNew; 3483 PetscInt maxConeSize = 0, pStart, pEnd, p, pNew; 3484 PetscErrorCode ierr; 3485 3486 PetscFunctionBegin; 3487 for (p = 0; p < DM_NUM_POLYTOPES; ++p) maxConeSize = PetscMax(maxConeSize, DMPolytopeTypeGetConeSize((DMPolytopeType) p)); 3488 ierr = PetscMalloc2(maxConeSize, &coneNew, maxConeSize, &orntNew);CHKERRQ(ierr); 3489 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3490 for (p = pStart; p < pEnd; ++p) { 3491 const PetscInt *cone, *ornt; 3492 PetscInt coff, ooff, c; 3493 DMPolytopeType *rct; 3494 PetscInt *rsize, *rcone, *rornt; 3495 PetscInt Nct, n, r; 3496 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 3497 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 3498 ierr = DMPlexGetConeOrientation(dm, p, &ornt);CHKERRQ(ierr); 3499 ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 3500 for (n = 0, coff = 0, ooff = 0; n < Nct; ++n) { 3501 const DMPolytopeType ctNew = rct[n]; 3502 const PetscInt csizeNew = DMPolytopeTypeGetConeSize(ctNew); 3503 3504 for (r = 0; r < rsize[n]; ++r) { 3505 /* pNew is a subcell produced by subdividing p */ 3506 ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr); 3507 for (c = 0; c < csizeNew; ++c) { 3508 PetscInt ppp = -1; /* Parent Parent point: Parent of point pp */ 3509 PetscInt pp = p; /* Parent point: Point in the original mesh producing new cone point */ 3510 PetscInt po = 0; /* Orientation of parent point pp in parent parent point ppp */ 3511 DMPolytopeType pct = ct; /* Parent type: Cell type for parent of new cone point */ 3512 const PetscInt *pcone = cone; /* Parent cone: Cone of parent point pp */ 3513 PetscInt pr = -1; /* Replica number of pp that produces new cone point */ 3514 const DMPolytopeType ft = (DMPolytopeType) rcone[coff++]; /* Cell type for new cone point of pNew */ 3515 const PetscInt fn = rcone[coff++]; /* Number of cones of p that need to be taken when producing new cone point */ 3516 PetscInt fo = rornt[ooff++]; /* Orientation of new cone point in pNew */ 3517 PetscInt lc; 3518 3519 /* Get the type (pct) and point number (pp) of the parent point in the original mesh which produces this cone point */ 3520 for (lc = 0; lc < fn; ++lc) { 3521 const PetscInt *ppornt; 3522 PetscInt pcp; 3523 3524 ierr = DMPolytopeMapCell(pct, po, rcone[coff++], &pcp);CHKERRQ(ierr); 3525 ppp = pp; 3526 pp = pcone[pcp]; 3527 ierr = DMPlexGetCellType(dm, pp, &pct);CHKERRQ(ierr); 3528 ierr = DMPlexGetCone(dm, pp, &pcone);CHKERRQ(ierr); 3529 ierr = DMPlexGetConeOrientation(dm, ppp, &ppornt);CHKERRQ(ierr); 3530 if (po < 0 && pct != DM_POLYTOPE_POINT) { 3531 const PetscInt pornt = ppornt[pcp]; 3532 const PetscInt pcsize = DMPolytopeTypeGetConeSize(pct); 3533 const PetscInt pcstart = pornt < 0 ? -(pornt+1) : pornt; 3534 const PetscInt rcstart = (pcstart+pcsize-1)%pcsize; 3535 po = pornt < 0 ? -(rcstart+1) : rcstart; 3536 } else { 3537 po = ppornt[pcp]; 3538 } 3539 } 3540 pr = rcone[coff++]; 3541 /* Orientation po of pp maps (pr, fo) -> (pr', fo') */ 3542 ierr = DMPlexCellRefinerMapSubcells(cr, pct, pp, po, ft, pr, fo, &pr, &fo);CHKERRQ(ierr); 3543 ierr = DMPlexCellRefinerGetNewPoint(cr, pct, ft, pp, pr, &coneNew[c]);CHKERRQ(ierr); 3544 orntNew[c] = fo; 3545 } 3546 ierr = DMPlexSetCone(rdm, pNew, coneNew);CHKERRQ(ierr); 3547 ierr = DMPlexSetConeOrientation(rdm, pNew, orntNew);CHKERRQ(ierr); 3548 } 3549 } 3550 } 3551 ierr = PetscFree2(coneNew, orntNew);CHKERRQ(ierr); 3552 ierr = DMViewFromOptions(rdm, NULL, "-rdm_view");CHKERRQ(ierr); 3553 ierr = DMPlexSymmetrize(rdm);CHKERRQ(ierr); 3554 ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 3555 PetscFunctionReturn(0); 3556 } 3557 3558 static PetscErrorCode DMPlexCellRefinerGetCoordinateFE(DMPlexCellRefiner cr, DMPolytopeType ct, PetscFE *fe) 3559 { 3560 PetscErrorCode ierr; 3561 3562 PetscFunctionBegin; 3563 if (!cr->coordFE[ct]) { 3564 PetscInt dim, cdim; 3565 PetscBool isSimplex; 3566 3567 switch (ct) { 3568 case DM_POLYTOPE_SEGMENT: dim = 1; isSimplex = PETSC_TRUE; break; 3569 case DM_POLYTOPE_TRIANGLE: dim = 2; isSimplex = PETSC_TRUE; break; 3570 case DM_POLYTOPE_QUADRILATERAL: dim = 2; isSimplex = PETSC_FALSE; break; 3571 case DM_POLYTOPE_TETRAHEDRON: dim = 3; isSimplex = PETSC_TRUE; break; 3572 case DM_POLYTOPE_HEXAHEDRON: dim = 3; isSimplex = PETSC_FALSE; break; 3573 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No coordinate FE for cell type %s", DMPolytopeTypes[ct]); 3574 } 3575 ierr = DMGetCoordinateDim(cr->dm, &cdim);CHKERRQ(ierr); 3576 ierr = PetscFECreateLagrange(PETSC_COMM_SELF, dim, cdim, isSimplex, 1, PETSC_DETERMINE, &cr->coordFE[ct]);CHKERRQ(ierr); 3577 { 3578 PetscDualSpace dsp; 3579 PetscQuadrature quad; 3580 DM K; 3581 PetscFEGeom *cg; 3582 PetscReal *Xq, *xq, *wq; 3583 PetscInt Nq, q; 3584 3585 ierr = DMPlexCellRefinerGetCellVertices(cr, ct, &Nq, &Xq);CHKERRQ(ierr); 3586 ierr = PetscMalloc1(Nq*cdim, &xq);CHKERRQ(ierr); 3587 for (q = 0; q < Nq*cdim; ++q) xq[q] = Xq[q]; 3588 ierr = PetscMalloc1(Nq, &wq);CHKERRQ(ierr); 3589 for (q = 0; q < Nq; ++q) wq[q] = 1.0; 3590 ierr = PetscQuadratureCreate(PETSC_COMM_SELF, &quad);CHKERRQ(ierr); 3591 ierr = PetscQuadratureSetData(quad, dim, 1, Nq, xq, wq);CHKERRQ(ierr); 3592 ierr = PetscFESetQuadrature(cr->coordFE[ct], quad);CHKERRQ(ierr); 3593 3594 ierr = PetscFEGetDualSpace(cr->coordFE[ct], &dsp);CHKERRQ(ierr); 3595 ierr = PetscDualSpaceGetDM(dsp, &K);CHKERRQ(ierr); 3596 ierr = PetscFEGeomCreate(quad, 1, cdim, PETSC_FALSE, &cr->refGeom[ct]);CHKERRQ(ierr); 3597 cg = cr->refGeom[ct]; 3598 ierr = DMPlexComputeCellGeometryFEM(K, 0, NULL, cg->v, cg->J, cg->invJ, cg->detJ);CHKERRQ(ierr); 3599 ierr = PetscQuadratureDestroy(&quad);CHKERRQ(ierr); 3600 } 3601 } 3602 *fe = cr->coordFE[ct]; 3603 PetscFunctionReturn(0); 3604 } 3605 3606 /* 3607 DMPlexCellRefinerMapLocalizedCoordinates - Given a cell of type ct with localized coordinates x, we generate localized coordinates xr for subcell r of type rct. 3608 3609 Not collective 3610 3611 Input Parameters: 3612 + cr - The DMPlexCellRefiner 3613 . ct - The type of the parent cell 3614 . rct - The type of the produced cell 3615 . r - The index of the produced cell 3616 - x - The localized coordinates for the parent cell 3617 3618 Output Parameter: 3619 . xr - The localized coordinates for the produced cell 3620 3621 Level: developer 3622 3623 .seealso: DMPlexCellRefinerSetCoordinates() 3624 */ 3625 static PetscErrorCode DMPlexCellRefinerMapLocalizedCoordinates(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType rct, PetscInt r, const PetscScalar x[], PetscScalar xr[]) 3626 { 3627 PetscFE fe = NULL; 3628 PetscInt cdim, Nv, v, *subcellV; 3629 PetscErrorCode ierr; 3630 3631 PetscFunctionBegin; 3632 ierr = DMPlexCellRefinerGetCoordinateFE(cr, ct, &fe);CHKERRQ(ierr); 3633 ierr = DMPlexCellRefinerGetSubcellVertices(cr, ct, rct, r, &Nv, &subcellV);CHKERRQ(ierr); 3634 ierr = PetscFEGetNumComponents(fe, &cdim);CHKERRQ(ierr); 3635 for (v = 0; v < Nv; ++v) { 3636 ierr = PetscFEInterpolate_Static(fe, x, cr->refGeom[ct], subcellV[v], &xr[v*cdim]);CHKERRQ(ierr); 3637 } 3638 PetscFunctionReturn(0); 3639 } 3640 3641 static PetscErrorCode DMPlexCellRefinerSetCoordinates(DMPlexCellRefiner cr, DM rdm) 3642 { 3643 DM dm = cr->dm, cdm; 3644 PetscSection coordSection, coordSectionNew; 3645 Vec coordsLocal, coordsLocalNew; 3646 const PetscScalar *coords; 3647 PetscScalar *coordsNew; 3648 const DMBoundaryType *bd; 3649 const PetscReal *maxCell, *L; 3650 PetscBool isperiodic, localizeVertices = PETSC_FALSE, localizeCells = PETSC_FALSE; 3651 PetscInt dE, d, cStart, cEnd, c, vStartNew, vEndNew, v, pStart, pEnd, p, ocStart, ocEnd; 3652 PetscErrorCode ierr; 3653 3654 PetscFunctionBegin; 3655 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 3656 ierr = DMGetPeriodicity(dm, &isperiodic, &maxCell, &L, &bd);CHKERRQ(ierr); 3657 /* Determine if we need to localize coordinates when generating them */ 3658 if (isperiodic) { 3659 localizeVertices = PETSC_TRUE; 3660 if (!maxCell) { 3661 PetscBool localized; 3662 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 3663 if (!localized) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_USER, "Cannot refine a periodic mesh if coordinates have not been localized"); 3664 localizeCells = PETSC_TRUE; 3665 } 3666 } 3667 3668 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3669 ierr = PetscSectionGetFieldComponents(coordSection, 0, &dE);CHKERRQ(ierr); 3670 if (maxCell) { 3671 PetscReal maxCellNew[3]; 3672 3673 for (d = 0; d < dE; ++d) maxCellNew[d] = maxCell[d]/2.0; 3674 ierr = DMSetPeriodicity(rdm, isperiodic, maxCellNew, L, bd);CHKERRQ(ierr); 3675 } else { 3676 ierr = DMSetPeriodicity(rdm, isperiodic, maxCell, L, bd);CHKERRQ(ierr); 3677 } 3678 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &coordSectionNew);CHKERRQ(ierr); 3679 ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 3680 ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dE);CHKERRQ(ierr); 3681 ierr = DMPlexGetDepthStratum(rdm, 0, &vStartNew, &vEndNew);CHKERRQ(ierr); 3682 if (localizeCells) {ierr = PetscSectionSetChart(coordSectionNew, 0, vEndNew);CHKERRQ(ierr);} 3683 else {ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vEndNew);CHKERRQ(ierr);} 3684 3685 /* Localization should be inherited */ 3686 /* Stefano calculates parent cells for each new cell for localization */ 3687 /* Localized cells need coordinates of closure */ 3688 for (v = vStartNew; v < vEndNew; ++v) { 3689 ierr = PetscSectionSetDof(coordSectionNew, v, dE);CHKERRQ(ierr); 3690 ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dE);CHKERRQ(ierr); 3691 } 3692 if (localizeCells) { 3693 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3694 for (c = cStart; c < cEnd; ++c) { 3695 PetscInt dof; 3696 3697 ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr); 3698 if (dof) { 3699 DMPolytopeType ct; 3700 DMPolytopeType *rct; 3701 PetscInt *rsize, *rcone, *rornt; 3702 PetscInt dim, cNew, Nct, n, r; 3703 3704 ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr); 3705 dim = DMPolytopeTypeGetDim(ct); 3706 ierr = DMPlexCellRefinerRefine(cr, ct, c, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 3707 /* This allows for different cell types */ 3708 for (n = 0; n < Nct; ++n) { 3709 if (dim != DMPolytopeTypeGetDim(rct[n])) continue; 3710 for (r = 0; r < rsize[n]; ++r) { 3711 PetscInt *closure = NULL; 3712 PetscInt clSize, cl, Nv = 0; 3713 3714 ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], c, r, &cNew);CHKERRQ(ierr); 3715 ierr = DMPlexGetTransitiveClosure(rdm, cNew, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 3716 for (cl = 0; cl < clSize*2; cl += 2) {if ((closure[cl] >= vStartNew) && (closure[cl] < vEndNew)) ++Nv;} 3717 ierr = DMPlexRestoreTransitiveClosure(rdm, cNew, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr); 3718 ierr = PetscSectionSetDof(coordSectionNew, cNew, Nv * dE);CHKERRQ(ierr); 3719 ierr = PetscSectionSetFieldDof(coordSectionNew, cNew, 0, Nv * dE);CHKERRQ(ierr); 3720 } 3721 } 3722 } 3723 } 3724 } 3725 ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 3726 ierr = DMViewFromOptions(dm, NULL, "-coarse_dm_view");CHKERRQ(ierr); 3727 ierr = DMSetCoordinateSection(rdm, PETSC_DETERMINE, coordSectionNew);CHKERRQ(ierr); 3728 { 3729 VecType vtype; 3730 PetscInt coordSizeNew, bs; 3731 const char *name; 3732 3733 ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 3734 ierr = VecCreate(PETSC_COMM_SELF, &coordsLocalNew);CHKERRQ(ierr); 3735 ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 3736 ierr = VecSetSizes(coordsLocalNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 3737 ierr = PetscObjectGetName((PetscObject) coordsLocal, &name);CHKERRQ(ierr); 3738 ierr = PetscObjectSetName((PetscObject) coordsLocalNew, name);CHKERRQ(ierr); 3739 ierr = VecGetBlockSize(coordsLocal, &bs);CHKERRQ(ierr); 3740 ierr = VecSetBlockSize(coordsLocalNew, bs);CHKERRQ(ierr); 3741 ierr = VecGetType(coordsLocal, &vtype);CHKERRQ(ierr); 3742 ierr = VecSetType(coordsLocalNew, vtype);CHKERRQ(ierr); 3743 } 3744 ierr = VecGetArrayRead(coordsLocal, &coords);CHKERRQ(ierr); 3745 ierr = VecGetArray(coordsLocalNew, &coordsNew);CHKERRQ(ierr); 3746 ierr = PetscSectionGetChart(coordSection, &ocStart, &ocEnd);CHKERRQ(ierr); 3747 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3748 /* First set coordinates for vertices*/ 3749 for (p = pStart; p < pEnd; ++p) { 3750 DMPolytopeType ct; 3751 DMPolytopeType *rct; 3752 PetscInt *rsize, *rcone, *rornt; 3753 PetscInt Nct, n, r; 3754 PetscBool hasVertex = PETSC_FALSE, isLocalized = PETSC_FALSE; 3755 3756 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 3757 ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 3758 for (n = 0; n < Nct; ++n) { 3759 if (rct[n] == DM_POLYTOPE_POINT) {hasVertex = PETSC_TRUE; break;} 3760 } 3761 if (localizeVertices && ct != DM_POLYTOPE_POINT && (p >= ocStart) && (p < ocEnd)) { 3762 PetscInt dof; 3763 ierr = PetscSectionGetDof(coordSection, p, &dof);CHKERRQ(ierr); 3764 if (dof) isLocalized = PETSC_TRUE; 3765 } 3766 if (hasVertex) { 3767 const PetscScalar *icoords = NULL; 3768 PetscScalar *pcoords = NULL; 3769 PetscInt Nc, Nv, v, d; 3770 3771 ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, p, &Nc, &pcoords);CHKERRQ(ierr); 3772 3773 icoords = pcoords; 3774 Nv = Nc/dE; 3775 if (ct != DM_POLYTOPE_POINT) { 3776 if (localizeVertices) { 3777 PetscScalar anchor[3]; 3778 3779 for (d = 0; d < dE; ++d) anchor[d] = pcoords[d]; 3780 if (!isLocalized) { 3781 for (v = 0; v < Nv; ++v) {ierr = DMLocalizeCoordinate_Internal(dm, dE, anchor, &pcoords[v*dE], &pcoords[v*dE]);CHKERRQ(ierr);} 3782 } else { 3783 Nv = Nc/(2*dE); 3784 for (v = Nv; v < Nv*2; ++v) {ierr = DMLocalizeCoordinate_Internal(dm, dE, anchor, &pcoords[v*dE], &pcoords[v*dE]);CHKERRQ(ierr);} 3785 } 3786 } 3787 } 3788 for (n = 0; n < Nct; ++n) { 3789 if (rct[n] != DM_POLYTOPE_POINT) continue; 3790 for (r = 0; r < rsize[n]; ++r) { 3791 PetscScalar vcoords[3]; 3792 PetscInt vNew, off; 3793 3794 ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &vNew);CHKERRQ(ierr); 3795 ierr = PetscSectionGetOffset(coordSectionNew, vNew, &off);CHKERRQ(ierr); 3796 ierr = DMPlexCellRefinerMapCoordinates(cr, ct, rct[n], r, Nv, dE, icoords, vcoords);CHKERRQ(ierr); 3797 ierr = DMPlexSnapToGeomModel(dm, p, vcoords, &coordsNew[off]);CHKERRQ(ierr); 3798 } 3799 } 3800 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, p, &Nc, &pcoords);CHKERRQ(ierr); 3801 } 3802 } 3803 /* Then set coordinates for cells by localizing */ 3804 for (p = pStart; p < pEnd; ++p) { 3805 DMPolytopeType ct; 3806 DMPolytopeType *rct; 3807 PetscInt *rsize, *rcone, *rornt; 3808 PetscInt Nct, n, r; 3809 PetscBool isLocalized = PETSC_FALSE; 3810 3811 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 3812 ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 3813 if (localizeCells && ct != DM_POLYTOPE_POINT && (p >= ocStart) && (p < ocEnd)) { 3814 PetscInt dof; 3815 ierr = PetscSectionGetDof(coordSection, p, &dof);CHKERRQ(ierr); 3816 if (dof) isLocalized = PETSC_TRUE; 3817 } 3818 if (isLocalized) { 3819 const PetscScalar *pcoords; 3820 3821 ierr = DMPlexPointLocalRead(cdm, p, coords, &pcoords);CHKERRQ(ierr); 3822 for (n = 0; n < Nct; ++n) { 3823 const PetscInt Nr = rsize[n]; 3824 3825 if (DMPolytopeTypeGetDim(ct) != DMPolytopeTypeGetDim(rct[n])) continue; 3826 for (r = 0; r < Nr; ++r) { 3827 PetscInt pNew, offNew; 3828 3829 /* It looks like Stefano and Lisandro are allowing localized coordinates without defining the periodic boundary, which means that 3830 DMLocalizeCoordinate_Internal() will not work. Localized coordinates will have to have obtained by the affine map of the larger 3831 cell to the ones it produces. */ 3832 ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr); 3833 ierr = PetscSectionGetOffset(coordSectionNew, pNew, &offNew);CHKERRQ(ierr); 3834 ierr = DMPlexCellRefinerMapLocalizedCoordinates(cr, ct, rct[n], r, pcoords, &coordsNew[offNew]);CHKERRQ(ierr); 3835 } 3836 } 3837 } 3838 } 3839 ierr = VecRestoreArrayRead(coordsLocal, &coords);CHKERRQ(ierr); 3840 ierr = VecRestoreArray(coordsLocalNew, &coordsNew);CHKERRQ(ierr); 3841 ierr = DMSetCoordinatesLocal(rdm, coordsLocalNew);CHKERRQ(ierr); 3842 /* TODO Stefano has a final reduction if some hybrid coordinates cannot be found. (needcoords) Should not be needed. */ 3843 ierr = VecDestroy(&coordsLocalNew);CHKERRQ(ierr); 3844 ierr = PetscSectionDestroy(&coordSectionNew);CHKERRQ(ierr); 3845 if (!localizeCells) {ierr = DMLocalizeCoordinates(rdm);CHKERRQ(ierr);} 3846 PetscFunctionReturn(0); 3847 } 3848 3849 /*@ 3850 DMPlexCreateProcessSF - Create an SF which just has process connectivity 3851 3852 Collective on dm 3853 3854 Input Parameters: 3855 + dm - The DM 3856 - sfPoint - The PetscSF which encodes point connectivity 3857 3858 Output Parameters: 3859 + processRanks - A list of process neighbors, or NULL 3860 - sfProcess - An SF encoding the process connectivity, or NULL 3861 3862 Level: developer 3863 3864 .seealso: PetscSFCreate(), DMPlexCreateTwoSidedProcessSF() 3865 @*/ 3866 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 3867 { 3868 PetscInt numRoots, numLeaves, l; 3869 const PetscInt *localPoints; 3870 const PetscSFNode *remotePoints; 3871 PetscInt *localPointsNew; 3872 PetscSFNode *remotePointsNew; 3873 PetscInt *ranks, *ranksNew; 3874 PetscMPIInt size; 3875 PetscErrorCode ierr; 3876 3877 PetscFunctionBegin; 3878 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3879 PetscValidHeaderSpecific(sfPoint, PETSCSF_CLASSID, 2); 3880 if (processRanks) {PetscValidPointer(processRanks, 3);} 3881 if (sfProcess) {PetscValidPointer(sfProcess, 4);} 3882 ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size);CHKERRMPI(ierr); 3883 ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3884 ierr = PetscMalloc1(numLeaves, &ranks);CHKERRQ(ierr); 3885 for (l = 0; l < numLeaves; ++l) { 3886 ranks[l] = remotePoints[l].rank; 3887 } 3888 ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 3889 ierr = PetscMalloc1(numLeaves, &ranksNew);CHKERRQ(ierr); 3890 ierr = PetscMalloc1(numLeaves, &localPointsNew);CHKERRQ(ierr); 3891 ierr = PetscMalloc1(numLeaves, &remotePointsNew);CHKERRQ(ierr); 3892 for (l = 0; l < numLeaves; ++l) { 3893 ranksNew[l] = ranks[l]; 3894 localPointsNew[l] = l; 3895 remotePointsNew[l].index = 0; 3896 remotePointsNew[l].rank = ranksNew[l]; 3897 } 3898 ierr = PetscFree(ranks);CHKERRQ(ierr); 3899 if (processRanks) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr);} 3900 else {ierr = PetscFree(ranksNew);CHKERRQ(ierr);} 3901 if (sfProcess) { 3902 ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr); 3903 ierr = PetscObjectSetName((PetscObject) *sfProcess, "Process SF");CHKERRQ(ierr); 3904 ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 3905 ierr = PetscSFSetGraph(*sfProcess, size, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 3906 } 3907 PetscFunctionReturn(0); 3908 } 3909 3910 static PetscErrorCode DMPlexCellRefinerCreateSF(DMPlexCellRefiner cr, DM rdm) 3911 { 3912 DM dm = cr->dm; 3913 DMPlexCellRefiner *crRem; 3914 PetscSF sf, sfNew, sfProcess; 3915 IS processRanks; 3916 MPI_Datatype ctType; 3917 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 3918 const PetscInt *localPoints, *neighbors; 3919 const PetscSFNode *remotePoints; 3920 PetscInt *localPointsNew; 3921 PetscSFNode *remotePointsNew; 3922 PetscInt *ctStartRem, *ctStartNewRem; 3923 PetscInt ctSize = DM_NUM_POLYTOPES+1, numNeighbors, n, pStartNew, pEndNew, pNew, pNewRem; 3924 /* Brute force algorithm */ 3925 PetscSF rsf; 3926 PetscSection s; 3927 const PetscInt *rootdegree; 3928 PetscInt *rootPointsNew, *remoteOffsets; 3929 PetscInt numPointsNew, pStart, pEnd, p; 3930 PetscErrorCode ierr; 3931 3932 PetscFunctionBegin; 3933 ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 3934 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 3935 ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 3936 /* Calculate size of new SF */ 3937 ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3938 if (numRoots < 0) PetscFunctionReturn(0); 3939 for (l = 0; l < numLeaves; ++l) { 3940 const PetscInt p = localPoints[l]; 3941 DMPolytopeType ct; 3942 DMPolytopeType *rct; 3943 PetscInt *rsize, *rcone, *rornt; 3944 PetscInt Nct, n; 3945 3946 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 3947 ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 3948 for (n = 0; n < Nct; ++n) { 3949 numLeavesNew += rsize[n]; 3950 } 3951 } 3952 if (cr->refineType) { 3953 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3954 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &s);CHKERRQ(ierr); 3955 ierr = PetscSectionSetChart(s, pStart, pEnd);CHKERRQ(ierr); 3956 for (p = pStart; p < pEnd; ++p) { 3957 DMPolytopeType ct; 3958 DMPolytopeType *rct; 3959 PetscInt *rsize, *rcone, *rornt; 3960 PetscInt Nct, n; 3961 3962 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 3963 ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 3964 for (n = 0; n < Nct; ++n) { 3965 ierr = PetscSectionAddDof(s, p, rsize[n]);CHKERRQ(ierr); 3966 } 3967 } 3968 ierr = PetscSectionSetUp(s);CHKERRQ(ierr); 3969 ierr = PetscSectionGetStorageSize(s, &numPointsNew);CHKERRQ(ierr); 3970 ierr = PetscSFCreateRemoteOffsets(sf, s, s, &remoteOffsets);CHKERRQ(ierr); 3971 ierr = PetscSFCreateSectionSF(sf, s, remoteOffsets, s, &rsf);CHKERRQ(ierr); 3972 ierr = PetscFree(remoteOffsets);CHKERRQ(ierr); 3973 ierr = PetscSFComputeDegreeBegin(sf, &rootdegree);CHKERRQ(ierr); 3974 ierr = PetscSFComputeDegreeEnd(sf, &rootdegree);CHKERRQ(ierr); 3975 ierr = PetscMalloc1(numPointsNew, &rootPointsNew);CHKERRQ(ierr); 3976 for (p = 0; p < numPointsNew; ++p) rootPointsNew[p] = -1; 3977 for (p = pStart; p < pEnd; ++p) { 3978 DMPolytopeType ct; 3979 DMPolytopeType *rct; 3980 PetscInt *rsize, *rcone, *rornt; 3981 PetscInt Nct, n, r, off; 3982 3983 if (!rootdegree[p-pStart]) continue; 3984 ierr = PetscSectionGetOffset(s, p, &off);CHKERRQ(ierr); 3985 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 3986 ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 3987 for (n = 0, m = 0; n < Nct; ++n) { 3988 for (r = 0; r < rsize[n]; ++r, ++m) { 3989 ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr); 3990 rootPointsNew[off+m] = pNew; 3991 } 3992 } 3993 } 3994 ierr = PetscSFBcastBegin(rsf, MPIU_INT, rootPointsNew, rootPointsNew,MPI_REPLACE);CHKERRQ(ierr); 3995 ierr = PetscSFBcastEnd(rsf, MPIU_INT, rootPointsNew, rootPointsNew,MPI_REPLACE);CHKERRQ(ierr); 3996 ierr = PetscSFDestroy(&rsf);CHKERRQ(ierr); 3997 ierr = PetscMalloc1(numLeavesNew, &localPointsNew);CHKERRQ(ierr); 3998 ierr = PetscMalloc1(numLeavesNew, &remotePointsNew);CHKERRQ(ierr); 3999 for (l = 0, m = 0; l < numLeaves; ++l) { 4000 const PetscInt p = localPoints[l]; 4001 DMPolytopeType ct; 4002 DMPolytopeType *rct; 4003 PetscInt *rsize, *rcone, *rornt; 4004 PetscInt Nct, n, r, q, off; 4005 4006 ierr = PetscSectionGetOffset(s, p, &off);CHKERRQ(ierr); 4007 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 4008 ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 4009 for (n = 0, q = 0; n < Nct; ++n) { 4010 for (r = 0; r < rsize[n]; ++r, ++m, ++q) { 4011 ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr); 4012 localPointsNew[m] = pNew; 4013 remotePointsNew[m].index = rootPointsNew[off+q]; 4014 remotePointsNew[m].rank = remotePoints[l].rank; 4015 } 4016 } 4017 } 4018 ierr = PetscSectionDestroy(&s);CHKERRQ(ierr); 4019 ierr = PetscFree(rootPointsNew);CHKERRQ(ierr); 4020 } else { 4021 /* Communicate ctStart and cStartNew for each remote rank */ 4022 ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 4023 ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 4024 ierr = PetscMalloc2(ctSize*numNeighbors, &ctStartRem, ctSize*numNeighbors, &ctStartNewRem);CHKERRQ(ierr); 4025 ierr = MPI_Type_contiguous(ctSize, MPIU_INT, &ctType);CHKERRMPI(ierr); 4026 ierr = MPI_Type_commit(&ctType);CHKERRMPI(ierr); 4027 ierr = PetscSFBcastBegin(sfProcess, ctType, cr->ctStart, ctStartRem,MPI_REPLACE);CHKERRQ(ierr); 4028 ierr = PetscSFBcastEnd(sfProcess, ctType, cr->ctStart, ctStartRem,MPI_REPLACE);CHKERRQ(ierr); 4029 ierr = PetscSFBcastBegin(sfProcess, ctType, cr->ctStartNew, ctStartNewRem,MPI_REPLACE);CHKERRQ(ierr); 4030 ierr = PetscSFBcastEnd(sfProcess, ctType, cr->ctStartNew, ctStartNewRem,MPI_REPLACE);CHKERRQ(ierr); 4031 ierr = MPI_Type_free(&ctType);CHKERRMPI(ierr); 4032 ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 4033 ierr = PetscMalloc1(numNeighbors, &crRem);CHKERRQ(ierr); 4034 for (n = 0; n < numNeighbors; ++n) { 4035 ierr = DMPlexCellRefinerCreate(dm, &crRem[n]);CHKERRQ(ierr); 4036 ierr = DMPlexCellRefinerSetStarts(crRem[n], &ctStartRem[n*ctSize], &ctStartNewRem[n*ctSize]); 4037 ierr = DMPlexCellRefinerSetUp(crRem[n]);CHKERRQ(ierr); 4038 } 4039 ierr = PetscFree2(ctStartRem, ctStartNewRem);CHKERRQ(ierr); 4040 /* Calculate new point SF */ 4041 ierr = PetscMalloc1(numLeavesNew, &localPointsNew);CHKERRQ(ierr); 4042 ierr = PetscMalloc1(numLeavesNew, &remotePointsNew);CHKERRQ(ierr); 4043 ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 4044 for (l = 0, m = 0; l < numLeaves; ++l) { 4045 PetscInt p = localPoints[l]; 4046 PetscInt pRem = remotePoints[l].index; 4047 PetscMPIInt rankRem = remotePoints[l].rank; 4048 DMPolytopeType ct; 4049 DMPolytopeType *rct; 4050 PetscInt *rsize, *rcone, *rornt; 4051 PetscInt neighbor, Nct, n, r; 4052 4053 ierr = PetscFindInt(rankRem, numNeighbors, neighbors, &neighbor);CHKERRQ(ierr); 4054 if (neighbor < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %D", rankRem); 4055 ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr); 4056 ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 4057 for (n = 0; n < Nct; ++n) { 4058 for (r = 0; r < rsize[n]; ++r) { 4059 ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr); 4060 ierr = DMPlexCellRefinerGetNewPoint(crRem[neighbor], ct, rct[n], pRem, r, &pNewRem);CHKERRQ(ierr); 4061 localPointsNew[m] = pNew; 4062 remotePointsNew[m].index = pNewRem; 4063 remotePointsNew[m].rank = rankRem; 4064 ++m; 4065 } 4066 } 4067 } 4068 for (n = 0; n < numNeighbors; ++n) {ierr = DMPlexCellRefinerDestroy(&crRem[n]);CHKERRQ(ierr);} 4069 ierr = PetscFree(crRem);CHKERRQ(ierr); 4070 if (m != numLeavesNew) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of leaf point %D should be %D", m, numLeavesNew); 4071 ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 4072 ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 4073 } 4074 { 4075 PetscSFNode *rp, *rtmp; 4076 PetscInt *lp, *idx, *ltmp, i; 4077 4078 /* SF needs sorted leaves to correct calculate Gather */ 4079 ierr = PetscMalloc1(numLeavesNew, &idx);CHKERRQ(ierr); 4080 ierr = PetscMalloc1(numLeavesNew, &lp);CHKERRQ(ierr); 4081 ierr = PetscMalloc1(numLeavesNew, &rp);CHKERRQ(ierr); 4082 for (i = 0; i < numLeavesNew; ++i) { 4083 if ((localPointsNew[i] < pStartNew) || (localPointsNew[i] >= pEndNew)) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Local SF point %D (%D) not in [%D, %D)", localPointsNew[i], i, pStartNew, pEndNew); 4084 idx[i] = i; 4085 } 4086 ierr = PetscSortIntWithPermutation(numLeavesNew, localPointsNew, idx);CHKERRQ(ierr); 4087 for (i = 0; i < numLeavesNew; ++i) { 4088 lp[i] = localPointsNew[idx[i]]; 4089 rp[i] = remotePointsNew[idx[i]]; 4090 } 4091 ltmp = localPointsNew; 4092 localPointsNew = lp; 4093 rtmp = remotePointsNew; 4094 remotePointsNew = rp; 4095 ierr = PetscFree(idx);CHKERRQ(ierr); 4096 ierr = PetscFree(ltmp);CHKERRQ(ierr); 4097 ierr = PetscFree(rtmp);CHKERRQ(ierr); 4098 } 4099 ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 4100 PetscFunctionReturn(0); 4101 } 4102 4103 static PetscErrorCode RefineLabel_Internal(DMPlexCellRefiner cr, DMLabel label, DMLabel labelNew) 4104 { 4105 DM dm = cr->dm; 4106 IS valueIS; 4107 const PetscInt *values; 4108 PetscInt defVal, Nv, val; 4109 PetscErrorCode ierr; 4110 4111 PetscFunctionBegin; 4112 ierr = DMLabelGetDefaultValue(label, &defVal);CHKERRQ(ierr); 4113 ierr = DMLabelSetDefaultValue(labelNew, defVal);CHKERRQ(ierr); 4114 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 4115 ierr = ISGetLocalSize(valueIS, &Nv);CHKERRQ(ierr); 4116 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 4117 for (val = 0; val < Nv; ++val) { 4118 IS pointIS; 4119 const PetscInt *points; 4120 PetscInt numPoints, p; 4121 4122 /* Ensure refined label is created with same number of strata as 4123 * original (even if no entries here). */ 4124 ierr = DMLabelAddStratum(labelNew, values[val]);CHKERRQ(ierr); 4125 ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 4126 ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 4127 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 4128 for (p = 0; p < numPoints; ++p) { 4129 const PetscInt point = points[p]; 4130 DMPolytopeType ct; 4131 DMPolytopeType *rct; 4132 PetscInt *rsize, *rcone, *rornt; 4133 PetscInt Nct, n, r, pNew=0; 4134 4135 ierr = DMPlexGetCellType(dm, point, &ct);CHKERRQ(ierr); 4136 ierr = DMPlexCellRefinerRefine(cr, ct, point, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr); 4137 for (n = 0; n < Nct; ++n) { 4138 for (r = 0; r < rsize[n]; ++r) { 4139 ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], point, r, &pNew);CHKERRQ(ierr); 4140 ierr = DMLabelSetValue(labelNew, pNew, values[val]);CHKERRQ(ierr); 4141 } 4142 } 4143 } 4144 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 4145 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 4146 } 4147 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 4148 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 4149 PetscFunctionReturn(0); 4150 } 4151 4152 static PetscErrorCode DMPlexCellRefinerCreateLabels(DMPlexCellRefiner cr, DM rdm) 4153 { 4154 DM dm = cr->dm; 4155 PetscInt numLabels, l; 4156 PetscErrorCode ierr; 4157 4158 PetscFunctionBegin; 4159 ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 4160 for (l = 0; l < numLabels; ++l) { 4161 DMLabel label, labelNew; 4162 const char *lname; 4163 PetscBool isDepth, isCellType; 4164 4165 ierr = DMGetLabelName(dm, l, &lname);CHKERRQ(ierr); 4166 ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 4167 if (isDepth) continue; 4168 ierr = PetscStrcmp(lname, "celltype", &isCellType);CHKERRQ(ierr); 4169 if (isCellType) continue; 4170 ierr = DMCreateLabel(rdm, lname);CHKERRQ(ierr); 4171 ierr = DMGetLabel(dm, lname, &label);CHKERRQ(ierr); 4172 ierr = DMGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 4173 ierr = RefineLabel_Internal(cr, label, labelNew);CHKERRQ(ierr); 4174 } 4175 PetscFunctionReturn(0); 4176 } 4177 4178 /* This will only work for interpolated meshes */ 4179 PetscErrorCode DMPlexRefineUniform(DM dm, DMPlexCellRefiner cr, DM *dmRefined) 4180 { 4181 DM rdm; 4182 PetscInt dim, embedDim, depth; 4183 PetscErrorCode ierr; 4184 4185 PetscFunctionBegin; 4186 PetscValidHeader(cr, 2); 4187 ierr = DMCreate(PetscObjectComm((PetscObject)dm), &rdm);CHKERRQ(ierr); 4188 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 4189 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 4190 ierr = DMSetDimension(rdm, dim);CHKERRQ(ierr); 4191 ierr = DMGetCoordinateDim(dm, &embedDim);CHKERRQ(ierr); 4192 ierr = DMSetCoordinateDim(rdm, embedDim);CHKERRQ(ierr); 4193 /* Calculate number of new points of each depth */ 4194 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4195 if (depth >= 0 && dim != depth) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Mesh must be interpolated for regular refinement"); 4196 /* Step 1: Set chart */ 4197 ierr = DMPlexSetChart(rdm, 0, cr->ctStartNew[cr->ctOrder[DM_NUM_POLYTOPES]]);CHKERRQ(ierr); 4198 /* Step 2: Set cone/support sizes (automatically stratifies) */ 4199 ierr = DMPlexCellRefinerSetConeSizes(cr, rdm);CHKERRQ(ierr); 4200 /* Step 3: Setup refined DM */ 4201 ierr = DMSetUp(rdm);CHKERRQ(ierr); 4202 /* Step 4: Set cones and supports (automatically symmetrizes) */ 4203 ierr = DMPlexCellRefinerSetCones(cr, rdm);CHKERRQ(ierr); 4204 /* Step 5: Create pointSF */ 4205 ierr = DMPlexCellRefinerCreateSF(cr, rdm);CHKERRQ(ierr); 4206 /* Step 6: Create labels */ 4207 ierr = DMPlexCellRefinerCreateLabels(cr, rdm);CHKERRQ(ierr); 4208 /* Step 7: Set coordinates */ 4209 ierr = DMPlexCellRefinerSetCoordinates(cr, rdm);CHKERRQ(ierr); 4210 *dmRefined = rdm; 4211 PetscFunctionReturn(0); 4212 } 4213 4214 /*@ 4215 DMPlexCreateCoarsePointIS - Creates an IS covering the coarse DM chart with the fine points as data 4216 4217 Input Parameter: 4218 . dm - The coarse DM 4219 4220 Output Parameter: 4221 . fpointIS - The IS of all the fine points which exist in the original coarse mesh 4222 4223 Level: developer 4224 4225 .seealso: DMRefine(), DMPlexSetRefinementUniform(), DMPlexGetSubpointIS() 4226 @*/ 4227 PetscErrorCode DMPlexCreateCoarsePointIS(DM dm, IS *fpointIS) 4228 { 4229 DMPlexCellRefiner cr; 4230 PetscInt *fpoints; 4231 PetscInt pStart, pEnd, p, vStart, vEnd, v; 4232 PetscErrorCode ierr; 4233 4234 PetscFunctionBegin; 4235 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 4236 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4237 ierr = DMPlexCellRefinerCreate(dm, &cr);CHKERRQ(ierr); 4238 ierr = DMPlexCellRefinerSetUp(cr);CHKERRQ(ierr); 4239 ierr = PetscMalloc1(pEnd-pStart, &fpoints);CHKERRQ(ierr); 4240 for (p = 0; p < pEnd-pStart; ++p) fpoints[p] = -1; 4241 for (v = vStart; v < vEnd; ++v) { 4242 PetscInt vNew = -1; /* silent overzelous may be used uninitialized */ 4243 4244 ierr = DMPlexCellRefinerGetNewPoint(cr, DM_POLYTOPE_POINT, DM_POLYTOPE_POINT, p, 0, &vNew);CHKERRQ(ierr); 4245 fpoints[v-pStart] = vNew; 4246 } 4247 ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr); 4248 ierr = ISCreateGeneral(PETSC_COMM_SELF, pEnd-pStart, fpoints, PETSC_OWN_POINTER, fpointIS);CHKERRQ(ierr); 4249 PetscFunctionReturn(0); 4250 } 4251 4252 /*@ 4253 DMPlexSetRefinementUniform - Set the flag for uniform refinement 4254 4255 Input Parameters: 4256 + dm - The DM 4257 - refinementUniform - The flag for uniform refinement 4258 4259 Level: developer 4260 4261 .seealso: DMRefine(), DMPlexGetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit() 4262 @*/ 4263 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 4264 { 4265 DM_Plex *mesh = (DM_Plex*) dm->data; 4266 4267 PetscFunctionBegin; 4268 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4269 mesh->refinementUniform = refinementUniform; 4270 PetscFunctionReturn(0); 4271 } 4272 4273 /*@ 4274 DMPlexGetRefinementUniform - Retrieve the flag for uniform refinement 4275 4276 Input Parameter: 4277 . dm - The DM 4278 4279 Output Parameter: 4280 . refinementUniform - The flag for uniform refinement 4281 4282 Level: developer 4283 4284 .seealso: DMRefine(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit() 4285 @*/ 4286 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 4287 { 4288 DM_Plex *mesh = (DM_Plex*) dm->data; 4289 4290 PetscFunctionBegin; 4291 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4292 PetscValidPointer(refinementUniform, 2); 4293 *refinementUniform = mesh->refinementUniform; 4294 PetscFunctionReturn(0); 4295 } 4296 4297 /*@ 4298 DMPlexSetRefinementLimit - Set the maximum cell volume for refinement 4299 4300 Input Parameters: 4301 + dm - The DM 4302 - refinementLimit - The maximum cell volume in the refined mesh 4303 4304 Level: developer 4305 4306 .seealso: DMRefine(), DMPlexGetRefinementLimit(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform() 4307 @*/ 4308 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 4309 { 4310 DM_Plex *mesh = (DM_Plex*) dm->data; 4311 4312 PetscFunctionBegin; 4313 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4314 mesh->refinementLimit = refinementLimit; 4315 PetscFunctionReturn(0); 4316 } 4317 4318 /*@ 4319 DMPlexGetRefinementLimit - Retrieve the maximum cell volume for refinement 4320 4321 Input Parameter: 4322 . dm - The DM 4323 4324 Output Parameter: 4325 . refinementLimit - The maximum cell volume in the refined mesh 4326 4327 Level: developer 4328 4329 .seealso: DMRefine(), DMPlexSetRefinementLimit(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform() 4330 @*/ 4331 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 4332 { 4333 DM_Plex *mesh = (DM_Plex*) dm->data; 4334 4335 PetscFunctionBegin; 4336 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4337 PetscValidPointer(refinementLimit, 2); 4338 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 4339 *refinementLimit = mesh->refinementLimit; 4340 PetscFunctionReturn(0); 4341 } 4342 4343 /*@ 4344 DMPlexSetRefinementFunction - Set the function giving the maximum cell volume for refinement 4345 4346 Input Parameters: 4347 + dm - The DM 4348 - refinementFunc - Function giving the maximum cell volume in the refined mesh 4349 4350 Note: The calling sequence is refinementFunc(coords, limit) 4351 $ coords - Coordinates of the current point, usually a cell centroid 4352 $ limit - The maximum cell volume for a cell containing this point 4353 4354 Level: developer 4355 4356 .seealso: DMRefine(), DMPlexGetRefinementFunction(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit() 4357 @*/ 4358 PetscErrorCode DMPlexSetRefinementFunction(DM dm, PetscErrorCode (*refinementFunc)(const PetscReal [], PetscReal *)) 4359 { 4360 DM_Plex *mesh = (DM_Plex*) dm->data; 4361 4362 PetscFunctionBegin; 4363 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4364 mesh->refinementFunc = refinementFunc; 4365 PetscFunctionReturn(0); 4366 } 4367 4368 /*@ 4369 DMPlexGetRefinementFunction - Get the function giving the maximum cell volume for refinement 4370 4371 Input Parameter: 4372 . dm - The DM 4373 4374 Output Parameter: 4375 . refinementFunc - Function giving the maximum cell volume in the refined mesh 4376 4377 Note: The calling sequence is refinementFunc(coords, limit) 4378 $ coords - Coordinates of the current point, usually a cell centroid 4379 $ limit - The maximum cell volume for a cell containing this point 4380 4381 Level: developer 4382 4383 .seealso: DMRefine(), DMPlexSetRefinementFunction(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit() 4384 @*/ 4385 PetscErrorCode DMPlexGetRefinementFunction(DM dm, PetscErrorCode (**refinementFunc)(const PetscReal [], PetscReal *)) 4386 { 4387 DM_Plex *mesh = (DM_Plex*) dm->data; 4388 4389 PetscFunctionBegin; 4390 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4391 PetscValidPointer(refinementFunc, 2); 4392 *refinementFunc = mesh->refinementFunc; 4393 PetscFunctionReturn(0); 4394 } 4395 4396 static PetscErrorCode RefineDiscLabels_Internal(DMPlexCellRefiner cr, DM rdm) 4397 { 4398 DM dm = cr->dm; 4399 PetscInt Nf, f, Nds, s; 4400 PetscErrorCode ierr; 4401 4402 PetscFunctionBegin; 4403 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 4404 for (f = 0; f < Nf; ++f) { 4405 DMLabel label, labelNew; 4406 PetscObject obj; 4407 const char *lname; 4408 4409 ierr = DMGetField(rdm, f, &label, &obj);CHKERRQ(ierr); 4410 if (!label) continue; 4411 ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr); 4412 ierr = DMLabelCreate(PETSC_COMM_SELF, lname, &labelNew);CHKERRQ(ierr); 4413 ierr = RefineLabel_Internal(cr, label, labelNew);CHKERRQ(ierr); 4414 ierr = DMSetField_Internal(rdm, f, labelNew, obj);CHKERRQ(ierr); 4415 ierr = DMLabelDestroy(&labelNew);CHKERRQ(ierr); 4416 } 4417 ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr); 4418 for (s = 0; s < Nds; ++s) { 4419 DMLabel label, labelNew; 4420 const char *lname; 4421 4422 ierr = DMGetRegionNumDS(rdm, s, &label, NULL, NULL);CHKERRQ(ierr); 4423 if (!label) continue; 4424 ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr); 4425 ierr = DMLabelCreate(PETSC_COMM_SELF, lname, &labelNew);CHKERRQ(ierr); 4426 ierr = RefineLabel_Internal(cr, label, labelNew);CHKERRQ(ierr); 4427 ierr = DMSetRegionNumDS(rdm, s, labelNew, NULL, NULL);CHKERRQ(ierr); 4428 ierr = DMLabelDestroy(&labelNew);CHKERRQ(ierr); 4429 } 4430 PetscFunctionReturn(0); 4431 } 4432 4433 PetscErrorCode DMPlexCellRefinerAdaptLabel(DM dm, DMLabel adaptLabel, DM *dmRefined) 4434 { 4435 DMPlexCellRefiner cr; 4436 DM cdm, rcdm; 4437 PetscErrorCode ierr; 4438 4439 PetscFunctionBegin; 4440 ierr = DMPlexCellRefinerCreate(dm, &cr);CHKERRQ(ierr); 4441 cr->adaptLabel = adaptLabel; 4442 ierr = DMPlexCellRefinerSetUp(cr);CHKERRQ(ierr); 4443 ierr = DMPlexRefineUniform(dm, cr, dmRefined);CHKERRQ(ierr); 4444 ierr = DMCopyDisc(dm, *dmRefined);CHKERRQ(ierr); 4445 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4446 ierr = DMGetCoordinateDM(*dmRefined, &rcdm);CHKERRQ(ierr); 4447 ierr = DMCopyDisc(cdm, rcdm);CHKERRQ(ierr); 4448 ierr = RefineDiscLabels_Internal(cr, *dmRefined);CHKERRQ(ierr); 4449 ierr = DMCopyDisc(dm, *dmRefined);CHKERRQ(ierr); 4450 ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr); 4451 PetscFunctionReturn(0); 4452 } 4453 4454 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 4455 { 4456 PetscBool isUniform; 4457 DMPlexCellRefiner cr; 4458 PetscErrorCode ierr; 4459 4460 PetscFunctionBegin; 4461 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 4462 ierr = DMViewFromOptions(dm, NULL, "-initref_dm_view");CHKERRQ(ierr); 4463 if (isUniform) { 4464 DM cdm, rcdm; 4465 PetscBool localized; 4466 4467 ierr = DMPlexCellRefinerCreate(dm, &cr);CHKERRQ(ierr); 4468 ierr = DMPlexCellRefinerSetUp(cr);CHKERRQ(ierr); 4469 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 4470 ierr = DMPlexRefineUniform(dm, cr, dmRefined);CHKERRQ(ierr); 4471 ierr = DMPlexSetRegularRefinement(*dmRefined, PETSC_TRUE);CHKERRQ(ierr); 4472 ierr = DMCopyDisc(dm, *dmRefined);CHKERRQ(ierr); 4473 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 4474 ierr = DMGetCoordinateDM(*dmRefined, &rcdm);CHKERRQ(ierr); 4475 ierr = DMCopyDisc(cdm, rcdm);CHKERRQ(ierr); 4476 ierr = RefineDiscLabels_Internal(cr, *dmRefined);CHKERRQ(ierr); 4477 ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr); 4478 } else { 4479 ierr = DMPlexRefine_Internal(dm, NULL, dmRefined);CHKERRQ(ierr); 4480 } 4481 if (*dmRefined) { 4482 ((DM_Plex *) (*dmRefined)->data)->printFEM = ((DM_Plex *) dm->data)->printFEM; 4483 ((DM_Plex *) (*dmRefined)->data)->printL2 = ((DM_Plex *) dm->data)->printL2; 4484 } 4485 PetscFunctionReturn(0); 4486 } 4487 4488 PetscErrorCode DMRefineHierarchy_Plex(DM dm, PetscInt nlevels, DM dmRefined[]) 4489 { 4490 DM cdm = dm; 4491 PetscInt r; 4492 PetscBool isUniform, localized; 4493 PetscErrorCode ierr; 4494 4495 PetscFunctionBegin; 4496 ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 4497 ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr); 4498 if (isUniform) { 4499 for (r = 0; r < nlevels; ++r) { 4500 DMPlexCellRefiner cr; 4501 DM codm, rcodm; 4502 4503 ierr = DMPlexCellRefinerCreate(cdm, &cr);CHKERRQ(ierr); 4504 ierr = DMPlexCellRefinerSetUp(cr);CHKERRQ(ierr); 4505 ierr = DMPlexRefineUniform(cdm, cr, &dmRefined[r]);CHKERRQ(ierr); 4506 ierr = DMSetCoarsenLevel(dmRefined[r], cdm->leveldown);CHKERRQ(ierr); 4507 ierr = DMSetRefineLevel(dmRefined[r], cdm->levelup+1);CHKERRQ(ierr); 4508 ierr = DMCopyDisc(cdm, dmRefined[r]);CHKERRQ(ierr); 4509 ierr = DMGetCoordinateDM(dm, &codm);CHKERRQ(ierr); 4510 ierr = DMGetCoordinateDM(dmRefined[r], &rcodm);CHKERRQ(ierr); 4511 ierr = DMCopyDisc(codm, rcodm);CHKERRQ(ierr); 4512 ierr = RefineDiscLabels_Internal(cr, dmRefined[r]);CHKERRQ(ierr); 4513 ierr = DMSetCoarseDM(dmRefined[r], cdm);CHKERRQ(ierr); 4514 ierr = DMPlexSetRegularRefinement(dmRefined[r], PETSC_TRUE);CHKERRQ(ierr); 4515 if (dmRefined[r]) { 4516 ((DM_Plex *) (dmRefined[r])->data)->printFEM = ((DM_Plex *) dm->data)->printFEM; 4517 ((DM_Plex *) (dmRefined[r])->data)->printL2 = ((DM_Plex *) dm->data)->printL2; 4518 } 4519 cdm = dmRefined[r]; 4520 ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr); 4521 } 4522 } else { 4523 for (r = 0; r < nlevels; ++r) { 4524 ierr = DMRefine(cdm, PetscObjectComm((PetscObject) dm), &dmRefined[r]);CHKERRQ(ierr); 4525 ierr = DMCopyDisc(cdm, dmRefined[r]);CHKERRQ(ierr); 4526 if (localized) {ierr = DMLocalizeCoordinates(dmRefined[r]);CHKERRQ(ierr);} 4527 ierr = DMSetCoarseDM(dmRefined[r], cdm);CHKERRQ(ierr); 4528 if (dmRefined[r]) { 4529 ((DM_Plex *) (dmRefined[r])->data)->printFEM = ((DM_Plex *) dm->data)->printFEM; 4530 ((DM_Plex *) (dmRefined[r])->data)->printL2 = ((DM_Plex *) dm->data)->printL2; 4531 } 4532 cdm = dmRefined[r]; 4533 } 4534 } 4535 PetscFunctionReturn(0); 4536 } 4537