1 #define PETSCDM_DLL 2 #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 3 4 /*@C 5 DMPlexCreateGmshFromFile - Create a DMPlex mesh from a Gmsh file 6 7 + comm - The MPI communicator 8 . filename - Name of the Gmsh file 9 - interpolate - Create faces and edges in the mesh 10 11 Output Parameter: 12 . dm - The DM object representing the mesh 13 14 Level: beginner 15 16 .seealso: DMPlexCreateFromFile(), DMPlexCreateGmsh(), DMPlexCreate() 17 @*/ 18 PetscErrorCode DMPlexCreateGmshFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 19 { 20 PetscViewer viewer; 21 PetscMPIInt rank; 22 int fileType; 23 PetscViewerType vtype; 24 PetscErrorCode ierr; 25 26 PetscFunctionBegin; 27 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 28 29 /* Determine Gmsh file type (ASCII or binary) from file header */ 30 if (!rank) { 31 PetscViewer vheader; 32 char line[PETSC_MAX_PATH_LEN]; 33 PetscBool match; 34 int snum; 35 float version; 36 37 ierr = PetscViewerCreate(PETSC_COMM_SELF, &vheader);CHKERRQ(ierr); 38 ierr = PetscViewerSetType(vheader, PETSCVIEWERASCII);CHKERRQ(ierr); 39 ierr = PetscViewerFileSetMode(vheader, FILE_MODE_READ);CHKERRQ(ierr); 40 ierr = PetscViewerFileSetName(vheader, filename);CHKERRQ(ierr); 41 /* Read only the first two lines of the Gmsh file */ 42 ierr = PetscViewerRead(vheader, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); 43 ierr = PetscStrncmp(line, "$MeshFormat", sizeof(line), &match);CHKERRQ(ierr); 44 if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); 45 ierr = PetscViewerRead(vheader, line, 2, NULL, PETSC_STRING);CHKERRQ(ierr); 46 snum = sscanf(line, "%f %d", &version, &fileType); 47 if (snum != 2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Gmsh file header: %s", line); 48 if (version < 2.0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Gmsh file must be at least version 2.0"); 49 ierr = PetscViewerDestroy(&vheader);CHKERRQ(ierr); 50 } 51 ierr = MPI_Bcast(&fileType, 1, MPI_INT, 0, comm);CHKERRQ(ierr); 52 vtype = (fileType == 0) ? PETSCVIEWERASCII : PETSCVIEWERBINARY; 53 54 /* Create appropriate viewer and build plex */ 55 ierr = PetscViewerCreate(comm, &viewer);CHKERRQ(ierr); 56 ierr = PetscViewerSetType(viewer, vtype);CHKERRQ(ierr); 57 ierr = PetscViewerFileSetMode(viewer, FILE_MODE_READ);CHKERRQ(ierr); 58 ierr = PetscViewerFileSetName(viewer, filename);CHKERRQ(ierr); 59 ierr = DMPlexCreateGmsh(comm, viewer, interpolate, dm);CHKERRQ(ierr); 60 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 61 PetscFunctionReturn(0); 62 } 63 64 static PetscErrorCode DMPlexCreateGmsh_ReadNodes(PetscViewer viewer, PetscBool binary, PetscBool byteSwap, int shift, int numVertices, double **coordinates) 65 { 66 int v,nid; 67 PetscErrorCode ierr; 68 69 PetscFunctionBegin; 70 ierr = PetscMalloc1(numVertices*3, coordinates);CHKERRQ(ierr); 71 for (v = 0; v < numVertices; ++v) { 72 double *xyz = *coordinates + v*3; 73 ierr = PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM);CHKERRQ(ierr); 74 if (byteSwap) {ierr = PetscByteSwap(&nid, PETSC_ENUM, 1);CHKERRQ(ierr);} 75 if (nid != v+shift) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unexpected node number %d should be %d", nid, v+shift); 76 ierr = PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE);CHKERRQ(ierr); 77 if (byteSwap) {ierr = PetscByteSwap(xyz, PETSC_DOUBLE, 3);CHKERRQ(ierr);} 78 } 79 PetscFunctionReturn(0); 80 } 81 82 static PetscErrorCode DMPlexCreateGmsh_ReadElements(PetscViewer viewer, PetscBool binary, PetscBool byteSwap, PETSC_UNUSED int shift, int numCells, GmshElement **gmsh_elems) 83 { 84 GmshElement *elements; 85 int i, c, p, ibuf[1+4+512]; 86 int cellType, dim, numNodes, numNodesIgnore, numElem, numTags; 87 PetscErrorCode ierr; 88 89 PetscFunctionBegin; 90 ierr = PetscMalloc1(numCells, &elements);CHKERRQ(ierr); 91 for (c = 0; c < numCells;) { 92 ierr = PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM);CHKERRQ(ierr); 93 if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, 3);CHKERRQ(ierr);} 94 if (binary) { 95 cellType = ibuf[0]; 96 numElem = ibuf[1]; 97 numTags = ibuf[2]; 98 } else { 99 elements[c].id = ibuf[0]; 100 cellType = ibuf[1]; 101 numTags = ibuf[2]; 102 numElem = 1; 103 } 104 /* http://gmsh.info/doc/texinfo/gmsh.html#MSH-ASCII-file-format */ 105 numNodesIgnore = 0; 106 switch (cellType) { 107 case 1: /* 2-node line */ 108 dim = 1; 109 numNodes = 2; 110 break; 111 case 2: /* 3-node triangle */ 112 dim = 2; 113 numNodes = 3; 114 break; 115 case 3: /* 4-node quadrangle */ 116 dim = 2; 117 numNodes = 4; 118 break; 119 case 4: /* 4-node tetrahedron */ 120 dim = 3; 121 numNodes = 4; 122 break; 123 case 5: /* 8-node hexahedron */ 124 dim = 3; 125 numNodes = 8; 126 break; 127 case 8: /* 3-node 2nd order line */ 128 dim = 1; 129 numNodes = 2; 130 numNodesIgnore = 1; 131 break; 132 case 9: /* 6-node 2nd order triangle */ 133 dim = 2; 134 numNodes = 3; 135 numNodesIgnore = 3; 136 break; 137 case 15: /* 1-node vertex */ 138 dim = 0; 139 numNodes = 1; 140 break; 141 case 6: /* 6-node prism */ 142 case 7: /* 5-node pyramid */ 143 case 10: /* 9-node 2nd order quadrangle */ 144 case 11: /* 10-node 2nd order tetrahedron */ 145 case 12: /* 27-node 2nd order hexhedron */ 146 case 13: /* 19-node 2nd order prism */ 147 case 14: /* 14-node 2nd order pyramid */ 148 default: 149 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported Gmsh element type %d", cellType); 150 } 151 if (binary) { 152 const int nint = 1 + numTags + numNodes + numNodesIgnore; 153 /* Loop over element blocks */ 154 for (i = 0; i < numElem; ++i, ++c) { 155 ierr = PetscViewerRead(viewer, ibuf, nint, NULL, PETSC_ENUM);CHKERRQ(ierr); 156 if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, nint);CHKERRQ(ierr);} 157 elements[c].dim = dim; 158 elements[c].numNodes = numNodes; 159 elements[c].numTags = numTags; 160 elements[c].id = ibuf[0]; 161 for (p = 0; p < numTags; p++) elements[c].tags[p] = ibuf[1 + p]; 162 for (p = 0; p < numNodes; p++) elements[c].nodes[p] = ibuf[1 + numTags + p]; 163 } 164 } else { 165 elements[c].dim = dim; 166 elements[c].numNodes = numNodes; 167 elements[c].numTags = numTags; 168 ierr = PetscViewerRead(viewer, elements[c].tags, elements[c].numTags, NULL, PETSC_ENUM);CHKERRQ(ierr); 169 ierr = PetscViewerRead(viewer, elements[c].nodes, elements[c].numNodes, NULL, PETSC_ENUM);CHKERRQ(ierr); 170 ierr = PetscViewerRead(viewer, ibuf, numNodesIgnore, NULL, PETSC_ENUM);CHKERRQ(ierr); 171 c++; 172 } 173 } 174 *gmsh_elems = elements; 175 PetscFunctionReturn(0); 176 } 177 178 /*@ 179 DMPlexCreateGmsh - Create a DMPlex mesh from a Gmsh file viewer 180 181 Collective on comm 182 183 Input Parameters: 184 + comm - The MPI communicator 185 . viewer - The Viewer associated with a Gmsh file 186 - interpolate - Create faces and edges in the mesh 187 188 Output Parameter: 189 . dm - The DM object representing the mesh 190 191 Note: http://www.geuz.org/gmsh/doc/texinfo/#MSH-ASCII-file-format 192 and http://www.geuz.org/gmsh/doc/texinfo/#MSH-binary-file-format 193 194 Level: beginner 195 196 .keywords: mesh,Gmsh 197 .seealso: DMPLEX, DMCreate() 198 @*/ 199 PetscErrorCode DMPlexCreateGmsh(MPI_Comm comm, PetscViewer viewer, PetscBool interpolate, DM *dm) 200 { 201 PetscViewer parentviewer = NULL; 202 double *coordsIn = NULL; 203 GmshElement *gmsh_elem = NULL; 204 PetscSection coordSection; 205 Vec coordinates; 206 PetscBT periodicV = NULL, periodicC = NULL; 207 PetscScalar *coords; 208 PetscInt dim = 0, embedDim, coordSize, c, v, d, r, cell, *periodicMap = NULL, *periodicMapI = NULL; 209 int i, numVertices = 0, numCells = 0, trueNumCells = 0, numRegions = 0, snum, shift = 1; 210 PetscMPIInt rank; 211 char line[PETSC_MAX_PATH_LEN]; 212 PetscBool binary, mpiio, byteSwap = PETSC_FALSE, zerobase = PETSC_FALSE, isbd = PETSC_FALSE, periodic = PETSC_FALSE, usemarker = PETSC_FALSE; 213 PetscErrorCode ierr; 214 215 PetscFunctionBegin; 216 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 217 ierr = PetscOptionsGetBool(NULL, NULL, "-dm_plex_gmsh_periodic", &periodic, NULL);CHKERRQ(ierr); 218 ierr = PetscOptionsGetBool(NULL, NULL, "-dm_plex_gmsh_usemarker", &usemarker, NULL);CHKERRQ(ierr); 219 ierr = PetscOptionsGetBool(NULL, NULL, "-gmsh_zero_base", &zerobase, NULL);CHKERRQ(ierr); 220 ierr = PetscOptionsGetBool(NULL, NULL, "-gmsh_bd", &isbd, NULL);CHKERRQ(ierr); 221 if (zerobase) shift = 0; 222 223 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 224 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 225 ierr = PetscLogEventBegin(DMPLEX_CreateGmsh,*dm,0,0,0);CHKERRQ(ierr); 226 227 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &binary);CHKERRQ(ierr); 228 ierr = PetscViewerBinaryGetUseMPIIO(viewer, &mpiio);CHKERRQ(ierr); 229 230 /* Binary viewers read on all ranks, get subviewer to read only in rank 0 */ 231 if (binary && !mpiio) { 232 parentviewer = viewer; 233 ierr = PetscViewerGetSubViewer(parentviewer, PETSC_COMM_SELF, &viewer);CHKERRQ(ierr); 234 } 235 236 if (!rank || mpiio) { 237 PetscBool match; 238 int fileType, dataSize; 239 float version; 240 241 /* Read header */ 242 ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); 243 ierr = PetscStrncmp(line, "$MeshFormat", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); 244 if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); 245 ierr = PetscViewerRead(viewer, line, 3, NULL, PETSC_STRING);CHKERRQ(ierr); 246 snum = sscanf(line, "%f %d %d", &version, &fileType, &dataSize); 247 if (snum != 3) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Gmsh file header: %s", line); 248 if (version < 2.0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Gmsh file must be at least version 2.0"); 249 if (dataSize != sizeof(double)) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data size %d is not valid for a Gmsh file", dataSize); 250 if (binary) { 251 int checkInt; 252 ierr = PetscViewerRead(viewer, &checkInt, 1, NULL, PETSC_ENUM);CHKERRQ(ierr); 253 if (checkInt != 1) { 254 ierr = PetscByteSwap(&checkInt, PETSC_ENUM, 1);CHKERRQ(ierr); 255 if (checkInt == 1) byteSwap = PETSC_TRUE; 256 else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File type %d is not a valid Gmsh binary file", fileType); 257 } 258 } else if (fileType) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File type %d is not a valid Gmsh ASCII file", fileType); 259 ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); 260 ierr = PetscStrncmp(line, "$EndMeshFormat", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); 261 if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); 262 263 /* OPTIONAL Read physical names */ 264 ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); 265 ierr = PetscStrncmp(line, "$PhysicalNames", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); 266 if (match) { 267 ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); 268 snum = sscanf(line, "%d", &numRegions); 269 if (snum != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); 270 for (r = 0; r < numRegions; ++r) { 271 ierr = PetscViewerRead(viewer, line, 3, NULL, PETSC_STRING);CHKERRQ(ierr); 272 } 273 ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); 274 ierr = PetscStrncmp(line, "$EndPhysicalNames", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); 275 if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); 276 /* Initial read for vertex section */ 277 ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); 278 } 279 280 /* Read vertices */ 281 ierr = PetscStrncmp(line, "$Nodes", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); 282 if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); 283 ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); 284 snum = sscanf(line, "%d", &numVertices); 285 if (snum != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); 286 ierr = DMPlexCreateGmsh_ReadNodes(viewer, binary, byteSwap, shift, numVertices, &coordsIn);CHKERRQ(ierr); 287 ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);; 288 ierr = PetscStrncmp(line, "$EndNodes", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); 289 if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); 290 291 /* Read cells */ 292 ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);; 293 ierr = PetscStrncmp(line, "$Elements", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); 294 if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); 295 ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr);; 296 snum = sscanf(line, "%d", &numCells); 297 if (snum != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); 298 /* Gmsh elements can be of any dimension/co-dimension, so we need to traverse the 299 file contents multiple times to figure out the true number of cells and facets 300 in the given mesh. To make this more efficient we read the file contents only 301 once and store them in memory, while determining the true number of cells. */ 302 ierr = DMPlexCreateGmsh_ReadElements(viewer, binary, byteSwap, shift, numCells, &gmsh_elem);CHKERRQ(ierr); 303 for (trueNumCells=0, c = 0; c < numCells; ++c) { 304 if (gmsh_elem[c].dim > dim) {dim = gmsh_elem[c].dim; trueNumCells = 0;} 305 if (gmsh_elem[c].dim == dim) trueNumCells++; 306 } 307 ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); 308 ierr = PetscStrncmp(line, "$EndElements", 12, &match);CHKERRQ(ierr); 309 if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); 310 311 /* OPTIONAL Read periodic section */ 312 if (periodic) { 313 PetscInt pVert, *periodicMapT, *aux; 314 int numPeriodic; 315 316 ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); 317 ierr = PetscStrncmp(line, "$Periodic", 9, &match);CHKERRQ(ierr); 318 if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); 319 ierr = PetscMalloc1(numVertices, &periodicMapT);CHKERRQ(ierr); 320 ierr = PetscBTCreate(numVertices, &periodicV);CHKERRQ(ierr); 321 for (i = 0; i < numVertices; i++) periodicMapT[i] = i; 322 ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); 323 snum = sscanf(line, "%d", &numPeriodic); 324 if (snum != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); 325 for (i = 0; i < numPeriodic; i++) { 326 int j, edim = -1, slaveTag = -1, masterTag = -1, nNodes; 327 328 ierr = PetscViewerRead(viewer, line, 3, NULL, PETSC_STRING);CHKERRQ(ierr); 329 snum = sscanf(line, "%d %d %d", &edim, &slaveTag, &masterTag); /* slaveTag and masterTag are unused */ 330 if (snum != 3) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); 331 /* Type of tranformation, discarded */ 332 ierr = PetscViewerRead(viewer, line, -PETSC_MAX_PATH_LEN, NULL, PETSC_STRING);CHKERRQ(ierr); 333 ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); 334 snum = sscanf(line, "%d", &nNodes); 335 if (snum != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); 336 for (j = 0; j < nNodes; j++) { 337 int slaveNode, masterNode; 338 339 ierr = PetscViewerRead(viewer, line, 2, NULL, PETSC_STRING);CHKERRQ(ierr); 340 snum = sscanf(line, "%d %d", &slaveNode, &masterNode); 341 if (snum != 2) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); 342 periodicMapT[slaveNode - shift] = masterNode - shift; 343 ierr = PetscBTSet(periodicV, slaveNode - shift);CHKERRQ(ierr); 344 ierr = PetscBTSet(periodicV, masterNode - shift);CHKERRQ(ierr); 345 } 346 } 347 ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); 348 ierr = PetscStrncmp(line, "$EndPeriodic", 12, &match);CHKERRQ(ierr); 349 if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); 350 /* we may have slaves of slaves */ 351 for (i = 0; i < numVertices; i++) { 352 while (periodicMapT[periodicMapT[i]] != periodicMapT[i]) { 353 periodicMapT[i] = periodicMapT[periodicMapT[i]]; 354 } 355 } 356 /* periodicMap : from old to new numbering (periodic vertices excluded) 357 periodicMapI: from new to old numbering */ 358 ierr = PetscMalloc1(numVertices, &periodicMap);CHKERRQ(ierr); 359 ierr = PetscMalloc1(numVertices, &periodicMapI);CHKERRQ(ierr); 360 ierr = PetscMalloc1(numVertices, &aux);CHKERRQ(ierr); 361 for (i = 0, pVert = 0; i < numVertices; i++) { 362 if (periodicMapT[i] != i) { 363 pVert++; 364 } else { 365 aux[i] = i - pVert; 366 periodicMapI[i - pVert] = i; 367 } 368 } 369 for (i = 0 ; i < numVertices; i++) { 370 periodicMap[i] = aux[periodicMapT[i]]; 371 } 372 ierr = PetscFree(periodicMapT);CHKERRQ(ierr); 373 ierr = PetscFree(aux);CHKERRQ(ierr); 374 /* remove periodic vertices */ 375 numVertices = numVertices - pVert; 376 } 377 } 378 379 /* For (binary) MPI I/O we read on all ranks, but only build the plex on rank 0 */ 380 if (mpiio && rank) { 381 numVertices = 0; numCells = 0; trueNumCells = 0; 382 ierr = PetscFree(periodicMap);CHKERRQ(ierr); 383 ierr = PetscFree(periodicMapI);CHKERRQ(ierr); 384 } 385 386 if (parentviewer) { 387 ierr = PetscViewerRestoreSubViewer(parentviewer, PETSC_COMM_SELF, &viewer);CHKERRQ(ierr); 388 } 389 390 /* Allocate the cell-vertex mesh */ 391 ierr = DMPlexSetChart(*dm, 0, trueNumCells+numVertices);CHKERRQ(ierr); 392 for (cell = 0, c = 0; c < numCells; ++c) { 393 if (gmsh_elem[c].dim == dim) { 394 ierr = DMPlexSetConeSize(*dm, cell, gmsh_elem[c].numNodes);CHKERRQ(ierr); 395 cell++; 396 } 397 } 398 ierr = DMSetUp(*dm);CHKERRQ(ierr); 399 /* Add cell-vertex connections */ 400 for (cell = 0, c = 0; c < numCells; ++c) { 401 if (gmsh_elem[c].dim == dim) { 402 PetscInt pcone[8], corner; 403 for (corner = 0; corner < gmsh_elem[c].numNodes; ++corner) { 404 const PetscInt cc = gmsh_elem[c].nodes[corner] - shift; 405 pcone[corner] = (periodicMap ? periodicMap[cc] : cc) + trueNumCells; 406 } 407 if (dim == 3) { 408 /* Tetrahedra are inverted */ 409 if (gmsh_elem[c].numNodes == 4) { 410 PetscInt tmp = pcone[0]; 411 pcone[0] = pcone[1]; 412 pcone[1] = tmp; 413 } 414 /* Hexahedra are inverted */ 415 if (gmsh_elem[c].numNodes == 8) { 416 PetscInt tmp = pcone[1]; 417 pcone[1] = pcone[3]; 418 pcone[3] = tmp; 419 } 420 } 421 ierr = DMPlexSetCone(*dm, cell, pcone);CHKERRQ(ierr); 422 cell++; 423 } 424 } 425 ierr = MPI_Bcast(&dim, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 426 ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); 427 ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr); 428 ierr = DMPlexStratify(*dm);CHKERRQ(ierr); 429 if (interpolate) { 430 DM idm = NULL; 431 432 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 433 ierr = DMDestroy(dm);CHKERRQ(ierr); 434 *dm = idm; 435 } 436 437 if (!rank && usemarker) { 438 PetscInt f, fStart, fEnd; 439 440 ierr = DMCreateLabel(*dm, "marker");CHKERRQ(ierr); 441 ierr = DMPlexGetHeightStratum(*dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 442 for (f = fStart; f < fEnd; ++f) { 443 PetscInt suppSize; 444 445 ierr = DMPlexGetSupportSize(*dm, f, &suppSize);CHKERRQ(ierr); 446 if (suppSize == 1) { 447 PetscInt *cone = NULL, coneSize, p; 448 449 ierr = DMPlexGetTransitiveClosure(*dm, f, PETSC_TRUE, &coneSize, &cone);CHKERRQ(ierr); 450 for (p = 0; p < coneSize; p += 2) { 451 ierr = DMSetLabelValue(*dm, "marker", cone[p], 1);CHKERRQ(ierr); 452 } 453 ierr = DMPlexRestoreTransitiveClosure(*dm, f, PETSC_TRUE, &coneSize, &cone);CHKERRQ(ierr); 454 } 455 } 456 } 457 458 if (!rank) { 459 PetscInt vStart, vEnd; 460 461 ierr = DMPlexGetDepthStratum(*dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 462 for (cell = 0, c = 0; c < numCells; ++c) { 463 464 /* Create face sets */ 465 if (gmsh_elem[c].dim == dim-1) { 466 const PetscInt *join; 467 PetscInt joinSize, pcone[8], corner; 468 /* Find the relevant facet with vertex joins */ 469 for (corner = 0; corner < gmsh_elem[c].numNodes; ++corner) { 470 const PetscInt cc = gmsh_elem[c].nodes[corner] - shift; 471 pcone[corner] = (periodicMap ? periodicMap[cc] : cc) + vStart; 472 } 473 ierr = DMPlexGetFullJoin(*dm, gmsh_elem[c].numNodes, pcone, &joinSize, &join);CHKERRQ(ierr); 474 if (joinSize != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not determine Plex facet for element %d", gmsh_elem[c].id); 475 ierr = DMSetLabelValue(*dm, "Face Sets", join[0], gmsh_elem[c].tags[0]);CHKERRQ(ierr); 476 ierr = DMPlexRestoreJoin(*dm, gmsh_elem[c].numNodes, (const PetscInt *) pcone, &joinSize, &join);CHKERRQ(ierr); 477 } 478 479 /* Create cell sets */ 480 if (gmsh_elem[c].dim == dim) { 481 if (gmsh_elem[c].numTags > 0) { 482 ierr = DMSetLabelValue(*dm, "Cell Sets", cell, gmsh_elem[c].tags[0]);CHKERRQ(ierr); 483 } 484 cell++; 485 } 486 487 /* Create vertex sets */ 488 if (gmsh_elem[c].dim == 0) { 489 if (gmsh_elem[c].numTags > 0) { 490 const PetscInt cc = gmsh_elem[c].nodes[0] - shift; 491 const PetscInt vid = (periodicMap ? periodicMap[cc] : cc) + vStart; 492 ierr = DMSetLabelValue(*dm, "Vertex Sets", vid, gmsh_elem[c].tags[0]);CHKERRQ(ierr); 493 } 494 } 495 } 496 } 497 498 /* Create coordinates */ 499 embedDim = isbd ? dim+1 : dim; 500 ierr = DMGetCoordinateSection(*dm, &coordSection);CHKERRQ(ierr); 501 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 502 ierr = PetscSectionSetFieldComponents(coordSection, 0, embedDim);CHKERRQ(ierr); 503 if (periodicMap) { /* we need to localize coordinates on cells */ 504 ierr = PetscSectionSetChart(coordSection, 0, trueNumCells + numVertices);CHKERRQ(ierr); 505 } else { 506 ierr = PetscSectionSetChart(coordSection, trueNumCells, trueNumCells + numVertices);CHKERRQ(ierr); 507 } 508 for (v = trueNumCells; v < trueNumCells+numVertices; ++v) { 509 ierr = PetscSectionSetDof(coordSection, v, embedDim);CHKERRQ(ierr); 510 ierr = PetscSectionSetFieldDof(coordSection, v, 0, embedDim);CHKERRQ(ierr); 511 } 512 if (periodicMap) { 513 ierr = PetscBTCreate(trueNumCells, &periodicC);CHKERRQ(ierr); 514 for (cell = 0, c = 0; c < numCells; ++c) { 515 if (gmsh_elem[c].dim == dim) { 516 PetscInt corner; 517 PetscBool pc = PETSC_FALSE; 518 for (corner = 0; corner < gmsh_elem[c].numNodes; ++corner) { 519 pc = (PetscBool)(pc || PetscBTLookup(periodicV, gmsh_elem[c].nodes[corner] - shift)); 520 } 521 if (pc) { 522 PetscInt dof = gmsh_elem[c].numNodes*embedDim; 523 ierr = PetscBTSet(periodicC, cell);CHKERRQ(ierr); 524 ierr = PetscSectionSetDof(coordSection, cell, dof);CHKERRQ(ierr); 525 ierr = PetscSectionSetFieldDof(coordSection, cell, 0, dof);CHKERRQ(ierr); 526 } 527 cell++; 528 } 529 } 530 } 531 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 532 ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 533 ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr); 534 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 535 ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 536 ierr = VecSetBlockSize(coordinates, embedDim);CHKERRQ(ierr); 537 ierr = VecSetType(coordinates, VECSTANDARD);CHKERRQ(ierr); 538 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 539 if (periodicMap) { 540 PetscInt off; 541 542 for (cell = 0, c = 0; c < numCells; ++c) { 543 PetscInt pcone[8], corner; 544 if (gmsh_elem[c].dim == dim) { 545 if (PetscUnlikely(PetscBTLookup(periodicC, cell))) { 546 for (corner = 0; corner < gmsh_elem[c].numNodes; ++corner) { 547 pcone[corner] = gmsh_elem[c].nodes[corner] - shift; 548 } 549 if (dim == 3) { 550 /* Tetrahedra are inverted */ 551 if (gmsh_elem[c].numNodes == 4) { 552 PetscInt tmp = pcone[0]; 553 pcone[0] = pcone[1]; 554 pcone[1] = tmp; 555 } 556 /* Hexahedra are inverted */ 557 if (gmsh_elem[c].numNodes == 8) { 558 PetscInt tmp = pcone[1]; 559 pcone[1] = pcone[3]; 560 pcone[3] = tmp; 561 } 562 } 563 ierr = PetscSectionGetOffset(coordSection, cell, &off);CHKERRQ(ierr); 564 for (corner = 0; corner < gmsh_elem[c].numNodes; ++corner) { 565 v = pcone[corner]; 566 for (d = 0; d < embedDim; ++d) { 567 coords[off++] = (PetscReal) coordsIn[v*3+d]; 568 } 569 } 570 } 571 cell++; 572 } 573 } 574 for (v = 0; v < numVertices; ++v) { 575 ierr = PetscSectionGetOffset(coordSection, v + trueNumCells, &off);CHKERRQ(ierr); 576 for (d = 0; d < embedDim; ++d) { 577 coords[off+d] = (PetscReal) coordsIn[periodicMapI[v]*3+d]; 578 } 579 } 580 } else { 581 for (v = 0; v < numVertices; ++v) { 582 for (d = 0; d < embedDim; ++d) { 583 coords[v*embedDim+d] = (PetscReal) coordsIn[v*3+d]; 584 } 585 } 586 } 587 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 588 ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr); 589 ierr = DMSetPeriodicity(*dm, periodic, NULL, NULL, NULL);CHKERRQ(ierr); 590 591 ierr = PetscFree(coordsIn);CHKERRQ(ierr); 592 ierr = PetscFree(gmsh_elem);CHKERRQ(ierr); 593 ierr = PetscFree(periodicMap);CHKERRQ(ierr); 594 ierr = PetscFree(periodicMapI);CHKERRQ(ierr); 595 ierr = PetscBTDestroy(&periodicV);CHKERRQ(ierr); 596 ierr = PetscBTDestroy(&periodicC);CHKERRQ(ierr); 597 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 598 599 ierr = PetscLogEventEnd(DMPLEX_CreateGmsh,*dm,0,0,0);CHKERRQ(ierr); 600 PetscFunctionReturn(0); 601 } 602