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);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) { 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) { 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) numCells = segments; 698 if (!rank) 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) { 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 ? edges[0] : 0; 801 const PetscInt numYEdges = !rank ? edges[1] : 0; 802 const PetscInt numZEdges = !rank ? edges[2] : 0; 803 const PetscInt numXVertices = !rank ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0]+1) : 0; 804 const PetscInt numYVertices = !rank ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1]+1) : 0; 805 const PetscInt numZVertices = !rank ? (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[], PetscBool orderHeight, PetscBool interpolate) 1273 { 1274 DM bdm, vol; 1275 PetscReal normal[3] = {0., 0., 1.}; 1276 PetscInt i; 1277 PetscErrorCode ierr; 1278 1279 PetscFunctionBegin; 1280 for (i = 0; i < 3; ++i) if (periodicity[i] != DM_BOUNDARY_NONE) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Periodicity not yet supported"); 1281 ierr = DMCreate(PetscObjectComm((PetscObject) dm), &bdm);CHKERRQ(ierr); 1282 ierr = DMSetType(bdm, DMPLEX);CHKERRQ(ierr); 1283 ierr = DMSetDimension(bdm, 2);CHKERRQ(ierr); 1284 ierr = DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, interpolate);CHKERRQ(ierr); 1285 ierr = DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], orderHeight, normal, interpolate, &vol);CHKERRQ(ierr); 1286 ierr = DMDestroy(&bdm);CHKERRQ(ierr); 1287 ierr = DMPlexReplace_Static(dm, &vol);CHKERRQ(ierr); 1288 if (lower[2] != 0.0) { 1289 Vec v; 1290 PetscScalar *x; 1291 PetscInt cDim, n; 1292 1293 ierr = DMGetCoordinatesLocal(dm, &v);CHKERRQ(ierr); 1294 ierr = VecGetBlockSize(v, &cDim);CHKERRQ(ierr); 1295 ierr = VecGetLocalSize(v, &n);CHKERRQ(ierr); 1296 ierr = VecGetArray(v, &x);CHKERRQ(ierr); 1297 x += cDim; 1298 for (i = 0; i < n; i += cDim) x[i] += lower[2]; 1299 ierr = VecRestoreArray(v,&x);CHKERRQ(ierr); 1300 ierr = DMSetCoordinatesLocal(dm, v);CHKERRQ(ierr); 1301 } 1302 PetscFunctionReturn(0); 1303 } 1304 1305 /*@ 1306 DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tesselating the (x,y) plane and extruding in the third direction using wedge cells. 1307 1308 Collective 1309 1310 Input Parameters: 1311 + comm - The communicator for the DM object 1312 . faces - Number of faces per dimension, or NULL for (1, 1, 1) 1313 . lower - The lower left corner, or NULL for (0, 0, 0) 1314 . upper - The upper right corner, or NULL for (1, 1, 1) 1315 . periodicity - The boundary type for the X,Y,Z direction, or NULL for DM_BOUNDARY_NONE 1316 . orderHeight - If PETSC_TRUE, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first 1317 - interpolate - Flag to create intermediate mesh pieces (edges, faces) 1318 1319 Output Parameter: 1320 . dm - The DM object 1321 1322 Level: beginner 1323 1324 .seealso: DMPlexCreateHexCylinderMesh(), DMPlexCreateWedgeCylinderMesh(), DMPlexExtrude(), DMPlexCreateBoxMesh(), DMSetType(), DMCreate() 1325 @*/ 1326 PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm) 1327 { 1328 PetscInt fac[3] = {1, 1, 1}; 1329 PetscReal low[3] = {0, 0, 0}; 1330 PetscReal upp[3] = {1, 1, 1}; 1331 DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 1332 PetscErrorCode ierr; 1333 1334 PetscFunctionBegin; 1335 ierr = DMCreate(comm,dm);CHKERRQ(ierr); 1336 ierr = DMSetType(*dm,DMPLEX);CHKERRQ(ierr); 1337 ierr = DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, orderHeight, interpolate);CHKERRQ(ierr); 1338 PetscFunctionReturn(0); 1339 } 1340 1341 /*@C 1342 DMPlexExtrude - Creates a (d+1)-D mesh by extruding a d-D mesh in the normal direction using prismatic cells. 1343 1344 Collective on idm 1345 1346 Input Parameters: 1347 + idm - The mesh to be extruded 1348 . layers - The number of layers, or PETSC_DETERMINE to use the default 1349 . height - The total height of the extrusion, or PETSC_DETERMINE to use the default 1350 . orderHeight - If PETSC_TRUE, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first 1351 . extNormal - The normal direction in which the mesh should be extruded, or NULL to extrude using the surface normal 1352 - interpolate - Flag to create intermediate mesh pieces (edges, faces) 1353 1354 Output Parameter: 1355 . dm - The DM object 1356 1357 Notes: 1358 The mesh created has prismatic cells, and the vertex ordering in the cone of the cell is that of the tensor prismatic cells. Not currently supported in Fortran. 1359 1360 Options Database Keys: 1361 + -dm_plex_extrude_layers <k> - Sets the number of layers k 1362 . -dm_plex_extrude_height <h> - Sets the total height of the extrusion 1363 . -dm_plex_extrude_heights <h0,h1,...> - Sets the height of each layer 1364 . -dm_plex_extrude_order_height - If true, order cells by height first 1365 - -dm_plex_extrude_normal <n0,...,nd> - Sets the normal vector along which to extrude 1366 1367 Level: advanced 1368 1369 .seealso: DMPlexCreateWedgeCylinderMesh(), DMPlexCreateWedgeBoxMesh(), DMSetType(), DMCreate() 1370 @*/ 1371 PetscErrorCode DMPlexExtrude(DM idm, PetscInt layers, PetscReal height, PetscBool orderHeight, const PetscReal extNormal[], PetscBool interpolate, DM* dm) 1372 { 1373 PetscScalar *coordsB; 1374 const PetscScalar *coordsA; 1375 PetscReal *normals = NULL, *heights = NULL; 1376 PetscReal clNormal[3]; 1377 Vec coordinatesA, coordinatesB; 1378 PetscSection coordSectionA, coordSectionB; 1379 PetscInt dim, cDim, cDimB, c, l, v, coordSize, *newCone, nl; 1380 PetscInt cStart, cEnd, vStart, vEnd, cellV, numCells, numVertices; 1381 const char *prefix; 1382 PetscBool haveCLNormal, flg; 1383 PetscErrorCode ierr; 1384 1385 PetscFunctionBegin; 1386 PetscValidHeaderSpecific(idm, DM_CLASSID, 1); 1387 PetscValidLogicalCollectiveInt(idm, layers, 2); 1388 PetscValidLogicalCollectiveReal(idm, height, 3); 1389 PetscValidLogicalCollectiveBool(idm, interpolate, 6); 1390 ierr = DMGetDimension(idm, &dim);CHKERRQ(ierr); 1391 ierr = DMGetCoordinateDim(idm, &cDim);CHKERRQ(ierr); 1392 cDimB = cDim == dim ? cDim+1 : cDim; 1393 if (dim < 1 || dim > 3) SETERRQ1(PetscObjectComm((PetscObject)idm), PETSC_ERR_SUP, "Support for dimension %D not coded", dim); 1394 1395 ierr = PetscObjectGetOptionsPrefix((PetscObject) idm, &prefix);CHKERRQ(ierr); 1396 if (layers < 0) layers = 1; 1397 ierr = PetscOptionsGetInt(NULL, prefix, "-dm_plex_extrude_layers", &layers, NULL);CHKERRQ(ierr); 1398 if (layers <= 0) SETERRQ1(PetscObjectComm((PetscObject) idm), PETSC_ERR_ARG_OUTOFRANGE, "Number of layers %D must be positive", layers); 1399 if (height < 0.) height = 1.; 1400 ierr = PetscOptionsGetReal(NULL, prefix, "-dm_plex_extrude_height", &height, NULL);CHKERRQ(ierr); 1401 if (height <= 0.) SETERRQ1(PetscObjectComm((PetscObject) idm), PETSC_ERR_ARG_OUTOFRANGE, "Height of layers %g must be positive", (double) height); 1402 ierr = PetscMalloc1(layers, &heights);CHKERRQ(ierr); 1403 nl = layers; 1404 ierr = PetscOptionsGetRealArray(NULL, prefix, "-dm_plex_extrude_heights", heights, &nl, &flg);CHKERRQ(ierr); 1405 if (flg) { 1406 if (!nl) SETERRQ(PetscObjectComm((PetscObject) idm), PETSC_ERR_ARG_OUTOFRANGE, "Must give at least one height for -dm_plex_extrude_heights"); 1407 for (l = nl; l < layers; ++l) heights[l] = heights[l-1]; 1408 for (l = 0; l < layers; ++l) if (heights[l] <= 0.) SETERRQ2(PetscObjectComm((PetscObject) idm), PETSC_ERR_ARG_OUTOFRANGE, "Height %g of layers %D must be positive", (double) heights[l], l); 1409 } else { 1410 for (l = 0; l < layers; ++l) heights[l] = height/layers; 1411 } 1412 ierr = PetscOptionsGetBool(NULL, prefix, "-dm_plex_extrude_order_height", &orderHeight, NULL);CHKERRQ(ierr); 1413 c = 3; 1414 ierr = PetscOptionsGetRealArray(NULL, prefix, "-dm_plex_extrude_normal", clNormal, &c, &haveCLNormal);CHKERRQ(ierr); 1415 if (haveCLNormal && c != cDimB) SETERRQ2(PetscObjectComm((PetscObject)idm), PETSC_ERR_ARG_SIZ, "Input normal has size %D != %D extruded coordinate dimension", c, cDimB); 1416 1417 ierr = DMPlexGetHeightStratum(idm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1418 ierr = DMPlexGetDepthStratum(idm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1419 numCells = (cEnd - cStart)*layers; 1420 numVertices = (vEnd - vStart)*(layers+1); 1421 ierr = DMCreate(PetscObjectComm((PetscObject)idm), dm);CHKERRQ(ierr); 1422 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 1423 ierr = DMSetDimension(*dm, dim+1);CHKERRQ(ierr); 1424 ierr = DMPlexSetChart(*dm, 0, numCells+numVertices);CHKERRQ(ierr); 1425 /* Must create the celltype label here so that we do not automatically try to compute the types */ 1426 ierr = DMCreateLabel(*dm, "celltype");CHKERRQ(ierr); 1427 for (c = cStart, cellV = 0; c < cEnd; ++c) { 1428 DMPolytopeType ct, nct; 1429 PetscInt *closure = NULL; 1430 PetscInt closureSize, numCorners = 0; 1431 1432 ierr = DMPlexGetCellType(idm, c, &ct);CHKERRQ(ierr); 1433 switch (ct) { 1434 case DM_POLYTOPE_SEGMENT: nct = DM_POLYTOPE_SEG_PRISM_TENSOR;break; 1435 case DM_POLYTOPE_TRIANGLE: nct = DM_POLYTOPE_TRI_PRISM_TENSOR;break; 1436 case DM_POLYTOPE_QUADRILATERAL: nct = DM_POLYTOPE_QUAD_PRISM_TENSOR;break; 1437 default: nct = DM_POLYTOPE_UNKNOWN; 1438 } 1439 ierr = DMPlexGetTransitiveClosure(idm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1440 for (v = 0; v < closureSize*2; v += 2) if ((closure[v] >= vStart) && (closure[v] < vEnd)) numCorners++; 1441 ierr = DMPlexRestoreTransitiveClosure(idm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1442 for (l = 0; l < layers; ++l) { 1443 const PetscInt cell = orderHeight ? layers*(c - cStart) + l : l*(cEnd - cStart) + c - cStart; 1444 1445 ierr = DMPlexSetConeSize(*dm, cell, 2*numCorners);CHKERRQ(ierr); 1446 ierr = DMPlexSetCellType(*dm, cell, nct);CHKERRQ(ierr); 1447 } 1448 cellV = PetscMax(numCorners,cellV); 1449 } 1450 ierr = DMSetUp(*dm);CHKERRQ(ierr); 1451 1452 if (dim != cDim && !(extNormal || haveCLNormal)) {ierr = PetscCalloc1(cDim*(vEnd - vStart), &normals);CHKERRQ(ierr);} 1453 ierr = PetscMalloc1(3*cellV,&newCone);CHKERRQ(ierr); 1454 for (c = cStart; c < cEnd; ++c) { 1455 PetscInt *closure = NULL; 1456 PetscInt closureSize, numCorners = 0, l; 1457 PetscReal normal[3] = {0, 0, 0}; 1458 1459 if (normals) {ierr = DMPlexComputeCellGeometryFVM(idm, c, NULL, NULL, normal);CHKERRQ(ierr);} 1460 ierr = DMPlexGetTransitiveClosure(idm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1461 for (v = 0; v < closureSize*2; v += 2) { 1462 if ((closure[v] >= vStart) && (closure[v] < vEnd)) { 1463 PetscInt d; 1464 1465 newCone[numCorners++] = closure[v] - vStart; 1466 if (normals) {for (d = 0; d < cDim; ++d) normals[cDim*(closure[v]-vStart)+d] += normal[d];} 1467 } 1468 } 1469 ierr = DMPlexRestoreTransitiveClosure(idm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1470 for (l = 0; l < layers; ++l) { 1471 PetscInt i; 1472 1473 for (i = 0; i < numCorners; ++i) { 1474 newCone[ numCorners + i] = orderHeight ? (layers+1)*newCone[i] + l + numCells : l*(vEnd - vStart) + newCone[i] + numCells; 1475 newCone[2*numCorners + i] = orderHeight ? (layers+1)*newCone[i] + l + 1 + numCells : (l+1)*(vEnd - vStart) + newCone[i] + numCells; 1476 } 1477 ierr = DMPlexSetCone(*dm, orderHeight ? layers*(c - cStart) + l : l*(cEnd - cStart) + c - cStart, newCone + numCorners);CHKERRQ(ierr); 1478 } 1479 } 1480 ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr); 1481 ierr = DMPlexStratify(*dm);CHKERRQ(ierr); 1482 ierr = PetscFree(newCone);CHKERRQ(ierr); 1483 1484 ierr = DMGetCoordinateSection(*dm, &coordSectionB);CHKERRQ(ierr); 1485 ierr = PetscSectionSetNumFields(coordSectionB, 1);CHKERRQ(ierr); 1486 ierr = PetscSectionSetFieldComponents(coordSectionB, 0, cDimB);CHKERRQ(ierr); 1487 ierr = PetscSectionSetChart(coordSectionB, numCells, numCells+numVertices);CHKERRQ(ierr); 1488 for (v = numCells; v < numCells+numVertices; ++v) { 1489 ierr = PetscSectionSetDof(coordSectionB, v, cDimB);CHKERRQ(ierr); 1490 ierr = PetscSectionSetFieldDof(coordSectionB, v, 0, cDimB);CHKERRQ(ierr); 1491 ierr = DMPlexSetCellType(*dm, v, DM_POLYTOPE_POINT);CHKERRQ(ierr); 1492 } 1493 ierr = PetscSectionSetUp(coordSectionB);CHKERRQ(ierr); 1494 ierr = PetscSectionGetStorageSize(coordSectionB, &coordSize);CHKERRQ(ierr); 1495 ierr = VecCreate(PETSC_COMM_SELF, &coordinatesB);CHKERRQ(ierr); 1496 ierr = PetscObjectSetName((PetscObject) coordinatesB, "coordinates");CHKERRQ(ierr); 1497 ierr = VecSetSizes(coordinatesB, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 1498 ierr = VecSetBlockSize(coordinatesB, cDimB);CHKERRQ(ierr); 1499 ierr = VecSetType(coordinatesB,VECSTANDARD);CHKERRQ(ierr); 1500 1501 ierr = DMGetCoordinateSection(idm, &coordSectionA);CHKERRQ(ierr); 1502 ierr = DMGetCoordinatesLocal(idm, &coordinatesA);CHKERRQ(ierr); 1503 ierr = VecGetArray(coordinatesB, &coordsB);CHKERRQ(ierr); 1504 ierr = VecGetArrayRead(coordinatesA, &coordsA);CHKERRQ(ierr); 1505 for (v = vStart; v < vEnd; ++v) { 1506 const PetscScalar *cptr; 1507 PetscReal ones2[2] = { 0., 1.}, ones3[3] = { 0., 0., 1.}; 1508 PetscReal normal[3]; 1509 PetscReal norm; 1510 PetscInt offA, d, cDimA = cDim; 1511 1512 if (normals) {for (d = 0; d < cDimB; ++d) normal[d] = normals[cDimB*(v - vStart)+d];} 1513 else if (haveCLNormal) {for (d = 0; d < cDimB; ++d) normal[d] = clNormal[d];} 1514 else if (extNormal) {for (d = 0; d < cDimB; ++d) normal[d] = extNormal[d];} 1515 else if (cDimB == 2) {for (d = 0; d < cDimB; ++d) normal[d] = ones2[d];} 1516 else if (cDimB == 3) {for (d = 0; d < cDimB; ++d) normal[d] = ones3[d];} 1517 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unable to determine normal for extrusion"); 1518 for (d = 0, norm = 0.0; d < cDimB; ++d) norm += normal[d]*normal[d]; 1519 for (d = 0; d < cDimB; ++d) normal[d] *= 1./PetscSqrtReal(norm); 1520 1521 ierr = PetscSectionGetOffset(coordSectionA, v, &offA);CHKERRQ(ierr); 1522 cptr = coordsA + offA; 1523 for (l = 0; l <= layers; ++l) { 1524 PetscInt offB, d, newV; 1525 1526 newV = orderHeight ? (layers+1)*(v -vStart) + l + numCells : (vEnd -vStart)*l + (v -vStart) + numCells; 1527 ierr = PetscSectionGetOffset(coordSectionB, newV, &offB);CHKERRQ(ierr); 1528 for (d = 0; d < cDimA; ++d) { coordsB[offB+d] = cptr[d]; } 1529 for (d = 0; d < cDimB; ++d) { coordsB[offB+d] += l ? normal[d]*heights[l-1] : 0.0; } 1530 cptr = coordsB + offB; 1531 cDimA = cDimB; 1532 } 1533 } 1534 ierr = VecRestoreArrayRead(coordinatesA, &coordsA);CHKERRQ(ierr); 1535 ierr = VecRestoreArray(coordinatesB, &coordsB);CHKERRQ(ierr); 1536 ierr = DMSetCoordinatesLocal(*dm, coordinatesB);CHKERRQ(ierr); 1537 ierr = VecDestroy(&coordinatesB);CHKERRQ(ierr); 1538 ierr = PetscFree(normals);CHKERRQ(ierr); 1539 ierr = PetscFree(heights);CHKERRQ(ierr); 1540 if (interpolate) { 1541 DM idm; 1542 1543 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 1544 ierr = DMPlexCopyCoordinates(*dm, idm);CHKERRQ(ierr); 1545 ierr = DMDestroy(dm);CHKERRQ(ierr); 1546 *dm = idm; 1547 } 1548 PetscFunctionReturn(0); 1549 } 1550 1551 /*@C 1552 DMPlexSetOptionsPrefix - Sets the prefix used for searching for all DM options in the database. 1553 1554 Logically Collective on dm 1555 1556 Input Parameters: 1557 + dm - the DM context 1558 - prefix - the prefix to prepend to all option names 1559 1560 Notes: 1561 A hyphen (-) must NOT be given at the beginning of the prefix name. 1562 The first character of all runtime options is AUTOMATICALLY the hyphen. 1563 1564 Level: advanced 1565 1566 .seealso: SNESSetFromOptions() 1567 @*/ 1568 PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[]) 1569 { 1570 DM_Plex *mesh = (DM_Plex *) dm->data; 1571 PetscErrorCode ierr; 1572 1573 PetscFunctionBegin; 1574 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1575 ierr = PetscObjectSetOptionsPrefix((PetscObject) dm, prefix);CHKERRQ(ierr); 1576 ierr = PetscObjectSetOptionsPrefix((PetscObject) mesh->partitioner, prefix);CHKERRQ(ierr); 1577 PetscFunctionReturn(0); 1578 } 1579 1580 /* Remap geometry to cylinder 1581 TODO: This only works for a single refinement, then it is broken 1582 1583 Interior square: Linear interpolation is correct 1584 The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing 1585 such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance 1586 1587 phi = arctan(y/x) 1588 d_close = sqrt(1/8 + 1/4 sin^2(phi)) 1589 d_far = sqrt(1/2 + sin^2(phi)) 1590 1591 so we remap them using 1592 1593 x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close) 1594 y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close) 1595 1596 If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y. 1597 */ 1598 static void snapToCylinder(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1599 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1600 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1601 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 1602 { 1603 const PetscReal dis = 1.0/PetscSqrtReal(2.0); 1604 const PetscReal ds2 = 0.5*dis; 1605 1606 if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) { 1607 f0[0] = u[0]; 1608 f0[1] = u[1]; 1609 } else { 1610 PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc; 1611 1612 x = PetscRealPart(u[0]); 1613 y = PetscRealPart(u[1]); 1614 phi = PetscAtan2Real(y, x); 1615 sinp = PetscSinReal(phi); 1616 cosp = PetscCosReal(phi); 1617 if ((PetscAbsReal(phi) > PETSC_PI/4.0) && (PetscAbsReal(phi) < 3.0*PETSC_PI/4.0)) { 1618 dc = PetscAbsReal(ds2/sinp); 1619 df = PetscAbsReal(dis/sinp); 1620 xc = ds2*x/PetscAbsReal(y); 1621 yc = ds2*PetscSignReal(y); 1622 } else { 1623 dc = PetscAbsReal(ds2/cosp); 1624 df = PetscAbsReal(dis/cosp); 1625 xc = ds2*PetscSignReal(x); 1626 yc = ds2*y/PetscAbsReal(x); 1627 } 1628 f0[0] = xc + (u[0] - xc)*(1.0 - dc)/(df - dc); 1629 f0[1] = yc + (u[1] - yc)*(1.0 - dc)/(df - dc); 1630 } 1631 f0[2] = u[2]; 1632 } 1633 1634 static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ) 1635 { 1636 const PetscInt dim = 3; 1637 PetscInt numCells, numVertices; 1638 PetscMPIInt rank; 1639 PetscErrorCode ierr; 1640 1641 PetscFunctionBegin; 1642 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 1643 ierr = DMSetDimension(dm, dim);CHKERRQ(ierr); 1644 /* Create topology */ 1645 { 1646 PetscInt cone[8], c; 1647 1648 numCells = !rank ? 5 : 0; 1649 numVertices = !rank ? 16 : 0; 1650 if (periodicZ == DM_BOUNDARY_PERIODIC) { 1651 numCells *= 3; 1652 numVertices = !rank ? 24 : 0; 1653 } 1654 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 1655 for (c = 0; c < numCells; c++) {ierr = DMPlexSetConeSize(dm, c, 8);CHKERRQ(ierr);} 1656 ierr = DMSetUp(dm);CHKERRQ(ierr); 1657 if (!rank) { 1658 if (periodicZ == DM_BOUNDARY_PERIODIC) { 1659 cone[0] = 15; cone[1] = 18; cone[2] = 17; cone[3] = 16; 1660 cone[4] = 31; cone[5] = 32; cone[6] = 33; cone[7] = 34; 1661 ierr = DMPlexSetCone(dm, 0, cone);CHKERRQ(ierr); 1662 cone[0] = 16; cone[1] = 17; cone[2] = 24; cone[3] = 23; 1663 cone[4] = 32; cone[5] = 36; cone[6] = 37; cone[7] = 33; /* 22 25 26 21 */ 1664 ierr = DMPlexSetCone(dm, 1, cone);CHKERRQ(ierr); 1665 cone[0] = 18; cone[1] = 27; cone[2] = 24; cone[3] = 17; 1666 cone[4] = 34; cone[5] = 33; cone[6] = 37; cone[7] = 38; 1667 ierr = DMPlexSetCone(dm, 2, cone);CHKERRQ(ierr); 1668 cone[0] = 29; cone[1] = 27; cone[2] = 18; cone[3] = 15; 1669 cone[4] = 35; cone[5] = 31; cone[6] = 34; cone[7] = 38; 1670 ierr = DMPlexSetCone(dm, 3, cone);CHKERRQ(ierr); 1671 cone[0] = 29; cone[1] = 15; cone[2] = 16; cone[3] = 23; 1672 cone[4] = 35; cone[5] = 36; cone[6] = 32; cone[7] = 31; 1673 ierr = DMPlexSetCone(dm, 4, cone);CHKERRQ(ierr); 1674 1675 cone[0] = 31; cone[1] = 34; cone[2] = 33; cone[3] = 32; 1676 cone[4] = 19; cone[5] = 22; cone[6] = 21; cone[7] = 20; 1677 ierr = DMPlexSetCone(dm, 5, cone);CHKERRQ(ierr); 1678 cone[0] = 32; cone[1] = 33; cone[2] = 37; cone[3] = 36; 1679 cone[4] = 22; cone[5] = 25; cone[6] = 26; cone[7] = 21; 1680 ierr = DMPlexSetCone(dm, 6, cone);CHKERRQ(ierr); 1681 cone[0] = 34; cone[1] = 38; cone[2] = 37; cone[3] = 33; 1682 cone[4] = 20; cone[5] = 21; cone[6] = 26; cone[7] = 28; 1683 ierr = DMPlexSetCone(dm, 7, cone);CHKERRQ(ierr); 1684 cone[0] = 35; cone[1] = 38; cone[2] = 34; cone[3] = 31; 1685 cone[4] = 30; cone[5] = 19; cone[6] = 20; cone[7] = 28; 1686 ierr = DMPlexSetCone(dm, 8, cone);CHKERRQ(ierr); 1687 cone[0] = 35; cone[1] = 31; cone[2] = 32; cone[3] = 36; 1688 cone[4] = 30; cone[5] = 25; cone[6] = 22; cone[7] = 19; 1689 ierr = DMPlexSetCone(dm, 9, cone);CHKERRQ(ierr); 1690 1691 cone[0] = 19; cone[1] = 20; cone[2] = 21; cone[3] = 22; 1692 cone[4] = 15; cone[5] = 16; cone[6] = 17; cone[7] = 18; 1693 ierr = DMPlexSetCone(dm, 10, cone);CHKERRQ(ierr); 1694 cone[0] = 22; cone[1] = 21; cone[2] = 26; cone[3] = 25; 1695 cone[4] = 16; cone[5] = 23; cone[6] = 24; cone[7] = 17; 1696 ierr = DMPlexSetCone(dm, 11, cone);CHKERRQ(ierr); 1697 cone[0] = 20; cone[1] = 28; cone[2] = 26; cone[3] = 21; 1698 cone[4] = 18; cone[5] = 17; cone[6] = 24; cone[7] = 27; 1699 ierr = DMPlexSetCone(dm, 12, cone);CHKERRQ(ierr); 1700 cone[0] = 30; cone[1] = 28; cone[2] = 20; cone[3] = 19; 1701 cone[4] = 29; cone[5] = 15; cone[6] = 18; cone[7] = 27; 1702 ierr = DMPlexSetCone(dm, 13, cone);CHKERRQ(ierr); 1703 cone[0] = 30; cone[1] = 19; cone[2] = 22; cone[3] = 25; 1704 cone[4] = 29; cone[5] = 23; cone[6] = 16; cone[7] = 15; 1705 ierr = DMPlexSetCone(dm, 14, cone);CHKERRQ(ierr); 1706 } else { 1707 cone[0] = 5; cone[1] = 8; cone[2] = 7; cone[3] = 6; 1708 cone[4] = 9; cone[5] = 12; cone[6] = 11; cone[7] = 10; 1709 ierr = DMPlexSetCone(dm, 0, cone);CHKERRQ(ierr); 1710 cone[0] = 6; cone[1] = 7; cone[2] = 14; cone[3] = 13; 1711 cone[4] = 12; cone[5] = 15; cone[6] = 16; cone[7] = 11; 1712 ierr = DMPlexSetCone(dm, 1, cone);CHKERRQ(ierr); 1713 cone[0] = 8; cone[1] = 17; cone[2] = 14; cone[3] = 7; 1714 cone[4] = 10; cone[5] = 11; cone[6] = 16; cone[7] = 18; 1715 ierr = DMPlexSetCone(dm, 2, cone);CHKERRQ(ierr); 1716 cone[0] = 19; cone[1] = 17; cone[2] = 8; cone[3] = 5; 1717 cone[4] = 20; cone[5] = 9; cone[6] = 10; cone[7] = 18; 1718 ierr = DMPlexSetCone(dm, 3, cone);CHKERRQ(ierr); 1719 cone[0] = 19; cone[1] = 5; cone[2] = 6; cone[3] = 13; 1720 cone[4] = 20; cone[5] = 15; cone[6] = 12; cone[7] = 9; 1721 ierr = DMPlexSetCone(dm, 4, cone);CHKERRQ(ierr); 1722 } 1723 } 1724 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 1725 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 1726 } 1727 /* Create cube geometry */ 1728 { 1729 Vec coordinates; 1730 PetscSection coordSection; 1731 PetscScalar *coords; 1732 PetscInt coordSize, v; 1733 const PetscReal dis = 1.0/PetscSqrtReal(2.0); 1734 const PetscReal ds2 = dis/2.0; 1735 1736 /* Build coordinates */ 1737 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 1738 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 1739 ierr = PetscSectionSetFieldComponents(coordSection, 0, dim);CHKERRQ(ierr); 1740 ierr = PetscSectionSetChart(coordSection, numCells, numCells+numVertices);CHKERRQ(ierr); 1741 for (v = numCells; v < numCells+numVertices; ++v) { 1742 ierr = PetscSectionSetDof(coordSection, v, dim);CHKERRQ(ierr); 1743 ierr = PetscSectionSetFieldDof(coordSection, v, 0, dim);CHKERRQ(ierr); 1744 } 1745 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 1746 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 1747 ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr); 1748 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 1749 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 1750 ierr = VecSetBlockSize(coordinates, dim);CHKERRQ(ierr); 1751 ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr); 1752 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 1753 if (!rank) { 1754 coords[0*dim+0] = -ds2; coords[0*dim+1] = -ds2; coords[0*dim+2] = 0.0; 1755 coords[1*dim+0] = ds2; coords[1*dim+1] = -ds2; coords[1*dim+2] = 0.0; 1756 coords[2*dim+0] = ds2; coords[2*dim+1] = ds2; coords[2*dim+2] = 0.0; 1757 coords[3*dim+0] = -ds2; coords[3*dim+1] = ds2; coords[3*dim+2] = 0.0; 1758 coords[4*dim+0] = -ds2; coords[4*dim+1] = -ds2; coords[4*dim+2] = 1.0; 1759 coords[5*dim+0] = -ds2; coords[5*dim+1] = ds2; coords[5*dim+2] = 1.0; 1760 coords[6*dim+0] = ds2; coords[6*dim+1] = ds2; coords[6*dim+2] = 1.0; 1761 coords[7*dim+0] = ds2; coords[7*dim+1] = -ds2; coords[7*dim+2] = 1.0; 1762 coords[ 8*dim+0] = dis; coords[ 8*dim+1] = -dis; coords[ 8*dim+2] = 0.0; 1763 coords[ 9*dim+0] = dis; coords[ 9*dim+1] = dis; coords[ 9*dim+2] = 0.0; 1764 coords[10*dim+0] = dis; coords[10*dim+1] = -dis; coords[10*dim+2] = 1.0; 1765 coords[11*dim+0] = dis; coords[11*dim+1] = dis; coords[11*dim+2] = 1.0; 1766 coords[12*dim+0] = -dis; coords[12*dim+1] = dis; coords[12*dim+2] = 0.0; 1767 coords[13*dim+0] = -dis; coords[13*dim+1] = dis; coords[13*dim+2] = 1.0; 1768 coords[14*dim+0] = -dis; coords[14*dim+1] = -dis; coords[14*dim+2] = 0.0; 1769 coords[15*dim+0] = -dis; coords[15*dim+1] = -dis; coords[15*dim+2] = 1.0; 1770 if (periodicZ == DM_BOUNDARY_PERIODIC) { 1771 /* 15 31 19 */ coords[16*dim+0] = -ds2; coords[16*dim+1] = -ds2; coords[16*dim+2] = 0.5; 1772 /* 16 32 22 */ coords[17*dim+0] = ds2; coords[17*dim+1] = -ds2; coords[17*dim+2] = 0.5; 1773 /* 17 33 21 */ coords[18*dim+0] = ds2; coords[18*dim+1] = ds2; coords[18*dim+2] = 0.5; 1774 /* 18 34 20 */ coords[19*dim+0] = -ds2; coords[19*dim+1] = ds2; coords[19*dim+2] = 0.5; 1775 /* 29 35 30 */ coords[20*dim+0] = -dis; coords[20*dim+1] = -dis; coords[20*dim+2] = 0.5; 1776 /* 23 36 25 */ coords[21*dim+0] = dis; coords[21*dim+1] = -dis; coords[21*dim+2] = 0.5; 1777 /* 24 37 26 */ coords[22*dim+0] = dis; coords[22*dim+1] = dis; coords[22*dim+2] = 0.5; 1778 /* 27 38 28 */ coords[23*dim+0] = -dis; coords[23*dim+1] = dis; coords[23*dim+2] = 0.5; 1779 } 1780 } 1781 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 1782 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 1783 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 1784 } 1785 /* Create periodicity */ 1786 if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) { 1787 PetscReal L[3]; 1788 PetscReal maxCell[3]; 1789 DMBoundaryType bdType[3]; 1790 PetscReal lower[3] = {0.0, 0.0, 0.0}; 1791 PetscReal upper[3] = {1.0, 1.0, 1.5}; 1792 PetscInt i, numZCells = 3; 1793 1794 bdType[0] = DM_BOUNDARY_NONE; 1795 bdType[1] = DM_BOUNDARY_NONE; 1796 bdType[2] = periodicZ; 1797 for (i = 0; i < dim; i++) { 1798 L[i] = upper[i] - lower[i]; 1799 maxCell[i] = 1.1 * (L[i] / numZCells); 1800 } 1801 ierr = DMSetPeriodicity(dm, PETSC_TRUE, maxCell, L, bdType);CHKERRQ(ierr); 1802 } 1803 { 1804 DM cdm; 1805 PetscDS cds; 1806 PetscScalar c[2] = {1.0, 1.0}; 1807 1808 ierr = DMPlexCreateCoordinateSpace(dm, 1, snapToCylinder);CHKERRQ(ierr); 1809 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 1810 ierr = DMGetDS(cdm, &cds);CHKERRQ(ierr); 1811 ierr = PetscDSSetConstants(cds, 2, c);CHKERRQ(ierr); 1812 } 1813 /* Wait for coordinate creation before doing in-place modification */ 1814 ierr = DMPlexInterpolateInPlace_Internal(dm);CHKERRQ(ierr); 1815 PetscFunctionReturn(0); 1816 } 1817 1818 /*@ 1819 DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra. 1820 1821 Collective 1822 1823 Input Parameters: 1824 + comm - The communicator for the DM object 1825 - periodicZ - The boundary type for the Z direction 1826 1827 Output Parameter: 1828 . dm - The DM object 1829 1830 Note: 1831 Here is the output numbering looking from the bottom of the cylinder: 1832 $ 17-----14 1833 $ | | 1834 $ | 2 | 1835 $ | | 1836 $ 17-----8-----7-----14 1837 $ | | | | 1838 $ | 3 | 0 | 1 | 1839 $ | | | | 1840 $ 19-----5-----6-----13 1841 $ | | 1842 $ | 4 | 1843 $ | | 1844 $ 19-----13 1845 $ 1846 $ and up through the top 1847 $ 1848 $ 18-----16 1849 $ | | 1850 $ | 2 | 1851 $ | | 1852 $ 18----10----11-----16 1853 $ | | | | 1854 $ | 3 | 0 | 1 | 1855 $ | | | | 1856 $ 20-----9----12-----15 1857 $ | | 1858 $ | 4 | 1859 $ | | 1860 $ 20-----15 1861 1862 Level: beginner 1863 1864 .seealso: DMPlexCreateBoxMesh(), DMSetType(), DMCreate() 1865 @*/ 1866 PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, DM *dm) 1867 { 1868 PetscErrorCode ierr; 1869 1870 PetscFunctionBegin; 1871 PetscValidPointer(dm, 3); 1872 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 1873 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 1874 ierr = DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ);CHKERRQ(ierr); 1875 PetscFunctionReturn(0); 1876 } 1877 1878 static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate) 1879 { 1880 const PetscInt dim = 3; 1881 PetscInt numCells, numVertices, v; 1882 PetscMPIInt rank; 1883 PetscErrorCode ierr; 1884 1885 PetscFunctionBegin; 1886 if (n < 0) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %D cannot be negative", n); 1887 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 1888 ierr = DMSetDimension(dm, dim);CHKERRQ(ierr); 1889 /* Must create the celltype label here so that we do not automatically try to compute the types */ 1890 ierr = DMCreateLabel(dm, "celltype");CHKERRQ(ierr); 1891 /* Create topology */ 1892 { 1893 PetscInt cone[6], c; 1894 1895 numCells = !rank ? n : 0; 1896 numVertices = !rank ? 2*(n+1) : 0; 1897 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 1898 for (c = 0; c < numCells; c++) {ierr = DMPlexSetConeSize(dm, c, 6);CHKERRQ(ierr);} 1899 ierr = DMSetUp(dm);CHKERRQ(ierr); 1900 for (c = 0; c < numCells; c++) { 1901 cone[0] = c+n*1; cone[1] = (c+1)%n+n*1; cone[2] = 0+3*n; 1902 cone[3] = c+n*2; cone[4] = (c+1)%n+n*2; cone[5] = 1+3*n; 1903 ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); 1904 ierr = DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR);CHKERRQ(ierr); 1905 } 1906 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 1907 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 1908 } 1909 for (v = numCells; v < numCells+numVertices; ++v) { 1910 ierr = DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT);CHKERRQ(ierr); 1911 } 1912 /* Create cylinder geometry */ 1913 { 1914 Vec coordinates; 1915 PetscSection coordSection; 1916 PetscScalar *coords; 1917 PetscInt coordSize, c; 1918 1919 /* Build coordinates */ 1920 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 1921 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 1922 ierr = PetscSectionSetFieldComponents(coordSection, 0, dim);CHKERRQ(ierr); 1923 ierr = PetscSectionSetChart(coordSection, numCells, numCells+numVertices);CHKERRQ(ierr); 1924 for (v = numCells; v < numCells+numVertices; ++v) { 1925 ierr = PetscSectionSetDof(coordSection, v, dim);CHKERRQ(ierr); 1926 ierr = PetscSectionSetFieldDof(coordSection, v, 0, dim);CHKERRQ(ierr); 1927 } 1928 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 1929 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 1930 ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr); 1931 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 1932 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 1933 ierr = VecSetBlockSize(coordinates, dim);CHKERRQ(ierr); 1934 ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr); 1935 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 1936 for (c = 0; c < numCells; c++) { 1937 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; 1938 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; 1939 } 1940 if (!rank) { 1941 coords[(2*n+0)*dim+0] = 0.0; coords[(2*n+0)*dim+1] = 0.0; coords[(2*n+0)*dim+2] = 1.0; 1942 coords[(2*n+1)*dim+0] = 0.0; coords[(2*n+1)*dim+1] = 0.0; coords[(2*n+1)*dim+2] = 0.0; 1943 } 1944 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 1945 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 1946 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 1947 } 1948 /* Interpolate */ 1949 if (interpolate) {ierr = DMPlexInterpolateInPlace_Internal(dm);CHKERRQ(ierr);} 1950 PetscFunctionReturn(0); 1951 } 1952 1953 /*@ 1954 DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges. 1955 1956 Collective 1957 1958 Input Parameters: 1959 + comm - The communicator for the DM object 1960 . n - The number of wedges around the origin 1961 - interpolate - Create edges and faces 1962 1963 Output Parameter: 1964 . dm - The DM object 1965 1966 Level: beginner 1967 1968 .seealso: DMPlexCreateHexCylinderMesh(), DMPlexCreateBoxMesh(), DMSetType(), DMCreate() 1969 @*/ 1970 PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm) 1971 { 1972 PetscErrorCode ierr; 1973 1974 PetscFunctionBegin; 1975 PetscValidPointer(dm, 4); 1976 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 1977 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 1978 ierr = DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate);CHKERRQ(ierr); 1979 PetscFunctionReturn(0); 1980 } 1981 1982 PETSC_STATIC_INLINE PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 1983 { 1984 PetscReal prod = 0.0; 1985 PetscInt i; 1986 for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]); 1987 return PetscSqrtReal(prod); 1988 } 1989 PETSC_STATIC_INLINE PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 1990 { 1991 PetscReal prod = 0.0; 1992 PetscInt i; 1993 for (i = 0; i < dim; ++i) prod += x[i]*y[i]; 1994 return prod; 1995 } 1996 1997 /* The first constant is the sphere radius */ 1998 static void snapToSphere(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1999 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2000 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2001 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 2002 { 2003 PetscReal r = PetscRealPart(constants[0]); 2004 PetscReal norm2 = 0.0, fac; 2005 PetscInt n = uOff[1] - uOff[0], d; 2006 2007 for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d])); 2008 fac = r/PetscSqrtReal(norm2); 2009 for (d = 0; d < n; ++d) f0[d] = u[d]*fac; 2010 } 2011 2012 static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R) 2013 { 2014 const PetscInt embedDim = dim+1; 2015 PetscSection coordSection; 2016 Vec coordinates; 2017 PetscScalar *coords; 2018 PetscReal *coordsIn; 2019 PetscInt numCells, numEdges, numVerts, firstVertex, v, firstEdge, coordSize, d, c, e; 2020 PetscMPIInt rank; 2021 PetscErrorCode ierr; 2022 2023 PetscFunctionBegin; 2024 PetscValidLogicalCollectiveBool(dm, simplex, 3); 2025 ierr = DMSetDimension(dm, dim);CHKERRQ(ierr); 2026 ierr = DMSetCoordinateDim(dm, dim+1);CHKERRQ(ierr); 2027 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 2028 switch (dim) { 2029 case 2: 2030 if (simplex) { 2031 const PetscReal radius = PetscSqrtReal(1 + PETSC_PHI*PETSC_PHI)/(1.0 + PETSC_PHI); 2032 const PetscReal edgeLen = 2.0/(1.0 + PETSC_PHI) * (R/radius); 2033 const PetscInt degree = 5; 2034 PetscReal vertex[3] = {0.0, 1.0/(1.0 + PETSC_PHI), PETSC_PHI/(1.0 + PETSC_PHI)}; 2035 PetscInt s[3] = {1, 1, 1}; 2036 PetscInt cone[3]; 2037 PetscInt *graph, p, i, j, k; 2038 2039 vertex[0] *= R/radius; vertex[1] *= R/radius; vertex[2] *= R/radius; 2040 numCells = !rank ? 20 : 0; 2041 numVerts = !rank ? 12 : 0; 2042 firstVertex = numCells; 2043 /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of 2044 2045 (0, \pm 1/\phi+1, \pm \phi/\phi+1) 2046 2047 where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 2048 length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393. 2049 */ 2050 /* Construct vertices */ 2051 ierr = PetscCalloc1(numVerts * embedDim, &coordsIn);CHKERRQ(ierr); 2052 if (!rank) { 2053 for (p = 0, i = 0; p < embedDim; ++p) { 2054 for (s[1] = -1; s[1] < 2; s[1] += 2) { 2055 for (s[2] = -1; s[2] < 2; s[2] += 2) { 2056 for (d = 0; d < embedDim; ++d) coordsIn[i*embedDim+d] = s[(d+p)%embedDim]*vertex[(d+p)%embedDim]; 2057 ++i; 2058 } 2059 } 2060 } 2061 } 2062 /* Construct graph */ 2063 ierr = PetscCalloc1(numVerts * numVerts, &graph);CHKERRQ(ierr); 2064 for (i = 0; i < numVerts; ++i) { 2065 for (j = 0, k = 0; j < numVerts; ++j) { 2066 if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i*embedDim], &coordsIn[j*embedDim]) - edgeLen) < PETSC_SMALL) {graph[i*numVerts+j] = 1; ++k;} 2067 } 2068 if (k != degree) SETERRQ3(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %D degree %D != %D", i, k, degree); 2069 } 2070 /* Build Topology */ 2071 ierr = DMPlexSetChart(dm, 0, numCells+numVerts);CHKERRQ(ierr); 2072 for (c = 0; c < numCells; c++) { 2073 ierr = DMPlexSetConeSize(dm, c, embedDim);CHKERRQ(ierr); 2074 } 2075 ierr = DMSetUp(dm);CHKERRQ(ierr); /* Allocate space for cones */ 2076 /* Cells */ 2077 for (i = 0, c = 0; i < numVerts; ++i) { 2078 for (j = 0; j < i; ++j) { 2079 for (k = 0; k < j; ++k) { 2080 if (graph[i*numVerts+j] && graph[j*numVerts+k] && graph[k*numVerts+i]) { 2081 cone[0] = firstVertex+i; cone[1] = firstVertex+j; cone[2] = firstVertex+k; 2082 /* Check orientation */ 2083 { 2084 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}}}; 2085 PetscReal normal[3]; 2086 PetscInt e, f; 2087 2088 for (d = 0; d < embedDim; ++d) { 2089 normal[d] = 0.0; 2090 for (e = 0; e < embedDim; ++e) { 2091 for (f = 0; f < embedDim; ++f) { 2092 normal[d] += epsilon[d][e][f]*(coordsIn[j*embedDim+e] - coordsIn[i*embedDim+e])*(coordsIn[k*embedDim+f] - coordsIn[i*embedDim+f]); 2093 } 2094 } 2095 } 2096 if (DotReal(embedDim, normal, &coordsIn[i*embedDim]) < 0) {PetscInt tmp = cone[1]; cone[1] = cone[2]; cone[2] = tmp;} 2097 } 2098 ierr = DMPlexSetCone(dm, c++, cone);CHKERRQ(ierr); 2099 } 2100 } 2101 } 2102 } 2103 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 2104 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 2105 ierr = PetscFree(graph);CHKERRQ(ierr); 2106 } else { 2107 /* 2108 12-21--13 2109 | | 2110 25 4 24 2111 | | 2112 12-25--9-16--8-24--13 2113 | | | | 2114 23 5 17 0 15 3 22 2115 | | | | 2116 10-20--6-14--7-19--11 2117 | | 2118 20 1 19 2119 | | 2120 10-18--11 2121 | | 2122 23 2 22 2123 | | 2124 12-21--13 2125 */ 2126 PetscInt cone[4], ornt[4]; 2127 2128 numCells = !rank ? 6 : 0; 2129 numEdges = !rank ? 12 : 0; 2130 numVerts = !rank ? 8 : 0; 2131 firstVertex = numCells; 2132 firstEdge = numCells + numVerts; 2133 /* Build Topology */ 2134 ierr = DMPlexSetChart(dm, 0, numCells+numEdges+numVerts);CHKERRQ(ierr); 2135 for (c = 0; c < numCells; c++) { 2136 ierr = DMPlexSetConeSize(dm, c, 4);CHKERRQ(ierr); 2137 } 2138 for (e = firstEdge; e < firstEdge+numEdges; ++e) { 2139 ierr = DMPlexSetConeSize(dm, e, 2);CHKERRQ(ierr); 2140 } 2141 ierr = DMSetUp(dm);CHKERRQ(ierr); /* Allocate space for cones */ 2142 if (!rank) { 2143 /* Cell 0 */ 2144 cone[0] = 14; cone[1] = 15; cone[2] = 16; cone[3] = 17; 2145 ierr = DMPlexSetCone(dm, 0, cone);CHKERRQ(ierr); 2146 ornt[0] = 0; ornt[1] = 0; ornt[2] = 0; ornt[3] = 0; 2147 ierr = DMPlexSetConeOrientation(dm, 0, ornt);CHKERRQ(ierr); 2148 /* Cell 1 */ 2149 cone[0] = 18; cone[1] = 19; cone[2] = 14; cone[3] = 20; 2150 ierr = DMPlexSetCone(dm, 1, cone);CHKERRQ(ierr); 2151 ornt[0] = 0; ornt[1] = 0; ornt[2] = -1; ornt[3] = 0; 2152 ierr = DMPlexSetConeOrientation(dm, 1, ornt);CHKERRQ(ierr); 2153 /* Cell 2 */ 2154 cone[0] = 21; cone[1] = 22; cone[2] = 18; cone[3] = 23; 2155 ierr = DMPlexSetCone(dm, 2, cone);CHKERRQ(ierr); 2156 ornt[0] = 0; ornt[1] = 0; ornt[2] = -1; ornt[3] = 0; 2157 ierr = DMPlexSetConeOrientation(dm, 2, ornt);CHKERRQ(ierr); 2158 /* Cell 3 */ 2159 cone[0] = 19; cone[1] = 22; cone[2] = 24; cone[3] = 15; 2160 ierr = DMPlexSetCone(dm, 3, cone);CHKERRQ(ierr); 2161 ornt[0] = -1; ornt[1] = -1; ornt[2] = 0; ornt[3] = -1; 2162 ierr = DMPlexSetConeOrientation(dm, 3, ornt);CHKERRQ(ierr); 2163 /* Cell 4 */ 2164 cone[0] = 16; cone[1] = 24; cone[2] = 21; cone[3] = 25; 2165 ierr = DMPlexSetCone(dm, 4, cone);CHKERRQ(ierr); 2166 ornt[0] = -1; ornt[1] = -1; ornt[2] = -1; ornt[3] = 0; 2167 ierr = DMPlexSetConeOrientation(dm, 4, ornt);CHKERRQ(ierr); 2168 /* Cell 5 */ 2169 cone[0] = 20; cone[1] = 17; cone[2] = 25; cone[3] = 23; 2170 ierr = DMPlexSetCone(dm, 5, cone);CHKERRQ(ierr); 2171 ornt[0] = -1; ornt[1] = -1; ornt[2] = -1; ornt[3] = -1; 2172 ierr = DMPlexSetConeOrientation(dm, 5, ornt);CHKERRQ(ierr); 2173 /* Edges */ 2174 cone[0] = 6; cone[1] = 7; 2175 ierr = DMPlexSetCone(dm, 14, cone);CHKERRQ(ierr); 2176 cone[0] = 7; cone[1] = 8; 2177 ierr = DMPlexSetCone(dm, 15, cone);CHKERRQ(ierr); 2178 cone[0] = 8; cone[1] = 9; 2179 ierr = DMPlexSetCone(dm, 16, cone);CHKERRQ(ierr); 2180 cone[0] = 9; cone[1] = 6; 2181 ierr = DMPlexSetCone(dm, 17, cone);CHKERRQ(ierr); 2182 cone[0] = 10; cone[1] = 11; 2183 ierr = DMPlexSetCone(dm, 18, cone);CHKERRQ(ierr); 2184 cone[0] = 11; cone[1] = 7; 2185 ierr = DMPlexSetCone(dm, 19, cone);CHKERRQ(ierr); 2186 cone[0] = 6; cone[1] = 10; 2187 ierr = DMPlexSetCone(dm, 20, cone);CHKERRQ(ierr); 2188 cone[0] = 12; cone[1] = 13; 2189 ierr = DMPlexSetCone(dm, 21, cone);CHKERRQ(ierr); 2190 cone[0] = 13; cone[1] = 11; 2191 ierr = DMPlexSetCone(dm, 22, cone);CHKERRQ(ierr); 2192 cone[0] = 10; cone[1] = 12; 2193 ierr = DMPlexSetCone(dm, 23, cone);CHKERRQ(ierr); 2194 cone[0] = 13; cone[1] = 8; 2195 ierr = DMPlexSetCone(dm, 24, cone);CHKERRQ(ierr); 2196 cone[0] = 12; cone[1] = 9; 2197 ierr = DMPlexSetCone(dm, 25, cone);CHKERRQ(ierr); 2198 } 2199 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 2200 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 2201 /* Build coordinates */ 2202 ierr = PetscCalloc1(numVerts * embedDim, &coordsIn);CHKERRQ(ierr); 2203 if (!rank) { 2204 coordsIn[0*embedDim+0] = -R; coordsIn[0*embedDim+1] = R; coordsIn[0*embedDim+2] = -R; 2205 coordsIn[1*embedDim+0] = R; coordsIn[1*embedDim+1] = R; coordsIn[1*embedDim+2] = -R; 2206 coordsIn[2*embedDim+0] = R; coordsIn[2*embedDim+1] = -R; coordsIn[2*embedDim+2] = -R; 2207 coordsIn[3*embedDim+0] = -R; coordsIn[3*embedDim+1] = -R; coordsIn[3*embedDim+2] = -R; 2208 coordsIn[4*embedDim+0] = -R; coordsIn[4*embedDim+1] = R; coordsIn[4*embedDim+2] = R; 2209 coordsIn[5*embedDim+0] = R; coordsIn[5*embedDim+1] = R; coordsIn[5*embedDim+2] = R; 2210 coordsIn[6*embedDim+0] = -R; coordsIn[6*embedDim+1] = -R; coordsIn[6*embedDim+2] = R; 2211 coordsIn[7*embedDim+0] = R; coordsIn[7*embedDim+1] = -R; coordsIn[7*embedDim+2] = R; 2212 } 2213 } 2214 break; 2215 case 3: 2216 if (simplex) { 2217 const PetscReal edgeLen = 1.0/PETSC_PHI; 2218 PetscReal vertexA[4] = {0.5, 0.5, 0.5, 0.5}; 2219 PetscReal vertexB[4] = {1.0, 0.0, 0.0, 0.0}; 2220 PetscReal vertexC[4] = {0.5, 0.5*PETSC_PHI, 0.5/PETSC_PHI, 0.0}; 2221 const PetscInt degree = 12; 2222 PetscInt s[4] = {1, 1, 1}; 2223 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}, 2224 {2, 0, 1, 3}, {2, 1, 3, 0}, {2, 3, 0, 1}, {3, 0, 2, 1}, {3, 1, 0, 2}, {3, 2, 1, 0}}; 2225 PetscInt cone[4]; 2226 PetscInt *graph, p, i, j, k, l; 2227 2228 vertexA[0] *= R; vertexA[1] *= R; vertexA[2] *= R; vertexA[3] *= R; 2229 vertexB[0] *= R; vertexB[1] *= R; vertexB[2] *= R; vertexB[3] *= R; 2230 vertexC[0] *= R; vertexC[1] *= R; vertexC[2] *= R; vertexC[3] *= R; 2231 numCells = !rank ? 600 : 0; 2232 numVerts = !rank ? 120 : 0; 2233 firstVertex = numCells; 2234 /* Use the 600-cell, which for a unit sphere has coordinates which are 2235 2236 1/2 (\pm 1, \pm 1, \pm 1, \pm 1) 16 2237 (\pm 1, 0, 0, 0) all cyclic permutations 8 2238 1/2 (\pm 1, \pm phi, \pm 1/phi, 0) all even permutations 96 2239 2240 where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 2241 length is then given by 1/\phi = 0.61803. 2242 2243 http://buzzard.pugetsound.edu/sage-practice/ch03s03.html 2244 http://mathworld.wolfram.com/600-Cell.html 2245 */ 2246 /* Construct vertices */ 2247 ierr = PetscCalloc1(numVerts * embedDim, &coordsIn);CHKERRQ(ierr); 2248 i = 0; 2249 if (!rank) { 2250 for (s[0] = -1; s[0] < 2; s[0] += 2) { 2251 for (s[1] = -1; s[1] < 2; s[1] += 2) { 2252 for (s[2] = -1; s[2] < 2; s[2] += 2) { 2253 for (s[3] = -1; s[3] < 2; s[3] += 2) { 2254 for (d = 0; d < embedDim; ++d) coordsIn[i*embedDim+d] = s[d]*vertexA[d]; 2255 ++i; 2256 } 2257 } 2258 } 2259 } 2260 for (p = 0; p < embedDim; ++p) { 2261 s[1] = s[2] = s[3] = 1; 2262 for (s[0] = -1; s[0] < 2; s[0] += 2) { 2263 for (d = 0; d < embedDim; ++d) coordsIn[i*embedDim+d] = s[(d+p)%embedDim]*vertexB[(d+p)%embedDim]; 2264 ++i; 2265 } 2266 } 2267 for (p = 0; p < 12; ++p) { 2268 s[3] = 1; 2269 for (s[0] = -1; s[0] < 2; s[0] += 2) { 2270 for (s[1] = -1; s[1] < 2; s[1] += 2) { 2271 for (s[2] = -1; s[2] < 2; s[2] += 2) { 2272 for (d = 0; d < embedDim; ++d) coordsIn[i*embedDim+d] = s[evenPerm[p][d]]*vertexC[evenPerm[p][d]]; 2273 ++i; 2274 } 2275 } 2276 } 2277 } 2278 } 2279 if (i != numVerts) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %D != %D", i, numVerts); 2280 /* Construct graph */ 2281 ierr = PetscCalloc1(numVerts * numVerts, &graph);CHKERRQ(ierr); 2282 for (i = 0; i < numVerts; ++i) { 2283 for (j = 0, k = 0; j < numVerts; ++j) { 2284 if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i*embedDim], &coordsIn[j*embedDim]) - edgeLen) < PETSC_SMALL) {graph[i*numVerts+j] = 1; ++k;} 2285 } 2286 if (k != degree) SETERRQ3(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %D degree %D != %D", i, k, degree); 2287 } 2288 /* Build Topology */ 2289 ierr = DMPlexSetChart(dm, 0, numCells+numVerts);CHKERRQ(ierr); 2290 for (c = 0; c < numCells; c++) { 2291 ierr = DMPlexSetConeSize(dm, c, embedDim);CHKERRQ(ierr); 2292 } 2293 ierr = DMSetUp(dm);CHKERRQ(ierr); /* Allocate space for cones */ 2294 /* Cells */ 2295 if (!rank) { 2296 for (i = 0, c = 0; i < numVerts; ++i) { 2297 for (j = 0; j < i; ++j) { 2298 for (k = 0; k < j; ++k) { 2299 for (l = 0; l < k; ++l) { 2300 if (graph[i*numVerts+j] && graph[j*numVerts+k] && graph[k*numVerts+i] && 2301 graph[l*numVerts+i] && graph[l*numVerts+j] && graph[l*numVerts+k]) { 2302 cone[0] = firstVertex+i; cone[1] = firstVertex+j; cone[2] = firstVertex+k; cone[3] = firstVertex+l; 2303 /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */ 2304 { 2305 const PetscInt epsilon[4][4][4][4] = {{{{0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}}, 2306 {{0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 1}, { 0, 0, -1, 0}}, 2307 {{0, 0, 0, 0}, { 0, 0, 0, -1}, { 0, 0, 0, 0}, { 0, 1, 0, 0}}, 2308 {{0, 0, 0, 0}, { 0, 0, 1, 0}, { 0, -1, 0, 0}, { 0, 0, 0, 0}}}, 2309 2310 {{{0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, -1}, { 0, 0, 1, 0}}, 2311 {{0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}}, 2312 {{0, 0, 0, 1}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, {-1, 0, 0, 0}}, 2313 {{0, 0, -1, 0}, { 0, 0, 0, 0}, { 1, 0, 0, 0}, { 0, 0, 0, 0}}}, 2314 2315 {{{0, 0, 0, 0}, { 0, 0, 0, 1}, { 0, 0, 0, 0}, { 0, -1, 0, 0}}, 2316 {{0, 0, 0, -1}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 1, 0, 0, 0}}, 2317 {{0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}}, 2318 {{0, 1, 0, 0}, {-1, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}}}, 2319 2320 {{{0, 0, 0, 0}, { 0, 0, -1, 0}, { 0, 1, 0, 0}, { 0, 0, 0, 0}}, 2321 {{0, 0, 1, 0}, { 0, 0, 0, 0}, {-1, 0, 0, 0}, { 0, 0, 0, 0}}, 2322 {{0, -1, 0, 0}, { 1, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}}, 2323 {{0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}}}}; 2324 PetscReal normal[4]; 2325 PetscInt e, f, g; 2326 2327 for (d = 0; d < embedDim; ++d) { 2328 normal[d] = 0.0; 2329 for (e = 0; e < embedDim; ++e) { 2330 for (f = 0; f < embedDim; ++f) { 2331 for (g = 0; g < embedDim; ++g) { 2332 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]); 2333 } 2334 } 2335 } 2336 } 2337 if (DotReal(embedDim, normal, &coordsIn[i*embedDim]) < 0) {PetscInt tmp = cone[1]; cone[1] = cone[2]; cone[2] = tmp;} 2338 } 2339 ierr = DMPlexSetCone(dm, c++, cone);CHKERRQ(ierr); 2340 } 2341 } 2342 } 2343 } 2344 } 2345 } 2346 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 2347 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 2348 ierr = PetscFree(graph);CHKERRQ(ierr); 2349 break; 2350 } 2351 default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %D", dim); 2352 } 2353 /* Create coordinates */ 2354 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 2355 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 2356 ierr = PetscSectionSetFieldComponents(coordSection, 0, embedDim);CHKERRQ(ierr); 2357 ierr = PetscSectionSetChart(coordSection, firstVertex, firstVertex+numVerts);CHKERRQ(ierr); 2358 for (v = firstVertex; v < firstVertex+numVerts; ++v) { 2359 ierr = PetscSectionSetDof(coordSection, v, embedDim);CHKERRQ(ierr); 2360 ierr = PetscSectionSetFieldDof(coordSection, v, 0, embedDim);CHKERRQ(ierr); 2361 } 2362 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 2363 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 2364 ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr); 2365 ierr = VecSetBlockSize(coordinates, embedDim);CHKERRQ(ierr); 2366 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 2367 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 2368 ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr); 2369 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 2370 for (v = 0; v < numVerts; ++v) for (d = 0; d < embedDim; ++d) {coords[v*embedDim+d] = coordsIn[v*embedDim+d];} 2371 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 2372 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 2373 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 2374 ierr = PetscFree(coordsIn);CHKERRQ(ierr); 2375 { 2376 DM cdm; 2377 PetscDS cds; 2378 PetscScalar c = R; 2379 2380 ierr = DMPlexCreateCoordinateSpace(dm, 1, snapToSphere);CHKERRQ(ierr); 2381 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 2382 ierr = DMGetDS(cdm, &cds);CHKERRQ(ierr); 2383 ierr = PetscDSSetConstants(cds, 1, &c);CHKERRQ(ierr); 2384 } 2385 /* Wait for coordinate creation before doing in-place modification */ 2386 if (simplex) {ierr = DMPlexInterpolateInPlace_Internal(dm);CHKERRQ(ierr);} 2387 PetscFunctionReturn(0); 2388 } 2389 2390 /*@ 2391 DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d. 2392 2393 Collective 2394 2395 Input Parameters: 2396 + comm - The communicator for the DM object 2397 . dim - The dimension 2398 . simplex - Use simplices, or tensor product cells 2399 - R - The radius 2400 2401 Output Parameter: 2402 . dm - The DM object 2403 2404 Level: beginner 2405 2406 .seealso: DMPlexCreateBallMesh(), DMPlexCreateBoxMesh(), DMSetType(), DMCreate() 2407 @*/ 2408 PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm) 2409 { 2410 PetscErrorCode ierr; 2411 2412 PetscFunctionBegin; 2413 PetscValidPointer(dm, 5); 2414 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 2415 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 2416 ierr = DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R);CHKERRQ(ierr); 2417 PetscFunctionReturn(0); 2418 } 2419 2420 static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R) 2421 { 2422 DM sdm, vol; 2423 DMLabel bdlabel; 2424 PetscErrorCode ierr; 2425 2426 PetscFunctionBegin; 2427 ierr = DMCreate(PetscObjectComm((PetscObject) dm), &sdm);CHKERRQ(ierr); 2428 ierr = DMSetType(sdm, DMPLEX);CHKERRQ(ierr); 2429 ierr = PetscObjectSetOptionsPrefix((PetscObject) sdm, "bd_");CHKERRQ(ierr); 2430 ierr = DMPlexCreateSphereMesh_Internal(sdm, dim-1, PETSC_TRUE, R);CHKERRQ(ierr); 2431 ierr = DMSetFromOptions(sdm);CHKERRQ(ierr); 2432 ierr = DMViewFromOptions(sdm, NULL, "-dm_view");CHKERRQ(ierr); 2433 ierr = DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol);CHKERRQ(ierr); 2434 ierr = DMDestroy(&sdm);CHKERRQ(ierr); 2435 ierr = DMPlexReplace_Static(dm, &vol);CHKERRQ(ierr); 2436 ierr = DMCreateLabel(dm, "marker");CHKERRQ(ierr); 2437 ierr = DMGetLabel(dm, "marker", &bdlabel);CHKERRQ(ierr); 2438 ierr = DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel);CHKERRQ(ierr); 2439 ierr = DMPlexLabelComplete(dm, bdlabel);CHKERRQ(ierr); 2440 PetscFunctionReturn(0); 2441 } 2442 2443 /*@ 2444 DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d. 2445 2446 Collective 2447 2448 Input Parameters: 2449 + comm - The communicator for the DM object 2450 . dim - The dimension 2451 - R - The radius 2452 2453 Output Parameter: 2454 . dm - The DM object 2455 2456 Options Database Keys: 2457 - bd_dm_refine - This will refine the surface mesh preserving the sphere geometry 2458 2459 Level: beginner 2460 2461 .seealso: DMPlexCreateSphereMesh(), DMPlexCreateBoxMesh(), DMSetType(), DMCreate() 2462 @*/ 2463 PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm) 2464 { 2465 PetscErrorCode ierr; 2466 2467 PetscFunctionBegin; 2468 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 2469 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 2470 ierr = DMPlexCreateBallMesh_Internal(*dm, dim, R);CHKERRQ(ierr); 2471 PetscFunctionReturn(0); 2472 } 2473 2474 static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct) 2475 { 2476 PetscErrorCode ierr; 2477 2478 PetscFunctionBegin; 2479 switch (ct) { 2480 case DM_POLYTOPE_POINT: 2481 { 2482 PetscInt numPoints[1] = {1}; 2483 PetscInt coneSize[1] = {0}; 2484 PetscInt cones[1] = {0}; 2485 PetscInt coneOrientations[1] = {0}; 2486 PetscScalar vertexCoords[1] = {0.0}; 2487 2488 ierr = DMSetDimension(rdm, 0);CHKERRQ(ierr); 2489 ierr = DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 2490 } 2491 break; 2492 case DM_POLYTOPE_SEGMENT: 2493 { 2494 PetscInt numPoints[2] = {2, 1}; 2495 PetscInt coneSize[3] = {2, 0, 0}; 2496 PetscInt cones[2] = {1, 2}; 2497 PetscInt coneOrientations[2] = {0, 0}; 2498 PetscScalar vertexCoords[2] = {-1.0, 1.0}; 2499 2500 ierr = DMSetDimension(rdm, 1);CHKERRQ(ierr); 2501 ierr = DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 2502 } 2503 break; 2504 case DM_POLYTOPE_POINT_PRISM_TENSOR: 2505 { 2506 PetscInt numPoints[2] = {2, 1}; 2507 PetscInt coneSize[3] = {2, 0, 0}; 2508 PetscInt cones[2] = {1, 2}; 2509 PetscInt coneOrientations[2] = {0, 0}; 2510 PetscScalar vertexCoords[2] = {-1.0, 1.0}; 2511 2512 ierr = DMSetDimension(rdm, 1);CHKERRQ(ierr); 2513 ierr = DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 2514 } 2515 break; 2516 case DM_POLYTOPE_TRIANGLE: 2517 { 2518 PetscInt numPoints[2] = {3, 1}; 2519 PetscInt coneSize[4] = {3, 0, 0, 0}; 2520 PetscInt cones[3] = {1, 2, 3}; 2521 PetscInt coneOrientations[3] = {0, 0, 0}; 2522 PetscScalar vertexCoords[6] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0}; 2523 2524 ierr = DMSetDimension(rdm, 2);CHKERRQ(ierr); 2525 ierr = DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 2526 } 2527 break; 2528 case DM_POLYTOPE_QUADRILATERAL: 2529 { 2530 PetscInt numPoints[2] = {4, 1}; 2531 PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 2532 PetscInt cones[4] = {1, 2, 3, 4}; 2533 PetscInt coneOrientations[4] = {0, 0, 0, 0}; 2534 PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0}; 2535 2536 ierr = DMSetDimension(rdm, 2);CHKERRQ(ierr); 2537 ierr = DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 2538 } 2539 break; 2540 case DM_POLYTOPE_SEG_PRISM_TENSOR: 2541 { 2542 PetscInt numPoints[2] = {4, 1}; 2543 PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 2544 PetscInt cones[4] = {1, 2, 3, 4}; 2545 PetscInt coneOrientations[4] = {0, 0, 0, 0}; 2546 PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0}; 2547 2548 ierr = DMSetDimension(rdm, 2);CHKERRQ(ierr); 2549 ierr = DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 2550 } 2551 break; 2552 case DM_POLYTOPE_TETRAHEDRON: 2553 { 2554 PetscInt numPoints[2] = {4, 1}; 2555 PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 2556 PetscInt cones[4] = {1, 2, 3, 4}; 2557 PetscInt coneOrientations[4] = {0, 0, 0, 0}; 2558 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}; 2559 2560 ierr = DMSetDimension(rdm, 3);CHKERRQ(ierr); 2561 ierr = DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 2562 } 2563 break; 2564 case DM_POLYTOPE_HEXAHEDRON: 2565 { 2566 PetscInt numPoints[2] = {8, 1}; 2567 PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 2568 PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 2569 PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 2570 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, 2571 -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0}; 2572 2573 ierr = DMSetDimension(rdm, 3);CHKERRQ(ierr); 2574 ierr = DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 2575 } 2576 break; 2577 case DM_POLYTOPE_TRI_PRISM: 2578 { 2579 PetscInt numPoints[2] = {6, 1}; 2580 PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 2581 PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 2582 PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 2583 PetscScalar vertexCoords[18] = {-1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 2584 -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0}; 2585 2586 ierr = DMSetDimension(rdm, 3);CHKERRQ(ierr); 2587 ierr = DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 2588 } 2589 break; 2590 case DM_POLYTOPE_TRI_PRISM_TENSOR: 2591 { 2592 PetscInt numPoints[2] = {6, 1}; 2593 PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 2594 PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 2595 PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 2596 PetscScalar vertexCoords[18] = {-1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 2597 -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0}; 2598 2599 ierr = DMSetDimension(rdm, 3);CHKERRQ(ierr); 2600 ierr = DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 2601 } 2602 break; 2603 case DM_POLYTOPE_QUAD_PRISM_TENSOR: 2604 { 2605 PetscInt numPoints[2] = {8, 1}; 2606 PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 2607 PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 2608 PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 2609 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, 2610 -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0}; 2611 2612 ierr = DMSetDimension(rdm, 3);CHKERRQ(ierr); 2613 ierr = DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 2614 } 2615 break; 2616 case DM_POLYTOPE_PYRAMID: 2617 { 2618 PetscInt numPoints[2] = {5, 1}; 2619 PetscInt coneSize[6] = {5, 0, 0, 0, 0, 0}; 2620 PetscInt cones[5] = {1, 2, 3, 4, 5}; 2621 PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 2622 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, 2623 0.0, 0.0, 1.0}; 2624 2625 ierr = DMSetDimension(rdm, 3);CHKERRQ(ierr); 2626 ierr = DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); 2627 } 2628 break; 2629 default: SETERRQ1(PetscObjectComm((PetscObject) rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]); 2630 } 2631 { 2632 PetscInt Nv, v; 2633 2634 /* Must create the celltype label here so that we do not automatically try to compute the types */ 2635 ierr = DMCreateLabel(rdm, "celltype");CHKERRQ(ierr); 2636 ierr = DMPlexSetCellType(rdm, 0, ct);CHKERRQ(ierr); 2637 ierr = DMPlexGetChart(rdm, NULL, &Nv);CHKERRQ(ierr); 2638 for (v = 1; v < Nv; ++v) {ierr = DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT);CHKERRQ(ierr);} 2639 } 2640 ierr = DMPlexInterpolateInPlace_Internal(rdm);CHKERRQ(ierr); 2641 ierr = PetscObjectSetName((PetscObject) rdm, DMPolytopeTypes[ct]);CHKERRQ(ierr); 2642 PetscFunctionReturn(0); 2643 } 2644 2645 /*@ 2646 DMPlexCreateReferenceCell - Create a DMPLEX with the appropriate FEM reference cell 2647 2648 Collective 2649 2650 Input Parameters: 2651 + comm - The communicator 2652 - ct - The cell type of the reference cell 2653 2654 Output Parameter: 2655 . refdm - The reference cell 2656 2657 Level: intermediate 2658 2659 .seealso: DMPlexCreateReferenceCell(), DMPlexCreateBoxMesh() 2660 @*/ 2661 PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm) 2662 { 2663 PetscErrorCode ierr; 2664 2665 PetscFunctionBegin; 2666 ierr = DMCreate(comm, refdm);CHKERRQ(ierr); 2667 ierr = DMSetType(*refdm, DMPLEX);CHKERRQ(ierr); 2668 ierr = DMPlexCreateReferenceCell_Internal(*refdm, ct);CHKERRQ(ierr); 2669 PetscFunctionReturn(0); 2670 } 2671 2672 static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[]) 2673 { 2674 DM plex; 2675 DMLabel label; 2676 PetscBool hasLabel; 2677 PetscErrorCode ierr; 2678 2679 PetscFunctionBeginUser; 2680 ierr = DMHasLabel(dm, name, &hasLabel);CHKERRQ(ierr); 2681 if (hasLabel) PetscFunctionReturn(0); 2682 ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); 2683 ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); 2684 ierr = DMConvert(dm, DMPLEX, &plex);CHKERRQ(ierr); 2685 ierr = DMPlexMarkBoundaryFaces(plex, 1, label);CHKERRQ(ierr); 2686 ierr = DMDestroy(&plex);CHKERRQ(ierr); 2687 PetscFunctionReturn(0); 2688 } 2689 2690 const char * const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "unknown", "DMPlexShape", "DM_SHAPE_", NULL}; 2691 2692 static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems *PetscOptionsObject, PetscBool *useCoordSpace, DM dm) 2693 { 2694 DMPlexShape shape = DM_SHAPE_BOX; 2695 DMPolytopeType cell = DM_POLYTOPE_TRIANGLE; 2696 PetscInt dim = 2; 2697 PetscBool simplex = PETSC_TRUE, interpolate = PETSC_TRUE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE; 2698 PetscBool flg, flg2, fflg, bdfflg; 2699 MPI_Comm comm; 2700 char filename[PETSC_MAX_PATH_LEN], bdFilename[PETSC_MAX_PATH_LEN]; 2701 PetscErrorCode ierr; 2702 2703 PetscFunctionBegin; 2704 ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 2705 /* TODO Turn this into a registration interface */ 2706 ierr = PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg);CHKERRQ(ierr); 2707 ierr = PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg);CHKERRQ(ierr); 2708 ierr = PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum) cell, (PetscEnum *) &cell, NULL);CHKERRQ(ierr); 2709 ierr = PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL);CHKERRQ(ierr); 2710 ierr = PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum) shape, (PetscEnum *) &shape, &flg);CHKERRQ(ierr); 2711 ierr = PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0);CHKERRQ(ierr); 2712 if ((dim < 0) || (dim > 3)) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D should be in [1, 3]", dim); 2713 ierr = PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg);CHKERRQ(ierr); 2714 ierr = PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg);CHKERRQ(ierr); 2715 ierr = PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg);CHKERRQ(ierr); 2716 ierr = PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2);CHKERRQ(ierr); 2717 if (flg || flg2) {ierr = DMSetBasicAdjacency(dm, adjCone, adjClosure);CHKERRQ(ierr);} 2718 2719 switch (cell) { 2720 case DM_POLYTOPE_POINT: 2721 case DM_POLYTOPE_SEGMENT: 2722 case DM_POLYTOPE_POINT_PRISM_TENSOR: 2723 case DM_POLYTOPE_TRIANGLE: 2724 case DM_POLYTOPE_QUADRILATERAL: 2725 case DM_POLYTOPE_TETRAHEDRON: 2726 case DM_POLYTOPE_HEXAHEDRON: 2727 *useCoordSpace = PETSC_TRUE;break; 2728 default: *useCoordSpace = PETSC_FALSE;break; 2729 } 2730 2731 if (fflg) { 2732 DM dmnew; 2733 2734 ierr = DMPlexCreateFromFile(PetscObjectComm((PetscObject) dm), filename, interpolate, &dmnew);CHKERRQ(ierr); 2735 ierr = DMPlexReplace_Static(dm, &dmnew);CHKERRQ(ierr); 2736 } else if (refDomain) { 2737 ierr = DMPlexCreateReferenceCell_Internal(dm, cell);CHKERRQ(ierr); 2738 } else if (bdfflg) { 2739 DM bdm, dmnew; 2740 2741 ierr = DMPlexCreateFromFile(PetscObjectComm((PetscObject) dm), bdFilename, interpolate, &bdm);CHKERRQ(ierr); 2742 ierr = PetscObjectSetOptionsPrefix((PetscObject) bdm, "bd_");CHKERRQ(ierr); 2743 ierr = DMSetFromOptions(bdm);CHKERRQ(ierr); 2744 ierr = DMPlexGenerate(bdm, NULL, interpolate, &dmnew);CHKERRQ(ierr); 2745 ierr = DMDestroy(&bdm);CHKERRQ(ierr); 2746 ierr = DMPlexReplace_Static(dm, &dmnew);CHKERRQ(ierr); 2747 } else { 2748 ierr = PetscObjectSetName((PetscObject) dm, DMPlexShapes[shape]);CHKERRQ(ierr); 2749 switch (shape) { 2750 case DM_SHAPE_BOX: 2751 { 2752 PetscInt faces[3] = {0, 0, 0}; 2753 PetscReal lower[3] = {0, 0, 0}; 2754 PetscReal upper[3] = {1, 1, 1}; 2755 DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 2756 PetscInt i, n; 2757 2758 n = dim; 2759 for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4-dim); 2760 ierr = PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg);CHKERRQ(ierr); 2761 n = 3; 2762 ierr = PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg);CHKERRQ(ierr); 2763 if (flg && (n != dim)) SETERRQ2(comm, PETSC_ERR_ARG_SIZ, "Lower box point had %D values, should have been %D", n, dim); 2764 n = 3; 2765 ierr = PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg);CHKERRQ(ierr); 2766 if (flg && (n != dim)) SETERRQ2(comm, PETSC_ERR_ARG_SIZ, "Upper box point had %D values, should have been %D", n, dim); 2767 n = 3; 2768 ierr = PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *) bdt, &n, &flg);CHKERRQ(ierr); 2769 if (flg && (n != dim)) SETERRQ2(comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %D values, should have been %D", n, dim); 2770 switch (cell) { 2771 case DM_POLYTOPE_TRI_PRISM_TENSOR: 2772 ierr = DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt, PETSC_FALSE, interpolate);CHKERRQ(ierr); 2773 break; 2774 default: 2775 ierr = DMPlexCreateBoxMesh_Internal(dm, dim, simplex, faces, lower, upper, bdt, interpolate);CHKERRQ(ierr); 2776 break; 2777 } 2778 } 2779 break; 2780 case DM_SHAPE_BOX_SURFACE: 2781 { 2782 PetscInt faces[3] = {0, 0, 0}; 2783 PetscReal lower[3] = {0, 0, 0}; 2784 PetscReal upper[3] = {1, 1, 1}; 2785 PetscInt i, n; 2786 2787 n = dim+1; 2788 for (i = 0; i < dim+1; ++i) faces[i] = (dim+1 == 1 ? 1 : 4-(dim+1)); 2789 ierr = PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg);CHKERRQ(ierr); 2790 n = 3; 2791 ierr = PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg);CHKERRQ(ierr); 2792 if (flg && (n != dim+1)) SETERRQ2(comm, PETSC_ERR_ARG_SIZ, "Lower box point had %D values, should have been %D", n, dim+1); 2793 n = 3; 2794 ierr = PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg);CHKERRQ(ierr); 2795 if (flg && (n != dim+1)) SETERRQ2(comm, PETSC_ERR_ARG_SIZ, "Upper box point had %D values, should have been %D", n, dim+1); 2796 ierr = DMPlexCreateBoxSurfaceMesh_Internal(dm, dim+1, faces, lower, upper, interpolate);CHKERRQ(ierr); 2797 } 2798 break; 2799 case DM_SHAPE_SPHERE: 2800 { 2801 PetscReal R = 1.0; 2802 2803 ierr = PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg);CHKERRQ(ierr); 2804 ierr = DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R);CHKERRQ(ierr); 2805 } 2806 break; 2807 case DM_SHAPE_BALL: 2808 { 2809 PetscReal R = 1.0; 2810 2811 ierr = PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg);CHKERRQ(ierr); 2812 ierr = DMPlexCreateBallMesh_Internal(dm, dim, R);CHKERRQ(ierr); 2813 } 2814 break; 2815 case DM_SHAPE_CYLINDER: 2816 { 2817 DMBoundaryType bdt = DM_BOUNDARY_NONE; 2818 PetscInt Nw = 6; 2819 2820 ierr = PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum) bdt, (PetscEnum *) &bdt, NULL);CHKERRQ(ierr); 2821 ierr = PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL);CHKERRQ(ierr); 2822 switch (cell) { 2823 case DM_POLYTOPE_TRI_PRISM_TENSOR: 2824 ierr = DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate);CHKERRQ(ierr); 2825 break; 2826 default: 2827 ierr = DMPlexCreateHexCylinderMesh_Internal(dm, bdt);CHKERRQ(ierr); 2828 break; 2829 } 2830 } 2831 break; 2832 default: SETERRQ1(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]); 2833 } 2834 } 2835 ierr = DMPlexSetRefinementUniform(dm, PETSC_TRUE);CHKERRQ(ierr); 2836 PetscFunctionReturn(0); 2837 } 2838 2839 PetscErrorCode DMSetFromOptions_NonRefinement_Plex(PetscOptionItems *PetscOptionsObject, DM dm) 2840 { 2841 DM_Plex *mesh = (DM_Plex*) dm->data; 2842 PetscBool flg; 2843 char bdLabel[PETSC_MAX_PATH_LEN]; 2844 PetscErrorCode ierr; 2845 2846 PetscFunctionBegin; 2847 /* Handle viewing */ 2848 ierr = PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL);CHKERRQ(ierr); 2849 ierr = PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL,0);CHKERRQ(ierr); 2850 ierr = PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL);CHKERRQ(ierr); 2851 ierr = PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL,0);CHKERRQ(ierr); 2852 ierr = DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg);CHKERRQ(ierr); 2853 if (flg) {ierr = PetscLogDefaultBegin();CHKERRQ(ierr);} 2854 /* Labeling */ 2855 ierr = PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg);CHKERRQ(ierr); 2856 if (flg) {ierr = DMPlexCreateBoundaryLabel_Private(dm, bdLabel);CHKERRQ(ierr);} 2857 /* Point Location */ 2858 ierr = PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL);CHKERRQ(ierr); 2859 /* Partitioning and distribution */ 2860 ierr = PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL);CHKERRQ(ierr); 2861 /* Generation and remeshing */ 2862 ierr = PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL);CHKERRQ(ierr); 2863 /* Projection behavior */ 2864 ierr = PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maxmimum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL,0);CHKERRQ(ierr); 2865 ierr = PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL);CHKERRQ(ierr); 2866 /* Checking structure */ 2867 { 2868 PetscBool flg = PETSC_FALSE, flg2 = PETSC_FALSE, all = PETSC_FALSE; 2869 2870 ierr = PetscOptionsBool("-dm_plex_check_all", "Perform all checks", NULL, PETSC_FALSE, &all, &flg2);CHKERRQ(ierr); 2871 ierr = PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2);CHKERRQ(ierr); 2872 if (all || (flg && flg2)) {ierr = DMPlexCheckSymmetry(dm);CHKERRQ(ierr);} 2873 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); 2874 if (all || (flg && flg2)) {ierr = DMPlexCheckSkeleton(dm, 0);CHKERRQ(ierr);} 2875 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); 2876 if (all || (flg && flg2)) {ierr = DMPlexCheckFaces(dm, 0);CHKERRQ(ierr);} 2877 ierr = PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2);CHKERRQ(ierr); 2878 if (all || (flg && flg2)) {ierr = DMPlexCheckGeometry(dm);CHKERRQ(ierr);} 2879 ierr = PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2);CHKERRQ(ierr); 2880 if (all || (flg && flg2)) {ierr = DMPlexCheckPointSF(dm);CHKERRQ(ierr);} 2881 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); 2882 if (all || (flg && flg2)) {ierr = DMPlexCheckInterfaceCones(dm);CHKERRQ(ierr);} 2883 ierr = PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2);CHKERRQ(ierr); 2884 if (flg && flg2) {ierr = DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE);CHKERRQ(ierr);} 2885 } 2886 { 2887 PetscReal scale = 1.0; 2888 2889 ierr = PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg);CHKERRQ(ierr); 2890 if (flg) { 2891 Vec coordinates, coordinatesLocal; 2892 2893 ierr = DMGetCoordinates(dm, &coordinates);CHKERRQ(ierr); 2894 ierr = DMGetCoordinatesLocal(dm, &coordinatesLocal);CHKERRQ(ierr); 2895 ierr = VecScale(coordinates, scale);CHKERRQ(ierr); 2896 ierr = VecScale(coordinatesLocal, scale);CHKERRQ(ierr); 2897 } 2898 } 2899 ierr = PetscPartitionerSetFromOptions(mesh->partitioner);CHKERRQ(ierr); 2900 PetscFunctionReturn(0); 2901 } 2902 2903 static PetscErrorCode DMSetFromOptions_Plex(PetscOptionItems *PetscOptionsObject,DM dm) 2904 { 2905 PetscReal volume = -1.0, extThickness = 1.0; 2906 PetscInt prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim; 2907 PetscBool uniformOrig, created = PETSC_FALSE, uniform = PETSC_TRUE, distribute = PETSC_FALSE, interpolate = PETSC_TRUE, extColOrder = PETSC_TRUE, coordSpace = PETSC_TRUE, remap = PETSC_TRUE, ghostCells = PETSC_FALSE, isHierarchy, ignoreModel = PETSC_FALSE, flg; 2908 PetscErrorCode ierr; 2909 2910 PetscFunctionBegin; 2911 PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 2912 ierr = PetscOptionsHead(PetscOptionsObject,"DMPlex Options");CHKERRQ(ierr); 2913 /* Handle automatic creation */ 2914 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 2915 if (dim < 0) {ierr = DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm);CHKERRQ(ierr);created = PETSC_TRUE;} 2916 /* Handle interpolation before distribution */ 2917 ierr = PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg);CHKERRQ(ierr); 2918 if (flg) { 2919 DMPlexInterpolatedFlag interpolated; 2920 2921 ierr = DMPlexIsInterpolated(dm, &interpolated);CHKERRQ(ierr); 2922 if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) { 2923 DM udm; 2924 2925 ierr = DMPlexUninterpolate(dm, &udm);CHKERRQ(ierr); 2926 ierr = DMPlexReplace_Static(dm, &udm);CHKERRQ(ierr); 2927 } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) { 2928 DM idm; 2929 2930 ierr = DMPlexInterpolate(dm, &idm);CHKERRQ(ierr); 2931 ierr = DMPlexReplace_Static(dm, &idm);CHKERRQ(ierr); 2932 } 2933 } 2934 /* Handle DMPlex refinement before distribution */ 2935 ierr = PetscOptionsBool("-dm_refine_ignore_model", "Flag to ignore the geometry model when refining", "DMCreate", ignoreModel, &ignoreModel, &flg);CHKERRQ(ierr); 2936 if (flg) {((DM_Plex *) dm->data)->ignoreModel = ignoreModel;} 2937 ierr = DMPlexGetRefinementUniform(dm, &uniformOrig);CHKERRQ(ierr); 2938 ierr = PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL,0);CHKERRQ(ierr); 2939 ierr = PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL);CHKERRQ(ierr); 2940 ierr = PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg);CHKERRQ(ierr); 2941 if (flg) {ierr = DMPlexSetRefinementUniform(dm, uniform);CHKERRQ(ierr);} 2942 ierr = PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg);CHKERRQ(ierr); 2943 if (flg) { 2944 ierr = DMPlexSetRefinementUniform(dm, PETSC_FALSE);CHKERRQ(ierr); 2945 ierr = DMPlexSetRefinementLimit(dm, volume);CHKERRQ(ierr); 2946 prerefine = PetscMax(prerefine, 1); 2947 } 2948 for (r = 0; r < prerefine; ++r) { 2949 DM rdm; 2950 PetscPointFunc coordFunc = ((DM_Plex*) dm->data)->coordFunc; 2951 2952 ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm);CHKERRQ(ierr); 2953 ierr = DMRefine(dm, PetscObjectComm((PetscObject) dm), &rdm);CHKERRQ(ierr); 2954 ierr = DMPlexReplace_Static(dm, &rdm);CHKERRQ(ierr); 2955 ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm);CHKERRQ(ierr); 2956 if (coordFunc && remap) { 2957 ierr = DMPlexRemapGeometry(dm, 0.0, coordFunc);CHKERRQ(ierr); 2958 ((DM_Plex*) dm->data)->coordFunc = coordFunc; 2959 } 2960 } 2961 ierr = DMPlexSetRefinementUniform(dm, uniformOrig);CHKERRQ(ierr); 2962 /* Handle DMPlex extrusion before distribution */ 2963 ierr = PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, NULL);CHKERRQ(ierr); 2964 ierr = PetscOptionsBoundedInt("-dm_extrude_layers", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0);CHKERRQ(ierr); 2965 ierr = PetscOptionsReal("-dm_extrude_thickness", "The thickness of the layer to be extruded", "", extThickness, &extThickness, NULL);CHKERRQ(ierr); 2966 ierr = PetscOptionsBool("-dm_extrude_column_first", "Order the cells in a vertical column first", "", extColOrder, &extColOrder, NULL);CHKERRQ(ierr); 2967 if (extLayers) { 2968 DM edm; 2969 2970 ierr = DMPlexExtrude(dm, extLayers, extThickness, extColOrder, NULL, interpolate, &edm);CHKERRQ(ierr); 2971 ierr = DMPlexReplace_Static(dm, &edm);CHKERRQ(ierr); 2972 } 2973 /* Handle DMPlex distribution */ 2974 ierr = PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMCreate", distribute, &distribute, NULL);CHKERRQ(ierr); 2975 ierr = PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMCreate", overlap, &overlap, NULL, 0);CHKERRQ(ierr); 2976 if (distribute) { 2977 DM pdm = NULL; 2978 PetscPartitioner part; 2979 2980 ierr = DMPlexGetPartitioner(dm, &part);CHKERRQ(ierr); 2981 ierr = PetscPartitionerSetFromOptions(part);CHKERRQ(ierr); 2982 ierr = DMPlexDistribute(dm, overlap, NULL, &pdm);CHKERRQ(ierr); 2983 if (pdm) { 2984 ierr = DMPlexReplace_Static(dm, &pdm);CHKERRQ(ierr); 2985 } 2986 } 2987 /* Create coordinate space */ 2988 if (created) { 2989 DM_Plex *mesh = (DM_Plex *) dm->data; 2990 PetscInt degree = 1; 2991 PetscBool periodic, flg; 2992 2993 ierr = PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, &flg);CHKERRQ(ierr); 2994 ierr = PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, °ree, NULL);CHKERRQ(ierr); 2995 if (coordSpace) {ierr = DMPlexCreateCoordinateSpace(dm, degree, mesh->coordFunc);CHKERRQ(ierr);} 2996 if (flg && !coordSpace) { 2997 DM cdm; 2998 PetscDS cds; 2999 PetscObject obj; 3000 PetscClassId id; 3001 3002 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 3003 ierr = DMGetDS(cdm, &cds);CHKERRQ(ierr); 3004 ierr = PetscDSGetDiscretization(cds, 0, &obj);CHKERRQ(ierr); 3005 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 3006 if (id == PETSCFE_CLASSID) { 3007 PetscContainer dummy; 3008 3009 ierr = PetscContainerCreate(PETSC_COMM_SELF, &dummy);CHKERRQ(ierr); 3010 ierr = PetscObjectSetName((PetscObject) dummy, "coordinates");CHKERRQ(ierr); 3011 ierr = DMSetField(cdm, 0, NULL, (PetscObject) dummy);CHKERRQ(ierr); 3012 ierr = PetscContainerDestroy(&dummy);CHKERRQ(ierr); 3013 ierr = DMClearDS(cdm);CHKERRQ(ierr); 3014 } 3015 mesh->coordFunc = NULL; 3016 } 3017 ierr = DMLocalizeCoordinates(dm);CHKERRQ(ierr); 3018 ierr = DMGetPeriodicity(dm, &periodic, NULL, NULL, NULL);CHKERRQ(ierr); 3019 if (periodic) {ierr = DMSetPeriodicity(dm, PETSC_TRUE, NULL, NULL, NULL);CHKERRQ(ierr);} 3020 } 3021 /* Handle DMPlex refinement */ 3022 remap = PETSC_TRUE; 3023 ierr = PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL,0);CHKERRQ(ierr); 3024 ierr = PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL);CHKERRQ(ierr); 3025 ierr = PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy,0);CHKERRQ(ierr); 3026 if (refine) {ierr = DMPlexSetRefinementUniform(dm, PETSC_TRUE);CHKERRQ(ierr);} 3027 if (refine && isHierarchy) { 3028 DM *dms, coarseDM; 3029 3030 ierr = DMGetCoarseDM(dm, &coarseDM);CHKERRQ(ierr); 3031 ierr = PetscObjectReference((PetscObject)coarseDM);CHKERRQ(ierr); 3032 ierr = PetscMalloc1(refine,&dms);CHKERRQ(ierr); 3033 ierr = DMRefineHierarchy(dm, refine, dms);CHKERRQ(ierr); 3034 /* Total hack since we do not pass in a pointer */ 3035 ierr = DMPlexSwap_Static(dm, dms[refine-1]);CHKERRQ(ierr); 3036 if (refine == 1) { 3037 ierr = DMSetCoarseDM(dm, dms[0]);CHKERRQ(ierr); 3038 ierr = DMPlexSetRegularRefinement(dm, PETSC_TRUE);CHKERRQ(ierr); 3039 } else { 3040 ierr = DMSetCoarseDM(dm, dms[refine-2]);CHKERRQ(ierr); 3041 ierr = DMPlexSetRegularRefinement(dm, PETSC_TRUE);CHKERRQ(ierr); 3042 ierr = DMSetCoarseDM(dms[0], dms[refine-1]);CHKERRQ(ierr); 3043 ierr = DMPlexSetRegularRefinement(dms[0], PETSC_TRUE);CHKERRQ(ierr); 3044 } 3045 ierr = DMSetCoarseDM(dms[refine-1], coarseDM);CHKERRQ(ierr); 3046 ierr = PetscObjectDereference((PetscObject)coarseDM);CHKERRQ(ierr); 3047 /* Free DMs */ 3048 for (r = 0; r < refine; ++r) { 3049 ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dms[r]);CHKERRQ(ierr); 3050 ierr = DMDestroy(&dms[r]);CHKERRQ(ierr); 3051 } 3052 ierr = PetscFree(dms);CHKERRQ(ierr); 3053 } else { 3054 for (r = 0; r < refine; ++r) { 3055 DM rdm; 3056 PetscPointFunc coordFunc = ((DM_Plex*) dm->data)->coordFunc; 3057 3058 ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm);CHKERRQ(ierr); 3059 ierr = DMRefine(dm, PetscObjectComm((PetscObject) dm), &rdm);CHKERRQ(ierr); 3060 /* Total hack since we do not pass in a pointer */ 3061 ierr = DMPlexReplace_Static(dm, &rdm);CHKERRQ(ierr); 3062 ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm);CHKERRQ(ierr); 3063 if (coordFunc && remap) { 3064 ierr = DMPlexRemapGeometry(dm, 0.0, coordFunc);CHKERRQ(ierr); 3065 ((DM_Plex*) dm->data)->coordFunc = coordFunc; 3066 } 3067 } 3068 } 3069 /* Handle DMPlex coarsening */ 3070 ierr = PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL,0);CHKERRQ(ierr); 3071 ierr = PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy,0);CHKERRQ(ierr); 3072 if (coarsen && isHierarchy) { 3073 DM *dms; 3074 3075 ierr = PetscMalloc1(coarsen, &dms);CHKERRQ(ierr); 3076 ierr = DMCoarsenHierarchy(dm, coarsen, dms);CHKERRQ(ierr); 3077 /* Free DMs */ 3078 for (r = 0; r < coarsen; ++r) { 3079 ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dms[r]);CHKERRQ(ierr); 3080 ierr = DMDestroy(&dms[r]);CHKERRQ(ierr); 3081 } 3082 ierr = PetscFree(dms);CHKERRQ(ierr); 3083 } else { 3084 for (r = 0; r < coarsen; ++r) { 3085 DM cdm; 3086 PetscPointFunc coordFunc = ((DM_Plex*) dm->data)->coordFunc; 3087 3088 ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm);CHKERRQ(ierr); 3089 ierr = DMCoarsen(dm, PetscObjectComm((PetscObject) dm), &cdm);CHKERRQ(ierr); 3090 /* Total hack since we do not pass in a pointer */ 3091 ierr = DMPlexReplace_Static(dm, &cdm);CHKERRQ(ierr); 3092 ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm);CHKERRQ(ierr); 3093 if (coordFunc) { 3094 ierr = DMPlexRemapGeometry(dm, 0.0, coordFunc);CHKERRQ(ierr); 3095 ((DM_Plex*) dm->data)->coordFunc = coordFunc; 3096 } 3097 } 3098 } 3099 /* Handle ghost cells */ 3100 ierr = PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL);CHKERRQ(ierr); 3101 if (ghostCells) { 3102 DM gdm; 3103 char lname[PETSC_MAX_PATH_LEN]; 3104 3105 lname[0] = '\0'; 3106 ierr = PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg);CHKERRQ(ierr); 3107 ierr = DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm);CHKERRQ(ierr); 3108 ierr = DMPlexReplace_Static(dm, &gdm);CHKERRQ(ierr); 3109 } 3110 /* Handle */ 3111 ierr = DMSetFromOptions_NonRefinement_Plex(PetscOptionsObject, dm);CHKERRQ(ierr); 3112 ierr = PetscOptionsTail();CHKERRQ(ierr); 3113 PetscFunctionReturn(0); 3114 } 3115 3116 static PetscErrorCode DMCreateGlobalVector_Plex(DM dm,Vec *vec) 3117 { 3118 PetscErrorCode ierr; 3119 3120 PetscFunctionBegin; 3121 ierr = DMCreateGlobalVector_Section_Private(dm,vec);CHKERRQ(ierr); 3122 /* ierr = VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM);CHKERRQ(ierr); */ 3123 ierr = VecSetOperation(*vec, VECOP_VIEW, (void (*)(void)) VecView_Plex);CHKERRQ(ierr); 3124 ierr = VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void)) VecView_Plex_Native);CHKERRQ(ierr); 3125 ierr = VecSetOperation(*vec, VECOP_LOAD, (void (*)(void)) VecLoad_Plex);CHKERRQ(ierr); 3126 ierr = VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void)) VecLoad_Plex_Native);CHKERRQ(ierr); 3127 PetscFunctionReturn(0); 3128 } 3129 3130 static PetscErrorCode DMCreateLocalVector_Plex(DM dm,Vec *vec) 3131 { 3132 PetscErrorCode ierr; 3133 3134 PetscFunctionBegin; 3135 ierr = DMCreateLocalVector_Section_Private(dm,vec);CHKERRQ(ierr); 3136 ierr = VecSetOperation(*vec, VECOP_VIEW, (void (*)(void)) VecView_Plex_Local);CHKERRQ(ierr); 3137 ierr = VecSetOperation(*vec, VECOP_LOAD, (void (*)(void)) VecLoad_Plex_Local);CHKERRQ(ierr); 3138 PetscFunctionReturn(0); 3139 } 3140 3141 static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 3142 { 3143 PetscInt depth, d; 3144 PetscErrorCode ierr; 3145 3146 PetscFunctionBegin; 3147 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3148 if (depth == 1) { 3149 ierr = DMGetDimension(dm, &d);CHKERRQ(ierr); 3150 if (dim == 0) {ierr = DMPlexGetDepthStratum(dm, dim, pStart, pEnd);CHKERRQ(ierr);} 3151 else if (dim == d) {ierr = DMPlexGetDepthStratum(dm, 1, pStart, pEnd);CHKERRQ(ierr);} 3152 else {*pStart = 0; *pEnd = 0;} 3153 } else { 3154 ierr = DMPlexGetDepthStratum(dm, dim, pStart, pEnd);CHKERRQ(ierr); 3155 } 3156 PetscFunctionReturn(0); 3157 } 3158 3159 static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[]) 3160 { 3161 PetscSF sf; 3162 PetscInt niranks, njranks, n; 3163 const PetscMPIInt *iranks, *jranks; 3164 DM_Plex *data = (DM_Plex*) dm->data; 3165 PetscErrorCode ierr; 3166 3167 PetscFunctionBegin; 3168 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 3169 if (!data->neighbors) { 3170 ierr = PetscSFSetUp(sf);CHKERRQ(ierr); 3171 ierr = PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL);CHKERRQ(ierr); 3172 ierr = PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL);CHKERRQ(ierr); 3173 ierr = PetscMalloc1(njranks + niranks + 1, &data->neighbors);CHKERRQ(ierr); 3174 ierr = PetscArraycpy(data->neighbors + 1, jranks, njranks);CHKERRQ(ierr); 3175 ierr = PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks);CHKERRQ(ierr); 3176 n = njranks + niranks; 3177 ierr = PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1);CHKERRQ(ierr); 3178 /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */ 3179 ierr = PetscMPIIntCast(n, data->neighbors);CHKERRQ(ierr); 3180 } 3181 if (nranks) *nranks = data->neighbors[0]; 3182 if (ranks) { 3183 if (data->neighbors[0]) *ranks = data->neighbors + 1; 3184 else *ranks = NULL; 3185 } 3186 PetscFunctionReturn(0); 3187 } 3188 3189 PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec); 3190 3191 static PetscErrorCode DMInitialize_Plex(DM dm) 3192 { 3193 PetscErrorCode ierr; 3194 3195 PetscFunctionBegin; 3196 dm->ops->view = DMView_Plex; 3197 dm->ops->load = DMLoad_Plex; 3198 dm->ops->setfromoptions = DMSetFromOptions_Plex; 3199 dm->ops->clone = DMClone_Plex; 3200 dm->ops->setup = DMSetUp_Plex; 3201 dm->ops->createlocalsection = DMCreateLocalSection_Plex; 3202 dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_Plex; 3203 dm->ops->createglobalvector = DMCreateGlobalVector_Plex; 3204 dm->ops->createlocalvector = DMCreateLocalVector_Plex; 3205 dm->ops->getlocaltoglobalmapping = NULL; 3206 dm->ops->createfieldis = NULL; 3207 dm->ops->createcoordinatedm = DMCreateCoordinateDM_Plex; 3208 dm->ops->createcoordinatefield = DMCreateCoordinateField_Plex; 3209 dm->ops->getcoloring = NULL; 3210 dm->ops->creatematrix = DMCreateMatrix_Plex; 3211 dm->ops->createinterpolation = DMCreateInterpolation_Plex; 3212 dm->ops->createmassmatrix = DMCreateMassMatrix_Plex; 3213 dm->ops->createinjection = DMCreateInjection_Plex; 3214 dm->ops->refine = DMRefine_Plex; 3215 dm->ops->coarsen = DMCoarsen_Plex; 3216 dm->ops->refinehierarchy = DMRefineHierarchy_Plex; 3217 dm->ops->coarsenhierarchy = DMCoarsenHierarchy_Plex; 3218 dm->ops->adaptlabel = DMAdaptLabel_Plex; 3219 dm->ops->adaptmetric = DMAdaptMetric_Plex; 3220 dm->ops->globaltolocalbegin = NULL; 3221 dm->ops->globaltolocalend = NULL; 3222 dm->ops->localtoglobalbegin = NULL; 3223 dm->ops->localtoglobalend = NULL; 3224 dm->ops->destroy = DMDestroy_Plex; 3225 dm->ops->createsubdm = DMCreateSubDM_Plex; 3226 dm->ops->createsuperdm = DMCreateSuperDM_Plex; 3227 dm->ops->getdimpoints = DMGetDimPoints_Plex; 3228 dm->ops->locatepoints = DMLocatePoints_Plex; 3229 dm->ops->projectfunctionlocal = DMProjectFunctionLocal_Plex; 3230 dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex; 3231 dm->ops->projectfieldlocal = DMProjectFieldLocal_Plex; 3232 dm->ops->projectfieldlabellocal = DMProjectFieldLabelLocal_Plex; 3233 dm->ops->projectbdfieldlabellocal = DMProjectBdFieldLabelLocal_Plex; 3234 dm->ops->computel2diff = DMComputeL2Diff_Plex; 3235 dm->ops->computel2gradientdiff = DMComputeL2GradientDiff_Plex; 3236 dm->ops->computel2fielddiff = DMComputeL2FieldDiff_Plex; 3237 dm->ops->getneighbors = DMGetNeighbors_Plex; 3238 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C",DMPlexInsertBoundaryValues_Plex);CHKERRQ(ierr); 3239 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertTimeDerviativeBoundaryValues_C",DMPlexInsertTimeDerivativeBoundaryValues_Plex);CHKERRQ(ierr); 3240 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",DMSetUpGLVisViewer_Plex);CHKERRQ(ierr); 3241 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C",DMCreateNeumannOverlap_Plex);CHKERRQ(ierr); 3242 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMPlexGetOverlap_C",DMPlexGetOverlap_Plex);CHKERRQ(ierr); 3243 ierr = PetscObjectComposeFunction((PetscObject)dm,"DMInterpolateSolution_C",DMInterpolateSolution_Plex);CHKERRQ(ierr); 3244 PetscFunctionReturn(0); 3245 } 3246 3247 PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm) 3248 { 3249 DM_Plex *mesh = (DM_Plex *) dm->data; 3250 PetscErrorCode ierr; 3251 3252 PetscFunctionBegin; 3253 mesh->refct++; 3254 (*newdm)->data = mesh; 3255 ierr = PetscObjectChangeTypeName((PetscObject) *newdm, DMPLEX);CHKERRQ(ierr); 3256 ierr = DMInitialize_Plex(*newdm);CHKERRQ(ierr); 3257 PetscFunctionReturn(0); 3258 } 3259 3260 /*MC 3261 DMPLEX = "plex" - A DM object that encapsulates an unstructured mesh, or CW Complex, which can be expressed using a Hasse Diagram. 3262 In the local representation, Vecs contain all unknowns in the interior and shared boundary. This is 3263 specified by a PetscSection object. Ownership in the global representation is determined by 3264 ownership of the underlying DMPlex points. This is specified by another PetscSection object. 3265 3266 Options Database Keys: 3267 + -dm_refine_pre - Refine mesh before distribution 3268 + -dm_refine_uniform_pre - Choose uniform or generator-based refinement 3269 + -dm_refine_volume_limit_pre - Cell volume limit after pre-refinement using generator 3270 . -dm_distribute - Distribute mesh across processes 3271 . -dm_distribute_overlap - Number of cells to overlap for distribution 3272 . -dm_refine - Refine mesh after distribution 3273 . -dm_plex_hash_location - Use grid hashing for point location 3274 . -dm_plex_partition_balance - Attempt to evenly divide points on partition boundary between processes 3275 . -dm_plex_remesh_bd - Allow changes to the boundary on remeshing 3276 . -dm_plex_max_projection_height - Maxmimum mesh point height used to project locally 3277 . -dm_plex_regular_refinement - Use special nested projection algorithm for regular refinement 3278 . -dm_plex_check_all - Perform all shecks below 3279 . -dm_plex_check_symmetry - Check that the adjacency information in the mesh is symmetric 3280 . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices 3281 . -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 3282 . -dm_plex_check_geometry - Check that cells have positive volume 3283 . -dm_view :mesh.tex:ascii_latex - View the mesh in LaTeX/TikZ 3284 . -dm_plex_view_scale <num> - Scale the TikZ 3285 - -dm_plex_print_fem <num> - View FEM assembly information, such as element vectors and matrices 3286 3287 Level: intermediate 3288 3289 .seealso: DMType, DMPlexCreate(), DMCreate(), DMSetType() 3290 M*/ 3291 3292 PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm) 3293 { 3294 DM_Plex *mesh; 3295 PetscInt unit; 3296 PetscErrorCode ierr; 3297 3298 PetscFunctionBegin; 3299 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3300 ierr = PetscNewLog(dm,&mesh);CHKERRQ(ierr); 3301 dm->data = mesh; 3302 3303 mesh->refct = 1; 3304 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection);CHKERRQ(ierr); 3305 mesh->maxConeSize = 0; 3306 mesh->cones = NULL; 3307 mesh->coneOrientations = NULL; 3308 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection);CHKERRQ(ierr); 3309 mesh->maxSupportSize = 0; 3310 mesh->supports = NULL; 3311 mesh->refinementUniform = PETSC_TRUE; 3312 mesh->refinementLimit = -1.0; 3313 mesh->interpolated = DMPLEX_INTERPOLATED_INVALID; 3314 mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID; 3315 3316 mesh->facesTmp = NULL; 3317 3318 mesh->tetgenOpts = NULL; 3319 mesh->triangleOpts = NULL; 3320 ierr = PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner);CHKERRQ(ierr); 3321 mesh->remeshBd = PETSC_FALSE; 3322 3323 mesh->subpointMap = NULL; 3324 3325 for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0; 3326 3327 mesh->regularRefinement = PETSC_FALSE; 3328 mesh->depthState = -1; 3329 mesh->celltypeState = -1; 3330 mesh->globalVertexNumbers = NULL; 3331 mesh->globalCellNumbers = NULL; 3332 mesh->anchorSection = NULL; 3333 mesh->anchorIS = NULL; 3334 mesh->createanchors = NULL; 3335 mesh->computeanchormatrix = NULL; 3336 mesh->parentSection = NULL; 3337 mesh->parents = NULL; 3338 mesh->childIDs = NULL; 3339 mesh->childSection = NULL; 3340 mesh->children = NULL; 3341 mesh->referenceTree = NULL; 3342 mesh->getchildsymmetry = NULL; 3343 mesh->vtkCellHeight = 0; 3344 mesh->useAnchors = PETSC_FALSE; 3345 3346 mesh->maxProjectionHeight = 0; 3347 3348 mesh->neighbors = NULL; 3349 3350 mesh->printSetValues = PETSC_FALSE; 3351 mesh->printFEM = 0; 3352 mesh->printTol = 1.0e-10; 3353 3354 ierr = DMInitialize_Plex(dm);CHKERRQ(ierr); 3355 PetscFunctionReturn(0); 3356 } 3357 3358 /*@ 3359 DMPlexCreate - Creates a DMPlex object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram. 3360 3361 Collective 3362 3363 Input Parameter: 3364 . comm - The communicator for the DMPlex object 3365 3366 Output Parameter: 3367 . mesh - The DMPlex object 3368 3369 Level: beginner 3370 3371 @*/ 3372 PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh) 3373 { 3374 PetscErrorCode ierr; 3375 3376 PetscFunctionBegin; 3377 PetscValidPointer(mesh,2); 3378 ierr = DMCreate(comm, mesh);CHKERRQ(ierr); 3379 ierr = DMSetType(*mesh, DMPLEX);CHKERRQ(ierr); 3380 PetscFunctionReturn(0); 3381 } 3382 3383 /*@C 3384 DMPlexBuildFromCellListParallel - Build distributed DMPLEX topology from a list of vertices for each cell (common mesh generator output) 3385 3386 Input Parameters: 3387 + dm - The DM 3388 . numCells - The number of cells owned by this process 3389 . numVertices - The number of vertices owned by this process, or PETSC_DECIDE 3390 . NVertices - The global number of vertices, or PETSC_DECIDE 3391 . numCorners - The number of vertices for each cell 3392 - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 3393 3394 Output Parameter: 3395 . vertexSF - (Optional) SF describing complete vertex ownership 3396 3397 Notes: 3398 Two triangles sharing a face 3399 $ 3400 $ 2 3401 $ / | \ 3402 $ / | \ 3403 $ / | \ 3404 $ 0 0 | 1 3 3405 $ \ | / 3406 $ \ | / 3407 $ \ | / 3408 $ 1 3409 would have input 3410 $ numCells = 2, numVertices = 4 3411 $ cells = [0 1 2 1 3 2] 3412 $ 3413 which would result in the DMPlex 3414 $ 3415 $ 4 3416 $ / | \ 3417 $ / | \ 3418 $ / | \ 3419 $ 2 0 | 1 5 3420 $ \ | / 3421 $ \ | / 3422 $ \ | / 3423 $ 3 3424 3425 Vertices are implicitly numbered consecutively 0,...,NVertices. 3426 Each rank owns a chunk of numVertices consecutive vertices. 3427 If numVertices is PETSC_DECIDE, PETSc will distribute them as evenly as possible using PetscLayout. 3428 If both NVertices and numVertices are PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1. 3429 If only NVertices is PETSC_DECIDE, it is computed as the sum of numVertices over all ranks. 3430 3431 The cell distribution is arbitrary non-overlapping, independent of the vertex distribution. 3432 3433 Not currently supported in Fortran. 3434 3435 Level: advanced 3436 3437 .seealso: DMPlexBuildFromCellList(), DMPlexCreateFromCellListParallelPetsc(), DMPlexBuildCoordinatesFromCellListParallel() 3438 @*/ 3439 PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PetscSF *vertexSF) 3440 { 3441 PetscSF sfPoint; 3442 PetscLayout layout; 3443 PetscInt numVerticesAdj, *verticesAdj, *cones, c, p, dim; 3444 PetscMPIInt rank, size; 3445 PetscErrorCode ierr; 3446 3447 PetscFunctionBegin; 3448 PetscValidLogicalCollectiveInt(dm,NVertices,4); 3449 ierr = PetscLogEventBegin(DMPLEX_BuildFromCellList,dm,0,0,0);CHKERRQ(ierr); 3450 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr); 3451 ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size);CHKERRMPI(ierr); 3452 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3453 /* Get/check global number of vertices */ 3454 { 3455 PetscInt NVerticesInCells, i; 3456 const PetscInt len = numCells * numCorners; 3457 3458 /* NVerticesInCells = max(cells) + 1 */ 3459 NVerticesInCells = PETSC_MIN_INT; 3460 for (i=0; i<len; i++) if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 3461 ++NVerticesInCells; 3462 ierr = MPI_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr); 3463 3464 if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells; 3465 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); 3466 } 3467 /* Count locally unique vertices */ 3468 { 3469 PetscHSetI vhash; 3470 PetscInt off = 0; 3471 3472 ierr = PetscHSetICreate(&vhash);CHKERRQ(ierr); 3473 for (c = 0; c < numCells; ++c) { 3474 for (p = 0; p < numCorners; ++p) { 3475 ierr = PetscHSetIAdd(vhash, cells[c*numCorners+p]);CHKERRQ(ierr); 3476 } 3477 } 3478 ierr = PetscHSetIGetSize(vhash, &numVerticesAdj);CHKERRQ(ierr); 3479 ierr = PetscMalloc1(numVerticesAdj, &verticesAdj);CHKERRQ(ierr); 3480 ierr = PetscHSetIGetElems(vhash, &off, verticesAdj);CHKERRQ(ierr); 3481 ierr = PetscHSetIDestroy(&vhash);CHKERRQ(ierr); 3482 if (off != numVerticesAdj) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %D should be %D", off, numVerticesAdj); 3483 } 3484 ierr = PetscSortInt(numVerticesAdj, verticesAdj);CHKERRQ(ierr); 3485 /* Create cones */ 3486 ierr = DMPlexSetChart(dm, 0, numCells+numVerticesAdj);CHKERRQ(ierr); 3487 for (c = 0; c < numCells; ++c) {ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr);} 3488 ierr = DMSetUp(dm);CHKERRQ(ierr); 3489 ierr = DMPlexGetCones(dm,&cones);CHKERRQ(ierr); 3490 for (c = 0; c < numCells; ++c) { 3491 for (p = 0; p < numCorners; ++p) { 3492 const PetscInt gv = cells[c*numCorners+p]; 3493 PetscInt lv; 3494 3495 /* Positions within verticesAdj form 0-based local vertex numbering; 3496 we need to shift it by numCells to get correct DAG points (cells go first) */ 3497 ierr = PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv);CHKERRQ(ierr); 3498 if (lv < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %D in local connectivity", gv); 3499 cones[c*numCorners+p] = lv+numCells; 3500 } 3501 } 3502 /* Build point sf */ 3503 ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout);CHKERRQ(ierr); 3504 ierr = PetscLayoutSetSize(layout, NVertices);CHKERRQ(ierr); 3505 ierr = PetscLayoutSetLocalSize(layout, numVertices);CHKERRQ(ierr); 3506 ierr = PetscLayoutSetBlockSize(layout, 1);CHKERRQ(ierr); 3507 ierr = PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint);CHKERRQ(ierr); 3508 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 3509 ierr = PetscFree(verticesAdj);CHKERRQ(ierr); 3510 ierr = PetscObjectSetName((PetscObject) sfPoint, "point SF");CHKERRQ(ierr); 3511 if (dm->sf) { 3512 const char *prefix; 3513 3514 ierr = PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix);CHKERRQ(ierr); 3515 ierr = PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix);CHKERRQ(ierr); 3516 } 3517 ierr = DMSetPointSF(dm, sfPoint);CHKERRQ(ierr); 3518 ierr = PetscSFDestroy(&sfPoint);CHKERRQ(ierr); 3519 if (vertexSF) {ierr = PetscObjectSetName((PetscObject)(*vertexSF), "Vertex Ownership SF");CHKERRQ(ierr);} 3520 /* Fill in the rest of the topology structure */ 3521 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 3522 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 3523 ierr = PetscLogEventEnd(DMPLEX_BuildFromCellList,dm,0,0,0);CHKERRQ(ierr); 3524 PetscFunctionReturn(0); 3525 } 3526 3527 /*@C 3528 DMPlexBuildCoordinatesFromCellListParallel - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output) 3529 3530 Input Parameters: 3531 + dm - The DM 3532 . spaceDim - The spatial dimension used for coordinates 3533 . sfVert - SF describing complete vertex ownership 3534 - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 3535 3536 Level: advanced 3537 3538 Notes: 3539 Not currently supported in Fortran. 3540 3541 .seealso: DMPlexBuildCoordinatesFromCellList(), DMPlexCreateFromCellListParallelPetsc(), DMPlexBuildFromCellListParallel() 3542 @*/ 3543 PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[]) 3544 { 3545 PetscSection coordSection; 3546 Vec coordinates; 3547 PetscScalar *coords; 3548 PetscInt numVertices, numVerticesAdj, coordSize, v, vStart, vEnd; 3549 PetscErrorCode ierr; 3550 3551 PetscFunctionBegin; 3552 ierr = PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList,dm,0,0,0);CHKERRQ(ierr); 3553 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3554 if (vStart < 0 || vEnd < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 3555 ierr = DMSetCoordinateDim(dm, spaceDim);CHKERRQ(ierr); 3556 ierr = PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL);CHKERRQ(ierr); 3557 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); 3558 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3559 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 3560 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 3561 ierr = PetscSectionSetChart(coordSection, vStart, vEnd);CHKERRQ(ierr); 3562 for (v = vStart; v < vEnd; ++v) { 3563 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 3564 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 3565 } 3566 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 3567 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 3568 ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinates);CHKERRQ(ierr); 3569 ierr = VecSetBlockSize(coordinates, spaceDim);CHKERRQ(ierr); 3570 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 3571 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 3572 ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr); 3573 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 3574 { 3575 MPI_Datatype coordtype; 3576 3577 /* Need a temp buffer for coords if we have complex/single */ 3578 ierr = MPI_Type_contiguous(spaceDim, MPIU_SCALAR, &coordtype);CHKERRMPI(ierr); 3579 ierr = MPI_Type_commit(&coordtype);CHKERRMPI(ierr); 3580 #if defined(PETSC_USE_COMPLEX) 3581 { 3582 PetscScalar *svertexCoords; 3583 PetscInt i; 3584 ierr = PetscMalloc1(numVertices*spaceDim,&svertexCoords);CHKERRQ(ierr); 3585 for (i=0; i<numVertices*spaceDim; i++) svertexCoords[i] = vertexCoords[i]; 3586 ierr = PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords,MPI_REPLACE);CHKERRQ(ierr); 3587 ierr = PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords,MPI_REPLACE);CHKERRQ(ierr); 3588 ierr = PetscFree(svertexCoords);CHKERRQ(ierr); 3589 } 3590 #else 3591 ierr = PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords,MPI_REPLACE);CHKERRQ(ierr); 3592 ierr = PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords,MPI_REPLACE);CHKERRQ(ierr); 3593 #endif 3594 ierr = MPI_Type_free(&coordtype);CHKERRMPI(ierr); 3595 } 3596 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 3597 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 3598 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 3599 ierr = PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList,dm,0,0,0);CHKERRQ(ierr); 3600 PetscFunctionReturn(0); 3601 } 3602 3603 /*@ 3604 DMPlexCreateFromCellListParallelPetsc - Create distributed DMPLEX from a list of vertices for each cell (common mesh generator output) 3605 3606 Input Parameters: 3607 + comm - The communicator 3608 . dim - The topological dimension of the mesh 3609 . numCells - The number of cells owned by this process 3610 . numVertices - The number of vertices owned by this process, or PETSC_DECIDE 3611 . NVertices - The global number of vertices, or PETSC_DECIDE 3612 . numCorners - The number of vertices for each cell 3613 . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 3614 . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 3615 . spaceDim - The spatial dimension used for coordinates 3616 - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 3617 3618 Output Parameter: 3619 + dm - The DM 3620 - vertexSF - (Optional) SF describing complete vertex ownership 3621 3622 Notes: 3623 This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(), 3624 DMPlexBuildFromCellListParallel(), DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellListParallel() 3625 3626 See DMPlexBuildFromCellListParallel() for an example and details about the topology-related parameters. 3627 See DMPlexBuildCoordinatesFromCellListParallel() for details about the geometry-related parameters. 3628 3629 Level: intermediate 3630 3631 .seealso: DMPlexCreateFromCellListPetsc(), DMPlexBuildFromCellListParallel(), DMPlexBuildCoordinatesFromCellListParallel(), DMPlexCreateFromDAG(), DMPlexCreate() 3632 @*/ 3633 PetscErrorCode DMPlexCreateFromCellListParallelPetsc(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, PetscBool interpolate, const PetscInt cells[], PetscInt spaceDim, const PetscReal vertexCoords[], PetscSF *vertexSF, DM *dm) 3634 { 3635 PetscSF sfVert; 3636 PetscErrorCode ierr; 3637 3638 PetscFunctionBegin; 3639 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 3640 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 3641 PetscValidLogicalCollectiveInt(*dm, dim, 2); 3642 PetscValidLogicalCollectiveInt(*dm, spaceDim, 9); 3643 ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); 3644 ierr = DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert);CHKERRQ(ierr); 3645 if (interpolate) { 3646 DM idm; 3647 3648 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 3649 ierr = DMDestroy(dm);CHKERRQ(ierr); 3650 *dm = idm; 3651 } 3652 ierr = DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords);CHKERRQ(ierr); 3653 if (vertexSF) *vertexSF = sfVert; 3654 else {ierr = PetscSFDestroy(&sfVert);CHKERRQ(ierr);} 3655 PetscFunctionReturn(0); 3656 } 3657 3658 /*@ 3659 DMPlexCreateFromCellListParallel - Deprecated, use DMPlexCreateFromCellListParallelPetsc() 3660 3661 Level: deprecated 3662 3663 .seealso: DMPlexCreateFromCellListParallelPetsc() 3664 @*/ 3665 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) 3666 { 3667 PetscErrorCode ierr; 3668 PetscInt i; 3669 PetscInt *pintCells; 3670 3671 PetscFunctionBegin; 3672 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)); 3673 if (sizeof(int) == sizeof(PetscInt)) { 3674 pintCells = (PetscInt *) cells; 3675 } else { 3676 ierr = PetscMalloc1(numCells*numCorners, &pintCells);CHKERRQ(ierr); 3677 for (i = 0; i < numCells*numCorners; i++) { 3678 pintCells[i] = (PetscInt) cells[i]; 3679 } 3680 } 3681 ierr = DMPlexCreateFromCellListParallelPetsc(comm, dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, pintCells, spaceDim, vertexCoords, vertexSF, dm);CHKERRQ(ierr); 3682 if (sizeof(int) != sizeof(PetscInt)) { 3683 ierr = PetscFree(pintCells);CHKERRQ(ierr); 3684 } 3685 PetscFunctionReturn(0); 3686 } 3687 3688 /*@C 3689 DMPlexBuildFromCellList - Build DMPLEX topology from a list of vertices for each cell (common mesh generator output) 3690 3691 Input Parameters: 3692 + dm - The DM 3693 . numCells - The number of cells owned by this process 3694 . numVertices - The number of vertices owned by this process, or PETSC_DECIDE 3695 . numCorners - The number of vertices for each cell 3696 - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 3697 3698 Level: advanced 3699 3700 Notes: 3701 Two triangles sharing a face 3702 $ 3703 $ 2 3704 $ / | \ 3705 $ / | \ 3706 $ / | \ 3707 $ 0 0 | 1 3 3708 $ \ | / 3709 $ \ | / 3710 $ \ | / 3711 $ 1 3712 would have input 3713 $ numCells = 2, numVertices = 4 3714 $ cells = [0 1 2 1 3 2] 3715 $ 3716 which would result in the DMPlex 3717 $ 3718 $ 4 3719 $ / | \ 3720 $ / | \ 3721 $ / | \ 3722 $ 2 0 | 1 5 3723 $ \ | / 3724 $ \ | / 3725 $ \ | / 3726 $ 3 3727 3728 If numVertices is PETSC_DECIDE, it is computed by PETSc as the maximum vertex index in cells + 1. 3729 3730 Not currently supported in Fortran. 3731 3732 .seealso: DMPlexBuildFromCellListParallel(), DMPlexBuildCoordinatesFromCellList(), DMPlexCreateFromCellListPetsc() 3733 @*/ 3734 PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[]) 3735 { 3736 PetscInt *cones, c, p, dim; 3737 PetscErrorCode ierr; 3738 3739 PetscFunctionBegin; 3740 ierr = PetscLogEventBegin(DMPLEX_BuildFromCellList,dm,0,0,0);CHKERRQ(ierr); 3741 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3742 /* Get/check global number of vertices */ 3743 { 3744 PetscInt NVerticesInCells, i; 3745 const PetscInt len = numCells * numCorners; 3746 3747 /* NVerticesInCells = max(cells) + 1 */ 3748 NVerticesInCells = PETSC_MIN_INT; 3749 for (i=0; i<len; i++) if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 3750 ++NVerticesInCells; 3751 3752 if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells; 3753 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); 3754 } 3755 ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 3756 for (c = 0; c < numCells; ++c) { 3757 ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); 3758 } 3759 ierr = DMSetUp(dm);CHKERRQ(ierr); 3760 ierr = DMPlexGetCones(dm,&cones);CHKERRQ(ierr); 3761 for (c = 0; c < numCells; ++c) { 3762 for (p = 0; p < numCorners; ++p) { 3763 cones[c*numCorners+p] = cells[c*numCorners+p]+numCells; 3764 } 3765 } 3766 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 3767 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 3768 ierr = PetscLogEventEnd(DMPLEX_BuildFromCellList,dm,0,0,0);CHKERRQ(ierr); 3769 PetscFunctionReturn(0); 3770 } 3771 3772 /*@C 3773 DMPlexBuildCoordinatesFromCellList - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output) 3774 3775 Input Parameters: 3776 + dm - The DM 3777 . spaceDim - The spatial dimension used for coordinates 3778 - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 3779 3780 Level: advanced 3781 3782 Notes: 3783 Not currently supported in Fortran. 3784 3785 .seealso: DMPlexBuildCoordinatesFromCellListParallel(), DMPlexCreateFromCellListPetsc(), DMPlexBuildFromCellList() 3786 @*/ 3787 PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[]) 3788 { 3789 PetscSection coordSection; 3790 Vec coordinates; 3791 DM cdm; 3792 PetscScalar *coords; 3793 PetscInt v, vStart, vEnd, d; 3794 PetscErrorCode ierr; 3795 3796 PetscFunctionBegin; 3797 ierr = PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList,dm,0,0,0);CHKERRQ(ierr); 3798 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3799 if (vStart < 0 || vEnd < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 3800 ierr = DMSetCoordinateDim(dm, spaceDim);CHKERRQ(ierr); 3801 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3802 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 3803 ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 3804 ierr = PetscSectionSetChart(coordSection, vStart, vEnd);CHKERRQ(ierr); 3805 for (v = vStart; v < vEnd; ++v) { 3806 ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 3807 ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 3808 } 3809 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 3810 3811 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 3812 ierr = DMCreateLocalVector(cdm, &coordinates);CHKERRQ(ierr); 3813 ierr = VecSetBlockSize(coordinates, spaceDim);CHKERRQ(ierr); 3814 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 3815 ierr = VecGetArrayWrite(coordinates, &coords);CHKERRQ(ierr); 3816 for (v = 0; v < vEnd-vStart; ++v) { 3817 for (d = 0; d < spaceDim; ++d) { 3818 coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 3819 } 3820 } 3821 ierr = VecRestoreArrayWrite(coordinates, &coords);CHKERRQ(ierr); 3822 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 3823 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 3824 ierr = PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList,dm,0,0,0);CHKERRQ(ierr); 3825 PetscFunctionReturn(0); 3826 } 3827 3828 /*@ 3829 DMPlexCreateFromCellListPetsc - Create DMPLEX from a list of vertices for each cell (common mesh generator output), but only process 0 takes in the input 3830 3831 Collective on comm 3832 3833 Input Parameters: 3834 + comm - The communicator 3835 . dim - The topological dimension of the mesh 3836 . numCells - The number of cells, only on process 0 3837 . numVertices - The number of vertices owned by this process, or PETSC_DECIDE, only on process 0 3838 . numCorners - The number of vertices for each cell, only on process 0 3839 . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 3840 . cells - An array of numCells*numCorners numbers, the vertices for each cell, only on process 0 3841 . spaceDim - The spatial dimension used for coordinates 3842 - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex, only on process 0 3843 3844 Output Parameter: 3845 . dm - The DM, which only has points on process 0 3846 3847 Notes: 3848 This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(), DMPlexBuildFromCellList(), 3849 DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellList() 3850 3851 See DMPlexBuildFromCellList() for an example and details about the topology-related parameters. 3852 See DMPlexBuildCoordinatesFromCellList() for details about the geometry-related parameters. 3853 See DMPlexCreateFromCellListParallelPetsc() for parallel input 3854 3855 Level: intermediate 3856 3857 .seealso: DMPlexCreateFromCellListParallelPetsc(), DMPlexBuildFromCellList(), DMPlexBuildCoordinatesFromCellList(), DMPlexCreateFromDAG(), DMPlexCreate() 3858 @*/ 3859 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) 3860 { 3861 PetscMPIInt rank; 3862 PetscErrorCode ierr; 3863 3864 PetscFunctionBegin; 3865 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."); 3866 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 3867 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 3868 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 3869 ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); 3870 if (!rank) {ierr = DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr);} 3871 else {ierr = DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL);CHKERRQ(ierr);} 3872 if (interpolate) { 3873 DM idm; 3874 3875 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 3876 ierr = DMDestroy(dm);CHKERRQ(ierr); 3877 *dm = idm; 3878 } 3879 if (!rank) {ierr = DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords);CHKERRQ(ierr);} 3880 else {ierr = DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL);CHKERRQ(ierr);} 3881 PetscFunctionReturn(0); 3882 } 3883 3884 /*@ 3885 DMPlexCreateFromCellList - Deprecated, use DMPlexCreateFromCellListPetsc() 3886 3887 Level: deprecated 3888 3889 .seealso: DMPlexCreateFromCellListPetsc() 3890 @*/ 3891 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) 3892 { 3893 PetscErrorCode ierr; 3894 PetscInt i; 3895 PetscInt *pintCells; 3896 PetscReal *prealVC; 3897 3898 PetscFunctionBegin; 3899 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)); 3900 if (sizeof(int) == sizeof(PetscInt)) { 3901 pintCells = (PetscInt *) cells; 3902 } else { 3903 ierr = PetscMalloc1(numCells*numCorners, &pintCells);CHKERRQ(ierr); 3904 for (i = 0; i < numCells*numCorners; i++) { 3905 pintCells[i] = (PetscInt) cells[i]; 3906 } 3907 } 3908 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)); 3909 if (sizeof(double) == sizeof(PetscReal)) { 3910 prealVC = (PetscReal *) vertexCoords; 3911 } else { 3912 ierr = PetscMalloc1(numVertices*spaceDim, &prealVC);CHKERRQ(ierr); 3913 for (i = 0; i < numVertices*spaceDim; i++) { 3914 prealVC[i] = (PetscReal) vertexCoords[i]; 3915 } 3916 } 3917 ierr = DMPlexCreateFromCellListPetsc(comm, dim, numCells, numVertices, numCorners, interpolate, pintCells, spaceDim, prealVC, dm);CHKERRQ(ierr); 3918 if (sizeof(int) != sizeof(PetscInt)) { 3919 ierr = PetscFree(pintCells);CHKERRQ(ierr); 3920 } 3921 if (sizeof(double) != sizeof(PetscReal)) { 3922 ierr = PetscFree(prealVC);CHKERRQ(ierr); 3923 } 3924 PetscFunctionReturn(0); 3925 } 3926 3927 /*@ 3928 DMPlexCreateFromDAG - This takes as input the adjacency-list representation of the Directed Acyclic Graph (Hasse Diagram) encoding a mesh, and produces a DM 3929 3930 Input Parameters: 3931 + dm - The empty DM object, usually from DMCreate() and DMSetDimension() 3932 . depth - The depth of the DAG 3933 . numPoints - Array of size depth + 1 containing the number of points at each depth 3934 . coneSize - The cone size of each point 3935 . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point 3936 . coneOrientations - The orientation of each cone point 3937 - vertexCoords - An array of numPoints[0]*spacedim numbers representing the coordinates of each vertex, with spacedim the value set via DMSetCoordinateDim() 3938 3939 Output Parameter: 3940 . dm - The DM 3941 3942 Note: Two triangles sharing a face would have input 3943 $ depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0] 3944 $ cones = [2 3 4 3 5 4], coneOrientations = [0 0 0 0 0 0] 3945 $ vertexCoords = [-1.0 0.0 0.0 -1.0 0.0 1.0 1.0 0.0] 3946 $ 3947 which would result in the DMPlex 3948 $ 3949 $ 4 3950 $ / | \ 3951 $ / | \ 3952 $ / | \ 3953 $ 2 0 | 1 5 3954 $ \ | / 3955 $ \ | / 3956 $ \ | / 3957 $ 3 3958 $ 3959 $ Notice that all points are numbered consecutively, unlike DMPlexCreateFromCellListPetsc() 3960 3961 Level: advanced 3962 3963 .seealso: DMPlexCreateFromCellListPetsc(), DMPlexCreate() 3964 @*/ 3965 PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[]) 3966 { 3967 Vec coordinates; 3968 PetscSection coordSection; 3969 PetscScalar *coords; 3970 PetscInt coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off; 3971 PetscErrorCode ierr; 3972 3973 PetscFunctionBegin; 3974 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 3975 ierr = DMGetCoordinateDim(dm, &dimEmbed);CHKERRQ(ierr); 3976 if (dimEmbed < dim) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Embedding dimension %D cannot be less than intrinsic dimension %d",dimEmbed,dim); 3977 for (d = 0; d <= depth; ++d) pEnd += numPoints[d]; 3978 ierr = DMPlexSetChart(dm, pStart, pEnd);CHKERRQ(ierr); 3979 for (p = pStart; p < pEnd; ++p) { 3980 ierr = DMPlexSetConeSize(dm, p, coneSize[p-pStart]);CHKERRQ(ierr); 3981 if (firstVertex < 0 && !coneSize[p - pStart]) { 3982 firstVertex = p - pStart; 3983 } 3984 } 3985 if (firstVertex < 0 && numPoints[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Expected %D vertices but could not find any", numPoints[0]); 3986 ierr = DMSetUp(dm);CHKERRQ(ierr); /* Allocate space for cones */ 3987 for (p = pStart, off = 0; p < pEnd; off += coneSize[p-pStart], ++p) { 3988 ierr = DMPlexSetCone(dm, p, &cones[off]);CHKERRQ(ierr); 3989 ierr = DMPlexSetConeOrientation(dm, p, &coneOrientations[off]);CHKERRQ(ierr); 3990 } 3991 ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 3992 ierr = DMPlexStratify(dm);CHKERRQ(ierr); 3993 /* Build coordinates */ 3994 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3995 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 3996 ierr = PetscSectionSetFieldComponents(coordSection, 0, dimEmbed);CHKERRQ(ierr); 3997 ierr = PetscSectionSetChart(coordSection, firstVertex, firstVertex+numPoints[0]);CHKERRQ(ierr); 3998 for (v = firstVertex; v < firstVertex+numPoints[0]; ++v) { 3999 ierr = PetscSectionSetDof(coordSection, v, dimEmbed);CHKERRQ(ierr); 4000 ierr = PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed);CHKERRQ(ierr); 4001 } 4002 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4003 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4004 ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr); 4005 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 4006 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4007 ierr = VecSetBlockSize(coordinates, dimEmbed);CHKERRQ(ierr); 4008 ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr); 4009 if (vertexCoords) { 4010 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4011 for (v = 0; v < numPoints[0]; ++v) { 4012 PetscInt off; 4013 4014 ierr = PetscSectionGetOffset(coordSection, v+firstVertex, &off);CHKERRQ(ierr); 4015 for (d = 0; d < dimEmbed; ++d) { 4016 coords[off+d] = vertexCoords[v*dimEmbed+d]; 4017 } 4018 } 4019 } 4020 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4021 ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4022 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4023 PetscFunctionReturn(0); 4024 } 4025 4026 /*@C 4027 DMPlexCreateCellVertexFromFile - Create a DMPlex mesh from a simple cell-vertex file. 4028 4029 + comm - The MPI communicator 4030 . filename - Name of the .dat file 4031 - interpolate - Create faces and edges in the mesh 4032 4033 Output Parameter: 4034 . dm - The DM object representing the mesh 4035 4036 Note: The format is the simplest possible: 4037 $ Ne 4038 $ v0 v1 ... vk 4039 $ Nv 4040 $ x y z marker 4041 4042 Level: beginner 4043 4044 .seealso: DMPlexCreateFromFile(), DMPlexCreateMedFromFile(), DMPlexCreateGmsh(), DMPlexCreate() 4045 @*/ 4046 PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 4047 { 4048 DMLabel marker; 4049 PetscViewer viewer; 4050 Vec coordinates; 4051 PetscSection coordSection; 4052 PetscScalar *coords; 4053 char line[PETSC_MAX_PATH_LEN]; 4054 PetscInt dim = 3, cdim = 3, coordSize, v, c, d; 4055 PetscMPIInt rank; 4056 int snum, Nv, Nc; 4057 PetscErrorCode ierr; 4058 4059 PetscFunctionBegin; 4060 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 4061 ierr = PetscViewerCreate(comm, &viewer);CHKERRQ(ierr); 4062 ierr = PetscViewerSetType(viewer, PETSCVIEWERASCII);CHKERRQ(ierr); 4063 ierr = PetscViewerFileSetMode(viewer, FILE_MODE_READ);CHKERRQ(ierr); 4064 ierr = PetscViewerFileSetName(viewer, filename);CHKERRQ(ierr); 4065 if (!rank) { 4066 ierr = PetscViewerRead(viewer, line, 2, NULL, PETSC_STRING);CHKERRQ(ierr); 4067 snum = sscanf(line, "%d %d", &Nc, &Nv); 4068 if (snum != 2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 4069 } else { 4070 Nc = Nv = 0; 4071 } 4072 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 4073 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 4074 ierr = DMPlexSetChart(*dm, 0, Nc+Nv);CHKERRQ(ierr); 4075 ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); 4076 ierr = DMSetCoordinateDim(*dm, cdim);CHKERRQ(ierr); 4077 /* Read topology */ 4078 if (!rank) { 4079 PetscInt cone[8], corners = 8; 4080 int vbuf[8], v; 4081 4082 for (c = 0; c < Nc; ++c) {ierr = DMPlexSetConeSize(*dm, c, corners);CHKERRQ(ierr);} 4083 ierr = DMSetUp(*dm);CHKERRQ(ierr); 4084 for (c = 0; c < Nc; ++c) { 4085 ierr = PetscViewerRead(viewer, line, corners, NULL, PETSC_STRING);CHKERRQ(ierr); 4086 snum = sscanf(line, "%d %d %d %d %d %d %d %d", &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]); 4087 if (snum != corners) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 4088 for (v = 0; v < corners; ++v) cone[v] = vbuf[v] + Nc; 4089 /* Hexahedra are inverted */ 4090 { 4091 PetscInt tmp = cone[1]; 4092 cone[1] = cone[3]; 4093 cone[3] = tmp; 4094 } 4095 ierr = DMPlexSetCone(*dm, c, cone);CHKERRQ(ierr); 4096 } 4097 } 4098 ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr); 4099 ierr = DMPlexStratify(*dm);CHKERRQ(ierr); 4100 /* Read coordinates */ 4101 ierr = DMGetCoordinateSection(*dm, &coordSection);CHKERRQ(ierr); 4102 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4103 ierr = PetscSectionSetFieldComponents(coordSection, 0, cdim);CHKERRQ(ierr); 4104 ierr = PetscSectionSetChart(coordSection, Nc, Nc + Nv);CHKERRQ(ierr); 4105 for (v = Nc; v < Nc+Nv; ++v) { 4106 ierr = PetscSectionSetDof(coordSection, v, cdim);CHKERRQ(ierr); 4107 ierr = PetscSectionSetFieldDof(coordSection, v, 0, cdim);CHKERRQ(ierr); 4108 } 4109 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4110 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4111 ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr); 4112 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 4113 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4114 ierr = VecSetBlockSize(coordinates, cdim);CHKERRQ(ierr); 4115 ierr = VecSetType(coordinates, VECSTANDARD);CHKERRQ(ierr); 4116 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4117 if (!rank) { 4118 double x[3]; 4119 int val; 4120 4121 ierr = DMCreateLabel(*dm, "marker");CHKERRQ(ierr); 4122 ierr = DMGetLabel(*dm, "marker", &marker);CHKERRQ(ierr); 4123 for (v = 0; v < Nv; ++v) { 4124 ierr = PetscViewerRead(viewer, line, 4, NULL, PETSC_STRING);CHKERRQ(ierr); 4125 snum = sscanf(line, "%lg %lg %lg %d", &x[0], &x[1], &x[2], &val); 4126 if (snum != 4) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 4127 for (d = 0; d < cdim; ++d) coords[v*cdim+d] = x[d]; 4128 if (val) {ierr = DMLabelSetValue(marker, v+Nc, val);CHKERRQ(ierr);} 4129 } 4130 } 4131 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4132 ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr); 4133 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4134 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 4135 if (interpolate) { 4136 DM idm; 4137 DMLabel bdlabel; 4138 4139 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 4140 ierr = DMDestroy(dm);CHKERRQ(ierr); 4141 *dm = idm; 4142 4143 ierr = DMGetLabel(*dm, "marker", &bdlabel);CHKERRQ(ierr); 4144 ierr = DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel);CHKERRQ(ierr); 4145 ierr = DMPlexLabelComplete(*dm, bdlabel);CHKERRQ(ierr); 4146 } 4147 PetscFunctionReturn(0); 4148 } 4149 4150 /*@C 4151 DMPlexCreateFromFile - This takes a filename and produces a DM 4152 4153 Input Parameters: 4154 + comm - The communicator 4155 . filename - A file name 4156 - interpolate - Flag to create intermediate mesh pieces (edges, faces) 4157 4158 Output Parameter: 4159 . dm - The DM 4160 4161 Options Database Keys: 4162 . -dm_plex_create_from_hdf5_xdmf - use the PETSC_VIEWER_HDF5_XDMF format for reading HDF5 4163 4164 Use -dm_plex_create_ prefix to pass options to the internal PetscViewer, e.g. 4165 $ -dm_plex_create_viewer_hdf5_collective 4166 4167 Level: beginner 4168 4169 .seealso: DMPlexCreateFromDAG(), DMPlexCreateFromCellListPetsc(), DMPlexCreate() 4170 @*/ 4171 PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 4172 { 4173 const char *extGmsh = ".msh"; 4174 const char *extGmsh2 = ".msh2"; 4175 const char *extGmsh4 = ".msh4"; 4176 const char *extCGNS = ".cgns"; 4177 const char *extExodus = ".exo"; 4178 const char *extGenesis = ".gen"; 4179 const char *extFluent = ".cas"; 4180 const char *extHDF5 = ".h5"; 4181 const char *extMed = ".med"; 4182 const char *extPLY = ".ply"; 4183 const char *extEGADSLite = ".egadslite"; 4184 const char *extEGADS = ".egads"; 4185 const char *extIGES = ".igs"; 4186 const char *extSTEP = ".stp"; 4187 const char *extCV = ".dat"; 4188 size_t len; 4189 PetscBool isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isMed, isPLY, isEGADSLite, isEGADS, isIGES, isSTEP, isCV; 4190 PetscMPIInt rank; 4191 PetscErrorCode ierr; 4192 4193 PetscFunctionBegin; 4194 PetscValidCharPointer(filename, 2); 4195 PetscValidPointer(dm, 4); 4196 ierr = DMInitializePackage();CHKERRQ(ierr); 4197 ierr = PetscLogEventBegin(DMPLEX_CreateFromFile,0,0,0,0);CHKERRQ(ierr); 4198 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 4199 ierr = PetscStrlen(filename, &len);CHKERRQ(ierr); 4200 if (!len) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path"); 4201 ierr = PetscStrncmp(&filename[PetscMax(0,len-4)], extGmsh, 4, &isGmsh);CHKERRQ(ierr); 4202 ierr = PetscStrncmp(&filename[PetscMax(0,len-5)], extGmsh2, 5, &isGmsh2);CHKERRQ(ierr); 4203 ierr = PetscStrncmp(&filename[PetscMax(0,len-5)], extGmsh4, 5, &isGmsh4);CHKERRQ(ierr); 4204 ierr = PetscStrncmp(&filename[PetscMax(0,len-5)], extCGNS, 5, &isCGNS);CHKERRQ(ierr); 4205 ierr = PetscStrncmp(&filename[PetscMax(0,len-4)], extExodus, 4, &isExodus);CHKERRQ(ierr); 4206 ierr = PetscStrncmp(&filename[PetscMax(0,len-4)], extGenesis, 4, &isGenesis);CHKERRQ(ierr); 4207 ierr = PetscStrncmp(&filename[PetscMax(0,len-4)], extFluent, 4, &isFluent);CHKERRQ(ierr); 4208 ierr = PetscStrncmp(&filename[PetscMax(0,len-3)], extHDF5, 3, &isHDF5);CHKERRQ(ierr); 4209 ierr = PetscStrncmp(&filename[PetscMax(0,len-4)], extMed, 4, &isMed);CHKERRQ(ierr); 4210 ierr = PetscStrncmp(&filename[PetscMax(0,len-4)], extPLY, 4, &isPLY);CHKERRQ(ierr); 4211 ierr = PetscStrncmp(&filename[PetscMax(0,len-10)], extEGADSLite, 10, &isEGADSLite);CHKERRQ(ierr); 4212 ierr = PetscStrncmp(&filename[PetscMax(0,len-6)], extEGADS, 6, &isEGADS);CHKERRQ(ierr); 4213 ierr = PetscStrncmp(&filename[PetscMax(0,len-4)], extIGES, 4, &isIGES);CHKERRQ(ierr); 4214 ierr = PetscStrncmp(&filename[PetscMax(0,len-4)], extSTEP, 4, &isSTEP);CHKERRQ(ierr); 4215 ierr = PetscStrncmp(&filename[PetscMax(0,len-4)], extCV, 4, &isCV);CHKERRQ(ierr); 4216 if (isGmsh || isGmsh2 || isGmsh4) { 4217 ierr = DMPlexCreateGmshFromFile(comm, filename, interpolate, dm);CHKERRQ(ierr); 4218 } else if (isCGNS) { 4219 ierr = DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm);CHKERRQ(ierr); 4220 } else if (isExodus || isGenesis) { 4221 ierr = DMPlexCreateExodusFromFile(comm, filename, interpolate, dm);CHKERRQ(ierr); 4222 } else if (isFluent) { 4223 ierr = DMPlexCreateFluentFromFile(comm, filename, interpolate, dm);CHKERRQ(ierr); 4224 } else if (isHDF5) { 4225 PetscBool load_hdf5_xdmf = PETSC_FALSE; 4226 PetscViewer viewer; 4227 4228 /* PETSC_VIEWER_HDF5_XDMF is used if the filename ends with .xdmf.h5, or if -dm_plex_create_from_hdf5_xdmf option is present */ 4229 ierr = PetscStrncmp(&filename[PetscMax(0,len-8)], ".xdmf", 5, &load_hdf5_xdmf);CHKERRQ(ierr); 4230 ierr = PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &load_hdf5_xdmf, NULL);CHKERRQ(ierr); 4231 ierr = PetscViewerCreate(comm, &viewer);CHKERRQ(ierr); 4232 ierr = PetscViewerSetType(viewer, PETSCVIEWERHDF5);CHKERRQ(ierr); 4233 ierr = PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_");CHKERRQ(ierr); 4234 ierr = PetscViewerSetFromOptions(viewer);CHKERRQ(ierr); 4235 ierr = PetscViewerFileSetMode(viewer, FILE_MODE_READ);CHKERRQ(ierr); 4236 ierr = PetscViewerFileSetName(viewer, filename);CHKERRQ(ierr); 4237 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 4238 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 4239 if (load_hdf5_xdmf) {ierr = PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF);CHKERRQ(ierr);} 4240 ierr = DMLoad(*dm, viewer);CHKERRQ(ierr); 4241 if (load_hdf5_xdmf) {ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);} 4242 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 4243 4244 if (interpolate) { 4245 DM idm; 4246 4247 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 4248 ierr = DMDestroy(dm);CHKERRQ(ierr); 4249 *dm = idm; 4250 } 4251 } else if (isMed) { 4252 ierr = DMPlexCreateMedFromFile(comm, filename, interpolate, dm);CHKERRQ(ierr); 4253 } else if (isPLY) { 4254 ierr = DMPlexCreatePLYFromFile(comm, filename, interpolate, dm);CHKERRQ(ierr); 4255 } else if (isEGADSLite || isEGADS || isIGES || isSTEP) { 4256 if (isEGADSLite) {ierr = DMPlexCreateEGADSLiteFromFile(comm, filename, dm);CHKERRQ(ierr);} 4257 else {ierr = DMPlexCreateEGADSFromFile(comm, filename, dm);CHKERRQ(ierr);} 4258 if (!interpolate) { 4259 DM udm; 4260 4261 ierr = DMPlexUninterpolate(*dm, &udm);CHKERRQ(ierr); 4262 ierr = DMDestroy(dm);CHKERRQ(ierr); 4263 *dm = udm; 4264 } 4265 } else if (isCV) { 4266 ierr = DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm);CHKERRQ(ierr); 4267 } else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename); 4268 ierr = PetscLogEventEnd(DMPLEX_CreateFromFile,0,0,0,0);CHKERRQ(ierr); 4269 PetscFunctionReturn(0); 4270 } 4271