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