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) { 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 PetscInt dim = 0, coordDim = -1, order = 0; 1442 PetscInt numNodes = 0, numElems = 0, numVerts = 0, numCells = 0; 1443 PetscInt cell, cone[8], e, n, v, d; 1444 PetscBool binary, usemarker = PETSC_FALSE; 1445 PetscBool hybrid = interpolate, periodic = PETSC_TRUE; 1446 PetscBool highOrder = PETSC_TRUE, highOrderSet, project = PETSC_FALSE; 1447 PetscBool isSimplex = PETSC_FALSE, isHybrid = PETSC_FALSE, hasTetra = PETSC_FALSE; 1448 PetscMPIInt rank; 1449 PetscErrorCode ierr; 1450 1451 PetscFunctionBegin; 1452 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 1453 ierr = PetscObjectOptionsBegin((PetscObject)viewer);CHKERRQ(ierr); 1454 ierr = PetscOptionsHead(PetscOptionsObject,"DMPlex Gmsh options");CHKERRQ(ierr); 1455 ierr = PetscOptionsBool("-dm_plex_gmsh_hybrid", "Generate hybrid cell bounds", "DMPlexCreateGmsh", hybrid, &hybrid, NULL);CHKERRQ(ierr); 1456 ierr = PetscOptionsBool("-dm_plex_gmsh_periodic","Read Gmsh periodic section", "DMPlexCreateGmsh", periodic, &periodic, NULL);CHKERRQ(ierr); 1457 ierr = PetscOptionsBool("-dm_plex_gmsh_highorder","Generate high-order coordinates", "DMPlexCreateGmsh", highOrder, &highOrder, &highOrderSet);CHKERRQ(ierr); 1458 ierr = PetscOptionsBool("-dm_plex_gmsh_project", "Project high-order coordinates to a different space", "DMPlexCreateGmsh", project, &project, NULL);CHKERRQ(ierr); 1459 ierr = PetscOptionsBool("-dm_plex_gmsh_use_marker", "Generate marker label", "DMPlexCreateGmsh", usemarker, &usemarker, NULL);CHKERRQ(ierr); 1460 ierr = PetscOptionsBoundedInt("-dm_plex_gmsh_spacedim", "Embedding space dimension", "DMPlexCreateGmsh", coordDim, &coordDim, NULL, PETSC_DECIDE);CHKERRQ(ierr); 1461 ierr = PetscOptionsTail();CHKERRQ(ierr); 1462 ierr = PetscOptionsEnd();CHKERRQ(ierr); 1463 1464 ierr = GmshCellInfoSetUp();CHKERRQ(ierr); 1465 1466 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 1467 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 1468 ierr = PetscLogEventBegin(DMPLEX_CreateGmsh,*dm,NULL,NULL,NULL);CHKERRQ(ierr); 1469 1470 ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &binary);CHKERRQ(ierr); 1471 1472 /* Binary viewers read on all ranks, get subviewer to read only in rank 0 */ 1473 if (binary) { 1474 parentviewer = viewer; 1475 ierr = PetscViewerGetSubViewer(parentviewer, PETSC_COMM_SELF, &viewer);CHKERRQ(ierr); 1476 } 1477 1478 if (!rank) { 1479 GmshFile gmsh[1]; 1480 char line[PETSC_MAX_PATH_LEN]; 1481 PetscBool match; 1482 1483 ierr = PetscArrayzero(gmsh,1);CHKERRQ(ierr); 1484 gmsh->viewer = viewer; 1485 gmsh->binary = binary; 1486 1487 ierr = GmshMeshCreate(&mesh);CHKERRQ(ierr); 1488 1489 /* Read mesh format */ 1490 ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr); 1491 ierr = GmshExpect(gmsh, "$MeshFormat", line);CHKERRQ(ierr); 1492 ierr = GmshReadMeshFormat(gmsh);CHKERRQ(ierr); 1493 ierr = GmshReadEndSection(gmsh, "$EndMeshFormat", line);CHKERRQ(ierr); 1494 1495 /* OPTIONAL Read physical names */ 1496 ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr); 1497 ierr = GmshMatch(gmsh, "$PhysicalNames", line, &match);CHKERRQ(ierr); 1498 if (match) { 1499 ierr = GmshExpect(gmsh, "$PhysicalNames", line);CHKERRQ(ierr); 1500 ierr = GmshReadPhysicalNames(gmsh);CHKERRQ(ierr); 1501 ierr = GmshReadEndSection(gmsh, "$EndPhysicalNames", line);CHKERRQ(ierr); 1502 /* Initial read for entity section */ 1503 ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr); 1504 } 1505 1506 /* Read entities */ 1507 if (gmsh->fileFormat >= 40) { 1508 ierr = GmshExpect(gmsh, "$Entities", line);CHKERRQ(ierr); 1509 ierr = GmshReadEntities(gmsh, mesh);CHKERRQ(ierr); 1510 ierr = GmshReadEndSection(gmsh, "$EndEntities", line);CHKERRQ(ierr); 1511 /* Initial read for nodes section */ 1512 ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr); 1513 } 1514 1515 /* Read nodes */ 1516 ierr = GmshExpect(gmsh, "$Nodes", line);CHKERRQ(ierr); 1517 ierr = GmshReadNodes(gmsh, mesh);CHKERRQ(ierr); 1518 ierr = GmshReadEndSection(gmsh, "$EndNodes", line);CHKERRQ(ierr); 1519 1520 /* Read elements */ 1521 ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr); 1522 ierr = GmshExpect(gmsh, "$Elements", line);CHKERRQ(ierr); 1523 ierr = GmshReadElements(gmsh, mesh);CHKERRQ(ierr); 1524 ierr = GmshReadEndSection(gmsh, "$EndElements", line);CHKERRQ(ierr); 1525 1526 /* Read periodic section (OPTIONAL) */ 1527 if (periodic) { 1528 ierr = GmshReadSection(gmsh, line);CHKERRQ(ierr); 1529 ierr = GmshMatch(gmsh, "$Periodic", line, &periodic);CHKERRQ(ierr); 1530 } 1531 if (periodic) { 1532 ierr = GmshExpect(gmsh, "$Periodic", line);CHKERRQ(ierr); 1533 ierr = GmshReadPeriodic(gmsh, mesh);CHKERRQ(ierr); 1534 ierr = GmshReadEndSection(gmsh, "$EndPeriodic", line);CHKERRQ(ierr); 1535 } 1536 1537 ierr = PetscFree(gmsh->wbuf);CHKERRQ(ierr); 1538 ierr = PetscFree(gmsh->sbuf);CHKERRQ(ierr); 1539 ierr = PetscFree(gmsh->nbuf);CHKERRQ(ierr); 1540 1541 dim = mesh->dim; 1542 order = mesh->order; 1543 numNodes = mesh->numNodes; 1544 numElems = mesh->numElems; 1545 numVerts = mesh->numVerts; 1546 numCells = mesh->numCells; 1547 1548 { 1549 GmshElement *elemA = mesh->numCells > 0 ? mesh->elements : NULL; 1550 GmshElement *elemB = elemA ? elemA + mesh->numCells - 1 : NULL; 1551 int ptA = elemA ? GmshCellMap[elemA->cellType].polytope : -1; 1552 int ptB = elemB ? GmshCellMap[elemB->cellType].polytope : -1; 1553 isSimplex = (ptA == GMSH_QUA || ptA == GMSH_HEX) ? PETSC_FALSE : PETSC_TRUE; 1554 isHybrid = (ptA == ptB) ? PETSC_FALSE : PETSC_TRUE; 1555 hasTetra = (ptA == GMSH_TET) ? PETSC_TRUE : PETSC_FALSE; 1556 } 1557 } 1558 1559 if (parentviewer) { 1560 ierr = PetscViewerRestoreSubViewer(parentviewer, PETSC_COMM_SELF, &viewer);CHKERRQ(ierr); 1561 } 1562 1563 { 1564 int buf[6]; 1565 1566 buf[0] = (int)dim; 1567 buf[1] = (int)order; 1568 buf[2] = periodic; 1569 buf[3] = isSimplex; 1570 buf[4] = isHybrid; 1571 buf[5] = hasTetra; 1572 1573 ierr = MPI_Bcast(buf, 6, MPI_INT, 0, comm);CHKERRMPI(ierr); 1574 1575 dim = buf[0]; 1576 order = buf[1]; 1577 periodic = buf[2] ? PETSC_TRUE : PETSC_FALSE; 1578 isSimplex = buf[3] ? PETSC_TRUE : PETSC_FALSE; 1579 isHybrid = buf[4] ? PETSC_TRUE : PETSC_FALSE; 1580 hasTetra = buf[5] ? PETSC_TRUE : PETSC_FALSE; 1581 } 1582 1583 if (!highOrderSet) highOrder = (order > 1) ? PETSC_TRUE : PETSC_FALSE; 1584 if (highOrder && isHybrid) SETERRQ(comm, PETSC_ERR_SUP, "No support for discretization on hybrid meshes yet"); 1585 1586 /* We do not want this label automatically computed, instead we fill it here */ 1587 ierr = DMCreateLabel(*dm, "celltype");CHKERRQ(ierr); 1588 1589 /* Allocate the cell-vertex mesh */ 1590 ierr = DMPlexSetChart(*dm, 0, numCells+numVerts);CHKERRQ(ierr); 1591 for (cell = 0; cell < numCells; ++cell) { 1592 GmshElement *elem = mesh->elements + cell; 1593 DMPolytopeType ctype = DMPolytopeTypeFromGmsh(elem->cellType); 1594 if (hybrid && hasTetra && ctype == DM_POLYTOPE_TRI_PRISM) ctype = DM_POLYTOPE_TRI_PRISM_TENSOR; 1595 ierr = DMPlexSetConeSize(*dm, cell, elem->numVerts);CHKERRQ(ierr); 1596 ierr = DMPlexSetCellType(*dm, cell, ctype);CHKERRQ(ierr); 1597 } 1598 for (v = numCells; v < numCells+numVerts; ++v) { 1599 ierr = DMPlexSetCellType(*dm, v, DM_POLYTOPE_POINT);CHKERRQ(ierr); 1600 } 1601 ierr = DMSetUp(*dm);CHKERRQ(ierr); 1602 1603 /* Add cell-vertex connections */ 1604 for (cell = 0; cell < numCells; ++cell) { 1605 GmshElement *elem = mesh->elements + cell; 1606 for (v = 0; v < elem->numVerts; ++v) { 1607 const PetscInt nn = elem->nodes[v]; 1608 const PetscInt vv = mesh->vertexMap[nn]; 1609 cone[v] = numCells + vv; 1610 } 1611 ierr = DMPlexReorderCell(*dm, cell, cone);CHKERRQ(ierr); 1612 ierr = DMPlexSetCone(*dm, cell, cone);CHKERRQ(ierr); 1613 } 1614 1615 ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); 1616 ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr); 1617 ierr = DMPlexStratify(*dm);CHKERRQ(ierr); 1618 if (interpolate) { 1619 DM idm; 1620 1621 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 1622 ierr = DMDestroy(dm);CHKERRQ(ierr); 1623 *dm = idm; 1624 } 1625 1626 if (usemarker && !interpolate && dim > 1) SETERRQ(comm,PETSC_ERR_SUP,"Cannot create marker label without interpolation"); 1627 if (!rank && usemarker) { 1628 PetscInt f, fStart, fEnd; 1629 1630 ierr = DMCreateLabel(*dm, "marker");CHKERRQ(ierr); 1631 ierr = DMPlexGetHeightStratum(*dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 1632 for (f = fStart; f < fEnd; ++f) { 1633 PetscInt suppSize; 1634 1635 ierr = DMPlexGetSupportSize(*dm, f, &suppSize);CHKERRQ(ierr); 1636 if (suppSize == 1) { 1637 PetscInt *cone = NULL, coneSize, p; 1638 1639 ierr = DMPlexGetTransitiveClosure(*dm, f, PETSC_TRUE, &coneSize, &cone);CHKERRQ(ierr); 1640 for (p = 0; p < coneSize; p += 2) { 1641 ierr = DMSetLabelValue(*dm, "marker", cone[p], 1);CHKERRQ(ierr); 1642 } 1643 ierr = DMPlexRestoreTransitiveClosure(*dm, f, PETSC_TRUE, &coneSize, &cone);CHKERRQ(ierr); 1644 } 1645 } 1646 } 1647 1648 if (!rank) { 1649 PetscInt vStart, vEnd; 1650 1651 ierr = DMPlexGetDepthStratum(*dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1652 for (cell = 0, e = 0; e < numElems; ++e) { 1653 GmshElement *elem = mesh->elements + e; 1654 1655 /* Create cell sets */ 1656 if (elem->dim == dim && dim > 0) { 1657 if (elem->numTags > 0) { 1658 ierr = DMSetLabelValue(*dm, "Cell Sets", cell, elem->tags[0]);CHKERRQ(ierr); 1659 } 1660 cell++; 1661 } 1662 1663 /* Create face sets */ 1664 if (interpolate && elem->dim == dim-1) { 1665 PetscInt joinSize; 1666 const PetscInt *join = NULL; 1667 /* Find the relevant facet with vertex joins */ 1668 for (v = 0; v < elem->numVerts; ++v) { 1669 const PetscInt nn = elem->nodes[v]; 1670 const PetscInt vv = mesh->vertexMap[nn]; 1671 cone[v] = vStart + vv; 1672 } 1673 ierr = DMPlexGetFullJoin(*dm, elem->numVerts, cone, &joinSize, &join);CHKERRQ(ierr); 1674 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); 1675 ierr = DMSetLabelValue(*dm, "Face Sets", join[0], elem->tags[0]);CHKERRQ(ierr); 1676 ierr = DMPlexRestoreJoin(*dm, elem->numVerts, cone, &joinSize, &join);CHKERRQ(ierr); 1677 } 1678 1679 /* Create vertex sets */ 1680 if (elem->dim == 0) { 1681 if (elem->numTags > 0) { 1682 const PetscInt nn = elem->nodes[0]; 1683 const PetscInt vv = mesh->vertexMap[nn]; 1684 ierr = DMSetLabelValue(*dm, "Vertex Sets", vStart + vv, elem->tags[0]);CHKERRQ(ierr); 1685 } 1686 } 1687 } 1688 } 1689 1690 if (periodic) { 1691 ierr = PetscBTCreate(numVerts, &periodicVerts);CHKERRQ(ierr); 1692 for (n = 0; n < numNodes; ++n) { 1693 if (mesh->vertexMap[n] >= 0) { 1694 if (PetscUnlikely(mesh->periodMap[n] != n)) { 1695 PetscInt m = mesh->periodMap[n]; 1696 ierr = PetscBTSet(periodicVerts, mesh->vertexMap[n]);CHKERRQ(ierr); 1697 ierr = PetscBTSet(periodicVerts, mesh->vertexMap[m]);CHKERRQ(ierr); 1698 } 1699 } 1700 } 1701 ierr = PetscBTCreate(numCells, &periodicCells);CHKERRQ(ierr); 1702 for (cell = 0; cell < numCells; ++cell) { 1703 GmshElement *elem = mesh->elements + cell; 1704 for (v = 0; v < elem->numVerts; ++v) { 1705 PetscInt nn = elem->nodes[v]; 1706 PetscInt vv = mesh->vertexMap[nn]; 1707 if (PetscUnlikely(PetscBTLookup(periodicVerts, vv))) { 1708 ierr = PetscBTSet(periodicCells, cell);CHKERRQ(ierr); break; 1709 } 1710 } 1711 } 1712 } 1713 1714 /* Setup coordinate DM */ 1715 if (coordDim < 0) coordDim = dim; 1716 ierr = DMSetCoordinateDim(*dm, coordDim);CHKERRQ(ierr); 1717 ierr = DMGetCoordinateDM(*dm, &cdm);CHKERRQ(ierr); 1718 if (highOrder) { 1719 PetscFE fe; 1720 PetscBool continuity = periodic ? PETSC_FALSE : PETSC_TRUE; 1721 PetscDTNodeType nodeType = PETSCDTNODES_EQUISPACED; 1722 1723 if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */ 1724 1725 ierr = GmshCreateFE(comm, NULL, isSimplex, continuity, nodeType, dim, coordDim, order, &fe);CHKERRQ(ierr); 1726 ierr = PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_fe_view");CHKERRQ(ierr); 1727 ierr = DMSetField(cdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 1728 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 1729 ierr = DMCreateDS(cdm);CHKERRQ(ierr); 1730 } 1731 1732 /* Create coordinates */ 1733 if (highOrder) { 1734 1735 PetscInt maxDof = GmshNumNodes_HEX(order)*coordDim; 1736 double *coords = mesh ? mesh->nodelist->xyz : NULL; 1737 PetscSection section; 1738 PetscScalar *cellCoords; 1739 1740 ierr = DMSetLocalSection(cdm, NULL);CHKERRQ(ierr); 1741 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 1742 ierr = PetscSectionClone(coordSection, §ion);CHKERRQ(ierr); 1743 ierr = DMPlexSetClosurePermutationTensor(cdm, 0, section);CHKERRQ(ierr); /* XXX Implement DMPlexSetClosurePermutationLexicographic() */ 1744 1745 ierr = DMCreateLocalVector(cdm, &coordinates);CHKERRQ(ierr); 1746 ierr = PetscMalloc1(maxDof, &cellCoords);CHKERRQ(ierr); 1747 for (cell = 0; cell < numCells; ++cell) { 1748 GmshElement *elem = mesh->elements + cell; 1749 const int *lexorder = GmshCellMap[elem->cellType].lexorder(); 1750 for (n = 0; n < elem->numNodes; ++n) { 1751 const PetscInt node = elem->nodes[lexorder[n]]; 1752 for (d = 0; d < coordDim; ++d) 1753 cellCoords[n*coordDim+d] = (PetscReal) coords[node*3+d]; 1754 } 1755 ierr = DMPlexVecSetClosure(cdm, section, coordinates, cell, cellCoords, INSERT_VALUES);CHKERRQ(ierr); 1756 } 1757 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 1758 ierr = PetscFree(cellCoords);CHKERRQ(ierr); 1759 1760 } else { 1761 1762 PetscInt *nodeMap; 1763 double *coords = mesh ? mesh->nodelist->xyz : NULL; 1764 PetscScalar *pointCoords; 1765 1766 ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 1767 ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 1768 ierr = PetscSectionSetFieldComponents(coordSection, 0, coordDim);CHKERRQ(ierr); 1769 if (periodic) { /* we need to localize coordinates on cells */ 1770 ierr = PetscSectionSetChart(coordSection, 0, numCells+numVerts);CHKERRQ(ierr); 1771 } else { 1772 ierr = PetscSectionSetChart(coordSection, numCells, numCells+numVerts);CHKERRQ(ierr); 1773 } 1774 if (periodic) { 1775 for (cell = 0; cell < numCells; ++cell) { 1776 if (PetscUnlikely(PetscBTLookup(periodicCells, cell))) { 1777 GmshElement *elem = mesh->elements + cell; 1778 PetscInt dof = elem->numVerts * coordDim; 1779 ierr = PetscSectionSetDof(coordSection, cell, dof);CHKERRQ(ierr); 1780 ierr = PetscSectionSetFieldDof(coordSection, cell, 0, dof);CHKERRQ(ierr); 1781 } 1782 } 1783 } 1784 for (v = numCells; v < numCells+numVerts; ++v) { 1785 ierr = PetscSectionSetDof(coordSection, v, coordDim);CHKERRQ(ierr); 1786 ierr = PetscSectionSetFieldDof(coordSection, v, 0, coordDim);CHKERRQ(ierr); 1787 } 1788 ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 1789 1790 ierr = DMCreateLocalVector(cdm, &coordinates);CHKERRQ(ierr); 1791 ierr = VecGetArray(coordinates, &pointCoords);CHKERRQ(ierr); 1792 if (periodic) { 1793 for (cell = 0; cell < numCells; ++cell) { 1794 if (PetscUnlikely(PetscBTLookup(periodicCells, cell))) { 1795 GmshElement *elem = mesh->elements + cell; 1796 PetscInt off, node; 1797 for (v = 0; v < elem->numVerts; ++v) 1798 cone[v] = elem->nodes[v]; 1799 ierr = DMPlexReorderCell(cdm, cell, cone);CHKERRQ(ierr); 1800 ierr = PetscSectionGetOffset(coordSection, cell, &off);CHKERRQ(ierr); 1801 for (v = 0; v < elem->numVerts; ++v) 1802 for (node = cone[v], d = 0; d < coordDim; ++d) 1803 pointCoords[off++] = (PetscReal) coords[node*3+d]; 1804 } 1805 } 1806 } 1807 ierr = PetscMalloc1(numVerts, &nodeMap);CHKERRQ(ierr); 1808 for (n = 0; n < numNodes; n++) 1809 if (mesh->vertexMap[n] >= 0) 1810 nodeMap[mesh->vertexMap[n]] = n; 1811 for (v = 0; v < numVerts; ++v) { 1812 PetscInt off, node = nodeMap[v]; 1813 ierr = PetscSectionGetOffset(coordSection, numCells + v, &off);CHKERRQ(ierr); 1814 for (d = 0; d < coordDim; ++d) 1815 pointCoords[off+d] = (PetscReal) coords[node*3+d]; 1816 } 1817 ierr = PetscFree(nodeMap);CHKERRQ(ierr); 1818 ierr = VecRestoreArray(coordinates, &pointCoords);CHKERRQ(ierr); 1819 1820 } 1821 1822 ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 1823 ierr = VecSetBlockSize(coordinates, coordDim);CHKERRQ(ierr); 1824 ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr); 1825 ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 1826 ierr = DMSetPeriodicity(*dm, periodic, NULL, NULL, NULL);CHKERRQ(ierr); 1827 1828 ierr = GmshMeshDestroy(&mesh);CHKERRQ(ierr); 1829 ierr = PetscBTDestroy(&periodicVerts);CHKERRQ(ierr); 1830 ierr = PetscBTDestroy(&periodicCells);CHKERRQ(ierr); 1831 1832 if (highOrder && project) { 1833 PetscFE fe; 1834 const char prefix[] = "dm_plex_gmsh_project_"; 1835 PetscBool continuity = periodic ? PETSC_FALSE : PETSC_TRUE; 1836 PetscDTNodeType nodeType = PETSCDTNODES_GAUSSJACOBI; 1837 1838 if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */ 1839 1840 ierr = GmshCreateFE(comm, prefix, isSimplex, continuity, nodeType, dim, coordDim, order, &fe);CHKERRQ(ierr); 1841 ierr = PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_project_fe_view");CHKERRQ(ierr); 1842 ierr = DMProjectCoordinates(*dm, fe);CHKERRQ(ierr); 1843 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 1844 } 1845 1846 ierr = PetscLogEventEnd(DMPLEX_CreateGmsh,*dm,NULL,NULL,NULL);CHKERRQ(ierr); 1847 PetscFunctionReturn(0); 1848 } 1849