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 188 typedef struct { 189 PetscViewer viewer; 190 int fileFormat; 191 int dataSize; 192 PetscBool binary; 193 PetscBool byteSwap; 194 size_t wlen; 195 void *wbuf; 196 size_t slen; 197 void *sbuf; 198 PetscInt *nbuf; 199 PetscInt nodeStart; 200 PetscInt nodeEnd; 201 PetscInt *nodeMap; 202 } GmshFile; 203 204 static PetscErrorCode GmshBufferGet(GmshFile *gmsh, size_t count, size_t eltsize, void *buf) 205 { 206 size_t size = count * eltsize; 207 PetscErrorCode ierr; 208 209 PetscFunctionBegin; 210 if (gmsh->wlen < size) { 211 ierr = PetscFree(gmsh->wbuf);CHKERRQ(ierr); 212 ierr = PetscMalloc(size, &gmsh->wbuf);CHKERRQ(ierr); 213 gmsh->wlen = size; 214 } 215 *(void**)buf = size ? gmsh->wbuf : NULL; 216 PetscFunctionReturn(0); 217 } 218 219 static PetscErrorCode GmshBufferSizeGet(GmshFile *gmsh, size_t count, void *buf) 220 { 221 size_t dataSize = (size_t)gmsh->dataSize; 222 size_t size = count * dataSize; 223 PetscErrorCode ierr; 224 225 PetscFunctionBegin; 226 if (gmsh->slen < size) { 227 ierr = PetscFree(gmsh->sbuf);CHKERRQ(ierr); 228 ierr = PetscMalloc(size, &gmsh->sbuf);CHKERRQ(ierr); 229 gmsh->slen = size; 230 } 231 *(void**)buf = size ? gmsh->sbuf : NULL; 232 PetscFunctionReturn(0); 233 } 234 235 static PetscErrorCode GmshRead(GmshFile *gmsh, void *buf, PetscInt count, PetscDataType dtype) 236 { 237 PetscErrorCode ierr; 238 PetscFunctionBegin; 239 ierr = PetscViewerRead(gmsh->viewer, buf, count, NULL, dtype);CHKERRQ(ierr); 240 if (gmsh->byteSwap) {ierr = PetscByteSwap(buf, dtype, count);CHKERRQ(ierr);} 241 PetscFunctionReturn(0); 242 } 243 244 static PetscErrorCode GmshReadString(GmshFile *gmsh, char *buf, PetscInt count) 245 { 246 PetscErrorCode ierr; 247 PetscFunctionBegin; 248 ierr = PetscViewerRead(gmsh->viewer, buf, count, NULL, PETSC_STRING);CHKERRQ(ierr); 249 PetscFunctionReturn(0); 250 } 251 252 static PetscErrorCode GmshMatch(PETSC_UNUSED GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN], PetscBool *match) 253 { 254 PetscErrorCode ierr; 255 PetscFunctionBegin; 256 ierr = PetscStrcmp(line, Section, match);CHKERRQ(ierr); 257 PetscFunctionReturn(0); 258 } 259 260 static PetscErrorCode GmshExpect(GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN]) 261 { 262 PetscBool match; 263 PetscErrorCode ierr; 264 265 PetscFunctionBegin; 266 ierr = GmshMatch(gmsh, Section, line, &match);CHKERRQ(ierr); 267 if (!match) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file, expecting %s",Section); 268 PetscFunctionReturn(0); 269 } 270 271 static PetscErrorCode GmshReadSection(GmshFile *gmsh, char line[PETSC_MAX_PATH_LEN]) 272 { 273 PetscBool match; 274 PetscErrorCode ierr; 275 276 PetscFunctionBegin; 277 while (PETSC_TRUE) { 278 ierr = GmshReadString(gmsh, line, 1);CHKERRQ(ierr); 279 ierr = GmshMatch(gmsh, "$Comments", line, &match);CHKERRQ(ierr); 280 if (!match) break; 281 while (PETSC_TRUE) { 282 ierr = GmshReadString(gmsh, line, 1);CHKERRQ(ierr); 283 ierr = GmshMatch(gmsh, "$EndComments", line, &match);CHKERRQ(ierr); 284 if (match) break; 285 } 286 } 287 PetscFunctionReturn(0); 288 } 289 290 static PetscErrorCode GmshReadEndSection(GmshFile *gmsh, const char EndSection[], char line[PETSC_MAX_PATH_LEN]) 291 { 292 PetscErrorCode ierr; 293 PetscFunctionBegin; 294 ierr = GmshReadString(gmsh, line, 1);CHKERRQ(ierr); 295 ierr = GmshExpect(gmsh, EndSection, line);CHKERRQ(ierr); 296 PetscFunctionReturn(0); 297 } 298 299 static PetscErrorCode GmshReadSize(GmshFile *gmsh, PetscInt *buf, PetscInt count) 300 { 301 PetscInt i; 302 size_t dataSize = (size_t)gmsh->dataSize; 303 PetscErrorCode ierr; 304 305 PetscFunctionBegin; 306 if (dataSize == sizeof(PetscInt)) { 307 ierr = GmshRead(gmsh, buf, count, PETSC_INT);CHKERRQ(ierr); 308 } else if (dataSize == sizeof(int)) { 309 int *ibuf = NULL; 310 ierr = GmshBufferSizeGet(gmsh, count, &ibuf);CHKERRQ(ierr); 311 ierr = GmshRead(gmsh, ibuf, count, PETSC_ENUM);CHKERRQ(ierr); 312 for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 313 } else if (dataSize == sizeof(long)) { 314 long *ibuf = NULL; 315 ierr = GmshBufferSizeGet(gmsh, count, &ibuf);CHKERRQ(ierr); 316 ierr = GmshRead(gmsh, ibuf, count, PETSC_LONG);CHKERRQ(ierr); 317 for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 318 } else if (dataSize == sizeof(PetscInt64)) { 319 PetscInt64 *ibuf = NULL; 320 ierr = GmshBufferSizeGet(gmsh, count, &ibuf);CHKERRQ(ierr); 321 ierr = GmshRead(gmsh, ibuf, count, PETSC_INT64);CHKERRQ(ierr); 322 for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 323 } 324 PetscFunctionReturn(0); 325 } 326 327 static PetscErrorCode GmshReadInt(GmshFile *gmsh, int *buf, PetscInt count) 328 { 329 PetscErrorCode ierr; 330 PetscFunctionBegin; 331 ierr = GmshRead(gmsh, buf, count, PETSC_ENUM);CHKERRQ(ierr); 332 PetscFunctionReturn(0); 333 } 334 335 static PetscErrorCode GmshReadDouble(GmshFile *gmsh, double *buf, PetscInt count) 336 { 337 PetscErrorCode ierr; 338 PetscFunctionBegin; 339 ierr = GmshRead(gmsh, buf, count, PETSC_DOUBLE);CHKERRQ(ierr); 340 PetscFunctionReturn(0); 341 } 342 343 typedef struct { 344 PetscInt id; /* Entity ID */ 345 PetscInt dim; /* Dimension */ 346 double bbox[6]; /* Bounding box */ 347 PetscInt numTags; /* Size of tag array */ 348 int tags[4]; /* Tag array */ 349 } GmshEntity; 350 351 typedef struct { 352 GmshEntity *entity[4]; 353 PetscHMapI entityMap[4]; 354 } GmshEntities; 355 356 static PetscErrorCode GmshEntitiesCreate(PetscInt count[4], GmshEntities **entities) 357 { 358 PetscInt dim; 359 PetscErrorCode ierr; 360 361 PetscFunctionBegin; 362 ierr = PetscNew(entities);CHKERRQ(ierr); 363 for (dim = 0; dim < 4; ++dim) { 364 ierr = PetscCalloc1(count[dim], &(*entities)->entity[dim]);CHKERRQ(ierr); 365 ierr = PetscHMapICreate(&(*entities)->entityMap[dim]);CHKERRQ(ierr); 366 } 367 PetscFunctionReturn(0); 368 } 369 370 static PetscErrorCode GmshEntitiesDestroy(GmshEntities **entities) 371 { 372 PetscInt dim; 373 PetscErrorCode ierr; 374 375 PetscFunctionBegin; 376 if (!*entities) PetscFunctionReturn(0); 377 for (dim = 0; dim < 4; ++dim) { 378 ierr = PetscFree((*entities)->entity[dim]);CHKERRQ(ierr); 379 ierr = PetscHMapIDestroy(&(*entities)->entityMap[dim]);CHKERRQ(ierr); 380 } 381 ierr = PetscFree((*entities));CHKERRQ(ierr); 382 PetscFunctionReturn(0); 383 } 384 385 static PetscErrorCode GmshEntitiesAdd(GmshEntities *entities, PetscInt index, PetscInt dim, PetscInt eid, GmshEntity** entity) 386 { 387 PetscErrorCode ierr; 388 389 PetscFunctionBegin; 390 ierr = PetscHMapISet(entities->entityMap[dim], eid, index);CHKERRQ(ierr); 391 entities->entity[dim][index].dim = dim; 392 entities->entity[dim][index].id = eid; 393 if (entity) *entity = &entities->entity[dim][index]; 394 PetscFunctionReturn(0); 395 } 396 397 static PetscErrorCode GmshEntitiesGet(GmshEntities *entities, PetscInt dim, PetscInt eid, GmshEntity** entity) 398 { 399 PetscInt index; 400 PetscErrorCode ierr; 401 402 PetscFunctionBegin; 403 ierr = PetscHMapIGet(entities->entityMap[dim], eid, &index);CHKERRQ(ierr); 404 *entity = &entities->entity[dim][index]; 405 PetscFunctionReturn(0); 406 } 407 408 typedef struct { 409 PetscInt *id; /* Node IDs */ 410 double *xyz; /* Coordinates */ 411 } GmshNodes; 412 413 static PetscErrorCode GmshNodesCreate(PetscInt count, GmshNodes **nodes) 414 { 415 PetscErrorCode ierr; 416 417 PetscFunctionBegin; 418 ierr = PetscNew(nodes);CHKERRQ(ierr); 419 ierr = PetscMalloc1(count*1, &(*nodes)->id);CHKERRQ(ierr); 420 ierr = PetscMalloc1(count*3, &(*nodes)->xyz);CHKERRQ(ierr); 421 PetscFunctionReturn(0); 422 } 423 424 static PetscErrorCode GmshNodesDestroy(GmshNodes **nodes) 425 { 426 PetscErrorCode ierr; 427 PetscFunctionBegin; 428 if (!*nodes) PetscFunctionReturn(0); 429 ierr = PetscFree((*nodes)->id);CHKERRQ(ierr); 430 ierr = PetscFree((*nodes)->xyz);CHKERRQ(ierr); 431 ierr = PetscFree((*nodes));CHKERRQ(ierr); 432 PetscFunctionReturn(0); 433 } 434 435 typedef struct { 436 PetscInt id; /* Element ID */ 437 PetscInt dim; /* Dimension */ 438 PetscInt cellType; /* Cell type */ 439 PetscInt numVerts; /* Size of vertex array */ 440 PetscInt numNodes; /* Size of node array */ 441 PetscInt *nodes; /* Vertex/Node array */ 442 PetscInt numTags; /* Size of tag array */ 443 int tags[4]; /* Tag array */ 444 } GmshElement; 445 446 static PetscErrorCode GmshElementsCreate(PetscInt count, GmshElement **elements) 447 { 448 PetscErrorCode ierr; 449 450 PetscFunctionBegin; 451 ierr = PetscCalloc1(count, elements);CHKERRQ(ierr); 452 PetscFunctionReturn(0); 453 } 454 455 static PetscErrorCode GmshElementsDestroy(GmshElement **elements) 456 { 457 PetscErrorCode ierr; 458 459 PetscFunctionBegin; 460 if (!*elements) PetscFunctionReturn(0); 461 ierr = PetscFree(*elements);CHKERRQ(ierr); 462 PetscFunctionReturn(0); 463 } 464 465 typedef struct { 466 PetscInt dim; 467 PetscInt order; 468 GmshEntities *entities; 469 PetscInt numNodes; 470 GmshNodes *nodelist; 471 PetscInt numElems; 472 GmshElement *elements; 473 PetscInt numVerts; 474 PetscInt numCells; 475 PetscInt *periodMap; 476 PetscInt *vertexMap; 477 PetscSegBuffer segbuf; 478 } GmshMesh; 479 480 static PetscErrorCode GmshMeshCreate(GmshMesh **mesh) 481 { 482 PetscErrorCode ierr; 483 484 PetscFunctionBegin; 485 ierr = PetscNew(mesh);CHKERRQ(ierr); 486 ierr = PetscSegBufferCreate(sizeof(PetscInt), 0, &(*mesh)->segbuf);CHKERRQ(ierr); 487 PetscFunctionReturn(0); 488 } 489 490 static PetscErrorCode GmshMeshDestroy(GmshMesh **mesh) 491 { 492 PetscErrorCode ierr; 493 494 PetscFunctionBegin; 495 if (!*mesh) PetscFunctionReturn(0); 496 ierr = GmshEntitiesDestroy(&(*mesh)->entities);CHKERRQ(ierr); 497 ierr = GmshNodesDestroy(&(*mesh)->nodelist);CHKERRQ(ierr); 498 ierr = GmshElementsDestroy(&(*mesh)->elements);CHKERRQ(ierr); 499 ierr = PetscFree((*mesh)->periodMap);CHKERRQ(ierr); 500 ierr = PetscFree((*mesh)->vertexMap);CHKERRQ(ierr); 501 ierr = PetscSegBufferDestroy(&(*mesh)->segbuf);CHKERRQ(ierr); 502 ierr = PetscFree((*mesh));CHKERRQ(ierr); 503 PetscFunctionReturn(0); 504 } 505 506 static PetscErrorCode GmshReadNodes_v22(GmshFile *gmsh, GmshMesh *mesh) 507 { 508 PetscViewer viewer = gmsh->viewer; 509 PetscBool byteSwap = gmsh->byteSwap; 510 char line[PETSC_MAX_PATH_LEN]; 511 int n, num, nid, snum; 512 GmshNodes *nodes; 513 PetscErrorCode ierr; 514 515 PetscFunctionBegin; 516 ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); 517 snum = sscanf(line, "%d", &num); 518 if (snum != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 519 ierr = GmshNodesCreate(num, &nodes);CHKERRQ(ierr); 520 mesh->numNodes = num; 521 mesh->nodelist = nodes; 522 for (n = 0; n < num; ++n) { 523 double *xyz = nodes->xyz + n*3; 524 ierr = PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM);CHKERRQ(ierr); 525 ierr = PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE);CHKERRQ(ierr); 526 if (byteSwap) {ierr = PetscByteSwap(&nid, PETSC_ENUM, 1);CHKERRQ(ierr);} 527 if (byteSwap) {ierr = PetscByteSwap(xyz, PETSC_DOUBLE, 3);CHKERRQ(ierr);} 528 nodes->id[n] = nid; 529 } 530 PetscFunctionReturn(0); 531 } 532 533 /* Gmsh elements can be of any dimension/co-dimension, so we need to traverse the 534 file contents multiple times to figure out the true number of cells and facets 535 in the given mesh. To make this more efficient we read the file contents only 536 once and store them in memory, while determining the true number of cells. */ 537 static PetscErrorCode GmshReadElements_v22(GmshFile* gmsh, GmshMesh *mesh) 538 { 539 PetscViewer viewer = gmsh->viewer; 540 PetscBool binary = gmsh->binary; 541 PetscBool byteSwap = gmsh->byteSwap; 542 char line[PETSC_MAX_PATH_LEN]; 543 int i, c, p, num, ibuf[1+4+1000], snum; 544 int cellType, numElem, numVerts, numNodes, numTags; 545 GmshElement *elements; 546 PetscInt *nodeMap = gmsh->nodeMap; 547 PetscErrorCode ierr; 548 549 PetscFunctionBegin; 550 ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); 551 snum = sscanf(line, "%d", &num); 552 if (snum != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 553 ierr = GmshElementsCreate(num, &elements);CHKERRQ(ierr); 554 mesh->numElems = num; 555 mesh->elements = elements; 556 for (c = 0; c < num;) { 557 ierr = PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM);CHKERRQ(ierr); 558 if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, 3);CHKERRQ(ierr);} 559 560 cellType = binary ? ibuf[0] : ibuf[1]; 561 numElem = binary ? ibuf[1] : 1; 562 numTags = ibuf[2]; 563 564 ierr = GmshCellTypeCheck(cellType);CHKERRQ(ierr); 565 numVerts = GmshCellMap[cellType].numVerts; 566 numNodes = GmshCellMap[cellType].numNodes; 567 568 for (i = 0; i < numElem; ++i, ++c) { 569 GmshElement *element = elements + c; 570 const int off = binary ? 0 : 1, nint = 1 + numTags + numNodes - off; 571 const int *id = ibuf, *nodes = ibuf + 1 + numTags, *tags = ibuf + 1; 572 ierr = PetscViewerRead(viewer, ibuf+off, nint, NULL, PETSC_ENUM);CHKERRQ(ierr); 573 if (byteSwap) {ierr = PetscByteSwap(ibuf+off, PETSC_ENUM, nint);CHKERRQ(ierr);} 574 element->id = id[0]; 575 element->dim = GmshCellMap[cellType].dim; 576 element->cellType = cellType; 577 element->numVerts = numVerts; 578 element->numNodes = numNodes; 579 element->numTags = PetscMin(numTags, 4); 580 ierr = PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes);CHKERRQ(ierr); 581 for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 582 for (p = 0; p < element->numTags; p++) element->tags[p] = tags[p]; 583 } 584 } 585 PetscFunctionReturn(0); 586 } 587 588 /* 589 $Entities 590 numPoints(unsigned long) numCurves(unsigned long) 591 numSurfaces(unsigned long) numVolumes(unsigned long) 592 // points 593 tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 594 boxMaxX(double) boxMaxY(double) boxMaxZ(double) 595 numPhysicals(unsigned long) phyisicalTag[...](int) 596 ... 597 // curves 598 tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 599 boxMaxX(double) boxMaxY(double) boxMaxZ(double) 600 numPhysicals(unsigned long) physicalTag[...](int) 601 numBREPVert(unsigned long) tagBREPVert[...](int) 602 ... 603 // surfaces 604 tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 605 boxMaxX(double) boxMaxY(double) boxMaxZ(double) 606 numPhysicals(unsigned long) physicalTag[...](int) 607 numBREPCurve(unsigned long) tagBREPCurve[...](int) 608 ... 609 // volumes 610 tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 611 boxMaxX(double) boxMaxY(double) boxMaxZ(double) 612 numPhysicals(unsigned long) physicalTag[...](int) 613 numBREPSurfaces(unsigned long) tagBREPSurfaces[...](int) 614 ... 615 $EndEntities 616 */ 617 static PetscErrorCode GmshReadEntities_v40(GmshFile *gmsh, GmshMesh *mesh) 618 { 619 PetscViewer viewer = gmsh->viewer; 620 PetscBool byteSwap = gmsh->byteSwap; 621 long index, num, lbuf[4]; 622 int dim, eid, numTags, *ibuf, t; 623 PetscInt count[4], i; 624 GmshEntity *entity = NULL; 625 PetscErrorCode ierr; 626 627 PetscFunctionBegin; 628 ierr = PetscViewerRead(viewer, lbuf, 4, NULL, PETSC_LONG);CHKERRQ(ierr); 629 if (byteSwap) {ierr = PetscByteSwap(lbuf, PETSC_LONG, 4);CHKERRQ(ierr);} 630 for (i = 0; i < 4; ++i) count[i] = lbuf[i]; 631 ierr = GmshEntitiesCreate(count, &mesh->entities);CHKERRQ(ierr); 632 for (dim = 0; dim < 4; ++dim) { 633 for (index = 0; index < count[dim]; ++index) { 634 ierr = PetscViewerRead(viewer, &eid, 1, NULL, PETSC_ENUM);CHKERRQ(ierr); 635 if (byteSwap) {ierr = PetscByteSwap(&eid, PETSC_ENUM, 1);CHKERRQ(ierr);} 636 ierr = GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity);CHKERRQ(ierr); 637 ierr = PetscViewerRead(viewer, entity->bbox, 6, NULL, PETSC_DOUBLE);CHKERRQ(ierr); 638 if (byteSwap) {ierr = PetscByteSwap(entity->bbox, PETSC_DOUBLE, 6);CHKERRQ(ierr);} 639 ierr = PetscViewerRead(viewer, &num, 1, NULL, PETSC_LONG);CHKERRQ(ierr); 640 if (byteSwap) {ierr = PetscByteSwap(&num, PETSC_LONG, 1);CHKERRQ(ierr);} 641 ierr = GmshBufferGet(gmsh, num, sizeof(int), &ibuf);CHKERRQ(ierr); 642 ierr = PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM);CHKERRQ(ierr); 643 if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, num);CHKERRQ(ierr);} 644 entity->numTags = numTags = (int) PetscMin(num, 4); 645 for (t = 0; t < numTags; ++t) entity->tags[t] = ibuf[t]; 646 if (dim == 0) continue; 647 ierr = PetscViewerRead(viewer, &num, 1, NULL, PETSC_LONG);CHKERRQ(ierr); 648 if (byteSwap) {ierr = PetscByteSwap(&num, PETSC_LONG, 1);CHKERRQ(ierr);} 649 ierr = GmshBufferGet(gmsh, num, sizeof(int), &ibuf);CHKERRQ(ierr); 650 ierr = PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM);CHKERRQ(ierr); 651 if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, num);CHKERRQ(ierr);} 652 } 653 } 654 PetscFunctionReturn(0); 655 } 656 657 /* 658 $Nodes 659 numEntityBlocks(unsigned long) numNodes(unsigned long) 660 tagEntity(int) dimEntity(int) typeNode(int) numNodes(unsigned long) 661 tag(int) x(double) y(double) z(double) 662 ... 663 ... 664 $EndNodes 665 */ 666 static PetscErrorCode GmshReadNodes_v40(GmshFile *gmsh, GmshMesh *mesh) 667 { 668 PetscViewer viewer = gmsh->viewer; 669 PetscBool byteSwap = gmsh->byteSwap; 670 long block, node, n, numEntityBlocks, numTotalNodes, numNodes; 671 int info[3], nid; 672 GmshNodes *nodes; 673 PetscErrorCode ierr; 674 675 PetscFunctionBegin; 676 ierr = PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG);CHKERRQ(ierr); 677 if (byteSwap) {ierr = PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1);CHKERRQ(ierr);} 678 ierr = PetscViewerRead(viewer, &numTotalNodes, 1, NULL, PETSC_LONG);CHKERRQ(ierr); 679 if (byteSwap) {ierr = PetscByteSwap(&numTotalNodes, PETSC_LONG, 1);CHKERRQ(ierr);} 680 ierr = GmshNodesCreate(numTotalNodes, &nodes);CHKERRQ(ierr); 681 mesh->numNodes = numTotalNodes; 682 mesh->nodelist = nodes; 683 for (n = 0, block = 0; block < numEntityBlocks; ++block) { 684 ierr = PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM);CHKERRQ(ierr); 685 ierr = PetscViewerRead(viewer, &numNodes, 1, NULL, PETSC_LONG);CHKERRQ(ierr); 686 if (byteSwap) {ierr = PetscByteSwap(&numNodes, PETSC_LONG, 1);CHKERRQ(ierr);} 687 if (gmsh->binary) { 688 size_t nbytes = sizeof(int) + 3*sizeof(double); 689 char *cbuf = NULL; /* dummy value to prevent warning from compiler about possible unitilized value */ 690 ierr = GmshBufferGet(gmsh, numNodes, nbytes, &cbuf);CHKERRQ(ierr); 691 ierr = PetscViewerRead(viewer, cbuf, numNodes*nbytes, NULL, PETSC_CHAR);CHKERRQ(ierr); 692 for (node = 0; node < numNodes; ++node, ++n) { 693 char *cnid = cbuf + node*nbytes, *cxyz = cnid + sizeof(int); 694 double *xyz = nodes->xyz + n*3; 695 if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(cnid, PETSC_ENUM, 1);CHKERRQ(ierr);} 696 if (!PetscBinaryBigEndian()) {ierr = PetscByteSwap(cxyz, PETSC_DOUBLE, 3);CHKERRQ(ierr);} 697 ierr = PetscMemcpy(&nid, cnid, sizeof(int));CHKERRQ(ierr); 698 ierr = PetscMemcpy(xyz, cxyz, 3*sizeof(double));CHKERRQ(ierr); 699 if (byteSwap) {ierr = PetscByteSwap(&nid, PETSC_ENUM, 1);CHKERRQ(ierr);} 700 if (byteSwap) {ierr = PetscByteSwap(xyz, PETSC_DOUBLE, 3);CHKERRQ(ierr);} 701 nodes->id[n] = nid; 702 } 703 } else { 704 for (node = 0; node < numNodes; ++node, ++n) { 705 double *xyz = nodes->xyz + n*3; 706 ierr = PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM);CHKERRQ(ierr); 707 ierr = PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE);CHKERRQ(ierr); 708 if (byteSwap) {ierr = PetscByteSwap(&nid, PETSC_ENUM, 1);CHKERRQ(ierr);} 709 if (byteSwap) {ierr = PetscByteSwap(xyz, PETSC_DOUBLE, 3);CHKERRQ(ierr);} 710 nodes->id[n] = nid; 711 } 712 } 713 } 714 PetscFunctionReturn(0); 715 } 716 717 /* 718 $Elements 719 numEntityBlocks(unsigned long) numElements(unsigned long) 720 tagEntity(int) dimEntity(int) typeEle(int) numElements(unsigned long) 721 tag(int) numVert[...](int) 722 ... 723 ... 724 $EndElements 725 */ 726 static PetscErrorCode GmshReadElements_v40(GmshFile *gmsh, GmshMesh *mesh) 727 { 728 PetscViewer viewer = gmsh->viewer; 729 PetscBool byteSwap = gmsh->byteSwap; 730 long c, block, numEntityBlocks, numTotalElements, elem, numElements; 731 int p, info[3], *ibuf = NULL; 732 int eid, dim, cellType, numVerts, numNodes, numTags; 733 GmshEntity *entity = NULL; 734 GmshElement *elements; 735 PetscInt *nodeMap = gmsh->nodeMap; 736 PetscErrorCode ierr; 737 738 PetscFunctionBegin; 739 ierr = PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG);CHKERRQ(ierr); 740 if (byteSwap) {ierr = PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1);CHKERRQ(ierr);} 741 ierr = PetscViewerRead(viewer, &numTotalElements, 1, NULL, PETSC_LONG);CHKERRQ(ierr); 742 if (byteSwap) {ierr = PetscByteSwap(&numTotalElements, PETSC_LONG, 1);CHKERRQ(ierr);} 743 ierr = GmshElementsCreate(numTotalElements, &elements);CHKERRQ(ierr); 744 mesh->numElems = numTotalElements; 745 mesh->elements = elements; 746 for (c = 0, block = 0; block < numEntityBlocks; ++block) { 747 ierr = PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM);CHKERRQ(ierr); 748 if (byteSwap) {ierr = PetscByteSwap(info, PETSC_ENUM, 3);CHKERRQ(ierr);} 749 eid = info[0]; dim = info[1]; cellType = info[2]; 750 ierr = GmshEntitiesGet(mesh->entities, dim, eid, &entity);CHKERRQ(ierr); 751 ierr = GmshCellTypeCheck(cellType);CHKERRQ(ierr); 752 numVerts = GmshCellMap[cellType].numVerts; 753 numNodes = GmshCellMap[cellType].numNodes; 754 numTags = entity->numTags; 755 ierr = PetscViewerRead(viewer, &numElements, 1, NULL, PETSC_LONG);CHKERRQ(ierr); 756 if (byteSwap) {ierr = PetscByteSwap(&numElements, PETSC_LONG, 1);CHKERRQ(ierr);} 757 ierr = GmshBufferGet(gmsh, (1+numNodes)*numElements, sizeof(int), &ibuf);CHKERRQ(ierr); 758 ierr = PetscViewerRead(viewer, ibuf, (1+numNodes)*numElements, NULL, PETSC_ENUM);CHKERRQ(ierr); 759 if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, (1+numNodes)*numElements);CHKERRQ(ierr);} 760 for (elem = 0; elem < numElements; ++elem, ++c) { 761 GmshElement *element = elements + c; 762 const int *id = ibuf + elem*(1+numNodes), *nodes = id + 1; 763 element->id = id[0]; 764 element->dim = dim; 765 element->cellType = cellType; 766 element->numVerts = numVerts; 767 element->numNodes = numNodes; 768 element->numTags = numTags; 769 ierr = PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes);CHKERRQ(ierr); 770 for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 771 for (p = 0; p < element->numTags; p++) element->tags[p] = entity->tags[p]; 772 } 773 } 774 PetscFunctionReturn(0); 775 } 776 777 static PetscErrorCode GmshReadPeriodic_v40(GmshFile *gmsh, PetscInt periodicMap[]) 778 { 779 PetscViewer viewer = gmsh->viewer; 780 int fileFormat = gmsh->fileFormat; 781 PetscBool binary = gmsh->binary; 782 PetscBool byteSwap = gmsh->byteSwap; 783 int numPeriodic, snum, i; 784 char line[PETSC_MAX_PATH_LEN]; 785 PetscInt *nodeMap = gmsh->nodeMap; 786 PetscErrorCode ierr; 787 788 PetscFunctionBegin; 789 if (fileFormat == 22 || !binary) { 790 ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); 791 snum = sscanf(line, "%d", &numPeriodic); 792 if (snum != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 793 } else { 794 ierr = PetscViewerRead(viewer, &numPeriodic, 1, NULL, PETSC_ENUM);CHKERRQ(ierr); 795 if (byteSwap) {ierr = PetscByteSwap(&numPeriodic, PETSC_ENUM, 1);CHKERRQ(ierr);} 796 } 797 for (i = 0; i < numPeriodic; i++) { 798 int ibuf[3], slaveDim = -1, slaveTag = -1, masterTag = -1, slaveNode, masterNode; 799 long j, nNodes; 800 double affine[16]; 801 802 if (fileFormat == 22 || !binary) { 803 ierr = PetscViewerRead(viewer, line, 3, NULL, PETSC_STRING);CHKERRQ(ierr); 804 snum = sscanf(line, "%d %d %d", &slaveDim, &slaveTag, &masterTag); 805 if (snum != 3) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 806 } else { 807 ierr = PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM);CHKERRQ(ierr); 808 if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, 3);CHKERRQ(ierr);} 809 slaveDim = ibuf[0]; slaveTag = ibuf[1]; masterTag = ibuf[2]; 810 } 811 (void)slaveDim; (void)slaveTag; (void)masterTag; /* unused */ 812 813 if (fileFormat == 22 || !binary) { 814 ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); 815 snum = sscanf(line, "%ld", &nNodes); 816 if (snum != 1) { /* discard transformation and try again */ 817 ierr = PetscViewerRead(viewer, line, -PETSC_MAX_PATH_LEN, NULL, PETSC_STRING);CHKERRQ(ierr); 818 ierr = PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING);CHKERRQ(ierr); 819 snum = sscanf(line, "%ld", &nNodes); 820 if (snum != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 821 } 822 } else { 823 ierr = PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG);CHKERRQ(ierr); 824 if (byteSwap) {ierr = PetscByteSwap(&nNodes, PETSC_LONG, 1);CHKERRQ(ierr);} 825 if (nNodes == -1) { /* discard transformation and try again */ 826 ierr = PetscViewerRead(viewer, affine, 16, NULL, PETSC_DOUBLE);CHKERRQ(ierr); 827 ierr = PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG);CHKERRQ(ierr); 828 if (byteSwap) {ierr = PetscByteSwap(&nNodes, PETSC_LONG, 1);CHKERRQ(ierr);} 829 } 830 } 831 832 for (j = 0; j < nNodes; j++) { 833 if (fileFormat == 22 || !binary) { 834 ierr = PetscViewerRead(viewer, line, 2, NULL, PETSC_STRING);CHKERRQ(ierr); 835 snum = sscanf(line, "%d %d", &slaveNode, &masterNode); 836 if (snum != 2) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 837 } else { 838 ierr = PetscViewerRead(viewer, ibuf, 2, NULL, PETSC_ENUM);CHKERRQ(ierr); 839 if (byteSwap) {ierr = PetscByteSwap(ibuf, PETSC_ENUM, 2);CHKERRQ(ierr);} 840 slaveNode = ibuf[0]; masterNode = ibuf[1]; 841 } 842 slaveNode = (int) nodeMap[slaveNode]; 843 masterNode = (int) nodeMap[masterNode]; 844 periodicMap[slaveNode] = masterNode; 845 } 846 } 847 PetscFunctionReturn(0); 848 } 849 850 /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 851 $Entities 852 numPoints(size_t) numCurves(size_t) 853 numSurfaces(size_t) numVolumes(size_t) 854 pointTag(int) X(double) Y(double) Z(double) 855 numPhysicalTags(size_t) physicalTag(int) ... 856 ... 857 curveTag(int) minX(double) minY(double) minZ(double) 858 maxX(double) maxY(double) maxZ(double) 859 numPhysicalTags(size_t) physicalTag(int) ... 860 numBoundingPoints(size_t) pointTag(int) ... 861 ... 862 surfaceTag(int) minX(double) minY(double) minZ(double) 863 maxX(double) maxY(double) maxZ(double) 864 numPhysicalTags(size_t) physicalTag(int) ... 865 numBoundingCurves(size_t) curveTag(int) ... 866 ... 867 volumeTag(int) minX(double) minY(double) minZ(double) 868 maxX(double) maxY(double) maxZ(double) 869 numPhysicalTags(size_t) physicalTag(int) ... 870 numBoundngSurfaces(size_t) surfaceTag(int) ... 871 ... 872 $EndEntities 873 */ 874 static PetscErrorCode GmshReadEntities_v41(GmshFile *gmsh, GmshMesh *mesh) 875 { 876 PetscInt count[4], index, numTags, i; 877 int dim, eid, *tags = NULL; 878 GmshEntity *entity = NULL; 879 PetscErrorCode ierr; 880 881 PetscFunctionBegin; 882 ierr = GmshReadSize(gmsh, count, 4);CHKERRQ(ierr); 883 ierr = GmshEntitiesCreate(count, &mesh->entities);CHKERRQ(ierr); 884 for (dim = 0; dim < 4; ++dim) { 885 for (index = 0; index < count[dim]; ++index) { 886 ierr = GmshReadInt(gmsh, &eid, 1);CHKERRQ(ierr); 887 ierr = GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity);CHKERRQ(ierr); 888 ierr = GmshReadDouble(gmsh, entity->bbox, (dim == 0) ? 3 : 6);CHKERRQ(ierr); 889 ierr = GmshReadSize(gmsh, &numTags, 1);CHKERRQ(ierr); 890 ierr = GmshBufferGet(gmsh, numTags, sizeof(int), &tags);CHKERRQ(ierr); 891 ierr = GmshReadInt(gmsh, tags, numTags);CHKERRQ(ierr); 892 entity->numTags = PetscMin(numTags, 4); 893 for (i = 0; i < entity->numTags; ++i) entity->tags[i] = tags[i]; 894 if (dim == 0) continue; 895 ierr = GmshReadSize(gmsh, &numTags, 1);CHKERRQ(ierr); 896 ierr = GmshBufferGet(gmsh, numTags, sizeof(int), &tags);CHKERRQ(ierr); 897 ierr = GmshReadInt(gmsh, tags, numTags);CHKERRQ(ierr); 898 } 899 } 900 PetscFunctionReturn(0); 901 } 902 903 /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 904 $Nodes 905 numEntityBlocks(size_t) numNodes(size_t) 906 minNodeTag(size_t) maxNodeTag(size_t) 907 entityDim(int) entityTag(int) parametric(int; 0 or 1) numNodesBlock(size_t) 908 nodeTag(size_t) 909 ... 910 x(double) y(double) z(double) 911 < u(double; if parametric and entityDim = 1 or entityDim = 2) > 912 < v(double; if parametric and entityDim = 2) > 913 ... 914 ... 915 $EndNodes 916 */ 917 static PetscErrorCode GmshReadNodes_v41(GmshFile *gmsh, GmshMesh *mesh) 918 { 919 int info[3]; 920 PetscInt sizes[4], numEntityBlocks, numNodes, numNodesBlock = 0, block, node; 921 GmshNodes *nodes; 922 PetscErrorCode ierr; 923 924 PetscFunctionBegin; 925 ierr = GmshReadSize(gmsh, sizes, 4);CHKERRQ(ierr); 926 numEntityBlocks = sizes[0]; numNodes = sizes[1]; 927 ierr = GmshNodesCreate(numNodes, &nodes);CHKERRQ(ierr); 928 mesh->numNodes = numNodes; 929 mesh->nodelist = nodes; 930 for (block = 0, node = 0; block < numEntityBlocks; ++block, node += numNodesBlock) { 931 ierr = GmshReadInt(gmsh, info, 3);CHKERRQ(ierr); 932 if (info[2] != 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Parametric coordinates not supported"); 933 ierr = GmshReadSize(gmsh, &numNodesBlock, 1);CHKERRQ(ierr); 934 ierr = GmshReadSize(gmsh, nodes->id+node, numNodesBlock);CHKERRQ(ierr); 935 ierr = GmshReadDouble(gmsh, nodes->xyz+node*3, numNodesBlock*3);CHKERRQ(ierr); 936 } 937 gmsh->nodeStart = sizes[2]; 938 gmsh->nodeEnd = sizes[3]+1; 939 PetscFunctionReturn(0); 940 } 941 942 /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 943 $Elements 944 numEntityBlocks(size_t) numElements(size_t) 945 minElementTag(size_t) maxElementTag(size_t) 946 entityDim(int) entityTag(int) elementType(int; see below) numElementsBlock(size_t) 947 elementTag(size_t) nodeTag(size_t) ... 948 ... 949 ... 950 $EndElements 951 */ 952 static PetscErrorCode GmshReadElements_v41(GmshFile *gmsh, GmshMesh *mesh) 953 { 954 int info[3], eid, dim, cellType; 955 PetscInt sizes[4], *ibuf = NULL, numEntityBlocks, numElements, numBlockElements, numVerts, numNodes, numTags, block, elem, c, p; 956 GmshEntity *entity = NULL; 957 GmshElement *elements; 958 PetscInt *nodeMap = gmsh->nodeMap; 959 PetscErrorCode ierr; 960 961 PetscFunctionBegin; 962 ierr = GmshReadSize(gmsh, sizes, 4);CHKERRQ(ierr); 963 numEntityBlocks = sizes[0]; numElements = sizes[1]; 964 ierr = GmshElementsCreate(numElements, &elements);CHKERRQ(ierr); 965 mesh->numElems = numElements; 966 mesh->elements = elements; 967 for (c = 0, block = 0; block < numEntityBlocks; ++block) { 968 ierr = GmshReadInt(gmsh, info, 3);CHKERRQ(ierr); 969 dim = info[0]; eid = info[1]; cellType = info[2]; 970 ierr = GmshEntitiesGet(mesh->entities, dim, eid, &entity);CHKERRQ(ierr); 971 ierr = GmshCellTypeCheck(cellType);CHKERRQ(ierr); 972 numVerts = GmshCellMap[cellType].numVerts; 973 numNodes = GmshCellMap[cellType].numNodes; 974 numTags = entity->numTags; 975 ierr = GmshReadSize(gmsh, &numBlockElements, 1);CHKERRQ(ierr); 976 ierr = GmshBufferGet(gmsh, (1+numNodes)*numBlockElements, sizeof(PetscInt), &ibuf);CHKERRQ(ierr); 977 ierr = GmshReadSize(gmsh, ibuf, (1+numNodes)*numBlockElements);CHKERRQ(ierr); 978 for (elem = 0; elem < numBlockElements; ++elem, ++c) { 979 GmshElement *element = elements + c; 980 const PetscInt *id = ibuf + elem*(1+numNodes), *nodes = id + 1; 981 element->id = id[0]; 982 element->dim = dim; 983 element->cellType = cellType; 984 element->numVerts = numVerts; 985 element->numNodes = numNodes; 986 element->numTags = numTags; 987 ierr = PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes);CHKERRQ(ierr); 988 for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 989 for (p = 0; p < element->numTags; p++) element->tags[p] = entity->tags[p]; 990 } 991 } 992 PetscFunctionReturn(0); 993 } 994 995 /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 996 $Periodic 997 numPeriodicLinks(size_t) 998 entityDim(int) entityTag(int) entityTagMaster(int) 999 numAffine(size_t) value(double) ... 1000 numCorrespondingNodes(size_t) 1001 nodeTag(size_t) nodeTagMaster(size_t) 1002 ... 1003 ... 1004 $EndPeriodic 1005 */ 1006 static PetscErrorCode GmshReadPeriodic_v41(GmshFile *gmsh, PetscInt periodicMap[]) 1007 { 1008 int info[3]; 1009 double dbuf[16]; 1010 PetscInt numPeriodicLinks, numAffine, numCorrespondingNodes, *nodeTags = NULL, link, node; 1011 PetscInt *nodeMap = gmsh->nodeMap; 1012 PetscErrorCode ierr; 1013 1014 PetscFunctionBegin; 1015 ierr = GmshReadSize(gmsh, &numPeriodicLinks, 1);CHKERRQ(ierr); 1016 for (link = 0; link < numPeriodicLinks; ++link) { 1017 ierr = GmshReadInt(gmsh, info, 3);CHKERRQ(ierr); 1018 ierr = GmshReadSize(gmsh, &numAffine, 1);CHKERRQ(ierr); 1019 ierr = GmshReadDouble(gmsh, dbuf, numAffine);CHKERRQ(ierr); 1020 ierr = GmshReadSize(gmsh, &numCorrespondingNodes, 1);CHKERRQ(ierr); 1021 ierr = GmshBufferGet(gmsh, numCorrespondingNodes, sizeof(PetscInt), &nodeTags);CHKERRQ(ierr); 1022 ierr = GmshReadSize(gmsh, nodeTags, numCorrespondingNodes*2);CHKERRQ(ierr); 1023 for (node = 0; node < numCorrespondingNodes; ++node) { 1024 PetscInt slaveNode = nodeMap[nodeTags[node*2+0]]; 1025 PetscInt masterNode = nodeMap[nodeTags[node*2+1]]; 1026 periodicMap[slaveNode] = masterNode; 1027 } 1028 } 1029 PetscFunctionReturn(0); 1030 } 1031 1032 /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 1033 $MeshFormat // same as MSH version 2 1034 version(ASCII double; currently 4.1) 1035 file-type(ASCII int; 0 for ASCII mode, 1 for binary mode) 1036 data-size(ASCII int; sizeof(size_t)) 1037 < int with value one; only in binary mode, to detect endianness > 1038 $EndMeshFormat 1039 */ 1040 static PetscErrorCode GmshReadMeshFormat(GmshFile *gmsh) 1041 { 1042 char line[PETSC_MAX_PATH_LEN]; 1043 int snum, fileType, fileFormat, dataSize, checkEndian; 1044 float version; 1045 PetscErrorCode ierr; 1046 1047 PetscFunctionBegin; 1048 ierr = GmshReadString(gmsh, line, 3);CHKERRQ(ierr); 1049 snum = sscanf(line, "%f %d %d", &version, &fileType, &dataSize); 1050 if (snum != 3) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line); 1051 if (version < 2.2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version); 1052 if ((int)version == 3) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version); 1053 if (version > 4.1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version); 1054 if (gmsh->binary && !fileType) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is binary but Gmsh file is ASCII"); 1055 if (!gmsh->binary && fileType) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is ASCII but Gmsh file is binary"); 1056 fileFormat = (int)(version*10); /* XXX Should use (int)roundf(version*10) ? */ 1057 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); 1058 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); 1059 gmsh->fileFormat = fileFormat; 1060 gmsh->dataSize = dataSize; 1061 gmsh->byteSwap = PETSC_FALSE; 1062 if (gmsh->binary) { 1063 ierr = GmshReadInt(gmsh, &checkEndian, 1);CHKERRQ(ierr); 1064 if (checkEndian != 1) { 1065 ierr = PetscByteSwap(&checkEndian, PETSC_ENUM, 1);CHKERRQ(ierr); 1066 if (checkEndian != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to detect endianness in Gmsh file header: %s", line); 1067 gmsh->byteSwap = PETSC_TRUE; 1068 } 1069 } 1070 PetscFunctionReturn(0); 1071 } 1072 1073 /* 1074 PhysicalNames 1075 numPhysicalNames(ASCII int) 1076 dimension(ASCII int) physicalTag(ASCII int) "name"(127 characters max) 1077 ... 1078 $EndPhysicalNames 1079 */ 1080 static PetscErrorCode GmshReadPhysicalNames(GmshFile *gmsh) 1081 { 1082 char line[PETSC_MAX_PATH_LEN], name[128+2], *p, *q; 1083 int snum, numRegions, region, dim, tag; 1084 PetscErrorCode ierr; 1085 1086 PetscFunctionBegin; 1087 ierr = GmshReadString(gmsh, line, 1);CHKERRQ(ierr); 1088 snum = sscanf(line, "%d", &numRegions); 1089 if (snum != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 1090 for (region = 0; region < numRegions; ++region) { 1091 ierr = GmshReadString(gmsh, line, 2);CHKERRQ(ierr); 1092 snum = sscanf(line, "%d %d", &dim, &tag); 1093 if (snum != 2) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 1094 ierr = GmshReadString(gmsh, line, -(PetscInt)sizeof(line));CHKERRQ(ierr); 1095 ierr = PetscStrchr(line, '"', &p);CHKERRQ(ierr); 1096 if (!p) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 1097 ierr = PetscStrrchr(line, '"', &q);CHKERRQ(ierr); 1098 if (q == p) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 1099 ierr = PetscStrncpy(name, p+1, (size_t)(q-p-1));CHKERRQ(ierr); 1100 } 1101 PetscFunctionReturn(0); 1102 } 1103 1104 static PetscErrorCode GmshReadEntities(GmshFile *gmsh, GmshMesh *mesh) 1105 { 1106 PetscErrorCode ierr; 1107 1108 PetscFunctionBegin; 1109 switch (gmsh->fileFormat) { 1110 case 41: ierr = GmshReadEntities_v41(gmsh, mesh);CHKERRQ(ierr); break; 1111 default: ierr = GmshReadEntities_v40(gmsh, mesh);CHKERRQ(ierr); break; 1112 } 1113 PetscFunctionReturn(0); 1114 } 1115 1116 static PetscErrorCode GmshReadNodes(GmshFile *gmsh, GmshMesh *mesh) 1117 { 1118 PetscErrorCode ierr; 1119 1120 PetscFunctionBegin; 1121 switch (gmsh->fileFormat) { 1122 case 41: ierr = GmshReadNodes_v41(gmsh, mesh);CHKERRQ(ierr); break; 1123 case 40: ierr = GmshReadNodes_v40(gmsh, mesh);CHKERRQ(ierr); break; 1124 default: ierr = GmshReadNodes_v22(gmsh, mesh);CHKERRQ(ierr); break; 1125 } 1126 1127 { /* Gmsh v2.2/v4.0 does not provide min/max node tags */ 1128 if (mesh->numNodes > 0 && gmsh->nodeEnd >= gmsh->nodeStart) { 1129 PetscInt tagMin = PETSC_MAX_INT, tagMax = PETSC_MIN_INT, n; 1130 GmshNodes *nodes = mesh->nodelist; 1131 for (n = 0; n < mesh->numNodes; ++n) { 1132 const PetscInt tag = nodes->id[n]; 1133 tagMin = PetscMin(tag, tagMin); 1134 tagMax = PetscMax(tag, tagMax); 1135 } 1136 gmsh->nodeStart = tagMin; 1137 gmsh->nodeEnd = tagMax+1; 1138 } 1139 } 1140 1141 { /* Support for sparse node tags */ 1142 PetscInt n, t; 1143 GmshNodes *nodes = mesh->nodelist; 1144 ierr = PetscMalloc1(gmsh->nodeEnd - gmsh->nodeStart, &gmsh->nbuf);CHKERRQ(ierr); 1145 for (t = 0; t < gmsh->nodeEnd - gmsh->nodeStart; ++t) gmsh->nbuf[t] = PETSC_MIN_INT; 1146 gmsh->nodeMap = gmsh->nbuf - gmsh->nodeStart; 1147 for (n = 0; n < mesh->numNodes; ++n) { 1148 const PetscInt tag = nodes->id[n]; 1149 if (gmsh->nodeMap[tag] >= 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Repeated node tag %D", tag); 1150 gmsh->nodeMap[tag] = n; 1151 } 1152 } 1153 PetscFunctionReturn(0); 1154 } 1155 1156 static PetscErrorCode GmshReadElements(GmshFile *gmsh, GmshMesh *mesh) 1157 { 1158 PetscErrorCode ierr; 1159 1160 PetscFunctionBegin; 1161 switch (gmsh->fileFormat) { 1162 case 41: ierr = GmshReadElements_v41(gmsh, mesh);CHKERRQ(ierr); break; 1163 case 40: ierr = GmshReadElements_v40(gmsh, mesh);CHKERRQ(ierr); break; 1164 default: ierr = GmshReadElements_v22(gmsh, mesh);CHKERRQ(ierr); break; 1165 } 1166 1167 { /* Reorder elements by codimension and polytope type */ 1168 PetscInt ne = mesh->numElems; 1169 GmshElement *elements = mesh->elements; 1170 PetscInt keymap[GMSH_NUM_POLYTOPES], nk = 0; 1171 PetscInt offset[GMSH_NUM_POLYTOPES+1], e, k; 1172 1173 for (k = 0; k < GMSH_NUM_POLYTOPES; ++k) keymap[k] = PETSC_MIN_INT; 1174 ierr = PetscMemzero(offset,sizeof(offset));CHKERRQ(ierr); 1175 1176 keymap[GMSH_TET] = nk++; 1177 keymap[GMSH_HEX] = nk++; 1178 keymap[GMSH_PRI] = nk++; 1179 keymap[GMSH_PYR] = nk++; 1180 keymap[GMSH_TRI] = nk++; 1181 keymap[GMSH_QUA] = nk++; 1182 keymap[GMSH_SEG] = nk++; 1183 keymap[GMSH_VTX] = nk++; 1184 1185 ierr = GmshElementsCreate(mesh->numElems, &mesh->elements);CHKERRQ(ierr); 1186 #define key(eid) keymap[GmshCellMap[elements[(eid)].cellType].polytope] 1187 for (e = 0; e < ne; ++e) offset[1+key(e)]++; 1188 for (k = 1; k < nk; ++k) offset[k] += offset[k-1]; 1189 for (e = 0; e < ne; ++e) mesh->elements[offset[key(e)]++] = elements[e]; 1190 #undef key 1191 ierr = GmshElementsDestroy(&elements);CHKERRQ(ierr); 1192 } 1193 1194 { /* Mesh dimension and order */ 1195 GmshElement *elem = mesh->numElems ? mesh->elements : NULL; 1196 mesh->dim = elem ? GmshCellMap[elem->cellType].dim : 0; 1197 mesh->order = elem ? GmshCellMap[elem->cellType].order : 0; 1198 } 1199 1200 { 1201 PetscBT vtx; 1202 PetscInt dim = mesh->dim, e, n, v; 1203 1204 ierr = PetscBTCreate(mesh->numNodes, &vtx);CHKERRQ(ierr); 1205 1206 /* Compute number of cells and set of vertices */ 1207 mesh->numCells = 0; 1208 for (e = 0; e < mesh->numElems; ++e) { 1209 GmshElement *elem = mesh->elements + e; 1210 if (elem->dim == dim && dim > 0) mesh->numCells++; 1211 for (v = 0; v < elem->numVerts; v++) { 1212 ierr = PetscBTSet(vtx, elem->nodes[v]);CHKERRQ(ierr); 1213 } 1214 } 1215 1216 /* Compute numbering for vertices */ 1217 mesh->numVerts = 0; 1218 ierr = PetscMalloc1(mesh->numNodes, &mesh->vertexMap);CHKERRQ(ierr); 1219 for (n = 0; n < mesh->numNodes; ++n) 1220 mesh->vertexMap[n] = PetscBTLookup(vtx, n) ? mesh->numVerts++ : PETSC_MIN_INT; 1221 1222 ierr = PetscBTDestroy(&vtx);CHKERRQ(ierr); 1223 } 1224 PetscFunctionReturn(0); 1225 } 1226 1227 static PetscErrorCode GmshReadPeriodic(GmshFile *gmsh, GmshMesh *mesh) 1228 { 1229 PetscInt n; 1230 PetscErrorCode ierr; 1231 1232 PetscFunctionBegin; 1233 ierr = PetscMalloc1(mesh->numNodes, &mesh->periodMap);CHKERRQ(ierr); 1234 for (n = 0; n < mesh->numNodes; ++n) mesh->periodMap[n] = n; 1235 switch (gmsh->fileFormat) { 1236 case 41: ierr = GmshReadPeriodic_v41(gmsh, mesh->periodMap);CHKERRQ(ierr); break; 1237 default: ierr = GmshReadPeriodic_v40(gmsh, mesh->periodMap);CHKERRQ(ierr); break; 1238 } 1239 1240 /* Find canonical master nodes */ 1241 for (n = 0; n < mesh->numNodes; ++n) 1242 while (mesh->periodMap[n] != mesh->periodMap[mesh->periodMap[n]]) 1243 mesh->periodMap[n] = mesh->periodMap[mesh->periodMap[n]]; 1244 1245 /* Renumber vertices (filter out slaves) */ 1246 mesh->numVerts = 0; 1247 for (n = 0; n < mesh->numNodes; ++n) 1248 if (mesh->vertexMap[n] >= 0) /* is vertex */ 1249 if (mesh->periodMap[n] == n) /* is master */ 1250 mesh->vertexMap[n] = mesh->numVerts++; 1251 for (n = 0; n < mesh->numNodes; ++n) 1252 if (mesh->vertexMap[n] >= 0) /* is vertex */ 1253 if (mesh->periodMap[n] != n) /* is slave */ 1254 mesh->vertexMap[n] = mesh->vertexMap[mesh->periodMap[n]]; 1255 PetscFunctionReturn(0); 1256 } 1257 1258 #define DM_POLYTOPE_VERTEX DM_POLYTOPE_POINT 1259 #define DM_POLYTOPE_PYRAMID DM_POLYTOPE_UNKNOWN 1260 static const DMPolytopeType DMPolytopeMap[] = { 1261 /* GMSH_VTX */ DM_POLYTOPE_VERTEX, 1262 /* GMSH_SEG */ DM_POLYTOPE_SEGMENT, 1263 /* GMSH_TRI */ DM_POLYTOPE_TRIANGLE, 1264 /* GMSH_QUA */ DM_POLYTOPE_QUADRILATERAL, 1265 /* GMSH_TET */ DM_POLYTOPE_TETRAHEDRON, 1266 /* GMSH_HEX */ DM_POLYTOPE_HEXAHEDRON, 1267 /* GMSH_PRI */ DM_POLYTOPE_TRI_PRISM, 1268 /* GMSH_PYR */ DM_POLYTOPE_PYRAMID, 1269 DM_POLYTOPE_UNKNOWN 1270 }; 1271 1272 PETSC_STATIC_INLINE DMPolytopeType DMPolytopeTypeFromGmsh(PetscInt cellType) 1273 { 1274 return DMPolytopeMap[GmshCellMap[cellType].polytope]; 1275 } 1276 1277 static PetscErrorCode GmshCreateFE(MPI_Comm comm, const char prefix[], PetscBool isSimplex, PetscBool continuity, PetscDTNodeType nodeType, PetscInt dim, PetscInt Nc, PetscInt k, PetscFE *fem) 1278 { 1279 DM K; 1280 PetscSpace P; 1281 PetscDualSpace Q; 1282 PetscQuadrature q, fq; 1283 PetscBool isTensor = isSimplex ? PETSC_FALSE : PETSC_TRUE; 1284 PetscBool endpoint = PETSC_TRUE; 1285 char name[32]; 1286 PetscErrorCode ierr; 1287 1288 PetscFunctionBegin; 1289 /* Create space */ 1290 ierr = PetscSpaceCreate(comm, &P);CHKERRQ(ierr); 1291 ierr = PetscSpaceSetType(P, PETSCSPACEPOLYNOMIAL);CHKERRQ(ierr); 1292 ierr = PetscSpacePolynomialSetTensor(P, isTensor);CHKERRQ(ierr); 1293 ierr = PetscSpaceSetNumComponents(P, Nc);CHKERRQ(ierr); 1294 ierr = PetscSpaceSetNumVariables(P, dim);CHKERRQ(ierr); 1295 ierr = PetscSpaceSetDegree(P, k, PETSC_DETERMINE);CHKERRQ(ierr); 1296 if (prefix) { 1297 ierr = PetscObjectSetOptionsPrefix((PetscObject) P, prefix);CHKERRQ(ierr); 1298 ierr = PetscSpaceSetFromOptions(P);CHKERRQ(ierr); 1299 ierr = PetscObjectSetOptionsPrefix((PetscObject) P, NULL);CHKERRQ(ierr); 1300 ierr = PetscSpaceGetDegree(P, &k, NULL);CHKERRQ(ierr); 1301 } 1302 ierr = PetscSpaceSetUp(P);CHKERRQ(ierr); 1303 /* Create dual space */ 1304 ierr = PetscDualSpaceCreate(comm, &Q);CHKERRQ(ierr); 1305 ierr = PetscDualSpaceSetType(Q, PETSCDUALSPACELAGRANGE);CHKERRQ(ierr); 1306 ierr = PetscDualSpaceLagrangeSetTensor(Q, isTensor);CHKERRQ(ierr); 1307 ierr = PetscDualSpaceLagrangeSetContinuity(Q, continuity);CHKERRQ(ierr); 1308 ierr = PetscDualSpaceLagrangeSetNodeType(Q, nodeType, endpoint, 0);CHKERRQ(ierr); 1309 ierr = PetscDualSpaceSetNumComponents(Q, Nc);CHKERRQ(ierr); 1310 ierr = PetscDualSpaceSetOrder(Q, k);CHKERRQ(ierr); 1311 ierr = PetscDualSpaceCreateReferenceCell(Q, dim, isSimplex, &K);CHKERRQ(ierr); 1312 ierr = PetscDualSpaceSetDM(Q, K);CHKERRQ(ierr); 1313 ierr = DMDestroy(&K);CHKERRQ(ierr); 1314 if (prefix) { 1315 ierr = PetscObjectSetOptionsPrefix((PetscObject) Q, prefix);CHKERRQ(ierr); 1316 ierr = PetscDualSpaceSetFromOptions(Q);CHKERRQ(ierr); 1317 ierr = PetscObjectSetOptionsPrefix((PetscObject) Q, NULL);CHKERRQ(ierr); 1318 } 1319 ierr = PetscDualSpaceSetUp(Q);CHKERRQ(ierr); 1320 /* Create quadrature */ 1321 if (isSimplex) { 1322 ierr = PetscDTStroudConicalQuadrature(dim, 1, k+1, -1, +1, &q);CHKERRQ(ierr); 1323 ierr = PetscDTStroudConicalQuadrature(dim-1, 1, k+1, -1, +1, &fq);CHKERRQ(ierr); 1324 } else { 1325 ierr = PetscDTGaussTensorQuadrature(dim, 1, k+1, -1, +1, &q);CHKERRQ(ierr); 1326 ierr = PetscDTGaussTensorQuadrature(dim-1, 1, k+1, -1, +1, &fq);CHKERRQ(ierr); 1327 } 1328 /* Create finite element */ 1329 ierr = PetscFECreate(comm, fem);CHKERRQ(ierr); 1330 ierr = PetscFESetType(*fem, PETSCFEBASIC);CHKERRQ(ierr); 1331 ierr = PetscFESetNumComponents(*fem, Nc);CHKERRQ(ierr); 1332 ierr = PetscFESetBasisSpace(*fem, P);CHKERRQ(ierr); 1333 ierr = PetscFESetDualSpace(*fem, Q);CHKERRQ(ierr); 1334 ierr = PetscFESetQuadrature(*fem, q);CHKERRQ(ierr); 1335 ierr = PetscFESetFaceQuadrature(*fem, fq);CHKERRQ(ierr); 1336 if (prefix) { 1337 ierr = PetscObjectSetOptionsPrefix((PetscObject) *fem, prefix);CHKERRQ(ierr); 1338 ierr = PetscFESetFromOptions(*fem);CHKERRQ(ierr); 1339 ierr = PetscObjectSetOptionsPrefix((PetscObject) *fem, NULL);CHKERRQ(ierr); 1340 } 1341 ierr = PetscFESetUp(*fem);CHKERRQ(ierr); 1342 /* Cleanup */ 1343 ierr = PetscSpaceDestroy(&P);CHKERRQ(ierr); 1344 ierr = PetscDualSpaceDestroy(&Q);CHKERRQ(ierr); 1345 ierr = PetscQuadratureDestroy(&q);CHKERRQ(ierr); 1346 ierr = PetscQuadratureDestroy(&fq);CHKERRQ(ierr); 1347 /* Set finite element name */ 1348 ierr = PetscSNPrintf(name, sizeof(name), "%s%D", isSimplex? "P" : "Q", k);CHKERRQ(ierr); 1349 ierr = PetscFESetName(*fem, name);CHKERRQ(ierr); 1350 PetscFunctionReturn(0); 1351 } 1352 1353 /*@C 1354 DMPlexCreateGmshFromFile - Create a DMPlex mesh from a Gmsh file 1355 1356 + comm - The MPI communicator 1357 . filename - Name of the Gmsh file 1358 - interpolate - Create faces and edges in the mesh 1359 1360 Output Parameter: 1361 . dm - The DM object representing the mesh 1362 1363 Level: beginner 1364 1365 .seealso: DMPlexCreateFromFile(), DMPlexCreateGmsh(), DMPlexCreate() 1366 @*/ 1367 PetscErrorCode DMPlexCreateGmshFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 1368 { 1369 PetscViewer viewer; 1370 PetscMPIInt rank; 1371 int fileType; 1372 PetscViewerType vtype; 1373 PetscErrorCode ierr; 1374 1375 PetscFunctionBegin; 1376 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 1377 1378 /* Determine Gmsh file type (ASCII or binary) from file header */ 1379 if (!rank) { 1380 GmshFile gmsh[1]; 1381 char line[PETSC_MAX_PATH_LEN]; 1382 int snum; 1383 float version; 1384 1385 ierr = PetscArrayzero(gmsh,1);CHKERRQ(ierr); 1386 ierr = PetscViewerCreate(PETSC_COMM_SELF, &gmsh->viewer);CHKERRQ(ierr); 1387 ierr = PetscViewerSetType(gmsh->viewer, PETSCVIEWERASCII);CHKERRQ(ierr); 1388 ierr = PetscViewerFileSetMode(gmsh->viewer, FILE_MODE_READ);CHKERRQ(ierr); 1389 ierr = PetscViewerFileSetName(gmsh->viewer, filename);CHKERRQ(ierr); 1390 /* Read only the first two lines of the Gmsh file */ 1391 ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr); 1392 ierr = GmshExpect(gmsh, "$MeshFormat", line);CHKERRQ(ierr); 1393 ierr = GmshReadString(gmsh, line, 2);CHKERRQ(ierr); 1394 snum = sscanf(line, "%f %d", &version, &fileType); 1395 if (snum != 2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line); 1396 if (version < 2.2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version); 1397 if ((int)version == 3) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version); 1398 if (version > 4.1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version); 1399 ierr = PetscViewerDestroy(&gmsh->viewer);CHKERRQ(ierr); 1400 } 1401 ierr = MPI_Bcast(&fileType, 1, MPI_INT, 0, comm);CHKERRQ(ierr); 1402 vtype = (fileType == 0) ? PETSCVIEWERASCII : PETSCVIEWERBINARY; 1403 1404 /* Create appropriate viewer and build plex */ 1405 ierr = PetscViewerCreate(comm, &viewer);CHKERRQ(ierr); 1406 ierr = PetscViewerSetType(viewer, vtype);CHKERRQ(ierr); 1407 ierr = PetscViewerFileSetMode(viewer, FILE_MODE_READ);CHKERRQ(ierr); 1408 ierr = PetscViewerFileSetName(viewer, filename);CHKERRQ(ierr); 1409 ierr = DMPlexCreateGmsh(comm, viewer, interpolate, dm);CHKERRQ(ierr); 1410 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 1411 PetscFunctionReturn(0); 1412 } 1413 1414 /*@ 1415 DMPlexCreateGmsh - Create a DMPlex mesh from a Gmsh file viewer 1416 1417 Collective 1418 1419 Input Parameters: 1420 + comm - The MPI communicator 1421 . viewer - The Viewer associated with a Gmsh file 1422 - interpolate - Create faces and edges in the mesh 1423 1424 Output Parameter: 1425 . dm - The DM object representing the mesh 1426 1427 Note: http://gmsh.info/doc/texinfo/gmsh.html#MSH-file-format 1428 1429 Level: beginner 1430 1431 .seealso: DMPLEX, DMCreate() 1432 @*/ 1433 PetscErrorCode DMPlexCreateGmsh(MPI_Comm comm, PetscViewer viewer, PetscBool interpolate, DM *dm) 1434 { 1435 GmshMesh *mesh = NULL; 1436 PetscViewer parentviewer = NULL; 1437 PetscBT periodicVerts = NULL; 1438 PetscBT periodicCells = NULL; 1439 DM cdm; 1440 PetscSection coordSection; 1441 Vec coordinates; 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);CHKERRQ(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) { 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);CHKERRQ(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 && 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(*dm, "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) { 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(*dm, "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(*dm, "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(*dm, "Vertex Sets", vStart + vv, elem->tags[0]);CHKERRQ(ierr); 1686 } 1687 } 1688 } 1689 } 1690 1691 if (periodic) { 1692 ierr = PetscBTCreate(numVerts, &periodicVerts);CHKERRQ(ierr); 1693 for (n = 0; n < numNodes; ++n) { 1694 if (mesh->vertexMap[n] >= 0) { 1695 if (PetscUnlikely(mesh->periodMap[n] != n)) { 1696 PetscInt m = mesh->periodMap[n]; 1697 ierr= PetscBTSet(periodicVerts, mesh->vertexMap[n]);CHKERRQ(ierr); 1698 ierr= PetscBTSet(periodicVerts, mesh->vertexMap[m]);CHKERRQ(ierr); 1699 } 1700 } 1701 } 1702 ierr = PetscBTCreate(numCells, &periodicCells);CHKERRQ(ierr); 1703 for (cell = 0; cell < numCells; ++cell) { 1704 GmshElement *elem = mesh->elements + cell; 1705 for (v = 0; v < elem->numVerts; ++v) { 1706 PetscInt nn = elem->nodes[v]; 1707 PetscInt vv = mesh->vertexMap[nn]; 1708 if (PetscUnlikely(PetscBTLookup(periodicVerts, vv))) { 1709 ierr = PetscBTSet(periodicCells, cell);CHKERRQ(ierr); break; 1710 } 1711 } 1712 } 1713 } 1714 1715 /* Setup coordinate DM */ 1716 if (coordDim < 0) coordDim = dim; 1717 ierr = DMSetCoordinateDim(*dm, coordDim);CHKERRQ(ierr); 1718 ierr = DMGetCoordinateDM(*dm, &cdm);CHKERRQ(ierr); 1719 if (highOrder) { 1720 PetscFE fe; 1721 PetscBool continuity = periodic ? PETSC_FALSE : PETSC_TRUE; 1722 PetscDTNodeType nodeType = PETSCDTNODES_EQUISPACED; 1723 1724 if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */ 1725 1726 ierr = GmshCreateFE(comm, NULL, isSimplex, continuity, nodeType, dim, coordDim, order, &fe);CHKERRQ(ierr); 1727 ierr = PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_fe_view");CHKERRQ(ierr); 1728 ierr = DMSetField(cdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 1729 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 1730 ierr = DMCreateDS(cdm);CHKERRQ(ierr); 1731 } 1732 1733 /* Create coordinates */ 1734 if (highOrder) { 1735 1736 PetscInt maxDof = GmshNumNodes_HEX(order)*coordDim; 1737 double *coords = mesh ? mesh->nodelist->xyz : NULL; 1738 PetscSection section; 1739 PetscScalar *cellCoords; 1740 1741 ierr = DMSetLocalSection(cdm, NULL);CHKERRQ(ierr); 1742 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 1743 ierr = PetscSectionClone(coordSection, §ion);CHKERRQ(ierr); 1744 ierr = DMPlexSetClosurePermutationTensor(cdm, 0, section);CHKERRQ(ierr); /* XXX Implement DMPlexSetClosurePermutationLexicographic() */ 1745 1746 ierr = DMCreateLocalVector(cdm, &coordinates);CHKERRQ(ierr); 1747 ierr = PetscMalloc1(maxDof, &cellCoords);CHKERRQ(ierr); 1748 for (cell = 0; cell < numCells; ++cell) { 1749 GmshElement *elem = mesh->elements + cell; 1750 const int *lexorder = GmshCellMap[elem->cellType].lexorder(); 1751 for (n = 0; n < elem->numNodes; ++n) { 1752 const PetscInt node = elem->nodes[lexorder[n]]; 1753 for (d = 0; d < coordDim; ++d) 1754 cellCoords[n*coordDim+d] = (PetscReal) coords[node*3+d]; 1755 } 1756 ierr = DMPlexVecSetClosure(cdm, section, coordinates, cell, cellCoords, INSERT_VALUES);CHKERRQ(ierr); 1757 } 1758 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 1759 ierr = PetscFree(cellCoords);CHKERRQ(ierr); 1760 1761 } else { 1762 1763 PetscInt *nodeMap; 1764 double *coords = mesh ? mesh->nodelist->xyz : NULL; 1765 PetscScalar *pointCoords; 1766 1767 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 1768 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 1769 ierr = PetscSectionSetFieldComponents(coordSection, 0, coordDim);CHKERRQ(ierr); 1770 if (periodic) { /* we need to localize coordinates on cells */ 1771 ierr = PetscSectionSetChart(coordSection, 0, numCells+numVerts);CHKERRQ(ierr); 1772 } else { 1773 ierr = PetscSectionSetChart(coordSection, numCells, numCells+numVerts);CHKERRQ(ierr); 1774 } 1775 if (periodic) { 1776 for (cell = 0; cell < numCells; ++cell) { 1777 if (PetscUnlikely(PetscBTLookup(periodicCells, cell))) { 1778 GmshElement *elem = mesh->elements + cell; 1779 PetscInt dof = elem->numVerts * coordDim; 1780 ierr = PetscSectionSetDof(coordSection, cell, dof);CHKERRQ(ierr); 1781 ierr = PetscSectionSetFieldDof(coordSection, cell, 0, dof);CHKERRQ(ierr); 1782 } 1783 } 1784 } 1785 for (v = numCells; v < numCells+numVerts; ++v) { 1786 ierr = PetscSectionSetDof(coordSection, v, coordDim);CHKERRQ(ierr); 1787 ierr = PetscSectionSetFieldDof(coordSection, v, 0, coordDim);CHKERRQ(ierr); 1788 } 1789 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 1790 1791 ierr = DMCreateLocalVector(cdm, &coordinates);CHKERRQ(ierr); 1792 ierr = VecGetArray(coordinates, &pointCoords);CHKERRQ(ierr); 1793 if (periodic) { 1794 for (cell = 0; cell < numCells; ++cell) { 1795 if (PetscUnlikely(PetscBTLookup(periodicCells, cell))) { 1796 GmshElement *elem = mesh->elements + cell; 1797 PetscInt off, node; 1798 for (v = 0; v < elem->numVerts; ++v) 1799 cone[v] = elem->nodes[v]; 1800 ierr = DMPlexReorderCell(cdm, cell, cone);CHKERRQ(ierr); 1801 ierr = PetscSectionGetOffset(coordSection, cell, &off);CHKERRQ(ierr); 1802 for (v = 0; v < elem->numVerts; ++v) 1803 for (node = cone[v], d = 0; d < coordDim; ++d) 1804 pointCoords[off++] = (PetscReal) coords[node*3+d]; 1805 } 1806 } 1807 } 1808 ierr = PetscMalloc1(numVerts, &nodeMap);CHKERRQ(ierr); 1809 for (n = 0; n < numNodes; n++) 1810 if (mesh->vertexMap[n] >= 0) 1811 nodeMap[mesh->vertexMap[n]] = n; 1812 for (v = 0; v < numVerts; ++v) { 1813 PetscInt off, node = nodeMap[v]; 1814 ierr = PetscSectionGetOffset(coordSection, numCells + v, &off);CHKERRQ(ierr); 1815 for (d = 0; d < coordDim; ++d) 1816 pointCoords[off+d] = (PetscReal) coords[node*3+d]; 1817 } 1818 ierr = PetscFree(nodeMap);CHKERRQ(ierr); 1819 ierr = VecRestoreArray(coordinates, &pointCoords);CHKERRQ(ierr); 1820 1821 } 1822 1823 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 1824 ierr = VecSetBlockSize(coordinates, coordDim);CHKERRQ(ierr); 1825 ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr); 1826 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 1827 ierr = DMSetPeriodicity(*dm, periodic, NULL, NULL, NULL);CHKERRQ(ierr); 1828 1829 ierr = GmshMeshDestroy(&mesh);CHKERRQ(ierr); 1830 ierr = PetscBTDestroy(&periodicVerts);CHKERRQ(ierr); 1831 ierr = PetscBTDestroy(&periodicCells);CHKERRQ(ierr); 1832 1833 if (highOrder && project) { 1834 PetscFE fe; 1835 const char prefix[] = "dm_plex_gmsh_project_"; 1836 PetscBool continuity = periodic ? PETSC_FALSE : PETSC_TRUE; 1837 PetscDTNodeType nodeType = PETSCDTNODES_GAUSSJACOBI; 1838 1839 if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */ 1840 1841 ierr = GmshCreateFE(comm, prefix, isSimplex, continuity, nodeType, dim, coordDim, order, &fe);CHKERRQ(ierr); 1842 ierr = PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_project_fe_view");CHKERRQ(ierr); 1843 ierr = DMProjectCoordinates(*dm, fe);CHKERRQ(ierr); 1844 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 1845 } 1846 1847 ierr = PetscLogEventEnd(DMPLEX_CreateGmsh,*dm,NULL,NULL,NULL);CHKERRQ(ierr); 1848 PetscFunctionReturn(0); 1849 } 1850