1 #define PETSCDM_DLL 2 #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 3 #include <petscdmda.h> 4 #include <petscsf.h> 5 6 /*@ 7 DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement. 8 9 Collective on MPI_Comm 10 11 Input Parameters: 12 + comm - The communicator for the DM object 13 . dim - The spatial dimension 14 . simplex - Flag for simplicial cells, otherwise they are tensor product cells 15 . interpolate - Flag to create intermediate mesh pieces (edges, faces) 16 . refinementUniform - Flag for uniform parallel refinement 17 - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell 18 19 Output Parameter: 20 . dm - The DM object 21 22 Level: beginner 23 24 .keywords: DM, create 25 .seealso: DMSetType(), DMCreate() 26 @*/ 27 PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscBool refinementUniform, PetscReal refinementLimit, DM *newdm) 28 { 29 DM dm; 30 PetscInt p; 31 PetscMPIInt rank; 32 PetscErrorCode ierr; 33 34 PetscFunctionBegin; 35 ierr = DMCreate(comm, &dm);CHKERRQ(ierr); 36 ierr = DMSetType(dm, DMPLEX);CHKERRQ(ierr); 37 ierr = DMSetDimension(dm, dim);CHKERRQ(ierr); 38 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 39 switch (dim) { 40 case 2: 41 if (simplex) {ierr = PetscObjectSetName((PetscObject) dm, "triangular");CHKERRQ(ierr);} 42 else {ierr = PetscObjectSetName((PetscObject) dm, "quadrilateral");CHKERRQ(ierr);} 43 break; 44 case 3: 45 if (simplex) {ierr = PetscObjectSetName((PetscObject) dm, "tetrahedral");CHKERRQ(ierr);} 46 else {ierr = PetscObjectSetName((PetscObject) dm, "hexahedral");CHKERRQ(ierr);} 47 break; 48 default: 49 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %d", dim); 50 } 51 if (rank) { 52 PetscInt numPoints[2] = {0, 0}; 53 ierr = DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 54 } else { 55 switch (dim) { 56 case 2: 57 if (simplex) { 58 PetscInt numPoints[2] = {4, 2}; 59 PetscInt coneSize[6] = {3, 3, 0, 0, 0, 0}; 60 PetscInt cones[6] = {2, 3, 4, 5, 4, 3}; 61 PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 62 PetscScalar vertexCoords[8] = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5}; 63 PetscInt markerPoints[8] = {2, 1, 3, 1, 4, 1, 5, 1}; 64 65 ierr = DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 66 for (p = 0; p < 4; ++p) {ierr = DMSetLabelValue(dm, "marker", markerPoints[p*2], markerPoints[p*2+1]);CHKERRQ(ierr);} 67 } else { 68 PetscInt numPoints[2] = {6, 2}; 69 PetscInt coneSize[8] = {4, 4, 0, 0, 0, 0, 0, 0}; 70 PetscInt cones[8] = {2, 3, 4, 5, 3, 6, 7, 4}; 71 PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 72 PetscScalar vertexCoords[12] = {-1.0, -0.5, 0.0, -0.5, 0.0, 0.5, -1.0, 0.5, 1.0, -0.5, 1.0, 0.5}; 73 74 ierr = DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 75 } 76 break; 77 case 3: 78 if (simplex) { 79 PetscInt numPoints[2] = {5, 2}; 80 PetscInt coneSize[7] = {4, 4, 0, 0, 0, 0, 0}; 81 PetscInt cones[8] = {4, 3, 5, 2, 5, 3, 4, 6}; 82 PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 83 PetscScalar vertexCoords[15] = {-1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0}; 84 PetscInt markerPoints[10] = {2, 1, 3, 1, 4, 1, 5, 1, 6, 1}; 85 86 ierr = DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 87 for (p = 0; p < 5; ++p) {ierr = DMSetLabelValue(dm, "marker", markerPoints[p*2], markerPoints[p*2+1]);CHKERRQ(ierr);} 88 } else { 89 PetscInt numPoints[2] = {12, 2}; 90 PetscInt coneSize[14] = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 91 PetscInt cones[16] = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8}; 92 PetscInt coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 93 PetscScalar vertexCoords[36] = {-1.0, -0.5, -0.5, -1.0, 0.5, -0.5, 0.0, 0.5, -0.5, 0.0, -0.5, -0.5, 94 -1.0, -0.5, 0.5, 0.0, -0.5, 0.5, 0.0, 0.5, 0.5, -1.0, 0.5, 0.5, 95 1.0, 0.5, -0.5, 1.0, -0.5, -0.5, 1.0, -0.5, 0.5, 1.0, 0.5, 0.5}; 96 97 ierr = DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 98 } 99 break; 100 default: 101 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %d", dim); 102 } 103 } 104 *newdm = dm; 105 if (refinementLimit > 0.0) { 106 DM rdm; 107 const char *name; 108 109 ierr = DMPlexSetRefinementUniform(*newdm, PETSC_FALSE);CHKERRQ(ierr); 110 ierr = DMPlexSetRefinementLimit(*newdm, refinementLimit);CHKERRQ(ierr); 111 ierr = DMRefine(*newdm, comm, &rdm);CHKERRQ(ierr); 112 ierr = PetscObjectGetName((PetscObject) *newdm, &name);CHKERRQ(ierr); 113 ierr = PetscObjectSetName((PetscObject) rdm, name);CHKERRQ(ierr); 114 ierr = DMDestroy(newdm);CHKERRQ(ierr); 115 *newdm = rdm; 116 } 117 if (interpolate) { 118 DM idm = NULL; 119 const char *name; 120 121 ierr = DMPlexInterpolate(*newdm, &idm);CHKERRQ(ierr); 122 ierr = PetscObjectGetName((PetscObject) *newdm, &name);CHKERRQ(ierr); 123 ierr = PetscObjectSetName((PetscObject) idm, name);CHKERRQ(ierr); 124 ierr = DMPlexCopyCoordinates(*newdm, idm);CHKERRQ(ierr); 125 ierr = DMCopyLabels(*newdm, idm);CHKERRQ(ierr); 126 ierr = DMDestroy(newdm);CHKERRQ(ierr); 127 *newdm = idm; 128 } 129 { 130 DM refinedMesh = NULL; 131 DM distributedMesh = NULL; 132 133 /* Distribute mesh over processes */ 134 ierr = DMPlexDistribute(*newdm, 0, NULL, &distributedMesh);CHKERRQ(ierr); 135 if (distributedMesh) { 136 ierr = DMDestroy(newdm);CHKERRQ(ierr); 137 *newdm = distributedMesh; 138 } 139 if (refinementUniform) { 140 ierr = DMPlexSetRefinementUniform(*newdm, refinementUniform);CHKERRQ(ierr); 141 ierr = DMRefine(*newdm, comm, &refinedMesh);CHKERRQ(ierr); 142 if (refinedMesh) { 143 ierr = DMDestroy(newdm);CHKERRQ(ierr); 144 *newdm = refinedMesh; 145 } 146 } 147 } 148 PetscFunctionReturn(0); 149 } 150 151 /*@ 152 DMPlexCreateSquareBoundary - Creates a 1D mesh the is the boundary of a square lattice. 153 154 Collective on MPI_Comm 155 156 Input Parameters: 157 + comm - The communicator for the DM object 158 . lower - The lower left corner coordinates 159 . upper - The upper right corner coordinates 160 - edges - The number of cells in each direction 161 162 Output Parameter: 163 . dm - The DM object 164 165 Note: Here is the numbering returned for 2 cells in each direction: 166 $ 18--5-17--4--16 167 $ | | | 168 $ 6 10 3 169 $ | | | 170 $ 19-11-20--9--15 171 $ | | | 172 $ 7 8 2 173 $ | | | 174 $ 12--0-13--1--14 175 176 Level: beginner 177 178 .keywords: DM, create 179 .seealso: DMPlexCreateBoxMesh(), DMPlexCreateCubeBoundary(), DMSetType(), DMCreate() 180 @*/ 181 PetscErrorCode DMPlexCreateSquareBoundary(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 182 { 183 const PetscInt numVertices = (edges[0]+1)*(edges[1]+1); 184 const PetscInt numEdges = edges[0]*(edges[1]+1) + (edges[0]+1)*edges[1]; 185 PetscInt markerTop = 1; 186 PetscInt markerBottom = 1; 187 PetscInt markerRight = 1; 188 PetscInt markerLeft = 1; 189 PetscBool markerSeparate = PETSC_FALSE; 190 Vec coordinates; 191 PetscSection coordSection; 192 PetscScalar *coords; 193 PetscInt coordSize; 194 PetscMPIInt rank; 195 PetscInt v, vx, vy; 196 PetscErrorCode ierr; 197 198 PetscFunctionBegin; 199 ierr = PetscOptionsGetBool(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL);CHKERRQ(ierr); 200 if (markerSeparate) { 201 markerTop = 3; 202 markerBottom = 1; 203 markerRight = 2; 204 markerLeft = 4; 205 } 206 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 207 if (!rank) { 208 PetscInt e, ex, ey; 209 210 ierr = DMPlexSetChart(dm, 0, numEdges+numVertices);CHKERRQ(ierr); 211 for (e = 0; e < numEdges; ++e) { 212 ierr = DMPlexSetConeSize(dm, e, 2);CHKERRQ(ierr); 213 } 214 ierr = DMSetUp(dm);CHKERRQ(ierr); /* Allocate space for cones */ 215 for (vx = 0; vx <= edges[0]; vx++) { 216 for (ey = 0; ey < edges[1]; ey++) { 217 PetscInt edge = vx*edges[1] + ey + edges[0]*(edges[1]+1); 218 PetscInt vertex = ey*(edges[0]+1) + vx + numEdges; 219 PetscInt cone[2]; 220 221 cone[0] = vertex; cone[1] = vertex+edges[0]+1; 222 ierr = DMPlexSetCone(dm, edge, cone);CHKERRQ(ierr); 223 if (vx == edges[0]) { 224 ierr = DMSetLabelValue(dm, "marker", edge, markerRight);CHKERRQ(ierr); 225 ierr = DMSetLabelValue(dm, "marker", cone[0], markerRight);CHKERRQ(ierr); 226 if (ey == edges[1]-1) { 227 ierr = DMSetLabelValue(dm, "marker", cone[1], markerRight);CHKERRQ(ierr); 228 ierr = DMSetLabelValue(dm, "Face Sets", cone[1], markerRight);CHKERRQ(ierr); 229 } 230 } else if (vx == 0) { 231 ierr = DMSetLabelValue(dm, "marker", edge, markerLeft);CHKERRQ(ierr); 232 ierr = DMSetLabelValue(dm, "marker", cone[0], markerLeft);CHKERRQ(ierr); 233 if (ey == edges[1]-1) { 234 ierr = DMSetLabelValue(dm, "marker", cone[1], markerLeft);CHKERRQ(ierr); 235 ierr = DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft);CHKERRQ(ierr); 236 } 237 } 238 } 239 } 240 for (vy = 0; vy <= edges[1]; vy++) { 241 for (ex = 0; ex < edges[0]; ex++) { 242 PetscInt edge = vy*edges[0] + ex; 243 PetscInt vertex = vy*(edges[0]+1) + ex + numEdges; 244 PetscInt cone[2]; 245 246 cone[0] = vertex; cone[1] = vertex+1; 247 ierr = DMPlexSetCone(dm, edge, cone);CHKERRQ(ierr); 248 if (vy == edges[1]) { 249 ierr = DMSetLabelValue(dm, "marker", edge, markerTop);CHKERRQ(ierr); 250 ierr = DMSetLabelValue(dm, "marker", cone[0], markerTop);CHKERRQ(ierr); 251 if (ex == edges[0]-1) { 252 ierr = DMSetLabelValue(dm, "marker", cone[1], markerTop);CHKERRQ(ierr); 253 ierr = DMSetLabelValue(dm, "Face Sets", cone[1], markerTop);CHKERRQ(ierr); 254 } 255 } else if (vy == 0) { 256 ierr = DMSetLabelValue(dm, "marker", edge, markerBottom);CHKERRQ(ierr); 257 ierr = DMSetLabelValue(dm, "marker", cone[0], markerBottom);CHKERRQ(ierr); 258 if (ex == edges[0]-1) { 259 ierr = DMSetLabelValue(dm, "marker", cone[1], markerBottom);CHKERRQ(ierr); 260 ierr = DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom);CHKERRQ(ierr); 261 } 262 } 263 } 264 } 265 } 266 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 267 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 268 /* Build coordinates */ 269 ierr = DMSetCoordinateDim(dm, 2);CHKERRQ(ierr); 270 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 271 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 272 ierr = PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices);CHKERRQ(ierr); 273 ierr = PetscSectionSetFieldComponents(coordSection, 0, 2);CHKERRQ(ierr); 274 for (v = numEdges; v < numEdges+numVertices; ++v) { 275 ierr = PetscSectionSetDof(coordSection, v, 2);CHKERRQ(ierr); 276 ierr = PetscSectionSetFieldDof(coordSection, v, 0, 2);CHKERRQ(ierr); 277 } 278 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 279 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 280 ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr); 281 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 282 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 283 ierr = VecSetBlockSize(coordinates, 2);CHKERRQ(ierr); 284 ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr); 285 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 286 for (vy = 0; vy <= edges[1]; ++vy) { 287 for (vx = 0; vx <= edges[0]; ++vx) { 288 coords[(vy*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/edges[0])*vx; 289 coords[(vy*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/edges[1])*vy; 290 } 291 } 292 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 293 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 294 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 295 PetscFunctionReturn(0); 296 } 297 298 /*@ 299 DMPlexCreateCubeBoundary - Creates a 2D mesh the is the boundary of a cubic lattice. 300 301 Collective on MPI_Comm 302 303 Input Parameters: 304 + comm - The communicator for the DM object 305 . lower - The lower left front corner coordinates 306 . upper - The upper right back corner coordinates 307 - edges - The number of cells in each direction 308 309 Output Parameter: 310 . dm - The DM object 311 312 Level: beginner 313 314 .keywords: DM, create 315 .seealso: DMPlexCreateBoxMesh(), DMPlexCreateSquareBoundary(), DMSetType(), DMCreate() 316 @*/ 317 PetscErrorCode DMPlexCreateCubeBoundary(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[]) 318 { 319 PetscInt vertices[3], numVertices; 320 PetscInt numFaces = 2*faces[0]*faces[1] + 2*faces[1]*faces[2] + 2*faces[0]*faces[2]; 321 Vec coordinates; 322 PetscSection coordSection; 323 PetscScalar *coords; 324 PetscInt coordSize; 325 PetscMPIInt rank; 326 PetscInt v, vx, vy, vz; 327 PetscInt voffset, iface=0, cone[4]; 328 PetscErrorCode ierr; 329 330 PetscFunctionBegin; 331 if ((faces[0] < 1) || (faces[1] < 1) || (faces[2] < 1)) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Must have at least 1 face per side"); 332 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 333 vertices[0] = faces[0]+1; vertices[1] = faces[1]+1; vertices[2] = faces[2]+1; 334 numVertices = vertices[0]*vertices[1]*vertices[2]; 335 if (!rank) { 336 PetscInt f; 337 338 ierr = DMPlexSetChart(dm, 0, numFaces+numVertices);CHKERRQ(ierr); 339 for (f = 0; f < numFaces; ++f) { 340 ierr = DMPlexSetConeSize(dm, f, 4);CHKERRQ(ierr); 341 } 342 ierr = DMSetUp(dm);CHKERRQ(ierr); /* Allocate space for cones */ 343 for (v = 0; v < numFaces+numVertices; ++v) { 344 ierr = DMSetLabelValue(dm, "marker", v, 1);CHKERRQ(ierr); 345 } 346 347 /* Side 0 (Top) */ 348 for (vy = 0; vy < faces[1]; vy++) { 349 for (vx = 0; vx < faces[0]; vx++) { 350 voffset = numFaces + vertices[0]*vertices[1]*(vertices[2]-1) + vy*vertices[0] + vx; 351 cone[0] = voffset; cone[1] = voffset+1; cone[2] = voffset+vertices[0]+1; cone[3] = voffset+vertices[0]; 352 ierr = DMPlexSetCone(dm, iface, cone);CHKERRQ(ierr); 353 iface++; 354 } 355 } 356 357 /* Side 1 (Bottom) */ 358 for (vy = 0; vy < faces[1]; vy++) { 359 for (vx = 0; vx < faces[0]; vx++) { 360 voffset = numFaces + vy*(faces[0]+1) + vx; 361 cone[0] = voffset+1; cone[1] = voffset; cone[2] = voffset+vertices[0]; cone[3] = voffset+vertices[0]+1; 362 ierr = DMPlexSetCone(dm, iface, cone);CHKERRQ(ierr); 363 iface++; 364 } 365 } 366 367 /* Side 2 (Front) */ 368 for (vz = 0; vz < faces[2]; vz++) { 369 for (vx = 0; vx < faces[0]; vx++) { 370 voffset = numFaces + vz*vertices[0]*vertices[1] + vx; 371 cone[0] = voffset; cone[1] = voffset+1; cone[2] = voffset+vertices[0]*vertices[1]+1; cone[3] = voffset+vertices[0]*vertices[1]; 372 ierr = DMPlexSetCone(dm, iface, cone);CHKERRQ(ierr); 373 iface++; 374 } 375 } 376 377 /* Side 3 (Back) */ 378 for (vz = 0; vz < faces[2]; vz++) { 379 for (vx = 0; vx < faces[0]; vx++) { 380 voffset = numFaces + vz*vertices[0]*vertices[1] + vertices[0]*(vertices[1]-1) + vx; 381 cone[0] = voffset+vertices[0]*vertices[1]; cone[1] = voffset+vertices[0]*vertices[1]+1; 382 cone[2] = voffset+1; cone[3] = voffset; 383 ierr = DMPlexSetCone(dm, iface, cone);CHKERRQ(ierr); 384 iface++; 385 } 386 } 387 388 /* Side 4 (Left) */ 389 for (vz = 0; vz < faces[2]; vz++) { 390 for (vy = 0; vy < faces[1]; vy++) { 391 voffset = numFaces + vz*vertices[0]*vertices[1] + vy*vertices[0]; 392 cone[0] = voffset; cone[1] = voffset+vertices[0]*vertices[1]; 393 cone[2] = voffset+vertices[0]*vertices[1]+vertices[0]; cone[3] = voffset+vertices[0]; 394 ierr = DMPlexSetCone(dm, iface, cone);CHKERRQ(ierr); 395 iface++; 396 } 397 } 398 399 /* Side 5 (Right) */ 400 for (vz = 0; vz < faces[2]; vz++) { 401 for (vy = 0; vy < faces[1]; vy++) { 402 voffset = numFaces + vz*vertices[0]*vertices[1] + vy*vertices[0] + faces[0]; 403 cone[0] = voffset+vertices[0]*vertices[1]; cone[1] = voffset; 404 cone[2] = voffset+vertices[0]; cone[3] = voffset+vertices[0]*vertices[1]+vertices[0]; 405 ierr = DMPlexSetCone(dm, iface, cone);CHKERRQ(ierr); 406 iface++; 407 } 408 } 409 } 410 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 411 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 412 /* Build coordinates */ 413 ierr = DMSetCoordinateDim(dm, 3);CHKERRQ(ierr); 414 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 415 ierr = PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices);CHKERRQ(ierr); 416 for (v = numFaces; v < numFaces+numVertices; ++v) { 417 ierr = PetscSectionSetDof(coordSection, v, 3);CHKERRQ(ierr); 418 } 419 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 420 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 421 ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr); 422 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 423 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 424 ierr = VecSetBlockSize(coordinates, 3);CHKERRQ(ierr); 425 ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr); 426 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 427 for (vz = 0; vz <= faces[2]; ++vz) { 428 for (vy = 0; vy <= faces[1]; ++vy) { 429 for (vx = 0; vx <= faces[0]; ++vx) { 430 coords[((vz*(faces[1]+1)+vy)*(faces[0]+1)+vx)*3+0] = lower[0] + ((upper[0] - lower[0])/faces[0])*vx; 431 coords[((vz*(faces[1]+1)+vy)*(faces[0]+1)+vx)*3+1] = lower[1] + ((upper[1] - lower[1])/faces[1])*vy; 432 coords[((vz*(faces[1]+1)+vy)*(faces[0]+1)+vx)*3+2] = lower[2] + ((upper[2] - lower[2])/faces[2])*vz; 433 } 434 } 435 } 436 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 437 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 438 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 439 PetscFunctionReturn(0); 440 } 441 442 /*@C 443 DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices. 444 445 Collective on MPI_Comm 446 447 Input Parameters: 448 + comm - The communicator for the DM object 449 . dim - The spatial dimension 450 . faces - Number of faces per dimension, or NULL for (2, 2) in 2D and (1, 1, 1) in 3D 451 . lower - The lower left corner, or NULL for (0, 0, 0) 452 . upper - The upper right corner, or NULL for (1, 1, 1) 453 - interpolate - Flag to create intermediate mesh pieces (edges, faces) 454 455 Output Parameter: 456 . dm - The DM object 457 458 Level: beginner 459 460 .keywords: DM, create 461 .seealso: DMPlexCreateHexBoxMesh(), DMSetType(), DMCreate() 462 @*/ 463 PetscErrorCode DMPlexCreateBoxMesh(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate, DM *dm) 464 { 465 DM boundary; 466 PetscReal low[3] = {lower ? lower[0] : 0.0, lower ? lower[1] : 0.0, lower ? lower[2] : 0.0}; 467 PetscReal upp[3] = {upper ? upper[0] : 1.0, upper ? upper[1] : 1.0, upper ? upper[2] : 1.0}; 468 PetscInt fac[3] = {faces ? faces[0] : 4-dim, faces ? faces[1] : 4-dim, faces ? faces[2] : 4-dim}; 469 PetscErrorCode ierr; 470 471 PetscFunctionBegin; 472 PetscValidPointer(dm, 4); 473 ierr = DMCreate(comm, &boundary);CHKERRQ(ierr); 474 PetscValidLogicalCollectiveInt(boundary,dim,2); 475 ierr = DMSetType(boundary, DMPLEX);CHKERRQ(ierr); 476 ierr = DMSetDimension(boundary, dim-1);CHKERRQ(ierr); 477 ierr = DMSetCoordinateDim(boundary, dim);CHKERRQ(ierr); 478 switch (dim) { 479 case 2: ierr = DMPlexCreateSquareBoundary(boundary, low, upp, fac);CHKERRQ(ierr);break; 480 case 3: ierr = DMPlexCreateCubeBoundary(boundary, low, upp, fac);CHKERRQ(ierr);break; 481 default: SETERRQ1(comm, PETSC_ERR_SUP, "Dimension not supported: %d", dim); 482 } 483 ierr = DMPlexGenerate(boundary, NULL, interpolate, dm);CHKERRQ(ierr); 484 ierr = DMDestroy(&boundary);CHKERRQ(ierr); 485 PetscFunctionReturn(0); 486 } 487 488 static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ) 489 { 490 DMLabel cutLabel = NULL; 491 PetscInt markerTop = 1, faceMarkerTop = 1; 492 PetscInt markerBottom = 1, faceMarkerBottom = 1; 493 PetscInt markerFront = 1, faceMarkerFront = 1; 494 PetscInt markerBack = 1, faceMarkerBack = 1; 495 PetscInt markerRight = 1, faceMarkerRight = 1; 496 PetscInt markerLeft = 1, faceMarkerLeft = 1; 497 PetscInt dim; 498 PetscBool markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE; 499 PetscMPIInt rank; 500 PetscErrorCode ierr; 501 502 PetscFunctionBegin; 503 ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr); 504 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 505 ierr = DMCreateLabel(dm,"marker");CHKERRQ(ierr); 506 ierr = DMCreateLabel(dm,"Face Sets");CHKERRQ(ierr); 507 if (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST || 508 bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST || 509 bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST) { 510 ierr = PetscOptionsGetBool(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL);CHKERRQ(ierr); 511 if (cutMarker) {ierr = DMCreateLabel(dm, "periodic_cut");CHKERRQ(ierr); ierr = DMGetLabel(dm, "periodic_cut", &cutLabel);CHKERRQ(ierr);} 512 } 513 switch (dim) { 514 case 2: 515 faceMarkerTop = 3; 516 faceMarkerBottom = 1; 517 faceMarkerRight = 2; 518 faceMarkerLeft = 4; 519 break; 520 case 3: 521 faceMarkerBottom = 1; 522 faceMarkerTop = 2; 523 faceMarkerFront = 3; 524 faceMarkerBack = 4; 525 faceMarkerRight = 5; 526 faceMarkerLeft = 6; 527 break; 528 default: 529 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Dimension %d not supported",dim); 530 break; 531 } 532 ierr = PetscOptionsGetBool(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL);CHKERRQ(ierr); 533 if (markerSeparate) { 534 markerBottom = faceMarkerBottom; 535 markerTop = faceMarkerTop; 536 markerFront = faceMarkerFront; 537 markerBack = faceMarkerBack; 538 markerRight = faceMarkerRight; 539 markerLeft = faceMarkerLeft; 540 } 541 { 542 const PetscInt numXEdges = !rank ? edges[0] : 0; 543 const PetscInt numYEdges = !rank ? edges[1] : 0; 544 const PetscInt numZEdges = !rank ? edges[2] : 0; 545 const PetscInt numXVertices = !rank ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0]+1) : 0; 546 const PetscInt numYVertices = !rank ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1]+1) : 0; 547 const PetscInt numZVertices = !rank ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2]+1) : 0; 548 const PetscInt numCells = numXEdges*numYEdges*numZEdges; 549 const PetscInt numXFaces = numYEdges*numZEdges; 550 const PetscInt numYFaces = numXEdges*numZEdges; 551 const PetscInt numZFaces = numXEdges*numYEdges; 552 const PetscInt numTotXFaces = numXVertices*numXFaces; 553 const PetscInt numTotYFaces = numYVertices*numYFaces; 554 const PetscInt numTotZFaces = numZVertices*numZFaces; 555 const PetscInt numFaces = numTotXFaces + numTotYFaces + numTotZFaces; 556 const PetscInt numTotXEdges = numXEdges*numYVertices*numZVertices; 557 const PetscInt numTotYEdges = numYEdges*numXVertices*numZVertices; 558 const PetscInt numTotZEdges = numZEdges*numXVertices*numYVertices; 559 const PetscInt numVertices = numXVertices*numYVertices*numZVertices; 560 const PetscInt numEdges = numTotXEdges + numTotYEdges + numTotZEdges; 561 const PetscInt firstVertex = (dim == 2) ? numFaces : numCells; 562 const PetscInt firstXFace = (dim == 2) ? 0 : numCells + numVertices; 563 const PetscInt firstYFace = firstXFace + numTotXFaces; 564 const PetscInt firstZFace = firstYFace + numTotYFaces; 565 const PetscInt firstXEdge = numCells + numFaces + numVertices; 566 const PetscInt firstYEdge = firstXEdge + numTotXEdges; 567 const PetscInt firstZEdge = firstYEdge + numTotYEdges; 568 Vec coordinates; 569 PetscSection coordSection; 570 PetscScalar *coords; 571 PetscInt coordSize; 572 PetscInt v, vx, vy, vz; 573 PetscInt c, f, fx, fy, fz, e, ex, ey, ez; 574 575 ierr = DMPlexSetChart(dm, 0, numCells+numFaces+numEdges+numVertices);CHKERRQ(ierr); 576 for (c = 0; c < numCells; c++) { 577 ierr = DMPlexSetConeSize(dm, c, 6);CHKERRQ(ierr); 578 } 579 for (f = firstXFace; f < firstXFace+numFaces; ++f) { 580 ierr = DMPlexSetConeSize(dm, f, 4);CHKERRQ(ierr); 581 } 582 for (e = firstXEdge; e < firstXEdge+numEdges; ++e) { 583 ierr = DMPlexSetConeSize(dm, e, 2);CHKERRQ(ierr); 584 } 585 ierr = DMSetUp(dm);CHKERRQ(ierr); /* Allocate space for cones */ 586 /* Build cells */ 587 for (fz = 0; fz < numZEdges; ++fz) { 588 for (fy = 0; fy < numYEdges; ++fy) { 589 for (fx = 0; fx < numXEdges; ++fx) { 590 PetscInt cell = (fz*numYEdges + fy)*numXEdges + fx; 591 PetscInt faceB = firstZFace + (fy*numXEdges+fx)*numZVertices + fz; 592 PetscInt faceT = firstZFace + (fy*numXEdges+fx)*numZVertices + ((fz+1)%numZVertices); 593 PetscInt faceF = firstYFace + (fz*numXEdges+fx)*numYVertices + fy; 594 PetscInt faceK = firstYFace + (fz*numXEdges+fx)*numYVertices + ((fy+1)%numYVertices); 595 PetscInt faceL = firstXFace + (fz*numYEdges+fy)*numXVertices + fx; 596 PetscInt faceR = firstXFace + (fz*numYEdges+fy)*numXVertices + ((fx+1)%numXVertices); 597 /* B, T, F, K, R, L */ 598 PetscInt ornt[6] = {-4, 0, 0, -1, 0, -4}; /* ??? */ 599 PetscInt cone[6]; 600 601 /* no boundary twisting in 3D */ 602 cone[0] = faceB; cone[1] = faceT; cone[2] = faceF; cone[3] = faceK; cone[4] = faceR; cone[5] = faceL; 603 ierr = DMPlexSetCone(dm, cell, cone);CHKERRQ(ierr); 604 ierr = DMPlexSetConeOrientation(dm, cell, ornt);CHKERRQ(ierr); 605 if (bdX != DM_BOUNDARY_NONE && fx == numXEdges-1 && cutLabel) {ierr = DMLabelSetValue(cutLabel, cell, 2);CHKERRQ(ierr);} 606 if (bdY != DM_BOUNDARY_NONE && fy == numYEdges-1 && cutLabel) {ierr = DMLabelSetValue(cutLabel, cell, 2);CHKERRQ(ierr);} 607 if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges-1 && cutLabel) {ierr = DMLabelSetValue(cutLabel, cell, 2);CHKERRQ(ierr);} 608 } 609 } 610 } 611 /* Build x faces */ 612 for (fz = 0; fz < numZEdges; ++fz) { 613 for (fy = 0; fy < numYEdges; ++fy) { 614 for (fx = 0; fx < numXVertices; ++fx) { 615 PetscInt face = firstXFace + (fz*numYEdges+fy)*numXVertices + fx; 616 PetscInt edgeL = firstZEdge + ( fy* numXVertices+fx)*numZEdges + fz; 617 PetscInt edgeR = firstZEdge + (((fy+1)%numYVertices)*numXVertices+fx)*numZEdges + fz; 618 PetscInt edgeB = firstYEdge + ( fz* numXVertices+fx)*numYEdges + fy; 619 PetscInt edgeT = firstYEdge + (((fz+1)%numZVertices)*numXVertices+fx)*numYEdges + fy; 620 PetscInt ornt[4] = {0, 0, -2, -2}; 621 PetscInt cone[4]; 622 623 if (dim == 3) { 624 /* markers */ 625 if (bdX != DM_BOUNDARY_PERIODIC) { 626 if (fx == numXVertices-1) { 627 ierr = DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight);CHKERRQ(ierr); 628 ierr = DMSetLabelValue(dm, "marker", face, markerRight);CHKERRQ(ierr); 629 } 630 else if (fx == 0) { 631 ierr = DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft);CHKERRQ(ierr); 632 ierr = DMSetLabelValue(dm, "marker", face, markerLeft);CHKERRQ(ierr); 633 } 634 } 635 } 636 cone[0] = edgeB; cone[1] = edgeR; cone[2] = edgeT; cone[3] = edgeL; 637 ierr = DMPlexSetCone(dm, face, cone);CHKERRQ(ierr); 638 ierr = DMPlexSetConeOrientation(dm, face, ornt);CHKERRQ(ierr); 639 } 640 } 641 } 642 /* Build y faces */ 643 for (fz = 0; fz < numZEdges; ++fz) { 644 for (fx = 0; fx < numXEdges; ++fx) { 645 for (fy = 0; fy < numYVertices; ++fy) { 646 PetscInt face = firstYFace + (fz*numXEdges+fx)*numYVertices + fy; 647 PetscInt edgeL = firstZEdge + (fy*numXVertices+ fx )*numZEdges + fz; 648 PetscInt edgeR = firstZEdge + (fy*numXVertices+((fx+1)%numXVertices))*numZEdges + fz; 649 PetscInt edgeB = firstXEdge + ( fz *numYVertices+fy)*numXEdges + fx; 650 PetscInt edgeT = firstXEdge + (((fz+1)%numZVertices)*numYVertices+fy)*numXEdges + fx; 651 PetscInt ornt[4] = {0, 0, -2, -2}; 652 PetscInt cone[4]; 653 654 if (dim == 3) { 655 /* markers */ 656 if (bdY != DM_BOUNDARY_PERIODIC) { 657 if (fy == numYVertices-1) { 658 ierr = DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack);CHKERRQ(ierr); 659 ierr = DMSetLabelValue(dm, "marker", face, markerBack);CHKERRQ(ierr); 660 } 661 else if (fy == 0) { 662 ierr = DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront);CHKERRQ(ierr); 663 ierr = DMSetLabelValue(dm, "marker", face, markerFront);CHKERRQ(ierr); 664 } 665 } 666 } 667 cone[0] = edgeB; cone[1] = edgeR; cone[2] = edgeT; cone[3] = edgeL; 668 ierr = DMPlexSetCone(dm, face, cone);CHKERRQ(ierr); 669 ierr = DMPlexSetConeOrientation(dm, face, ornt);CHKERRQ(ierr); 670 } 671 } 672 } 673 /* Build z faces */ 674 for (fy = 0; fy < numYEdges; ++fy) { 675 for (fx = 0; fx < numXEdges; ++fx) { 676 for (fz = 0; fz < numZVertices; fz++) { 677 PetscInt face = firstZFace + (fy*numXEdges+fx)*numZVertices + fz; 678 PetscInt edgeL = firstYEdge + (fz*numXVertices+ fx )*numYEdges + fy; 679 PetscInt edgeR = firstYEdge + (fz*numXVertices+((fx+1)%numXVertices))*numYEdges + fy; 680 PetscInt edgeB = firstXEdge + (fz*numYVertices+ fy )*numXEdges + fx; 681 PetscInt edgeT = firstXEdge + (fz*numYVertices+((fy+1)%numYVertices))*numXEdges + fx; 682 PetscInt ornt[4] = {0, 0, -2, -2}; 683 PetscInt cone[4]; 684 685 if (dim == 2) { 686 if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges-1) {edgeR += numYEdges-1-2*fy; ornt[1] = -2;} 687 if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges-1) {edgeT += numXEdges-1-2*fx; ornt[2] = 0;} 688 if (bdX != DM_BOUNDARY_NONE && fx == numXEdges-1 && cutLabel) {ierr = DMLabelSetValue(cutLabel, face, 2);CHKERRQ(ierr);} 689 if (bdY != DM_BOUNDARY_NONE && fy == numYEdges-1 && cutLabel) {ierr = DMLabelSetValue(cutLabel, face, 2);CHKERRQ(ierr);} 690 } else { 691 /* markers */ 692 if (bdZ != DM_BOUNDARY_PERIODIC) { 693 if (fz == numZVertices-1) { 694 ierr = DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop);CHKERRQ(ierr); 695 ierr = DMSetLabelValue(dm, "marker", face, markerTop);CHKERRQ(ierr); 696 } 697 else if (fz == 0) { 698 ierr = DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom);CHKERRQ(ierr); 699 ierr = DMSetLabelValue(dm, "marker", face, markerBottom);CHKERRQ(ierr); 700 } 701 } 702 } 703 cone[0] = edgeB; cone[1] = edgeR; cone[2] = edgeT; cone[3] = edgeL; 704 ierr = DMPlexSetCone(dm, face, cone);CHKERRQ(ierr); 705 ierr = DMPlexSetConeOrientation(dm, face, ornt);CHKERRQ(ierr); 706 } 707 } 708 } 709 /* Build Z edges*/ 710 for (vy = 0; vy < numYVertices; vy++) { 711 for (vx = 0; vx < numXVertices; vx++) { 712 for (ez = 0; ez < numZEdges; ez++) { 713 const PetscInt edge = firstZEdge + (vy*numXVertices+vx)*numZEdges + ez; 714 const PetscInt vertexB = firstVertex + ( ez *numYVertices+vy)*numXVertices + vx; 715 const PetscInt vertexT = firstVertex + (((ez+1)%numZVertices)*numYVertices+vy)*numXVertices + vx; 716 PetscInt cone[2]; 717 718 if (dim == 3) { 719 if (bdX != DM_BOUNDARY_PERIODIC) { 720 if (vx == numXVertices-1) { 721 ierr = DMSetLabelValue(dm, "marker", edge, markerRight);CHKERRQ(ierr); 722 } 723 else if (vx == 0) { 724 ierr = DMSetLabelValue(dm, "marker", edge, markerLeft);CHKERRQ(ierr); 725 } 726 } 727 if (bdY != DM_BOUNDARY_PERIODIC) { 728 if (vy == numYVertices-1) { 729 ierr = DMSetLabelValue(dm, "marker", edge, markerBack);CHKERRQ(ierr); 730 } 731 else if (vy == 0) { 732 ierr = DMSetLabelValue(dm, "marker", edge, markerFront);CHKERRQ(ierr); 733 } 734 } 735 } 736 cone[0] = vertexB; cone[1] = vertexT; 737 ierr = DMPlexSetCone(dm, edge, cone);CHKERRQ(ierr); 738 } 739 } 740 } 741 /* Build Y edges*/ 742 for (vz = 0; vz < numZVertices; vz++) { 743 for (vx = 0; vx < numXVertices; vx++) { 744 for (ey = 0; ey < numYEdges; ey++) { 745 const PetscInt nextv = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges-1) ? (numXVertices-vx-1) : (vz*numYVertices+((ey+1)%numYVertices))*numXVertices + vx; 746 const PetscInt edge = firstYEdge + (vz*numXVertices+vx)*numYEdges + ey; 747 const PetscInt vertexF = firstVertex + (vz*numYVertices+ey)*numXVertices + vx; 748 const PetscInt vertexK = firstVertex + nextv; 749 PetscInt cone[2]; 750 751 cone[0] = vertexF; cone[1] = vertexK; 752 ierr = DMPlexSetCone(dm, edge, cone);CHKERRQ(ierr); 753 if (dim == 2) { 754 if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) { 755 if (vx == numXVertices-1) { 756 ierr = DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight);CHKERRQ(ierr); 757 ierr = DMSetLabelValue(dm, "marker", edge, markerRight);CHKERRQ(ierr); 758 ierr = DMSetLabelValue(dm, "marker", cone[0], markerRight);CHKERRQ(ierr); 759 if (ey == numYEdges-1) { 760 ierr = DMSetLabelValue(dm, "marker", cone[1], markerRight);CHKERRQ(ierr); 761 } 762 } else if (vx == 0) { 763 ierr = DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft);CHKERRQ(ierr); 764 ierr = DMSetLabelValue(dm, "marker", edge, markerLeft);CHKERRQ(ierr); 765 ierr = DMSetLabelValue(dm, "marker", cone[0], markerLeft);CHKERRQ(ierr); 766 if (ey == numYEdges-1) { 767 ierr = DMSetLabelValue(dm, "marker", cone[1], markerLeft);CHKERRQ(ierr); 768 } 769 } 770 } else { 771 if (vx == 0 && cutMarker) { 772 ierr = DMLabelSetValue(cutLabel, edge, 1);CHKERRQ(ierr); 773 ierr = DMLabelSetValue(cutLabel, cone[0], 1);CHKERRQ(ierr); 774 if (ey == numYEdges-1) { 775 ierr = DMLabelSetValue(cutLabel, cone[1], 1);CHKERRQ(ierr); 776 } 777 } 778 } 779 } else { 780 if (bdX != DM_BOUNDARY_PERIODIC) { 781 if (vx == numXVertices-1) { 782 ierr = DMSetLabelValue(dm, "marker", edge, markerRight);CHKERRQ(ierr); 783 } else if (vx == 0) { 784 ierr = DMSetLabelValue(dm, "marker", edge, markerLeft);CHKERRQ(ierr); 785 } 786 } 787 if (bdZ != DM_BOUNDARY_PERIODIC) { 788 if (vz == numZVertices-1) { 789 ierr = DMSetLabelValue(dm, "marker", edge, markerTop);CHKERRQ(ierr); 790 } else if (vz == 0) { 791 ierr = DMSetLabelValue(dm, "marker", edge, markerBottom);CHKERRQ(ierr); 792 } 793 } 794 } 795 } 796 } 797 } 798 /* Build X edges*/ 799 for (vz = 0; vz < numZVertices; vz++) { 800 for (vy = 0; vy < numYVertices; vy++) { 801 for (ex = 0; ex < numXEdges; ex++) { 802 const PetscInt nextv = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges-1) ? (numYVertices-vy-1)*numXVertices : (vz*numYVertices+vy)*numXVertices + (ex+1)%numXVertices; 803 const PetscInt edge = firstXEdge + (vz*numYVertices+vy)*numXEdges + ex; 804 const PetscInt vertexL = firstVertex + (vz*numYVertices+vy)*numXVertices + ex; 805 const PetscInt vertexR = firstVertex + nextv; 806 PetscInt cone[2]; 807 808 cone[0] = vertexL; cone[1] = vertexR; 809 ierr = DMPlexSetCone(dm, edge, cone);CHKERRQ(ierr); 810 if (dim == 2) { 811 if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) { 812 if (vy == numYVertices-1) { 813 ierr = DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop);CHKERRQ(ierr); 814 ierr = DMSetLabelValue(dm, "marker", edge, markerTop);CHKERRQ(ierr); 815 ierr = DMSetLabelValue(dm, "marker", cone[0], markerTop);CHKERRQ(ierr); 816 if (ex == numXEdges-1) { 817 ierr = DMSetLabelValue(dm, "marker", cone[1], markerTop);CHKERRQ(ierr); 818 } 819 } else if (vy == 0) { 820 ierr = DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom);CHKERRQ(ierr); 821 ierr = DMSetLabelValue(dm, "marker", edge, markerBottom);CHKERRQ(ierr); 822 ierr = DMSetLabelValue(dm, "marker", cone[0], markerBottom);CHKERRQ(ierr); 823 if (ex == numXEdges-1) { 824 ierr = DMSetLabelValue(dm, "marker", cone[1], markerBottom);CHKERRQ(ierr); 825 } 826 } 827 } else { 828 if (vy == 0 && cutMarker) { 829 ierr = DMLabelSetValue(cutLabel, edge, 1);CHKERRQ(ierr); 830 ierr = DMLabelSetValue(cutLabel, cone[0], 1);CHKERRQ(ierr); 831 if (ex == numXEdges-1) { 832 ierr = DMLabelSetValue(cutLabel, cone[1], 1);CHKERRQ(ierr); 833 } 834 } 835 } 836 } else { 837 if (bdY != DM_BOUNDARY_PERIODIC) { 838 if (vy == numYVertices-1) { 839 ierr = DMSetLabelValue(dm, "marker", edge, markerBack);CHKERRQ(ierr); 840 } 841 else if (vy == 0) { 842 ierr = DMSetLabelValue(dm, "marker", edge, markerFront);CHKERRQ(ierr); 843 } 844 } 845 if (bdZ != DM_BOUNDARY_PERIODIC) { 846 if (vz == numZVertices-1) { 847 ierr = DMSetLabelValue(dm, "marker", edge, markerTop);CHKERRQ(ierr); 848 } 849 else if (vz == 0) { 850 ierr = DMSetLabelValue(dm, "marker", edge, markerBottom);CHKERRQ(ierr); 851 } 852 } 853 } 854 } 855 } 856 } 857 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 858 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 859 /* Build coordinates */ 860 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 861 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 862 ierr = PetscSectionSetFieldComponents(coordSection, 0, dim);CHKERRQ(ierr); 863 ierr = PetscSectionSetChart(coordSection, firstVertex, firstVertex+numVertices);CHKERRQ(ierr); 864 for (v = firstVertex; v < firstVertex+numVertices; ++v) { 865 ierr = PetscSectionSetDof(coordSection, v, dim);CHKERRQ(ierr); 866 ierr = PetscSectionSetFieldDof(coordSection, v, 0, dim);CHKERRQ(ierr); 867 } 868 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 869 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 870 ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr); 871 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 872 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 873 ierr = VecSetBlockSize(coordinates, dim);CHKERRQ(ierr); 874 ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr); 875 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 876 for (vz = 0; vz < numZVertices; ++vz) { 877 for (vy = 0; vy < numYVertices; ++vy) { 878 for (vx = 0; vx < numXVertices; ++vx) { 879 coords[((vz*numYVertices+vy)*numXVertices+vx)*dim+0] = lower[0] + ((upper[0] - lower[0])/numXEdges)*vx; 880 coords[((vz*numYVertices+vy)*numXVertices+vx)*dim+1] = lower[1] + ((upper[1] - lower[1])/numYEdges)*vy; 881 if (dim == 3) { 882 coords[((vz*numYVertices+vy)*numXVertices+vx)*dim+2] = lower[2] + ((upper[2] - lower[2])/numZEdges)*vz; 883 } 884 } 885 } 886 } 887 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 888 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 889 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 890 } 891 PetscFunctionReturn(0); 892 } 893 894 /*@ 895 DMPlexCreateHexBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using hexahedra. 896 897 Collective on MPI_Comm 898 899 Input Parameters: 900 + comm - The communicator for the DM object 901 . dim - The spatial dimension 902 . lower - The lower left corner, or NULL for (0, 0, 0) 903 . upper - The upper right corner, or NULL for (1, 1, 1) 904 . periodicX - The boundary type for the X direction 905 . periodicY - The boundary type for the Y direction 906 . periodicZ - The boundary type for the Z direction 907 - cells - The number of cells in each direction 908 909 Output Parameter: 910 . dm - The DM object 911 912 Note: Here is the numbering returned for 2 cells in each direction: 913 $ 22--8-23--9--24 914 $ | | | 915 $ 13 2 14 3 15 916 $ | | | 917 $ 19--6-20--7--21 918 $ | | | 919 $ 10 0 11 1 12 920 $ | | | 921 $ 16--4-17--5--18 922 923 Level: beginner 924 925 .keywords: DM, create 926 .seealso: DMPlexCreateBoxMesh(), DMSetType(), DMCreate() 927 @*/ 928 PetscErrorCode DMPlexCreateHexBoxMesh(MPI_Comm comm, PetscInt dim, const PetscInt cells[], const PetscReal lower[], const PetscReal upper[], DMBoundaryType periodicX, DMBoundaryType periodicY, DMBoundaryType periodicZ, DM *dm) 929 { 930 PetscInt i; 931 PetscErrorCode ierr; 932 933 PetscFunctionBegin; 934 PetscValidPointer(dm, 7); 935 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 936 PetscValidLogicalCollectiveInt(*dm,dim,2); 937 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 938 ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); 939 switch (dim) { 940 case 2: 941 { 942 PetscReal low[3] = {lower ? lower[0] : 0.0, lower ? lower[1] : 0.0, 0.0}; 943 PetscReal upp[3] = {upper ? upper[0] : 1.0, upper ? upper[1] : 1.0, 0.0}; 944 PetscInt edges[3]; 945 946 edges[0] = cells[0]; 947 edges[1] = cells[1]; 948 edges[2] = 0; 949 ierr = DMPlexCreateCubeMesh_Internal(*dm, low, upp, edges, periodicX, periodicY, DM_BOUNDARY_NONE);CHKERRQ(ierr); 950 if (periodicX == DM_BOUNDARY_PERIODIC || periodicX == DM_BOUNDARY_TWIST || 951 periodicY == DM_BOUNDARY_PERIODIC || periodicY == DM_BOUNDARY_TWIST) { 952 PetscReal L[2]; 953 PetscReal maxCell[2]; 954 DMBoundaryType bdType[2]; 955 956 bdType[0] = periodicX; 957 bdType[1] = periodicY; 958 for (i = 0; i < dim; i++) { 959 L[i] = upper[i] - lower[i]; 960 maxCell[i] = 1.1 * (L[i] / PetscMax(1,cells[i])); 961 } 962 963 ierr = DMSetPeriodicity(*dm,PETSC_TRUE,maxCell,L,bdType);CHKERRQ(ierr); 964 } 965 break; 966 } 967 case 3: 968 { 969 PetscReal low[3] = {lower ? lower[0] : 0.0, lower ? lower[1] : 0.0, lower ? lower[2] : 0.0}; 970 PetscReal upp[3] = {upper ? upper[0] : 1.0, upper ? upper[1] : 1.0, upper ? upper[2] : 1.0}; 971 972 ierr = DMPlexCreateCubeMesh_Internal(*dm, low, upp, cells, periodicX, periodicY, periodicZ);CHKERRQ(ierr); 973 if (periodicX == DM_BOUNDARY_PERIODIC || periodicX == DM_BOUNDARY_TWIST || 974 periodicY == DM_BOUNDARY_PERIODIC || periodicY == DM_BOUNDARY_TWIST || 975 periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) { 976 PetscReal L[3]; 977 PetscReal maxCell[3]; 978 DMBoundaryType bdType[3]; 979 980 bdType[0] = periodicX; 981 bdType[1] = periodicY; 982 bdType[2] = periodicZ; 983 for (i = 0; i < dim; i++) { 984 L[i] = upper[i] - lower[i]; 985 maxCell[i] = 1.1 * (L[i] / cells[i]); 986 } 987 988 ierr = DMSetPeriodicity(*dm,PETSC_TRUE,maxCell,L,bdType);CHKERRQ(ierr); 989 } 990 break; 991 } 992 default: 993 SETERRQ1(comm, PETSC_ERR_SUP, "Dimension not supported: %d", dim); 994 } 995 PetscFunctionReturn(0); 996 } 997 998 /*@C 999 DMPlexSetOptionsPrefix - Sets the prefix used for searching for all DM options in the database. 1000 1001 Logically Collective on DM 1002 1003 Input Parameters: 1004 + dm - the DM context 1005 - prefix - the prefix to prepend to all option names 1006 1007 Notes: 1008 A hyphen (-) must NOT be given at the beginning of the prefix name. 1009 The first character of all runtime options is AUTOMATICALLY the hyphen. 1010 1011 Level: advanced 1012 1013 .seealso: SNESSetFromOptions() 1014 @*/ 1015 PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[]) 1016 { 1017 DM_Plex *mesh = (DM_Plex *) dm->data; 1018 PetscErrorCode ierr; 1019 1020 PetscFunctionBegin; 1021 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1022 ierr = PetscObjectSetOptionsPrefix((PetscObject) dm, prefix);CHKERRQ(ierr); 1023 ierr = PetscObjectSetOptionsPrefix((PetscObject) mesh->partitioner, prefix);CHKERRQ(ierr); 1024 PetscFunctionReturn(0); 1025 } 1026 1027 /*@ 1028 DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra. 1029 1030 Collective on MPI_Comm 1031 1032 Input Parameters: 1033 + comm - The communicator for the DM object 1034 . numRefine - The number of regular refinements to the basic 5 cell structure 1035 - periodicZ - The boundary type for the Z direction 1036 1037 Output Parameter: 1038 . dm - The DM object 1039 1040 Note: Here is the output numbering looking from the bottom of the cylinder: 1041 $ 17-----14 1042 $ | | 1043 $ | 2 | 1044 $ | | 1045 $ 17-----8-----7-----14 1046 $ | | | | 1047 $ | 3 | 0 | 1 | 1048 $ | | | | 1049 $ 19-----5-----6-----13 1050 $ | | 1051 $ | 4 | 1052 $ | | 1053 $ 19-----13 1054 $ 1055 $ and up through the top 1056 $ 1057 $ 18-----16 1058 $ | | 1059 $ | 2 | 1060 $ | | 1061 $ 18----10----11-----16 1062 $ | | | | 1063 $ | 3 | 0 | 1 | 1064 $ | | | | 1065 $ 20-----9----12-----15 1066 $ | | 1067 $ | 4 | 1068 $ | | 1069 $ 20-----15 1070 1071 Level: beginner 1072 1073 .keywords: DM, create 1074 .seealso: DMPlexCreateHexBoxMesh(), DMPlexCreateBoxMesh(), DMSetType(), DMCreate() 1075 @*/ 1076 PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, PetscInt numRefine, DMBoundaryType periodicZ, DM *dm) 1077 { 1078 const PetscInt dim = 3; 1079 PetscInt numCells, numVertices, r; 1080 PetscErrorCode ierr; 1081 1082 PetscFunctionBegin; 1083 PetscValidPointer(dm, 4); 1084 if (numRefine < 0) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of refinements %D cannot be negative", numRefine); 1085 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 1086 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 1087 ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); 1088 /* Create topology */ 1089 { 1090 PetscInt cone[8], c; 1091 1092 numCells = 5; 1093 numVertices = 16; 1094 if (periodicZ == DM_BOUNDARY_PERIODIC) { 1095 numCells *= 3; 1096 numVertices = 24; 1097 } 1098 ierr = DMPlexSetChart(*dm, 0, numCells+numVertices);CHKERRQ(ierr); 1099 for (c = 0; c < numCells; c++) {ierr = DMPlexSetConeSize(*dm, c, 8);CHKERRQ(ierr);} 1100 ierr = DMSetUp(*dm);CHKERRQ(ierr); 1101 if (periodicZ == DM_BOUNDARY_PERIODIC) { 1102 cone[0] = 15; cone[1] = 18; cone[2] = 17; cone[3] = 16; 1103 cone[4] = 31; cone[5] = 32; cone[6] = 33; cone[7] = 34; 1104 ierr = DMPlexSetCone(*dm, 0, cone);CHKERRQ(ierr); 1105 cone[0] = 16; cone[1] = 17; cone[2] = 24; cone[3] = 23; 1106 cone[4] = 32; cone[5] = 36; cone[6] = 37; cone[7] = 33; /* 22 25 26 21 */ 1107 ierr = DMPlexSetCone(*dm, 1, cone);CHKERRQ(ierr); 1108 cone[0] = 18; cone[1] = 27; cone[2] = 24; cone[3] = 17; 1109 cone[4] = 34; cone[5] = 33; cone[6] = 37; cone[7] = 38; 1110 ierr = DMPlexSetCone(*dm, 2, cone);CHKERRQ(ierr); 1111 cone[0] = 29; cone[1] = 27; cone[2] = 18; cone[3] = 15; 1112 cone[4] = 35; cone[5] = 31; cone[6] = 34; cone[7] = 38; 1113 ierr = DMPlexSetCone(*dm, 3, cone);CHKERRQ(ierr); 1114 cone[0] = 29; cone[1] = 15; cone[2] = 16; cone[3] = 23; 1115 cone[4] = 35; cone[5] = 36; cone[6] = 32; cone[7] = 31; 1116 ierr = DMPlexSetCone(*dm, 4, cone);CHKERRQ(ierr); 1117 1118 cone[0] = 31; cone[1] = 34; cone[2] = 33; cone[3] = 32; 1119 cone[4] = 19; cone[5] = 22; cone[6] = 21; cone[7] = 20; 1120 ierr = DMPlexSetCone(*dm, 5, cone);CHKERRQ(ierr); 1121 cone[0] = 32; cone[1] = 33; cone[2] = 37; cone[3] = 36; 1122 cone[4] = 22; cone[5] = 25; cone[6] = 26; cone[7] = 21; 1123 ierr = DMPlexSetCone(*dm, 6, cone);CHKERRQ(ierr); 1124 cone[0] = 34; cone[1] = 38; cone[2] = 37; cone[3] = 33; 1125 cone[4] = 20; cone[5] = 21; cone[6] = 26; cone[7] = 28; 1126 ierr = DMPlexSetCone(*dm, 7, cone);CHKERRQ(ierr); 1127 cone[0] = 35; cone[1] = 38; cone[2] = 34; cone[3] = 31; 1128 cone[4] = 30; cone[5] = 19; cone[6] = 20; cone[7] = 28; 1129 ierr = DMPlexSetCone(*dm, 8, cone);CHKERRQ(ierr); 1130 cone[0] = 35; cone[1] = 31; cone[2] = 32; cone[3] = 36; 1131 cone[4] = 30; cone[5] = 25; cone[6] = 22; cone[7] = 19; 1132 ierr = DMPlexSetCone(*dm, 9, cone);CHKERRQ(ierr); 1133 1134 cone[0] = 19; cone[1] = 20; cone[2] = 21; cone[3] = 22; 1135 cone[4] = 15; cone[5] = 16; cone[6] = 17; cone[7] = 18; 1136 ierr = DMPlexSetCone(*dm, 10, cone);CHKERRQ(ierr); 1137 cone[0] = 22; cone[1] = 21; cone[2] = 26; cone[3] = 25; 1138 cone[4] = 16; cone[5] = 23; cone[6] = 24; cone[7] = 17; 1139 ierr = DMPlexSetCone(*dm, 11, cone);CHKERRQ(ierr); 1140 cone[0] = 20; cone[1] = 28; cone[2] = 26; cone[3] = 21; 1141 cone[4] = 18; cone[5] = 17; cone[6] = 24; cone[7] = 27; 1142 ierr = DMPlexSetCone(*dm, 12, cone);CHKERRQ(ierr); 1143 cone[0] = 30; cone[1] = 28; cone[2] = 20; cone[3] = 19; 1144 cone[4] = 29; cone[5] = 15; cone[6] = 18; cone[7] = 27; 1145 ierr = DMPlexSetCone(*dm, 13, cone);CHKERRQ(ierr); 1146 cone[0] = 30; cone[1] = 19; cone[2] = 22; cone[3] = 25; 1147 cone[4] = 29; cone[5] = 23; cone[6] = 16; cone[7] = 15; 1148 ierr = DMPlexSetCone(*dm, 14, cone);CHKERRQ(ierr); 1149 } else { 1150 cone[0] = 5; cone[1] = 8; cone[2] = 7; cone[3] = 6; 1151 cone[4] = 9; cone[5] = 12; cone[6] = 11; cone[7] = 10; 1152 ierr = DMPlexSetCone(*dm, 0, cone);CHKERRQ(ierr); 1153 cone[0] = 6; cone[1] = 7; cone[2] = 14; cone[3] = 13; 1154 cone[4] = 12; cone[5] = 15; cone[6] = 16; cone[7] = 11; 1155 ierr = DMPlexSetCone(*dm, 1, cone);CHKERRQ(ierr); 1156 cone[0] = 8; cone[1] = 17; cone[2] = 14; cone[3] = 7; 1157 cone[4] = 10; cone[5] = 11; cone[6] = 16; cone[7] = 18; 1158 ierr = DMPlexSetCone(*dm, 2, cone);CHKERRQ(ierr); 1159 cone[0] = 19; cone[1] = 17; cone[2] = 8; cone[3] = 5; 1160 cone[4] = 20; cone[5] = 9; cone[6] = 10; cone[7] = 18; 1161 ierr = DMPlexSetCone(*dm, 3, cone);CHKERRQ(ierr); 1162 cone[0] = 19; cone[1] = 5; cone[2] = 6; cone[3] = 13; 1163 cone[4] = 20; cone[5] = 15; cone[6] = 12; cone[7] = 9; 1164 ierr = DMPlexSetCone(*dm, 4, cone);CHKERRQ(ierr); 1165 } 1166 ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr); 1167 ierr = DMPlexStratify(*dm);CHKERRQ(ierr); 1168 } 1169 /* Interpolate */ 1170 { 1171 DM idm = NULL; 1172 1173 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 1174 ierr = DMDestroy(dm);CHKERRQ(ierr); 1175 *dm = idm; 1176 } 1177 /* Create cube geometry */ 1178 { 1179 Vec coordinates; 1180 PetscSection coordSection; 1181 PetscScalar *coords; 1182 PetscInt coordSize, v; 1183 const PetscReal dis = 1.0/PetscSqrtReal(2.0); 1184 const PetscReal ds2 = dis/2.0; 1185 1186 /* Build coordinates */ 1187 ierr = DMGetCoordinateSection(*dm, &coordSection);CHKERRQ(ierr); 1188 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 1189 ierr = PetscSectionSetFieldComponents(coordSection, 0, dim);CHKERRQ(ierr); 1190 ierr = PetscSectionSetChart(coordSection, numCells, numCells+numVertices);CHKERRQ(ierr); 1191 for (v = numCells; v < numCells+numVertices; ++v) { 1192 ierr = PetscSectionSetDof(coordSection, v, dim);CHKERRQ(ierr); 1193 ierr = PetscSectionSetFieldDof(coordSection, v, 0, dim);CHKERRQ(ierr); 1194 } 1195 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 1196 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 1197 ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr); 1198 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 1199 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 1200 ierr = VecSetBlockSize(coordinates, dim);CHKERRQ(ierr); 1201 ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr); 1202 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 1203 coords[0*dim+0] = -ds2; coords[0*dim+1] = -ds2; coords[0*dim+2] = 0.0; 1204 coords[1*dim+0] = ds2; coords[1*dim+1] = -ds2; coords[1*dim+2] = 0.0; 1205 coords[2*dim+0] = ds2; coords[2*dim+1] = ds2; coords[2*dim+2] = 0.0; 1206 coords[3*dim+0] = -ds2; coords[3*dim+1] = ds2; coords[3*dim+2] = 0.0; 1207 coords[4*dim+0] = -ds2; coords[4*dim+1] = -ds2; coords[4*dim+2] = 1.0; 1208 coords[5*dim+0] = -ds2; coords[5*dim+1] = ds2; coords[5*dim+2] = 1.0; 1209 coords[6*dim+0] = ds2; coords[6*dim+1] = ds2; coords[6*dim+2] = 1.0; 1210 coords[7*dim+0] = ds2; coords[7*dim+1] = -ds2; coords[7*dim+2] = 1.0; 1211 coords[ 8*dim+0] = dis; coords[ 8*dim+1] = -dis; coords[ 8*dim+2] = 0.0; 1212 coords[ 9*dim+0] = dis; coords[ 9*dim+1] = dis; coords[ 9*dim+2] = 0.0; 1213 coords[10*dim+0] = dis; coords[10*dim+1] = -dis; coords[10*dim+2] = 1.0; 1214 coords[11*dim+0] = dis; coords[11*dim+1] = dis; coords[11*dim+2] = 1.0; 1215 coords[12*dim+0] = -dis; coords[12*dim+1] = dis; coords[12*dim+2] = 0.0; 1216 coords[13*dim+0] = -dis; coords[13*dim+1] = dis; coords[13*dim+2] = 1.0; 1217 coords[14*dim+0] = -dis; coords[14*dim+1] = -dis; coords[14*dim+2] = 0.0; 1218 coords[15*dim+0] = -dis; coords[15*dim+1] = -dis; coords[15*dim+2] = 1.0; 1219 if (periodicZ == DM_BOUNDARY_PERIODIC) { 1220 /* 15 31 19 */ coords[16*dim+0] = -ds2; coords[16*dim+1] = -ds2; coords[16*dim+2] = 0.5; 1221 /* 16 32 22 */ coords[17*dim+0] = ds2; coords[17*dim+1] = -ds2; coords[17*dim+2] = 0.5; 1222 /* 17 33 21 */ coords[18*dim+0] = ds2; coords[18*dim+1] = ds2; coords[18*dim+2] = 0.5; 1223 /* 18 34 20 */ coords[19*dim+0] = -ds2; coords[19*dim+1] = ds2; coords[19*dim+2] = 0.5; 1224 /* 29 35 30 */ coords[20*dim+0] = -dis; coords[20*dim+1] = -dis; coords[20*dim+2] = 0.5; 1225 /* 23 36 25 */ coords[21*dim+0] = dis; coords[21*dim+1] = -dis; coords[21*dim+2] = 0.5; 1226 /* 24 37 26 */ coords[22*dim+0] = dis; coords[22*dim+1] = dis; coords[22*dim+2] = 0.5; 1227 /* 27 38 28 */ coords[23*dim+0] = -dis; coords[23*dim+1] = dis; coords[23*dim+2] = 0.5; 1228 } 1229 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 1230 ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr); 1231 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 1232 } 1233 /* Create periodicity */ 1234 if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) { 1235 PetscReal L[3]; 1236 PetscReal maxCell[3]; 1237 DMBoundaryType bdType[3]; 1238 PetscReal lower[3] = {0.0, 0.0, 0.0}; 1239 PetscReal upper[3] = {1.0, 1.0, 1.5}; 1240 PetscInt i, numZCells = 3; 1241 1242 bdType[0] = DM_BOUNDARY_NONE; 1243 bdType[1] = DM_BOUNDARY_NONE; 1244 bdType[2] = periodicZ; 1245 for (i = 0; i < dim; i++) { 1246 L[i] = upper[i] - lower[i]; 1247 maxCell[i] = 1.1 * (L[i] / numZCells); 1248 } 1249 ierr = DMSetPeriodicity(*dm, PETSC_TRUE, maxCell, L, bdType);CHKERRQ(ierr); 1250 } 1251 /* Refine topology */ 1252 for (r = 0; r < numRefine; ++r) { 1253 DM rdm = NULL; 1254 1255 ierr = DMRefine(*dm, comm, &rdm);CHKERRQ(ierr); 1256 ierr = DMDestroy(dm);CHKERRQ(ierr); 1257 *dm = rdm; 1258 } 1259 /* Remap geometry to cylinder 1260 Interior square: Linear interpolation is correct 1261 The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing 1262 such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance 1263 1264 phi = arctan(y/x) 1265 d_close = sqrt(1/8 + 1/4 sin^2(phi)) 1266 d_far = sqrt(1/2 + sin^2(phi)) 1267 1268 so we remap them using 1269 1270 x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close) 1271 y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close) 1272 1273 If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y. 1274 */ 1275 { 1276 Vec coordinates; 1277 PetscSection coordSection; 1278 PetscScalar *coords; 1279 PetscInt vStart, vEnd, v; 1280 const PetscReal dis = 1.0/PetscSqrtReal(2.0); 1281 const PetscReal ds2 = 0.5*dis; 1282 1283 ierr = DMPlexGetDepthStratum(*dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1284 ierr = DMGetCoordinateSection(*dm, &coordSection);CHKERRQ(ierr); 1285 ierr = DMGetCoordinatesLocal(*dm, &coordinates);CHKERRQ(ierr); 1286 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 1287 for (v = vStart; v < vEnd; ++v) { 1288 PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc; 1289 PetscInt off; 1290 1291 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 1292 if ((PetscAbsScalar(coords[off+0]) <= ds2) && (PetscAbsScalar(coords[off+1]) <= ds2)) continue; 1293 x = PetscRealPart(coords[off]); 1294 y = PetscRealPart(coords[off+1]); 1295 phi = PetscAtan2Real(y, x); 1296 sinp = PetscSinReal(phi); 1297 cosp = PetscCosReal(phi); 1298 if ((PetscAbsReal(phi) > PETSC_PI/4.0) && (PetscAbsReal(phi) < 3.0*PETSC_PI/4.0)) { 1299 dc = PetscAbsReal(ds2/sinp); 1300 df = PetscAbsReal(dis/sinp); 1301 xc = ds2*x/PetscAbsReal(y); 1302 yc = ds2*PetscSignReal(y); 1303 } else { 1304 dc = PetscAbsReal(ds2/cosp); 1305 df = PetscAbsReal(dis/cosp); 1306 xc = ds2*PetscSignReal(x); 1307 yc = ds2*y/PetscAbsReal(x); 1308 } 1309 coords[off+0] = xc + (coords[off+0] - xc)*(1.0 - dc)/(df - dc); 1310 coords[off+1] = yc + (coords[off+1] - yc)*(1.0 - dc)/(df - dc); 1311 } 1312 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 1313 if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) { 1314 ierr = DMLocalizeCoordinates(*dm);CHKERRQ(ierr); 1315 } 1316 } 1317 PetscFunctionReturn(0); 1318 } 1319 1320 /*@ 1321 DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges. 1322 1323 Collective on MPI_Comm 1324 1325 Input Parameters: 1326 + comm - The communicator for the DM object 1327 . n - The number of wedges around the origin 1328 - interpolate - Create edges and faces 1329 1330 Output Parameter: 1331 . dm - The DM object 1332 1333 Level: beginner 1334 1335 .keywords: DM, create 1336 .seealso: DMPlexCreateHexCylinderMesh(), DMPlexCreateHexBoxMesh(), DMPlexCreateBoxMesh(), DMSetType(), DMCreate() 1337 @*/ 1338 PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm) 1339 { 1340 const PetscInt dim = 3; 1341 PetscInt numCells, numVertices; 1342 PetscErrorCode ierr; 1343 1344 PetscFunctionBegin; 1345 PetscValidPointer(dm, 3); 1346 if (n < 0) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %D cannot be negative", n); 1347 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 1348 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 1349 ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); 1350 /* Create topology */ 1351 { 1352 PetscInt cone[6], c; 1353 1354 numCells = n; 1355 numVertices = 2*(n+1); 1356 ierr = DMPlexSetChart(*dm, 0, numCells+numVertices);CHKERRQ(ierr); 1357 for (c = 0; c < numCells; c++) {ierr = DMPlexSetConeSize(*dm, c, 6);CHKERRQ(ierr);} 1358 ierr = DMSetUp(*dm);CHKERRQ(ierr); 1359 for (c = 0; c < numCells; c++) { 1360 cone[0] = c+n*1; cone[1] = (c+1)%n+n*1; cone[2] = 0+3*n; 1361 cone[3] = c+n*2; cone[4] = (c+1)%n+n*2; cone[5] = 1+3*n; 1362 ierr = DMPlexSetCone(*dm, c, cone);CHKERRQ(ierr); 1363 } 1364 ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr); 1365 ierr = DMPlexStratify(*dm);CHKERRQ(ierr); 1366 } 1367 /* Interpolate */ 1368 if (interpolate) { 1369 DM idm = NULL; 1370 1371 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 1372 ierr = DMDestroy(dm);CHKERRQ(ierr); 1373 *dm = idm; 1374 } 1375 /* Create cylinder geometry */ 1376 { 1377 Vec coordinates; 1378 PetscSection coordSection; 1379 PetscScalar *coords; 1380 PetscInt coordSize, v, c; 1381 1382 /* Build coordinates */ 1383 ierr = DMGetCoordinateSection(*dm, &coordSection);CHKERRQ(ierr); 1384 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 1385 ierr = PetscSectionSetFieldComponents(coordSection, 0, dim);CHKERRQ(ierr); 1386 ierr = PetscSectionSetChart(coordSection, numCells, numCells+numVertices);CHKERRQ(ierr); 1387 for (v = numCells; v < numCells+numVertices; ++v) { 1388 ierr = PetscSectionSetDof(coordSection, v, dim);CHKERRQ(ierr); 1389 ierr = PetscSectionSetFieldDof(coordSection, v, 0, dim);CHKERRQ(ierr); 1390 } 1391 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 1392 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 1393 ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr); 1394 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 1395 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 1396 ierr = VecSetBlockSize(coordinates, dim);CHKERRQ(ierr); 1397 ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr); 1398 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 1399 for (c = 0; c < numCells; c++) { 1400 coords[(c+0*n)*dim+0] = PetscCosReal(2.0*c*PETSC_PI/n); coords[(c+0*n)*dim+1] = PetscSinReal(2.0*c*PETSC_PI/n); coords[(c+0*n)*dim+2] = 1.0; 1401 coords[(c+1*n)*dim+0] = PetscCosReal(2.0*c*PETSC_PI/n); coords[(c+1*n)*dim+1] = PetscSinReal(2.0*c*PETSC_PI/n); coords[(c+1*n)*dim+2] = 0.0; 1402 } 1403 coords[(2*n+0)*dim+0] = 0.0; coords[(2*n+0)*dim+1] = 0.0; coords[(2*n+0)*dim+2] = 1.0; 1404 coords[(2*n+1)*dim+0] = 0.0; coords[(2*n+1)*dim+1] = 0.0; coords[(2*n+1)*dim+2] = 0.0; 1405 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 1406 ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr); 1407 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 1408 } 1409 PetscFunctionReturn(0); 1410 } 1411 1412 PETSC_STATIC_INLINE PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 1413 { 1414 PetscReal prod = 0.0; 1415 PetscInt i; 1416 for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]); 1417 return PetscSqrtReal(prod); 1418 } 1419 PETSC_STATIC_INLINE PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 1420 { 1421 PetscReal prod = 0.0; 1422 PetscInt i; 1423 for (i = 0; i < dim; ++i) prod += x[i]*y[i]; 1424 return prod; 1425 } 1426 1427 /*@ 1428 DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d. 1429 1430 Collective on MPI_Comm 1431 1432 Input Parameters: 1433 . comm - The communicator for the DM object 1434 . dim - The dimension 1435 - simplex - Use simplices, or tensor product cells 1436 1437 Output Parameter: 1438 . dm - The DM object 1439 1440 Level: beginner 1441 1442 .keywords: DM, create 1443 .seealso: DMPlexCreateBoxMesh(), DMPlexCreateHexBoxMesh(), DMSetType(), DMCreate() 1444 @*/ 1445 PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, DM *dm) 1446 { 1447 const PetscInt embedDim = dim+1; 1448 PetscSection coordSection; 1449 Vec coordinates; 1450 PetscScalar *coords; 1451 PetscReal *coordsIn; 1452 PetscInt numCells, numEdges, numVerts, firstVertex, v, firstEdge, coordSize, d, c, e; 1453 PetscMPIInt rank; 1454 PetscErrorCode ierr; 1455 1456 PetscFunctionBegin; 1457 PetscValidPointer(dm, 4); 1458 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 1459 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 1460 ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); 1461 ierr = DMSetCoordinateDim(*dm, dim+1);CHKERRQ(ierr); 1462 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) *dm), &rank);CHKERRQ(ierr); 1463 switch (dim) { 1464 case 2: 1465 if (simplex) { 1466 DM idm = NULL; 1467 const PetscReal edgeLen = 2.0/(1.0 + PETSC_PHI); 1468 const PetscReal vertex[3] = {0.0, 1.0/(1.0 + PETSC_PHI), PETSC_PHI/(1.0 + PETSC_PHI)}; 1469 const PetscInt degree = 5; 1470 PetscInt s[3] = {1, 1, 1}; 1471 PetscInt cone[3]; 1472 PetscInt *graph, p, i, j, k; 1473 1474 numCells = !rank ? 20 : 0; 1475 numVerts = !rank ? 12 : 0; 1476 firstVertex = numCells; 1477 /* Use icosahedron, which for a unit sphere has coordinates which are all cyclic permutations of 1478 1479 (0, \pm 1/\phi+1, \pm \phi/\phi+1) 1480 1481 where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 1482 length is then given by 2/\phi = 2 * 2.73606 = 5.47214. 1483 */ 1484 /* Construct vertices */ 1485 ierr = PetscCalloc1(numVerts * embedDim, &coordsIn);CHKERRQ(ierr); 1486 for (p = 0, i = 0; p < embedDim; ++p) { 1487 for (s[1] = -1; s[1] < 2; s[1] += 2) { 1488 for (s[2] = -1; s[2] < 2; s[2] += 2) { 1489 for (d = 0; d < embedDim; ++d) coordsIn[i*embedDim+d] = s[(d+p)%embedDim]*vertex[(d+p)%embedDim]; 1490 ++i; 1491 } 1492 } 1493 } 1494 /* Construct graph */ 1495 ierr = PetscCalloc1(numVerts * numVerts, &graph);CHKERRQ(ierr); 1496 for (i = 0; i < numVerts; ++i) { 1497 for (j = 0, k = 0; j < numVerts; ++j) { 1498 if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i*embedDim], &coordsIn[j*embedDim]) - edgeLen) < PETSC_SMALL) {graph[i*numVerts+j] = 1; ++k;} 1499 } 1500 if (k != degree) SETERRQ3(comm, PETSC_ERR_PLIB, "Invalid icosahedron, vertex %D degree %D != %D", i, k, degree); 1501 } 1502 /* Build Topology */ 1503 ierr = DMPlexSetChart(*dm, 0, numCells+numVerts);CHKERRQ(ierr); 1504 for (c = 0; c < numCells; c++) { 1505 ierr = DMPlexSetConeSize(*dm, c, embedDim);CHKERRQ(ierr); 1506 } 1507 ierr = DMSetUp(*dm);CHKERRQ(ierr); /* Allocate space for cones */ 1508 /* Cells */ 1509 for (i = 0, c = 0; i < numVerts; ++i) { 1510 for (j = 0; j < i; ++j) { 1511 for (k = 0; k < j; ++k) { 1512 if (graph[i*numVerts+j] && graph[j*numVerts+k] && graph[k*numVerts+i]) { 1513 cone[0] = firstVertex+i; cone[1] = firstVertex+j; cone[2] = firstVertex+k; 1514 /* Check orientation */ 1515 { 1516 const PetscInt epsilon[3][3][3] = {{{0, 0, 0}, {0, 0, 1}, {0, -1, 0}}, {{0, 0, -1}, {0, 0, 0}, {1, 0, 0}}, {{0, 1, 0}, {-1, 0, 0}, {0, 0, 0}}}; 1517 PetscReal normal[3]; 1518 PetscInt e, f; 1519 1520 for (d = 0; d < embedDim; ++d) { 1521 normal[d] = 0.0; 1522 for (e = 0; e < embedDim; ++e) { 1523 for (f = 0; f < embedDim; ++f) { 1524 normal[d] += epsilon[d][e][f]*(coordsIn[j*embedDim+e] - coordsIn[i*embedDim+e])*(coordsIn[k*embedDim+f] - coordsIn[i*embedDim+f]); 1525 } 1526 } 1527 } 1528 if (DotReal(embedDim, normal, &coordsIn[i*embedDim]) < 0) {PetscInt tmp = cone[1]; cone[1] = cone[2]; cone[2] = tmp;} 1529 } 1530 ierr = DMPlexSetCone(*dm, c++, cone);CHKERRQ(ierr); 1531 } 1532 } 1533 } 1534 } 1535 ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr); 1536 ierr = DMPlexStratify(*dm);CHKERRQ(ierr); 1537 ierr = PetscFree(graph);CHKERRQ(ierr); 1538 /* Interpolate mesh */ 1539 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 1540 ierr = DMDestroy(dm);CHKERRQ(ierr); 1541 *dm = idm; 1542 } else { 1543 /* 1544 12-21--13 1545 | | 1546 25 4 24 1547 | | 1548 12-25--9-16--8-24--13 1549 | | | | 1550 23 5 17 0 15 3 22 1551 | | | | 1552 10-20--6-14--7-19--11 1553 | | 1554 20 1 19 1555 | | 1556 10-18--11 1557 | | 1558 23 2 22 1559 | | 1560 12-21--13 1561 */ 1562 const PetscReal dist = 1.0/PetscSqrtReal(3.0); 1563 PetscInt cone[4], ornt[4]; 1564 1565 numCells = !rank ? 6 : 0; 1566 numEdges = !rank ? 12 : 0; 1567 numVerts = !rank ? 8 : 0; 1568 firstVertex = numCells; 1569 firstEdge = numCells + numVerts; 1570 /* Build Topology */ 1571 ierr = DMPlexSetChart(*dm, 0, numCells+numEdges+numVerts);CHKERRQ(ierr); 1572 for (c = 0; c < numCells; c++) { 1573 ierr = DMPlexSetConeSize(*dm, c, 4);CHKERRQ(ierr); 1574 } 1575 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 1576 ierr = DMPlexSetConeSize(*dm, e, 2);CHKERRQ(ierr); 1577 } 1578 ierr = DMSetUp(*dm);CHKERRQ(ierr); /* Allocate space for cones */ 1579 /* Cell 0 */ 1580 cone[0] = 14; cone[1] = 15; cone[2] = 16; cone[3] = 17; 1581 ierr = DMPlexSetCone(*dm, 0, cone);CHKERRQ(ierr); 1582 ornt[0] = 0; ornt[1] = 0; ornt[2] = 0; ornt[3] = 0; 1583 ierr = DMPlexSetConeOrientation(*dm, 0, ornt);CHKERRQ(ierr); 1584 /* Cell 1 */ 1585 cone[0] = 18; cone[1] = 19; cone[2] = 14; cone[3] = 20; 1586 ierr = DMPlexSetCone(*dm, 1, cone);CHKERRQ(ierr); 1587 ornt[0] = 0; ornt[1] = 0; ornt[2] = -2; ornt[3] = 0; 1588 ierr = DMPlexSetConeOrientation(*dm, 1, ornt);CHKERRQ(ierr); 1589 /* Cell 2 */ 1590 cone[0] = 21; cone[1] = 22; cone[2] = 18; cone[3] = 23; 1591 ierr = DMPlexSetCone(*dm, 2, cone);CHKERRQ(ierr); 1592 ornt[0] = 0; ornt[1] = 0; ornt[2] = -2; ornt[3] = 0; 1593 ierr = DMPlexSetConeOrientation(*dm, 2, ornt);CHKERRQ(ierr); 1594 /* Cell 3 */ 1595 cone[0] = 19; cone[1] = 22; cone[2] = 24; cone[3] = 15; 1596 ierr = DMPlexSetCone(*dm, 3, cone);CHKERRQ(ierr); 1597 ornt[0] = -2; ornt[1] = -2; ornt[2] = 0; ornt[3] = -2; 1598 ierr = DMPlexSetConeOrientation(*dm, 3, ornt);CHKERRQ(ierr); 1599 /* Cell 4 */ 1600 cone[0] = 16; cone[1] = 24; cone[2] = 21; cone[3] = 25; 1601 ierr = DMPlexSetCone(*dm, 4, cone);CHKERRQ(ierr); 1602 ornt[0] = -2; ornt[1] = -2; ornt[2] = -2; ornt[3] = 0; 1603 ierr = DMPlexSetConeOrientation(*dm, 4, ornt);CHKERRQ(ierr); 1604 /* Cell 5 */ 1605 cone[0] = 20; cone[1] = 17; cone[2] = 25; cone[3] = 23; 1606 ierr = DMPlexSetCone(*dm, 5, cone);CHKERRQ(ierr); 1607 ornt[0] = -2; ornt[1] = -2; ornt[2] = -2; ornt[3] = -2; 1608 ierr = DMPlexSetConeOrientation(*dm, 5, ornt);CHKERRQ(ierr); 1609 /* Edges */ 1610 cone[0] = 6; cone[1] = 7; 1611 ierr = DMPlexSetCone(*dm, 14, cone);CHKERRQ(ierr); 1612 cone[0] = 7; cone[1] = 8; 1613 ierr = DMPlexSetCone(*dm, 15, cone);CHKERRQ(ierr); 1614 cone[0] = 8; cone[1] = 9; 1615 ierr = DMPlexSetCone(*dm, 16, cone);CHKERRQ(ierr); 1616 cone[0] = 9; cone[1] = 6; 1617 ierr = DMPlexSetCone(*dm, 17, cone);CHKERRQ(ierr); 1618 cone[0] = 10; cone[1] = 11; 1619 ierr = DMPlexSetCone(*dm, 18, cone);CHKERRQ(ierr); 1620 cone[0] = 11; cone[1] = 7; 1621 ierr = DMPlexSetCone(*dm, 19, cone);CHKERRQ(ierr); 1622 cone[0] = 6; cone[1] = 10; 1623 ierr = DMPlexSetCone(*dm, 20, cone);CHKERRQ(ierr); 1624 cone[0] = 12; cone[1] = 13; 1625 ierr = DMPlexSetCone(*dm, 21, cone);CHKERRQ(ierr); 1626 cone[0] = 13; cone[1] = 11; 1627 ierr = DMPlexSetCone(*dm, 22, cone);CHKERRQ(ierr); 1628 cone[0] = 10; cone[1] = 12; 1629 ierr = DMPlexSetCone(*dm, 23, cone);CHKERRQ(ierr); 1630 cone[0] = 13; cone[1] = 8; 1631 ierr = DMPlexSetCone(*dm, 24, cone);CHKERRQ(ierr); 1632 cone[0] = 12; cone[1] = 9; 1633 ierr = DMPlexSetCone(*dm, 25, cone);CHKERRQ(ierr); 1634 ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr); 1635 ierr = DMPlexStratify(*dm);CHKERRQ(ierr); 1636 /* Build coordinates */ 1637 ierr = PetscCalloc1(numVerts * embedDim, &coordsIn);CHKERRQ(ierr); 1638 coordsIn[0*embedDim+0] = -dist; coordsIn[0*embedDim+1] = dist; coordsIn[0*embedDim+2] = -dist; 1639 coordsIn[1*embedDim+0] = dist; coordsIn[1*embedDim+1] = dist; coordsIn[1*embedDim+2] = -dist; 1640 coordsIn[2*embedDim+0] = dist; coordsIn[2*embedDim+1] = -dist; coordsIn[2*embedDim+2] = -dist; 1641 coordsIn[3*embedDim+0] = -dist; coordsIn[3*embedDim+1] = -dist; coordsIn[3*embedDim+2] = -dist; 1642 coordsIn[4*embedDim+0] = -dist; coordsIn[4*embedDim+1] = dist; coordsIn[4*embedDim+2] = dist; 1643 coordsIn[5*embedDim+0] = dist; coordsIn[5*embedDim+1] = dist; coordsIn[5*embedDim+2] = dist; 1644 coordsIn[6*embedDim+0] = -dist; coordsIn[6*embedDim+1] = -dist; coordsIn[6*embedDim+2] = dist; 1645 coordsIn[7*embedDim+0] = dist; coordsIn[7*embedDim+1] = -dist; coordsIn[7*embedDim+2] = dist; 1646 } 1647 break; 1648 case 3: 1649 if (simplex) { 1650 DM idm = NULL; 1651 const PetscReal edgeLen = 1.0/PETSC_PHI; 1652 const PetscReal vertexA[4] = {0.5, 0.5, 0.5, 0.5}; 1653 const PetscReal vertexB[4] = {1.0, 0.0, 0.0, 0.0}; 1654 const PetscReal vertexC[4] = {0.5, 0.5*PETSC_PHI, 0.5/PETSC_PHI, 0.0}; 1655 const PetscInt degree = 12; 1656 PetscInt s[4] = {1, 1, 1}; 1657 PetscInt evenPerm[12][4] = {{0, 1, 2, 3}, {0, 2, 3, 1}, {0, 3, 1, 2}, {1, 0, 3, 2}, {1, 2, 0, 3}, {1, 3, 2, 0}, 1658 {2, 0, 1, 3}, {2, 1, 3, 0}, {2, 3, 0, 1}, {3, 0, 2, 1}, {3, 1, 0, 2}, {3, 2, 1, 0}}; 1659 PetscInt cone[4]; 1660 PetscInt *graph, p, i, j, k, l; 1661 1662 numCells = !rank ? 600 : 0; 1663 numVerts = !rank ? 120 : 0; 1664 firstVertex = numCells; 1665 /* Use the 600-cell, which for a unit sphere has coordinates which are 1666 1667 1/2 (\pm 1, \pm 1, \pm 1, \pm 1) 16 1668 (\pm 1, 0, 0, 0) all cyclic permutations 8 1669 1/2 (\pm 1, \pm phi, \pm 1/phi, 0) all even permutations 96 1670 1671 where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 1672 length is then given by 1/\phi = 2.73606. 1673 1674 http://buzzard.pugetsound.edu/sage-practice/ch03s03.html 1675 http://mathworld.wolfram.com/600-Cell.html 1676 */ 1677 /* Construct vertices */ 1678 ierr = PetscCalloc1(numVerts * embedDim, &coordsIn);CHKERRQ(ierr); 1679 i = 0; 1680 for (s[0] = -1; s[0] < 2; s[0] += 2) { 1681 for (s[1] = -1; s[1] < 2; s[1] += 2) { 1682 for (s[2] = -1; s[2] < 2; s[2] += 2) { 1683 for (s[3] = -1; s[3] < 2; s[3] += 2) { 1684 for (d = 0; d < embedDim; ++d) coordsIn[i*embedDim+d] = s[d]*vertexA[d]; 1685 ++i; 1686 } 1687 } 1688 } 1689 } 1690 for (p = 0; p < embedDim; ++p) { 1691 s[1] = s[2] = s[3] = 1; 1692 for (s[0] = -1; s[0] < 2; s[0] += 2) { 1693 for (d = 0; d < embedDim; ++d) coordsIn[i*embedDim+d] = s[(d+p)%embedDim]*vertexB[(d+p)%embedDim]; 1694 ++i; 1695 } 1696 } 1697 for (p = 0; p < 12; ++p) { 1698 s[3] = 1; 1699 for (s[0] = -1; s[0] < 2; s[0] += 2) { 1700 for (s[1] = -1; s[1] < 2; s[1] += 2) { 1701 for (s[2] = -1; s[2] < 2; s[2] += 2) { 1702 for (d = 0; d < embedDim; ++d) coordsIn[i*embedDim+d] = s[evenPerm[p][d]]*vertexC[evenPerm[p][d]]; 1703 ++i; 1704 } 1705 } 1706 } 1707 } 1708 if (i != numVerts) SETERRQ2(comm, PETSC_ERR_PLIB, "Invalid 600-cell, vertices %D != %D", i, numVerts); 1709 /* Construct graph */ 1710 ierr = PetscCalloc1(numVerts * numVerts, &graph);CHKERRQ(ierr); 1711 for (i = 0; i < numVerts; ++i) { 1712 for (j = 0, k = 0; j < numVerts; ++j) { 1713 if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i*embedDim], &coordsIn[j*embedDim]) - edgeLen) < PETSC_SMALL) {graph[i*numVerts+j] = 1; ++k;} 1714 } 1715 if (k != degree) SETERRQ3(comm, PETSC_ERR_PLIB, "Invalid 600-cell, vertex %D degree %D != %D", i, k, degree); 1716 } 1717 /* Build Topology */ 1718 ierr = DMPlexSetChart(*dm, 0, numCells+numVerts);CHKERRQ(ierr); 1719 for (c = 0; c < numCells; c++) { 1720 ierr = DMPlexSetConeSize(*dm, c, embedDim);CHKERRQ(ierr); 1721 } 1722 ierr = DMSetUp(*dm);CHKERRQ(ierr); /* Allocate space for cones */ 1723 /* Cells */ 1724 for (i = 0, c = 0; i < numVerts; ++i) { 1725 for (j = 0; j < i; ++j) { 1726 for (k = 0; k < j; ++k) { 1727 for (l = 0; l < k; ++l) { 1728 if (graph[i*numVerts+j] && graph[j*numVerts+k] && graph[k*numVerts+i] && 1729 graph[l*numVerts+i] && graph[l*numVerts+j] && graph[l*numVerts+k]) { 1730 cone[0] = firstVertex+i; cone[1] = firstVertex+j; cone[2] = firstVertex+k; cone[3] = firstVertex+l; 1731 /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */ 1732 { 1733 const PetscInt epsilon[4][4][4][4] = {{{{0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}}, 1734 {{0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 1}, { 0, 0, -1, 0}}, 1735 {{0, 0, 0, 0}, { 0, 0, 0, -1}, { 0, 0, 0, 0}, { 0, 1, 0, 0}}, 1736 {{0, 0, 0, 0}, { 0, 0, 1, 0}, { 0, -1, 0, 0}, { 0, 0, 0, 0}}}, 1737 1738 {{{0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, -1}, { 0, 0, 1, 0}}, 1739 {{0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}}, 1740 {{0, 0, 0, 1}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, {-1, 0, 0, 0}}, 1741 {{0, 0, -1, 0}, { 0, 0, 0, 0}, { 1, 0, 0, 0}, { 0, 0, 0, 0}}}, 1742 1743 {{{0, 0, 0, 0}, { 0, 0, 0, 1}, { 0, 0, 0, 0}, { 0, -1, 0, 0}}, 1744 {{0, 0, 0, -1}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 1, 0, 0, 0}}, 1745 {{0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}}, 1746 {{0, 1, 0, 0}, {-1, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}}}, 1747 1748 {{{0, 0, 0, 0}, { 0, 0, -1, 0}, { 0, 1, 0, 0}, { 0, 0, 0, 0}}, 1749 {{0, 0, 1, 0}, { 0, 0, 0, 0}, {-1, 0, 0, 0}, { 0, 0, 0, 0}}, 1750 {{0, -1, 0, 0}, { 1, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}}, 1751 {{0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}}}}; 1752 PetscReal normal[4]; 1753 PetscInt e, f, g; 1754 1755 for (d = 0; d < embedDim; ++d) { 1756 normal[d] = 0.0; 1757 for (e = 0; e < embedDim; ++e) { 1758 for (f = 0; f < embedDim; ++f) { 1759 for (g = 0; g < embedDim; ++g) { 1760 normal[d] += epsilon[d][e][f][g]*(coordsIn[j*embedDim+e] - coordsIn[i*embedDim+e])*(coordsIn[k*embedDim+f] - coordsIn[i*embedDim+f])*(coordsIn[l*embedDim+f] - coordsIn[i*embedDim+f]); 1761 } 1762 } 1763 } 1764 } 1765 if (DotReal(embedDim, normal, &coordsIn[i*embedDim]) < 0) {PetscInt tmp = cone[1]; cone[1] = cone[2]; cone[2] = tmp;} 1766 } 1767 ierr = DMPlexSetCone(*dm, c++, cone);CHKERRQ(ierr); 1768 } 1769 } 1770 } 1771 } 1772 } 1773 ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr); 1774 ierr = DMPlexStratify(*dm);CHKERRQ(ierr); 1775 ierr = PetscFree(graph);CHKERRQ(ierr); 1776 /* Interpolate mesh */ 1777 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 1778 ierr = DMDestroy(dm);CHKERRQ(ierr); 1779 *dm = idm; 1780 break; 1781 } 1782 default: SETERRQ1(comm, PETSC_ERR_SUP, "Unsupported dimension for sphere: %D", dim); 1783 } 1784 /* Create coordinates */ 1785 ierr = DMGetCoordinateSection(*dm, &coordSection);CHKERRQ(ierr); 1786 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 1787 ierr = PetscSectionSetFieldComponents(coordSection, 0, embedDim);CHKERRQ(ierr); 1788 ierr = PetscSectionSetChart(coordSection, firstVertex, firstVertex+numVerts);CHKERRQ(ierr); 1789 for (v = firstVertex; v < firstVertex+numVerts; ++v) { 1790 ierr = PetscSectionSetDof(coordSection, v, embedDim);CHKERRQ(ierr); 1791 ierr = PetscSectionSetFieldDof(coordSection, v, 0, embedDim);CHKERRQ(ierr); 1792 } 1793 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 1794 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 1795 ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr); 1796 ierr = VecSetBlockSize(coordinates, embedDim);CHKERRQ(ierr); 1797 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 1798 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 1799 ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr); 1800 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 1801 for (v = 0; v < numVerts; ++v) for (d = 0; d < embedDim; ++d) {coords[v*embedDim+d] = coordsIn[v*embedDim+d];} 1802 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 1803 ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr); 1804 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 1805 ierr = PetscFree(coordsIn);CHKERRQ(ierr); 1806 PetscFunctionReturn(0); 1807 } 1808 1809 /* External function declarations here */ 1810 extern PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling); 1811 extern PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat); 1812 extern PetscErrorCode DMCreateDefaultSection_Plex(DM dm); 1813 extern PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm); 1814 extern PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J); 1815 extern PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm); 1816 PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm); 1817 extern PetscErrorCode DMSetUp_Plex(DM dm); 1818 extern PetscErrorCode DMDestroy_Plex(DM dm); 1819 extern PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer); 1820 extern PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer); 1821 extern PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm); 1822 static PetscErrorCode DMInitialize_Plex(DM dm); 1823 1824 /* Replace dm with the contents of dmNew 1825 - Share the DM_Plex structure 1826 - Share the coordinates 1827 - Share the SF 1828 */ 1829 static PetscErrorCode DMPlexReplace_Static(DM dm, DM dmNew) 1830 { 1831 PetscSF sf; 1832 DM coordDM, coarseDM; 1833 Vec coords; 1834 PetscBool isper; 1835 const PetscReal *maxCell, *L; 1836 const DMBoundaryType *bd; 1837 PetscErrorCode ierr; 1838 1839 PetscFunctionBegin; 1840 ierr = DMGetPointSF(dmNew, &sf);CHKERRQ(ierr); 1841 ierr = DMSetPointSF(dm, sf);CHKERRQ(ierr); 1842 ierr = DMGetCoordinateDM(dmNew, &coordDM);CHKERRQ(ierr); 1843 ierr = DMGetCoordinatesLocal(dmNew, &coords);CHKERRQ(ierr); 1844 ierr = DMSetCoordinateDM(dm, coordDM);CHKERRQ(ierr); 1845 ierr = DMSetCoordinatesLocal(dm, coords);CHKERRQ(ierr); 1846 ierr = DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);CHKERRQ(ierr); 1847 ierr = DMSetPeriodicity(dmNew, isper, maxCell, L, bd);CHKERRQ(ierr); 1848 ierr = DMDestroy_Plex(dm);CHKERRQ(ierr); 1849 ierr = DMInitialize_Plex(dm);CHKERRQ(ierr); 1850 dm->data = dmNew->data; 1851 ((DM_Plex *) dmNew->data)->refct++; 1852 dmNew->labels->refct++; 1853 if (!--(dm->labels->refct)) { 1854 DMLabelLink next = dm->labels->next; 1855 1856 /* destroy the labels */ 1857 while (next) { 1858 DMLabelLink tmp = next->next; 1859 1860 ierr = DMLabelDestroy(&next->label);CHKERRQ(ierr); 1861 ierr = PetscFree(next);CHKERRQ(ierr); 1862 next = tmp; 1863 } 1864 ierr = PetscFree(dm->labels);CHKERRQ(ierr); 1865 } 1866 dm->labels = dmNew->labels; 1867 dm->depthLabel = dmNew->depthLabel; 1868 ierr = DMGetCoarseDM(dmNew,&coarseDM);CHKERRQ(ierr); 1869 ierr = DMSetCoarseDM(dm,coarseDM);CHKERRQ(ierr); 1870 PetscFunctionReturn(0); 1871 } 1872 1873 /* Swap dm with the contents of dmNew 1874 - Swap the DM_Plex structure 1875 - Swap the coordinates 1876 - Swap the point PetscSF 1877 */ 1878 static PetscErrorCode DMPlexSwap_Static(DM dmA, DM dmB) 1879 { 1880 DM coordDMA, coordDMB; 1881 Vec coordsA, coordsB; 1882 PetscSF sfA, sfB; 1883 void *tmp; 1884 DMLabelLinkList listTmp; 1885 DMLabel depthTmp; 1886 PetscErrorCode ierr; 1887 1888 PetscFunctionBegin; 1889 ierr = DMGetPointSF(dmA, &sfA);CHKERRQ(ierr); 1890 ierr = DMGetPointSF(dmB, &sfB);CHKERRQ(ierr); 1891 ierr = PetscObjectReference((PetscObject) sfA);CHKERRQ(ierr); 1892 ierr = DMSetPointSF(dmA, sfB);CHKERRQ(ierr); 1893 ierr = DMSetPointSF(dmB, sfA);CHKERRQ(ierr); 1894 ierr = PetscObjectDereference((PetscObject) sfA);CHKERRQ(ierr); 1895 1896 ierr = DMGetCoordinateDM(dmA, &coordDMA);CHKERRQ(ierr); 1897 ierr = DMGetCoordinateDM(dmB, &coordDMB);CHKERRQ(ierr); 1898 ierr = PetscObjectReference((PetscObject) coordDMA);CHKERRQ(ierr); 1899 ierr = DMSetCoordinateDM(dmA, coordDMB);CHKERRQ(ierr); 1900 ierr = DMSetCoordinateDM(dmB, coordDMA);CHKERRQ(ierr); 1901 ierr = PetscObjectDereference((PetscObject) coordDMA);CHKERRQ(ierr); 1902 1903 ierr = DMGetCoordinatesLocal(dmA, &coordsA);CHKERRQ(ierr); 1904 ierr = DMGetCoordinatesLocal(dmB, &coordsB);CHKERRQ(ierr); 1905 ierr = PetscObjectReference((PetscObject) coordsA);CHKERRQ(ierr); 1906 ierr = DMSetCoordinatesLocal(dmA, coordsB);CHKERRQ(ierr); 1907 ierr = DMSetCoordinatesLocal(dmB, coordsA);CHKERRQ(ierr); 1908 ierr = PetscObjectDereference((PetscObject) coordsA);CHKERRQ(ierr); 1909 1910 tmp = dmA->data; 1911 dmA->data = dmB->data; 1912 dmB->data = tmp; 1913 listTmp = dmA->labels; 1914 dmA->labels = dmB->labels; 1915 dmB->labels = listTmp; 1916 depthTmp = dmA->depthLabel; 1917 dmA->depthLabel = dmB->depthLabel; 1918 dmB->depthLabel = depthTmp; 1919 PetscFunctionReturn(0); 1920 } 1921 1922 PetscErrorCode DMSetFromOptions_NonRefinement_Plex(PetscOptionItems *PetscOptionsObject,DM dm) 1923 { 1924 DM_Plex *mesh = (DM_Plex*) dm->data; 1925 PetscErrorCode ierr; 1926 1927 PetscFunctionBegin; 1928 /* Handle viewing */ 1929 ierr = PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMView", PETSC_FALSE, &mesh->printSetValues, NULL);CHKERRQ(ierr); 1930 ierr = PetscOptionsInt("-dm_plex_print_fem", "Debug output level all fem computations", "DMView", 0, &mesh->printFEM, NULL);CHKERRQ(ierr); 1931 ierr = PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMView", mesh->printTol, &mesh->printTol, NULL);CHKERRQ(ierr); 1932 /* Point Location */ 1933 ierr = PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMView", PETSC_FALSE, &mesh->useHashLocation, NULL);CHKERRQ(ierr); 1934 /* Generation and remeshing */ 1935 ierr = PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMView", PETSC_FALSE, &mesh->remeshBd, NULL);CHKERRQ(ierr); 1936 /* Projection behavior */ 1937 ierr = PetscOptionsInt("-dm_plex_max_projection_height", "Maxmimum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL);CHKERRQ(ierr); 1938 ierr = PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL);CHKERRQ(ierr); 1939 1940 ierr = PetscPartitionerSetFromOptions(mesh->partitioner);CHKERRQ(ierr); 1941 PetscFunctionReturn(0); 1942 } 1943 1944 static PetscErrorCode DMSetFromOptions_Plex(PetscOptionItems *PetscOptionsObject,DM dm) 1945 { 1946 PetscInt refine = 0, coarsen = 0, r; 1947 PetscBool isHierarchy; 1948 PetscErrorCode ierr; 1949 1950 PetscFunctionBegin; 1951 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1952 ierr = PetscOptionsHead(PetscOptionsObject,"DMPlex Options");CHKERRQ(ierr); 1953 /* Handle DMPlex refinement */ 1954 ierr = PetscOptionsInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL);CHKERRQ(ierr); 1955 ierr = PetscOptionsInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy);CHKERRQ(ierr); 1956 if (refine) {ierr = DMPlexSetRefinementUniform(dm, PETSC_TRUE);CHKERRQ(ierr);} 1957 if (refine && isHierarchy) { 1958 DM *dms, coarseDM; 1959 1960 ierr = DMGetCoarseDM(dm, &coarseDM);CHKERRQ(ierr); 1961 ierr = PetscObjectReference((PetscObject)coarseDM);CHKERRQ(ierr); 1962 ierr = PetscMalloc1(refine,&dms);CHKERRQ(ierr); 1963 ierr = DMRefineHierarchy(dm, refine, dms);CHKERRQ(ierr); 1964 /* Total hack since we do not pass in a pointer */ 1965 ierr = DMPlexSwap_Static(dm, dms[refine-1]);CHKERRQ(ierr); 1966 if (refine == 1) { 1967 ierr = DMSetCoarseDM(dm, dms[0]);CHKERRQ(ierr); 1968 ierr = DMPlexSetRegularRefinement(dm, PETSC_TRUE);CHKERRQ(ierr); 1969 } else { 1970 ierr = DMSetCoarseDM(dm, dms[refine-2]);CHKERRQ(ierr); 1971 ierr = DMPlexSetRegularRefinement(dm, PETSC_TRUE);CHKERRQ(ierr); 1972 ierr = DMSetCoarseDM(dms[0], dms[refine-1]);CHKERRQ(ierr); 1973 ierr = DMPlexSetRegularRefinement(dms[0], PETSC_TRUE);CHKERRQ(ierr); 1974 } 1975 ierr = DMSetCoarseDM(dms[refine-1], coarseDM);CHKERRQ(ierr); 1976 ierr = PetscObjectDereference((PetscObject)coarseDM);CHKERRQ(ierr); 1977 /* Free DMs */ 1978 for (r = 0; r < refine; ++r) { 1979 ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dms[r]);CHKERRQ(ierr); 1980 ierr = DMDestroy(&dms[r]);CHKERRQ(ierr); 1981 } 1982 ierr = PetscFree(dms);CHKERRQ(ierr); 1983 } else { 1984 for (r = 0; r < refine; ++r) { 1985 DM refinedMesh; 1986 1987 ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm);CHKERRQ(ierr); 1988 ierr = DMRefine(dm, PetscObjectComm((PetscObject) dm), &refinedMesh);CHKERRQ(ierr); 1989 /* Total hack since we do not pass in a pointer */ 1990 ierr = DMPlexReplace_Static(dm, refinedMesh);CHKERRQ(ierr); 1991 ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm);CHKERRQ(ierr); 1992 ierr = DMDestroy(&refinedMesh);CHKERRQ(ierr); 1993 } 1994 } 1995 /* Handle DMPlex coarsening */ 1996 ierr = PetscOptionsInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL);CHKERRQ(ierr); 1997 ierr = PetscOptionsInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy);CHKERRQ(ierr); 1998 if (coarsen && isHierarchy) { 1999 DM *dms; 2000 2001 ierr = PetscMalloc1(coarsen, &dms);CHKERRQ(ierr); 2002 ierr = DMCoarsenHierarchy(dm, coarsen, dms);CHKERRQ(ierr); 2003 /* Free DMs */ 2004 for (r = 0; r < coarsen; ++r) { 2005 ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dms[r]);CHKERRQ(ierr); 2006 ierr = DMDestroy(&dms[r]);CHKERRQ(ierr); 2007 } 2008 ierr = PetscFree(dms);CHKERRQ(ierr); 2009 } else { 2010 for (r = 0; r < coarsen; ++r) { 2011 DM coarseMesh; 2012 2013 ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm);CHKERRQ(ierr); 2014 ierr = DMCoarsen(dm, PetscObjectComm((PetscObject) dm), &coarseMesh);CHKERRQ(ierr); 2015 /* Total hack since we do not pass in a pointer */ 2016 ierr = DMPlexReplace_Static(dm, coarseMesh);CHKERRQ(ierr); 2017 ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm);CHKERRQ(ierr); 2018 ierr = DMDestroy(&coarseMesh);CHKERRQ(ierr); 2019 } 2020 } 2021 /* Handle */ 2022 ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm);CHKERRQ(ierr); 2023 ierr = PetscOptionsTail();CHKERRQ(ierr); 2024 PetscFunctionReturn(0); 2025 } 2026 2027 static PetscErrorCode DMCreateGlobalVector_Plex(DM dm,Vec *vec) 2028 { 2029 PetscErrorCode ierr; 2030 2031 PetscFunctionBegin; 2032 ierr = DMCreateGlobalVector_Section_Private(dm,vec);CHKERRQ(ierr); 2033 /* ierr = VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM);CHKERRQ(ierr); */ 2034 ierr = VecSetOperation(*vec, VECOP_VIEW, (void (*)(void)) VecView_Plex);CHKERRQ(ierr); 2035 ierr = VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void)) VecView_Plex_Native);CHKERRQ(ierr); 2036 ierr = VecSetOperation(*vec, VECOP_LOAD, (void (*)(void)) VecLoad_Plex);CHKERRQ(ierr); 2037 ierr = VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void)) VecLoad_Plex_Native);CHKERRQ(ierr); 2038 PetscFunctionReturn(0); 2039 } 2040 2041 static PetscErrorCode DMCreateLocalVector_Plex(DM dm,Vec *vec) 2042 { 2043 PetscErrorCode ierr; 2044 2045 PetscFunctionBegin; 2046 ierr = DMCreateLocalVector_Section_Private(dm,vec);CHKERRQ(ierr); 2047 ierr = VecSetOperation(*vec, VECOP_VIEW, (void (*)(void)) VecView_Plex_Local);CHKERRQ(ierr); 2048 ierr = VecSetOperation(*vec, VECOP_LOAD, (void (*)(void)) VecLoad_Plex_Local);CHKERRQ(ierr); 2049 PetscFunctionReturn(0); 2050 } 2051 2052 static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 2053 { 2054 PetscInt depth, d; 2055 PetscErrorCode ierr; 2056 2057 PetscFunctionBegin; 2058 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2059 if (depth == 1) { 2060 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 2061 if (dim == 0) {ierr = DMPlexGetDepthStratum(dm, dim, pStart, pEnd);CHKERRQ(ierr);} 2062 else if (dim == d) {ierr = DMPlexGetDepthStratum(dm, 1, pStart, pEnd);CHKERRQ(ierr);} 2063 else {*pStart = 0; *pEnd = 0;} 2064 } else { 2065 ierr = DMPlexGetDepthStratum(dm, dim, pStart, pEnd);CHKERRQ(ierr); 2066 } 2067 PetscFunctionReturn(0); 2068 } 2069 2070 static PetscErrorCode DMGetNeighors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[]) 2071 { 2072 PetscSF sf; 2073 PetscErrorCode ierr; 2074 2075 PetscFunctionBegin; 2076 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 2077 ierr = PetscSFGetRanks(sf, nranks, ranks, NULL, NULL, NULL);CHKERRQ(ierr); 2078 PetscFunctionReturn(0); 2079 } 2080 2081 static PetscErrorCode DMInitialize_Plex(DM dm) 2082 { 2083 PetscErrorCode ierr; 2084 2085 PetscFunctionBegin; 2086 dm->ops->view = DMView_Plex; 2087 dm->ops->load = DMLoad_Plex; 2088 dm->ops->setfromoptions = DMSetFromOptions_Plex; 2089 dm->ops->clone = DMClone_Plex; 2090 dm->ops->setup = DMSetUp_Plex; 2091 dm->ops->createdefaultsection = DMCreateDefaultSection_Plex; 2092 dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_Plex; 2093 dm->ops->createglobalvector = DMCreateGlobalVector_Plex; 2094 dm->ops->createlocalvector = DMCreateLocalVector_Plex; 2095 dm->ops->getlocaltoglobalmapping = NULL; 2096 dm->ops->createfieldis = NULL; 2097 dm->ops->createcoordinatedm = DMCreateCoordinateDM_Plex; 2098 dm->ops->getcoloring = NULL; 2099 dm->ops->creatematrix = DMCreateMatrix_Plex; 2100 dm->ops->createinterpolation = DMCreateInterpolation_Plex; 2101 dm->ops->getaggregates = NULL; 2102 dm->ops->getinjection = DMCreateInjection_Plex; 2103 dm->ops->refine = DMRefine_Plex; 2104 dm->ops->coarsen = DMCoarsen_Plex; 2105 dm->ops->refinehierarchy = DMRefineHierarchy_Plex; 2106 dm->ops->coarsenhierarchy = DMCoarsenHierarchy_Plex; 2107 dm->ops->adaptlabel = DMAdaptLabel_Plex; 2108 dm->ops->adaptmetric = DMAdaptMetric_Plex; 2109 dm->ops->globaltolocalbegin = NULL; 2110 dm->ops->globaltolocalend = NULL; 2111 dm->ops->localtoglobalbegin = NULL; 2112 dm->ops->localtoglobalend = NULL; 2113 dm->ops->destroy = DMDestroy_Plex; 2114 dm->ops->createsubdm = DMCreateSubDM_Plex; 2115 dm->ops->getdimpoints = DMGetDimPoints_Plex; 2116 dm->ops->locatepoints = DMLocatePoints_Plex; 2117 dm->ops->projectfunctionlocal = DMProjectFunctionLocal_Plex; 2118 dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex; 2119 dm->ops->projectfieldlocal = DMProjectFieldLocal_Plex; 2120 dm->ops->projectfieldlabellocal = DMProjectFieldLabelLocal_Plex; 2121 dm->ops->computel2diff = DMComputeL2Diff_Plex; 2122 dm->ops->computel2gradientdiff = DMComputeL2GradientDiff_Plex; 2123 dm->ops->computel2fielddiff = DMComputeL2FieldDiff_Plex; 2124 dm->ops->getneighbors = DMGetNeighors_Plex; 2125 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C",DMPlexInsertBoundaryValues_Plex);CHKERRQ(ierr); 2126 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",DMSetUpGLVisViewer_Plex);CHKERRQ(ierr); 2127 PetscFunctionReturn(0); 2128 } 2129 2130 PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm) 2131 { 2132 DM_Plex *mesh = (DM_Plex *) dm->data; 2133 PetscErrorCode ierr; 2134 2135 PetscFunctionBegin; 2136 mesh->refct++; 2137 (*newdm)->data = mesh; 2138 ierr = PetscObjectChangeTypeName((PetscObject) *newdm, DMPLEX);CHKERRQ(ierr); 2139 ierr = DMInitialize_Plex(*newdm);CHKERRQ(ierr); 2140 PetscFunctionReturn(0); 2141 } 2142 2143 /*MC 2144 DMPLEX = "plex" - A DM object that encapsulates an unstructured mesh, or CW Complex, which can be expressed using a Hasse Diagram. 2145 In the local representation, Vecs contain all unknowns in the interior and shared boundary. This is 2146 specified by a PetscSection object. Ownership in the global representation is determined by 2147 ownership of the underlying DMPlex points. This is specified by another PetscSection object. 2148 2149 Level: intermediate 2150 2151 .seealso: DMType, DMPlexCreate(), DMCreate(), DMSetType() 2152 M*/ 2153 2154 PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm) 2155 { 2156 DM_Plex *mesh; 2157 PetscInt unit, d; 2158 PetscErrorCode ierr; 2159 2160 PetscFunctionBegin; 2161 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2162 ierr = PetscNewLog(dm,&mesh);CHKERRQ(ierr); 2163 dm->dim = 0; 2164 dm->data = mesh; 2165 2166 mesh->refct = 1; 2167 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection);CHKERRQ(ierr); 2168 mesh->maxConeSize = 0; 2169 mesh->cones = NULL; 2170 mesh->coneOrientations = NULL; 2171 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection);CHKERRQ(ierr); 2172 mesh->maxSupportSize = 0; 2173 mesh->supports = NULL; 2174 mesh->refinementUniform = PETSC_TRUE; 2175 mesh->refinementLimit = -1.0; 2176 2177 mesh->facesTmp = NULL; 2178 2179 mesh->tetgenOpts = NULL; 2180 mesh->triangleOpts = NULL; 2181 ierr = PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner);CHKERRQ(ierr); 2182 mesh->remeshBd = PETSC_FALSE; 2183 2184 mesh->subpointMap = NULL; 2185 2186 for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0; 2187 2188 mesh->regularRefinement = PETSC_FALSE; 2189 mesh->depthState = -1; 2190 mesh->globalVertexNumbers = NULL; 2191 mesh->globalCellNumbers = NULL; 2192 mesh->anchorSection = NULL; 2193 mesh->anchorIS = NULL; 2194 mesh->createanchors = NULL; 2195 mesh->computeanchormatrix = NULL; 2196 mesh->parentSection = NULL; 2197 mesh->parents = NULL; 2198 mesh->childIDs = NULL; 2199 mesh->childSection = NULL; 2200 mesh->children = NULL; 2201 mesh->referenceTree = NULL; 2202 mesh->getchildsymmetry = NULL; 2203 for (d = 0; d < 8; ++d) mesh->hybridPointMax[d] = PETSC_DETERMINE; 2204 mesh->vtkCellHeight = 0; 2205 mesh->useCone = PETSC_FALSE; 2206 mesh->useClosure = PETSC_TRUE; 2207 mesh->useAnchors = PETSC_FALSE; 2208 2209 mesh->maxProjectionHeight = 0; 2210 2211 mesh->printSetValues = PETSC_FALSE; 2212 mesh->printFEM = 0; 2213 mesh->printTol = 1.0e-10; 2214 2215 ierr = DMInitialize_Plex(dm);CHKERRQ(ierr); 2216 PetscFunctionReturn(0); 2217 } 2218 2219 /*@ 2220 DMPlexCreate - Creates a DMPlex object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram. 2221 2222 Collective on MPI_Comm 2223 2224 Input Parameter: 2225 . comm - The communicator for the DMPlex object 2226 2227 Output Parameter: 2228 . mesh - The DMPlex object 2229 2230 Level: beginner 2231 2232 .keywords: DMPlex, create 2233 @*/ 2234 PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh) 2235 { 2236 PetscErrorCode ierr; 2237 2238 PetscFunctionBegin; 2239 PetscValidPointer(mesh,2); 2240 ierr = DMCreate(comm, mesh);CHKERRQ(ierr); 2241 ierr = DMSetType(*mesh, DMPLEX);CHKERRQ(ierr); 2242 PetscFunctionReturn(0); 2243 } 2244 2245 /* 2246 This takes as input the common mesh generator output, a list of the vertices for each cell, but vertex numbers are global and an SF is built for them 2247 */ 2248 static PetscErrorCode DMPlexBuildFromCellList_Parallel_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[], PetscSF *sfVert) 2249 { 2250 PetscSF sfPoint; 2251 PetscLayout vLayout; 2252 PetscHashI vhash; 2253 PetscSFNode *remoteVerticesAdj, *vertexLocal, *vertexOwner, *remoteVertex; 2254 const PetscInt *vrange; 2255 PetscInt numVerticesAdj, off, *verticesAdj, numVerticesGhost = 0, *localVertex, *cone, c, p, v, g; 2256 PETSC_UNUSED PetscHashIIter ret, iter; 2257 PetscMPIInt rank, size; 2258 PetscErrorCode ierr; 2259 2260 PetscFunctionBegin; 2261 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 2262 ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size);CHKERRQ(ierr); 2263 /* Partition vertices */ 2264 ierr = PetscLayoutCreate(PetscObjectComm((PetscObject) dm), &vLayout);CHKERRQ(ierr); 2265 ierr = PetscLayoutSetLocalSize(vLayout, numVertices);CHKERRQ(ierr); 2266 ierr = PetscLayoutSetBlockSize(vLayout, 1);CHKERRQ(ierr); 2267 ierr = PetscLayoutSetUp(vLayout);CHKERRQ(ierr); 2268 ierr = PetscLayoutGetRanges(vLayout, &vrange);CHKERRQ(ierr); 2269 /* Count vertices and map them to procs */ 2270 PetscHashICreate(vhash); 2271 for (c = 0; c < numCells; ++c) { 2272 for (p = 0; p < numCorners; ++p) { 2273 PetscHashIPut(vhash, cells[c*numCorners+p], ret, iter); 2274 } 2275 } 2276 PetscHashISize(vhash, numVerticesAdj); 2277 ierr = PetscMalloc1(numVerticesAdj, &verticesAdj);CHKERRQ(ierr); 2278 off = 0; ierr = PetscHashIGetKeys(vhash, &off, verticesAdj);CHKERRQ(ierr); 2279 if (off != numVerticesAdj) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %D should be %D", off, numVerticesAdj); 2280 ierr = PetscSortInt(numVerticesAdj, verticesAdj);CHKERRQ(ierr); 2281 ierr = PetscMalloc1(numVerticesAdj, &remoteVerticesAdj);CHKERRQ(ierr); 2282 for (v = 0; v < numVerticesAdj; ++v) { 2283 const PetscInt gv = verticesAdj[v]; 2284 PetscInt vrank; 2285 2286 ierr = PetscFindInt(gv, size+1, vrange, &vrank);CHKERRQ(ierr); 2287 vrank = vrank < 0 ? -(vrank+2) : vrank; 2288 remoteVerticesAdj[v].index = gv - vrange[vrank]; 2289 remoteVerticesAdj[v].rank = vrank; 2290 } 2291 /* Create cones */ 2292 ierr = DMPlexSetChart(dm, 0, numCells+numVerticesAdj);CHKERRQ(ierr); 2293 for (c = 0; c < numCells; ++c) {ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr);} 2294 ierr = DMSetUp(dm);CHKERRQ(ierr); 2295 ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 2296 for (c = 0; c < numCells; ++c) { 2297 for (p = 0; p < numCorners; ++p) { 2298 const PetscInt gv = cells[c*numCorners+p]; 2299 PetscInt lv; 2300 2301 ierr = PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv);CHKERRQ(ierr); 2302 if (lv < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %D in local connectivity", gv); 2303 cone[p] = lv+numCells; 2304 } 2305 ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); 2306 } 2307 ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 2308 /* Create SF for vertices */ 2309 ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfVert);CHKERRQ(ierr); 2310 ierr = PetscObjectSetName((PetscObject) *sfVert, "Vertex Ownership SF");CHKERRQ(ierr); 2311 ierr = PetscSFSetFromOptions(*sfVert);CHKERRQ(ierr); 2312 ierr = PetscSFSetGraph(*sfVert, numVertices, numVerticesAdj, NULL, PETSC_OWN_POINTER, remoteVerticesAdj, PETSC_OWN_POINTER);CHKERRQ(ierr); 2313 ierr = PetscFree(verticesAdj);CHKERRQ(ierr); 2314 /* Build pointSF */ 2315 ierr = PetscMalloc2(numVerticesAdj, &vertexLocal, numVertices, &vertexOwner);CHKERRQ(ierr); 2316 for (v = 0; v < numVerticesAdj; ++v) {vertexLocal[v].index = v+numCells; vertexLocal[v].rank = rank;} 2317 for (v = 0; v < numVertices; ++v) {vertexOwner[v].index = -1; vertexOwner[v].rank = -1;} 2318 ierr = PetscSFReduceBegin(*sfVert, MPIU_2INT, vertexLocal, vertexOwner, MPI_MAXLOC);CHKERRQ(ierr); 2319 ierr = PetscSFReduceEnd(*sfVert, MPIU_2INT, vertexLocal, vertexOwner, MPI_MAXLOC);CHKERRQ(ierr); 2320 for (v = 0; v < numVertices; ++v) if (vertexOwner[v].rank < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Global vertex %d on rank %d was unclaimed", v + vrange[rank], rank); 2321 ierr = PetscSFBcastBegin(*sfVert, MPIU_2INT, vertexOwner, vertexLocal);CHKERRQ(ierr); 2322 ierr = PetscSFBcastEnd(*sfVert, MPIU_2INT, vertexOwner, vertexLocal);CHKERRQ(ierr); 2323 for (v = 0; v < numVerticesAdj; ++v) if (vertexLocal[v].rank != rank) ++numVerticesGhost; 2324 ierr = PetscMalloc1(numVerticesGhost, &localVertex);CHKERRQ(ierr); 2325 ierr = PetscMalloc1(numVerticesGhost, &remoteVertex);CHKERRQ(ierr); 2326 for (v = 0, g = 0; v < numVerticesAdj; ++v) { 2327 if (vertexLocal[v].rank != rank) { 2328 localVertex[g] = v+numCells; 2329 remoteVertex[g].index = vertexLocal[v].index; 2330 remoteVertex[g].rank = vertexLocal[v].rank; 2331 ++g; 2332 } 2333 } 2334 ierr = PetscFree2(vertexLocal, vertexOwner);CHKERRQ(ierr); 2335 if (g != numVerticesGhost) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of vertex ghosts %D should be %D", g, numVerticesGhost); 2336 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 2337 ierr = PetscObjectSetName((PetscObject) sfPoint, "point SF");CHKERRQ(ierr); 2338 ierr = PetscSFSetGraph(sfPoint, numCells+numVerticesAdj, numVerticesGhost, localVertex, PETSC_OWN_POINTER, remoteVertex, PETSC_OWN_POINTER);CHKERRQ(ierr); 2339 ierr = PetscLayoutDestroy(&vLayout);CHKERRQ(ierr); 2340 PetscHashIDestroy(vhash); 2341 /* Fill in the rest of the topology structure */ 2342 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 2343 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 2344 PetscFunctionReturn(0); 2345 } 2346 2347 /* 2348 This takes as input the coordinates for each owned vertex 2349 */ 2350 static PetscErrorCode DMPlexBuildCoordinates_Parallel_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numV, PetscSF sfVert, const PetscReal vertexCoords[]) 2351 { 2352 PetscSection coordSection; 2353 Vec coordinates; 2354 PetscScalar *coords; 2355 PetscInt numVertices, numVerticesAdj, coordSize, v; 2356 PetscErrorCode ierr; 2357 2358 PetscFunctionBegin; 2359 ierr = DMSetCoordinateDim(dm, spaceDim);CHKERRQ(ierr); 2360 ierr = PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL);CHKERRQ(ierr); 2361 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 2362 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 2363 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 2364 ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVerticesAdj);CHKERRQ(ierr); 2365 for (v = numCells; v < numCells+numVerticesAdj; ++v) { 2366 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 2367 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 2368 } 2369 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 2370 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 2371 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinates);CHKERRQ(ierr); 2372 ierr = VecSetBlockSize(coordinates, spaceDim);CHKERRQ(ierr); 2373 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 2374 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 2375 ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr); 2376 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 2377 { 2378 MPI_Datatype coordtype; 2379 2380 /* Need a temp buffer for coords if we have complex/single */ 2381 ierr = MPI_Type_contiguous(spaceDim, MPIU_SCALAR, &coordtype);CHKERRQ(ierr); 2382 ierr = MPI_Type_commit(&coordtype);CHKERRQ(ierr); 2383 #if defined(PETSC_USE_COMPLEX) 2384 { 2385 PetscScalar *svertexCoords; 2386 PetscInt i; 2387 ierr = PetscMalloc1(numV*spaceDim,&svertexCoords);CHKERRQ(ierr); 2388 for (i=0; i<numV*spaceDim; i++) svertexCoords[i] = vertexCoords[i]; 2389 ierr = PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords);CHKERRQ(ierr); 2390 ierr = PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords);CHKERRQ(ierr); 2391 ierr = PetscFree(svertexCoords);CHKERRQ(ierr); 2392 } 2393 #else 2394 ierr = PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords);CHKERRQ(ierr); 2395 ierr = PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords);CHKERRQ(ierr); 2396 #endif 2397 ierr = MPI_Type_free(&coordtype);CHKERRQ(ierr); 2398 } 2399 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 2400 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 2401 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 2402 PetscFunctionReturn(0); 2403 } 2404 2405 /*@C 2406 DMPlexCreateFromCellListParallel - This takes as input common mesh generator output, a list of the vertices for each cell, and produces a DM 2407 2408 Input Parameters: 2409 + comm - The communicator 2410 . dim - The topological dimension of the mesh 2411 . numCells - The number of cells owned by this process 2412 . numVertices - The number of vertices owned by this process 2413 . numCorners - The number of vertices for each cell 2414 . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 2415 . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 2416 . spaceDim - The spatial dimension used for coordinates 2417 - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 2418 2419 Output Parameter: 2420 + dm - The DM 2421 - vertexSF - Optional, SF describing complete vertex ownership 2422 2423 Note: Two triangles sharing a face 2424 $ 2425 $ 2 2426 $ / | \ 2427 $ / | \ 2428 $ / | \ 2429 $ 0 0 | 1 3 2430 $ \ | / 2431 $ \ | / 2432 $ \ | / 2433 $ 1 2434 would have input 2435 $ numCells = 2, numVertices = 4 2436 $ cells = [0 1 2 1 3 2] 2437 $ 2438 which would result in the DMPlex 2439 $ 2440 $ 4 2441 $ / | \ 2442 $ / | \ 2443 $ / | \ 2444 $ 2 0 | 1 5 2445 $ \ | / 2446 $ \ | / 2447 $ \ | / 2448 $ 3 2449 2450 Level: beginner 2451 2452 .seealso: DMPlexCreateFromCellList(), DMPlexCreateFromDAG(), DMPlexCreate() 2453 @*/ 2454 PetscErrorCode DMPlexCreateFromCellListParallel(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], PetscInt spaceDim, const PetscReal vertexCoords[], PetscSF *vertexSF, DM *dm) 2455 { 2456 PetscSF sfVert; 2457 PetscErrorCode ierr; 2458 2459 PetscFunctionBegin; 2460 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 2461 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 2462 PetscValidLogicalCollectiveInt(*dm, dim, 2); 2463 PetscValidLogicalCollectiveInt(*dm, spaceDim, 8); 2464 ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); 2465 ierr = DMPlexBuildFromCellList_Parallel_Private(*dm, numCells, numVertices, numCorners, cells, &sfVert);CHKERRQ(ierr); 2466 if (interpolate) { 2467 DM idm = NULL; 2468 2469 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 2470 ierr = DMDestroy(dm);CHKERRQ(ierr); 2471 *dm = idm; 2472 } 2473 ierr = DMPlexBuildCoordinates_Parallel_Private(*dm, spaceDim, numCells, numVertices,sfVert, vertexCoords);CHKERRQ(ierr); 2474 if (vertexSF) *vertexSF = sfVert; 2475 else {ierr = PetscSFDestroy(&sfVert);CHKERRQ(ierr);} 2476 PetscFunctionReturn(0); 2477 } 2478 2479 /* 2480 This takes as input the common mesh generator output, a list of the vertices for each cell 2481 */ 2482 static PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[]) 2483 { 2484 PetscInt *cone, c, p; 2485 PetscErrorCode ierr; 2486 2487 PetscFunctionBegin; 2488 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 2489 for (c = 0; c < numCells; ++c) { 2490 ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); 2491 } 2492 ierr = DMSetUp(dm);CHKERRQ(ierr); 2493 ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 2494 for (c = 0; c < numCells; ++c) { 2495 for (p = 0; p < numCorners; ++p) { 2496 cone[p] = cells[c*numCorners+p]+numCells; 2497 } 2498 ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); 2499 } 2500 ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 2501 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 2502 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 2503 PetscFunctionReturn(0); 2504 } 2505 2506 /* 2507 This takes as input the coordinates for each vertex 2508 */ 2509 static PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[]) 2510 { 2511 PetscSection coordSection; 2512 Vec coordinates; 2513 DM cdm; 2514 PetscScalar *coords; 2515 PetscInt v, d; 2516 PetscErrorCode ierr; 2517 2518 PetscFunctionBegin; 2519 ierr = DMSetCoordinateDim(dm, spaceDim);CHKERRQ(ierr); 2520 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 2521 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 2522 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 2523 ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); 2524 for (v = numCells; v < numCells+numVertices; ++v) { 2525 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 2526 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 2527 } 2528 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 2529 2530 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 2531 ierr = DMCreateLocalVector(cdm, &coordinates);CHKERRQ(ierr); 2532 ierr = VecSetBlockSize(coordinates, spaceDim);CHKERRQ(ierr); 2533 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 2534 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 2535 for (v = 0; v < numVertices; ++v) { 2536 for (d = 0; d < spaceDim; ++d) { 2537 coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 2538 } 2539 } 2540 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 2541 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 2542 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 2543 PetscFunctionReturn(0); 2544 } 2545 2546 /*@C 2547 DMPlexCreateFromCellList - This takes as input common mesh generator output, a list of the vertices for each cell, and produces a DM 2548 2549 Input Parameters: 2550 + comm - The communicator 2551 . dim - The topological dimension of the mesh 2552 . numCells - The number of cells 2553 . numVertices - The number of vertices 2554 . numCorners - The number of vertices for each cell 2555 . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 2556 . cells - An array of numCells*numCorners numbers, the vertices for each cell 2557 . spaceDim - The spatial dimension used for coordinates 2558 - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 2559 2560 Output Parameter: 2561 . dm - The DM 2562 2563 Note: Two triangles sharing a face 2564 $ 2565 $ 2 2566 $ / | \ 2567 $ / | \ 2568 $ / | \ 2569 $ 0 0 | 1 3 2570 $ \ | / 2571 $ \ | / 2572 $ \ | / 2573 $ 1 2574 would have input 2575 $ numCells = 2, numVertices = 4 2576 $ cells = [0 1 2 1 3 2] 2577 $ 2578 which would result in the DMPlex 2579 $ 2580 $ 4 2581 $ / | \ 2582 $ / | \ 2583 $ / | \ 2584 $ 2 0 | 1 5 2585 $ \ | / 2586 $ \ | / 2587 $ \ | / 2588 $ 3 2589 2590 Level: beginner 2591 2592 .seealso: DMPlexCreateFromDAG(), DMPlexCreate() 2593 @*/ 2594 PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], PetscInt spaceDim, const double vertexCoords[], DM *dm) 2595 { 2596 PetscErrorCode ierr; 2597 2598 PetscFunctionBegin; 2599 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 2600 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 2601 ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); 2602 ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); 2603 if (interpolate) { 2604 DM idm = NULL; 2605 2606 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 2607 ierr = DMDestroy(dm);CHKERRQ(ierr); 2608 *dm = idm; 2609 } 2610 ierr = DMPlexBuildCoordinates_Private(*dm, spaceDim, numCells, numVertices, vertexCoords);CHKERRQ(ierr); 2611 PetscFunctionReturn(0); 2612 } 2613 2614 /*@ 2615 DMPlexCreateFromDAG - This takes as input the adjacency-list representation of the Directed Acyclic Graph (Hasse Diagram) encoding a mesh, and produces a DM 2616 2617 Input Parameters: 2618 + dm - The empty DM object, usually from DMCreate() and DMSetDimension() 2619 . depth - The depth of the DAG 2620 . numPoints - The number of points at each depth 2621 . coneSize - The cone size of each point 2622 . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point 2623 . coneOrientations - The orientation of each cone point 2624 - vertexCoords - An array of numVertices*dim numbers, the coordinates of each vertex 2625 2626 Output Parameter: 2627 . dm - The DM 2628 2629 Note: Two triangles sharing a face would have input 2630 $ depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0] 2631 $ cones = [2 3 4 3 5 4], coneOrientations = [0 0 0 0 0 0] 2632 $ vertexCoords = [-1.0 0.0 0.0 -1.0 0.0 1.0 1.0 0.0] 2633 $ 2634 which would result in the DMPlex 2635 $ 2636 $ 4 2637 $ / | \ 2638 $ / | \ 2639 $ / | \ 2640 $ 2 0 | 1 5 2641 $ \ | / 2642 $ \ | / 2643 $ \ | / 2644 $ 3 2645 $ 2646 $ Notice that all points are numbered consecutively, unlikely DMPlexCreateFromCellList() 2647 2648 Level: advanced 2649 2650 .seealso: DMPlexCreateFromCellList(), DMPlexCreate() 2651 @*/ 2652 PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[]) 2653 { 2654 Vec coordinates; 2655 PetscSection coordSection; 2656 PetscScalar *coords; 2657 PetscInt coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off; 2658 PetscErrorCode ierr; 2659 2660 PetscFunctionBegin; 2661 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 2662 ierr = DMGetCoordinateDim(dm, &dimEmbed);CHKERRQ(ierr); 2663 if (dimEmbed < dim) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Embedding dimension %d cannot be less than intrinsic dimension %d",dimEmbed,dim); 2664 for (d = 0; d <= depth; ++d) pEnd += numPoints[d]; 2665 ierr = DMPlexSetChart(dm, pStart, pEnd);CHKERRQ(ierr); 2666 for (p = pStart; p < pEnd; ++p) { 2667 ierr = DMPlexSetConeSize(dm, p, coneSize[p-pStart]);CHKERRQ(ierr); 2668 if (firstVertex < 0 && !coneSize[p - pStart]) { 2669 firstVertex = p - pStart; 2670 } 2671 } 2672 if (firstVertex < 0 && numPoints[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Expected %d vertices but could not find any", numPoints[0]); 2673 ierr = DMSetUp(dm);CHKERRQ(ierr); /* Allocate space for cones */ 2674 for (p = pStart, off = 0; p < pEnd; off += coneSize[p-pStart], ++p) { 2675 ierr = DMPlexSetCone(dm, p, &cones[off]);CHKERRQ(ierr); 2676 ierr = DMPlexSetConeOrientation(dm, p, &coneOrientations[off]);CHKERRQ(ierr); 2677 } 2678 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 2679 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 2680 /* Build coordinates */ 2681 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 2682 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 2683 ierr = PetscSectionSetFieldComponents(coordSection, 0, dimEmbed);CHKERRQ(ierr); 2684 ierr = PetscSectionSetChart(coordSection, firstVertex, firstVertex+numPoints[0]);CHKERRQ(ierr); 2685 for (v = firstVertex; v < firstVertex+numPoints[0]; ++v) { 2686 ierr = PetscSectionSetDof(coordSection, v, dimEmbed);CHKERRQ(ierr); 2687 ierr = PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed);CHKERRQ(ierr); 2688 } 2689 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 2690 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 2691 ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr); 2692 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 2693 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 2694 ierr = VecSetBlockSize(coordinates, dimEmbed);CHKERRQ(ierr); 2695 ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr); 2696 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 2697 for (v = 0; v < numPoints[0]; ++v) { 2698 PetscInt off; 2699 2700 ierr = PetscSectionGetOffset(coordSection, v+firstVertex, &off);CHKERRQ(ierr); 2701 for (d = 0; d < dimEmbed; ++d) { 2702 coords[off+d] = vertexCoords[v*dimEmbed+d]; 2703 } 2704 } 2705 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 2706 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 2707 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 2708 PetscFunctionReturn(0); 2709 } 2710 2711 /*@C 2712 DMPlexCreateFromFile - This takes a filename and produces a DM 2713 2714 Input Parameters: 2715 + comm - The communicator 2716 . filename - A file name 2717 - interpolate - Flag to create intermediate mesh pieces (edges, faces) 2718 2719 Output Parameter: 2720 . dm - The DM 2721 2722 Level: beginner 2723 2724 .seealso: DMPlexCreateFromDAG(), DMPlexCreateFromCellList(), DMPlexCreate() 2725 @*/ 2726 PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 2727 { 2728 const char *extGmsh = ".msh"; 2729 const char *extCGNS = ".cgns"; 2730 const char *extExodus = ".exo"; 2731 const char *extGenesis = ".gen"; 2732 const char *extFluent = ".cas"; 2733 const char *extHDF5 = ".h5"; 2734 const char *extMed = ".med"; 2735 const char *extPLY = ".ply"; 2736 size_t len; 2737 PetscBool isGmsh, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isMed, isPLY; 2738 PetscMPIInt rank; 2739 PetscErrorCode ierr; 2740 2741 PetscFunctionBegin; 2742 PetscValidPointer(filename, 2); 2743 PetscValidPointer(dm, 4); 2744 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 2745 ierr = PetscStrlen(filename, &len);CHKERRQ(ierr); 2746 if (!len) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path"); 2747 ierr = PetscStrncmp(&filename[PetscMax(0,len-4)], extGmsh, 4, &isGmsh);CHKERRQ(ierr); 2748 ierr = PetscStrncmp(&filename[PetscMax(0,len-5)], extCGNS, 5, &isCGNS);CHKERRQ(ierr); 2749 ierr = PetscStrncmp(&filename[PetscMax(0,len-4)], extExodus, 4, &isExodus);CHKERRQ(ierr); 2750 ierr = PetscStrncmp(&filename[PetscMax(0,len-4)], extGenesis, 4, &isGenesis);CHKERRQ(ierr); 2751 ierr = PetscStrncmp(&filename[PetscMax(0,len-4)], extFluent, 4, &isFluent);CHKERRQ(ierr); 2752 ierr = PetscStrncmp(&filename[PetscMax(0,len-3)], extHDF5, 3, &isHDF5);CHKERRQ(ierr); 2753 ierr = PetscStrncmp(&filename[PetscMax(0,len-4)], extMed, 4, &isMed);CHKERRQ(ierr); 2754 ierr = PetscStrncmp(&filename[PetscMax(0,len-4)], extPLY, 4, &isPLY);CHKERRQ(ierr); 2755 if (isGmsh) { 2756 ierr = DMPlexCreateGmshFromFile(comm, filename, interpolate, dm);CHKERRQ(ierr); 2757 } else if (isCGNS) { 2758 ierr = DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm);CHKERRQ(ierr); 2759 } else if (isExodus || isGenesis) { 2760 ierr = DMPlexCreateExodusFromFile(comm, filename, interpolate, dm);CHKERRQ(ierr); 2761 } else if (isFluent) { 2762 ierr = DMPlexCreateFluentFromFile(comm, filename, interpolate, dm);CHKERRQ(ierr); 2763 } else if (isHDF5) { 2764 PetscViewer viewer; 2765 2766 ierr = PetscViewerCreate(comm, &viewer);CHKERRQ(ierr); 2767 ierr = PetscViewerSetType(viewer, PETSCVIEWERHDF5);CHKERRQ(ierr); 2768 ierr = PetscViewerFileSetMode(viewer, FILE_MODE_READ);CHKERRQ(ierr); 2769 ierr = PetscViewerFileSetName(viewer, filename);CHKERRQ(ierr); 2770 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 2771 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 2772 ierr = DMLoad(*dm, viewer);CHKERRQ(ierr); 2773 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 2774 } else if (isMed) { 2775 ierr = DMPlexCreateMedFromFile(comm, filename, interpolate, dm);CHKERRQ(ierr); 2776 } else if (isPLY) { 2777 ierr = DMPlexCreatePLYFromFile(comm, filename, interpolate, dm);CHKERRQ(ierr); 2778 } else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename); 2779 PetscFunctionReturn(0); 2780 } 2781 2782 /*@ 2783 DMPlexCreateReferenceCell - Create a DMPLEX with the appropriate FEM reference cell 2784 2785 Collective on comm 2786 2787 Input Parameters: 2788 + comm - The communicator 2789 . dim - The spatial dimension 2790 - simplex - Flag for simplex, otherwise use a tensor-product cell 2791 2792 Output Parameter: 2793 . refdm - The reference cell 2794 2795 Level: intermediate 2796 2797 .keywords: reference cell 2798 .seealso: 2799 @*/ 2800 PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, PetscInt dim, PetscBool simplex, DM *refdm) 2801 { 2802 DM rdm; 2803 Vec coords; 2804 PetscErrorCode ierr; 2805 2806 PetscFunctionBeginUser; 2807 ierr = DMCreate(comm, &rdm);CHKERRQ(ierr); 2808 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 2809 ierr = DMSetDimension(rdm, dim);CHKERRQ(ierr); 2810 switch (dim) { 2811 case 0: 2812 { 2813 PetscInt numPoints[1] = {1}; 2814 PetscInt coneSize[1] = {0}; 2815 PetscInt cones[1] = {0}; 2816 PetscInt coneOrientations[1] = {0}; 2817 PetscScalar vertexCoords[1] = {0.0}; 2818 2819 ierr = DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 2820 } 2821 break; 2822 case 1: 2823 { 2824 PetscInt numPoints[2] = {2, 1}; 2825 PetscInt coneSize[3] = {2, 0, 0}; 2826 PetscInt cones[2] = {1, 2}; 2827 PetscInt coneOrientations[2] = {0, 0}; 2828 PetscScalar vertexCoords[2] = {-1.0, 1.0}; 2829 2830 ierr = DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 2831 } 2832 break; 2833 case 2: 2834 if (simplex) { 2835 PetscInt numPoints[2] = {3, 1}; 2836 PetscInt coneSize[4] = {3, 0, 0, 0}; 2837 PetscInt cones[3] = {1, 2, 3}; 2838 PetscInt coneOrientations[3] = {0, 0, 0}; 2839 PetscScalar vertexCoords[6] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0}; 2840 2841 ierr = DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 2842 } else { 2843 PetscInt numPoints[2] = {4, 1}; 2844 PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 2845 PetscInt cones[4] = {1, 2, 3, 4}; 2846 PetscInt coneOrientations[4] = {0, 0, 0, 0}; 2847 PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0}; 2848 2849 ierr = DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 2850 } 2851 break; 2852 case 3: 2853 if (simplex) { 2854 PetscInt numPoints[2] = {4, 1}; 2855 PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 2856 PetscInt cones[4] = {1, 3, 2, 4}; 2857 PetscInt coneOrientations[4] = {0, 0, 0, 0}; 2858 PetscScalar vertexCoords[12] = {-1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0}; 2859 2860 ierr = DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 2861 } else { 2862 PetscInt numPoints[2] = {8, 1}; 2863 PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 2864 PetscInt cones[8] = {1, 4, 3, 2, 5, 6, 7, 8}; 2865 PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 2866 PetscScalar vertexCoords[24] = {-1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 2867 -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0}; 2868 2869 ierr = DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 2870 } 2871 break; 2872 default: 2873 SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Cannot create reference cell for dimension %d", dim); 2874 } 2875 *refdm = NULL; 2876 ierr = DMPlexInterpolate(rdm, refdm);CHKERRQ(ierr); 2877 if (rdm->coordinateDM) { 2878 DM ncdm; 2879 PetscSection cs; 2880 PetscInt pEnd = -1; 2881 2882 ierr = DMGetDefaultSection(rdm->coordinateDM, &cs);CHKERRQ(ierr); 2883 if (cs) {ierr = PetscSectionGetChart(cs, NULL, &pEnd);CHKERRQ(ierr);} 2884 if (pEnd >= 0) { 2885 ierr = DMClone(rdm->coordinateDM, &ncdm);CHKERRQ(ierr); 2886 ierr = DMSetDefaultSection(ncdm, cs);CHKERRQ(ierr); 2887 ierr = DMSetCoordinateDM(*refdm, ncdm);CHKERRQ(ierr); 2888 ierr = DMDestroy(&ncdm);CHKERRQ(ierr); 2889 } 2890 } 2891 ierr = DMGetCoordinatesLocal(rdm, &coords);CHKERRQ(ierr); 2892 if (coords) { 2893 ierr = DMSetCoordinatesLocal(*refdm, coords);CHKERRQ(ierr); 2894 } else { 2895 ierr = DMGetCoordinates(rdm, &coords);CHKERRQ(ierr); 2896 if (coords) {ierr = DMSetCoordinates(*refdm, coords);CHKERRQ(ierr);} 2897 } 2898 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 2899 PetscFunctionReturn(0); 2900 } 2901