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