1 #define PETSCDM_DLL 2 #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 3 #include <petsc/private/hashseti.h> /*I "petscdmplex.h" I*/ 4 #include <petscsf.h> 5 6 PetscLogEvent DMPLEX_CreateFromFile, DMPLEX_BuildFromCellList, DMPLEX_BuildCoordinatesFromCellList; 7 8 /*@ 9 DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement. 10 11 Collective 12 13 Input Parameters: 14 + comm - The communicator for the DM object 15 . dim - The spatial dimension 16 . simplex - Flag for simplicial cells, otherwise they are tensor product cells 17 . interpolate - Flag to create intermediate mesh pieces (edges, faces) 18 . refinementUniform - Flag for uniform parallel refinement 19 - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell 20 21 Output Parameter: 22 . dm - The DM object 23 24 Level: beginner 25 26 .seealso: DMSetType(), DMCreate() 27 @*/ 28 PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscBool refinementUniform, PetscReal refinementLimit, DM *newdm) 29 { 30 DM dm; 31 PetscInt p; 32 PetscMPIInt rank; 33 PetscErrorCode ierr; 34 35 PetscFunctionBegin; 36 ierr = DMCreate(comm, &dm);CHKERRQ(ierr); 37 ierr = DMSetType(dm, DMPLEX);CHKERRQ(ierr); 38 ierr = DMSetDimension(dm, dim);CHKERRQ(ierr); 39 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 40 switch (dim) { 41 case 2: 42 if (simplex) {ierr = PetscObjectSetName((PetscObject) dm, "triangular");CHKERRQ(ierr);} 43 else {ierr = PetscObjectSetName((PetscObject) dm, "quadrilateral");CHKERRQ(ierr);} 44 break; 45 case 3: 46 if (simplex) {ierr = PetscObjectSetName((PetscObject) dm, "tetrahedral");CHKERRQ(ierr);} 47 else {ierr = PetscObjectSetName((PetscObject) dm, "hexahedral");CHKERRQ(ierr);} 48 break; 49 default: 50 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %D", dim); 51 } 52 if (rank) { 53 PetscInt numPoints[2] = {0, 0}; 54 ierr = DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 55 } else { 56 switch (dim) { 57 case 2: 58 if (simplex) { 59 PetscInt numPoints[2] = {4, 2}; 60 PetscInt coneSize[6] = {3, 3, 0, 0, 0, 0}; 61 PetscInt cones[6] = {2, 3, 4, 5, 4, 3}; 62 PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 63 PetscScalar vertexCoords[8] = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5}; 64 PetscInt markerPoints[8] = {2, 1, 3, 1, 4, 1, 5, 1}; 65 66 ierr = DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 67 for (p = 0; p < 4; ++p) {ierr = DMSetLabelValue(dm, "marker", markerPoints[p*2], markerPoints[p*2+1]);CHKERRQ(ierr);} 68 } else { 69 PetscInt numPoints[2] = {6, 2}; 70 PetscInt coneSize[8] = {4, 4, 0, 0, 0, 0, 0, 0}; 71 PetscInt cones[8] = {2, 3, 4, 5, 3, 6, 7, 4}; 72 PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 73 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}; 74 75 ierr = DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 76 } 77 break; 78 case 3: 79 if (simplex) { 80 PetscInt numPoints[2] = {5, 2}; 81 PetscInt coneSize[7] = {4, 4, 0, 0, 0, 0, 0}; 82 PetscInt cones[8] = {4, 3, 5, 2, 5, 3, 4, 6}; 83 PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 84 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}; 85 PetscInt markerPoints[10] = {2, 1, 3, 1, 4, 1, 5, 1, 6, 1}; 86 87 ierr = DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 88 for (p = 0; p < 5; ++p) {ierr = DMSetLabelValue(dm, "marker", markerPoints[p*2], markerPoints[p*2+1]);CHKERRQ(ierr);} 89 } else { 90 PetscInt numPoints[2] = {12, 2}; 91 PetscInt coneSize[14] = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 92 PetscInt cones[16] = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8}; 93 PetscInt coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 94 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, 95 -1.0, -0.5, 0.5, 0.0, -0.5, 0.5, 0.0, 0.5, 0.5, -1.0, 0.5, 0.5, 96 1.0, 0.5, -0.5, 1.0, -0.5, -0.5, 1.0, -0.5, 0.5, 1.0, 0.5, 0.5}; 97 98 ierr = DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 99 } 100 break; 101 default: 102 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %D", dim); 103 } 104 } 105 *newdm = dm; 106 if (refinementLimit > 0.0) { 107 DM rdm; 108 const char *name; 109 110 ierr = DMPlexSetRefinementUniform(*newdm, PETSC_FALSE);CHKERRQ(ierr); 111 ierr = DMPlexSetRefinementLimit(*newdm, refinementLimit);CHKERRQ(ierr); 112 ierr = DMRefine(*newdm, comm, &rdm);CHKERRQ(ierr); 113 ierr = PetscObjectGetName((PetscObject) *newdm, &name);CHKERRQ(ierr); 114 ierr = PetscObjectSetName((PetscObject) rdm, name);CHKERRQ(ierr); 115 ierr = DMDestroy(newdm);CHKERRQ(ierr); 116 *newdm = rdm; 117 } 118 if (interpolate) { 119 DM idm; 120 121 ierr = DMPlexInterpolate(*newdm, &idm);CHKERRQ(ierr); 122 ierr = DMDestroy(newdm);CHKERRQ(ierr); 123 *newdm = idm; 124 } 125 { 126 DM refinedMesh = NULL; 127 DM distributedMesh = NULL; 128 129 /* Distribute mesh over processes */ 130 ierr = DMPlexDistribute(*newdm, 0, NULL, &distributedMesh);CHKERRQ(ierr); 131 if (distributedMesh) { 132 ierr = DMDestroy(newdm);CHKERRQ(ierr); 133 *newdm = distributedMesh; 134 } 135 if (refinementUniform) { 136 ierr = DMPlexSetRefinementUniform(*newdm, refinementUniform);CHKERRQ(ierr); 137 ierr = DMRefine(*newdm, comm, &refinedMesh);CHKERRQ(ierr); 138 if (refinedMesh) { 139 ierr = DMDestroy(newdm);CHKERRQ(ierr); 140 *newdm = refinedMesh; 141 } 142 } 143 } 144 PetscFunctionReturn(0); 145 } 146 147 /*@ 148 DMPlexCreateSquareBoundary - Creates a 1D mesh the is the boundary of a square lattice. 149 150 Collective 151 152 Input Parameters: 153 + comm - The communicator for the DM object 154 . lower - The lower left corner coordinates 155 . upper - The upper right corner coordinates 156 - edges - The number of cells in each direction 157 158 Output Parameter: 159 . dm - The DM object 160 161 Note: Here is the numbering returned for 2 cells in each direction: 162 $ 18--5-17--4--16 163 $ | | | 164 $ 6 10 3 165 $ | | | 166 $ 19-11-20--9--15 167 $ | | | 168 $ 7 8 2 169 $ | | | 170 $ 12--0-13--1--14 171 172 Level: beginner 173 174 .seealso: DMPlexCreateBoxMesh(), DMPlexCreateCubeBoundary(), DMSetType(), DMCreate() 175 @*/ 176 PetscErrorCode DMPlexCreateSquareBoundary(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 177 { 178 const PetscInt numVertices = (edges[0]+1)*(edges[1]+1); 179 const PetscInt numEdges = edges[0]*(edges[1]+1) + (edges[0]+1)*edges[1]; 180 PetscInt markerTop = 1; 181 PetscInt markerBottom = 1; 182 PetscInt markerRight = 1; 183 PetscInt markerLeft = 1; 184 PetscBool markerSeparate = PETSC_FALSE; 185 Vec coordinates; 186 PetscSection coordSection; 187 PetscScalar *coords; 188 PetscInt coordSize; 189 PetscMPIInt rank; 190 PetscInt v, vx, vy; 191 PetscErrorCode ierr; 192 193 PetscFunctionBegin; 194 ierr = PetscOptionsGetBool(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL);CHKERRQ(ierr); 195 if (markerSeparate) { 196 markerTop = 3; 197 markerBottom = 1; 198 markerRight = 2; 199 markerLeft = 4; 200 } 201 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 202 if (!rank) { 203 PetscInt e, ex, ey; 204 205 ierr = DMPlexSetChart(dm, 0, numEdges+numVertices);CHKERRQ(ierr); 206 for (e = 0; e < numEdges; ++e) { 207 ierr = DMPlexSetConeSize(dm, e, 2);CHKERRQ(ierr); 208 } 209 ierr = DMSetUp(dm);CHKERRQ(ierr); /* Allocate space for cones */ 210 for (vx = 0; vx <= edges[0]; vx++) { 211 for (ey = 0; ey < edges[1]; ey++) { 212 PetscInt edge = vx*edges[1] + ey + edges[0]*(edges[1]+1); 213 PetscInt vertex = ey*(edges[0]+1) + vx + numEdges; 214 PetscInt cone[2]; 215 216 cone[0] = vertex; cone[1] = vertex+edges[0]+1; 217 ierr = DMPlexSetCone(dm, edge, cone);CHKERRQ(ierr); 218 if (vx == edges[0]) { 219 ierr = DMSetLabelValue(dm, "marker", edge, markerRight);CHKERRQ(ierr); 220 ierr = DMSetLabelValue(dm, "marker", cone[0], markerRight);CHKERRQ(ierr); 221 if (ey == edges[1]-1) { 222 ierr = DMSetLabelValue(dm, "marker", cone[1], markerRight);CHKERRQ(ierr); 223 ierr = DMSetLabelValue(dm, "Face Sets", cone[1], markerRight);CHKERRQ(ierr); 224 } 225 } else if (vx == 0) { 226 ierr = DMSetLabelValue(dm, "marker", edge, markerLeft);CHKERRQ(ierr); 227 ierr = DMSetLabelValue(dm, "marker", cone[0], markerLeft);CHKERRQ(ierr); 228 if (ey == edges[1]-1) { 229 ierr = DMSetLabelValue(dm, "marker", cone[1], markerLeft);CHKERRQ(ierr); 230 ierr = DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft);CHKERRQ(ierr); 231 } 232 } 233 } 234 } 235 for (vy = 0; vy <= edges[1]; vy++) { 236 for (ex = 0; ex < edges[0]; ex++) { 237 PetscInt edge = vy*edges[0] + ex; 238 PetscInt vertex = vy*(edges[0]+1) + ex + numEdges; 239 PetscInt cone[2]; 240 241 cone[0] = vertex; cone[1] = vertex+1; 242 ierr = DMPlexSetCone(dm, edge, cone);CHKERRQ(ierr); 243 if (vy == edges[1]) { 244 ierr = DMSetLabelValue(dm, "marker", edge, markerTop);CHKERRQ(ierr); 245 ierr = DMSetLabelValue(dm, "marker", cone[0], markerTop);CHKERRQ(ierr); 246 if (ex == edges[0]-1) { 247 ierr = DMSetLabelValue(dm, "marker", cone[1], markerTop);CHKERRQ(ierr); 248 ierr = DMSetLabelValue(dm, "Face Sets", cone[1], markerTop);CHKERRQ(ierr); 249 } 250 } else if (vy == 0) { 251 ierr = DMSetLabelValue(dm, "marker", edge, markerBottom);CHKERRQ(ierr); 252 ierr = DMSetLabelValue(dm, "marker", cone[0], markerBottom);CHKERRQ(ierr); 253 if (ex == edges[0]-1) { 254 ierr = DMSetLabelValue(dm, "marker", cone[1], markerBottom);CHKERRQ(ierr); 255 ierr = DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom);CHKERRQ(ierr); 256 } 257 } 258 } 259 } 260 } 261 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 262 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 263 /* Build coordinates */ 264 ierr = DMSetCoordinateDim(dm, 2);CHKERRQ(ierr); 265 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 266 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 267 ierr = PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices);CHKERRQ(ierr); 268 ierr = PetscSectionSetFieldComponents(coordSection, 0, 2);CHKERRQ(ierr); 269 for (v = numEdges; v < numEdges+numVertices; ++v) { 270 ierr = PetscSectionSetDof(coordSection, v, 2);CHKERRQ(ierr); 271 ierr = PetscSectionSetFieldDof(coordSection, v, 0, 2);CHKERRQ(ierr); 272 } 273 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 274 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 275 ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr); 276 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 277 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 278 ierr = VecSetBlockSize(coordinates, 2);CHKERRQ(ierr); 279 ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr); 280 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 281 for (vy = 0; vy <= edges[1]; ++vy) { 282 for (vx = 0; vx <= edges[0]; ++vx) { 283 coords[(vy*(edges[0]+1)+vx)*2+0] = lower[0] + ((upper[0] - lower[0])/edges[0])*vx; 284 coords[(vy*(edges[0]+1)+vx)*2+1] = lower[1] + ((upper[1] - lower[1])/edges[1])*vy; 285 } 286 } 287 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 288 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 289 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 290 PetscFunctionReturn(0); 291 } 292 293 /*@ 294 DMPlexCreateCubeBoundary - Creates a 2D mesh that is the boundary of a cubic lattice. 295 296 Collective 297 298 Input Parameters: 299 + comm - The communicator for the DM object 300 . lower - The lower left front corner coordinates 301 . upper - The upper right back corner coordinates 302 - faces - The number of faces in each direction (the same as the number of cells) 303 304 Output Parameter: 305 . dm - The DM object 306 307 Level: beginner 308 309 .seealso: DMPlexCreateBoxMesh(), DMPlexCreateSquareBoundary(), DMSetType(), DMCreate() 310 @*/ 311 PetscErrorCode DMPlexCreateCubeBoundary(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[]) 312 { 313 PetscInt vertices[3], numVertices; 314 PetscInt numFaces = 2*faces[0]*faces[1] + 2*faces[1]*faces[2] + 2*faces[0]*faces[2]; 315 Vec coordinates; 316 PetscSection coordSection; 317 PetscScalar *coords; 318 PetscInt coordSize; 319 PetscMPIInt rank; 320 PetscInt v, vx, vy, vz; 321 PetscInt voffset, iface=0, cone[4]; 322 PetscErrorCode ierr; 323 324 PetscFunctionBegin; 325 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"); 326 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 327 vertices[0] = faces[0]+1; vertices[1] = faces[1]+1; vertices[2] = faces[2]+1; 328 numVertices = vertices[0]*vertices[1]*vertices[2]; 329 if (!rank) { 330 PetscInt f; 331 332 ierr = DMPlexSetChart(dm, 0, numFaces+numVertices);CHKERRQ(ierr); 333 for (f = 0; f < numFaces; ++f) { 334 ierr = DMPlexSetConeSize(dm, f, 4);CHKERRQ(ierr); 335 } 336 ierr = DMSetUp(dm);CHKERRQ(ierr); /* Allocate space for cones */ 337 338 /* Side 0 (Top) */ 339 for (vy = 0; vy < faces[1]; vy++) { 340 for (vx = 0; vx < faces[0]; vx++) { 341 voffset = numFaces + vertices[0]*vertices[1]*(vertices[2]-1) + vy*vertices[0] + vx; 342 cone[0] = voffset; cone[1] = voffset+1; cone[2] = voffset+vertices[0]+1; cone[3] = voffset+vertices[0]; 343 ierr = DMPlexSetCone(dm, iface, cone);CHKERRQ(ierr); 344 ierr = DMSetLabelValue(dm, "marker", iface, 1);CHKERRQ(ierr); 345 ierr = DMSetLabelValue(dm, "marker", voffset+0, 1);CHKERRQ(ierr); 346 ierr = DMSetLabelValue(dm, "marker", voffset+1, 1);CHKERRQ(ierr); 347 ierr = DMSetLabelValue(dm, "marker", voffset+vertices[0]+0, 1);CHKERRQ(ierr); 348 ierr = DMSetLabelValue(dm, "marker", voffset+vertices[0]+1, 1);CHKERRQ(ierr); 349 iface++; 350 } 351 } 352 353 /* Side 1 (Bottom) */ 354 for (vy = 0; vy < faces[1]; vy++) { 355 for (vx = 0; vx < faces[0]; vx++) { 356 voffset = numFaces + vy*(faces[0]+1) + vx; 357 cone[0] = voffset+1; cone[1] = voffset; cone[2] = voffset+vertices[0]; cone[3] = voffset+vertices[0]+1; 358 ierr = DMPlexSetCone(dm, iface, cone);CHKERRQ(ierr); 359 ierr = DMSetLabelValue(dm, "marker", iface, 1);CHKERRQ(ierr); 360 ierr = DMSetLabelValue(dm, "marker", voffset+0, 1);CHKERRQ(ierr); 361 ierr = DMSetLabelValue(dm, "marker", voffset+1, 1);CHKERRQ(ierr); 362 ierr = DMSetLabelValue(dm, "marker", voffset+vertices[0]+0, 1);CHKERRQ(ierr); 363 ierr = DMSetLabelValue(dm, "marker", voffset+vertices[0]+1, 1);CHKERRQ(ierr); 364 iface++; 365 } 366 } 367 368 /* Side 2 (Front) */ 369 for (vz = 0; vz < faces[2]; vz++) { 370 for (vx = 0; vx < faces[0]; vx++) { 371 voffset = numFaces + vz*vertices[0]*vertices[1] + vx; 372 cone[0] = voffset; cone[1] = voffset+1; cone[2] = voffset+vertices[0]*vertices[1]+1; cone[3] = voffset+vertices[0]*vertices[1]; 373 ierr = DMPlexSetCone(dm, iface, cone);CHKERRQ(ierr); 374 ierr = DMSetLabelValue(dm, "marker", iface, 1);CHKERRQ(ierr); 375 ierr = DMSetLabelValue(dm, "marker", voffset+0, 1);CHKERRQ(ierr); 376 ierr = DMSetLabelValue(dm, "marker", voffset+1, 1);CHKERRQ(ierr); 377 ierr = DMSetLabelValue(dm, "marker", voffset+vertices[0]*vertices[1]+0, 1);CHKERRQ(ierr); 378 ierr = DMSetLabelValue(dm, "marker", voffset+vertices[0]*vertices[1]+1, 1);CHKERRQ(ierr); 379 iface++; 380 } 381 } 382 383 /* Side 3 (Back) */ 384 for (vz = 0; vz < faces[2]; vz++) { 385 for (vx = 0; vx < faces[0]; vx++) { 386 voffset = numFaces + vz*vertices[0]*vertices[1] + vertices[0]*(vertices[1]-1) + vx; 387 cone[0] = voffset+vertices[0]*vertices[1]; cone[1] = voffset+vertices[0]*vertices[1]+1; 388 cone[2] = voffset+1; cone[3] = voffset; 389 ierr = DMPlexSetCone(dm, iface, cone);CHKERRQ(ierr); 390 ierr = DMSetLabelValue(dm, "marker", iface, 1);CHKERRQ(ierr); 391 ierr = DMSetLabelValue(dm, "marker", voffset+0, 1);CHKERRQ(ierr); 392 ierr = DMSetLabelValue(dm, "marker", voffset+1, 1);CHKERRQ(ierr); 393 ierr = DMSetLabelValue(dm, "marker", voffset+vertices[0]*vertices[1]+0, 1);CHKERRQ(ierr); 394 ierr = DMSetLabelValue(dm, "marker", voffset+vertices[0]*vertices[1]+1, 1);CHKERRQ(ierr); 395 iface++; 396 } 397 } 398 399 /* Side 4 (Left) */ 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]; 403 cone[0] = voffset; cone[1] = voffset+vertices[0]*vertices[1]; 404 cone[2] = voffset+vertices[0]*vertices[1]+vertices[0]; cone[3] = voffset+vertices[0]; 405 ierr = DMPlexSetCone(dm, iface, cone);CHKERRQ(ierr); 406 ierr = DMSetLabelValue(dm, "marker", iface, 1);CHKERRQ(ierr); 407 ierr = DMSetLabelValue(dm, "marker", voffset+0, 1);CHKERRQ(ierr); 408 ierr = DMSetLabelValue(dm, "marker", voffset+vertices[0]+0, 1);CHKERRQ(ierr); 409 ierr = DMSetLabelValue(dm, "marker", voffset+vertices[1]+0, 1);CHKERRQ(ierr); 410 ierr = DMSetLabelValue(dm, "marker", voffset+vertices[0]*vertices[1]+vertices[0], 1);CHKERRQ(ierr); 411 iface++; 412 } 413 } 414 415 /* Side 5 (Right) */ 416 for (vz = 0; vz < faces[2]; vz++) { 417 for (vy = 0; vy < faces[1]; vy++) { 418 voffset = numFaces + vz*vertices[0]*vertices[1] + vy*vertices[0] + faces[0]; 419 cone[0] = voffset+vertices[0]*vertices[1]; cone[1] = voffset; 420 cone[2] = voffset+vertices[0]; cone[3] = voffset+vertices[0]*vertices[1]+vertices[0]; 421 ierr = DMPlexSetCone(dm, iface, cone);CHKERRQ(ierr); 422 ierr = DMSetLabelValue(dm, "marker", iface, 1);CHKERRQ(ierr); 423 ierr = DMSetLabelValue(dm, "marker", voffset+0, 1);CHKERRQ(ierr); 424 ierr = DMSetLabelValue(dm, "marker", voffset+vertices[0]+0, 1);CHKERRQ(ierr); 425 ierr = DMSetLabelValue(dm, "marker", voffset+vertices[0]*vertices[1]+0, 1);CHKERRQ(ierr); 426 ierr = DMSetLabelValue(dm, "marker", voffset+vertices[0]*vertices[1]+vertices[0], 1);CHKERRQ(ierr); 427 iface++; 428 } 429 } 430 } 431 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 432 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 433 /* Build coordinates */ 434 ierr = DMSetCoordinateDim(dm, 3);CHKERRQ(ierr); 435 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 436 ierr = PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices);CHKERRQ(ierr); 437 for (v = numFaces; v < numFaces+numVertices; ++v) { 438 ierr = PetscSectionSetDof(coordSection, v, 3);CHKERRQ(ierr); 439 } 440 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 441 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 442 ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr); 443 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 444 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 445 ierr = VecSetBlockSize(coordinates, 3);CHKERRQ(ierr); 446 ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr); 447 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 448 for (vz = 0; vz <= faces[2]; ++vz) { 449 for (vy = 0; vy <= faces[1]; ++vy) { 450 for (vx = 0; vx <= faces[0]; ++vx) { 451 coords[((vz*(faces[1]+1)+vy)*(faces[0]+1)+vx)*3+0] = lower[0] + ((upper[0] - lower[0])/faces[0])*vx; 452 coords[((vz*(faces[1]+1)+vy)*(faces[0]+1)+vx)*3+1] = lower[1] + ((upper[1] - lower[1])/faces[1])*vy; 453 coords[((vz*(faces[1]+1)+vy)*(faces[0]+1)+vx)*3+2] = lower[2] + ((upper[2] - lower[2])/faces[2])*vz; 454 } 455 } 456 } 457 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 458 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 459 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 460 PetscFunctionReturn(0); 461 } 462 463 static PetscErrorCode DMPlexCreateLineMesh_Internal(MPI_Comm comm,PetscInt segments,PetscReal lower,PetscReal upper,DMBoundaryType bd,DM *dm) 464 { 465 PetscInt i,fStart,fEnd,numCells = 0,numVerts = 0; 466 PetscInt numPoints[2],*coneSize,*cones,*coneOrientations; 467 PetscScalar *vertexCoords; 468 PetscReal L,maxCell; 469 PetscBool markerSeparate = PETSC_FALSE; 470 PetscInt markerLeft = 1, faceMarkerLeft = 1; 471 PetscInt markerRight = 1, faceMarkerRight = 2; 472 PetscBool wrap = (bd == DM_BOUNDARY_PERIODIC || bd == DM_BOUNDARY_TWIST) ? PETSC_TRUE : PETSC_FALSE; 473 PetscMPIInt rank; 474 PetscErrorCode ierr; 475 476 PetscFunctionBegin; 477 PetscValidPointer(dm,4); 478 479 ierr = DMCreate(comm,dm);CHKERRQ(ierr); 480 ierr = DMSetType(*dm,DMPLEX);CHKERRQ(ierr); 481 ierr = DMSetDimension(*dm,1);CHKERRQ(ierr); 482 ierr = DMCreateLabel(*dm,"marker");CHKERRQ(ierr); 483 ierr = DMCreateLabel(*dm,"Face Sets");CHKERRQ(ierr); 484 485 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 486 if (!rank) numCells = segments; 487 if (!rank) numVerts = segments + (wrap ? 0 : 1); 488 489 numPoints[0] = numVerts ; numPoints[1] = numCells; 490 ierr = PetscMalloc4(numCells+numVerts,&coneSize,numCells*2,&cones,numCells+numVerts,&coneOrientations,numVerts,&vertexCoords);CHKERRQ(ierr); 491 ierr = PetscArrayzero(coneOrientations,numCells+numVerts);CHKERRQ(ierr); 492 for (i = 0; i < numCells; ++i) { coneSize[i] = 2; } 493 for (i = 0; i < numVerts; ++i) { coneSize[numCells+i] = 0; } 494 for (i = 0; i < numCells; ++i) { cones[2*i] = numCells + i%numVerts; cones[2*i+1] = numCells + (i+1)%numVerts; } 495 for (i = 0; i < numVerts; ++i) { vertexCoords[i] = lower + (upper-lower)*((PetscReal)i/(PetscReal)numCells); } 496 ierr = DMPlexCreateFromDAG(*dm,1,numPoints,coneSize,cones,coneOrientations,vertexCoords);CHKERRQ(ierr); 497 ierr = PetscFree4(coneSize,cones,coneOrientations,vertexCoords);CHKERRQ(ierr); 498 499 ierr = PetscOptionsGetBool(((PetscObject)*dm)->options,((PetscObject)*dm)->prefix,"-dm_plex_separate_marker",&markerSeparate,NULL);CHKERRQ(ierr); 500 if (markerSeparate) { markerLeft = faceMarkerLeft; markerRight = faceMarkerRight;} 501 if (!wrap && !rank) { 502 ierr = DMPlexGetHeightStratum(*dm,1,&fStart,&fEnd);CHKERRQ(ierr); 503 ierr = DMSetLabelValue(*dm,"marker",fStart,markerLeft);CHKERRQ(ierr); 504 ierr = DMSetLabelValue(*dm,"marker",fEnd-1,markerRight);CHKERRQ(ierr); 505 ierr = DMSetLabelValue(*dm,"Face Sets",fStart,faceMarkerLeft);CHKERRQ(ierr); 506 ierr = DMSetLabelValue(*dm,"Face Sets",fEnd-1,faceMarkerRight);CHKERRQ(ierr); 507 } 508 if (wrap) { 509 L = upper - lower; 510 maxCell = (PetscReal)1.1*(L/(PetscReal)PetscMax(1,segments)); 511 ierr = DMSetPeriodicity(*dm,PETSC_TRUE,&maxCell,&L,&bd);CHKERRQ(ierr); 512 } 513 PetscFunctionReturn(0); 514 } 515 516 static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate, DM *dm) 517 { 518 DM boundary; 519 PetscInt i; 520 PetscErrorCode ierr; 521 522 PetscFunctionBegin; 523 PetscValidPointer(dm, 4); 524 for (i = 0; i < dim; ++i) if (periodicity[i] != DM_BOUNDARY_NONE) SETERRQ(comm, PETSC_ERR_SUP, "Periodicity is not supported for simplex meshes"); 525 ierr = DMCreate(comm, &boundary);CHKERRQ(ierr); 526 PetscValidLogicalCollectiveInt(boundary,dim,2); 527 ierr = DMSetType(boundary, DMPLEX);CHKERRQ(ierr); 528 ierr = DMSetDimension(boundary, dim-1);CHKERRQ(ierr); 529 ierr = DMSetCoordinateDim(boundary, dim);CHKERRQ(ierr); 530 switch (dim) { 531 case 2: ierr = DMPlexCreateSquareBoundary(boundary, lower, upper, faces);CHKERRQ(ierr);break; 532 case 3: ierr = DMPlexCreateCubeBoundary(boundary, lower, upper, faces);CHKERRQ(ierr);break; 533 default: SETERRQ1(comm, PETSC_ERR_SUP, "Dimension not supported: %D", dim); 534 } 535 ierr = DMPlexGenerate(boundary, NULL, interpolate, dm);CHKERRQ(ierr); 536 ierr = DMDestroy(&boundary);CHKERRQ(ierr); 537 PetscFunctionReturn(0); 538 } 539 540 static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ) 541 { 542 DMLabel cutLabel = NULL; 543 PetscInt markerTop = 1, faceMarkerTop = 1; 544 PetscInt markerBottom = 1, faceMarkerBottom = 1; 545 PetscInt markerFront = 1, faceMarkerFront = 1; 546 PetscInt markerBack = 1, faceMarkerBack = 1; 547 PetscInt markerRight = 1, faceMarkerRight = 1; 548 PetscInt markerLeft = 1, faceMarkerLeft = 1; 549 PetscInt dim; 550 PetscBool markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE; 551 PetscMPIInt rank; 552 PetscErrorCode ierr; 553 554 PetscFunctionBegin; 555 ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr); 556 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 557 ierr = DMCreateLabel(dm,"marker");CHKERRQ(ierr); 558 ierr = DMCreateLabel(dm,"Face Sets");CHKERRQ(ierr); 559 ierr = PetscOptionsGetBool(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL);CHKERRQ(ierr); 560 if (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST || 561 bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST || 562 bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST) { 563 564 if (cutMarker) {ierr = DMCreateLabel(dm, "periodic_cut");CHKERRQ(ierr); ierr = DMGetLabel(dm, "periodic_cut", &cutLabel);CHKERRQ(ierr);} 565 } 566 switch (dim) { 567 case 2: 568 faceMarkerTop = 3; 569 faceMarkerBottom = 1; 570 faceMarkerRight = 2; 571 faceMarkerLeft = 4; 572 break; 573 case 3: 574 faceMarkerBottom = 1; 575 faceMarkerTop = 2; 576 faceMarkerFront = 3; 577 faceMarkerBack = 4; 578 faceMarkerRight = 5; 579 faceMarkerLeft = 6; 580 break; 581 default: 582 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Dimension %D not supported",dim); 583 break; 584 } 585 ierr = PetscOptionsGetBool(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL);CHKERRQ(ierr); 586 if (markerSeparate) { 587 markerBottom = faceMarkerBottom; 588 markerTop = faceMarkerTop; 589 markerFront = faceMarkerFront; 590 markerBack = faceMarkerBack; 591 markerRight = faceMarkerRight; 592 markerLeft = faceMarkerLeft; 593 } 594 { 595 const PetscInt numXEdges = !rank ? edges[0] : 0; 596 const PetscInt numYEdges = !rank ? edges[1] : 0; 597 const PetscInt numZEdges = !rank ? edges[2] : 0; 598 const PetscInt numXVertices = !rank ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0]+1) : 0; 599 const PetscInt numYVertices = !rank ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1]+1) : 0; 600 const PetscInt numZVertices = !rank ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2]+1) : 0; 601 const PetscInt numCells = numXEdges*numYEdges*numZEdges; 602 const PetscInt numXFaces = numYEdges*numZEdges; 603 const PetscInt numYFaces = numXEdges*numZEdges; 604 const PetscInt numZFaces = numXEdges*numYEdges; 605 const PetscInt numTotXFaces = numXVertices*numXFaces; 606 const PetscInt numTotYFaces = numYVertices*numYFaces; 607 const PetscInt numTotZFaces = numZVertices*numZFaces; 608 const PetscInt numFaces = numTotXFaces + numTotYFaces + numTotZFaces; 609 const PetscInt numTotXEdges = numXEdges*numYVertices*numZVertices; 610 const PetscInt numTotYEdges = numYEdges*numXVertices*numZVertices; 611 const PetscInt numTotZEdges = numZEdges*numXVertices*numYVertices; 612 const PetscInt numVertices = numXVertices*numYVertices*numZVertices; 613 const PetscInt numEdges = numTotXEdges + numTotYEdges + numTotZEdges; 614 const PetscInt firstVertex = (dim == 2) ? numFaces : numCells; 615 const PetscInt firstXFace = (dim == 2) ? 0 : numCells + numVertices; 616 const PetscInt firstYFace = firstXFace + numTotXFaces; 617 const PetscInt firstZFace = firstYFace + numTotYFaces; 618 const PetscInt firstXEdge = numCells + numFaces + numVertices; 619 const PetscInt firstYEdge = firstXEdge + numTotXEdges; 620 const PetscInt firstZEdge = firstYEdge + numTotYEdges; 621 Vec coordinates; 622 PetscSection coordSection; 623 PetscScalar *coords; 624 PetscInt coordSize; 625 PetscInt v, vx, vy, vz; 626 PetscInt c, f, fx, fy, fz, e, ex, ey, ez; 627 628 ierr = DMPlexSetChart(dm, 0, numCells+numFaces+numEdges+numVertices);CHKERRQ(ierr); 629 for (c = 0; c < numCells; c++) { 630 ierr = DMPlexSetConeSize(dm, c, 6);CHKERRQ(ierr); 631 } 632 for (f = firstXFace; f < firstXFace+numFaces; ++f) { 633 ierr = DMPlexSetConeSize(dm, f, 4);CHKERRQ(ierr); 634 } 635 for (e = firstXEdge; e < firstXEdge+numEdges; ++e) { 636 ierr = DMPlexSetConeSize(dm, e, 2);CHKERRQ(ierr); 637 } 638 ierr = DMSetUp(dm);CHKERRQ(ierr); /* Allocate space for cones */ 639 /* Build cells */ 640 for (fz = 0; fz < numZEdges; ++fz) { 641 for (fy = 0; fy < numYEdges; ++fy) { 642 for (fx = 0; fx < numXEdges; ++fx) { 643 PetscInt cell = (fz*numYEdges + fy)*numXEdges + fx; 644 PetscInt faceB = firstZFace + (fy*numXEdges+fx)*numZVertices + fz; 645 PetscInt faceT = firstZFace + (fy*numXEdges+fx)*numZVertices + ((fz+1)%numZVertices); 646 PetscInt faceF = firstYFace + (fz*numXEdges+fx)*numYVertices + fy; 647 PetscInt faceK = firstYFace + (fz*numXEdges+fx)*numYVertices + ((fy+1)%numYVertices); 648 PetscInt faceL = firstXFace + (fz*numYEdges+fy)*numXVertices + fx; 649 PetscInt faceR = firstXFace + (fz*numYEdges+fy)*numXVertices + ((fx+1)%numXVertices); 650 /* B, T, F, K, R, L */ 651 PetscInt ornt[6] = {-4, 0, 0, -1, 0, -4}; /* ??? */ 652 PetscInt cone[6]; 653 654 /* no boundary twisting in 3D */ 655 cone[0] = faceB; cone[1] = faceT; cone[2] = faceF; cone[3] = faceK; cone[4] = faceR; cone[5] = faceL; 656 ierr = DMPlexSetCone(dm, cell, cone);CHKERRQ(ierr); 657 ierr = DMPlexSetConeOrientation(dm, cell, ornt);CHKERRQ(ierr); 658 if (bdX != DM_BOUNDARY_NONE && fx == numXEdges-1 && cutLabel) {ierr = DMLabelSetValue(cutLabel, cell, 2);CHKERRQ(ierr);} 659 if (bdY != DM_BOUNDARY_NONE && fy == numYEdges-1 && cutLabel) {ierr = DMLabelSetValue(cutLabel, cell, 2);CHKERRQ(ierr);} 660 if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges-1 && cutLabel) {ierr = DMLabelSetValue(cutLabel, cell, 2);CHKERRQ(ierr);} 661 } 662 } 663 } 664 /* Build x faces */ 665 for (fz = 0; fz < numZEdges; ++fz) { 666 for (fy = 0; fy < numYEdges; ++fy) { 667 for (fx = 0; fx < numXVertices; ++fx) { 668 PetscInt face = firstXFace + (fz*numYEdges+fy) *numXVertices+fx; 669 PetscInt edgeL = firstZEdge + (fy *numXVertices+fx)*numZEdges + fz; 670 PetscInt edgeR = firstZEdge + (((fy+1)%numYVertices)*numXVertices+fx)*numZEdges + fz; 671 PetscInt edgeB = firstYEdge + (fz *numXVertices+fx)*numYEdges + fy; 672 PetscInt edgeT = firstYEdge + (((fz+1)%numZVertices)*numXVertices+fx)*numYEdges + fy; 673 PetscInt ornt[4] = {0, 0, -2, -2}; 674 PetscInt cone[4]; 675 676 if (dim == 3) { 677 /* markers */ 678 if (bdX != DM_BOUNDARY_PERIODIC) { 679 if (fx == numXVertices-1) { 680 ierr = DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight);CHKERRQ(ierr); 681 ierr = DMSetLabelValue(dm, "marker", face, markerRight);CHKERRQ(ierr); 682 } 683 else if (fx == 0) { 684 ierr = DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft);CHKERRQ(ierr); 685 ierr = DMSetLabelValue(dm, "marker", face, markerLeft);CHKERRQ(ierr); 686 } 687 } 688 } 689 cone[0] = edgeB; cone[1] = edgeR; cone[2] = edgeT; cone[3] = edgeL; 690 ierr = DMPlexSetCone(dm, face, cone);CHKERRQ(ierr); 691 ierr = DMPlexSetConeOrientation(dm, face, ornt);CHKERRQ(ierr); 692 } 693 } 694 } 695 /* Build y faces */ 696 for (fz = 0; fz < numZEdges; ++fz) { 697 for (fx = 0; fx < numXEdges; ++fx) { 698 for (fy = 0; fy < numYVertices; ++fy) { 699 PetscInt face = firstYFace + (fz*numXEdges+fx)*numYVertices + fy; 700 PetscInt edgeL = firstZEdge + (fy*numXVertices+ fx)*numZEdges + fz; 701 PetscInt edgeR = firstZEdge + (fy*numXVertices+((fx+1)%numXVertices))*numZEdges + fz; 702 PetscInt edgeB = firstXEdge + (fz *numYVertices+fy)*numXEdges + fx; 703 PetscInt edgeT = firstXEdge + (((fz+1)%numZVertices)*numYVertices+fy)*numXEdges + fx; 704 PetscInt ornt[4] = {0, 0, -2, -2}; 705 PetscInt cone[4]; 706 707 if (dim == 3) { 708 /* markers */ 709 if (bdY != DM_BOUNDARY_PERIODIC) { 710 if (fy == numYVertices-1) { 711 ierr = DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack);CHKERRQ(ierr); 712 ierr = DMSetLabelValue(dm, "marker", face, markerBack);CHKERRQ(ierr); 713 } 714 else if (fy == 0) { 715 ierr = DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront);CHKERRQ(ierr); 716 ierr = DMSetLabelValue(dm, "marker", face, markerFront);CHKERRQ(ierr); 717 } 718 } 719 } 720 cone[0] = edgeB; cone[1] = edgeR; cone[2] = edgeT; cone[3] = edgeL; 721 ierr = DMPlexSetCone(dm, face, cone);CHKERRQ(ierr); 722 ierr = DMPlexSetConeOrientation(dm, face, ornt);CHKERRQ(ierr); 723 } 724 } 725 } 726 /* Build z faces */ 727 for (fy = 0; fy < numYEdges; ++fy) { 728 for (fx = 0; fx < numXEdges; ++fx) { 729 for (fz = 0; fz < numZVertices; fz++) { 730 PetscInt face = firstZFace + (fy*numXEdges+fx)*numZVertices + fz; 731 PetscInt edgeL = firstYEdge + (fz*numXVertices+ fx)*numYEdges + fy; 732 PetscInt edgeR = firstYEdge + (fz*numXVertices+((fx+1)%numXVertices))*numYEdges + fy; 733 PetscInt edgeB = firstXEdge + (fz*numYVertices+ fy)*numXEdges + fx; 734 PetscInt edgeT = firstXEdge + (fz*numYVertices+((fy+1)%numYVertices))*numXEdges + fx; 735 PetscInt ornt[4] = {0, 0, -2, -2}; 736 PetscInt cone[4]; 737 738 if (dim == 2) { 739 if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges-1) {edgeR += numYEdges-1-2*fy; ornt[1] = -2;} 740 if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges-1) {edgeT += numXEdges-1-2*fx; ornt[2] = 0;} 741 if (bdX != DM_BOUNDARY_NONE && fx == numXEdges-1 && cutLabel) {ierr = DMLabelSetValue(cutLabel, face, 2);CHKERRQ(ierr);} 742 if (bdY != DM_BOUNDARY_NONE && fy == numYEdges-1 && cutLabel) {ierr = DMLabelSetValue(cutLabel, face, 2);CHKERRQ(ierr);} 743 } else { 744 /* markers */ 745 if (bdZ != DM_BOUNDARY_PERIODIC) { 746 if (fz == numZVertices-1) { 747 ierr = DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop);CHKERRQ(ierr); 748 ierr = DMSetLabelValue(dm, "marker", face, markerTop);CHKERRQ(ierr); 749 } 750 else if (fz == 0) { 751 ierr = DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom);CHKERRQ(ierr); 752 ierr = DMSetLabelValue(dm, "marker", face, markerBottom);CHKERRQ(ierr); 753 } 754 } 755 } 756 cone[0] = edgeB; cone[1] = edgeR; cone[2] = edgeT; cone[3] = edgeL; 757 ierr = DMPlexSetCone(dm, face, cone);CHKERRQ(ierr); 758 ierr = DMPlexSetConeOrientation(dm, face, ornt);CHKERRQ(ierr); 759 } 760 } 761 } 762 /* Build Z edges*/ 763 for (vy = 0; vy < numYVertices; vy++) { 764 for (vx = 0; vx < numXVertices; vx++) { 765 for (ez = 0; ez < numZEdges; ez++) { 766 const PetscInt edge = firstZEdge + (vy*numXVertices+vx)*numZEdges + ez; 767 const PetscInt vertexB = firstVertex + (ez *numYVertices+vy)*numXVertices + vx; 768 const PetscInt vertexT = firstVertex + (((ez+1)%numZVertices)*numYVertices+vy)*numXVertices + vx; 769 PetscInt cone[2]; 770 771 if (dim == 3) { 772 if (bdX != DM_BOUNDARY_PERIODIC) { 773 if (vx == numXVertices-1) { 774 ierr = DMSetLabelValue(dm, "marker", edge, markerRight);CHKERRQ(ierr); 775 } 776 else if (vx == 0) { 777 ierr = DMSetLabelValue(dm, "marker", edge, markerLeft);CHKERRQ(ierr); 778 } 779 } 780 if (bdY != DM_BOUNDARY_PERIODIC) { 781 if (vy == numYVertices-1) { 782 ierr = DMSetLabelValue(dm, "marker", edge, markerBack);CHKERRQ(ierr); 783 } 784 else if (vy == 0) { 785 ierr = DMSetLabelValue(dm, "marker", edge, markerFront);CHKERRQ(ierr); 786 } 787 } 788 } 789 cone[0] = vertexB; cone[1] = vertexT; 790 ierr = DMPlexSetCone(dm, edge, cone);CHKERRQ(ierr); 791 } 792 } 793 } 794 /* Build Y edges*/ 795 for (vz = 0; vz < numZVertices; vz++) { 796 for (vx = 0; vx < numXVertices; vx++) { 797 for (ey = 0; ey < numYEdges; ey++) { 798 const PetscInt nextv = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges-1) ? (numXVertices-vx-1) : (vz*numYVertices+((ey+1)%numYVertices))*numXVertices + vx; 799 const PetscInt edge = firstYEdge + (vz*numXVertices+vx)*numYEdges + ey; 800 const PetscInt vertexF = firstVertex + (vz*numYVertices+ey)*numXVertices + vx; 801 const PetscInt vertexK = firstVertex + nextv; 802 PetscInt cone[2]; 803 804 cone[0] = vertexF; cone[1] = vertexK; 805 ierr = DMPlexSetCone(dm, edge, cone);CHKERRQ(ierr); 806 if (dim == 2) { 807 if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) { 808 if (vx == numXVertices-1) { 809 ierr = DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight);CHKERRQ(ierr); 810 ierr = DMSetLabelValue(dm, "marker", edge, markerRight);CHKERRQ(ierr); 811 ierr = DMSetLabelValue(dm, "marker", cone[0], markerRight);CHKERRQ(ierr); 812 if (ey == numYEdges-1) { 813 ierr = DMSetLabelValue(dm, "marker", cone[1], markerRight);CHKERRQ(ierr); 814 } 815 } else if (vx == 0) { 816 ierr = DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft);CHKERRQ(ierr); 817 ierr = DMSetLabelValue(dm, "marker", edge, markerLeft);CHKERRQ(ierr); 818 ierr = DMSetLabelValue(dm, "marker", cone[0], markerLeft);CHKERRQ(ierr); 819 if (ey == numYEdges-1) { 820 ierr = DMSetLabelValue(dm, "marker", cone[1], markerLeft);CHKERRQ(ierr); 821 } 822 } 823 } else { 824 if (vx == 0 && cutLabel) { 825 ierr = DMLabelSetValue(cutLabel, edge, 1);CHKERRQ(ierr); 826 ierr = DMLabelSetValue(cutLabel, cone[0], 1);CHKERRQ(ierr); 827 if (ey == numYEdges-1) { 828 ierr = DMLabelSetValue(cutLabel, cone[1], 1);CHKERRQ(ierr); 829 } 830 } 831 } 832 } else { 833 if (bdX != DM_BOUNDARY_PERIODIC) { 834 if (vx == numXVertices-1) { 835 ierr = DMSetLabelValue(dm, "marker", edge, markerRight);CHKERRQ(ierr); 836 } else if (vx == 0) { 837 ierr = DMSetLabelValue(dm, "marker", edge, markerLeft);CHKERRQ(ierr); 838 } 839 } 840 if (bdZ != DM_BOUNDARY_PERIODIC) { 841 if (vz == numZVertices-1) { 842 ierr = DMSetLabelValue(dm, "marker", edge, markerTop);CHKERRQ(ierr); 843 } else if (vz == 0) { 844 ierr = DMSetLabelValue(dm, "marker", edge, markerBottom);CHKERRQ(ierr); 845 } 846 } 847 } 848 } 849 } 850 } 851 /* Build X edges*/ 852 for (vz = 0; vz < numZVertices; vz++) { 853 for (vy = 0; vy < numYVertices; vy++) { 854 for (ex = 0; ex < numXEdges; ex++) { 855 const PetscInt nextv = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges-1) ? (numYVertices-vy-1)*numXVertices : (vz*numYVertices+vy)*numXVertices + (ex+1)%numXVertices; 856 const PetscInt edge = firstXEdge + (vz*numYVertices+vy)*numXEdges + ex; 857 const PetscInt vertexL = firstVertex + (vz*numYVertices+vy)*numXVertices + ex; 858 const PetscInt vertexR = firstVertex + nextv; 859 PetscInt cone[2]; 860 861 cone[0] = vertexL; cone[1] = vertexR; 862 ierr = DMPlexSetCone(dm, edge, cone);CHKERRQ(ierr); 863 if (dim == 2) { 864 if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) { 865 if (vy == numYVertices-1) { 866 ierr = DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop);CHKERRQ(ierr); 867 ierr = DMSetLabelValue(dm, "marker", edge, markerTop);CHKERRQ(ierr); 868 ierr = DMSetLabelValue(dm, "marker", cone[0], markerTop);CHKERRQ(ierr); 869 if (ex == numXEdges-1) { 870 ierr = DMSetLabelValue(dm, "marker", cone[1], markerTop);CHKERRQ(ierr); 871 } 872 } else if (vy == 0) { 873 ierr = DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom);CHKERRQ(ierr); 874 ierr = DMSetLabelValue(dm, "marker", edge, markerBottom);CHKERRQ(ierr); 875 ierr = DMSetLabelValue(dm, "marker", cone[0], markerBottom);CHKERRQ(ierr); 876 if (ex == numXEdges-1) { 877 ierr = DMSetLabelValue(dm, "marker", cone[1], markerBottom);CHKERRQ(ierr); 878 } 879 } 880 } else { 881 if (vy == 0 && cutLabel) { 882 ierr = DMLabelSetValue(cutLabel, edge, 1);CHKERRQ(ierr); 883 ierr = DMLabelSetValue(cutLabel, cone[0], 1);CHKERRQ(ierr); 884 if (ex == numXEdges-1) { 885 ierr = DMLabelSetValue(cutLabel, cone[1], 1);CHKERRQ(ierr); 886 } 887 } 888 } 889 } else { 890 if (bdY != DM_BOUNDARY_PERIODIC) { 891 if (vy == numYVertices-1) { 892 ierr = DMSetLabelValue(dm, "marker", edge, markerBack);CHKERRQ(ierr); 893 } 894 else if (vy == 0) { 895 ierr = DMSetLabelValue(dm, "marker", edge, markerFront);CHKERRQ(ierr); 896 } 897 } 898 if (bdZ != DM_BOUNDARY_PERIODIC) { 899 if (vz == numZVertices-1) { 900 ierr = DMSetLabelValue(dm, "marker", edge, markerTop);CHKERRQ(ierr); 901 } 902 else if (vz == 0) { 903 ierr = DMSetLabelValue(dm, "marker", edge, markerBottom);CHKERRQ(ierr); 904 } 905 } 906 } 907 } 908 } 909 } 910 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 911 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 912 /* Build coordinates */ 913 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 914 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 915 ierr = PetscSectionSetFieldComponents(coordSection, 0, dim);CHKERRQ(ierr); 916 ierr = PetscSectionSetChart(coordSection, firstVertex, firstVertex+numVertices);CHKERRQ(ierr); 917 for (v = firstVertex; v < firstVertex+numVertices; ++v) { 918 ierr = PetscSectionSetDof(coordSection, v, dim);CHKERRQ(ierr); 919 ierr = PetscSectionSetFieldDof(coordSection, v, 0, dim);CHKERRQ(ierr); 920 } 921 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 922 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 923 ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr); 924 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 925 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 926 ierr = VecSetBlockSize(coordinates, dim);CHKERRQ(ierr); 927 ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr); 928 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 929 for (vz = 0; vz < numZVertices; ++vz) { 930 for (vy = 0; vy < numYVertices; ++vy) { 931 for (vx = 0; vx < numXVertices; ++vx) { 932 coords[((vz*numYVertices+vy)*numXVertices+vx)*dim+0] = lower[0] + ((upper[0] - lower[0])/numXEdges)*vx; 933 coords[((vz*numYVertices+vy)*numXVertices+vx)*dim+1] = lower[1] + ((upper[1] - lower[1])/numYEdges)*vy; 934 if (dim == 3) { 935 coords[((vz*numYVertices+vy)*numXVertices+vx)*dim+2] = lower[2] + ((upper[2] - lower[2])/numZEdges)*vz; 936 } 937 } 938 } 939 } 940 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 941 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 942 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 943 } 944 PetscFunctionReturn(0); 945 } 946 947 static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate, DM *dm) 948 { 949 PetscInt i; 950 PetscErrorCode ierr; 951 952 PetscFunctionBegin; 953 PetscValidPointer(dm, 7); 954 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 955 PetscValidLogicalCollectiveInt(*dm,dim,2); 956 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 957 ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); 958 switch (dim) { 959 case 2: {ierr = DMPlexCreateCubeMesh_Internal(*dm, lower, upper, faces, periodicity[0], periodicity[1], DM_BOUNDARY_NONE);CHKERRQ(ierr);break;} 960 case 3: {ierr = DMPlexCreateCubeMesh_Internal(*dm, lower, upper, faces, periodicity[0], periodicity[1], periodicity[2]);CHKERRQ(ierr);break;} 961 default: SETERRQ1(comm, PETSC_ERR_SUP, "Dimension not supported: %D", dim); 962 } 963 if (periodicity[0] == DM_BOUNDARY_PERIODIC || periodicity[0] == DM_BOUNDARY_TWIST || 964 periodicity[1] == DM_BOUNDARY_PERIODIC || periodicity[1] == DM_BOUNDARY_TWIST || 965 (dim > 2 && (periodicity[2] == DM_BOUNDARY_PERIODIC || periodicity[2] == DM_BOUNDARY_TWIST))) { 966 PetscReal L[3]; 967 PetscReal maxCell[3]; 968 969 for (i = 0; i < dim; i++) { 970 L[i] = upper[i] - lower[i]; 971 maxCell[i] = 1.1 * (L[i] / PetscMax(1,faces[i])); 972 } 973 ierr = DMSetPeriodicity(*dm,PETSC_TRUE,maxCell,L,periodicity);CHKERRQ(ierr); 974 } 975 if (!interpolate) { 976 DM udm; 977 978 ierr = DMPlexUninterpolate(*dm, &udm);CHKERRQ(ierr); 979 ierr = DMPlexCopyCoordinates(*dm, udm);CHKERRQ(ierr); 980 ierr = DMDestroy(dm);CHKERRQ(ierr); 981 *dm = udm; 982 } 983 PetscFunctionReturn(0); 984 } 985 986 /*@C 987 DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra). 988 989 Collective 990 991 Input Parameters: 992 + comm - The communicator for the DM object 993 . dim - The spatial dimension 994 . simplex - PETSC_TRUE for simplices, PETSC_FALSE for tensor cells 995 . faces - Number of faces per dimension, or NULL for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 996 . lower - The lower left corner, or NULL for (0, 0, 0) 997 . upper - The upper right corner, or NULL for (1, 1, 1) 998 . periodicity - The boundary type for the X,Y,Z direction, or NULL for DM_BOUNDARY_NONE 999 - interpolate - Flag to create intermediate mesh pieces (edges, faces) 1000 1001 Output Parameter: 1002 . dm - The DM object 1003 1004 Options Database Keys: 1005 These options override the hard-wired input values. 1006 + -dm_plex_box_dim <dim> - Set the topological dimension 1007 . -dm_plex_box_simplex <bool> - PETSC_TRUE for simplex elements, PETSC_FALSE for tensor elements 1008 . -dm_plex_box_lower <x,y,z> - Specify lower-left-bottom coordinates for the box 1009 . -dm_plex_box_upper <x,y,z> - Specify upper-right-top coordinates for the box 1010 . -dm_plex_box_faces <m,n,p> - Number of faces in each linear direction 1011 - -dm_plex_box_bd <bx,by,bz> - Specify the DMBoundaryType for each direction 1012 1013 Notes: 1014 The options database keys above take lists of length d in d dimensions. 1015 1016 Here is the numbering returned for 2 faces in each direction for tensor cells: 1017 $ 10---17---11---18----12 1018 $ | | | 1019 $ | | | 1020 $ 20 2 22 3 24 1021 $ | | | 1022 $ | | | 1023 $ 7---15----8---16----9 1024 $ | | | 1025 $ | | | 1026 $ 19 0 21 1 23 1027 $ | | | 1028 $ | | | 1029 $ 4---13----5---14----6 1030 1031 and for simplicial cells 1032 1033 $ 14----8---15----9----16 1034 $ |\ 5 |\ 7 | 1035 $ | \ | \ | 1036 $ 13 2 14 3 15 1037 $ | 4 \ | 6 \ | 1038 $ | \ | \ | 1039 $ 11----6---12----7----13 1040 $ |\ |\ | 1041 $ | \ 1 | \ 3 | 1042 $ 10 0 11 1 12 1043 $ | 0 \ | 2 \ | 1044 $ | \ | \ | 1045 $ 8----4----9----5----10 1046 1047 Level: beginner 1048 1049 .seealso: DMPlexCreateFromFile(), DMPlexCreateHexCylinderMesh(), DMSetType(), DMCreate() 1050 @*/ 1051 PetscErrorCode DMPlexCreateBoxMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate, DM *dm) 1052 { 1053 PetscInt fac[3] = {0, 0, 0}; 1054 PetscReal low[3] = {0, 0, 0}; 1055 PetscReal upp[3] = {1, 1, 1}; 1056 DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 1057 PetscInt i, n; 1058 PetscBool flg; 1059 PetscErrorCode ierr; 1060 1061 PetscFunctionBegin; 1062 ierr = PetscOptionsGetInt(NULL, NULL, "-dm_plex_box_dim", &dim, &flg);CHKERRQ(ierr); 1063 if ((dim < 0) || (dim > 3)) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D should be in [1, 3]", dim); 1064 ierr = PetscOptionsGetBool(NULL, NULL, "-dm_plex_box_simplex", &simplex, &flg);CHKERRQ(ierr); 1065 n = 3; 1066 ierr = PetscOptionsGetIntArray(NULL, NULL, "-dm_plex_box_faces", fac, &n, &flg);CHKERRQ(ierr); 1067 for (i = 0; i < dim; ++i) fac[i] = faces ? faces[i] : (flg && i < n ? fac[i] : (dim == 1 ? 1 : 4-dim)); 1068 if (lower) for (i = 0; i < dim; ++i) low[i] = lower[i]; 1069 if (upper) for (i = 0; i < dim; ++i) upp[i] = upper[i]; 1070 if (periodicity) for (i = 0; i < dim; ++i) bdt[i] = periodicity[i]; 1071 /* Allow bounds to be specified from the command line */ 1072 n = 3; 1073 ierr = PetscOptionsGetRealArray(NULL, NULL, "-dm_plex_box_lower", low, &n, &flg);CHKERRQ(ierr); 1074 if (flg && (n != dim)) SETERRQ2(comm, PETSC_ERR_ARG_SIZ, "Lower box point had %D values, should have been %D", n, dim); 1075 n = 3; 1076 ierr = PetscOptionsGetRealArray(NULL, NULL, "-dm_plex_box_upper", upp, &n, &flg);CHKERRQ(ierr); 1077 if (flg && (n != dim)) SETERRQ2(comm, PETSC_ERR_ARG_SIZ, "Upper box point had %D values, should have been %D", n, dim); 1078 n = 3; 1079 ierr = PetscOptionsGetEnumArray(NULL, NULL, "-dm_plex_box_bd", DMBoundaryTypes, (PetscEnum *) bdt, &n, &flg);CHKERRQ(ierr); 1080 if (flg && (n != dim)) SETERRQ2(comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %D values, should have been %D", n, dim); 1081 1082 if (dim == 1) {ierr = DMPlexCreateLineMesh_Internal(comm, fac[0], low[0], upp[0], bdt[0], dm);CHKERRQ(ierr);} 1083 else if (simplex) {ierr = DMPlexCreateBoxMesh_Simplex_Internal(comm, dim, fac, low, upp, bdt, interpolate, dm);CHKERRQ(ierr);} 1084 else {ierr = DMPlexCreateBoxMesh_Tensor_Internal(comm, dim, fac, low, upp, bdt, interpolate, dm);CHKERRQ(ierr);} 1085 PetscFunctionReturn(0); 1086 } 1087 1088 /*@ 1089 DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tesselating the (x,y) plane and extruding in the third direction using wedge cells. 1090 1091 Collective 1092 1093 Input Parameters: 1094 + comm - The communicator for the DM object 1095 . faces - Number of faces per dimension, or NULL for (1, 1, 1) 1096 . lower - The lower left corner, or NULL for (0, 0, 0) 1097 . upper - The upper right corner, or NULL for (1, 1, 1) 1098 . periodicity - The boundary type for the X,Y,Z direction, or NULL for DM_BOUNDARY_NONE 1099 . orderHeight - If PETSC_TRUE, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first 1100 - interpolate - Flag to create intermediate mesh pieces (edges, faces) 1101 1102 Output Parameter: 1103 . dm - The DM object 1104 1105 Level: beginner 1106 1107 .seealso: DMPlexCreateHexCylinderMesh(), DMPlexCreateWedgeCylinderMesh(), DMPlexExtrude(), DMPlexCreateBoxMesh(), DMSetType(), DMCreate() 1108 @*/ 1109 PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm) 1110 { 1111 DM bdm, botdm; 1112 PetscInt i; 1113 PetscInt fac[3] = {0, 0, 0}; 1114 PetscReal low[3] = {0, 0, 0}; 1115 PetscReal upp[3] = {1, 1, 1}; 1116 DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 1117 PetscErrorCode ierr; 1118 1119 PetscFunctionBegin; 1120 for (i = 0; i < 3; ++i) fac[i] = faces ? (faces[i] > 0 ? faces[i] : 1) : 1; 1121 if (lower) for (i = 0; i < 3; ++i) low[i] = lower[i]; 1122 if (upper) for (i = 0; i < 3; ++i) upp[i] = upper[i]; 1123 if (periodicity) for (i = 0; i < 3; ++i) bdt[i] = periodicity[i]; 1124 for (i = 0; i < 3; ++i) if (bdt[i] != DM_BOUNDARY_NONE) SETERRQ(comm, PETSC_ERR_SUP, "Periodicity not yet supported"); 1125 1126 ierr = DMCreate(comm, &bdm);CHKERRQ(ierr); 1127 ierr = DMSetType(bdm, DMPLEX);CHKERRQ(ierr); 1128 ierr = DMSetDimension(bdm, 1);CHKERRQ(ierr); 1129 ierr = DMSetCoordinateDim(bdm, 2);CHKERRQ(ierr); 1130 ierr = DMPlexCreateSquareBoundary(bdm, low, upp, fac);CHKERRQ(ierr); 1131 ierr = DMPlexGenerate(bdm, NULL, PETSC_FALSE, &botdm);CHKERRQ(ierr); 1132 ierr = DMDestroy(&bdm);CHKERRQ(ierr); 1133 ierr = DMPlexExtrude(botdm, fac[2], upp[2] - low[2], orderHeight, NULL, interpolate, dm);CHKERRQ(ierr); 1134 if (low[2] != 0.0) { 1135 Vec v; 1136 PetscScalar *x; 1137 PetscInt cDim, n; 1138 1139 ierr = DMGetCoordinatesLocal(*dm, &v);CHKERRQ(ierr); 1140 ierr = VecGetBlockSize(v, &cDim);CHKERRQ(ierr); 1141 ierr = VecGetLocalSize(v, &n);CHKERRQ(ierr); 1142 ierr = VecGetArray(v, &x);CHKERRQ(ierr); 1143 x += cDim; 1144 for (i=0; i<n; i+=cDim) x[i] += low[2]; 1145 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 1146 ierr = DMSetCoordinatesLocal(*dm, v);CHKERRQ(ierr); 1147 } 1148 ierr = DMDestroy(&botdm);CHKERRQ(ierr); 1149 PetscFunctionReturn(0); 1150 } 1151 1152 /*@C 1153 DMPlexExtrude - Creates a (d+1)-D mesh by extruding a d-D mesh in the normal direction using prismatic cells. 1154 1155 Collective on idm 1156 1157 Input Parameters: 1158 + idm - The mesh to be extruded 1159 . layers - The number of layers, or PETSC_DETERMINE to use the default 1160 . height - The height of the extruded layer, or PETSC_DETERMINE to use the default 1161 . orderHeight - If PETSC_TRUE, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first 1162 . extNormal - The normal direction in which the mesh should be extruded, or NULL to extrude using the surface normal 1163 - interpolate - Flag to create intermediate mesh pieces (edges, faces) 1164 1165 Output Parameter: 1166 . dm - The DM object 1167 1168 Notes: 1169 The mesh created has prismatic cells, and the vertex ordering in the cone of the cell is that of the tensor prismatic cells. Not currently supported in Fortran. 1170 1171 Options Database Keys: 1172 + -dm_plex_extrude_layers <k> - Sets the nubmer of layers k 1173 . -dm_plex_extrude_height <h> - Sets the height h of each layer 1174 . -dm_plex_extrude_order_height - If true, order cells by height first 1175 - -dm_plex_extrude_normal <n0,...,nd> - Sets the normal vector along which to extrude 1176 1177 Level: advanced 1178 1179 .seealso: DMPlexCreateWedgeCylinderMesh(), DMPlexCreateWedgeBoxMesh(), DMSetType(), DMCreate() 1180 @*/ 1181 PetscErrorCode DMPlexExtrude(DM idm, PetscInt layers, PetscReal height, PetscBool orderHeight, const PetscReal extNormal[], PetscBool interpolate, DM* dm) 1182 { 1183 PetscScalar *coordsB; 1184 const PetscScalar *coordsA; 1185 PetscReal *normals = NULL; 1186 PetscReal clNormal[3]; 1187 Vec coordinatesA, coordinatesB; 1188 PetscSection coordSectionA, coordSectionB; 1189 PetscInt dim, cDim, cDimB, c, l, v, coordSize, *newCone; 1190 PetscInt cStart, cEnd, vStart, vEnd, cellV, numCells, numVertices; 1191 const char *prefix; 1192 PetscBool haveCLNormal; 1193 PetscErrorCode ierr; 1194 1195 PetscFunctionBegin; 1196 PetscValidHeaderSpecific(idm, DM_CLASSID, 1); 1197 PetscValidLogicalCollectiveInt(idm, layers, 2); 1198 PetscValidLogicalCollectiveReal(idm, height, 3); 1199 PetscValidLogicalCollectiveBool(idm, interpolate, 4); 1200 ierr = DMGetDimension(idm, &dim);CHKERRQ(ierr); 1201 ierr = DMGetCoordinateDim(idm, &cDim);CHKERRQ(ierr); 1202 cDimB = cDim == dim ? cDim+1 : cDim; 1203 if (dim < 1 || dim > 3) SETERRQ1(PetscObjectComm((PetscObject)idm), PETSC_ERR_SUP, "Support for dimension %D not coded", dim); 1204 1205 ierr = PetscObjectGetOptionsPrefix((PetscObject) idm, &prefix);CHKERRQ(ierr); 1206 if (layers < 0) layers = 1; 1207 ierr = PetscOptionsGetInt(NULL, prefix, "-dm_plex_extrude_layers", &layers, NULL);CHKERRQ(ierr); 1208 if (layers <= 0) SETERRQ1(PetscObjectComm((PetscObject) idm), PETSC_ERR_ARG_OUTOFRANGE, "Number of layers %D must be positive", layers); 1209 if (height < 0.) height = 1.; 1210 ierr = PetscOptionsGetReal(NULL, prefix, "-dm_plex_extrude_height", &height, NULL);CHKERRQ(ierr); 1211 if (height <= 0.) SETERRQ1(PetscObjectComm((PetscObject) idm), PETSC_ERR_ARG_OUTOFRANGE, "Height of layers %g must be positive", (double) height); 1212 ierr = PetscOptionsGetBool(NULL, prefix, "-dm_plex_extrude_order_height", &orderHeight, NULL);CHKERRQ(ierr); 1213 c = 3; 1214 ierr = PetscOptionsGetRealArray(NULL, prefix, "-dm_plex_extrude_normal", clNormal, &c, &haveCLNormal);CHKERRQ(ierr); 1215 if (haveCLNormal && c != cDimB) SETERRQ2(PetscObjectComm((PetscObject)idm), PETSC_ERR_ARG_SIZ, "Input normal has size %D != %D extruded coordinate dimension", c, cDimB); 1216 1217 ierr = DMPlexGetHeightStratum(idm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1218 ierr = DMPlexGetDepthStratum(idm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1219 numCells = (cEnd - cStart)*layers; 1220 numVertices = (vEnd - vStart)*(layers+1); 1221 ierr = DMCreate(PetscObjectComm((PetscObject)idm), dm);CHKERRQ(ierr); 1222 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 1223 ierr = DMSetDimension(*dm, dim+1);CHKERRQ(ierr); 1224 ierr = DMPlexSetChart(*dm, 0, numCells+numVertices);CHKERRQ(ierr); 1225 /* Must create the celltype label here so that we do not automatically try to compute the types */ 1226 ierr = DMCreateLabel(*dm, "celltype");CHKERRQ(ierr); 1227 for (c = cStart, cellV = 0; c < cEnd; ++c) { 1228 DMPolytopeType ct, nct; 1229 PetscInt *closure = NULL; 1230 PetscInt closureSize, numCorners = 0; 1231 1232 ierr = DMPlexGetCellType(idm, c, &ct);CHKERRQ(ierr); 1233 switch (ct) { 1234 case DM_POLYTOPE_SEGMENT: nct = DM_POLYTOPE_SEG_PRISM_TENSOR;break; 1235 case DM_POLYTOPE_TRIANGLE: nct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 1236 case DM_POLYTOPE_QUADRILATERAL: nct = DM_POLYTOPE_QUAD_PRISM_TENSOR;break; 1237 default: nct = DM_POLYTOPE_UNKNOWN; 1238 } 1239 ierr = DMPlexGetTransitiveClosure(idm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1240 for (v = 0; v < closureSize*2; v += 2) if ((closure[v] >= vStart) && (closure[v] < vEnd)) numCorners++; 1241 ierr = DMPlexRestoreTransitiveClosure(idm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1242 for (l = 0; l < layers; ++l) { 1243 const PetscInt cell = orderHeight ? layers*(c - cStart) + l : l*(cEnd - cStart) + c - cStart; 1244 1245 ierr = DMPlexSetConeSize(*dm, cell, 2*numCorners);CHKERRQ(ierr); 1246 ierr = DMPlexSetCellType(*dm, cell, nct);CHKERRQ(ierr); 1247 } 1248 cellV = PetscMax(numCorners,cellV); 1249 } 1250 ierr = DMSetUp(*dm);CHKERRQ(ierr); 1251 1252 if (dim != cDim && !(extNormal || haveCLNormal)) {ierr = PetscCalloc1(cDim*(vEnd - vStart), &normals);CHKERRQ(ierr);} 1253 ierr = PetscMalloc1(3*cellV,&newCone);CHKERRQ(ierr); 1254 for (c = cStart; c < cEnd; ++c) { 1255 PetscInt *closure = NULL; 1256 PetscInt closureSize, numCorners = 0, l; 1257 PetscReal normal[3] = {0, 0, 0}; 1258 1259 if (normals) {ierr = DMPlexComputeCellGeometryFVM(idm, c, NULL, NULL, normal);CHKERRQ(ierr);} 1260 ierr = DMPlexGetTransitiveClosure(idm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1261 for (v = 0; v < closureSize*2; v += 2) { 1262 if ((closure[v] >= vStart) && (closure[v] < vEnd)) { 1263 PetscInt d; 1264 1265 newCone[numCorners++] = closure[v] - vStart; 1266 if (normals) {for (d = 0; d < cDim; ++d) normals[cDim*(closure[v]-vStart)+d] += normal[d];} 1267 } 1268 } 1269 ierr = DMPlexRestoreTransitiveClosure(idm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1270 for (l = 0; l < layers; ++l) { 1271 PetscInt i; 1272 1273 for (i = 0; i < numCorners; ++i) { 1274 newCone[ numCorners + i] = orderHeight ? (layers+1)*newCone[i] + l + numCells : l*(vEnd - vStart) + newCone[i] + numCells; 1275 newCone[2*numCorners + i] = orderHeight ? (layers+1)*newCone[i] + l + 1 + numCells : (l+1)*(vEnd - vStart) + newCone[i] + numCells; 1276 } 1277 ierr = DMPlexSetCone(*dm, orderHeight ? layers*(c - cStart) + l : l*(cEnd - cStart) + c - cStart, newCone + numCorners);CHKERRQ(ierr); 1278 } 1279 } 1280 ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr); 1281 ierr = DMPlexStratify(*dm);CHKERRQ(ierr); 1282 ierr = PetscFree(newCone);CHKERRQ(ierr); 1283 1284 ierr = DMGetCoordinateSection(*dm, &coordSectionB);CHKERRQ(ierr); 1285 ierr = PetscSectionSetNumFields(coordSectionB, 1);CHKERRQ(ierr); 1286 ierr = PetscSectionSetFieldComponents(coordSectionB, 0, cDimB);CHKERRQ(ierr); 1287 ierr = PetscSectionSetChart(coordSectionB, numCells, numCells+numVertices);CHKERRQ(ierr); 1288 for (v = numCells; v < numCells+numVertices; ++v) { 1289 ierr = PetscSectionSetDof(coordSectionB, v, cDimB);CHKERRQ(ierr); 1290 ierr = PetscSectionSetFieldDof(coordSectionB, v, 0, cDimB);CHKERRQ(ierr); 1291 ierr = DMPlexSetCellType(*dm, v, DM_POLYTOPE_POINT);CHKERRQ(ierr); 1292 } 1293 ierr = PetscSectionSetUp(coordSectionB);CHKERRQ(ierr); 1294 ierr = PetscSectionGetStorageSize(coordSectionB, &coordSize);CHKERRQ(ierr); 1295 ierr = VecCreate(PETSC_COMM_SELF, &coordinatesB);CHKERRQ(ierr); 1296 ierr = PetscObjectSetName((PetscObject) coordinatesB, "coordinates");CHKERRQ(ierr); 1297 ierr = VecSetSizes(coordinatesB, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 1298 ierr = VecSetBlockSize(coordinatesB, cDimB);CHKERRQ(ierr); 1299 ierr = VecSetType(coordinatesB,VECSTANDARD);CHKERRQ(ierr); 1300 1301 ierr = DMGetCoordinateSection(idm, &coordSectionA);CHKERRQ(ierr); 1302 ierr = DMGetCoordinatesLocal(idm, &coordinatesA);CHKERRQ(ierr); 1303 ierr = VecGetArray(coordinatesB, &coordsB);CHKERRQ(ierr); 1304 ierr = VecGetArrayRead(coordinatesA, &coordsA);CHKERRQ(ierr); 1305 for (v = vStart; v < vEnd; ++v) { 1306 const PetscScalar *cptr; 1307 PetscReal ones2[2] = { 0., 1.}, ones3[3] = { 0., 0., 1.}; 1308 PetscReal normal[3]; 1309 PetscReal norm, h = height/layers; 1310 PetscInt offA, d, cDimA = cDim; 1311 1312 if (normals) {for (d = 0; d < cDimB; ++d) normal[d] = normals[cDimB*(v - vStart)+d];} 1313 else if (haveCLNormal) {for (d = 0; d < cDimB; ++d) normal[d] = clNormal[d];} 1314 else if (extNormal) {for (d = 0; d < cDimB; ++d) normal[d] = extNormal[d];} 1315 else if (cDimB == 2) {for (d = 0; d < cDimB; ++d) normal[d] = ones2[d];} 1316 else if (cDimB == 3) {for (d = 0; d < cDimB; ++d) normal[d] = ones3[d];} 1317 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unable to determine normal for extrusion"); 1318 for (d = 0, norm = 0.0; d < cDimB; ++d) norm += normal[d]*normal[d]; 1319 for (d = 0; d < cDimB; ++d) normal[d] *= 1./PetscSqrtReal(norm); 1320 1321 ierr = PetscSectionGetOffset(coordSectionA, v, &offA);CHKERRQ(ierr); 1322 cptr = coordsA + offA; 1323 for (l = 0; l < layers+1; ++l) { 1324 PetscInt offB, d, newV; 1325 1326 newV = orderHeight ? (layers+1)*(v -vStart) + l + numCells : (vEnd -vStart)*l + (v -vStart) + numCells; 1327 ierr = PetscSectionGetOffset(coordSectionB, newV, &offB);CHKERRQ(ierr); 1328 for (d = 0; d < cDimA; ++d) { coordsB[offB+d] = cptr[d]; } 1329 for (d = 0; d < cDimB; ++d) { coordsB[offB+d] += l ? normal[d]*h : 0.0; } 1330 cptr = coordsB + offB; 1331 cDimA = cDimB; 1332 } 1333 } 1334 ierr = VecRestoreArrayRead(coordinatesA, &coordsA);CHKERRQ(ierr); 1335 ierr = VecRestoreArray(coordinatesB, &coordsB);CHKERRQ(ierr); 1336 ierr = DMSetCoordinatesLocal(*dm, coordinatesB);CHKERRQ(ierr); 1337 ierr = VecDestroy(&coordinatesB);CHKERRQ(ierr); 1338 ierr = PetscFree(normals);CHKERRQ(ierr); 1339 if (interpolate) { 1340 DM idm; 1341 1342 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 1343 ierr = DMPlexCopyCoordinates(*dm, idm);CHKERRQ(ierr); 1344 ierr = DMDestroy(dm);CHKERRQ(ierr); 1345 *dm = idm; 1346 } 1347 PetscFunctionReturn(0); 1348 } 1349 1350 /*@C 1351 DMPlexSetOptionsPrefix - Sets the prefix used for searching for all DM options in the database. 1352 1353 Logically Collective on dm 1354 1355 Input Parameters: 1356 + dm - the DM context 1357 - prefix - the prefix to prepend to all option names 1358 1359 Notes: 1360 A hyphen (-) must NOT be given at the beginning of the prefix name. 1361 The first character of all runtime options is AUTOMATICALLY the hyphen. 1362 1363 Level: advanced 1364 1365 .seealso: SNESSetFromOptions() 1366 @*/ 1367 PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[]) 1368 { 1369 DM_Plex *mesh = (DM_Plex *) dm->data; 1370 PetscErrorCode ierr; 1371 1372 PetscFunctionBegin; 1373 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1374 ierr = PetscObjectSetOptionsPrefix((PetscObject) dm, prefix);CHKERRQ(ierr); 1375 ierr = PetscObjectSetOptionsPrefix((PetscObject) mesh->partitioner, prefix);CHKERRQ(ierr); 1376 PetscFunctionReturn(0); 1377 } 1378 1379 /*@ 1380 DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra. 1381 1382 Collective 1383 1384 Input Parameters: 1385 + comm - The communicator for the DM object 1386 . numRefine - The number of regular refinements to the basic 5 cell structure 1387 - periodicZ - The boundary type for the Z direction 1388 1389 Output Parameter: 1390 . dm - The DM object 1391 1392 Note: Here is the output numbering looking from the bottom of the cylinder: 1393 $ 17-----14 1394 $ | | 1395 $ | 2 | 1396 $ | | 1397 $ 17-----8-----7-----14 1398 $ | | | | 1399 $ | 3 | 0 | 1 | 1400 $ | | | | 1401 $ 19-----5-----6-----13 1402 $ | | 1403 $ | 4 | 1404 $ | | 1405 $ 19-----13 1406 $ 1407 $ and up through the top 1408 $ 1409 $ 18-----16 1410 $ | | 1411 $ | 2 | 1412 $ | | 1413 $ 18----10----11-----16 1414 $ | | | | 1415 $ | 3 | 0 | 1 | 1416 $ | | | | 1417 $ 20-----9----12-----15 1418 $ | | 1419 $ | 4 | 1420 $ | | 1421 $ 20-----15 1422 1423 Level: beginner 1424 1425 .seealso: DMPlexCreateBoxMesh(), DMSetType(), DMCreate() 1426 @*/ 1427 PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, PetscInt numRefine, DMBoundaryType periodicZ, DM *dm) 1428 { 1429 const PetscInt dim = 3; 1430 PetscInt numCells, numVertices, r; 1431 PetscMPIInt rank; 1432 PetscErrorCode ierr; 1433 1434 PetscFunctionBegin; 1435 PetscValidPointer(dm, 4); 1436 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 1437 if (numRefine < 0) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of refinements %D cannot be negative", numRefine); 1438 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 1439 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 1440 ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); 1441 /* Create topology */ 1442 { 1443 PetscInt cone[8], c; 1444 1445 numCells = !rank ? 5 : 0; 1446 numVertices = !rank ? 16 : 0; 1447 if (periodicZ == DM_BOUNDARY_PERIODIC) { 1448 numCells *= 3; 1449 numVertices = !rank ? 24 : 0; 1450 } 1451 ierr = DMPlexSetChart(*dm, 0, numCells+numVertices);CHKERRQ(ierr); 1452 for (c = 0; c < numCells; c++) {ierr = DMPlexSetConeSize(*dm, c, 8);CHKERRQ(ierr);} 1453 ierr = DMSetUp(*dm);CHKERRQ(ierr); 1454 if (!rank) { 1455 if (periodicZ == DM_BOUNDARY_PERIODIC) { 1456 cone[0] = 15; cone[1] = 18; cone[2] = 17; cone[3] = 16; 1457 cone[4] = 31; cone[5] = 32; cone[6] = 33; cone[7] = 34; 1458 ierr = DMPlexSetCone(*dm, 0, cone);CHKERRQ(ierr); 1459 cone[0] = 16; cone[1] = 17; cone[2] = 24; cone[3] = 23; 1460 cone[4] = 32; cone[5] = 36; cone[6] = 37; cone[7] = 33; /* 22 25 26 21 */ 1461 ierr = DMPlexSetCone(*dm, 1, cone);CHKERRQ(ierr); 1462 cone[0] = 18; cone[1] = 27; cone[2] = 24; cone[3] = 17; 1463 cone[4] = 34; cone[5] = 33; cone[6] = 37; cone[7] = 38; 1464 ierr = DMPlexSetCone(*dm, 2, cone);CHKERRQ(ierr); 1465 cone[0] = 29; cone[1] = 27; cone[2] = 18; cone[3] = 15; 1466 cone[4] = 35; cone[5] = 31; cone[6] = 34; cone[7] = 38; 1467 ierr = DMPlexSetCone(*dm, 3, cone);CHKERRQ(ierr); 1468 cone[0] = 29; cone[1] = 15; cone[2] = 16; cone[3] = 23; 1469 cone[4] = 35; cone[5] = 36; cone[6] = 32; cone[7] = 31; 1470 ierr = DMPlexSetCone(*dm, 4, cone);CHKERRQ(ierr); 1471 1472 cone[0] = 31; cone[1] = 34; cone[2] = 33; cone[3] = 32; 1473 cone[4] = 19; cone[5] = 22; cone[6] = 21; cone[7] = 20; 1474 ierr = DMPlexSetCone(*dm, 5, cone);CHKERRQ(ierr); 1475 cone[0] = 32; cone[1] = 33; cone[2] = 37; cone[3] = 36; 1476 cone[4] = 22; cone[5] = 25; cone[6] = 26; cone[7] = 21; 1477 ierr = DMPlexSetCone(*dm, 6, cone);CHKERRQ(ierr); 1478 cone[0] = 34; cone[1] = 38; cone[2] = 37; cone[3] = 33; 1479 cone[4] = 20; cone[5] = 21; cone[6] = 26; cone[7] = 28; 1480 ierr = DMPlexSetCone(*dm, 7, cone);CHKERRQ(ierr); 1481 cone[0] = 35; cone[1] = 38; cone[2] = 34; cone[3] = 31; 1482 cone[4] = 30; cone[5] = 19; cone[6] = 20; cone[7] = 28; 1483 ierr = DMPlexSetCone(*dm, 8, cone);CHKERRQ(ierr); 1484 cone[0] = 35; cone[1] = 31; cone[2] = 32; cone[3] = 36; 1485 cone[4] = 30; cone[5] = 25; cone[6] = 22; cone[7] = 19; 1486 ierr = DMPlexSetCone(*dm, 9, cone);CHKERRQ(ierr); 1487 1488 cone[0] = 19; cone[1] = 20; cone[2] = 21; cone[3] = 22; 1489 cone[4] = 15; cone[5] = 16; cone[6] = 17; cone[7] = 18; 1490 ierr = DMPlexSetCone(*dm, 10, cone);CHKERRQ(ierr); 1491 cone[0] = 22; cone[1] = 21; cone[2] = 26; cone[3] = 25; 1492 cone[4] = 16; cone[5] = 23; cone[6] = 24; cone[7] = 17; 1493 ierr = DMPlexSetCone(*dm, 11, cone);CHKERRQ(ierr); 1494 cone[0] = 20; cone[1] = 28; cone[2] = 26; cone[3] = 21; 1495 cone[4] = 18; cone[5] = 17; cone[6] = 24; cone[7] = 27; 1496 ierr = DMPlexSetCone(*dm, 12, cone);CHKERRQ(ierr); 1497 cone[0] = 30; cone[1] = 28; cone[2] = 20; cone[3] = 19; 1498 cone[4] = 29; cone[5] = 15; cone[6] = 18; cone[7] = 27; 1499 ierr = DMPlexSetCone(*dm, 13, cone);CHKERRQ(ierr); 1500 cone[0] = 30; cone[1] = 19; cone[2] = 22; cone[3] = 25; 1501 cone[4] = 29; cone[5] = 23; cone[6] = 16; cone[7] = 15; 1502 ierr = DMPlexSetCone(*dm, 14, cone);CHKERRQ(ierr); 1503 } else { 1504 cone[0] = 5; cone[1] = 8; cone[2] = 7; cone[3] = 6; 1505 cone[4] = 9; cone[5] = 12; cone[6] = 11; cone[7] = 10; 1506 ierr = DMPlexSetCone(*dm, 0, cone);CHKERRQ(ierr); 1507 cone[0] = 6; cone[1] = 7; cone[2] = 14; cone[3] = 13; 1508 cone[4] = 12; cone[5] = 15; cone[6] = 16; cone[7] = 11; 1509 ierr = DMPlexSetCone(*dm, 1, cone);CHKERRQ(ierr); 1510 cone[0] = 8; cone[1] = 17; cone[2] = 14; cone[3] = 7; 1511 cone[4] = 10; cone[5] = 11; cone[6] = 16; cone[7] = 18; 1512 ierr = DMPlexSetCone(*dm, 2, cone);CHKERRQ(ierr); 1513 cone[0] = 19; cone[1] = 17; cone[2] = 8; cone[3] = 5; 1514 cone[4] = 20; cone[5] = 9; cone[6] = 10; cone[7] = 18; 1515 ierr = DMPlexSetCone(*dm, 3, cone);CHKERRQ(ierr); 1516 cone[0] = 19; cone[1] = 5; cone[2] = 6; cone[3] = 13; 1517 cone[4] = 20; cone[5] = 15; cone[6] = 12; cone[7] = 9; 1518 ierr = DMPlexSetCone(*dm, 4, cone);CHKERRQ(ierr); 1519 } 1520 } 1521 ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr); 1522 ierr = DMPlexStratify(*dm);CHKERRQ(ierr); 1523 } 1524 /* Interpolate */ 1525 { 1526 DM idm; 1527 1528 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 1529 ierr = DMDestroy(dm);CHKERRQ(ierr); 1530 *dm = idm; 1531 } 1532 /* Create cube geometry */ 1533 { 1534 Vec coordinates; 1535 PetscSection coordSection; 1536 PetscScalar *coords; 1537 PetscInt coordSize, v; 1538 const PetscReal dis = 1.0/PetscSqrtReal(2.0); 1539 const PetscReal ds2 = dis/2.0; 1540 1541 /* Build coordinates */ 1542 ierr = DMGetCoordinateSection(*dm, &coordSection);CHKERRQ(ierr); 1543 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 1544 ierr = PetscSectionSetFieldComponents(coordSection, 0, dim);CHKERRQ(ierr); 1545 ierr = PetscSectionSetChart(coordSection, numCells, numCells+numVertices);CHKERRQ(ierr); 1546 for (v = numCells; v < numCells+numVertices; ++v) { 1547 ierr = PetscSectionSetDof(coordSection, v, dim);CHKERRQ(ierr); 1548 ierr = PetscSectionSetFieldDof(coordSection, v, 0, dim);CHKERRQ(ierr); 1549 } 1550 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 1551 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 1552 ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr); 1553 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 1554 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 1555 ierr = VecSetBlockSize(coordinates, dim);CHKERRQ(ierr); 1556 ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr); 1557 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 1558 if (!rank) { 1559 coords[0*dim+0] = -ds2; coords[0*dim+1] = -ds2; coords[0*dim+2] = 0.0; 1560 coords[1*dim+0] = ds2; coords[1*dim+1] = -ds2; coords[1*dim+2] = 0.0; 1561 coords[2*dim+0] = ds2; coords[2*dim+1] = ds2; coords[2*dim+2] = 0.0; 1562 coords[3*dim+0] = -ds2; coords[3*dim+1] = ds2; coords[3*dim+2] = 0.0; 1563 coords[4*dim+0] = -ds2; coords[4*dim+1] = -ds2; coords[4*dim+2] = 1.0; 1564 coords[5*dim+0] = -ds2; coords[5*dim+1] = ds2; coords[5*dim+2] = 1.0; 1565 coords[6*dim+0] = ds2; coords[6*dim+1] = ds2; coords[6*dim+2] = 1.0; 1566 coords[7*dim+0] = ds2; coords[7*dim+1] = -ds2; coords[7*dim+2] = 1.0; 1567 coords[ 8*dim+0] = dis; coords[ 8*dim+1] = -dis; coords[ 8*dim+2] = 0.0; 1568 coords[ 9*dim+0] = dis; coords[ 9*dim+1] = dis; coords[ 9*dim+2] = 0.0; 1569 coords[10*dim+0] = dis; coords[10*dim+1] = -dis; coords[10*dim+2] = 1.0; 1570 coords[11*dim+0] = dis; coords[11*dim+1] = dis; coords[11*dim+2] = 1.0; 1571 coords[12*dim+0] = -dis; coords[12*dim+1] = dis; coords[12*dim+2] = 0.0; 1572 coords[13*dim+0] = -dis; coords[13*dim+1] = dis; coords[13*dim+2] = 1.0; 1573 coords[14*dim+0] = -dis; coords[14*dim+1] = -dis; coords[14*dim+2] = 0.0; 1574 coords[15*dim+0] = -dis; coords[15*dim+1] = -dis; coords[15*dim+2] = 1.0; 1575 if (periodicZ == DM_BOUNDARY_PERIODIC) { 1576 /* 15 31 19 */ coords[16*dim+0] = -ds2; coords[16*dim+1] = -ds2; coords[16*dim+2] = 0.5; 1577 /* 16 32 22 */ coords[17*dim+0] = ds2; coords[17*dim+1] = -ds2; coords[17*dim+2] = 0.5; 1578 /* 17 33 21 */ coords[18*dim+0] = ds2; coords[18*dim+1] = ds2; coords[18*dim+2] = 0.5; 1579 /* 18 34 20 */ coords[19*dim+0] = -ds2; coords[19*dim+1] = ds2; coords[19*dim+2] = 0.5; 1580 /* 29 35 30 */ coords[20*dim+0] = -dis; coords[20*dim+1] = -dis; coords[20*dim+2] = 0.5; 1581 /* 23 36 25 */ coords[21*dim+0] = dis; coords[21*dim+1] = -dis; coords[21*dim+2] = 0.5; 1582 /* 24 37 26 */ coords[22*dim+0] = dis; coords[22*dim+1] = dis; coords[22*dim+2] = 0.5; 1583 /* 27 38 28 */ coords[23*dim+0] = -dis; coords[23*dim+1] = dis; coords[23*dim+2] = 0.5; 1584 } 1585 } 1586 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 1587 ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr); 1588 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 1589 } 1590 /* Create periodicity */ 1591 if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) { 1592 PetscReal L[3]; 1593 PetscReal maxCell[3]; 1594 DMBoundaryType bdType[3]; 1595 PetscReal lower[3] = {0.0, 0.0, 0.0}; 1596 PetscReal upper[3] = {1.0, 1.0, 1.5}; 1597 PetscInt i, numZCells = 3; 1598 1599 bdType[0] = DM_BOUNDARY_NONE; 1600 bdType[1] = DM_BOUNDARY_NONE; 1601 bdType[2] = periodicZ; 1602 for (i = 0; i < dim; i++) { 1603 L[i] = upper[i] - lower[i]; 1604 maxCell[i] = 1.1 * (L[i] / numZCells); 1605 } 1606 ierr = DMSetPeriodicity(*dm, PETSC_TRUE, maxCell, L, bdType);CHKERRQ(ierr); 1607 } 1608 /* Refine topology */ 1609 for (r = 0; r < numRefine; ++r) { 1610 DM rdm = NULL; 1611 1612 ierr = DMRefine(*dm, comm, &rdm);CHKERRQ(ierr); 1613 ierr = DMDestroy(dm);CHKERRQ(ierr); 1614 *dm = rdm; 1615 } 1616 /* Remap geometry to cylinder 1617 Interior square: Linear interpolation is correct 1618 The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing 1619 such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance 1620 1621 phi = arctan(y/x) 1622 d_close = sqrt(1/8 + 1/4 sin^2(phi)) 1623 d_far = sqrt(1/2 + sin^2(phi)) 1624 1625 so we remap them using 1626 1627 x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close) 1628 y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close) 1629 1630 If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y. 1631 */ 1632 { 1633 Vec coordinates; 1634 PetscSection coordSection; 1635 PetscScalar *coords; 1636 PetscInt vStart, vEnd, v; 1637 const PetscReal dis = 1.0/PetscSqrtReal(2.0); 1638 const PetscReal ds2 = 0.5*dis; 1639 1640 ierr = DMPlexGetDepthStratum(*dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1641 ierr = DMGetCoordinateSection(*dm, &coordSection);CHKERRQ(ierr); 1642 ierr = DMGetCoordinatesLocal(*dm, &coordinates);CHKERRQ(ierr); 1643 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 1644 for (v = vStart; v < vEnd; ++v) { 1645 PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc; 1646 PetscInt off; 1647 1648 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 1649 if ((PetscAbsScalar(coords[off+0]) <= ds2) && (PetscAbsScalar(coords[off+1]) <= ds2)) continue; 1650 x = PetscRealPart(coords[off]); 1651 y = PetscRealPart(coords[off+1]); 1652 phi = PetscAtan2Real(y, x); 1653 sinp = PetscSinReal(phi); 1654 cosp = PetscCosReal(phi); 1655 if ((PetscAbsReal(phi) > PETSC_PI/4.0) && (PetscAbsReal(phi) < 3.0*PETSC_PI/4.0)) { 1656 dc = PetscAbsReal(ds2/sinp); 1657 df = PetscAbsReal(dis/sinp); 1658 xc = ds2*x/PetscAbsReal(y); 1659 yc = ds2*PetscSignReal(y); 1660 } else { 1661 dc = PetscAbsReal(ds2/cosp); 1662 df = PetscAbsReal(dis/cosp); 1663 xc = ds2*PetscSignReal(x); 1664 yc = ds2*y/PetscAbsReal(x); 1665 } 1666 coords[off+0] = xc + (coords[off+0] - xc)*(1.0 - dc)/(df - dc); 1667 coords[off+1] = yc + (coords[off+1] - yc)*(1.0 - dc)/(df - dc); 1668 } 1669 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 1670 if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) { 1671 ierr = DMLocalizeCoordinates(*dm);CHKERRQ(ierr); 1672 } 1673 } 1674 PetscFunctionReturn(0); 1675 } 1676 1677 /*@ 1678 DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges. 1679 1680 Collective 1681 1682 Input Parameters: 1683 + comm - The communicator for the DM object 1684 . n - The number of wedges around the origin 1685 - interpolate - Create edges and faces 1686 1687 Output Parameter: 1688 . dm - The DM object 1689 1690 Level: beginner 1691 1692 .seealso: DMPlexCreateHexCylinderMesh(), DMPlexCreateBoxMesh(), DMSetType(), DMCreate() 1693 @*/ 1694 PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm) 1695 { 1696 const PetscInt dim = 3; 1697 PetscInt numCells, numVertices, v; 1698 PetscMPIInt rank; 1699 PetscErrorCode ierr; 1700 1701 PetscFunctionBegin; 1702 PetscValidPointer(dm, 3); 1703 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 1704 if (n < 0) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %D cannot be negative", n); 1705 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 1706 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 1707 ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); 1708 /* Must create the celltype label here so that we do not automatically try to compute the types */ 1709 ierr = DMCreateLabel(*dm, "celltype");CHKERRQ(ierr); 1710 /* Create topology */ 1711 { 1712 PetscInt cone[6], c; 1713 1714 numCells = !rank ? n : 0; 1715 numVertices = !rank ? 2*(n+1) : 0; 1716 ierr = DMPlexSetChart(*dm, 0, numCells+numVertices);CHKERRQ(ierr); 1717 for (c = 0; c < numCells; c++) {ierr = DMPlexSetConeSize(*dm, c, 6);CHKERRQ(ierr);} 1718 ierr = DMSetUp(*dm);CHKERRQ(ierr); 1719 for (c = 0; c < numCells; c++) { 1720 cone[0] = c+n*1; cone[1] = (c+1)%n+n*1; cone[2] = 0+3*n; 1721 cone[3] = c+n*2; cone[4] = (c+1)%n+n*2; cone[5] = 1+3*n; 1722 ierr = DMPlexSetCone(*dm, c, cone);CHKERRQ(ierr); 1723 ierr = DMPlexSetCellType(*dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR);CHKERRQ(ierr); 1724 } 1725 ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr); 1726 ierr = DMPlexStratify(*dm);CHKERRQ(ierr); 1727 } 1728 for (v = numCells; v < numCells+numVertices; ++v) { 1729 ierr = DMPlexSetCellType(*dm, v, DM_POLYTOPE_POINT);CHKERRQ(ierr); 1730 } 1731 /* Interpolate */ 1732 if (interpolate) { 1733 DM idm; 1734 1735 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 1736 ierr = DMDestroy(dm);CHKERRQ(ierr); 1737 *dm = idm; 1738 } 1739 /* Create cylinder geometry */ 1740 { 1741 Vec coordinates; 1742 PetscSection coordSection; 1743 PetscScalar *coords; 1744 PetscInt coordSize, c; 1745 1746 /* Build coordinates */ 1747 ierr = DMGetCoordinateSection(*dm, &coordSection);CHKERRQ(ierr); 1748 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 1749 ierr = PetscSectionSetFieldComponents(coordSection, 0, dim);CHKERRQ(ierr); 1750 ierr = PetscSectionSetChart(coordSection, numCells, numCells+numVertices);CHKERRQ(ierr); 1751 for (v = numCells; v < numCells+numVertices; ++v) { 1752 ierr = PetscSectionSetDof(coordSection, v, dim);CHKERRQ(ierr); 1753 ierr = PetscSectionSetFieldDof(coordSection, v, 0, dim);CHKERRQ(ierr); 1754 } 1755 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 1756 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 1757 ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr); 1758 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 1759 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 1760 ierr = VecSetBlockSize(coordinates, dim);CHKERRQ(ierr); 1761 ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr); 1762 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 1763 for (c = 0; c < numCells; c++) { 1764 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; 1765 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; 1766 } 1767 if (!rank) { 1768 coords[(2*n+0)*dim+0] = 0.0; coords[(2*n+0)*dim+1] = 0.0; coords[(2*n+0)*dim+2] = 1.0; 1769 coords[(2*n+1)*dim+0] = 0.0; coords[(2*n+1)*dim+1] = 0.0; coords[(2*n+1)*dim+2] = 0.0; 1770 } 1771 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 1772 ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr); 1773 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 1774 } 1775 PetscFunctionReturn(0); 1776 } 1777 1778 PETSC_STATIC_INLINE PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 1779 { 1780 PetscReal prod = 0.0; 1781 PetscInt i; 1782 for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]); 1783 return PetscSqrtReal(prod); 1784 } 1785 PETSC_STATIC_INLINE PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 1786 { 1787 PetscReal prod = 0.0; 1788 PetscInt i; 1789 for (i = 0; i < dim; ++i) prod += x[i]*y[i]; 1790 return prod; 1791 } 1792 1793 /* The first constant is the sphere radius */ 1794 static void snapToSphere(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1795 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1796 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1797 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 1798 { 1799 PetscReal r = PetscRealPart(constants[0]); 1800 PetscReal norm2 = 0.0, fac; 1801 PetscInt n = uOff[1] - uOff[0], d; 1802 1803 for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d])); 1804 fac = r/PetscSqrtReal(norm2); 1805 for (d = 0; d < n; ++d) f0[d] = u[d]*fac; 1806 } 1807 1808 /*@ 1809 DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d. 1810 1811 Collective 1812 1813 Input Parameters: 1814 + comm - The communicator for the DM object 1815 . dim - The dimension 1816 . simplex - Use simplices, or tensor product cells 1817 - R - The radius 1818 1819 Output Parameter: 1820 . dm - The DM object 1821 1822 Level: beginner 1823 1824 .seealso: DMPlexCreateBallMesh(), DMPlexCreateBoxMesh(), DMSetType(), DMCreate() 1825 @*/ 1826 PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm) 1827 { 1828 const PetscInt embedDim = dim+1; 1829 PetscSection coordSection; 1830 Vec coordinates; 1831 PetscScalar *coords; 1832 PetscReal *coordsIn; 1833 PetscInt numCells, numEdges, numVerts, firstVertex, v, firstEdge, coordSize, d, c, e; 1834 PetscMPIInt rank; 1835 PetscErrorCode ierr; 1836 1837 PetscFunctionBegin; 1838 PetscValidPointer(dm, 4); 1839 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 1840 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 1841 ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); 1842 ierr = DMSetCoordinateDim(*dm, dim+1);CHKERRQ(ierr); 1843 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) *dm), &rank);CHKERRQ(ierr); 1844 switch (dim) { 1845 case 2: 1846 if (simplex) { 1847 DM idm; 1848 const PetscReal radius = PetscSqrtReal(1 + PETSC_PHI*PETSC_PHI)/(1.0 + PETSC_PHI); 1849 const PetscReal edgeLen = 2.0/(1.0 + PETSC_PHI) * (R/radius); 1850 const PetscInt degree = 5; 1851 PetscReal vertex[3] = {0.0, 1.0/(1.0 + PETSC_PHI), PETSC_PHI/(1.0 + PETSC_PHI)}; 1852 PetscInt s[3] = {1, 1, 1}; 1853 PetscInt cone[3]; 1854 PetscInt *graph, p, i, j, k; 1855 1856 vertex[0] *= R/radius; vertex[1] *= R/radius; vertex[2] *= R/radius; 1857 numCells = !rank ? 20 : 0; 1858 numVerts = !rank ? 12 : 0; 1859 firstVertex = numCells; 1860 /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of 1861 1862 (0, \pm 1/\phi+1, \pm \phi/\phi+1) 1863 1864 where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 1865 length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393. 1866 */ 1867 /* Construct vertices */ 1868 ierr = PetscCalloc1(numVerts * embedDim, &coordsIn);CHKERRQ(ierr); 1869 if (!rank) { 1870 for (p = 0, i = 0; p < embedDim; ++p) { 1871 for (s[1] = -1; s[1] < 2; s[1] += 2) { 1872 for (s[2] = -1; s[2] < 2; s[2] += 2) { 1873 for (d = 0; d < embedDim; ++d) coordsIn[i*embedDim+d] = s[(d+p)%embedDim]*vertex[(d+p)%embedDim]; 1874 ++i; 1875 } 1876 } 1877 } 1878 } 1879 /* Construct graph */ 1880 ierr = PetscCalloc1(numVerts * numVerts, &graph);CHKERRQ(ierr); 1881 for (i = 0; i < numVerts; ++i) { 1882 for (j = 0, k = 0; j < numVerts; ++j) { 1883 if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i*embedDim], &coordsIn[j*embedDim]) - edgeLen) < PETSC_SMALL) {graph[i*numVerts+j] = 1; ++k;} 1884 } 1885 if (k != degree) SETERRQ3(comm, PETSC_ERR_PLIB, "Invalid icosahedron, vertex %D degree %D != %D", i, k, degree); 1886 } 1887 /* Build Topology */ 1888 ierr = DMPlexSetChart(*dm, 0, numCells+numVerts);CHKERRQ(ierr); 1889 for (c = 0; c < numCells; c++) { 1890 ierr = DMPlexSetConeSize(*dm, c, embedDim);CHKERRQ(ierr); 1891 } 1892 ierr = DMSetUp(*dm);CHKERRQ(ierr); /* Allocate space for cones */ 1893 /* Cells */ 1894 for (i = 0, c = 0; i < numVerts; ++i) { 1895 for (j = 0; j < i; ++j) { 1896 for (k = 0; k < j; ++k) { 1897 if (graph[i*numVerts+j] && graph[j*numVerts+k] && graph[k*numVerts+i]) { 1898 cone[0] = firstVertex+i; cone[1] = firstVertex+j; cone[2] = firstVertex+k; 1899 /* Check orientation */ 1900 { 1901 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}}}; 1902 PetscReal normal[3]; 1903 PetscInt e, f; 1904 1905 for (d = 0; d < embedDim; ++d) { 1906 normal[d] = 0.0; 1907 for (e = 0; e < embedDim; ++e) { 1908 for (f = 0; f < embedDim; ++f) { 1909 normal[d] += epsilon[d][e][f]*(coordsIn[j*embedDim+e] - coordsIn[i*embedDim+e])*(coordsIn[k*embedDim+f] - coordsIn[i*embedDim+f]); 1910 } 1911 } 1912 } 1913 if (DotReal(embedDim, normal, &coordsIn[i*embedDim]) < 0) {PetscInt tmp = cone[1]; cone[1] = cone[2]; cone[2] = tmp;} 1914 } 1915 ierr = DMPlexSetCone(*dm, c++, cone);CHKERRQ(ierr); 1916 } 1917 } 1918 } 1919 } 1920 ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr); 1921 ierr = DMPlexStratify(*dm);CHKERRQ(ierr); 1922 ierr = PetscFree(graph);CHKERRQ(ierr); 1923 /* Interpolate mesh */ 1924 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 1925 ierr = DMDestroy(dm);CHKERRQ(ierr); 1926 *dm = idm; 1927 } else { 1928 /* 1929 12-21--13 1930 | | 1931 25 4 24 1932 | | 1933 12-25--9-16--8-24--13 1934 | | | | 1935 23 5 17 0 15 3 22 1936 | | | | 1937 10-20--6-14--7-19--11 1938 | | 1939 20 1 19 1940 | | 1941 10-18--11 1942 | | 1943 23 2 22 1944 | | 1945 12-21--13 1946 */ 1947 PetscInt cone[4], ornt[4]; 1948 1949 numCells = !rank ? 6 : 0; 1950 numEdges = !rank ? 12 : 0; 1951 numVerts = !rank ? 8 : 0; 1952 firstVertex = numCells; 1953 firstEdge = numCells + numVerts; 1954 /* Build Topology */ 1955 ierr = DMPlexSetChart(*dm, 0, numCells+numEdges+numVerts);CHKERRQ(ierr); 1956 for (c = 0; c < numCells; c++) { 1957 ierr = DMPlexSetConeSize(*dm, c, 4);CHKERRQ(ierr); 1958 } 1959 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 1960 ierr = DMPlexSetConeSize(*dm, e, 2);CHKERRQ(ierr); 1961 } 1962 ierr = DMSetUp(*dm);CHKERRQ(ierr); /* Allocate space for cones */ 1963 if (!rank) { 1964 /* Cell 0 */ 1965 cone[0] = 14; cone[1] = 15; cone[2] = 16; cone[3] = 17; 1966 ierr = DMPlexSetCone(*dm, 0, cone);CHKERRQ(ierr); 1967 ornt[0] = 0; ornt[1] = 0; ornt[2] = 0; ornt[3] = 0; 1968 ierr = DMPlexSetConeOrientation(*dm, 0, ornt);CHKERRQ(ierr); 1969 /* Cell 1 */ 1970 cone[0] = 18; cone[1] = 19; cone[2] = 14; cone[3] = 20; 1971 ierr = DMPlexSetCone(*dm, 1, cone);CHKERRQ(ierr); 1972 ornt[0] = 0; ornt[1] = 0; ornt[2] = -2; ornt[3] = 0; 1973 ierr = DMPlexSetConeOrientation(*dm, 1, ornt);CHKERRQ(ierr); 1974 /* Cell 2 */ 1975 cone[0] = 21; cone[1] = 22; cone[2] = 18; cone[3] = 23; 1976 ierr = DMPlexSetCone(*dm, 2, cone);CHKERRQ(ierr); 1977 ornt[0] = 0; ornt[1] = 0; ornt[2] = -2; ornt[3] = 0; 1978 ierr = DMPlexSetConeOrientation(*dm, 2, ornt);CHKERRQ(ierr); 1979 /* Cell 3 */ 1980 cone[0] = 19; cone[1] = 22; cone[2] = 24; cone[3] = 15; 1981 ierr = DMPlexSetCone(*dm, 3, cone);CHKERRQ(ierr); 1982 ornt[0] = -2; ornt[1] = -2; ornt[2] = 0; ornt[3] = -2; 1983 ierr = DMPlexSetConeOrientation(*dm, 3, ornt);CHKERRQ(ierr); 1984 /* Cell 4 */ 1985 cone[0] = 16; cone[1] = 24; cone[2] = 21; cone[3] = 25; 1986 ierr = DMPlexSetCone(*dm, 4, cone);CHKERRQ(ierr); 1987 ornt[0] = -2; ornt[1] = -2; ornt[2] = -2; ornt[3] = 0; 1988 ierr = DMPlexSetConeOrientation(*dm, 4, ornt);CHKERRQ(ierr); 1989 /* Cell 5 */ 1990 cone[0] = 20; cone[1] = 17; cone[2] = 25; cone[3] = 23; 1991 ierr = DMPlexSetCone(*dm, 5, cone);CHKERRQ(ierr); 1992 ornt[0] = -2; ornt[1] = -2; ornt[2] = -2; ornt[3] = -2; 1993 ierr = DMPlexSetConeOrientation(*dm, 5, ornt);CHKERRQ(ierr); 1994 /* Edges */ 1995 cone[0] = 6; cone[1] = 7; 1996 ierr = DMPlexSetCone(*dm, 14, cone);CHKERRQ(ierr); 1997 cone[0] = 7; cone[1] = 8; 1998 ierr = DMPlexSetCone(*dm, 15, cone);CHKERRQ(ierr); 1999 cone[0] = 8; cone[1] = 9; 2000 ierr = DMPlexSetCone(*dm, 16, cone);CHKERRQ(ierr); 2001 cone[0] = 9; cone[1] = 6; 2002 ierr = DMPlexSetCone(*dm, 17, cone);CHKERRQ(ierr); 2003 cone[0] = 10; cone[1] = 11; 2004 ierr = DMPlexSetCone(*dm, 18, cone);CHKERRQ(ierr); 2005 cone[0] = 11; cone[1] = 7; 2006 ierr = DMPlexSetCone(*dm, 19, cone);CHKERRQ(ierr); 2007 cone[0] = 6; cone[1] = 10; 2008 ierr = DMPlexSetCone(*dm, 20, cone);CHKERRQ(ierr); 2009 cone[0] = 12; cone[1] = 13; 2010 ierr = DMPlexSetCone(*dm, 21, cone);CHKERRQ(ierr); 2011 cone[0] = 13; cone[1] = 11; 2012 ierr = DMPlexSetCone(*dm, 22, cone);CHKERRQ(ierr); 2013 cone[0] = 10; cone[1] = 12; 2014 ierr = DMPlexSetCone(*dm, 23, cone);CHKERRQ(ierr); 2015 cone[0] = 13; cone[1] = 8; 2016 ierr = DMPlexSetCone(*dm, 24, cone);CHKERRQ(ierr); 2017 cone[0] = 12; cone[1] = 9; 2018 ierr = DMPlexSetCone(*dm, 25, cone);CHKERRQ(ierr); 2019 } 2020 ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr); 2021 ierr = DMPlexStratify(*dm);CHKERRQ(ierr); 2022 /* Build coordinates */ 2023 ierr = PetscCalloc1(numVerts * embedDim, &coordsIn);CHKERRQ(ierr); 2024 if (!rank) { 2025 coordsIn[0*embedDim+0] = -R; coordsIn[0*embedDim+1] = R; coordsIn[0*embedDim+2] = -R; 2026 coordsIn[1*embedDim+0] = R; coordsIn[1*embedDim+1] = R; coordsIn[1*embedDim+2] = -R; 2027 coordsIn[2*embedDim+0] = R; coordsIn[2*embedDim+1] = -R; coordsIn[2*embedDim+2] = -R; 2028 coordsIn[3*embedDim+0] = -R; coordsIn[3*embedDim+1] = -R; coordsIn[3*embedDim+2] = -R; 2029 coordsIn[4*embedDim+0] = -R; coordsIn[4*embedDim+1] = R; coordsIn[4*embedDim+2] = R; 2030 coordsIn[5*embedDim+0] = R; coordsIn[5*embedDim+1] = R; coordsIn[5*embedDim+2] = R; 2031 coordsIn[6*embedDim+0] = -R; coordsIn[6*embedDim+1] = -R; coordsIn[6*embedDim+2] = R; 2032 coordsIn[7*embedDim+0] = R; coordsIn[7*embedDim+1] = -R; coordsIn[7*embedDim+2] = R; 2033 } 2034 } 2035 break; 2036 case 3: 2037 if (simplex) { 2038 DM idm; 2039 const PetscReal edgeLen = 1.0/PETSC_PHI; 2040 PetscReal vertexA[4] = {0.5, 0.5, 0.5, 0.5}; 2041 PetscReal vertexB[4] = {1.0, 0.0, 0.0, 0.0}; 2042 PetscReal vertexC[4] = {0.5, 0.5*PETSC_PHI, 0.5/PETSC_PHI, 0.0}; 2043 const PetscInt degree = 12; 2044 PetscInt s[4] = {1, 1, 1}; 2045 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}, 2046 {2, 0, 1, 3}, {2, 1, 3, 0}, {2, 3, 0, 1}, {3, 0, 2, 1}, {3, 1, 0, 2}, {3, 2, 1, 0}}; 2047 PetscInt cone[4]; 2048 PetscInt *graph, p, i, j, k, l; 2049 2050 vertexA[0] *= R; vertexA[1] *= R; vertexA[2] *= R; vertexA[3] *= R; 2051 vertexB[0] *= R; vertexB[1] *= R; vertexB[2] *= R; vertexB[3] *= R; 2052 vertexC[0] *= R; vertexC[1] *= R; vertexC[2] *= R; vertexC[3] *= R; 2053 numCells = !rank ? 600 : 0; 2054 numVerts = !rank ? 120 : 0; 2055 firstVertex = numCells; 2056 /* Use the 600-cell, which for a unit sphere has coordinates which are 2057 2058 1/2 (\pm 1, \pm 1, \pm 1, \pm 1) 16 2059 (\pm 1, 0, 0, 0) all cyclic permutations 8 2060 1/2 (\pm 1, \pm phi, \pm 1/phi, 0) all even permutations 96 2061 2062 where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 2063 length is then given by 1/\phi = 0.61803. 2064 2065 http://buzzard.pugetsound.edu/sage-practice/ch03s03.html 2066 http://mathworld.wolfram.com/600-Cell.html 2067 */ 2068 /* Construct vertices */ 2069 ierr = PetscCalloc1(numVerts * embedDim, &coordsIn);CHKERRQ(ierr); 2070 i = 0; 2071 if (!rank) { 2072 for (s[0] = -1; s[0] < 2; s[0] += 2) { 2073 for (s[1] = -1; s[1] < 2; s[1] += 2) { 2074 for (s[2] = -1; s[2] < 2; s[2] += 2) { 2075 for (s[3] = -1; s[3] < 2; s[3] += 2) { 2076 for (d = 0; d < embedDim; ++d) coordsIn[i*embedDim+d] = s[d]*vertexA[d]; 2077 ++i; 2078 } 2079 } 2080 } 2081 } 2082 for (p = 0; p < embedDim; ++p) { 2083 s[1] = s[2] = s[3] = 1; 2084 for (s[0] = -1; s[0] < 2; s[0] += 2) { 2085 for (d = 0; d < embedDim; ++d) coordsIn[i*embedDim+d] = s[(d+p)%embedDim]*vertexB[(d+p)%embedDim]; 2086 ++i; 2087 } 2088 } 2089 for (p = 0; p < 12; ++p) { 2090 s[3] = 1; 2091 for (s[0] = -1; s[0] < 2; s[0] += 2) { 2092 for (s[1] = -1; s[1] < 2; s[1] += 2) { 2093 for (s[2] = -1; s[2] < 2; s[2] += 2) { 2094 for (d = 0; d < embedDim; ++d) coordsIn[i*embedDim+d] = s[evenPerm[p][d]]*vertexC[evenPerm[p][d]]; 2095 ++i; 2096 } 2097 } 2098 } 2099 } 2100 } 2101 if (i != numVerts) SETERRQ2(comm, PETSC_ERR_PLIB, "Invalid 600-cell, vertices %D != %D", i, numVerts); 2102 /* Construct graph */ 2103 ierr = PetscCalloc1(numVerts * numVerts, &graph);CHKERRQ(ierr); 2104 for (i = 0; i < numVerts; ++i) { 2105 for (j = 0, k = 0; j < numVerts; ++j) { 2106 if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i*embedDim], &coordsIn[j*embedDim]) - edgeLen) < PETSC_SMALL) {graph[i*numVerts+j] = 1; ++k;} 2107 } 2108 if (k != degree) SETERRQ3(comm, PETSC_ERR_PLIB, "Invalid 600-cell, vertex %D degree %D != %D", i, k, degree); 2109 } 2110 /* Build Topology */ 2111 ierr = DMPlexSetChart(*dm, 0, numCells+numVerts);CHKERRQ(ierr); 2112 for (c = 0; c < numCells; c++) { 2113 ierr = DMPlexSetConeSize(*dm, c, embedDim);CHKERRQ(ierr); 2114 } 2115 ierr = DMSetUp(*dm);CHKERRQ(ierr); /* Allocate space for cones */ 2116 /* Cells */ 2117 if (!rank) { 2118 for (i = 0, c = 0; i < numVerts; ++i) { 2119 for (j = 0; j < i; ++j) { 2120 for (k = 0; k < j; ++k) { 2121 for (l = 0; l < k; ++l) { 2122 if (graph[i*numVerts+j] && graph[j*numVerts+k] && graph[k*numVerts+i] && 2123 graph[l*numVerts+i] && graph[l*numVerts+j] && graph[l*numVerts+k]) { 2124 cone[0] = firstVertex+i; cone[1] = firstVertex+j; cone[2] = firstVertex+k; cone[3] = firstVertex+l; 2125 /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */ 2126 { 2127 const PetscInt epsilon[4][4][4][4] = {{{{0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}}, 2128 {{0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 1}, { 0, 0, -1, 0}}, 2129 {{0, 0, 0, 0}, { 0, 0, 0, -1}, { 0, 0, 0, 0}, { 0, 1, 0, 0}}, 2130 {{0, 0, 0, 0}, { 0, 0, 1, 0}, { 0, -1, 0, 0}, { 0, 0, 0, 0}}}, 2131 2132 {{{0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, -1}, { 0, 0, 1, 0}}, 2133 {{0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}}, 2134 {{0, 0, 0, 1}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, {-1, 0, 0, 0}}, 2135 {{0, 0, -1, 0}, { 0, 0, 0, 0}, { 1, 0, 0, 0}, { 0, 0, 0, 0}}}, 2136 2137 {{{0, 0, 0, 0}, { 0, 0, 0, 1}, { 0, 0, 0, 0}, { 0, -1, 0, 0}}, 2138 {{0, 0, 0, -1}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 1, 0, 0, 0}}, 2139 {{0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}}, 2140 {{0, 1, 0, 0}, {-1, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}}}, 2141 2142 {{{0, 0, 0, 0}, { 0, 0, -1, 0}, { 0, 1, 0, 0}, { 0, 0, 0, 0}}, 2143 {{0, 0, 1, 0}, { 0, 0, 0, 0}, {-1, 0, 0, 0}, { 0, 0, 0, 0}}, 2144 {{0, -1, 0, 0}, { 1, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}}, 2145 {{0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}}}}; 2146 PetscReal normal[4]; 2147 PetscInt e, f, g; 2148 2149 for (d = 0; d < embedDim; ++d) { 2150 normal[d] = 0.0; 2151 for (e = 0; e < embedDim; ++e) { 2152 for (f = 0; f < embedDim; ++f) { 2153 for (g = 0; g < embedDim; ++g) { 2154 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]); 2155 } 2156 } 2157 } 2158 } 2159 if (DotReal(embedDim, normal, &coordsIn[i*embedDim]) < 0) {PetscInt tmp = cone[1]; cone[1] = cone[2]; cone[2] = tmp;} 2160 } 2161 ierr = DMPlexSetCone(*dm, c++, cone);CHKERRQ(ierr); 2162 } 2163 } 2164 } 2165 } 2166 } 2167 } 2168 ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr); 2169 ierr = DMPlexStratify(*dm);CHKERRQ(ierr); 2170 ierr = PetscFree(graph);CHKERRQ(ierr); 2171 /* Interpolate mesh */ 2172 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 2173 ierr = DMDestroy(dm);CHKERRQ(ierr); 2174 *dm = idm; 2175 break; 2176 } 2177 default: SETERRQ1(comm, PETSC_ERR_SUP, "Unsupported dimension for sphere: %D", dim); 2178 } 2179 /* Create coordinates */ 2180 ierr = DMGetCoordinateSection(*dm, &coordSection);CHKERRQ(ierr); 2181 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 2182 ierr = PetscSectionSetFieldComponents(coordSection, 0, embedDim);CHKERRQ(ierr); 2183 ierr = PetscSectionSetChart(coordSection, firstVertex, firstVertex+numVerts);CHKERRQ(ierr); 2184 for (v = firstVertex; v < firstVertex+numVerts; ++v) { 2185 ierr = PetscSectionSetDof(coordSection, v, embedDim);CHKERRQ(ierr); 2186 ierr = PetscSectionSetFieldDof(coordSection, v, 0, embedDim);CHKERRQ(ierr); 2187 } 2188 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 2189 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 2190 ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr); 2191 ierr = VecSetBlockSize(coordinates, embedDim);CHKERRQ(ierr); 2192 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 2193 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 2194 ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr); 2195 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 2196 for (v = 0; v < numVerts; ++v) for (d = 0; d < embedDim; ++d) {coords[v*embedDim+d] = coordsIn[v*embedDim+d];} 2197 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 2198 ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr); 2199 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 2200 ierr = PetscFree(coordsIn);CHKERRQ(ierr); 2201 /* Create coordinate function space */ 2202 { 2203 DM cdm; 2204 PetscDS cds; 2205 PetscFE fe; 2206 PetscScalar radius = R; 2207 PetscInt dT, dE; 2208 2209 ierr = DMGetCoordinateDM(*dm, &cdm);CHKERRQ(ierr); 2210 ierr = DMGetDimension(*dm, &dT);CHKERRQ(ierr); 2211 ierr = DMGetCoordinateDim(*dm, &dE);CHKERRQ(ierr); 2212 ierr = PetscFECreateLagrange(PETSC_COMM_SELF, dT, dE, simplex, 1, -1, &fe);CHKERRQ(ierr); 2213 ierr = DMSetField(cdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 2214 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 2215 ierr = DMCreateDS(cdm);CHKERRQ(ierr); 2216 2217 ierr = DMGetDS(cdm, &cds);CHKERRQ(ierr); 2218 ierr = PetscDSSetConstants(cds, 1, &radius);CHKERRQ(ierr); 2219 } 2220 ((DM_Plex *) (*dm)->data)->coordFunc = snapToSphere; 2221 PetscFunctionReturn(0); 2222 } 2223 2224 /*@ 2225 DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d. 2226 2227 Collective 2228 2229 Input Parameters: 2230 + comm - The communicator for the DM object 2231 . dim - The dimension 2232 - R - The radius 2233 2234 Output Parameter: 2235 . dm - The DM object 2236 2237 Options Database Keys: 2238 - bd_dm_refine - This will refine the surface mesh preserving the sphere geometry 2239 2240 Level: beginner 2241 2242 .seealso: DMPlexCreateSphereMesh(), DMPlexCreateBoxMesh(), DMSetType(), DMCreate() 2243 @*/ 2244 PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm) 2245 { 2246 DM sdm; 2247 DMLabel bdlabel; 2248 PetscErrorCode ierr; 2249 2250 PetscFunctionBegin; 2251 ierr = DMPlexCreateSphereMesh(comm, dim-1, PETSC_TRUE, R, &sdm);CHKERRQ(ierr); 2252 ierr = PetscObjectSetOptionsPrefix((PetscObject) sdm, "bd_");CHKERRQ(ierr); 2253 ierr = DMSetFromOptions(sdm);CHKERRQ(ierr); 2254 ierr = DMPlexGenerate(sdm, NULL, PETSC_TRUE, dm);CHKERRQ(ierr); 2255 ierr = DMDestroy(&sdm);CHKERRQ(ierr); 2256 ierr = DMCreateLabel(*dm, "marker");CHKERRQ(ierr); 2257 ierr = DMGetLabel(*dm, "marker", &bdlabel);CHKERRQ(ierr); 2258 ierr = DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel);CHKERRQ(ierr); 2259 ierr = DMPlexLabelComplete(*dm, bdlabel);CHKERRQ(ierr); 2260 PetscFunctionReturn(0); 2261 } 2262 2263 /* External function declarations here */ 2264 extern PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling); 2265 extern PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat); 2266 extern PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mat); 2267 extern PetscErrorCode DMCreateLocalSection_Plex(DM dm); 2268 extern PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm); 2269 extern PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J); 2270 extern PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm); 2271 extern PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field); 2272 PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm); 2273 extern PetscErrorCode DMSetUp_Plex(DM dm); 2274 extern PetscErrorCode DMDestroy_Plex(DM dm); 2275 extern PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer); 2276 extern PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer); 2277 extern PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm); 2278 extern PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm); 2279 static PetscErrorCode DMInitialize_Plex(DM dm); 2280 2281 /* Replace dm with the contents of dmNew 2282 - Share the DM_Plex structure 2283 - Share the coordinates 2284 - Share the SF 2285 */ 2286 static PetscErrorCode DMPlexReplace_Static(DM dm, DM dmNew) 2287 { 2288 PetscSF sf; 2289 DM coordDM, coarseDM; 2290 DMField coordField; 2291 Vec coords; 2292 PetscBool isper; 2293 const PetscReal *maxCell, *L; 2294 const DMBoundaryType *bd; 2295 PetscErrorCode ierr; 2296 2297 PetscFunctionBegin; 2298 ierr = DMGetPointSF(dmNew, &sf);CHKERRQ(ierr); 2299 ierr = DMSetPointSF(dm, sf);CHKERRQ(ierr); 2300 ierr = DMGetCoordinateDM(dmNew, &coordDM);CHKERRQ(ierr); 2301 ierr = DMGetCoordinatesLocal(dmNew, &coords);CHKERRQ(ierr); 2302 ierr = DMGetCoordinateField(dmNew, &coordField);CHKERRQ(ierr); 2303 ierr = DMSetCoordinateDM(dm, coordDM);CHKERRQ(ierr); 2304 ierr = DMSetCoordinatesLocal(dm, coords);CHKERRQ(ierr); 2305 ierr = DMSetCoordinateField(dm, coordField);CHKERRQ(ierr); 2306 ierr = DMGetPeriodicity(dm, &isper, &maxCell, &L, &bd);CHKERRQ(ierr); 2307 ierr = DMSetPeriodicity(dmNew, isper, maxCell, L, bd);CHKERRQ(ierr); 2308 ierr = DMDestroy_Plex(dm);CHKERRQ(ierr); 2309 ierr = DMInitialize_Plex(dm);CHKERRQ(ierr); 2310 dm->data = dmNew->data; 2311 ((DM_Plex *) dmNew->data)->refct++; 2312 ierr = DMDestroyLabelLinkList_Internal(dm);CHKERRQ(ierr); 2313 ierr = DMCopyLabels(dmNew, dm, PETSC_OWN_POINTER, PETSC_TRUE);CHKERRQ(ierr); 2314 ierr = DMGetCoarseDM(dmNew,&coarseDM);CHKERRQ(ierr); 2315 ierr = DMSetCoarseDM(dm,coarseDM);CHKERRQ(ierr); 2316 PetscFunctionReturn(0); 2317 } 2318 2319 /* Swap dm with the contents of dmNew 2320 - Swap the DM_Plex structure 2321 - Swap the coordinates 2322 - Swap the point PetscSF 2323 */ 2324 static PetscErrorCode DMPlexSwap_Static(DM dmA, DM dmB) 2325 { 2326 DM coordDMA, coordDMB; 2327 Vec coordsA, coordsB; 2328 PetscSF sfA, sfB; 2329 void *tmp; 2330 DMLabelLink listTmp; 2331 DMLabel depthTmp; 2332 PetscInt tmpI; 2333 PetscErrorCode ierr; 2334 2335 PetscFunctionBegin; 2336 ierr = DMGetPointSF(dmA, &sfA);CHKERRQ(ierr); 2337 ierr = DMGetPointSF(dmB, &sfB);CHKERRQ(ierr); 2338 ierr = PetscObjectReference((PetscObject) sfA);CHKERRQ(ierr); 2339 ierr = DMSetPointSF(dmA, sfB);CHKERRQ(ierr); 2340 ierr = DMSetPointSF(dmB, sfA);CHKERRQ(ierr); 2341 ierr = PetscObjectDereference((PetscObject) sfA);CHKERRQ(ierr); 2342 2343 ierr = DMGetCoordinateDM(dmA, &coordDMA);CHKERRQ(ierr); 2344 ierr = DMGetCoordinateDM(dmB, &coordDMB);CHKERRQ(ierr); 2345 ierr = PetscObjectReference((PetscObject) coordDMA);CHKERRQ(ierr); 2346 ierr = DMSetCoordinateDM(dmA, coordDMB);CHKERRQ(ierr); 2347 ierr = DMSetCoordinateDM(dmB, coordDMA);CHKERRQ(ierr); 2348 ierr = PetscObjectDereference((PetscObject) coordDMA);CHKERRQ(ierr); 2349 2350 ierr = DMGetCoordinatesLocal(dmA, &coordsA);CHKERRQ(ierr); 2351 ierr = DMGetCoordinatesLocal(dmB, &coordsB);CHKERRQ(ierr); 2352 ierr = PetscObjectReference((PetscObject) coordsA);CHKERRQ(ierr); 2353 ierr = DMSetCoordinatesLocal(dmA, coordsB);CHKERRQ(ierr); 2354 ierr = DMSetCoordinatesLocal(dmB, coordsA);CHKERRQ(ierr); 2355 ierr = PetscObjectDereference((PetscObject) coordsA);CHKERRQ(ierr); 2356 2357 tmp = dmA->data; 2358 dmA->data = dmB->data; 2359 dmB->data = tmp; 2360 listTmp = dmA->labels; 2361 dmA->labels = dmB->labels; 2362 dmB->labels = listTmp; 2363 depthTmp = dmA->depthLabel; 2364 dmA->depthLabel = dmB->depthLabel; 2365 dmB->depthLabel = depthTmp; 2366 depthTmp = dmA->celltypeLabel; 2367 dmA->celltypeLabel = dmB->celltypeLabel; 2368 dmB->celltypeLabel = depthTmp; 2369 tmpI = dmA->levelup; 2370 dmA->levelup = dmB->levelup; 2371 dmB->levelup = tmpI; 2372 PetscFunctionReturn(0); 2373 } 2374 2375 PetscErrorCode DMSetFromOptions_NonRefinement_Plex(PetscOptionItems *PetscOptionsObject,DM dm) 2376 { 2377 DM_Plex *mesh = (DM_Plex*) dm->data; 2378 PetscBool flg; 2379 PetscErrorCode ierr; 2380 2381 PetscFunctionBegin; 2382 /* Handle viewing */ 2383 ierr = PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL);CHKERRQ(ierr); 2384 ierr = PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL,0);CHKERRQ(ierr); 2385 ierr = PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL);CHKERRQ(ierr); 2386 ierr = PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL,0);CHKERRQ(ierr); 2387 ierr = DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg);CHKERRQ(ierr); 2388 if (flg) {ierr = PetscLogDefaultBegin();CHKERRQ(ierr);} 2389 /* Point Location */ 2390 ierr = PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL);CHKERRQ(ierr); 2391 /* Partitioning and distribution */ 2392 ierr = PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL);CHKERRQ(ierr); 2393 /* Generation and remeshing */ 2394 ierr = PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL);CHKERRQ(ierr); 2395 /* Projection behavior */ 2396 ierr = PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maxmimum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL,0);CHKERRQ(ierr); 2397 ierr = PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL);CHKERRQ(ierr); 2398 ierr = PetscOptionsEnum("-dm_plex_cell_refiner", "Strategy for cell refinment", "ex40.c", DMPlexCellRefinerTypes, (PetscEnum) mesh->cellRefiner, (PetscEnum *) &mesh->cellRefiner, NULL);CHKERRQ(ierr); 2399 /* Checking structure */ 2400 { 2401 PetscBool flg = PETSC_FALSE, flg2 = PETSC_FALSE, all = PETSC_FALSE; 2402 2403 ierr = PetscOptionsBool("-dm_plex_check_all", "Perform all checks", NULL, PETSC_FALSE, &all, &flg2);CHKERRQ(ierr); 2404 ierr = PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2);CHKERRQ(ierr); 2405 if (all || (flg && flg2)) {ierr = DMPlexCheckSymmetry(dm);CHKERRQ(ierr);} 2406 ierr = PetscOptionsBool("-dm_plex_check_skeleton", "Check that each cell has the correct number of vertices (only for homogeneous simplex or tensor meshes)", "DMPlexCheckSkeleton", PETSC_FALSE, &flg, &flg2);CHKERRQ(ierr); 2407 if (all || (flg && flg2)) {ierr = DMPlexCheckSkeleton(dm, 0);CHKERRQ(ierr);} 2408 ierr = PetscOptionsBool("-dm_plex_check_faces", "Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type", "DMPlexCheckFaces", PETSC_FALSE, &flg, &flg2);CHKERRQ(ierr); 2409 if (all || (flg && flg2)) {ierr = DMPlexCheckFaces(dm, 0);CHKERRQ(ierr);} 2410 ierr = PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2);CHKERRQ(ierr); 2411 if (all || (flg && flg2)) {ierr = DMPlexCheckGeometry(dm);CHKERRQ(ierr);} 2412 ierr = PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2);CHKERRQ(ierr); 2413 if (all || (flg && flg2)) {ierr = DMPlexCheckPointSF(dm);CHKERRQ(ierr);} 2414 ierr = PetscOptionsBool("-dm_plex_check_interface_cones", "Check points on inter-partition interfaces have conforming order of cone points", "DMPlexCheckInterfaceCones", PETSC_FALSE, &flg, &flg2);CHKERRQ(ierr); 2415 if (all || (flg && flg2)) {ierr = DMPlexCheckInterfaceCones(dm);CHKERRQ(ierr);} 2416 ierr = PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2);CHKERRQ(ierr); 2417 if (flg && flg2) {ierr = DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE);CHKERRQ(ierr);} 2418 } 2419 2420 ierr = PetscPartitionerSetFromOptions(mesh->partitioner);CHKERRQ(ierr); 2421 PetscFunctionReturn(0); 2422 } 2423 2424 static PetscErrorCode DMSetFromOptions_Plex(PetscOptionItems *PetscOptionsObject,DM dm) 2425 { 2426 PetscReal volume = -1.0; 2427 PetscInt prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0; 2428 PetscBool uniformOrig, uniform = PETSC_TRUE, distribute = PETSC_FALSE, isHierarchy, flg; 2429 PetscErrorCode ierr; 2430 2431 PetscFunctionBegin; 2432 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2433 ierr = PetscOptionsHead(PetscOptionsObject,"DMPlex Options");CHKERRQ(ierr); 2434 /* Handle DMPlex refinement before distribution */ 2435 ierr = DMPlexGetRefinementUniform(dm, &uniformOrig);CHKERRQ(ierr); 2436 ierr = PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg);CHKERRQ(ierr); 2437 if (flg) {ierr = DMPlexSetRefinementUniform(dm, uniform);CHKERRQ(ierr);} 2438 ierr = PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg);CHKERRQ(ierr); 2439 if (flg) {ierr = DMPlexSetRefinementLimit(dm, volume);CHKERRQ(ierr);} 2440 ierr = PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL,0);CHKERRQ(ierr); 2441 for (r = 0; r < prerefine; ++r) { 2442 DM rdm; 2443 PetscPointFunc coordFunc = ((DM_Plex*) dm->data)->coordFunc; 2444 2445 ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm);CHKERRQ(ierr); 2446 ierr = DMRefine(dm, PetscObjectComm((PetscObject) dm), &rdm);CHKERRQ(ierr); 2447 /* Total hack since we do not pass in a pointer */ 2448 ierr = DMPlexReplace_Static(dm, rdm);CHKERRQ(ierr); 2449 ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm);CHKERRQ(ierr); 2450 if (coordFunc) { 2451 ierr = DMPlexRemapGeometry(dm, 0.0, coordFunc);CHKERRQ(ierr); 2452 ((DM_Plex*) dm->data)->coordFunc = coordFunc; 2453 } 2454 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 2455 } 2456 ierr = DMPlexSetRefinementUniform(dm, uniformOrig);CHKERRQ(ierr); 2457 /* Handle DMPlex distribution */ 2458 ierr = PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMCreate", distribute, &distribute, NULL);CHKERRQ(ierr); 2459 ierr = PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMCreate", overlap, &overlap, NULL, 0);CHKERRQ(ierr); 2460 if (distribute) { 2461 DM pdm = NULL; 2462 PetscPartitioner part; 2463 2464 ierr = DMPlexGetPartitioner(dm, &part);CHKERRQ(ierr); 2465 ierr = PetscPartitionerSetFromOptions(part);CHKERRQ(ierr); 2466 ierr = DMPlexDistribute(dm, overlap, NULL, &pdm);CHKERRQ(ierr); 2467 if (pdm) { 2468 ierr = DMPlexReplace_Static(dm, pdm);CHKERRQ(ierr); 2469 ierr = DMDestroy(&pdm);CHKERRQ(ierr); 2470 } 2471 } 2472 /* Handle DMPlex refinement */ 2473 ierr = PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL,0);CHKERRQ(ierr); 2474 ierr = PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy,0);CHKERRQ(ierr); 2475 if (refine) {ierr = DMPlexSetRefinementUniform(dm, PETSC_TRUE);CHKERRQ(ierr);} 2476 if (refine && isHierarchy) { 2477 DM *dms, coarseDM; 2478 2479 ierr = DMGetCoarseDM(dm, &coarseDM);CHKERRQ(ierr); 2480 ierr = PetscObjectReference((PetscObject)coarseDM);CHKERRQ(ierr); 2481 ierr = PetscMalloc1(refine,&dms);CHKERRQ(ierr); 2482 ierr = DMRefineHierarchy(dm, refine, dms);CHKERRQ(ierr); 2483 /* Total hack since we do not pass in a pointer */ 2484 ierr = DMPlexSwap_Static(dm, dms[refine-1]);CHKERRQ(ierr); 2485 if (refine == 1) { 2486 ierr = DMSetCoarseDM(dm, dms[0]);CHKERRQ(ierr); 2487 ierr = DMPlexSetRegularRefinement(dm, PETSC_TRUE);CHKERRQ(ierr); 2488 } else { 2489 ierr = DMSetCoarseDM(dm, dms[refine-2]);CHKERRQ(ierr); 2490 ierr = DMPlexSetRegularRefinement(dm, PETSC_TRUE);CHKERRQ(ierr); 2491 ierr = DMSetCoarseDM(dms[0], dms[refine-1]);CHKERRQ(ierr); 2492 ierr = DMPlexSetRegularRefinement(dms[0], PETSC_TRUE);CHKERRQ(ierr); 2493 } 2494 ierr = DMSetCoarseDM(dms[refine-1], coarseDM);CHKERRQ(ierr); 2495 ierr = PetscObjectDereference((PetscObject)coarseDM);CHKERRQ(ierr); 2496 /* Free DMs */ 2497 for (r = 0; r < refine; ++r) { 2498 ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dms[r]);CHKERRQ(ierr); 2499 ierr = DMDestroy(&dms[r]);CHKERRQ(ierr); 2500 } 2501 ierr = PetscFree(dms);CHKERRQ(ierr); 2502 } else { 2503 for (r = 0; r < refine; ++r) { 2504 DM refinedMesh; 2505 PetscPointFunc coordFunc = ((DM_Plex*) dm->data)->coordFunc; 2506 2507 ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm);CHKERRQ(ierr); 2508 ierr = DMRefine(dm, PetscObjectComm((PetscObject) dm), &refinedMesh);CHKERRQ(ierr); 2509 /* Total hack since we do not pass in a pointer */ 2510 ierr = DMPlexReplace_Static(dm, refinedMesh);CHKERRQ(ierr); 2511 ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm);CHKERRQ(ierr); 2512 if (coordFunc) { 2513 ierr = DMPlexRemapGeometry(dm, 0.0, coordFunc);CHKERRQ(ierr); 2514 ((DM_Plex*) dm->data)->coordFunc = coordFunc; 2515 } 2516 ierr = DMDestroy(&refinedMesh);CHKERRQ(ierr); 2517 } 2518 } 2519 /* Handle DMPlex coarsening */ 2520 ierr = PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL,0);CHKERRQ(ierr); 2521 ierr = PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy,0);CHKERRQ(ierr); 2522 if (coarsen && isHierarchy) { 2523 DM *dms; 2524 2525 ierr = PetscMalloc1(coarsen, &dms);CHKERRQ(ierr); 2526 ierr = DMCoarsenHierarchy(dm, coarsen, dms);CHKERRQ(ierr); 2527 /* Free DMs */ 2528 for (r = 0; r < coarsen; ++r) { 2529 ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dms[r]);CHKERRQ(ierr); 2530 ierr = DMDestroy(&dms[r]);CHKERRQ(ierr); 2531 } 2532 ierr = PetscFree(dms);CHKERRQ(ierr); 2533 } else { 2534 for (r = 0; r < coarsen; ++r) { 2535 DM coarseMesh; 2536 2537 ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm);CHKERRQ(ierr); 2538 ierr = DMCoarsen(dm, PetscObjectComm((PetscObject) dm), &coarseMesh);CHKERRQ(ierr); 2539 /* Total hack since we do not pass in a pointer */ 2540 ierr = DMPlexReplace_Static(dm, coarseMesh);CHKERRQ(ierr); 2541 ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm);CHKERRQ(ierr); 2542 ierr = DMDestroy(&coarseMesh);CHKERRQ(ierr); 2543 } 2544 } 2545 /* Handle */ 2546 ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm);CHKERRQ(ierr); 2547 ierr = PetscOptionsTail();CHKERRQ(ierr); 2548 PetscFunctionReturn(0); 2549 } 2550 2551 static PetscErrorCode DMCreateGlobalVector_Plex(DM dm,Vec *vec) 2552 { 2553 PetscErrorCode ierr; 2554 2555 PetscFunctionBegin; 2556 ierr = DMCreateGlobalVector_Section_Private(dm,vec);CHKERRQ(ierr); 2557 /* ierr = VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM);CHKERRQ(ierr); */ 2558 ierr = VecSetOperation(*vec, VECOP_VIEW, (void (*)(void)) VecView_Plex);CHKERRQ(ierr); 2559 ierr = VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void)) VecView_Plex_Native);CHKERRQ(ierr); 2560 ierr = VecSetOperation(*vec, VECOP_LOAD, (void (*)(void)) VecLoad_Plex);CHKERRQ(ierr); 2561 ierr = VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void)) VecLoad_Plex_Native);CHKERRQ(ierr); 2562 PetscFunctionReturn(0); 2563 } 2564 2565 static PetscErrorCode DMCreateLocalVector_Plex(DM dm,Vec *vec) 2566 { 2567 PetscErrorCode ierr; 2568 2569 PetscFunctionBegin; 2570 ierr = DMCreateLocalVector_Section_Private(dm,vec);CHKERRQ(ierr); 2571 ierr = VecSetOperation(*vec, VECOP_VIEW, (void (*)(void)) VecView_Plex_Local);CHKERRQ(ierr); 2572 ierr = VecSetOperation(*vec, VECOP_LOAD, (void (*)(void)) VecLoad_Plex_Local);CHKERRQ(ierr); 2573 PetscFunctionReturn(0); 2574 } 2575 2576 static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 2577 { 2578 PetscInt depth, d; 2579 PetscErrorCode ierr; 2580 2581 PetscFunctionBegin; 2582 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2583 if (depth == 1) { 2584 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 2585 if (dim == 0) {ierr = DMPlexGetDepthStratum(dm, dim, pStart, pEnd);CHKERRQ(ierr);} 2586 else if (dim == d) {ierr = DMPlexGetDepthStratum(dm, 1, pStart, pEnd);CHKERRQ(ierr);} 2587 else {*pStart = 0; *pEnd = 0;} 2588 } else { 2589 ierr = DMPlexGetDepthStratum(dm, dim, pStart, pEnd);CHKERRQ(ierr); 2590 } 2591 PetscFunctionReturn(0); 2592 } 2593 2594 static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[]) 2595 { 2596 PetscSF sf; 2597 PetscInt niranks, njranks, n; 2598 const PetscMPIInt *iranks, *jranks; 2599 DM_Plex *data = (DM_Plex*) dm->data; 2600 PetscErrorCode ierr; 2601 2602 PetscFunctionBegin; 2603 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 2604 if (!data->neighbors) { 2605 ierr = PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL);CHKERRQ(ierr); 2606 ierr = PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL);CHKERRQ(ierr); 2607 ierr = PetscMalloc1(njranks + niranks + 1, &data->neighbors);CHKERRQ(ierr); 2608 ierr = PetscArraycpy(data->neighbors + 1, jranks, njranks);CHKERRQ(ierr); 2609 ierr = PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks);CHKERRQ(ierr); 2610 n = njranks + niranks; 2611 ierr = PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1);CHKERRQ(ierr); 2612 /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */ 2613 ierr = PetscMPIIntCast(n, data->neighbors);CHKERRQ(ierr); 2614 } 2615 if (nranks) *nranks = data->neighbors[0]; 2616 if (ranks) { 2617 if (data->neighbors[0]) *ranks = data->neighbors + 1; 2618 else *ranks = NULL; 2619 } 2620 PetscFunctionReturn(0); 2621 } 2622 2623 static PetscErrorCode DMInitialize_Plex(DM dm) 2624 { 2625 PetscErrorCode ierr; 2626 2627 PetscFunctionBegin; 2628 dm->ops->view = DMView_Plex; 2629 dm->ops->load = DMLoad_Plex; 2630 dm->ops->setfromoptions = DMSetFromOptions_Plex; 2631 dm->ops->clone = DMClone_Plex; 2632 dm->ops->setup = DMSetUp_Plex; 2633 dm->ops->createlocalsection = DMCreateLocalSection_Plex; 2634 dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_Plex; 2635 dm->ops->createglobalvector = DMCreateGlobalVector_Plex; 2636 dm->ops->createlocalvector = DMCreateLocalVector_Plex; 2637 dm->ops->getlocaltoglobalmapping = NULL; 2638 dm->ops->createfieldis = NULL; 2639 dm->ops->createcoordinatedm = DMCreateCoordinateDM_Plex; 2640 dm->ops->createcoordinatefield = DMCreateCoordinateField_Plex; 2641 dm->ops->getcoloring = NULL; 2642 dm->ops->creatematrix = DMCreateMatrix_Plex; 2643 dm->ops->createinterpolation = DMCreateInterpolation_Plex; 2644 dm->ops->createmassmatrix = DMCreateMassMatrix_Plex; 2645 dm->ops->createinjection = DMCreateInjection_Plex; 2646 dm->ops->refine = DMRefine_Plex; 2647 dm->ops->coarsen = DMCoarsen_Plex; 2648 dm->ops->refinehierarchy = DMRefineHierarchy_Plex; 2649 dm->ops->coarsenhierarchy = DMCoarsenHierarchy_Plex; 2650 dm->ops->adaptlabel = DMAdaptLabel_Plex; 2651 dm->ops->adaptmetric = DMAdaptMetric_Plex; 2652 dm->ops->globaltolocalbegin = NULL; 2653 dm->ops->globaltolocalend = NULL; 2654 dm->ops->localtoglobalbegin = NULL; 2655 dm->ops->localtoglobalend = NULL; 2656 dm->ops->destroy = DMDestroy_Plex; 2657 dm->ops->createsubdm = DMCreateSubDM_Plex; 2658 dm->ops->createsuperdm = DMCreateSuperDM_Plex; 2659 dm->ops->getdimpoints = DMGetDimPoints_Plex; 2660 dm->ops->locatepoints = DMLocatePoints_Plex; 2661 dm->ops->projectfunctionlocal = DMProjectFunctionLocal_Plex; 2662 dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex; 2663 dm->ops->projectfieldlocal = DMProjectFieldLocal_Plex; 2664 dm->ops->projectfieldlabellocal = DMProjectFieldLabelLocal_Plex; 2665 dm->ops->projectbdfieldlabellocal = DMProjectBdFieldLabelLocal_Plex; 2666 dm->ops->computel2diff = DMComputeL2Diff_Plex; 2667 dm->ops->computel2gradientdiff = DMComputeL2GradientDiff_Plex; 2668 dm->ops->computel2fielddiff = DMComputeL2FieldDiff_Plex; 2669 dm->ops->getneighbors = DMGetNeighbors_Plex; 2670 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C",DMPlexInsertBoundaryValues_Plex);CHKERRQ(ierr); 2671 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertTimeDerviativeBoundaryValues_C",DMPlexInsertTimeDerivativeBoundaryValues_Plex);CHKERRQ(ierr); 2672 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",DMSetUpGLVisViewer_Plex);CHKERRQ(ierr); 2673 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C",DMCreateNeumannOverlap_Plex);CHKERRQ(ierr); 2674 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMPlexGetOverlap_C",DMPlexGetOverlap_Plex);CHKERRQ(ierr); 2675 PetscFunctionReturn(0); 2676 } 2677 2678 PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm) 2679 { 2680 DM_Plex *mesh = (DM_Plex *) dm->data; 2681 PetscErrorCode ierr; 2682 2683 PetscFunctionBegin; 2684 mesh->refct++; 2685 (*newdm)->data = mesh; 2686 ierr = PetscObjectChangeTypeName((PetscObject) *newdm, DMPLEX);CHKERRQ(ierr); 2687 ierr = DMInitialize_Plex(*newdm);CHKERRQ(ierr); 2688 PetscFunctionReturn(0); 2689 } 2690 2691 /*MC 2692 DMPLEX = "plex" - A DM object that encapsulates an unstructured mesh, or CW Complex, which can be expressed using a Hasse Diagram. 2693 In the local representation, Vecs contain all unknowns in the interior and shared boundary. This is 2694 specified by a PetscSection object. Ownership in the global representation is determined by 2695 ownership of the underlying DMPlex points. This is specified by another PetscSection object. 2696 2697 Options Database Keys: 2698 + -dm_refine_pre - Refine mesh before distribution 2699 + -dm_refine_uniform_pre - Choose uniform or generator-based refinement 2700 + -dm_refine_volume_limit_pre - Cell volume limit after pre-refinement using generator 2701 . -dm_distribute - Distribute mesh across processes 2702 . -dm_distribute_overlap - Number of cells to overlap for distribution 2703 . -dm_refine - Refine mesh after distribution 2704 . -dm_plex_hash_location - Use grid hashing for point location 2705 . -dm_plex_partition_balance - Attempt to evenly divide points on partition boundary between processes 2706 . -dm_plex_remesh_bd - Allow changes to the boundary on remeshing 2707 . -dm_plex_max_projection_height - Maxmimum mesh point height used to project locally 2708 . -dm_plex_regular_refinement - Use special nested projection algorithm for regular refinement 2709 . -dm_plex_check_all - Perform all shecks below 2710 . -dm_plex_check_symmetry - Check that the adjacency information in the mesh is symmetric 2711 . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices 2712 . -dm_plex_check_faces <celltype> - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 2713 . -dm_plex_check_geometry - Check that cells have positive volume 2714 . -dm_view :mesh.tex:ascii_latex - View the mesh in LaTeX/TikZ 2715 . -dm_plex_view_scale <num> - Scale the TikZ 2716 - -dm_plex_print_fem <num> - View FEM assembly information, such as element vectors and matrices 2717 2718 2719 Level: intermediate 2720 2721 .seealso: DMType, DMPlexCreate(), DMCreate(), DMSetType() 2722 M*/ 2723 2724 PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm) 2725 { 2726 DM_Plex *mesh; 2727 PetscInt unit; 2728 PetscErrorCode ierr; 2729 2730 PetscFunctionBegin; 2731 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2732 ierr = PetscNewLog(dm,&mesh);CHKERRQ(ierr); 2733 dm->dim = 0; 2734 dm->data = mesh; 2735 2736 mesh->refct = 1; 2737 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection);CHKERRQ(ierr); 2738 mesh->maxConeSize = 0; 2739 mesh->cones = NULL; 2740 mesh->coneOrientations = NULL; 2741 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection);CHKERRQ(ierr); 2742 mesh->maxSupportSize = 0; 2743 mesh->supports = NULL; 2744 mesh->refinementUniform = PETSC_TRUE; 2745 mesh->refinementLimit = -1.0; 2746 mesh->interpolated = DMPLEX_INTERPOLATED_INVALID; 2747 mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID; 2748 2749 mesh->facesTmp = NULL; 2750 2751 mesh->tetgenOpts = NULL; 2752 mesh->triangleOpts = NULL; 2753 ierr = PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner);CHKERRQ(ierr); 2754 mesh->remeshBd = PETSC_FALSE; 2755 2756 mesh->subpointMap = NULL; 2757 2758 for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0; 2759 2760 mesh->regularRefinement = PETSC_FALSE; 2761 mesh->depthState = -1; 2762 mesh->celltypeState = -1; 2763 mesh->globalVertexNumbers = NULL; 2764 mesh->globalCellNumbers = NULL; 2765 mesh->anchorSection = NULL; 2766 mesh->anchorIS = NULL; 2767 mesh->createanchors = NULL; 2768 mesh->computeanchormatrix = NULL; 2769 mesh->parentSection = NULL; 2770 mesh->parents = NULL; 2771 mesh->childIDs = NULL; 2772 mesh->childSection = NULL; 2773 mesh->children = NULL; 2774 mesh->referenceTree = NULL; 2775 mesh->getchildsymmetry = NULL; 2776 mesh->vtkCellHeight = 0; 2777 mesh->useAnchors = PETSC_FALSE; 2778 2779 mesh->maxProjectionHeight = 0; 2780 2781 mesh->neighbors = NULL; 2782 2783 mesh->printSetValues = PETSC_FALSE; 2784 mesh->printFEM = 0; 2785 mesh->printTol = 1.0e-10; 2786 2787 ierr = DMInitialize_Plex(dm);CHKERRQ(ierr); 2788 PetscFunctionReturn(0); 2789 } 2790 2791 /*@ 2792 DMPlexCreate - Creates a DMPlex object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram. 2793 2794 Collective 2795 2796 Input Parameter: 2797 . comm - The communicator for the DMPlex object 2798 2799 Output Parameter: 2800 . mesh - The DMPlex object 2801 2802 Level: beginner 2803 2804 @*/ 2805 PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh) 2806 { 2807 PetscErrorCode ierr; 2808 2809 PetscFunctionBegin; 2810 PetscValidPointer(mesh,2); 2811 ierr = DMCreate(comm, mesh);CHKERRQ(ierr); 2812 ierr = DMSetType(*mesh, DMPLEX);CHKERRQ(ierr); 2813 PetscFunctionReturn(0); 2814 } 2815 2816 /*@C 2817 DMPlexBuildFromCellListParallel - Build distributed DMPLEX topology from a list of vertices for each cell (common mesh generator output) 2818 2819 Input Parameters: 2820 + dm - The DM 2821 . numCells - The number of cells owned by this process 2822 . numVertices - The number of vertices owned by this process, or PETSC_DECIDE 2823 . NVertices - The global number of vertices, or PETSC_DECIDE 2824 . numCorners - The number of vertices for each cell 2825 - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 2826 2827 Output Parameter: 2828 . vertexSF - (Optional) SF describing complete vertex ownership 2829 2830 Notes: 2831 Two triangles sharing a face 2832 $ 2833 $ 2 2834 $ / | \ 2835 $ / | \ 2836 $ / | \ 2837 $ 0 0 | 1 3 2838 $ \ | / 2839 $ \ | / 2840 $ \ | / 2841 $ 1 2842 would have input 2843 $ numCells = 2, numVertices = 4 2844 $ cells = [0 1 2 1 3 2] 2845 $ 2846 which would result in the DMPlex 2847 $ 2848 $ 4 2849 $ / | \ 2850 $ / | \ 2851 $ / | \ 2852 $ 2 0 | 1 5 2853 $ \ | / 2854 $ \ | / 2855 $ \ | / 2856 $ 3 2857 2858 Vertices are implicitly numbered consecutively 0,...,NVertices. 2859 Each rank owns a chunk of numVertices consecutive vertices. 2860 If numVertices is PETSC_DECIDE, PETSc will distribute them as evenly as possible using PetscLayout. 2861 If both NVertices and numVertices are PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1. 2862 If only NVertices is PETSC_DECIDE, it is computed as the sum of numVertices over all ranks. 2863 2864 The cell distribution is arbitrary non-overlapping, independent of the vertex distribution. 2865 2866 Not currently supported in Fortran. 2867 2868 Level: advanced 2869 2870 .seealso: DMPlexBuildFromCellList(), DMPlexCreateFromCellListParallelPetsc(), DMPlexBuildCoordinatesFromCellListParallel() 2871 @*/ 2872 PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PetscSF *vertexSF) 2873 { 2874 PetscSF sfPoint, sfVert; 2875 PetscLayout vLayout; 2876 PetscHSetI vhash; 2877 PetscSFNode *remoteVerticesAdj, *vertexLocal, *vertexOwner, *remoteVertex; 2878 const PetscInt *vrange; 2879 PetscInt numVerticesAdj, off = 0, *verticesAdj, numVerticesGhost = 0, *localVertex, *cones, c, p, v, g, dim; 2880 PetscMPIInt rank, size; 2881 PetscErrorCode ierr; 2882 2883 PetscFunctionBegin; 2884 PetscValidLogicalCollectiveInt(dm,NVertices,4); 2885 ierr = PetscLogEventBegin(DMPLEX_BuildFromCellList,dm,0,0,0);CHKERRQ(ierr); 2886 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRQ(ierr); 2887 ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size);CHKERRQ(ierr); 2888 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 2889 /* Get/check global number of vertices */ 2890 { 2891 PetscInt NVerticesInCells, i; 2892 const PetscInt len = numCells * numCorners; 2893 2894 /* NVerticesInCells = max(cells) + 1 */ 2895 NVerticesInCells = PETSC_MIN_INT; 2896 for (i=0; i<len; i++) if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 2897 ++NVerticesInCells; 2898 ierr = MPI_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 2899 2900 if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells; 2901 else if (NVertices != PETSC_DECIDE && NVertices < NVerticesInCells) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Specified global number of vertices %D must be greater than or equal to the number of vertices in cells %D",NVertices,NVerticesInCells); 2902 } 2903 /* Partition vertices */ 2904 ierr = PetscLayoutCreate(PetscObjectComm((PetscObject) dm), &vLayout);CHKERRQ(ierr); 2905 ierr = PetscLayoutSetLocalSize(vLayout, numVertices);CHKERRQ(ierr); 2906 ierr = PetscLayoutSetSize(vLayout, NVertices);CHKERRQ(ierr); 2907 ierr = PetscLayoutSetBlockSize(vLayout, 1);CHKERRQ(ierr); 2908 ierr = PetscLayoutSetUp(vLayout);CHKERRQ(ierr); 2909 ierr = PetscLayoutGetRanges(vLayout, &vrange);CHKERRQ(ierr); 2910 /* Count vertices and map them to procs */ 2911 ierr = PetscHSetICreate(&vhash);CHKERRQ(ierr); 2912 for (c = 0; c < numCells; ++c) { 2913 for (p = 0; p < numCorners; ++p) { 2914 ierr = PetscHSetIAdd(vhash, cells[c*numCorners+p]);CHKERRQ(ierr); 2915 } 2916 } 2917 ierr = PetscHSetIGetSize(vhash, &numVerticesAdj);CHKERRQ(ierr); 2918 ierr = PetscMalloc1(numVerticesAdj, &verticesAdj);CHKERRQ(ierr); 2919 ierr = PetscHSetIGetElems(vhash, &off, verticesAdj);CHKERRQ(ierr); 2920 ierr = PetscHSetIDestroy(&vhash);CHKERRQ(ierr); 2921 if (off != numVerticesAdj) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %D should be %D", off, numVerticesAdj); 2922 ierr = PetscSortInt(numVerticesAdj, verticesAdj);CHKERRQ(ierr); 2923 ierr = PetscMalloc1(numVerticesAdj, &remoteVerticesAdj);CHKERRQ(ierr); 2924 for (v = 0; v < numVerticesAdj; ++v) { 2925 const PetscInt gv = verticesAdj[v]; 2926 PetscInt vrank; 2927 2928 ierr = PetscFindInt(gv, size+1, vrange, &vrank);CHKERRQ(ierr); 2929 vrank = vrank < 0 ? -(vrank+2) : vrank; 2930 remoteVerticesAdj[v].index = gv - vrange[vrank]; 2931 remoteVerticesAdj[v].rank = vrank; 2932 } 2933 /* Create cones */ 2934 ierr = DMPlexSetChart(dm, 0, numCells+numVerticesAdj);CHKERRQ(ierr); 2935 for (c = 0; c < numCells; ++c) {ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr);} 2936 ierr = DMSetUp(dm);CHKERRQ(ierr); 2937 ierr = DMPlexGetCones(dm,&cones);CHKERRQ(ierr); 2938 for (c = 0; c < numCells; ++c) { 2939 for (p = 0; p < numCorners; ++p) { 2940 const PetscInt gv = cells[c*numCorners+p]; 2941 PetscInt lv; 2942 2943 ierr = PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv);CHKERRQ(ierr); 2944 if (lv < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %D in local connectivity", gv); 2945 cones[c*numCorners+p] = lv+numCells; 2946 } 2947 } 2948 /* Create SF for vertices */ 2949 ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), &sfVert);CHKERRQ(ierr); 2950 ierr = PetscObjectSetName((PetscObject) sfVert, "Vertex Ownership SF");CHKERRQ(ierr); 2951 ierr = PetscSFSetFromOptions(sfVert);CHKERRQ(ierr); 2952 ierr = PetscSFSetGraph(sfVert, numVertices, numVerticesAdj, NULL, PETSC_OWN_POINTER, remoteVerticesAdj, PETSC_OWN_POINTER);CHKERRQ(ierr); 2953 ierr = PetscFree(verticesAdj);CHKERRQ(ierr); 2954 /* Build pointSF */ 2955 ierr = PetscMalloc2(numVerticesAdj, &vertexLocal, numVertices, &vertexOwner);CHKERRQ(ierr); 2956 for (v = 0; v < numVerticesAdj; ++v) {vertexLocal[v].index = v+numCells; vertexLocal[v].rank = rank;} 2957 for (v = 0; v < numVertices; ++v) {vertexOwner[v].index = -1; vertexOwner[v].rank = -1;} 2958 ierr = PetscSFReduceBegin(sfVert, MPIU_2INT, vertexLocal, vertexOwner, MPI_MAXLOC);CHKERRQ(ierr); 2959 ierr = PetscSFReduceEnd(sfVert, MPIU_2INT, vertexLocal, vertexOwner, MPI_MAXLOC);CHKERRQ(ierr); 2960 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); 2961 ierr = PetscSFBcastBegin(sfVert, MPIU_2INT, vertexOwner, vertexLocal);CHKERRQ(ierr); 2962 ierr = PetscSFBcastEnd(sfVert, MPIU_2INT, vertexOwner, vertexLocal);CHKERRQ(ierr); 2963 for (v = 0; v < numVerticesAdj; ++v) if (vertexLocal[v].rank != rank) ++numVerticesGhost; 2964 ierr = PetscMalloc1(numVerticesGhost, &localVertex);CHKERRQ(ierr); 2965 ierr = PetscMalloc1(numVerticesGhost, &remoteVertex);CHKERRQ(ierr); 2966 for (v = 0, g = 0; v < numVerticesAdj; ++v) { 2967 if (vertexLocal[v].rank != rank) { 2968 localVertex[g] = v+numCells; 2969 remoteVertex[g].index = vertexLocal[v].index; 2970 remoteVertex[g].rank = vertexLocal[v].rank; 2971 ++g; 2972 } 2973 } 2974 ierr = PetscFree2(vertexLocal, vertexOwner);CHKERRQ(ierr); 2975 if (g != numVerticesGhost) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of vertex ghosts %D should be %D", g, numVerticesGhost); 2976 ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 2977 ierr = PetscObjectSetName((PetscObject) sfPoint, "point SF");CHKERRQ(ierr); 2978 ierr = PetscSFSetGraph(sfPoint, numCells+numVerticesAdj, numVerticesGhost, localVertex, PETSC_OWN_POINTER, remoteVertex, PETSC_OWN_POINTER);CHKERRQ(ierr); 2979 ierr = PetscLayoutDestroy(&vLayout);CHKERRQ(ierr); 2980 /* Fill in the rest of the topology structure */ 2981 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 2982 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 2983 ierr = PetscLogEventEnd(DMPLEX_BuildFromCellList,dm,0,0,0);CHKERRQ(ierr); 2984 if (vertexSF) *vertexSF = sfVert; 2985 else {ierr = PetscSFDestroy(&sfVert);CHKERRQ(ierr);} 2986 PetscFunctionReturn(0); 2987 } 2988 2989 /*@C 2990 DMPlexBuildCoordinatesFromCellListParallel - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output) 2991 2992 Input Parameters: 2993 + dm - The DM 2994 . spaceDim - The spatial dimension used for coordinates 2995 . sfVert - SF describing complete vertex ownership 2996 - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 2997 2998 Level: advanced 2999 3000 Notes: 3001 Not currently supported in Fortran. 3002 3003 .seealso: DMPlexBuildCoordinatesFromCellList(), DMPlexCreateFromCellListParallelPetsc(), DMPlexBuildFromCellListParallel() 3004 @*/ 3005 PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[]) 3006 { 3007 PetscSection coordSection; 3008 Vec coordinates; 3009 PetscScalar *coords; 3010 PetscInt numVertices, numVerticesAdj, coordSize, v, vStart, vEnd; 3011 PetscErrorCode ierr; 3012 3013 PetscFunctionBegin; 3014 ierr = PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList,dm,0,0,0);CHKERRQ(ierr); 3015 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3016 if (vStart < 0 || vEnd < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 3017 ierr = DMSetCoordinateDim(dm, spaceDim);CHKERRQ(ierr); 3018 ierr = PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL);CHKERRQ(ierr); 3019 if (vEnd - vStart != numVerticesAdj) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Supplied sfVert has wrong number of leaves = %D != %D = vEnd - vStart",numVerticesAdj,vEnd - vStart); 3020 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3021 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 3022 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 3023 ierr = PetscSectionSetChart(coordSection, vStart, vEnd);CHKERRQ(ierr); 3024 for (v = vStart; v < vEnd; ++v) { 3025 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 3026 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 3027 } 3028 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 3029 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 3030 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinates);CHKERRQ(ierr); 3031 ierr = VecSetBlockSize(coordinates, spaceDim);CHKERRQ(ierr); 3032 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 3033 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 3034 ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr); 3035 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 3036 { 3037 MPI_Datatype coordtype; 3038 3039 /* Need a temp buffer for coords if we have complex/single */ 3040 ierr = MPI_Type_contiguous(spaceDim, MPIU_SCALAR, &coordtype);CHKERRQ(ierr); 3041 ierr = MPI_Type_commit(&coordtype);CHKERRQ(ierr); 3042 #if defined(PETSC_USE_COMPLEX) 3043 { 3044 PetscScalar *svertexCoords; 3045 PetscInt i; 3046 ierr = PetscMalloc1(numVertices*spaceDim,&svertexCoords);CHKERRQ(ierr); 3047 for (i=0; i<numVertices*spaceDim; i++) svertexCoords[i] = vertexCoords[i]; 3048 ierr = PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords);CHKERRQ(ierr); 3049 ierr = PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords);CHKERRQ(ierr); 3050 ierr = PetscFree(svertexCoords);CHKERRQ(ierr); 3051 } 3052 #else 3053 ierr = PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords);CHKERRQ(ierr); 3054 ierr = PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords);CHKERRQ(ierr); 3055 #endif 3056 ierr = MPI_Type_free(&coordtype);CHKERRQ(ierr); 3057 } 3058 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 3059 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 3060 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 3061 ierr = PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList,dm,0,0,0);CHKERRQ(ierr); 3062 PetscFunctionReturn(0); 3063 } 3064 3065 /*@ 3066 DMPlexCreateFromCellListParallelPetsc - Create distributed DMPLEX from a list of vertices for each cell (common mesh generator output) 3067 3068 Input Parameters: 3069 + comm - The communicator 3070 . dim - The topological dimension of the mesh 3071 . numCells - The number of cells owned by this process 3072 . numVertices - The number of vertices owned by this process, or PETSC_DECIDE 3073 . NVertices - The global number of vertices, or PETSC_DECIDE 3074 . numCorners - The number of vertices for each cell 3075 . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 3076 . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 3077 . spaceDim - The spatial dimension used for coordinates 3078 - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 3079 3080 Output Parameter: 3081 + dm - The DM 3082 - vertexSF - (Optional) SF describing complete vertex ownership 3083 3084 Notes: 3085 This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(), 3086 DMPlexBuildFromCellListParallel(), DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellListParallel() 3087 3088 See DMPlexBuildFromCellListParallel() for an example and details about the topology-related parameters. 3089 See DMPlexBuildCoordinatesFromCellListParallel() for details about the geometry-related parameters. 3090 3091 Level: intermediate 3092 3093 .seealso: DMPlexCreateFromCellListPetsc(), DMPlexBuildFromCellListParallel(), DMPlexBuildCoordinatesFromCellListParallel(), DMPlexCreateFromDAG(), DMPlexCreate() 3094 @*/ 3095 PetscErrorCode DMPlexCreateFromCellListParallelPetsc(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, PetscBool interpolate, const PetscInt cells[], PetscInt spaceDim, const PetscReal vertexCoords[], PetscSF *vertexSF, DM *dm) 3096 { 3097 PetscSF sfVert; 3098 PetscErrorCode ierr; 3099 3100 PetscFunctionBegin; 3101 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 3102 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 3103 PetscValidLogicalCollectiveInt(*dm, dim, 2); 3104 PetscValidLogicalCollectiveInt(*dm, spaceDim, 8); 3105 ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); 3106 ierr = DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert);CHKERRQ(ierr); 3107 if (interpolate) { 3108 DM idm; 3109 3110 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 3111 ierr = DMDestroy(dm);CHKERRQ(ierr); 3112 *dm = idm; 3113 } 3114 ierr = DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords);CHKERRQ(ierr); 3115 if (vertexSF) *vertexSF = sfVert; 3116 else {ierr = PetscSFDestroy(&sfVert);CHKERRQ(ierr);} 3117 PetscFunctionReturn(0); 3118 } 3119 3120 3121 /*@ 3122 DMPlexCreateFromCellListParallel - Deprecated, use DMPlexCreateFromCellListParallelPetsc() 3123 3124 Level: deprecated 3125 3126 .seealso: DMPlexCreateFromCellListParallelPetsc() 3127 @*/ 3128 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) 3129 { 3130 PetscErrorCode ierr; 3131 PetscInt i; 3132 PetscInt *pintCells; 3133 3134 PetscFunctionBegin; 3135 if (sizeof(int) > sizeof(PetscInt)) SETERRQ2(comm, PETSC_ERR_ARG_SIZ, "Size of int %zd greater than size of PetscInt %zd. Reconfigure PETSc --with-64-bit-indices=1", sizeof(int), sizeof(PetscInt)); 3136 if (sizeof(int) == sizeof(PetscInt)) { 3137 pintCells = (PetscInt *) cells; 3138 } else { 3139 ierr = PetscMalloc1(numCells*numCorners, &pintCells);CHKERRQ(ierr); 3140 for (i = 0; i < numCells*numCorners; i++) { 3141 pintCells[i] = (PetscInt) cells[i]; 3142 } 3143 } 3144 ierr = DMPlexCreateFromCellListParallelPetsc(comm, dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, pintCells, spaceDim, vertexCoords, vertexSF, dm);CHKERRQ(ierr); 3145 if (sizeof(int) != sizeof(PetscInt)) { 3146 ierr = PetscFree(pintCells);CHKERRQ(ierr); 3147 } 3148 PetscFunctionReturn(0); 3149 } 3150 3151 /*@C 3152 DMPlexBuildFromCellList - Build DMPLEX topology from a list of vertices for each cell (common mesh generator output) 3153 3154 Input Parameters: 3155 + dm - The DM 3156 . numCells - The number of cells owned by this process 3157 . numVertices - The number of vertices owned by this process, or PETSC_DECIDE 3158 . numCorners - The number of vertices for each cell 3159 - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 3160 3161 Level: advanced 3162 3163 Notes: 3164 Two triangles sharing a face 3165 $ 3166 $ 2 3167 $ / | \ 3168 $ / | \ 3169 $ / | \ 3170 $ 0 0 | 1 3 3171 $ \ | / 3172 $ \ | / 3173 $ \ | / 3174 $ 1 3175 would have input 3176 $ numCells = 2, numVertices = 4 3177 $ cells = [0 1 2 1 3 2] 3178 $ 3179 which would result in the DMPlex 3180 $ 3181 $ 4 3182 $ / | \ 3183 $ / | \ 3184 $ / | \ 3185 $ 2 0 | 1 5 3186 $ \ | / 3187 $ \ | / 3188 $ \ | / 3189 $ 3 3190 3191 If numVertices is PETSC_DECIDE, it is computed by PETSc as the maximum vertex index in cells + 1. 3192 3193 Not currently supported in Fortran. 3194 3195 .seealso: DMPlexBuildFromCellListParallel(), DMPlexBuildCoordinatesFromCellList(), DMPlexCreateFromCellListPetsc() 3196 @*/ 3197 PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[]) 3198 { 3199 PetscInt *cones, c, p, dim; 3200 PetscErrorCode ierr; 3201 3202 PetscFunctionBegin; 3203 ierr = PetscLogEventBegin(DMPLEX_BuildFromCellList,dm,0,0,0);CHKERRQ(ierr); 3204 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3205 /* Get/check global number of vertices */ 3206 { 3207 PetscInt NVerticesInCells, i; 3208 const PetscInt len = numCells * numCorners; 3209 3210 /* NVerticesInCells = max(cells) + 1 */ 3211 NVerticesInCells = PETSC_MIN_INT; 3212 for (i=0; i<len; i++) if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 3213 ++NVerticesInCells; 3214 3215 if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells; 3216 else if (numVertices < NVerticesInCells) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Specified number of vertices %D must be greater than or equal to the number of vertices in cells %D",numVertices,NVerticesInCells); 3217 } 3218 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 3219 for (c = 0; c < numCells; ++c) { 3220 ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); 3221 } 3222 ierr = DMSetUp(dm);CHKERRQ(ierr); 3223 ierr = DMPlexGetCones(dm,&cones);CHKERRQ(ierr); 3224 for (c = 0; c < numCells; ++c) { 3225 for (p = 0; p < numCorners; ++p) { 3226 cones[c*numCorners+p] = cells[c*numCorners+p]+numCells; 3227 } 3228 } 3229 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 3230 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 3231 ierr = PetscLogEventEnd(DMPLEX_BuildFromCellList,dm,0,0,0);CHKERRQ(ierr); 3232 PetscFunctionReturn(0); 3233 } 3234 3235 /*@C 3236 DMPlexBuildCoordinatesFromCellList - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output) 3237 3238 Input Parameters: 3239 + dm - The DM 3240 . spaceDim - The spatial dimension used for coordinates 3241 - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 3242 3243 Level: advanced 3244 3245 Notes: 3246 Not currently supported in Fortran. 3247 3248 .seealso: DMPlexBuildCoordinatesFromCellListParallel(), DMPlexCreateFromCellListPetsc(), DMPlexBuildFromCellList() 3249 @*/ 3250 PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[]) 3251 { 3252 PetscSection coordSection; 3253 Vec coordinates; 3254 DM cdm; 3255 PetscScalar *coords; 3256 PetscInt v, vStart, vEnd, d; 3257 PetscErrorCode ierr; 3258 3259 PetscFunctionBegin; 3260 ierr = PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList,dm,0,0,0);CHKERRQ(ierr); 3261 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3262 if (vStart < 0 || vEnd < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 3263 ierr = DMSetCoordinateDim(dm, spaceDim);CHKERRQ(ierr); 3264 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3265 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 3266 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 3267 ierr = PetscSectionSetChart(coordSection, vStart, vEnd);CHKERRQ(ierr); 3268 for (v = vStart; v < vEnd; ++v) { 3269 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 3270 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 3271 } 3272 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 3273 3274 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 3275 ierr = DMCreateLocalVector(cdm, &coordinates);CHKERRQ(ierr); 3276 ierr = VecSetBlockSize(coordinates, spaceDim);CHKERRQ(ierr); 3277 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 3278 ierr = VecGetArrayWrite(coordinates, &coords);CHKERRQ(ierr); 3279 for (v = 0; v < vEnd-vStart; ++v) { 3280 for (d = 0; d < spaceDim; ++d) { 3281 coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 3282 } 3283 } 3284 ierr = VecRestoreArrayWrite(coordinates, &coords);CHKERRQ(ierr); 3285 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 3286 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 3287 ierr = PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList,dm,0,0,0);CHKERRQ(ierr); 3288 PetscFunctionReturn(0); 3289 } 3290 3291 /*@ 3292 DMPlexCreateFromCellListPetsc - Create DMPLEX from a list of vertices for each cell (common mesh generator output) 3293 3294 Input Parameters: 3295 + comm - The communicator 3296 . dim - The topological dimension of the mesh 3297 . numCells - The number of cells 3298 . numVertices - The number of vertices owned by this process, or PETSC_DECIDE 3299 . numCorners - The number of vertices for each cell 3300 . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 3301 . cells - An array of numCells*numCorners numbers, the vertices for each cell 3302 . spaceDim - The spatial dimension used for coordinates 3303 - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 3304 3305 Output Parameter: 3306 . dm - The DM 3307 3308 Notes: 3309 This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(), DMPlexBuildFromCellList(), 3310 DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellList() 3311 3312 See DMPlexBuildFromCellList() for an example and details about the topology-related parameters. 3313 See DMPlexBuildCoordinatesFromCellList() for details about the geometry-related parameters. 3314 3315 Level: intermediate 3316 3317 .seealso: DMPlexCreateFromCellListParallelPetsc(), DMPlexBuildFromCellList(), DMPlexBuildCoordinatesFromCellList(), DMPlexCreateFromDAG(), DMPlexCreate() 3318 @*/ 3319 PetscErrorCode DMPlexCreateFromCellListPetsc(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const PetscInt cells[], PetscInt spaceDim, const PetscReal vertexCoords[], DM *dm) 3320 { 3321 PetscErrorCode ierr; 3322 3323 PetscFunctionBegin; 3324 if (!dim) SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "This is not appropriate for 0-dimensional meshes. Consider either creating the DM using DMPlexCreateFromDAG(), by hand, or using DMSwarm."); 3325 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 3326 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 3327 ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); 3328 ierr = DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); 3329 if (interpolate) { 3330 DM idm; 3331 3332 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 3333 ierr = DMDestroy(dm);CHKERRQ(ierr); 3334 *dm = idm; 3335 } 3336 ierr = DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords);CHKERRQ(ierr); 3337 PetscFunctionReturn(0); 3338 } 3339 3340 /*@ 3341 DMPlexCreateFromCellList - Deprecated, use DMPlexCreateFromCellListPetsc() 3342 3343 Level: deprecated 3344 3345 .seealso: DMPlexCreateFromCellListPetsc() 3346 @*/ 3347 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) 3348 { 3349 PetscErrorCode ierr; 3350 PetscInt i; 3351 PetscInt *pintCells; 3352 PetscReal *prealVC; 3353 3354 PetscFunctionBegin; 3355 if (sizeof(int) > sizeof(PetscInt)) SETERRQ2(comm, PETSC_ERR_ARG_SIZ, "Size of int %zd greater than size of PetscInt %zd. Reconfigure PETSc --with-64-bit-indices=1", sizeof(int), sizeof(PetscInt)); 3356 if (sizeof(int) == sizeof(PetscInt)) { 3357 pintCells = (PetscInt *) cells; 3358 } else { 3359 ierr = PetscMalloc1(numCells*numCorners, &pintCells);CHKERRQ(ierr); 3360 for (i = 0; i < numCells*numCorners; i++) { 3361 pintCells[i] = (PetscInt) cells[i]; 3362 } 3363 } 3364 if (sizeof(double) > sizeof(PetscReal)) SETERRQ2(comm, PETSC_ERR_ARG_SIZ, "Size of double %zd greater than size of PetscReal %zd. Reconfigure PETSc --with-precision=<higher precision>.", sizeof(double), sizeof(PetscReal)); 3365 if (sizeof(double) == sizeof(PetscReal)) { 3366 prealVC = (PetscReal *) vertexCoords; 3367 } else { 3368 ierr = PetscMalloc1(numVertices*spaceDim, &prealVC);CHKERRQ(ierr); 3369 for (i = 0; i < numVertices*spaceDim; i++) { 3370 prealVC[i] = (PetscReal) vertexCoords[i]; 3371 } 3372 } 3373 ierr = DMPlexCreateFromCellListPetsc(comm, dim, numCells, numVertices, numCorners, interpolate, pintCells, spaceDim, prealVC, dm);CHKERRQ(ierr); 3374 if (sizeof(int) != sizeof(PetscInt)) { 3375 ierr = PetscFree(pintCells);CHKERRQ(ierr); 3376 } 3377 if (sizeof(double) != sizeof(PetscReal)) { 3378 ierr = PetscFree(prealVC);CHKERRQ(ierr); 3379 } 3380 PetscFunctionReturn(0); 3381 } 3382 3383 /*@ 3384 DMPlexCreateFromDAG - This takes as input the adjacency-list representation of the Directed Acyclic Graph (Hasse Diagram) encoding a mesh, and produces a DM 3385 3386 Input Parameters: 3387 + dm - The empty DM object, usually from DMCreate() and DMSetDimension() 3388 . depth - The depth of the DAG 3389 . numPoints - Array of size depth + 1 containing the number of points at each depth 3390 . coneSize - The cone size of each point 3391 . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point 3392 . coneOrientations - The orientation of each cone point 3393 - vertexCoords - An array of numPoints[0]*spacedim numbers representing the coordinates of each vertex, with spacedim the value set via DMSetCoordinateDim() 3394 3395 Output Parameter: 3396 . dm - The DM 3397 3398 Note: Two triangles sharing a face would have input 3399 $ depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0] 3400 $ cones = [2 3 4 3 5 4], coneOrientations = [0 0 0 0 0 0] 3401 $ vertexCoords = [-1.0 0.0 0.0 -1.0 0.0 1.0 1.0 0.0] 3402 $ 3403 which would result in the DMPlex 3404 $ 3405 $ 4 3406 $ / | \ 3407 $ / | \ 3408 $ / | \ 3409 $ 2 0 | 1 5 3410 $ \ | / 3411 $ \ | / 3412 $ \ | / 3413 $ 3 3414 $ 3415 $ Notice that all points are numbered consecutively, unlike DMPlexCreateFromCellListPetsc() 3416 3417 Level: advanced 3418 3419 .seealso: DMPlexCreateFromCellListPetsc(), DMPlexCreate() 3420 @*/ 3421 PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[]) 3422 { 3423 Vec coordinates; 3424 PetscSection coordSection; 3425 PetscScalar *coords; 3426 PetscInt coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off; 3427 PetscErrorCode ierr; 3428 3429 PetscFunctionBegin; 3430 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3431 ierr = DMGetCoordinateDim(dm, &dimEmbed);CHKERRQ(ierr); 3432 if (dimEmbed < dim) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Embedding dimension %D cannot be less than intrinsic dimension %d",dimEmbed,dim); 3433 for (d = 0; d <= depth; ++d) pEnd += numPoints[d]; 3434 ierr = DMPlexSetChart(dm, pStart, pEnd);CHKERRQ(ierr); 3435 for (p = pStart; p < pEnd; ++p) { 3436 ierr = DMPlexSetConeSize(dm, p, coneSize[p-pStart]);CHKERRQ(ierr); 3437 if (firstVertex < 0 && !coneSize[p - pStart]) { 3438 firstVertex = p - pStart; 3439 } 3440 } 3441 if (firstVertex < 0 && numPoints[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Expected %D vertices but could not find any", numPoints[0]); 3442 ierr = DMSetUp(dm);CHKERRQ(ierr); /* Allocate space for cones */ 3443 for (p = pStart, off = 0; p < pEnd; off += coneSize[p-pStart], ++p) { 3444 ierr = DMPlexSetCone(dm, p, &cones[off]);CHKERRQ(ierr); 3445 ierr = DMPlexSetConeOrientation(dm, p, &coneOrientations[off]);CHKERRQ(ierr); 3446 } 3447 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 3448 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 3449 /* Build coordinates */ 3450 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3451 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 3452 ierr = PetscSectionSetFieldComponents(coordSection, 0, dimEmbed);CHKERRQ(ierr); 3453 ierr = PetscSectionSetChart(coordSection, firstVertex, firstVertex+numPoints[0]);CHKERRQ(ierr); 3454 for (v = firstVertex; v < firstVertex+numPoints[0]; ++v) { 3455 ierr = PetscSectionSetDof(coordSection, v, dimEmbed);CHKERRQ(ierr); 3456 ierr = PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed);CHKERRQ(ierr); 3457 } 3458 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 3459 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 3460 ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr); 3461 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 3462 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 3463 ierr = VecSetBlockSize(coordinates, dimEmbed);CHKERRQ(ierr); 3464 ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr); 3465 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 3466 for (v = 0; v < numPoints[0]; ++v) { 3467 PetscInt off; 3468 3469 ierr = PetscSectionGetOffset(coordSection, v+firstVertex, &off);CHKERRQ(ierr); 3470 for (d = 0; d < dimEmbed; ++d) { 3471 coords[off+d] = vertexCoords[v*dimEmbed+d]; 3472 } 3473 } 3474 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 3475 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 3476 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 3477 PetscFunctionReturn(0); 3478 } 3479 3480 /*@C 3481 DMPlexCreateCellVertexFromFile - Create a DMPlex mesh from a simple cell-vertex file. 3482 3483 + comm - The MPI communicator 3484 . filename - Name of the .dat file 3485 - interpolate - Create faces and edges in the mesh 3486 3487 Output Parameter: 3488 . dm - The DM object representing the mesh 3489 3490 Note: The format is the simplest possible: 3491 $ Ne 3492 $ v0 v1 ... vk 3493 $ Nv 3494 $ x y z marker 3495 3496 Level: beginner 3497 3498 .seealso: DMPlexCreateFromFile(), DMPlexCreateMedFromFile(), DMPlexCreateGmsh(), DMPlexCreate() 3499 @*/ 3500 PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 3501 { 3502 DMLabel marker; 3503 PetscViewer viewer; 3504 Vec coordinates; 3505 PetscSection coordSection; 3506 PetscScalar *coords; 3507 char line[PETSC_MAX_PATH_LEN]; 3508 PetscInt dim = 3, cdim = 3, coordSize, v, c, d; 3509 PetscMPIInt rank; 3510 int snum, Nv, Nc; 3511 PetscErrorCode ierr; 3512 3513 PetscFunctionBegin; 3514 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3515 ierr = PetscViewerCreate(comm, &viewer);CHKERRQ(ierr); 3516 ierr = PetscViewerSetType(viewer, PETSCVIEWERASCII);CHKERRQ(ierr); 3517 ierr = PetscViewerFileSetMode(viewer, FILE_MODE_READ);CHKERRQ(ierr); 3518 ierr = PetscViewerFileSetName(viewer, filename);CHKERRQ(ierr); 3519 if (!rank) { 3520 ierr = PetscViewerRead(viewer, line, 2, NULL, PETSC_STRING);CHKERRQ(ierr); 3521 snum = sscanf(line, "%d %d", &Nc, &Nv); 3522 if (snum != 2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 3523 } else { 3524 Nc = Nv = 0; 3525 } 3526 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 3527 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 3528 ierr = DMPlexSetChart(*dm, 0, Nc+Nv);CHKERRQ(ierr); 3529 ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); 3530 ierr = DMSetCoordinateDim(*dm, cdim);CHKERRQ(ierr); 3531 /* Read topology */ 3532 if (!rank) { 3533 PetscInt cone[8], corners = 8; 3534 int vbuf[8], v; 3535 3536 for (c = 0; c < Nc; ++c) {ierr = DMPlexSetConeSize(*dm, c, corners);CHKERRQ(ierr);} 3537 ierr = DMSetUp(*dm);CHKERRQ(ierr); 3538 for (c = 0; c < Nc; ++c) { 3539 ierr = PetscViewerRead(viewer, line, corners, NULL, PETSC_STRING);CHKERRQ(ierr); 3540 snum = sscanf(line, "%d %d %d %d %d %d %d %d", &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]); 3541 if (snum != corners) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 3542 for (v = 0; v < corners; ++v) cone[v] = vbuf[v] + Nc; 3543 /* Hexahedra are inverted */ 3544 { 3545 PetscInt tmp = cone[1]; 3546 cone[1] = cone[3]; 3547 cone[3] = tmp; 3548 } 3549 ierr = DMPlexSetCone(*dm, c, cone);CHKERRQ(ierr); 3550 } 3551 } 3552 ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr); 3553 ierr = DMPlexStratify(*dm);CHKERRQ(ierr); 3554 /* Read coordinates */ 3555 ierr = DMGetCoordinateSection(*dm, &coordSection);CHKERRQ(ierr); 3556 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 3557 ierr = PetscSectionSetFieldComponents(coordSection, 0, cdim);CHKERRQ(ierr); 3558 ierr = PetscSectionSetChart(coordSection, Nc, Nc + Nv);CHKERRQ(ierr); 3559 for (v = Nc; v < Nc+Nv; ++v) { 3560 ierr = PetscSectionSetDof(coordSection, v, cdim);CHKERRQ(ierr); 3561 ierr = PetscSectionSetFieldDof(coordSection, v, 0, cdim);CHKERRQ(ierr); 3562 } 3563 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 3564 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 3565 ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr); 3566 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 3567 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 3568 ierr = VecSetBlockSize(coordinates, cdim);CHKERRQ(ierr); 3569 ierr = VecSetType(coordinates, VECSTANDARD);CHKERRQ(ierr); 3570 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 3571 if (!rank) { 3572 double x[3]; 3573 int val; 3574 3575 ierr = DMCreateLabel(*dm, "marker");CHKERRQ(ierr); 3576 ierr = DMGetLabel(*dm, "marker", &marker);CHKERRQ(ierr); 3577 for (v = 0; v < Nv; ++v) { 3578 ierr = PetscViewerRead(viewer, line, 4, NULL, PETSC_STRING);CHKERRQ(ierr); 3579 snum = sscanf(line, "%lg %lg %lg %d", &x[0], &x[1], &x[2], &val); 3580 if (snum != 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 3581 for (d = 0; d < cdim; ++d) coords[v*cdim+d] = x[d]; 3582 if (val) {ierr = DMLabelSetValue(marker, v+Nc, val);CHKERRQ(ierr);} 3583 } 3584 } 3585 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 3586 ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr); 3587 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 3588 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 3589 if (interpolate) { 3590 DM idm; 3591 DMLabel bdlabel; 3592 3593 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 3594 ierr = DMDestroy(dm);CHKERRQ(ierr); 3595 *dm = idm; 3596 3597 ierr = DMGetLabel(*dm, "marker", &bdlabel);CHKERRQ(ierr); 3598 ierr = DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel);CHKERRQ(ierr); 3599 ierr = DMPlexLabelComplete(*dm, bdlabel);CHKERRQ(ierr); 3600 } 3601 PetscFunctionReturn(0); 3602 } 3603 3604 /*@C 3605 DMPlexCreateFromFile - This takes a filename and produces a DM 3606 3607 Input Parameters: 3608 + comm - The communicator 3609 . filename - A file name 3610 - interpolate - Flag to create intermediate mesh pieces (edges, faces) 3611 3612 Output Parameter: 3613 . dm - The DM 3614 3615 Options Database Keys: 3616 . -dm_plex_create_from_hdf5_xdmf - use the PETSC_VIEWER_HDF5_XDMF format for reading HDF5 3617 3618 Use -dm_plex_create_ prefix to pass options to the internal PetscViewer, e.g. 3619 $ -dm_plex_create_viewer_hdf5_collective 3620 3621 Level: beginner 3622 3623 .seealso: DMPlexCreateFromDAG(), DMPlexCreateFromCellListPetsc(), DMPlexCreate() 3624 @*/ 3625 PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 3626 { 3627 const char *extGmsh = ".msh"; 3628 const char *extGmsh2 = ".msh2"; 3629 const char *extGmsh4 = ".msh4"; 3630 const char *extCGNS = ".cgns"; 3631 const char *extExodus = ".exo"; 3632 const char *extGenesis = ".gen"; 3633 const char *extFluent = ".cas"; 3634 const char *extHDF5 = ".h5"; 3635 const char *extMed = ".med"; 3636 const char *extPLY = ".ply"; 3637 const char *extCV = ".dat"; 3638 size_t len; 3639 PetscBool isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isMed, isPLY, isCV; 3640 PetscMPIInt rank; 3641 PetscErrorCode ierr; 3642 3643 PetscFunctionBegin; 3644 PetscValidCharPointer(filename, 2); 3645 PetscValidPointer(dm, 4); 3646 ierr = DMInitializePackage();CHKERRQ(ierr); 3647 ierr = PetscLogEventBegin(DMPLEX_CreateFromFile,0,0,0,0);CHKERRQ(ierr); 3648 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3649 ierr = PetscStrlen(filename, &len);CHKERRQ(ierr); 3650 if (!len) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path"); 3651 ierr = PetscStrncmp(&filename[PetscMax(0,len-4)], extGmsh, 4, &isGmsh);CHKERRQ(ierr); 3652 ierr = PetscStrncmp(&filename[PetscMax(0,len-5)], extGmsh2, 5, &isGmsh2);CHKERRQ(ierr); 3653 ierr = PetscStrncmp(&filename[PetscMax(0,len-5)], extGmsh4, 5, &isGmsh4);CHKERRQ(ierr); 3654 ierr = PetscStrncmp(&filename[PetscMax(0,len-5)], extCGNS, 5, &isCGNS);CHKERRQ(ierr); 3655 ierr = PetscStrncmp(&filename[PetscMax(0,len-4)], extExodus, 4, &isExodus);CHKERRQ(ierr); 3656 ierr = PetscStrncmp(&filename[PetscMax(0,len-4)], extGenesis, 4, &isGenesis);CHKERRQ(ierr); 3657 ierr = PetscStrncmp(&filename[PetscMax(0,len-4)], extFluent, 4, &isFluent);CHKERRQ(ierr); 3658 ierr = PetscStrncmp(&filename[PetscMax(0,len-3)], extHDF5, 3, &isHDF5);CHKERRQ(ierr); 3659 ierr = PetscStrncmp(&filename[PetscMax(0,len-4)], extMed, 4, &isMed);CHKERRQ(ierr); 3660 ierr = PetscStrncmp(&filename[PetscMax(0,len-4)], extPLY, 4, &isPLY);CHKERRQ(ierr); 3661 ierr = PetscStrncmp(&filename[PetscMax(0,len-4)], extCV, 4, &isCV);CHKERRQ(ierr); 3662 if (isGmsh || isGmsh2 || isGmsh4) { 3663 ierr = DMPlexCreateGmshFromFile(comm, filename, interpolate, dm);CHKERRQ(ierr); 3664 } else if (isCGNS) { 3665 ierr = DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm);CHKERRQ(ierr); 3666 } else if (isExodus || isGenesis) { 3667 ierr = DMPlexCreateExodusFromFile(comm, filename, interpolate, dm);CHKERRQ(ierr); 3668 } else if (isFluent) { 3669 ierr = DMPlexCreateFluentFromFile(comm, filename, interpolate, dm);CHKERRQ(ierr); 3670 } else if (isHDF5) { 3671 PetscBool load_hdf5_xdmf = PETSC_FALSE; 3672 PetscViewer viewer; 3673 3674 /* PETSC_VIEWER_HDF5_XDMF is used if the filename ends with .xdmf.h5, or if -dm_plex_create_from_hdf5_xdmf option is present */ 3675 ierr = PetscStrncmp(&filename[PetscMax(0,len-8)], ".xdmf", 5, &load_hdf5_xdmf);CHKERRQ(ierr); 3676 ierr = PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &load_hdf5_xdmf, NULL);CHKERRQ(ierr); 3677 ierr = PetscViewerCreate(comm, &viewer);CHKERRQ(ierr); 3678 ierr = PetscViewerSetType(viewer, PETSCVIEWERHDF5);CHKERRQ(ierr); 3679 ierr = PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_");CHKERRQ(ierr); 3680 ierr = PetscViewerSetFromOptions(viewer);CHKERRQ(ierr); 3681 ierr = PetscViewerFileSetMode(viewer, FILE_MODE_READ);CHKERRQ(ierr); 3682 ierr = PetscViewerFileSetName(viewer, filename);CHKERRQ(ierr); 3683 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 3684 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 3685 if (load_hdf5_xdmf) {ierr = PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF);CHKERRQ(ierr);} 3686 ierr = DMLoad(*dm, viewer);CHKERRQ(ierr); 3687 if (load_hdf5_xdmf) {ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);} 3688 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 3689 3690 if (interpolate) { 3691 DM idm; 3692 3693 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 3694 ierr = DMDestroy(dm);CHKERRQ(ierr); 3695 *dm = idm; 3696 } 3697 } else if (isMed) { 3698 ierr = DMPlexCreateMedFromFile(comm, filename, interpolate, dm);CHKERRQ(ierr); 3699 } else if (isPLY) { 3700 ierr = DMPlexCreatePLYFromFile(comm, filename, interpolate, dm);CHKERRQ(ierr); 3701 } else if (isCV) { 3702 ierr = DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm);CHKERRQ(ierr); 3703 } else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename); 3704 ierr = PetscLogEventEnd(DMPLEX_CreateFromFile,0,0,0,0);CHKERRQ(ierr); 3705 PetscFunctionReturn(0); 3706 } 3707 3708 /*@ 3709 DMPlexCreateReferenceCellByType - Create a DMPLEX with the appropriate FEM reference cell 3710 3711 Collective 3712 3713 Input Parameters: 3714 + comm - The communicator 3715 - ct - The cell type of the reference cell 3716 3717 Output Parameter: 3718 . refdm - The reference cell 3719 3720 Level: intermediate 3721 3722 .seealso: DMPlexCreateReferenceCell(), DMPlexCreateBoxMesh() 3723 @*/ 3724 PetscErrorCode DMPlexCreateReferenceCellByType(MPI_Comm comm, DMPolytopeType ct, DM *refdm) 3725 { 3726 DM rdm; 3727 Vec coords; 3728 PetscErrorCode ierr; 3729 3730 PetscFunctionBegin; 3731 ierr = DMCreate(comm, &rdm);CHKERRQ(ierr); 3732 ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 3733 switch (ct) { 3734 case DM_POLYTOPE_POINT: 3735 { 3736 PetscInt numPoints[1] = {1}; 3737 PetscInt coneSize[1] = {0}; 3738 PetscInt cones[1] = {0}; 3739 PetscInt coneOrientations[1] = {0}; 3740 PetscScalar vertexCoords[1] = {0.0}; 3741 3742 ierr = DMSetDimension(rdm, 0);CHKERRQ(ierr); 3743 ierr = DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 3744 } 3745 break; 3746 case DM_POLYTOPE_SEGMENT: 3747 { 3748 PetscInt numPoints[2] = {2, 1}; 3749 PetscInt coneSize[3] = {2, 0, 0}; 3750 PetscInt cones[2] = {1, 2}; 3751 PetscInt coneOrientations[2] = {0, 0}; 3752 PetscScalar vertexCoords[2] = {-1.0, 1.0}; 3753 3754 ierr = DMSetDimension(rdm, 1);CHKERRQ(ierr); 3755 ierr = DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 3756 } 3757 break; 3758 case DM_POLYTOPE_TRIANGLE: 3759 { 3760 PetscInt numPoints[2] = {3, 1}; 3761 PetscInt coneSize[4] = {3, 0, 0, 0}; 3762 PetscInt cones[3] = {1, 2, 3}; 3763 PetscInt coneOrientations[3] = {0, 0, 0}; 3764 PetscScalar vertexCoords[6] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0}; 3765 3766 ierr = DMSetDimension(rdm, 2);CHKERRQ(ierr); 3767 ierr = DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 3768 } 3769 break; 3770 case DM_POLYTOPE_QUADRILATERAL: 3771 { 3772 PetscInt numPoints[2] = {4, 1}; 3773 PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 3774 PetscInt cones[4] = {1, 2, 3, 4}; 3775 PetscInt coneOrientations[4] = {0, 0, 0, 0}; 3776 PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0}; 3777 3778 ierr = DMSetDimension(rdm, 2);CHKERRQ(ierr); 3779 ierr = DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 3780 } 3781 break; 3782 case DM_POLYTOPE_SEG_PRISM_TENSOR: 3783 { 3784 PetscInt numPoints[2] = {4, 1}; 3785 PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 3786 PetscInt cones[4] = {1, 2, 3, 4}; 3787 PetscInt coneOrientations[4] = {0, 0, 0, 0}; 3788 PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0}; 3789 3790 ierr = DMSetDimension(rdm, 2);CHKERRQ(ierr); 3791 ierr = DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 3792 } 3793 break; 3794 case DM_POLYTOPE_TETRAHEDRON: 3795 { 3796 PetscInt numPoints[2] = {4, 1}; 3797 PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 3798 PetscInt cones[4] = {1, 3, 2, 4}; 3799 PetscInt coneOrientations[4] = {0, 0, 0, 0}; 3800 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}; 3801 3802 ierr = DMSetDimension(rdm, 3);CHKERRQ(ierr); 3803 ierr = DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 3804 } 3805 break; 3806 case DM_POLYTOPE_HEXAHEDRON: 3807 { 3808 PetscInt numPoints[2] = {8, 1}; 3809 PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 3810 PetscInt cones[8] = {1, 4, 3, 2, 5, 6, 7, 8}; 3811 PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 3812 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, 3813 -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0}; 3814 3815 ierr = DMSetDimension(rdm, 3);CHKERRQ(ierr); 3816 ierr = DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 3817 } 3818 break; 3819 case DM_POLYTOPE_TRI_PRISM: 3820 { 3821 PetscInt numPoints[2] = {6, 1}; 3822 PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 3823 PetscInt cones[6] = {1, 3, 2, 4, 5, 6}; 3824 PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 3825 PetscScalar vertexCoords[18] = {-1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 3826 -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0}; 3827 3828 ierr = DMSetDimension(rdm, 3);CHKERRQ(ierr); 3829 ierr = DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 3830 } 3831 break; 3832 case DM_POLYTOPE_TRI_PRISM_TENSOR: 3833 { 3834 PetscInt numPoints[2] = {6, 1}; 3835 PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 3836 PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 3837 PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 3838 PetscScalar vertexCoords[18] = {-1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 3839 -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0}; 3840 3841 ierr = DMSetDimension(rdm, 3);CHKERRQ(ierr); 3842 ierr = DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 3843 } 3844 break; 3845 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 3846 { 3847 PetscInt numPoints[2] = {8, 1}; 3848 PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 3849 PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 3850 PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 3851 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, 3852 -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0}; 3853 3854 ierr = DMSetDimension(rdm, 3);CHKERRQ(ierr); 3855 ierr = DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 3856 } 3857 break; 3858 default: SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]); 3859 } 3860 { 3861 PetscInt Nv, v; 3862 3863 /* Must create the celltype label here so that we do not automatically try to compute the types */ 3864 ierr = DMCreateLabel(rdm, "celltype");CHKERRQ(ierr); 3865 ierr = DMPlexSetCellType(rdm, 0, ct);CHKERRQ(ierr); 3866 ierr = DMPlexGetChart(rdm, NULL, &Nv);CHKERRQ(ierr); 3867 for (v = 1; v < Nv; ++v) {ierr = DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT);CHKERRQ(ierr);} 3868 } 3869 ierr = DMPlexInterpolate(rdm, refdm);CHKERRQ(ierr); 3870 if (rdm->coordinateDM) { 3871 DM ncdm; 3872 PetscSection cs; 3873 PetscInt pEnd = -1; 3874 3875 ierr = DMGetLocalSection(rdm->coordinateDM, &cs);CHKERRQ(ierr); 3876 if (cs) {ierr = PetscSectionGetChart(cs, NULL, &pEnd);CHKERRQ(ierr);} 3877 if (pEnd >= 0) { 3878 ierr = DMClone(*refdm, &ncdm);CHKERRQ(ierr); 3879 ierr = DMCopyDisc(rdm->coordinateDM, ncdm);CHKERRQ(ierr); 3880 ierr = DMSetLocalSection(ncdm, cs);CHKERRQ(ierr); 3881 ierr = DMSetCoordinateDM(*refdm, ncdm);CHKERRQ(ierr); 3882 ierr = DMDestroy(&ncdm);CHKERRQ(ierr); 3883 } 3884 } 3885 ierr = DMGetCoordinatesLocal(rdm, &coords);CHKERRQ(ierr); 3886 if (coords) { 3887 ierr = DMSetCoordinatesLocal(*refdm, coords);CHKERRQ(ierr); 3888 } else { 3889 ierr = DMGetCoordinates(rdm, &coords);CHKERRQ(ierr); 3890 if (coords) {ierr = DMSetCoordinates(*refdm, coords);CHKERRQ(ierr);} 3891 } 3892 ierr = DMDestroy(&rdm);CHKERRQ(ierr); 3893 PetscFunctionReturn(0); 3894 } 3895 3896 /*@ 3897 DMPlexCreateReferenceCell - Create a DMPLEX with the appropriate FEM reference cell 3898 3899 Collective 3900 3901 Input Parameters: 3902 + comm - The communicator 3903 . dim - The spatial dimension 3904 - simplex - Flag for simplex, otherwise use a tensor-product cell 3905 3906 Output Parameter: 3907 . refdm - The reference cell 3908 3909 Level: intermediate 3910 3911 .seealso: DMPlexCreateReferenceCellByType(), DMPlexCreateBoxMesh() 3912 @*/ 3913 PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, PetscInt dim, PetscBool simplex, DM *refdm) 3914 { 3915 PetscErrorCode ierr; 3916 3917 PetscFunctionBeginUser; 3918 switch (dim) { 3919 case 0: ierr = DMPlexCreateReferenceCellByType(comm, DM_POLYTOPE_POINT, refdm);CHKERRQ(ierr);break; 3920 case 1: ierr = DMPlexCreateReferenceCellByType(comm, DM_POLYTOPE_SEGMENT, refdm);CHKERRQ(ierr);break; 3921 case 2: 3922 if (simplex) {ierr = DMPlexCreateReferenceCellByType(comm, DM_POLYTOPE_TRIANGLE, refdm);CHKERRQ(ierr);} 3923 else {ierr = DMPlexCreateReferenceCellByType(comm, DM_POLYTOPE_QUADRILATERAL, refdm);CHKERRQ(ierr);} 3924 break; 3925 case 3: 3926 if (simplex) {ierr = DMPlexCreateReferenceCellByType(comm, DM_POLYTOPE_TETRAHEDRON, refdm);CHKERRQ(ierr);} 3927 else {ierr = DMPlexCreateReferenceCellByType(comm, DM_POLYTOPE_HEXAHEDRON, refdm);CHKERRQ(ierr);} 3928 break; 3929 default: 3930 SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Cannot create reference cell for dimension %D", dim); 3931 } 3932 PetscFunctionReturn(0); 3933 } 3934