1 #define PETSCDM_DLL 2 #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 3 #include <petsc/private/hashmapi.h> 4 5 #include <../src/dm/impls/plex/gmshlex.h> 6 7 #define GMSH_LEXORDER_ITEM(T, p) \ 8 static int *GmshLexOrder_##T##_##p(void) \ 9 { \ 10 static int Gmsh_LexOrder_##T##_##p[GmshNumNodes_##T(p)] = {-1}; \ 11 int *lex = Gmsh_LexOrder_##T##_##p; \ 12 if (lex[0] == -1) (void)GmshLexOrder_##T(p, lex, 0); \ 13 return lex; \ 14 } 15 16 #define GMSH_LEXORDER_LIST(T) \ 17 GMSH_LEXORDER_ITEM(T, 1) \ 18 GMSH_LEXORDER_ITEM(T, 2) \ 19 GMSH_LEXORDER_ITEM(T, 3) \ 20 GMSH_LEXORDER_ITEM(T, 4) \ 21 GMSH_LEXORDER_ITEM(T, 5) \ 22 GMSH_LEXORDER_ITEM(T, 6) \ 23 GMSH_LEXORDER_ITEM(T, 7) \ 24 GMSH_LEXORDER_ITEM(T, 8) \ 25 GMSH_LEXORDER_ITEM(T, 9) \ 26 GMSH_LEXORDER_ITEM(T, 10) 27 28 GMSH_LEXORDER_ITEM(VTX, 0) 29 GMSH_LEXORDER_LIST(SEG) 30 GMSH_LEXORDER_LIST(TRI) 31 GMSH_LEXORDER_LIST(QUA) 32 GMSH_LEXORDER_LIST(TET) 33 GMSH_LEXORDER_LIST(HEX) 34 GMSH_LEXORDER_LIST(PRI) 35 GMSH_LEXORDER_LIST(PYR) 36 37 typedef enum { 38 GMSH_VTX = 0, 39 GMSH_SEG = 1, 40 GMSH_TRI = 2, 41 GMSH_QUA = 3, 42 GMSH_TET = 4, 43 GMSH_HEX = 5, 44 GMSH_PRI = 6, 45 GMSH_PYR = 7, 46 GMSH_NUM_POLYTOPES = 8 47 } GmshPolytopeType; 48 49 typedef struct { 50 int cellType; 51 int polytope; 52 int dim; 53 int order; 54 int numVerts; 55 int numNodes; 56 int* (*lexorder)(void); 57 } GmshCellInfo; 58 59 #define GmshCellEntry(cellType, polytope, dim, order) \ 60 {cellType, GMSH_##polytope, dim, order, \ 61 GmshNumNodes_##polytope(1), \ 62 GmshNumNodes_##polytope(order), \ 63 GmshLexOrder_##polytope##_##order} 64 65 static const GmshCellInfo GmshCellTable[] = { 66 GmshCellEntry( 15, VTX, 0, 0), 67 68 GmshCellEntry( 1, SEG, 1, 1), 69 GmshCellEntry( 8, SEG, 1, 2), 70 GmshCellEntry( 26, SEG, 1, 3), 71 GmshCellEntry( 27, SEG, 1, 4), 72 GmshCellEntry( 28, SEG, 1, 5), 73 GmshCellEntry( 62, SEG, 1, 6), 74 GmshCellEntry( 63, SEG, 1, 7), 75 GmshCellEntry( 64, SEG, 1, 8), 76 GmshCellEntry( 65, SEG, 1, 9), 77 GmshCellEntry( 66, SEG, 1, 10), 78 79 GmshCellEntry( 2, TRI, 2, 1), 80 GmshCellEntry( 9, TRI, 2, 2), 81 GmshCellEntry( 21, TRI, 2, 3), 82 GmshCellEntry( 23, TRI, 2, 4), 83 GmshCellEntry( 25, TRI, 2, 5), 84 GmshCellEntry( 42, TRI, 2, 6), 85 GmshCellEntry( 43, TRI, 2, 7), 86 GmshCellEntry( 44, TRI, 2, 8), 87 GmshCellEntry( 45, TRI, 2, 9), 88 GmshCellEntry( 46, TRI, 2, 10), 89 90 GmshCellEntry( 3, QUA, 2, 1), 91 GmshCellEntry( 10, QUA, 2, 2), 92 GmshCellEntry( 36, QUA, 2, 3), 93 GmshCellEntry( 37, QUA, 2, 4), 94 GmshCellEntry( 38, QUA, 2, 5), 95 GmshCellEntry( 47, QUA, 2, 6), 96 GmshCellEntry( 48, QUA, 2, 7), 97 GmshCellEntry( 49, QUA, 2, 8), 98 GmshCellEntry( 50, QUA, 2, 9), 99 GmshCellEntry( 51, QUA, 2, 10), 100 101 GmshCellEntry( 4, TET, 3, 1), 102 GmshCellEntry( 11, TET, 3, 2), 103 GmshCellEntry( 29, TET, 3, 3), 104 GmshCellEntry( 30, TET, 3, 4), 105 GmshCellEntry( 31, TET, 3, 5), 106 GmshCellEntry( 71, TET, 3, 6), 107 GmshCellEntry( 72, TET, 3, 7), 108 GmshCellEntry( 73, TET, 3, 8), 109 GmshCellEntry( 74, TET, 3, 9), 110 GmshCellEntry( 75, TET, 3, 10), 111 112 GmshCellEntry( 5, HEX, 3, 1), 113 GmshCellEntry( 12, HEX, 3, 2), 114 GmshCellEntry( 92, HEX, 3, 3), 115 GmshCellEntry( 93, HEX, 3, 4), 116 GmshCellEntry( 94, HEX, 3, 5), 117 GmshCellEntry( 95, HEX, 3, 6), 118 GmshCellEntry( 96, HEX, 3, 7), 119 GmshCellEntry( 97, HEX, 3, 8), 120 GmshCellEntry( 98, HEX, 3, 9), 121 GmshCellEntry( -1, HEX, 3, 10), 122 123 GmshCellEntry( 6, PRI, 3, 1), 124 GmshCellEntry( 13, PRI, 3, 2), 125 GmshCellEntry( 90, PRI, 3, 3), 126 GmshCellEntry( 91, PRI, 3, 4), 127 GmshCellEntry(106, PRI, 3, 5), 128 GmshCellEntry(107, PRI, 3, 6), 129 GmshCellEntry(108, PRI, 3, 7), 130 GmshCellEntry(109, PRI, 3, 8), 131 GmshCellEntry(110, PRI, 3, 9), 132 GmshCellEntry( -1, PRI, 3, 10), 133 134 GmshCellEntry( 7, PYR, 3, 1), 135 GmshCellEntry( 14, PYR, 3, 2), 136 GmshCellEntry(118, PYR, 3, 3), 137 GmshCellEntry(119, PYR, 3, 4), 138 GmshCellEntry(120, PYR, 3, 5), 139 GmshCellEntry(121, PYR, 3, 6), 140 GmshCellEntry(122, PYR, 3, 7), 141 GmshCellEntry(123, PYR, 3, 8), 142 GmshCellEntry(124, PYR, 3, 9), 143 GmshCellEntry( -1, PYR, 3, 10) 144 145 #if 0 146 {20, GMSH_TRI, 2, 3, 3, 9, NULL}, 147 {16, GMSH_QUA, 2, 2, 4, 8, NULL}, 148 {17, GMSH_HEX, 3, 2, 8, 20, NULL}, 149 {18, GMSH_PRI, 3, 2, 6, 15, NULL}, 150 {19, GMSH_PYR, 3, 2, 5, 13, NULL}, 151 #endif 152 }; 153 154 static GmshCellInfo GmshCellMap[150]; 155 156 static PetscErrorCode GmshCellInfoSetUp(void) 157 { 158 size_t i, n; 159 static PetscBool called = PETSC_FALSE; 160 161 if (called) return 0; 162 PetscFunctionBegin; 163 called = PETSC_TRUE; 164 n = sizeof(GmshCellMap)/sizeof(GmshCellMap[0]); 165 for (i = 0; i < n; ++i) { 166 GmshCellMap[i].cellType = -1; 167 GmshCellMap[i].polytope = -1; 168 } 169 n = sizeof(GmshCellTable)/sizeof(GmshCellTable[0]); 170 for (i = 0; i < n; ++i) { 171 if (GmshCellTable[i].cellType <= 0) continue; 172 GmshCellMap[GmshCellTable[i].cellType] = GmshCellTable[i]; 173 } 174 PetscFunctionReturn(0); 175 } 176 177 #define GmshCellTypeCheck(ct) 0; do { \ 178 const int _ct_ = (int)ct; \ 179 if (_ct_ < 0 || _ct_ >= (int)(sizeof(GmshCellMap)/sizeof(GmshCellMap[0]))) \ 180 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid Gmsh element type %d", _ct_); \ 181 if (GmshCellMap[_ct_].cellType != _ct_) \ 182 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported Gmsh element type %d", _ct_); \ 183 if (GmshCellMap[_ct_].polytope == -1) \ 184 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported Gmsh element type %d", _ct_); \ 185 } while (0) 186 187 typedef struct { 188 PetscViewer viewer; 189 int fileFormat; 190 int dataSize; 191 PetscBool binary; 192 PetscBool byteSwap; 193 size_t wlen; 194 void *wbuf; 195 size_t slen; 196 void *sbuf; 197 PetscInt *nbuf; 198 PetscInt nodeStart; 199 PetscInt nodeEnd; 200 PetscInt *nodeMap; 201 } GmshFile; 202 203 static PetscErrorCode GmshBufferGet(GmshFile *gmsh, size_t count, size_t eltsize, void *buf) 204 { 205 size_t size = count * eltsize; 206 PetscErrorCode ierr; 207 208 PetscFunctionBegin; 209 if (gmsh->wlen < size) { 210 ierr = PetscFree(gmsh->wbuf);CHKERRQ(ierr); 211 ierr = PetscMalloc(size, &gmsh->wbuf);CHKERRQ(ierr); 212 gmsh->wlen = size; 213 } 214 *(void**)buf = size ? gmsh->wbuf : NULL; 215 PetscFunctionReturn(0); 216 } 217 218 static PetscErrorCode GmshBufferSizeGet(GmshFile *gmsh, size_t count, void *buf) 219 { 220 size_t dataSize = (size_t)gmsh->dataSize; 221 size_t size = count * dataSize; 222 PetscErrorCode ierr; 223 224 PetscFunctionBegin; 225 if (gmsh->slen < size) { 226 ierr = PetscFree(gmsh->sbuf);CHKERRQ(ierr); 227 ierr = PetscMalloc(size, &gmsh->sbuf);CHKERRQ(ierr); 228 gmsh->slen = size; 229 } 230 *(void**)buf = size ? gmsh->sbuf : NULL; 231 PetscFunctionReturn(0); 232 } 233 234 static PetscErrorCode GmshRead(GmshFile *gmsh, void *buf, PetscInt count, PetscDataType dtype) 235 { 236 PetscErrorCode ierr; 237 PetscFunctionBegin; 238 ierr = PetscViewerRead(gmsh->viewer, buf, count, NULL, dtype);CHKERRQ(ierr); 239 if (gmsh->byteSwap) {ierr = PetscByteSwap(buf, dtype, count);CHKERRQ(ierr);} 240 PetscFunctionReturn(0); 241 } 242 243 static PetscErrorCode GmshReadString(GmshFile *gmsh, char *buf, PetscInt count) 244 { 245 PetscErrorCode ierr; 246 PetscFunctionBegin; 247 ierr = PetscViewerRead(gmsh->viewer, buf, count, NULL, PETSC_STRING);CHKERRQ(ierr); 248 PetscFunctionReturn(0); 249 } 250 251 static PetscErrorCode GmshMatch(PETSC_UNUSED GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN], PetscBool *match) 252 { 253 PetscErrorCode ierr; 254 PetscFunctionBegin; 255 ierr = PetscStrcmp(line, Section, match);CHKERRQ(ierr); 256 PetscFunctionReturn(0); 257 } 258 259 static PetscErrorCode GmshExpect(GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN]) 260 { 261 PetscBool match; 262 PetscErrorCode ierr; 263 264 PetscFunctionBegin; 265 ierr = GmshMatch(gmsh, Section, line, &match);CHKERRQ(ierr); 266 if (!match) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file, expecting %s",Section); 267 PetscFunctionReturn(0); 268 } 269 270 static PetscErrorCode GmshReadSection(GmshFile *gmsh, char line[PETSC_MAX_PATH_LEN]) 271 { 272 PetscBool match; 273 PetscErrorCode ierr; 274 275 PetscFunctionBegin; 276 while (PETSC_TRUE) { 277 ierr = GmshReadString(gmsh, line, 1);CHKERRQ(ierr); 278 ierr = GmshMatch(gmsh, "$Comments", line, &match);CHKERRQ(ierr); 279 if (!match) break; 280 while (PETSC_TRUE) { 281 ierr = GmshReadString(gmsh, line, 1);CHKERRQ(ierr); 282 ierr = GmshMatch(gmsh, "$EndComments", line, &match);CHKERRQ(ierr); 283 if (match) break; 284 } 285 } 286 PetscFunctionReturn(0); 287 } 288 289 static PetscErrorCode GmshReadEndSection(GmshFile *gmsh, const char EndSection[], char line[PETSC_MAX_PATH_LEN]) 290 { 291 PetscErrorCode ierr; 292 PetscFunctionBegin; 293 ierr = GmshReadString(gmsh, line, 1);CHKERRQ(ierr); 294 ierr = GmshExpect(gmsh, EndSection, line);CHKERRQ(ierr); 295 PetscFunctionReturn(0); 296 } 297 298 static PetscErrorCode GmshReadSize(GmshFile *gmsh, PetscInt *buf, PetscInt count) 299 { 300 PetscInt i; 301 size_t dataSize = (size_t)gmsh->dataSize; 302 PetscErrorCode ierr; 303 304 PetscFunctionBegin; 305 if (dataSize == sizeof(PetscInt)) { 306 ierr = GmshRead(gmsh, buf, count, PETSC_INT);CHKERRQ(ierr); 307 } else if (dataSize == sizeof(int)) { 308 int *ibuf = NULL; 309 ierr = GmshBufferSizeGet(gmsh, count, &ibuf);CHKERRQ(ierr); 310 ierr = GmshRead(gmsh, ibuf, count, PETSC_ENUM);CHKERRQ(ierr); 311 for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 312 } else if (dataSize == sizeof(long)) { 313 long *ibuf = NULL; 314 ierr = GmshBufferSizeGet(gmsh, count, &ibuf);CHKERRQ(ierr); 315 ierr = GmshRead(gmsh, ibuf, count, PETSC_LONG);CHKERRQ(ierr); 316 for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 317 } else if (dataSize == sizeof(PetscInt64)) { 318 PetscInt64 *ibuf = NULL; 319 ierr = GmshBufferSizeGet(gmsh, count, &ibuf);CHKERRQ(ierr); 320 ierr = GmshRead(gmsh, ibuf, count, PETSC_INT64);CHKERRQ(ierr); 321 for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 322 } 323 PetscFunctionReturn(0); 324 } 325 326 static PetscErrorCode GmshReadInt(GmshFile *gmsh, int *buf, PetscInt count) 327 { 328 PetscErrorCode ierr; 329 PetscFunctionBegin; 330 ierr = GmshRead(gmsh, buf, count, PETSC_ENUM);CHKERRQ(ierr); 331 PetscFunctionReturn(0); 332 } 333 334 static PetscErrorCode GmshReadDouble(GmshFile *gmsh, double *buf, PetscInt count) 335 { 336 PetscErrorCode ierr; 337 PetscFunctionBegin; 338 ierr = GmshRead(gmsh, buf, count, PETSC_DOUBLE);CHKERRQ(ierr); 339 PetscFunctionReturn(0); 340 } 341 342 typedef struct { 343 PetscInt id; /* Entity ID */ 344 PetscInt dim; /* Dimension */ 345 double bbox[6]; /* Bounding box */ 346 PetscInt numTags; /* Size of tag array */ 347 int tags[4]; /* Tag array */ 348 } GmshEntity; 349 350 typedef struct { 351 GmshEntity *entity[4]; 352 PetscHMapI entityMap[4]; 353 } GmshEntities; 354 355 static PetscErrorCode GmshEntitiesCreate(PetscInt count[4], GmshEntities **entities) 356 { 357 PetscInt dim; 358 PetscErrorCode ierr; 359 360 PetscFunctionBegin; 361 ierr = PetscNew(entities);CHKERRQ(ierr); 362 for (dim = 0; dim < 4; ++dim) { 363 ierr = PetscCalloc1(count[dim], &(*entities)->entity[dim]);CHKERRQ(ierr); 364 ierr = PetscHMapICreate(&(*entities)->entityMap[dim]);CHKERRQ(ierr); 365 } 366 PetscFunctionReturn(0); 367 } 368 369 static PetscErrorCode GmshEntitiesDestroy(GmshEntities **entities) 370 { 371 PetscInt dim; 372 PetscErrorCode ierr; 373 374 PetscFunctionBegin; 375 if (!*entities) PetscFunctionReturn(0); 376 for (dim = 0; dim < 4; ++dim) { 377 ierr = PetscFree((*entities)->entity[dim]);CHKERRQ(ierr); 378 ierr = PetscHMapIDestroy(&(*entities)->entityMap[dim]);CHKERRQ(ierr); 379 } 380 ierr = PetscFree((*entities));CHKERRQ(ierr); 381 PetscFunctionReturn(0); 382 } 383 384 static PetscErrorCode GmshEntitiesAdd(GmshEntities *entities, PetscInt index, PetscInt dim, PetscInt eid, GmshEntity** entity) 385 { 386 PetscErrorCode ierr; 387 388 PetscFunctionBegin; 389 ierr = PetscHMapISet(entities->entityMap[dim], eid, index);CHKERRQ(ierr); 390 entities->entity[dim][index].dim = dim; 391 entities->entity[dim][index].id = eid; 392 if (entity) *entity = &entities->entity[dim][index]; 393 PetscFunctionReturn(0); 394 } 395 396 static PetscErrorCode GmshEntitiesGet(GmshEntities *entities, PetscInt dim, PetscInt eid, GmshEntity** entity) 397 { 398 PetscInt index; 399 PetscErrorCode ierr; 400 401 PetscFunctionBegin; 402 ierr = PetscHMapIGet(entities->entityMap[dim], eid, &index);CHKERRQ(ierr); 403 *entity = &entities->entity[dim][index]; 404 PetscFunctionReturn(0); 405 } 406 407 typedef struct { 408 PetscInt *id; /* Node IDs */ 409 double *xyz; /* Coordinates */ 410 } GmshNodes; 411 412 static PetscErrorCode GmshNodesCreate(PetscInt count, GmshNodes **nodes) 413 { 414 PetscErrorCode ierr; 415 416 PetscFunctionBegin; 417 ierr = PetscNew(nodes);CHKERRQ(ierr); 418 ierr = PetscMalloc1(count*1, &(*nodes)->id);CHKERRQ(ierr); 419 ierr = PetscMalloc1(count*3, &(*nodes)->xyz);CHKERRQ(ierr); 420 PetscFunctionReturn(0); 421 } 422 423 static PetscErrorCode GmshNodesDestroy(GmshNodes **nodes) 424 { 425 PetscErrorCode ierr; 426 PetscFunctionBegin; 427 if (!*nodes) PetscFunctionReturn(0); 428 ierr = PetscFree((*nodes)->id);CHKERRQ(ierr); 429 ierr = PetscFree((*nodes)->xyz);CHKERRQ(ierr); 430 ierr = PetscFree((*nodes));CHKERRQ(ierr); 431 PetscFunctionReturn(0); 432 } 433 434 typedef struct { 435 PetscInt id; /* Element ID */ 436 PetscInt dim; /* Dimension */ 437 PetscInt cellType; /* Cell type */ 438 PetscInt numVerts; /* Size of vertex array */ 439 PetscInt numNodes; /* Size of node array */ 440 PetscInt *nodes; /* Vertex/Node array */ 441 PetscInt numTags; /* Size of tag array */ 442 int tags[4]; /* Tag array */ 443 } GmshElement; 444 445 static PetscErrorCode GmshElementsCreate(PetscInt count, GmshElement **elements) 446 { 447 PetscErrorCode ierr; 448 449 PetscFunctionBegin; 450 ierr = PetscCalloc1(count, elements);CHKERRQ(ierr); 451 PetscFunctionReturn(0); 452 } 453 454 static PetscErrorCode GmshElementsDestroy(GmshElement **elements) 455 { 456 PetscErrorCode ierr; 457 458 PetscFunctionBegin; 459 if (!*elements) PetscFunctionReturn(0); 460 ierr = PetscFree(*elements);CHKERRQ(ierr); 461 PetscFunctionReturn(0); 462 } 463 464 typedef struct { 465 PetscInt dim; 466 PetscInt order; 467 GmshEntities *entities; 468 PetscInt numNodes; 469 GmshNodes *nodelist; 470 PetscInt numElems; 471 GmshElement *elements; 472 PetscInt numVerts; 473 PetscInt numCells; 474 PetscInt *periodMap; 475 PetscInt *vertexMap; 476 PetscSegBuffer segbuf; 477 } GmshMesh; 478 479 static PetscErrorCode GmshMeshCreate(GmshMesh **mesh) 480 { 481 PetscErrorCode ierr; 482 483 PetscFunctionBegin; 484 ierr = PetscNew(mesh);CHKERRQ(ierr); 485 ierr = PetscSegBufferCreate(sizeof(PetscInt), 0, &(*mesh)->segbuf);CHKERRQ(ierr); 486 PetscFunctionReturn(0); 487 } 488 489 static PetscErrorCode GmshMeshDestroy(GmshMesh **mesh) 490 { 491 PetscErrorCode ierr; 492 493 PetscFunctionBegin; 494 if (!*mesh) PetscFunctionReturn(0); 495 ierr = GmshEntitiesDestroy(&(*mesh)->entities);CHKERRQ(ierr); 496 ierr = GmshNodesDestroy(&(*mesh)->nodelist);CHKERRQ(ierr); 497 ierr = GmshElementsDestroy(&(*mesh)->elements);CHKERRQ(ierr); 498 ierr = PetscFree((*mesh)->periodMap);CHKERRQ(ierr); 499 ierr = PetscFree((*mesh)->vertexMap);CHKERRQ(ierr); 500 ierr = PetscSegBufferDestroy(&(*mesh)->segbuf);CHKERRQ(ierr); 501 ierr = PetscFree((*mesh));CHKERRQ(ierr); 502 PetscFunctionReturn(0); 503 } 504 505 static PetscErrorCode GmshReadNodes_v22(GmshFile *gmsh, GmshMesh *mesh) 506 { 507 PetscViewer viewer = gmsh->viewer; 508 PetscBool byteSwap = gmsh->byteSwap; 509 char line[PETSC_MAX_PATH_LEN]; 510 int n, num, nid, snum; 511 GmshNodes *nodes; 512 PetscErrorCode ierr; 513 514 PetscFunctionBegin; 515 ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); 516 snum = sscanf(line, "%d", &num); 517 if (snum != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 518 ierr = GmshNodesCreate(num, &nodes);CHKERRQ(ierr); 519 mesh->numNodes = num; 520 mesh->nodelist = nodes; 521 for (n = 0; n < num; ++n) { 522 double *xyz = nodes->xyz + n*3; 523 ierr = PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM);CHKERRQ(ierr); 524 ierr = PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE);CHKERRQ(ierr); 525 if (byteSwap) {ierr = PetscByteSwap(&nid, PETSC_ENUM, 1);CHKERRQ(ierr);} 526 if (byteSwap) {ierr = PetscByteSwap(xyz, PETSC_DOUBLE, 3);CHKERRQ(ierr);} 527 nodes->id[n] = nid; 528 } 529 PetscFunctionReturn(0); 530 } 531 532 /* Gmsh elements can be of any dimension/co-dimension, so we need to traverse the 533 file contents multiple times to figure out the true number of cells and facets 534 in the given mesh. To make this more efficient we read the file contents only 535 once and store them in memory, while determining the true number of cells. */ 536 static PetscErrorCode GmshReadElements_v22(GmshFile* gmsh, GmshMesh *mesh) 537 { 538 PetscViewer viewer = gmsh->viewer; 539 PetscBool binary = gmsh->binary; 540 PetscBool byteSwap = gmsh->byteSwap; 541 char line[PETSC_MAX_PATH_LEN]; 542 int i, c, p, num, ibuf[1+4+1000], snum; 543 int cellType, numElem, numVerts, numNodes, numTags; 544 GmshElement *elements; 545 PetscInt *nodeMap = gmsh->nodeMap; 546 PetscErrorCode ierr; 547 548 PetscFunctionBegin; 549 ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); 550 snum = sscanf(line, "%d", &num); 551 if (snum != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 552 ierr = GmshElementsCreate(num, &elements);CHKERRQ(ierr); 553 mesh->numElems = num; 554 mesh->elements = elements; 555 for (c = 0; c < num;) { 556 ierr = PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM);CHKERRQ(ierr); 557 if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, 3);CHKERRQ(ierr);} 558 559 cellType = binary ? ibuf[0] : ibuf[1]; 560 numElem = binary ? ibuf[1] : 1; 561 numTags = ibuf[2]; 562 563 ierr = GmshCellTypeCheck(cellType);CHKERRQ(ierr); 564 numVerts = GmshCellMap[cellType].numVerts; 565 numNodes = GmshCellMap[cellType].numNodes; 566 567 for (i = 0; i < numElem; ++i, ++c) { 568 GmshElement *element = elements + c; 569 const int off = binary ? 0 : 1, nint = 1 + numTags + numNodes - off; 570 const int *id = ibuf, *nodes = ibuf + 1 + numTags, *tags = ibuf + 1; 571 ierr = PetscViewerRead(viewer, ibuf+off, nint, NULL, PETSC_ENUM);CHKERRQ(ierr); 572 if (byteSwap) {ierr = PetscByteSwap(ibuf+off, PETSC_ENUM, nint);CHKERRQ(ierr);} 573 element->id = id[0]; 574 element->dim = GmshCellMap[cellType].dim; 575 element->cellType = cellType; 576 element->numVerts = numVerts; 577 element->numNodes = numNodes; 578 element->numTags = PetscMin(numTags, 4); 579 ierr = PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes);CHKERRQ(ierr); 580 for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 581 for (p = 0; p < element->numTags; p++) element->tags[p] = tags[p]; 582 } 583 } 584 PetscFunctionReturn(0); 585 } 586 587 /* 588 $Entities 589 numPoints(unsigned long) numCurves(unsigned long) 590 numSurfaces(unsigned long) numVolumes(unsigned long) 591 // points 592 tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 593 boxMaxX(double) boxMaxY(double) boxMaxZ(double) 594 numPhysicals(unsigned long) phyisicalTag[...](int) 595 ... 596 // curves 597 tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 598 boxMaxX(double) boxMaxY(double) boxMaxZ(double) 599 numPhysicals(unsigned long) physicalTag[...](int) 600 numBREPVert(unsigned long) tagBREPVert[...](int) 601 ... 602 // surfaces 603 tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 604 boxMaxX(double) boxMaxY(double) boxMaxZ(double) 605 numPhysicals(unsigned long) physicalTag[...](int) 606 numBREPCurve(unsigned long) tagBREPCurve[...](int) 607 ... 608 // volumes 609 tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 610 boxMaxX(double) boxMaxY(double) boxMaxZ(double) 611 numPhysicals(unsigned long) physicalTag[...](int) 612 numBREPSurfaces(unsigned long) tagBREPSurfaces[...](int) 613 ... 614 $EndEntities 615 */ 616 static PetscErrorCode GmshReadEntities_v40(GmshFile *gmsh, GmshMesh *mesh) 617 { 618 PetscViewer viewer = gmsh->viewer; 619 PetscBool byteSwap = gmsh->byteSwap; 620 long index, num, lbuf[4]; 621 int dim, eid, numTags, *ibuf, t; 622 PetscInt count[4], i; 623 GmshEntity *entity = NULL; 624 PetscErrorCode ierr; 625 626 PetscFunctionBegin; 627 ierr = PetscViewerRead(viewer, lbuf, 4, NULL, PETSC_LONG);CHKERRQ(ierr); 628 if (byteSwap) {ierr = PetscByteSwap(lbuf, PETSC_LONG, 4);CHKERRQ(ierr);} 629 for (i = 0; i < 4; ++i) count[i] = lbuf[i]; 630 ierr = GmshEntitiesCreate(count, &mesh->entities);CHKERRQ(ierr); 631 for (dim = 0; dim < 4; ++dim) { 632 for (index = 0; index < count[dim]; ++index) { 633 ierr = PetscViewerRead(viewer, &eid, 1, NULL, PETSC_ENUM);CHKERRQ(ierr); 634 if (byteSwap) {ierr = PetscByteSwap(&eid, PETSC_ENUM, 1);CHKERRQ(ierr);} 635 ierr = GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity);CHKERRQ(ierr); 636 ierr = PetscViewerRead(viewer, entity->bbox, 6, NULL, PETSC_DOUBLE);CHKERRQ(ierr); 637 if (byteSwap) {ierr = PetscByteSwap(entity->bbox, PETSC_DOUBLE, 6);CHKERRQ(ierr);} 638 ierr = PetscViewerRead(viewer, &num, 1, NULL, PETSC_LONG);CHKERRQ(ierr); 639 if (byteSwap) {ierr = PetscByteSwap(&num, PETSC_LONG, 1);CHKERRQ(ierr);} 640 ierr = GmshBufferGet(gmsh, num, sizeof(int), &ibuf);CHKERRQ(ierr); 641 ierr = PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM);CHKERRQ(ierr); 642 if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, num);CHKERRQ(ierr);} 643 entity->numTags = numTags = (int) PetscMin(num, 4); 644 for (t = 0; t < numTags; ++t) entity->tags[t] = ibuf[t]; 645 if (dim == 0) continue; 646 ierr = PetscViewerRead(viewer, &num, 1, NULL, PETSC_LONG);CHKERRQ(ierr); 647 if (byteSwap) {ierr = PetscByteSwap(&num, PETSC_LONG, 1);CHKERRQ(ierr);} 648 ierr = GmshBufferGet(gmsh, num, sizeof(int), &ibuf);CHKERRQ(ierr); 649 ierr = PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM);CHKERRQ(ierr); 650 if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, num);CHKERRQ(ierr);} 651 } 652 } 653 PetscFunctionReturn(0); 654 } 655 656 /* 657 $Nodes 658 numEntityBlocks(unsigned long) numNodes(unsigned long) 659 tagEntity(int) dimEntity(int) typeNode(int) numNodes(unsigned long) 660 tag(int) x(double) y(double) z(double) 661 ... 662 ... 663 $EndNodes 664 */ 665 static PetscErrorCode GmshReadNodes_v40(GmshFile *gmsh, GmshMesh *mesh) 666 { 667 PetscViewer viewer = gmsh->viewer; 668 PetscBool byteSwap = gmsh->byteSwap; 669 long block, node, n, numEntityBlocks, numTotalNodes, numNodes; 670 int info[3], nid; 671 GmshNodes *nodes; 672 PetscErrorCode ierr; 673 674 PetscFunctionBegin; 675 ierr = PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG);CHKERRQ(ierr); 676 if (byteSwap) {ierr = PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1);CHKERRQ(ierr);} 677 ierr = PetscViewerRead(viewer, &numTotalNodes, 1, NULL, PETSC_LONG);CHKERRQ(ierr); 678 if (byteSwap) {ierr = PetscByteSwap(&numTotalNodes, PETSC_LONG, 1);CHKERRQ(ierr);} 679 ierr = GmshNodesCreate(numTotalNodes, &nodes);CHKERRQ(ierr); 680 mesh->numNodes = numTotalNodes; 681 mesh->nodelist = nodes; 682 for (n = 0, block = 0; block < numEntityBlocks; ++block) { 683 ierr = PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM);CHKERRQ(ierr); 684 ierr = PetscViewerRead(viewer, &numNodes, 1, NULL, PETSC_LONG);CHKERRQ(ierr); 685 if (byteSwap) {ierr = PetscByteSwap(&numNodes, PETSC_LONG, 1);CHKERRQ(ierr);} 686 if (gmsh->binary) { 687 size_t nbytes = sizeof(int) + 3*sizeof(double); 688 char *cbuf = NULL; /* dummy value to prevent warning from compiler about possible unitilized value */ 689 ierr = GmshBufferGet(gmsh, numNodes, nbytes, &cbuf);CHKERRQ(ierr); 690 ierr = PetscViewerRead(viewer, cbuf, numNodes*nbytes, NULL, PETSC_CHAR);CHKERRQ(ierr); 691 for (node = 0; node < numNodes; ++node, ++n) { 692 char *cnid = cbuf + node*nbytes, *cxyz = cnid + sizeof(int); 693 double *xyz = nodes->xyz + n*3; 694 if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(cnid, PETSC_ENUM, 1);CHKERRQ(ierr);} 695 if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(cxyz, PETSC_DOUBLE, 3);CHKERRQ(ierr);} 696 ierr = PetscMemcpy(&nid, cnid, sizeof(int));CHKERRQ(ierr); 697 ierr = PetscMemcpy(xyz, cxyz, 3*sizeof(double));CHKERRQ(ierr); 698 if (byteSwap) {ierr = PetscByteSwap(&nid, PETSC_ENUM, 1);CHKERRQ(ierr);} 699 if (byteSwap) {ierr = PetscByteSwap(xyz, PETSC_DOUBLE, 3);CHKERRQ(ierr);} 700 nodes->id[n] = nid; 701 } 702 } else { 703 for (node = 0; node < numNodes; ++node, ++n) { 704 double *xyz = nodes->xyz + n*3; 705 ierr = PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM);CHKERRQ(ierr); 706 ierr = PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE);CHKERRQ(ierr); 707 if (byteSwap) {ierr = PetscByteSwap(&nid, PETSC_ENUM, 1);CHKERRQ(ierr);} 708 if (byteSwap) {ierr = PetscByteSwap(xyz, PETSC_DOUBLE, 3);CHKERRQ(ierr);} 709 nodes->id[n] = nid; 710 } 711 } 712 } 713 PetscFunctionReturn(0); 714 } 715 716 /* 717 $Elements 718 numEntityBlocks(unsigned long) numElements(unsigned long) 719 tagEntity(int) dimEntity(int) typeEle(int) numElements(unsigned long) 720 tag(int) numVert[...](int) 721 ... 722 ... 723 $EndElements 724 */ 725 static PetscErrorCode GmshReadElements_v40(GmshFile *gmsh, GmshMesh *mesh) 726 { 727 PetscViewer viewer = gmsh->viewer; 728 PetscBool byteSwap = gmsh->byteSwap; 729 long c, block, numEntityBlocks, numTotalElements, elem, numElements; 730 int p, info[3], *ibuf = NULL; 731 int eid, dim, cellType, numVerts, numNodes, numTags; 732 GmshEntity *entity = NULL; 733 GmshElement *elements; 734 PetscInt *nodeMap = gmsh->nodeMap; 735 PetscErrorCode ierr; 736 737 PetscFunctionBegin; 738 ierr = PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG);CHKERRQ(ierr); 739 if (byteSwap) {ierr = PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1);CHKERRQ(ierr);} 740 ierr = PetscViewerRead(viewer, &numTotalElements, 1, NULL, PETSC_LONG);CHKERRQ(ierr); 741 if (byteSwap) {ierr = PetscByteSwap(&numTotalElements, PETSC_LONG, 1);CHKERRQ(ierr);} 742 ierr = GmshElementsCreate(numTotalElements, &elements);CHKERRQ(ierr); 743 mesh->numElems = numTotalElements; 744 mesh->elements = elements; 745 for (c = 0, block = 0; block < numEntityBlocks; ++block) { 746 ierr = PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM);CHKERRQ(ierr); 747 if (byteSwap) {ierr = PetscByteSwap(info, PETSC_ENUM, 3);CHKERRQ(ierr);} 748 eid = info[0]; dim = info[1]; cellType = info[2]; 749 ierr = GmshEntitiesGet(mesh->entities, dim, eid, &entity);CHKERRQ(ierr); 750 ierr = GmshCellTypeCheck(cellType);CHKERRQ(ierr); 751 numVerts = GmshCellMap[cellType].numVerts; 752 numNodes = GmshCellMap[cellType].numNodes; 753 numTags = entity->numTags; 754 ierr = PetscViewerRead(viewer, &numElements, 1, NULL, PETSC_LONG);CHKERRQ(ierr); 755 if (byteSwap) {ierr = PetscByteSwap(&numElements, PETSC_LONG, 1);CHKERRQ(ierr);} 756 ierr = GmshBufferGet(gmsh, (1+numNodes)*numElements, sizeof(int), &ibuf);CHKERRQ(ierr); 757 ierr = PetscViewerRead(viewer, ibuf, (1+numNodes)*numElements, NULL, PETSC_ENUM);CHKERRQ(ierr); 758 if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, (1+numNodes)*numElements);CHKERRQ(ierr);} 759 for (elem = 0; elem < numElements; ++elem, ++c) { 760 GmshElement *element = elements + c; 761 const int *id = ibuf + elem*(1+numNodes), *nodes = id + 1; 762 element->id = id[0]; 763 element->dim = dim; 764 element->cellType = cellType; 765 element->numVerts = numVerts; 766 element->numNodes = numNodes; 767 element->numTags = numTags; 768 ierr = PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes);CHKERRQ(ierr); 769 for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 770 for (p = 0; p < element->numTags; p++) element->tags[p] = entity->tags[p]; 771 } 772 } 773 PetscFunctionReturn(0); 774 } 775 776 static PetscErrorCode GmshReadPeriodic_v40(GmshFile *gmsh, PetscInt periodicMap[]) 777 { 778 PetscViewer viewer = gmsh->viewer; 779 int fileFormat = gmsh->fileFormat; 780 PetscBool binary = gmsh->binary; 781 PetscBool byteSwap = gmsh->byteSwap; 782 int numPeriodic, snum, i; 783 char line[PETSC_MAX_PATH_LEN]; 784 PetscInt *nodeMap = gmsh->nodeMap; 785 PetscErrorCode ierr; 786 787 PetscFunctionBegin; 788 if (fileFormat == 22 || !binary) { 789 ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); 790 snum = sscanf(line, "%d", &numPeriodic); 791 if (snum != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 792 } else { 793 ierr = PetscViewerRead(viewer, &numPeriodic, 1, NULL, PETSC_ENUM);CHKERRQ(ierr); 794 if (byteSwap) {ierr = PetscByteSwap(&numPeriodic, PETSC_ENUM, 1);CHKERRQ(ierr);} 795 } 796 for (i = 0; i < numPeriodic; i++) { 797 int ibuf[3], correspondingDim = -1, correspondingTag = -1, primaryTag = -1, correspondingNode, primaryNode; 798 long j, nNodes; 799 double affine[16]; 800 801 if (fileFormat == 22 || !binary) { 802 ierr = PetscViewerRead(viewer, line, 3, NULL, PETSC_STRING);CHKERRQ(ierr); 803 snum = sscanf(line, "%d %d %d", &correspondingDim, &correspondingTag, &primaryTag); 804 if (snum != 3) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 805 } else { 806 ierr = PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM);CHKERRQ(ierr); 807 if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, 3);CHKERRQ(ierr);} 808 correspondingDim = ibuf[0]; correspondingTag = ibuf[1]; primaryTag = ibuf[2]; 809 } 810 (void)correspondingDim; (void)correspondingTag; (void)primaryTag; /* unused */ 811 812 if (fileFormat == 22 || !binary) { 813 ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); 814 snum = sscanf(line, "%ld", &nNodes); 815 if (snum != 1) { /* discard transformation and try again */ 816 ierr = PetscViewerRead(viewer, line, -PETSC_MAX_PATH_LEN, NULL, PETSC_STRING);CHKERRQ(ierr); 817 ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); 818 snum = sscanf(line, "%ld", &nNodes); 819 if (snum != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 820 } 821 } else { 822 ierr = PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG);CHKERRQ(ierr); 823 if (byteSwap) {ierr = PetscByteSwap(&nNodes, PETSC_LONG, 1);CHKERRQ(ierr);} 824 if (nNodes == -1) { /* discard transformation and try again */ 825 ierr = PetscViewerRead(viewer, affine, 16, NULL, PETSC_DOUBLE);CHKERRQ(ierr); 826 ierr = PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG);CHKERRQ(ierr); 827 if (byteSwap) {ierr = PetscByteSwap(&nNodes, PETSC_LONG, 1);CHKERRQ(ierr);} 828 } 829 } 830 831 for (j = 0; j < nNodes; j++) { 832 if (fileFormat == 22 || !binary) { 833 ierr = PetscViewerRead(viewer, line, 2, NULL, PETSC_STRING);CHKERRQ(ierr); 834 snum = sscanf(line, "%d %d", &correspondingNode, &primaryNode); 835 if (snum != 2) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 836 } else { 837 ierr = PetscViewerRead(viewer, ibuf, 2, NULL, PETSC_ENUM);CHKERRQ(ierr); 838 if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, 2);CHKERRQ(ierr);} 839 correspondingNode = ibuf[0]; primaryNode = ibuf[1]; 840 } 841 correspondingNode = (int) nodeMap[correspondingNode]; 842 primaryNode = (int) nodeMap[primaryNode]; 843 periodicMap[correspondingNode] = primaryNode; 844 } 845 } 846 PetscFunctionReturn(0); 847 } 848 849 /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 850 $Entities 851 numPoints(size_t) numCurves(size_t) 852 numSurfaces(size_t) numVolumes(size_t) 853 pointTag(int) X(double) Y(double) Z(double) 854 numPhysicalTags(size_t) physicalTag(int) ... 855 ... 856 curveTag(int) minX(double) minY(double) minZ(double) 857 maxX(double) maxY(double) maxZ(double) 858 numPhysicalTags(size_t) physicalTag(int) ... 859 numBoundingPoints(size_t) pointTag(int) ... 860 ... 861 surfaceTag(int) minX(double) minY(double) minZ(double) 862 maxX(double) maxY(double) maxZ(double) 863 numPhysicalTags(size_t) physicalTag(int) ... 864 numBoundingCurves(size_t) curveTag(int) ... 865 ... 866 volumeTag(int) minX(double) minY(double) minZ(double) 867 maxX(double) maxY(double) maxZ(double) 868 numPhysicalTags(size_t) physicalTag(int) ... 869 numBoundngSurfaces(size_t) surfaceTag(int) ... 870 ... 871 $EndEntities 872 */ 873 static PetscErrorCode GmshReadEntities_v41(GmshFile *gmsh, GmshMesh *mesh) 874 { 875 PetscInt count[4], index, numTags, i; 876 int dim, eid, *tags = NULL; 877 GmshEntity *entity = NULL; 878 PetscErrorCode ierr; 879 880 PetscFunctionBegin; 881 ierr = GmshReadSize(gmsh, count, 4);CHKERRQ(ierr); 882 ierr = GmshEntitiesCreate(count, &mesh->entities);CHKERRQ(ierr); 883 for (dim = 0; dim < 4; ++dim) { 884 for (index = 0; index < count[dim]; ++index) { 885 ierr = GmshReadInt(gmsh, &eid, 1);CHKERRQ(ierr); 886 ierr = GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity);CHKERRQ(ierr); 887 ierr = GmshReadDouble(gmsh, entity->bbox, (dim == 0) ? 3 : 6);CHKERRQ(ierr); 888 ierr = GmshReadSize(gmsh, &numTags, 1);CHKERRQ(ierr); 889 ierr = GmshBufferGet(gmsh, numTags, sizeof(int), &tags);CHKERRQ(ierr); 890 ierr = GmshReadInt(gmsh, tags, numTags);CHKERRQ(ierr); 891 entity->numTags = PetscMin(numTags, 4); 892 for (i = 0; i < entity->numTags; ++i) entity->tags[i] = tags[i]; 893 if (dim == 0) continue; 894 ierr = GmshReadSize(gmsh, &numTags, 1);CHKERRQ(ierr); 895 ierr = GmshBufferGet(gmsh, numTags, sizeof(int), &tags);CHKERRQ(ierr); 896 ierr = GmshReadInt(gmsh, tags, numTags);CHKERRQ(ierr); 897 } 898 } 899 PetscFunctionReturn(0); 900 } 901 902 /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 903 $Nodes 904 numEntityBlocks(size_t) numNodes(size_t) 905 minNodeTag(size_t) maxNodeTag(size_t) 906 entityDim(int) entityTag(int) parametric(int; 0 or 1) numNodesBlock(size_t) 907 nodeTag(size_t) 908 ... 909 x(double) y(double) z(double) 910 < u(double; if parametric and entityDim = 1 or entityDim = 2) > 911 < v(double; if parametric and entityDim = 2) > 912 ... 913 ... 914 $EndNodes 915 */ 916 static PetscErrorCode GmshReadNodes_v41(GmshFile *gmsh, GmshMesh *mesh) 917 { 918 int info[3]; 919 PetscInt sizes[4], numEntityBlocks, numNodes, numNodesBlock = 0, block, node; 920 GmshNodes *nodes; 921 PetscErrorCode ierr; 922 923 PetscFunctionBegin; 924 ierr = GmshReadSize(gmsh, sizes, 4);CHKERRQ(ierr); 925 numEntityBlocks = sizes[0]; numNodes = sizes[1]; 926 ierr = GmshNodesCreate(numNodes, &nodes);CHKERRQ(ierr); 927 mesh->numNodes = numNodes; 928 mesh->nodelist = nodes; 929 for (block = 0, node = 0; block < numEntityBlocks; ++block, node += numNodesBlock) { 930 ierr = GmshReadInt(gmsh, info, 3);CHKERRQ(ierr); 931 if (info[2] != 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Parametric coordinates not supported"); 932 ierr = GmshReadSize(gmsh, &numNodesBlock, 1);CHKERRQ(ierr); 933 ierr = GmshReadSize(gmsh, nodes->id+node, numNodesBlock);CHKERRQ(ierr); 934 ierr = GmshReadDouble(gmsh, nodes->xyz+node*3, numNodesBlock*3);CHKERRQ(ierr); 935 } 936 gmsh->nodeStart = sizes[2]; 937 gmsh->nodeEnd = sizes[3]+1; 938 PetscFunctionReturn(0); 939 } 940 941 /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 942 $Elements 943 numEntityBlocks(size_t) numElements(size_t) 944 minElementTag(size_t) maxElementTag(size_t) 945 entityDim(int) entityTag(int) elementType(int; see below) numElementsBlock(size_t) 946 elementTag(size_t) nodeTag(size_t) ... 947 ... 948 ... 949 $EndElements 950 */ 951 static PetscErrorCode GmshReadElements_v41(GmshFile *gmsh, GmshMesh *mesh) 952 { 953 int info[3], eid, dim, cellType; 954 PetscInt sizes[4], *ibuf = NULL, numEntityBlocks, numElements, numBlockElements, numVerts, numNodes, numTags, block, elem, c, p; 955 GmshEntity *entity = NULL; 956 GmshElement *elements; 957 PetscInt *nodeMap = gmsh->nodeMap; 958 PetscErrorCode ierr; 959 960 PetscFunctionBegin; 961 ierr = GmshReadSize(gmsh, sizes, 4);CHKERRQ(ierr); 962 numEntityBlocks = sizes[0]; numElements = sizes[1]; 963 ierr = GmshElementsCreate(numElements, &elements);CHKERRQ(ierr); 964 mesh->numElems = numElements; 965 mesh->elements = elements; 966 for (c = 0, block = 0; block < numEntityBlocks; ++block) { 967 ierr = GmshReadInt(gmsh, info, 3);CHKERRQ(ierr); 968 dim = info[0]; eid = info[1]; cellType = info[2]; 969 ierr = GmshEntitiesGet(mesh->entities, dim, eid, &entity);CHKERRQ(ierr); 970 ierr = GmshCellTypeCheck(cellType);CHKERRQ(ierr); 971 numVerts = GmshCellMap[cellType].numVerts; 972 numNodes = GmshCellMap[cellType].numNodes; 973 numTags = entity->numTags; 974 ierr = GmshReadSize(gmsh, &numBlockElements, 1);CHKERRQ(ierr); 975 ierr = GmshBufferGet(gmsh, (1+numNodes)*numBlockElements, sizeof(PetscInt), &ibuf);CHKERRQ(ierr); 976 ierr = GmshReadSize(gmsh, ibuf, (1+numNodes)*numBlockElements);CHKERRQ(ierr); 977 for (elem = 0; elem < numBlockElements; ++elem, ++c) { 978 GmshElement *element = elements + c; 979 const PetscInt *id = ibuf + elem*(1+numNodes), *nodes = id + 1; 980 element->id = id[0]; 981 element->dim = dim; 982 element->cellType = cellType; 983 element->numVerts = numVerts; 984 element->numNodes = numNodes; 985 element->numTags = numTags; 986 ierr = PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes);CHKERRQ(ierr); 987 for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 988 for (p = 0; p < element->numTags; p++) element->tags[p] = entity->tags[p]; 989 } 990 } 991 PetscFunctionReturn(0); 992 } 993 994 /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 995 $Periodic 996 numPeriodicLinks(size_t) 997 entityDim(int) entityTag(int) entityTagPrimary(int) 998 numAffine(size_t) value(double) ... 999 numCorrespondingNodes(size_t) 1000 nodeTag(size_t) nodeTagPrimary(size_t) 1001 ... 1002 ... 1003 $EndPeriodic 1004 */ 1005 static PetscErrorCode GmshReadPeriodic_v41(GmshFile *gmsh, PetscInt periodicMap[]) 1006 { 1007 int info[3]; 1008 double dbuf[16]; 1009 PetscInt numPeriodicLinks, numAffine, numCorrespondingNodes, *nodeTags = NULL, link, node; 1010 PetscInt *nodeMap = gmsh->nodeMap; 1011 PetscErrorCode ierr; 1012 1013 PetscFunctionBegin; 1014 ierr = GmshReadSize(gmsh, &numPeriodicLinks, 1);CHKERRQ(ierr); 1015 for (link = 0; link < numPeriodicLinks; ++link) { 1016 ierr = GmshReadInt(gmsh, info, 3);CHKERRQ(ierr); 1017 ierr = GmshReadSize(gmsh, &numAffine, 1);CHKERRQ(ierr); 1018 ierr = GmshReadDouble(gmsh, dbuf, numAffine);CHKERRQ(ierr); 1019 ierr = GmshReadSize(gmsh, &numCorrespondingNodes, 1);CHKERRQ(ierr); 1020 ierr = GmshBufferGet(gmsh, numCorrespondingNodes, sizeof(PetscInt), &nodeTags);CHKERRQ(ierr); 1021 ierr = GmshReadSize(gmsh, nodeTags, numCorrespondingNodes*2);CHKERRQ(ierr); 1022 for (node = 0; node < numCorrespondingNodes; ++node) { 1023 PetscInt correspondingNode = nodeMap[nodeTags[node*2+0]]; 1024 PetscInt primaryNode = nodeMap[nodeTags[node*2+1]]; 1025 periodicMap[correspondingNode] = primaryNode; 1026 } 1027 } 1028 PetscFunctionReturn(0); 1029 } 1030 1031 /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 1032 $MeshFormat // same as MSH version 2 1033 version(ASCII double; currently 4.1) 1034 file-type(ASCII int; 0 for ASCII mode, 1 for binary mode) 1035 data-size(ASCII int; sizeof(size_t)) 1036 < int with value one; only in binary mode, to detect endianness > 1037 $EndMeshFormat 1038 */ 1039 static PetscErrorCode GmshReadMeshFormat(GmshFile *gmsh) 1040 { 1041 char line[PETSC_MAX_PATH_LEN]; 1042 int snum, fileType, fileFormat, dataSize, checkEndian; 1043 float version; 1044 PetscErrorCode ierr; 1045 1046 PetscFunctionBegin; 1047 ierr = GmshReadString(gmsh, line, 3);CHKERRQ(ierr); 1048 snum = sscanf(line, "%f %d %d", &version, &fileType, &dataSize); 1049 if (snum != 3) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line); 1050 if (version < 2.2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version); 1051 if ((int)version == 3) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version); 1052 if (version > 4.1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version); 1053 if (gmsh->binary && !fileType) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is binary but Gmsh file is ASCII"); 1054 if (!gmsh->binary && fileType) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is ASCII but Gmsh file is binary"); 1055 fileFormat = (int)roundf(version*10); 1056 if (fileFormat <= 40 && dataSize != sizeof(double)) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Data size %d is not valid for a Gmsh file", dataSize); 1057 if (fileFormat >= 41 && dataSize != sizeof(int) && dataSize != sizeof(PetscInt64)) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Data size %d is not valid for a Gmsh file", dataSize); 1058 gmsh->fileFormat = fileFormat; 1059 gmsh->dataSize = dataSize; 1060 gmsh->byteSwap = PETSC_FALSE; 1061 if (gmsh->binary) { 1062 ierr = GmshReadInt(gmsh, &checkEndian, 1);CHKERRQ(ierr); 1063 if (checkEndian != 1) { 1064 ierr = PetscByteSwap(&checkEndian, PETSC_ENUM, 1);CHKERRQ(ierr); 1065 if (checkEndian != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to detect endianness in Gmsh file header: %s", line); 1066 gmsh->byteSwap = PETSC_TRUE; 1067 } 1068 } 1069 PetscFunctionReturn(0); 1070 } 1071 1072 /* 1073 PhysicalNames 1074 numPhysicalNames(ASCII int) 1075 dimension(ASCII int) physicalTag(ASCII int) "name"(127 characters max) 1076 ... 1077 $EndPhysicalNames 1078 */ 1079 static PetscErrorCode GmshReadPhysicalNames(GmshFile *gmsh) 1080 { 1081 char line[PETSC_MAX_PATH_LEN], name[128+2], *p, *q; 1082 int snum, numRegions, region, dim, tag; 1083 PetscErrorCode ierr; 1084 1085 PetscFunctionBegin; 1086 ierr = GmshReadString(gmsh, line, 1);CHKERRQ(ierr); 1087 snum = sscanf(line, "%d", &numRegions); 1088 if (snum != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 1089 for (region = 0; region < numRegions; ++region) { 1090 ierr = GmshReadString(gmsh, line, 2);CHKERRQ(ierr); 1091 snum = sscanf(line, "%d %d", &dim, &tag); 1092 if (snum != 2) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 1093 ierr = GmshReadString(gmsh, line, -(PetscInt)sizeof(line));CHKERRQ(ierr); 1094 ierr = PetscStrchr(line, '"', &p);CHKERRQ(ierr); 1095 if (!p) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 1096 ierr = PetscStrrchr(line, '"', &q);CHKERRQ(ierr); 1097 if (q == p) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 1098 ierr = PetscStrncpy(name, p+1, (size_t)(q-p-1));CHKERRQ(ierr); 1099 } 1100 PetscFunctionReturn(0); 1101 } 1102 1103 static PetscErrorCode GmshReadEntities(GmshFile *gmsh, GmshMesh *mesh) 1104 { 1105 PetscErrorCode ierr; 1106 1107 PetscFunctionBegin; 1108 switch (gmsh->fileFormat) { 1109 case 41: ierr = GmshReadEntities_v41(gmsh, mesh);CHKERRQ(ierr); break; 1110 default: ierr = GmshReadEntities_v40(gmsh, mesh);CHKERRQ(ierr); break; 1111 } 1112 PetscFunctionReturn(0); 1113 } 1114 1115 static PetscErrorCode GmshReadNodes(GmshFile *gmsh, GmshMesh *mesh) 1116 { 1117 PetscErrorCode ierr; 1118 1119 PetscFunctionBegin; 1120 switch (gmsh->fileFormat) { 1121 case 41: ierr = GmshReadNodes_v41(gmsh, mesh);CHKERRQ(ierr); break; 1122 case 40: ierr = GmshReadNodes_v40(gmsh, mesh);CHKERRQ(ierr); break; 1123 default: ierr = GmshReadNodes_v22(gmsh, mesh);CHKERRQ(ierr); break; 1124 } 1125 1126 { /* Gmsh v2.2/v4.0 does not provide min/max node tags */ 1127 if (mesh->numNodes > 0 && gmsh->nodeEnd >= gmsh->nodeStart) { 1128 PetscInt tagMin = PETSC_MAX_INT, tagMax = PETSC_MIN_INT, n; 1129 GmshNodes *nodes = mesh->nodelist; 1130 for (n = 0; n < mesh->numNodes; ++n) { 1131 const PetscInt tag = nodes->id[n]; 1132 tagMin = PetscMin(tag, tagMin); 1133 tagMax = PetscMax(tag, tagMax); 1134 } 1135 gmsh->nodeStart = tagMin; 1136 gmsh->nodeEnd = tagMax+1; 1137 } 1138 } 1139 1140 { /* Support for sparse node tags */ 1141 PetscInt n, t; 1142 GmshNodes *nodes = mesh->nodelist; 1143 ierr = PetscMalloc1(gmsh->nodeEnd - gmsh->nodeStart, &gmsh->nbuf);CHKERRQ(ierr); 1144 for (t = 0; t < gmsh->nodeEnd - gmsh->nodeStart; ++t) gmsh->nbuf[t] = PETSC_MIN_INT; 1145 gmsh->nodeMap = gmsh->nbuf - gmsh->nodeStart; 1146 for (n = 0; n < mesh->numNodes; ++n) { 1147 const PetscInt tag = nodes->id[n]; 1148 if (gmsh->nodeMap[tag] >= 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Repeated node tag %D", tag); 1149 gmsh->nodeMap[tag] = n; 1150 } 1151 } 1152 PetscFunctionReturn(0); 1153 } 1154 1155 static PetscErrorCode GmshReadElements(GmshFile *gmsh, GmshMesh *mesh) 1156 { 1157 PetscErrorCode ierr; 1158 1159 PetscFunctionBegin; 1160 switch (gmsh->fileFormat) { 1161 case 41: ierr = GmshReadElements_v41(gmsh, mesh);CHKERRQ(ierr); break; 1162 case 40: ierr = GmshReadElements_v40(gmsh, mesh);CHKERRQ(ierr); break; 1163 default: ierr = GmshReadElements_v22(gmsh, mesh);CHKERRQ(ierr); break; 1164 } 1165 1166 { /* Reorder elements by codimension and polytope type */ 1167 PetscInt ne = mesh->numElems; 1168 GmshElement *elements = mesh->elements; 1169 PetscInt keymap[GMSH_NUM_POLYTOPES], nk = 0; 1170 PetscInt offset[GMSH_NUM_POLYTOPES+1], e, k; 1171 1172 for (k = 0; k < GMSH_NUM_POLYTOPES; ++k) keymap[k] = PETSC_MIN_INT; 1173 ierr = PetscMemzero(offset,sizeof(offset));CHKERRQ(ierr); 1174 1175 keymap[GMSH_TET] = nk++; 1176 keymap[GMSH_HEX] = nk++; 1177 keymap[GMSH_PRI] = nk++; 1178 keymap[GMSH_PYR] = nk++; 1179 keymap[GMSH_TRI] = nk++; 1180 keymap[GMSH_QUA] = nk++; 1181 keymap[GMSH_SEG] = nk++; 1182 keymap[GMSH_VTX] = nk++; 1183 1184 ierr = GmshElementsCreate(mesh->numElems, &mesh->elements);CHKERRQ(ierr); 1185 #define key(eid) keymap[GmshCellMap[elements[(eid)].cellType].polytope] 1186 for (e = 0; e < ne; ++e) offset[1+key(e)]++; 1187 for (k = 1; k < nk; ++k) offset[k] += offset[k-1]; 1188 for (e = 0; e < ne; ++e) mesh->elements[offset[key(e)]++] = elements[e]; 1189 #undef key 1190 ierr = GmshElementsDestroy(&elements);CHKERRQ(ierr); 1191 } 1192 1193 { /* Mesh dimension and order */ 1194 GmshElement *elem = mesh->numElems ? mesh->elements : NULL; 1195 mesh->dim = elem ? GmshCellMap[elem->cellType].dim : 0; 1196 mesh->order = elem ? GmshCellMap[elem->cellType].order : 0; 1197 } 1198 1199 { 1200 PetscBT vtx; 1201 PetscInt dim = mesh->dim, e, n, v; 1202 1203 ierr = PetscBTCreate(mesh->numNodes, &vtx);CHKERRQ(ierr); 1204 1205 /* Compute number of cells and set of vertices */ 1206 mesh->numCells = 0; 1207 for (e = 0; e < mesh->numElems; ++e) { 1208 GmshElement *elem = mesh->elements + e; 1209 if (elem->dim == dim && dim > 0) mesh->numCells++; 1210 for (v = 0; v < elem->numVerts; v++) { 1211 ierr = PetscBTSet(vtx, elem->nodes[v]);CHKERRQ(ierr); 1212 } 1213 } 1214 1215 /* Compute numbering for vertices */ 1216 mesh->numVerts = 0; 1217 ierr = PetscMalloc1(mesh->numNodes, &mesh->vertexMap);CHKERRQ(ierr); 1218 for (n = 0; n < mesh->numNodes; ++n) 1219 mesh->vertexMap[n] = PetscBTLookup(vtx, n) ? mesh->numVerts++ : PETSC_MIN_INT; 1220 1221 ierr = PetscBTDestroy(&vtx);CHKERRQ(ierr); 1222 } 1223 PetscFunctionReturn(0); 1224 } 1225 1226 static PetscErrorCode GmshReadPeriodic(GmshFile *gmsh, GmshMesh *mesh) 1227 { 1228 PetscInt n; 1229 PetscErrorCode ierr; 1230 1231 PetscFunctionBegin; 1232 ierr = PetscMalloc1(mesh->numNodes, &mesh->periodMap);CHKERRQ(ierr); 1233 for (n = 0; n < mesh->numNodes; ++n) mesh->periodMap[n] = n; 1234 switch (gmsh->fileFormat) { 1235 case 41: ierr = GmshReadPeriodic_v41(gmsh, mesh->periodMap);CHKERRQ(ierr); break; 1236 default: ierr = GmshReadPeriodic_v40(gmsh, mesh->periodMap);CHKERRQ(ierr); break; 1237 } 1238 1239 /* Find canonical primary nodes */ 1240 for (n = 0; n < mesh->numNodes; ++n) 1241 while (mesh->periodMap[n] != mesh->periodMap[mesh->periodMap[n]]) 1242 mesh->periodMap[n] = mesh->periodMap[mesh->periodMap[n]]; 1243 1244 /* Renumber vertices (filter out correspondings) */ 1245 mesh->numVerts = 0; 1246 for (n = 0; n < mesh->numNodes; ++n) 1247 if (mesh->vertexMap[n] >= 0) /* is vertex */ 1248 if (mesh->periodMap[n] == n) /* is primary */ 1249 mesh->vertexMap[n] = mesh->numVerts++; 1250 for (n = 0; n < mesh->numNodes; ++n) 1251 if (mesh->vertexMap[n] >= 0) /* is vertex */ 1252 if (mesh->periodMap[n] != n) /* is corresponding */ 1253 mesh->vertexMap[n] = mesh->vertexMap[mesh->periodMap[n]]; 1254 PetscFunctionReturn(0); 1255 } 1256 1257 #define DM_POLYTOPE_VERTEX DM_POLYTOPE_POINT 1258 #define DM_POLYTOPE_PYRAMID DM_POLYTOPE_UNKNOWN 1259 static const DMPolytopeType DMPolytopeMap[] = { 1260 /* GMSH_VTX */ DM_POLYTOPE_VERTEX, 1261 /* GMSH_SEG */ DM_POLYTOPE_SEGMENT, 1262 /* GMSH_TRI */ DM_POLYTOPE_TRIANGLE, 1263 /* GMSH_QUA */ DM_POLYTOPE_QUADRILATERAL, 1264 /* GMSH_TET */ DM_POLYTOPE_TETRAHEDRON, 1265 /* GMSH_HEX */ DM_POLYTOPE_HEXAHEDRON, 1266 /* GMSH_PRI */ DM_POLYTOPE_TRI_PRISM, 1267 /* GMSH_PYR */ DM_POLYTOPE_PYRAMID, 1268 DM_POLYTOPE_UNKNOWN 1269 }; 1270 1271 PETSC_STATIC_INLINE DMPolytopeType DMPolytopeTypeFromGmsh(PetscInt cellType) 1272 { 1273 return DMPolytopeMap[GmshCellMap[cellType].polytope]; 1274 } 1275 1276 static PetscErrorCode GmshCreateFE(MPI_Comm comm, const char prefix[], PetscBool isSimplex, PetscBool continuity, PetscDTNodeType nodeType, PetscInt dim, PetscInt Nc, PetscInt k, PetscFE *fem) 1277 { 1278 DM K; 1279 PetscSpace P; 1280 PetscDualSpace Q; 1281 PetscQuadrature q, fq; 1282 PetscBool isTensor = isSimplex ? PETSC_FALSE : PETSC_TRUE; 1283 PetscBool endpoint = PETSC_TRUE; 1284 char name[32]; 1285 PetscErrorCode ierr; 1286 1287 PetscFunctionBegin; 1288 /* Create space */ 1289 ierr = PetscSpaceCreate(comm, &P);CHKERRQ(ierr); 1290 ierr = PetscSpaceSetType(P, PETSCSPACEPOLYNOMIAL);CHKERRQ(ierr); 1291 ierr = PetscSpacePolynomialSetTensor(P, isTensor);CHKERRQ(ierr); 1292 ierr = PetscSpaceSetNumComponents(P, Nc);CHKERRQ(ierr); 1293 ierr = PetscSpaceSetNumVariables(P, dim);CHKERRQ(ierr); 1294 ierr = PetscSpaceSetDegree(P, k, PETSC_DETERMINE);CHKERRQ(ierr); 1295 if (prefix) { 1296 ierr = PetscObjectSetOptionsPrefix((PetscObject) P, prefix);CHKERRQ(ierr); 1297 ierr = PetscSpaceSetFromOptions(P);CHKERRQ(ierr); 1298 ierr = PetscObjectSetOptionsPrefix((PetscObject) P, NULL);CHKERRQ(ierr); 1299 ierr = PetscSpaceGetDegree(P, &k, NULL);CHKERRQ(ierr); 1300 } 1301 ierr = PetscSpaceSetUp(P);CHKERRQ(ierr); 1302 /* Create dual space */ 1303 ierr = PetscDualSpaceCreate(comm, &Q);CHKERRQ(ierr); 1304 ierr = PetscDualSpaceSetType(Q, PETSCDUALSPACELAGRANGE);CHKERRQ(ierr); 1305 ierr = PetscDualSpaceLagrangeSetTensor(Q, isTensor);CHKERRQ(ierr); 1306 ierr = PetscDualSpaceLagrangeSetContinuity(Q, continuity);CHKERRQ(ierr); 1307 ierr = PetscDualSpaceLagrangeSetNodeType(Q, nodeType, endpoint, 0);CHKERRQ(ierr); 1308 ierr = PetscDualSpaceSetNumComponents(Q, Nc);CHKERRQ(ierr); 1309 ierr = PetscDualSpaceSetOrder(Q, k);CHKERRQ(ierr); 1310 ierr = PetscDualSpaceCreateReferenceCell(Q, dim, isSimplex, &K);CHKERRQ(ierr); 1311 ierr = PetscDualSpaceSetDM(Q, K);CHKERRQ(ierr); 1312 ierr = DMDestroy(&K);CHKERRQ(ierr); 1313 if (prefix) { 1314 ierr = PetscObjectSetOptionsPrefix((PetscObject) Q, prefix);CHKERRQ(ierr); 1315 ierr = PetscDualSpaceSetFromOptions(Q);CHKERRQ(ierr); 1316 ierr = PetscObjectSetOptionsPrefix((PetscObject) Q, NULL);CHKERRQ(ierr); 1317 } 1318 ierr = PetscDualSpaceSetUp(Q);CHKERRQ(ierr); 1319 /* Create quadrature */ 1320 if (isSimplex) { 1321 ierr = PetscDTStroudConicalQuadrature(dim, 1, k+1, -1, +1, &q);CHKERRQ(ierr); 1322 ierr = PetscDTStroudConicalQuadrature(dim-1, 1, k+1, -1, +1, &fq);CHKERRQ(ierr); 1323 } else { 1324 ierr = PetscDTGaussTensorQuadrature(dim, 1, k+1, -1, +1, &q);CHKERRQ(ierr); 1325 ierr = PetscDTGaussTensorQuadrature(dim-1, 1, k+1, -1, +1, &fq);CHKERRQ(ierr); 1326 } 1327 /* Create finite element */ 1328 ierr = PetscFECreate(comm, fem);CHKERRQ(ierr); 1329 ierr = PetscFESetType(*fem, PETSCFEBASIC);CHKERRQ(ierr); 1330 ierr = PetscFESetNumComponents(*fem, Nc);CHKERRQ(ierr); 1331 ierr = PetscFESetBasisSpace(*fem, P);CHKERRQ(ierr); 1332 ierr = PetscFESetDualSpace(*fem, Q);CHKERRQ(ierr); 1333 ierr = PetscFESetQuadrature(*fem, q);CHKERRQ(ierr); 1334 ierr = PetscFESetFaceQuadrature(*fem, fq);CHKERRQ(ierr); 1335 if (prefix) { 1336 ierr = PetscObjectSetOptionsPrefix((PetscObject) *fem, prefix);CHKERRQ(ierr); 1337 ierr = PetscFESetFromOptions(*fem);CHKERRQ(ierr); 1338 ierr = PetscObjectSetOptionsPrefix((PetscObject) *fem, NULL);CHKERRQ(ierr); 1339 } 1340 ierr = PetscFESetUp(*fem);CHKERRQ(ierr); 1341 /* Cleanup */ 1342 ierr = PetscSpaceDestroy(&P);CHKERRQ(ierr); 1343 ierr = PetscDualSpaceDestroy(&Q);CHKERRQ(ierr); 1344 ierr = PetscQuadratureDestroy(&q);CHKERRQ(ierr); 1345 ierr = PetscQuadratureDestroy(&fq);CHKERRQ(ierr); 1346 /* Set finite element name */ 1347 ierr = PetscSNPrintf(name, sizeof(name), "%s%D", isSimplex? "P" : "Q", k);CHKERRQ(ierr); 1348 ierr = PetscFESetName(*fem, name);CHKERRQ(ierr); 1349 PetscFunctionReturn(0); 1350 } 1351 1352 /*@C 1353 DMPlexCreateGmshFromFile - Create a DMPlex mesh from a Gmsh file 1354 1355 + comm - The MPI communicator 1356 . filename - Name of the Gmsh file 1357 - interpolate - Create faces and edges in the mesh 1358 1359 Output Parameter: 1360 . dm - The DM object representing the mesh 1361 1362 Level: beginner 1363 1364 .seealso: DMPlexCreateFromFile(), DMPlexCreateGmsh(), DMPlexCreate() 1365 @*/ 1366 PetscErrorCode DMPlexCreateGmshFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 1367 { 1368 PetscViewer viewer; 1369 PetscMPIInt rank; 1370 int fileType; 1371 PetscViewerType vtype; 1372 PetscErrorCode ierr; 1373 1374 PetscFunctionBegin; 1375 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 1376 1377 /* Determine Gmsh file type (ASCII or binary) from file header */ 1378 if (rank == 0) { 1379 GmshFile gmsh[1]; 1380 char line[PETSC_MAX_PATH_LEN]; 1381 int snum; 1382 float version; 1383 1384 ierr = PetscArrayzero(gmsh,1);CHKERRQ(ierr); 1385 ierr = PetscViewerCreate(PETSC_COMM_SELF, &gmsh->viewer);CHKERRQ(ierr); 1386 ierr = PetscViewerSetType(gmsh->viewer, PETSCVIEWERASCII);CHKERRQ(ierr); 1387 ierr = PetscViewerFileSetMode(gmsh->viewer, FILE_MODE_READ);CHKERRQ(ierr); 1388 ierr = PetscViewerFileSetName(gmsh->viewer, filename);CHKERRQ(ierr); 1389 /* Read only the first two lines of the Gmsh file */ 1390 ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr); 1391 ierr = GmshExpect(gmsh, "$MeshFormat", line);CHKERRQ(ierr); 1392 ierr = GmshReadString(gmsh, line, 2);CHKERRQ(ierr); 1393 snum = sscanf(line, "%f %d", &version, &fileType); 1394 if (snum != 2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line); 1395 if (version < 2.2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version); 1396 if ((int)version == 3) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version); 1397 if (version > 4.1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version); 1398 ierr = PetscViewerDestroy(&gmsh->viewer);CHKERRQ(ierr); 1399 } 1400 ierr = MPI_Bcast(&fileType, 1, MPI_INT, 0, comm);CHKERRMPI(ierr); 1401 vtype = (fileType == 0) ? PETSCVIEWERASCII : PETSCVIEWERBINARY; 1402 1403 /* Create appropriate viewer and build plex */ 1404 ierr = PetscViewerCreate(comm, &viewer);CHKERRQ(ierr); 1405 ierr = PetscViewerSetType(viewer, vtype);CHKERRQ(ierr); 1406 ierr = PetscViewerFileSetMode(viewer, FILE_MODE_READ);CHKERRQ(ierr); 1407 ierr = PetscViewerFileSetName(viewer, filename);CHKERRQ(ierr); 1408 ierr = DMPlexCreateGmsh(comm, viewer, interpolate, dm);CHKERRQ(ierr); 1409 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 1410 PetscFunctionReturn(0); 1411 } 1412 1413 /*@ 1414 DMPlexCreateGmsh - Create a DMPlex mesh from a Gmsh file viewer 1415 1416 Collective 1417 1418 Input Parameters: 1419 + comm - The MPI communicator 1420 . viewer - The Viewer associated with a Gmsh file 1421 - interpolate - Create faces and edges in the mesh 1422 1423 Output Parameter: 1424 . dm - The DM object representing the mesh 1425 1426 Note: http://gmsh.info/doc/texinfo/gmsh.html#MSH-file-format 1427 1428 Level: beginner 1429 1430 .seealso: DMPLEX, DMCreate() 1431 @*/ 1432 PetscErrorCode DMPlexCreateGmsh(MPI_Comm comm, PetscViewer viewer, PetscBool interpolate, DM *dm) 1433 { 1434 GmshMesh *mesh = NULL; 1435 PetscViewer parentviewer = NULL; 1436 PetscBT periodicVerts = NULL; 1437 PetscBT periodicCells = NULL; 1438 DM cdm; 1439 PetscSection coordSection; 1440 Vec coordinates; 1441 DMLabel cellSets = NULL, faceSets = NULL, vertSets = NULL, marker = NULL; 1442 PetscInt dim = 0, coordDim = -1, order = 0; 1443 PetscInt numNodes = 0, numElems = 0, numVerts = 0, numCells = 0; 1444 PetscInt cell, cone[8], e, n, v, d; 1445 PetscBool binary, usemarker = PETSC_FALSE; 1446 PetscBool hybrid = interpolate, periodic = PETSC_TRUE; 1447 PetscBool highOrder = PETSC_TRUE, highOrderSet, project = PETSC_FALSE; 1448 PetscBool isSimplex = PETSC_FALSE, isHybrid = PETSC_FALSE, hasTetra = PETSC_FALSE; 1449 PetscMPIInt rank; 1450 PetscErrorCode ierr; 1451 1452 PetscFunctionBegin; 1453 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 1454 ierr = PetscObjectOptionsBegin((PetscObject)viewer);CHKERRQ(ierr); 1455 ierr = PetscOptionsHead(PetscOptionsObject,"DMPlex Gmsh options");CHKERRQ(ierr); 1456 ierr = PetscOptionsBool("-dm_plex_gmsh_hybrid", "Generate hybrid cell bounds", "DMPlexCreateGmsh", hybrid, &hybrid, NULL);CHKERRQ(ierr); 1457 ierr = PetscOptionsBool("-dm_plex_gmsh_periodic","Read Gmsh periodic section", "DMPlexCreateGmsh", periodic, &periodic, NULL);CHKERRQ(ierr); 1458 ierr = PetscOptionsBool("-dm_plex_gmsh_highorder","Generate high-order coordinates", "DMPlexCreateGmsh", highOrder, &highOrder, &highOrderSet);CHKERRQ(ierr); 1459 ierr = PetscOptionsBool("-dm_plex_gmsh_project", "Project high-order coordinates to a different space", "DMPlexCreateGmsh", project, &project, NULL);CHKERRQ(ierr); 1460 ierr = PetscOptionsBool("-dm_plex_gmsh_use_marker", "Generate marker label", "DMPlexCreateGmsh", usemarker, &usemarker, NULL);CHKERRQ(ierr); 1461 ierr = PetscOptionsBoundedInt("-dm_plex_gmsh_spacedim", "Embedding space dimension", "DMPlexCreateGmsh", coordDim, &coordDim, NULL, PETSC_DECIDE);CHKERRQ(ierr); 1462 ierr = PetscOptionsTail();CHKERRQ(ierr); 1463 ierr = PetscOptionsEnd();CHKERRQ(ierr); 1464 1465 ierr = GmshCellInfoSetUp();CHKERRQ(ierr); 1466 1467 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 1468 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 1469 ierr = PetscLogEventBegin(DMPLEX_CreateGmsh,*dm,NULL,NULL,NULL);CHKERRQ(ierr); 1470 1471 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &binary);CHKERRQ(ierr); 1472 1473 /* Binary viewers read on all ranks, get subviewer to read only in rank 0 */ 1474 if (binary) { 1475 parentviewer = viewer; 1476 ierr = PetscViewerGetSubViewer(parentviewer, PETSC_COMM_SELF, &viewer);CHKERRQ(ierr); 1477 } 1478 1479 if (rank == 0) { 1480 GmshFile gmsh[1]; 1481 char line[PETSC_MAX_PATH_LEN]; 1482 PetscBool match; 1483 1484 ierr = PetscArrayzero(gmsh,1);CHKERRQ(ierr); 1485 gmsh->viewer = viewer; 1486 gmsh->binary = binary; 1487 1488 ierr = GmshMeshCreate(&mesh);CHKERRQ(ierr); 1489 1490 /* Read mesh format */ 1491 ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr); 1492 ierr = GmshExpect(gmsh, "$MeshFormat", line);CHKERRQ(ierr); 1493 ierr = GmshReadMeshFormat(gmsh);CHKERRQ(ierr); 1494 ierr = GmshReadEndSection(gmsh, "$EndMeshFormat", line);CHKERRQ(ierr); 1495 1496 /* OPTIONAL Read physical names */ 1497 ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr); 1498 ierr = GmshMatch(gmsh, "$PhysicalNames", line, &match);CHKERRQ(ierr); 1499 if (match) { 1500 ierr = GmshExpect(gmsh, "$PhysicalNames", line);CHKERRQ(ierr); 1501 ierr = GmshReadPhysicalNames(gmsh);CHKERRQ(ierr); 1502 ierr = GmshReadEndSection(gmsh, "$EndPhysicalNames", line);CHKERRQ(ierr); 1503 /* Initial read for entity section */ 1504 ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr); 1505 } 1506 1507 /* Read entities */ 1508 if (gmsh->fileFormat >= 40) { 1509 ierr = GmshExpect(gmsh, "$Entities", line);CHKERRQ(ierr); 1510 ierr = GmshReadEntities(gmsh, mesh);CHKERRQ(ierr); 1511 ierr = GmshReadEndSection(gmsh, "$EndEntities", line);CHKERRQ(ierr); 1512 /* Initial read for nodes section */ 1513 ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr); 1514 } 1515 1516 /* Read nodes */ 1517 ierr = GmshExpect(gmsh, "$Nodes", line);CHKERRQ(ierr); 1518 ierr = GmshReadNodes(gmsh, mesh);CHKERRQ(ierr); 1519 ierr = GmshReadEndSection(gmsh, "$EndNodes", line);CHKERRQ(ierr); 1520 1521 /* Read elements */ 1522 ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr); 1523 ierr = GmshExpect(gmsh, "$Elements", line);CHKERRQ(ierr); 1524 ierr = GmshReadElements(gmsh, mesh);CHKERRQ(ierr); 1525 ierr = GmshReadEndSection(gmsh, "$EndElements", line);CHKERRQ(ierr); 1526 1527 /* Read periodic section (OPTIONAL) */ 1528 if (periodic) { 1529 ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr); 1530 ierr = GmshMatch(gmsh, "$Periodic", line, &periodic);CHKERRQ(ierr); 1531 } 1532 if (periodic) { 1533 ierr = GmshExpect(gmsh, "$Periodic", line);CHKERRQ(ierr); 1534 ierr = GmshReadPeriodic(gmsh, mesh);CHKERRQ(ierr); 1535 ierr = GmshReadEndSection(gmsh, "$EndPeriodic", line);CHKERRQ(ierr); 1536 } 1537 1538 ierr = PetscFree(gmsh->wbuf);CHKERRQ(ierr); 1539 ierr = PetscFree(gmsh->sbuf);CHKERRQ(ierr); 1540 ierr = PetscFree(gmsh->nbuf);CHKERRQ(ierr); 1541 1542 dim = mesh->dim; 1543 order = mesh->order; 1544 numNodes = mesh->numNodes; 1545 numElems = mesh->numElems; 1546 numVerts = mesh->numVerts; 1547 numCells = mesh->numCells; 1548 1549 { 1550 GmshElement *elemA = mesh->numCells > 0 ? mesh->elements : NULL; 1551 GmshElement *elemB = elemA ? elemA + mesh->numCells - 1 : NULL; 1552 int ptA = elemA ? GmshCellMap[elemA->cellType].polytope : -1; 1553 int ptB = elemB ? GmshCellMap[elemB->cellType].polytope : -1; 1554 isSimplex = (ptA == GMSH_QUA || ptA == GMSH_HEX) ? PETSC_FALSE : PETSC_TRUE; 1555 isHybrid = (ptA == ptB) ? PETSC_FALSE : PETSC_TRUE; 1556 hasTetra = (ptA == GMSH_TET) ? PETSC_TRUE : PETSC_FALSE; 1557 } 1558 } 1559 1560 if (parentviewer) { 1561 ierr = PetscViewerRestoreSubViewer(parentviewer, PETSC_COMM_SELF, &viewer);CHKERRQ(ierr); 1562 } 1563 1564 { 1565 int buf[6]; 1566 1567 buf[0] = (int)dim; 1568 buf[1] = (int)order; 1569 buf[2] = periodic; 1570 buf[3] = isSimplex; 1571 buf[4] = isHybrid; 1572 buf[5] = hasTetra; 1573 1574 ierr = MPI_Bcast(buf, 6, MPI_INT, 0, comm);CHKERRMPI(ierr); 1575 1576 dim = buf[0]; 1577 order = buf[1]; 1578 periodic = buf[2] ? PETSC_TRUE : PETSC_FALSE; 1579 isSimplex = buf[3] ? PETSC_TRUE : PETSC_FALSE; 1580 isHybrid = buf[4] ? PETSC_TRUE : PETSC_FALSE; 1581 hasTetra = buf[5] ? PETSC_TRUE : PETSC_FALSE; 1582 } 1583 1584 if (!highOrderSet) highOrder = (order > 1) ? PETSC_TRUE : PETSC_FALSE; 1585 if (highOrder && isHybrid) SETERRQ(comm, PETSC_ERR_SUP, "No support for discretization on hybrid meshes yet"); 1586 1587 /* We do not want this label automatically computed, instead we fill it here */ 1588 ierr = DMCreateLabel(*dm, "celltype");CHKERRQ(ierr); 1589 1590 /* Allocate the cell-vertex mesh */ 1591 ierr = DMPlexSetChart(*dm, 0, numCells+numVerts);CHKERRQ(ierr); 1592 for (cell = 0; cell < numCells; ++cell) { 1593 GmshElement *elem = mesh->elements + cell; 1594 DMPolytopeType ctype = DMPolytopeTypeFromGmsh(elem->cellType); 1595 if (hybrid && hasTetra && ctype == DM_POLYTOPE_TRI_PRISM) ctype = DM_POLYTOPE_TRI_PRISM_TENSOR; 1596 ierr = DMPlexSetConeSize(*dm, cell, elem->numVerts);CHKERRQ(ierr); 1597 ierr = DMPlexSetCellType(*dm, cell, ctype);CHKERRQ(ierr); 1598 } 1599 for (v = numCells; v < numCells+numVerts; ++v) { 1600 ierr = DMPlexSetCellType(*dm, v, DM_POLYTOPE_POINT);CHKERRQ(ierr); 1601 } 1602 ierr = DMSetUp(*dm);CHKERRQ(ierr); 1603 1604 /* Add cell-vertex connections */ 1605 for (cell = 0; cell < numCells; ++cell) { 1606 GmshElement *elem = mesh->elements + cell; 1607 for (v = 0; v < elem->numVerts; ++v) { 1608 const PetscInt nn = elem->nodes[v]; 1609 const PetscInt vv = mesh->vertexMap[nn]; 1610 cone[v] = numCells + vv; 1611 } 1612 ierr = DMPlexReorderCell(*dm, cell, cone);CHKERRQ(ierr); 1613 ierr = DMPlexSetCone(*dm, cell, cone);CHKERRQ(ierr); 1614 } 1615 1616 ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); 1617 ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr); 1618 ierr = DMPlexStratify(*dm);CHKERRQ(ierr); 1619 if (interpolate) { 1620 DM idm; 1621 1622 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 1623 ierr = DMDestroy(dm);CHKERRQ(ierr); 1624 *dm = idm; 1625 } 1626 1627 if (usemarker && !interpolate && dim > 1) SETERRQ(comm,PETSC_ERR_SUP,"Cannot create marker label without interpolation"); 1628 if (rank == 0 && usemarker) { 1629 PetscInt f, fStart, fEnd; 1630 1631 ierr = DMCreateLabel(*dm, "marker");CHKERRQ(ierr); 1632 ierr = DMPlexGetHeightStratum(*dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 1633 for (f = fStart; f < fEnd; ++f) { 1634 PetscInt suppSize; 1635 1636 ierr = DMPlexGetSupportSize(*dm, f, &suppSize);CHKERRQ(ierr); 1637 if (suppSize == 1) { 1638 PetscInt *cone = NULL, coneSize, p; 1639 1640 ierr = DMPlexGetTransitiveClosure(*dm, f, PETSC_TRUE, &coneSize, &cone);CHKERRQ(ierr); 1641 for (p = 0; p < coneSize; p += 2) { 1642 ierr = DMSetLabelValue_Fast(*dm, &marker, "marker", cone[p], 1);CHKERRQ(ierr); 1643 } 1644 ierr = DMPlexRestoreTransitiveClosure(*dm, f, PETSC_TRUE, &coneSize, &cone);CHKERRQ(ierr); 1645 } 1646 } 1647 } 1648 1649 if (rank == 0) { 1650 PetscInt vStart, vEnd; 1651 1652 ierr = DMPlexGetDepthStratum(*dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1653 for (cell = 0, e = 0; e < numElems; ++e) { 1654 GmshElement *elem = mesh->elements + e; 1655 1656 /* Create cell sets */ 1657 if (elem->dim == dim && dim > 0) { 1658 if (elem->numTags > 0) { 1659 ierr = DMSetLabelValue_Fast(*dm, &cellSets, "Cell Sets", cell, elem->tags[0]);CHKERRQ(ierr); 1660 } 1661 cell++; 1662 } 1663 1664 /* Create face sets */ 1665 if (interpolate && elem->dim == dim-1) { 1666 PetscInt joinSize; 1667 const PetscInt *join = NULL; 1668 /* Find the relevant facet with vertex joins */ 1669 for (v = 0; v < elem->numVerts; ++v) { 1670 const PetscInt nn = elem->nodes[v]; 1671 const PetscInt vv = mesh->vertexMap[nn]; 1672 cone[v] = vStart + vv; 1673 } 1674 ierr = DMPlexGetFullJoin(*dm, elem->numVerts, cone, &joinSize, &join);CHKERRQ(ierr); 1675 if (joinSize != 1) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP, "Could not determine Plex facet for Gmsh element %D (Plex cell %D)", elem->id, e); 1676 ierr = DMSetLabelValue_Fast(*dm, &faceSets, "Face Sets", join[0], elem->tags[0]);CHKERRQ(ierr); 1677 ierr = DMPlexRestoreJoin(*dm, elem->numVerts, cone, &joinSize, &join);CHKERRQ(ierr); 1678 } 1679 1680 /* Create vertex sets */ 1681 if (elem->dim == 0) { 1682 if (elem->numTags > 0) { 1683 const PetscInt nn = elem->nodes[0]; 1684 const PetscInt vv = mesh->vertexMap[nn]; 1685 ierr = DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, elem->tags[0]);CHKERRQ(ierr); 1686 } 1687 } 1688 } 1689 } 1690 1691 { /* Create Cell/Face/Vertex Sets labels at all processes */ 1692 enum {n = 4}; 1693 PetscBool flag[n]; 1694 1695 flag[0] = cellSets ? PETSC_TRUE : PETSC_FALSE; 1696 flag[1] = faceSets ? PETSC_TRUE : PETSC_FALSE; 1697 flag[2] = vertSets ? PETSC_TRUE : PETSC_FALSE; 1698 flag[3] = marker ? PETSC_TRUE : PETSC_FALSE; 1699 ierr = MPI_Bcast(flag, n, MPIU_BOOL, 0, comm);CHKERRMPI(ierr); 1700 if (flag[0]) {ierr = DMCreateLabel(*dm, "Cell Sets");CHKERRQ(ierr);} 1701 if (flag[1]) {ierr = DMCreateLabel(*dm, "Face Sets");CHKERRQ(ierr);} 1702 if (flag[2]) {ierr = DMCreateLabel(*dm, "Vertex Sets");CHKERRQ(ierr);} 1703 if (flag[3]) {ierr = DMCreateLabel(*dm, "marker");CHKERRQ(ierr);} 1704 } 1705 1706 if (periodic) { 1707 ierr = PetscBTCreate(numVerts, &periodicVerts);CHKERRQ(ierr); 1708 for (n = 0; n < numNodes; ++n) { 1709 if (mesh->vertexMap[n] >= 0) { 1710 if (PetscUnlikely(mesh->periodMap[n] != n)) { 1711 PetscInt m = mesh->periodMap[n]; 1712 ierr = PetscBTSet(periodicVerts, mesh->vertexMap[n]);CHKERRQ(ierr); 1713 ierr = PetscBTSet(periodicVerts, mesh->vertexMap[m]);CHKERRQ(ierr); 1714 } 1715 } 1716 } 1717 ierr = PetscBTCreate(numCells, &periodicCells);CHKERRQ(ierr); 1718 for (cell = 0; cell < numCells; ++cell) { 1719 GmshElement *elem = mesh->elements + cell; 1720 for (v = 0; v < elem->numVerts; ++v) { 1721 PetscInt nn = elem->nodes[v]; 1722 PetscInt vv = mesh->vertexMap[nn]; 1723 if (PetscUnlikely(PetscBTLookup(periodicVerts, vv))) { 1724 ierr = PetscBTSet(periodicCells, cell);CHKERRQ(ierr); break; 1725 } 1726 } 1727 } 1728 } 1729 1730 /* Setup coordinate DM */ 1731 if (coordDim < 0) coordDim = dim; 1732 ierr = DMSetCoordinateDim(*dm, coordDim);CHKERRQ(ierr); 1733 ierr = DMGetCoordinateDM(*dm, &cdm);CHKERRQ(ierr); 1734 if (highOrder) { 1735 PetscFE fe; 1736 PetscBool continuity = periodic ? PETSC_FALSE : PETSC_TRUE; 1737 PetscDTNodeType nodeType = PETSCDTNODES_EQUISPACED; 1738 1739 if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */ 1740 1741 ierr = GmshCreateFE(comm, NULL, isSimplex, continuity, nodeType, dim, coordDim, order, &fe);CHKERRQ(ierr); 1742 ierr = PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_fe_view");CHKERRQ(ierr); 1743 ierr = DMSetField(cdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 1744 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 1745 ierr = DMCreateDS(cdm);CHKERRQ(ierr); 1746 } 1747 1748 /* Create coordinates */ 1749 if (highOrder) { 1750 1751 PetscInt maxDof = GmshNumNodes_HEX(order)*coordDim; 1752 double *coords = mesh ? mesh->nodelist->xyz : NULL; 1753 PetscSection section; 1754 PetscScalar *cellCoords; 1755 1756 ierr = DMSetLocalSection(cdm, NULL);CHKERRQ(ierr); 1757 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 1758 ierr = PetscSectionClone(coordSection, §ion);CHKERRQ(ierr); 1759 ierr = DMPlexSetClosurePermutationTensor(cdm, 0, section);CHKERRQ(ierr); /* XXX Implement DMPlexSetClosurePermutationLexicographic() */ 1760 1761 ierr = DMCreateLocalVector(cdm, &coordinates);CHKERRQ(ierr); 1762 ierr = PetscMalloc1(maxDof, &cellCoords);CHKERRQ(ierr); 1763 for (cell = 0; cell < numCells; ++cell) { 1764 GmshElement *elem = mesh->elements + cell; 1765 const int *lexorder = GmshCellMap[elem->cellType].lexorder(); 1766 for (n = 0; n < elem->numNodes; ++n) { 1767 const PetscInt node = elem->nodes[lexorder[n]]; 1768 for (d = 0; d < coordDim; ++d) 1769 cellCoords[n*coordDim+d] = (PetscReal) coords[node*3+d]; 1770 } 1771 ierr = DMPlexVecSetClosure(cdm, section, coordinates, cell, cellCoords, INSERT_VALUES);CHKERRQ(ierr); 1772 } 1773 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 1774 ierr = PetscFree(cellCoords);CHKERRQ(ierr); 1775 1776 } else { 1777 1778 PetscInt *nodeMap; 1779 double *coords = mesh ? mesh->nodelist->xyz : NULL; 1780 PetscScalar *pointCoords; 1781 1782 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 1783 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 1784 ierr = PetscSectionSetFieldComponents(coordSection, 0, coordDim);CHKERRQ(ierr); 1785 if (periodic) { /* we need to localize coordinates on cells */ 1786 ierr = PetscSectionSetChart(coordSection, 0, numCells+numVerts);CHKERRQ(ierr); 1787 } else { 1788 ierr = PetscSectionSetChart(coordSection, numCells, numCells+numVerts);CHKERRQ(ierr); 1789 } 1790 if (periodic) { 1791 for (cell = 0; cell < numCells; ++cell) { 1792 if (PetscUnlikely(PetscBTLookup(periodicCells, cell))) { 1793 GmshElement *elem = mesh->elements + cell; 1794 PetscInt dof = elem->numVerts * coordDim; 1795 ierr = PetscSectionSetDof(coordSection, cell, dof);CHKERRQ(ierr); 1796 ierr = PetscSectionSetFieldDof(coordSection, cell, 0, dof);CHKERRQ(ierr); 1797 } 1798 } 1799 } 1800 for (v = numCells; v < numCells+numVerts; ++v) { 1801 ierr = PetscSectionSetDof(coordSection, v, coordDim);CHKERRQ(ierr); 1802 ierr = PetscSectionSetFieldDof(coordSection, v, 0, coordDim);CHKERRQ(ierr); 1803 } 1804 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 1805 1806 ierr = DMCreateLocalVector(cdm, &coordinates);CHKERRQ(ierr); 1807 ierr = VecGetArray(coordinates, &pointCoords);CHKERRQ(ierr); 1808 if (periodic) { 1809 for (cell = 0; cell < numCells; ++cell) { 1810 if (PetscUnlikely(PetscBTLookup(periodicCells, cell))) { 1811 GmshElement *elem = mesh->elements + cell; 1812 PetscInt off, node; 1813 for (v = 0; v < elem->numVerts; ++v) 1814 cone[v] = elem->nodes[v]; 1815 ierr = DMPlexReorderCell(cdm, cell, cone);CHKERRQ(ierr); 1816 ierr = PetscSectionGetOffset(coordSection, cell, &off);CHKERRQ(ierr); 1817 for (v = 0; v < elem->numVerts; ++v) 1818 for (node = cone[v], d = 0; d < coordDim; ++d) 1819 pointCoords[off++] = (PetscReal) coords[node*3+d]; 1820 } 1821 } 1822 } 1823 ierr = PetscMalloc1(numVerts, &nodeMap);CHKERRQ(ierr); 1824 for (n = 0; n < numNodes; n++) 1825 if (mesh->vertexMap[n] >= 0) 1826 nodeMap[mesh->vertexMap[n]] = n; 1827 for (v = 0; v < numVerts; ++v) { 1828 PetscInt off, node = nodeMap[v]; 1829 ierr = PetscSectionGetOffset(coordSection, numCells + v, &off);CHKERRQ(ierr); 1830 for (d = 0; d < coordDim; ++d) 1831 pointCoords[off+d] = (PetscReal) coords[node*3+d]; 1832 } 1833 ierr = PetscFree(nodeMap);CHKERRQ(ierr); 1834 ierr = VecRestoreArray(coordinates, &pointCoords);CHKERRQ(ierr); 1835 1836 } 1837 1838 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 1839 ierr = VecSetBlockSize(coordinates, coordDim);CHKERRQ(ierr); 1840 ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr); 1841 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 1842 ierr = DMSetPeriodicity(*dm, periodic, NULL, NULL, NULL);CHKERRQ(ierr); 1843 1844 ierr = GmshMeshDestroy(&mesh);CHKERRQ(ierr); 1845 ierr = PetscBTDestroy(&periodicVerts);CHKERRQ(ierr); 1846 ierr = PetscBTDestroy(&periodicCells);CHKERRQ(ierr); 1847 1848 if (highOrder && project) { 1849 PetscFE fe; 1850 const char prefix[] = "dm_plex_gmsh_project_"; 1851 PetscBool continuity = periodic ? PETSC_FALSE : PETSC_TRUE; 1852 PetscDTNodeType nodeType = PETSCDTNODES_GAUSSJACOBI; 1853 1854 if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */ 1855 1856 ierr = GmshCreateFE(comm, prefix, isSimplex, continuity, nodeType, dim, coordDim, order, &fe);CHKERRQ(ierr); 1857 ierr = PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_project_fe_view");CHKERRQ(ierr); 1858 ierr = DMProjectCoordinates(*dm, fe);CHKERRQ(ierr); 1859 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 1860 } 1861 1862 ierr = PetscLogEventEnd(DMPLEX_CreateGmsh,*dm,NULL,NULL,NULL);CHKERRQ(ierr); 1863 PetscFunctionReturn(0); 1864 } 1865