1331830f3SMatthew G. Knepley #define PETSCDM_DLL 2af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 3730356f6SLisandro Dalcin #include <petsc/private/hashmapi.h> 4331830f3SMatthew G. Knepley 5066ea43fSLisandro Dalcin #include <../src/dm/impls/plex/gmshlex.h> 6066ea43fSLisandro Dalcin 7066ea43fSLisandro Dalcin #define GMSH_LEXORDER_ITEM(T, p) \ 8d71ae5a4SJacob Faibussowitsch static int *GmshLexOrder_##T##_##p(void) \ 9d71ae5a4SJacob Faibussowitsch { \ 10066ea43fSLisandro Dalcin static int Gmsh_LexOrder_##T##_##p[GmshNumNodes_##T(p)] = {-1}; \ 11066ea43fSLisandro Dalcin int *lex = Gmsh_LexOrder_##T##_##p; \ 12066ea43fSLisandro Dalcin if (lex[0] == -1) (void)GmshLexOrder_##T(p, lex, 0); \ 13066ea43fSLisandro Dalcin return lex; \ 14066ea43fSLisandro Dalcin } 15066ea43fSLisandro Dalcin 16d71ae5a4SJacob Faibussowitsch static int *GmshLexOrder_QUA_2_Serendipity(void) 17d71ae5a4SJacob Faibussowitsch { 18b9bf55e5SMatthew G. Knepley static int Gmsh_LexOrder_QUA_2_Serendipity[9] = {-1}; 19b9bf55e5SMatthew G. Knepley int *lex = Gmsh_LexOrder_QUA_2_Serendipity; 20b9bf55e5SMatthew G. Knepley if (lex[0] == -1) { 21b9bf55e5SMatthew G. Knepley /* Vertices */ 229371c9d4SSatish Balay lex[0] = 0; 239371c9d4SSatish Balay lex[2] = 1; 249371c9d4SSatish Balay lex[8] = 2; 259371c9d4SSatish Balay lex[6] = 3; 26b9bf55e5SMatthew G. Knepley /* Edges */ 279371c9d4SSatish Balay lex[1] = 4; 289371c9d4SSatish Balay lex[5] = 5; 299371c9d4SSatish Balay lex[7] = 6; 309371c9d4SSatish Balay lex[3] = 7; 31b9bf55e5SMatthew G. Knepley /* Cell */ 32b9bf55e5SMatthew G. Knepley lex[4] = -8; 33b9bf55e5SMatthew G. Knepley } 34b9bf55e5SMatthew G. Knepley return lex; 35b9bf55e5SMatthew G. Knepley } 36b9bf55e5SMatthew G. Knepley 37d71ae5a4SJacob Faibussowitsch static int *GmshLexOrder_HEX_2_Serendipity(void) 38d71ae5a4SJacob Faibussowitsch { 39b9bf55e5SMatthew G. Knepley static int Gmsh_LexOrder_HEX_2_Serendipity[27] = {-1}; 40b9bf55e5SMatthew G. Knepley int *lex = Gmsh_LexOrder_HEX_2_Serendipity; 41b9bf55e5SMatthew G. Knepley if (lex[0] == -1) { 42b9bf55e5SMatthew G. Knepley /* Vertices */ 439371c9d4SSatish Balay lex[0] = 0; 449371c9d4SSatish Balay lex[2] = 1; 459371c9d4SSatish Balay lex[8] = 2; 469371c9d4SSatish Balay lex[6] = 3; 479371c9d4SSatish Balay lex[18] = 4; 489371c9d4SSatish Balay lex[20] = 5; 499371c9d4SSatish Balay lex[26] = 6; 509371c9d4SSatish Balay lex[24] = 7; 51b9bf55e5SMatthew G. Knepley /* Edges */ 529371c9d4SSatish Balay lex[1] = 8; 539371c9d4SSatish Balay lex[3] = 9; 549371c9d4SSatish Balay lex[9] = 10; 559371c9d4SSatish Balay lex[5] = 11; 569371c9d4SSatish Balay lex[11] = 12; 579371c9d4SSatish Balay lex[7] = 13; 589371c9d4SSatish Balay lex[17] = 14; 599371c9d4SSatish Balay lex[15] = 15; 609371c9d4SSatish Balay lex[19] = 16; 619371c9d4SSatish Balay lex[21] = 17; 629371c9d4SSatish Balay lex[23] = 18; 639371c9d4SSatish Balay lex[25] = 19; 64b9bf55e5SMatthew G. Knepley /* Faces */ 659371c9d4SSatish Balay lex[4] = -20; 669371c9d4SSatish Balay lex[10] = -21; 679371c9d4SSatish Balay lex[12] = -22; 689371c9d4SSatish Balay lex[14] = -23; 699371c9d4SSatish Balay lex[16] = -24; 709371c9d4SSatish Balay lex[22] = -25; 71b9bf55e5SMatthew G. Knepley /* Cell */ 72b9bf55e5SMatthew G. Knepley lex[13] = -26; 73b9bf55e5SMatthew G. Knepley } 74b9bf55e5SMatthew G. Knepley return lex; 75b9bf55e5SMatthew G. Knepley } 76b9bf55e5SMatthew G. Knepley 77066ea43fSLisandro Dalcin #define GMSH_LEXORDER_LIST(T) \ 78066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 1) \ 79066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 2) \ 80066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 3) \ 81066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 4) \ 82066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 5) \ 83066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 6) \ 84066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 7) \ 85066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 8) \ 86066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 9) \ 87066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(T, 10) 88066ea43fSLisandro Dalcin 89066ea43fSLisandro Dalcin GMSH_LEXORDER_ITEM(VTX, 0) 90066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(SEG) 91066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(TRI) 92066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(QUA) 93066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(TET) 94066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(HEX) 95066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(PRI) 96066ea43fSLisandro Dalcin GMSH_LEXORDER_LIST(PYR) 97066ea43fSLisandro Dalcin 98066ea43fSLisandro Dalcin typedef enum { 99066ea43fSLisandro Dalcin GMSH_VTX = 0, 100066ea43fSLisandro Dalcin GMSH_SEG = 1, 101066ea43fSLisandro Dalcin GMSH_TRI = 2, 102066ea43fSLisandro Dalcin GMSH_QUA = 3, 103066ea43fSLisandro Dalcin GMSH_TET = 4, 104066ea43fSLisandro Dalcin GMSH_HEX = 5, 105066ea43fSLisandro Dalcin GMSH_PRI = 6, 106066ea43fSLisandro Dalcin GMSH_PYR = 7, 107066ea43fSLisandro Dalcin GMSH_NUM_POLYTOPES = 8 108066ea43fSLisandro Dalcin } GmshPolytopeType; 109066ea43fSLisandro Dalcin 110de78e4feSLisandro Dalcin typedef struct { 1110598e1a2SLisandro Dalcin int cellType; 112066ea43fSLisandro Dalcin int polytope; 1130598e1a2SLisandro Dalcin int dim; 1140598e1a2SLisandro Dalcin int order; 115066ea43fSLisandro Dalcin int numVerts; 1160598e1a2SLisandro Dalcin int numNodes; 117066ea43fSLisandro Dalcin int *(*lexorder)(void); 1180598e1a2SLisandro Dalcin } GmshCellInfo; 1190598e1a2SLisandro Dalcin 120066ea43fSLisandro Dalcin #define GmshCellEntry(cellType, polytope, dim, order) \ 121d71ae5a4SJacob Faibussowitsch { \ 122d71ae5a4SJacob Faibussowitsch cellType, GMSH_##polytope, dim, order, GmshNumNodes_##polytope(1), GmshNumNodes_##polytope(order), GmshLexOrder_##polytope##_##order \ 123d71ae5a4SJacob Faibussowitsch } 1240598e1a2SLisandro Dalcin 1250598e1a2SLisandro Dalcin static const GmshCellInfo GmshCellTable[] = { 126066ea43fSLisandro Dalcin GmshCellEntry(15, VTX, 0, 0), 1270598e1a2SLisandro Dalcin 1289371c9d4SSatish Balay GmshCellEntry(1, SEG, 1, 1), GmshCellEntry(8, SEG, 1, 2), GmshCellEntry(26, SEG, 1, 3), 1299371c9d4SSatish Balay GmshCellEntry(27, SEG, 1, 4), GmshCellEntry(28, SEG, 1, 5), GmshCellEntry(62, SEG, 1, 6), 1309371c9d4SSatish Balay GmshCellEntry(63, SEG, 1, 7), GmshCellEntry(64, SEG, 1, 8), GmshCellEntry(65, SEG, 1, 9), 131066ea43fSLisandro Dalcin GmshCellEntry(66, SEG, 1, 10), 1320598e1a2SLisandro Dalcin 1339371c9d4SSatish Balay GmshCellEntry(2, TRI, 2, 1), GmshCellEntry(9, TRI, 2, 2), GmshCellEntry(21, TRI, 2, 3), 1349371c9d4SSatish Balay GmshCellEntry(23, TRI, 2, 4), GmshCellEntry(25, TRI, 2, 5), GmshCellEntry(42, TRI, 2, 6), 1359371c9d4SSatish Balay GmshCellEntry(43, TRI, 2, 7), GmshCellEntry(44, TRI, 2, 8), GmshCellEntry(45, TRI, 2, 9), 136066ea43fSLisandro Dalcin GmshCellEntry(46, TRI, 2, 10), 1370598e1a2SLisandro Dalcin 1389371c9d4SSatish Balay GmshCellEntry(3, QUA, 2, 1), GmshCellEntry(10, QUA, 2, 2), {16, GMSH_QUA, 2, 2, 4, 8, GmshLexOrder_QUA_2_Serendipity}, 1399371c9d4SSatish Balay GmshCellEntry(36, QUA, 2, 3), GmshCellEntry(37, QUA, 2, 4), GmshCellEntry(38, QUA, 2, 5), 1409371c9d4SSatish Balay GmshCellEntry(47, QUA, 2, 6), GmshCellEntry(48, QUA, 2, 7), GmshCellEntry(49, QUA, 2, 8), 1419371c9d4SSatish Balay GmshCellEntry(50, QUA, 2, 9), GmshCellEntry(51, QUA, 2, 10), 1420598e1a2SLisandro Dalcin 1439371c9d4SSatish Balay GmshCellEntry(4, TET, 3, 1), GmshCellEntry(11, TET, 3, 2), GmshCellEntry(29, TET, 3, 3), 1449371c9d4SSatish Balay GmshCellEntry(30, TET, 3, 4), GmshCellEntry(31, TET, 3, 5), GmshCellEntry(71, TET, 3, 6), 1459371c9d4SSatish Balay GmshCellEntry(72, TET, 3, 7), GmshCellEntry(73, TET, 3, 8), GmshCellEntry(74, TET, 3, 9), 146066ea43fSLisandro Dalcin GmshCellEntry(75, TET, 3, 10), 1470598e1a2SLisandro Dalcin 1489371c9d4SSatish Balay GmshCellEntry(5, HEX, 3, 1), GmshCellEntry(12, HEX, 3, 2), {17, GMSH_HEX, 3, 2, 8, 20, GmshLexOrder_HEX_2_Serendipity}, 1499371c9d4SSatish Balay GmshCellEntry(92, HEX, 3, 3), GmshCellEntry(93, HEX, 3, 4), GmshCellEntry(94, HEX, 3, 5), 1509371c9d4SSatish Balay GmshCellEntry(95, HEX, 3, 6), GmshCellEntry(96, HEX, 3, 7), GmshCellEntry(97, HEX, 3, 8), 1519371c9d4SSatish Balay GmshCellEntry(98, HEX, 3, 9), GmshCellEntry(-1, HEX, 3, 10), 1520598e1a2SLisandro Dalcin 1539371c9d4SSatish Balay GmshCellEntry(6, PRI, 3, 1), GmshCellEntry(13, PRI, 3, 2), GmshCellEntry(90, PRI, 3, 3), 1549371c9d4SSatish Balay GmshCellEntry(91, PRI, 3, 4), GmshCellEntry(106, PRI, 3, 5), GmshCellEntry(107, PRI, 3, 6), 1559371c9d4SSatish Balay GmshCellEntry(108, PRI, 3, 7), GmshCellEntry(109, PRI, 3, 8), GmshCellEntry(110, PRI, 3, 9), 156066ea43fSLisandro Dalcin GmshCellEntry(-1, PRI, 3, 10), 1570598e1a2SLisandro Dalcin 1589371c9d4SSatish Balay GmshCellEntry(7, PYR, 3, 1), GmshCellEntry(14, PYR, 3, 2), GmshCellEntry(118, PYR, 3, 3), 1599371c9d4SSatish Balay GmshCellEntry(119, PYR, 3, 4), GmshCellEntry(120, PYR, 3, 5), GmshCellEntry(121, PYR, 3, 6), 1609371c9d4SSatish Balay GmshCellEntry(122, PYR, 3, 7), GmshCellEntry(123, PYR, 3, 8), GmshCellEntry(124, PYR, 3, 9), 161066ea43fSLisandro Dalcin GmshCellEntry(-1, PYR, 3, 10) 1620598e1a2SLisandro Dalcin 1630598e1a2SLisandro Dalcin #if 0 164066ea43fSLisandro Dalcin {20, GMSH_TRI, 2, 3, 3, 9, NULL}, 165066ea43fSLisandro Dalcin {18, GMSH_PRI, 3, 2, 6, 15, NULL}, 166066ea43fSLisandro Dalcin {19, GMSH_PYR, 3, 2, 5, 13, NULL}, 1670598e1a2SLisandro Dalcin #endif 1680598e1a2SLisandro Dalcin }; 1690598e1a2SLisandro Dalcin 1700598e1a2SLisandro Dalcin static GmshCellInfo GmshCellMap[150]; 1710598e1a2SLisandro Dalcin 172d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshCellInfoSetUp(void) 173d71ae5a4SJacob Faibussowitsch { 1740598e1a2SLisandro Dalcin size_t i, n; 1750598e1a2SLisandro Dalcin static PetscBool called = PETSC_FALSE; 1760598e1a2SLisandro Dalcin 1770598e1a2SLisandro Dalcin PetscFunctionBegin; 1784d86920dSPierre Jolivet if (called) PetscFunctionReturn(PETSC_SUCCESS); 1790598e1a2SLisandro Dalcin called = PETSC_TRUE; 180dd39110bSPierre Jolivet n = PETSC_STATIC_ARRAY_LENGTH(GmshCellMap); 1810598e1a2SLisandro Dalcin for (i = 0; i < n; ++i) { 1820598e1a2SLisandro Dalcin GmshCellMap[i].cellType = -1; 183066ea43fSLisandro Dalcin GmshCellMap[i].polytope = -1; 1840598e1a2SLisandro Dalcin } 185dd39110bSPierre Jolivet n = PETSC_STATIC_ARRAY_LENGTH(GmshCellTable); 186066ea43fSLisandro Dalcin for (i = 0; i < n; ++i) { 187066ea43fSLisandro Dalcin if (GmshCellTable[i].cellType <= 0) continue; 188066ea43fSLisandro Dalcin GmshCellMap[GmshCellTable[i].cellType] = GmshCellTable[i]; 189066ea43fSLisandro Dalcin } 1903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1910598e1a2SLisandro Dalcin } 1920598e1a2SLisandro Dalcin 1939371c9d4SSatish Balay #define GmshCellTypeCheck(ct) \ 1949371c9d4SSatish Balay PetscMacroReturnStandard(const int _ct_ = (int)ct; PetscCheck(_ct_ >= 0 && _ct_ < (int)PETSC_STATIC_ARRAY_LENGTH(GmshCellMap), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid Gmsh element type %d", _ct_); PetscCheck(GmshCellMap[_ct_].cellType == _ct_, PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported Gmsh element type %d", _ct_); \ 1959371c9d4SSatish Balay PetscCheck(GmshCellMap[_ct_].polytope != -1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported Gmsh element type %d", _ct_);) 1960598e1a2SLisandro Dalcin 1970598e1a2SLisandro Dalcin typedef struct { 198698a79b9SLisandro Dalcin PetscViewer viewer; 199698a79b9SLisandro Dalcin int fileFormat; 200698a79b9SLisandro Dalcin int dataSize; 201698a79b9SLisandro Dalcin PetscBool binary; 202698a79b9SLisandro Dalcin PetscBool byteSwap; 203698a79b9SLisandro Dalcin size_t wlen; 204698a79b9SLisandro Dalcin void *wbuf; 205698a79b9SLisandro Dalcin size_t slen; 206698a79b9SLisandro Dalcin void *sbuf; 2070598e1a2SLisandro Dalcin PetscInt *nbuf; 2080598e1a2SLisandro Dalcin PetscInt nodeStart; 2090598e1a2SLisandro Dalcin PetscInt nodeEnd; 21033a088b6SMatthew G. Knepley PetscInt *nodeMap; 211698a79b9SLisandro Dalcin } GmshFile; 212de78e4feSLisandro Dalcin 213d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshBufferGet(GmshFile *gmsh, size_t count, size_t eltsize, void *buf) 214d71ae5a4SJacob Faibussowitsch { 215de78e4feSLisandro Dalcin size_t size = count * eltsize; 21611c56cb0SLisandro Dalcin 21711c56cb0SLisandro Dalcin PetscFunctionBegin; 218698a79b9SLisandro Dalcin if (gmsh->wlen < size) { 2199566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->wbuf)); 2209566063dSJacob Faibussowitsch PetscCall(PetscMalloc(size, &gmsh->wbuf)); 221698a79b9SLisandro Dalcin gmsh->wlen = size; 222de78e4feSLisandro Dalcin } 223698a79b9SLisandro Dalcin *(void **)buf = size ? gmsh->wbuf : NULL; 2243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 225de78e4feSLisandro Dalcin } 226de78e4feSLisandro Dalcin 227d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshBufferSizeGet(GmshFile *gmsh, size_t count, void *buf) 228d71ae5a4SJacob Faibussowitsch { 229698a79b9SLisandro Dalcin size_t dataSize = (size_t)gmsh->dataSize; 230698a79b9SLisandro Dalcin size_t size = count * dataSize; 231698a79b9SLisandro Dalcin 232698a79b9SLisandro Dalcin PetscFunctionBegin; 233698a79b9SLisandro Dalcin if (gmsh->slen < size) { 2349566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->sbuf)); 2359566063dSJacob Faibussowitsch PetscCall(PetscMalloc(size, &gmsh->sbuf)); 236698a79b9SLisandro Dalcin gmsh->slen = size; 237698a79b9SLisandro Dalcin } 238698a79b9SLisandro Dalcin *(void **)buf = size ? gmsh->sbuf : NULL; 2393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 240698a79b9SLisandro Dalcin } 241698a79b9SLisandro Dalcin 242d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshRead(GmshFile *gmsh, void *buf, PetscInt count, PetscDataType dtype) 243d71ae5a4SJacob Faibussowitsch { 244de78e4feSLisandro Dalcin PetscFunctionBegin; 2459566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(gmsh->viewer, buf, count, NULL, dtype)); 2469566063dSJacob Faibussowitsch if (gmsh->byteSwap) PetscCall(PetscByteSwap(buf, dtype, count)); 2473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 248698a79b9SLisandro Dalcin } 249698a79b9SLisandro Dalcin 250d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadString(GmshFile *gmsh, char *buf, PetscInt count) 251d71ae5a4SJacob Faibussowitsch { 252698a79b9SLisandro Dalcin PetscFunctionBegin; 2539566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(gmsh->viewer, buf, count, NULL, PETSC_STRING)); 2543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 255698a79b9SLisandro Dalcin } 256698a79b9SLisandro Dalcin 257d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMatch(PETSC_UNUSED GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN], PetscBool *match) 258d71ae5a4SJacob Faibussowitsch { 259d6689ca9SLisandro Dalcin PetscFunctionBegin; 2609566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(line, Section, match)); 2613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 262d6689ca9SLisandro Dalcin } 263d6689ca9SLisandro Dalcin 264d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshExpect(GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN]) 265d71ae5a4SJacob Faibussowitsch { 266d6689ca9SLisandro Dalcin PetscBool match; 267d6689ca9SLisandro Dalcin 268d6689ca9SLisandro Dalcin PetscFunctionBegin; 2699566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, Section, line, &match)); 2708749820aSMatthew G. Knepley PetscCheck(match, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file, expecting %s\nnot %s", Section, line); 2713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 272d6689ca9SLisandro Dalcin } 273d6689ca9SLisandro Dalcin 274d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadSection(GmshFile *gmsh, char line[PETSC_MAX_PATH_LEN]) 275d71ae5a4SJacob Faibussowitsch { 276d6689ca9SLisandro Dalcin PetscBool match; 277d6689ca9SLisandro Dalcin 278d6689ca9SLisandro Dalcin PetscFunctionBegin; 279d6689ca9SLisandro Dalcin while (PETSC_TRUE) { 2809566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1)); 2819566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$Comments", line, &match)); 282d6689ca9SLisandro Dalcin if (!match) break; 283d6689ca9SLisandro Dalcin while (PETSC_TRUE) { 2849566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1)); 2859566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$EndComments", line, &match)); 286d6689ca9SLisandro Dalcin if (match) break; 287d6689ca9SLisandro Dalcin } 288d6689ca9SLisandro Dalcin } 2893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 290d6689ca9SLisandro Dalcin } 291d6689ca9SLisandro Dalcin 292d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEndSection(GmshFile *gmsh, const char EndSection[], char line[PETSC_MAX_PATH_LEN]) 293d71ae5a4SJacob Faibussowitsch { 294d6689ca9SLisandro Dalcin PetscFunctionBegin; 2959566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1)); 2969566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, EndSection, line)); 2973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 298d6689ca9SLisandro Dalcin } 299d6689ca9SLisandro Dalcin 300d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadSize(GmshFile *gmsh, PetscInt *buf, PetscInt count) 301d71ae5a4SJacob Faibussowitsch { 302698a79b9SLisandro Dalcin PetscInt i; 303698a79b9SLisandro Dalcin size_t dataSize = (size_t)gmsh->dataSize; 304698a79b9SLisandro Dalcin 305698a79b9SLisandro Dalcin PetscFunctionBegin; 306698a79b9SLisandro Dalcin if (dataSize == sizeof(PetscInt)) { 3079566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, buf, count, PETSC_INT)); 308698a79b9SLisandro Dalcin } else if (dataSize == sizeof(int)) { 309698a79b9SLisandro Dalcin int *ibuf = NULL; 3109566063dSJacob Faibussowitsch PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf)); 3119566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, ibuf, count, PETSC_ENUM)); 312698a79b9SLisandro Dalcin for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 313698a79b9SLisandro Dalcin } else if (dataSize == sizeof(long)) { 314698a79b9SLisandro Dalcin long *ibuf = NULL; 3159566063dSJacob Faibussowitsch PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf)); 3169566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, ibuf, count, PETSC_LONG)); 317698a79b9SLisandro Dalcin for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 318698a79b9SLisandro Dalcin } else if (dataSize == sizeof(PetscInt64)) { 319698a79b9SLisandro Dalcin PetscInt64 *ibuf = NULL; 3209566063dSJacob Faibussowitsch PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf)); 3219566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, ibuf, count, PETSC_INT64)); 322698a79b9SLisandro Dalcin for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 323698a79b9SLisandro Dalcin } 3243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 325698a79b9SLisandro Dalcin } 326698a79b9SLisandro Dalcin 327d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadInt(GmshFile *gmsh, int *buf, PetscInt count) 328d71ae5a4SJacob Faibussowitsch { 329698a79b9SLisandro Dalcin PetscFunctionBegin; 3309566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, buf, count, PETSC_ENUM)); 3313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 332698a79b9SLisandro Dalcin } 333698a79b9SLisandro Dalcin 334d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadDouble(GmshFile *gmsh, double *buf, PetscInt count) 335d71ae5a4SJacob Faibussowitsch { 336698a79b9SLisandro Dalcin PetscFunctionBegin; 3379566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, buf, count, PETSC_DOUBLE)); 3383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 339de78e4feSLisandro Dalcin } 340de78e4feSLisandro Dalcin 3419c0edc59SMatthew G. Knepley #define GMSH_MAX_TAGS 16 3427d5b9244SMatthew G. Knepley 343de78e4feSLisandro Dalcin typedef struct { 3440598e1a2SLisandro Dalcin PetscInt id; /* Entity ID */ 3450598e1a2SLisandro Dalcin PetscInt dim; /* Dimension */ 346de78e4feSLisandro Dalcin double bbox[6]; /* Bounding box */ 347de78e4feSLisandro Dalcin PetscInt numTags; /* Size of tag array */ 3487d5b9244SMatthew G. Knepley int tags[GMSH_MAX_TAGS]; /* Tag array */ 349de78e4feSLisandro Dalcin } GmshEntity; 350de78e4feSLisandro Dalcin 351de78e4feSLisandro Dalcin typedef struct { 352730356f6SLisandro Dalcin GmshEntity *entity[4]; 353730356f6SLisandro Dalcin PetscHMapI entityMap[4]; 354730356f6SLisandro Dalcin } GmshEntities; 355730356f6SLisandro Dalcin 356d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesCreate(PetscInt count[4], GmshEntities **entities) 357d71ae5a4SJacob Faibussowitsch { 358730356f6SLisandro Dalcin PetscInt dim; 359730356f6SLisandro Dalcin 360730356f6SLisandro Dalcin PetscFunctionBegin; 3619566063dSJacob Faibussowitsch PetscCall(PetscNew(entities)); 362730356f6SLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 3639566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(count[dim], &(*entities)->entity[dim])); 3649566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&(*entities)->entityMap[dim])); 365730356f6SLisandro Dalcin } 3663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 367730356f6SLisandro Dalcin } 368730356f6SLisandro Dalcin 369d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesDestroy(GmshEntities **entities) 370d71ae5a4SJacob Faibussowitsch { 3710598e1a2SLisandro Dalcin PetscInt dim; 3720598e1a2SLisandro Dalcin 3730598e1a2SLisandro Dalcin PetscFunctionBegin; 3743ba16761SJacob Faibussowitsch if (!*entities) PetscFunctionReturn(PETSC_SUCCESS); 3750598e1a2SLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 3769566063dSJacob Faibussowitsch PetscCall(PetscFree((*entities)->entity[dim])); 3779566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&(*entities)->entityMap[dim])); 3780598e1a2SLisandro Dalcin } 379*f4f49eeaSPierre Jolivet PetscCall(PetscFree(*entities)); 3803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3810598e1a2SLisandro Dalcin } 3820598e1a2SLisandro Dalcin 383d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesAdd(GmshEntities *entities, PetscInt index, PetscInt dim, PetscInt eid, GmshEntity **entity) 384d71ae5a4SJacob Faibussowitsch { 385730356f6SLisandro Dalcin PetscFunctionBegin; 3869566063dSJacob Faibussowitsch PetscCall(PetscHMapISet(entities->entityMap[dim], eid, index)); 387730356f6SLisandro Dalcin entities->entity[dim][index].dim = dim; 388730356f6SLisandro Dalcin entities->entity[dim][index].id = eid; 389730356f6SLisandro Dalcin if (entity) *entity = &entities->entity[dim][index]; 3903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 391730356f6SLisandro Dalcin } 392730356f6SLisandro Dalcin 393d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesGet(GmshEntities *entities, PetscInt dim, PetscInt eid, GmshEntity **entity) 394d71ae5a4SJacob Faibussowitsch { 395730356f6SLisandro Dalcin PetscInt index; 396730356f6SLisandro Dalcin 397730356f6SLisandro Dalcin PetscFunctionBegin; 3989566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(entities->entityMap[dim], eid, &index)); 399730356f6SLisandro Dalcin *entity = &entities->entity[dim][index]; 4003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 401730356f6SLisandro Dalcin } 402730356f6SLisandro Dalcin 4030598e1a2SLisandro Dalcin typedef struct { 4040598e1a2SLisandro Dalcin PetscInt *id; /* Node IDs */ 4050598e1a2SLisandro Dalcin double *xyz; /* Coordinates */ 40681a1af93SMatthew G. Knepley PetscInt *tag; /* Physical tag */ 4070598e1a2SLisandro Dalcin } GmshNodes; 4080598e1a2SLisandro Dalcin 409d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshNodesCreate(PetscInt count, GmshNodes **nodes) 410d71ae5a4SJacob Faibussowitsch { 411730356f6SLisandro Dalcin PetscFunctionBegin; 4129566063dSJacob Faibussowitsch PetscCall(PetscNew(nodes)); 4139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(count * 1, &(*nodes)->id)); 4149566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(count * 3, &(*nodes)->xyz)); 4157d5b9244SMatthew G. Knepley PetscCall(PetscMalloc1(count * GMSH_MAX_TAGS, &(*nodes)->tag)); 4163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 417730356f6SLisandro Dalcin } 4180598e1a2SLisandro Dalcin 419d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshNodesDestroy(GmshNodes **nodes) 420d71ae5a4SJacob Faibussowitsch { 4210598e1a2SLisandro Dalcin PetscFunctionBegin; 4223ba16761SJacob Faibussowitsch if (!*nodes) PetscFunctionReturn(PETSC_SUCCESS); 4239566063dSJacob Faibussowitsch PetscCall(PetscFree((*nodes)->id)); 4249566063dSJacob Faibussowitsch PetscCall(PetscFree((*nodes)->xyz)); 4259566063dSJacob Faibussowitsch PetscCall(PetscFree((*nodes)->tag)); 426*f4f49eeaSPierre Jolivet PetscCall(PetscFree(*nodes)); 4273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 428730356f6SLisandro Dalcin } 429730356f6SLisandro Dalcin 430730356f6SLisandro Dalcin typedef struct { 4310598e1a2SLisandro Dalcin PetscInt id; /* Element ID */ 4320598e1a2SLisandro Dalcin PetscInt dim; /* Dimension */ 433de78e4feSLisandro Dalcin PetscInt cellType; /* Cell type */ 4340598e1a2SLisandro Dalcin PetscInt numVerts; /* Size of vertex array */ 435de78e4feSLisandro Dalcin PetscInt numNodes; /* Size of node array */ 4360598e1a2SLisandro Dalcin PetscInt *nodes; /* Vertex/Node array */ 43781a1af93SMatthew G. Knepley PetscInt numTags; /* Size of physical tag array */ 4387d5b9244SMatthew G. Knepley int tags[GMSH_MAX_TAGS]; /* Physical tag array */ 439de78e4feSLisandro Dalcin } GmshElement; 440de78e4feSLisandro Dalcin 441d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshElementsCreate(PetscInt count, GmshElement **elements) 442d71ae5a4SJacob Faibussowitsch { 4430598e1a2SLisandro Dalcin PetscFunctionBegin; 4449566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(count, elements)); 4453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4460598e1a2SLisandro Dalcin } 4470598e1a2SLisandro Dalcin 448d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshElementsDestroy(GmshElement **elements) 449d71ae5a4SJacob Faibussowitsch { 4500598e1a2SLisandro Dalcin PetscFunctionBegin; 4513ba16761SJacob Faibussowitsch if (!*elements) PetscFunctionReturn(PETSC_SUCCESS); 4529566063dSJacob Faibussowitsch PetscCall(PetscFree(*elements)); 4533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4540598e1a2SLisandro Dalcin } 4550598e1a2SLisandro Dalcin 4560598e1a2SLisandro Dalcin typedef struct { 4570598e1a2SLisandro Dalcin PetscInt dim; 458066ea43fSLisandro Dalcin PetscInt order; 4590598e1a2SLisandro Dalcin GmshEntities *entities; 4600598e1a2SLisandro Dalcin PetscInt numNodes; 4610598e1a2SLisandro Dalcin GmshNodes *nodelist; 4620598e1a2SLisandro Dalcin PetscInt numElems; 4630598e1a2SLisandro Dalcin GmshElement *elements; 4640598e1a2SLisandro Dalcin PetscInt numVerts; 4650598e1a2SLisandro Dalcin PetscInt numCells; 4660598e1a2SLisandro Dalcin PetscInt *periodMap; 4670598e1a2SLisandro Dalcin PetscInt *vertexMap; 4680598e1a2SLisandro Dalcin PetscSegBuffer segbuf; 469a45dabc8SMatthew G. Knepley PetscInt numRegions; 47090d778b8SLisandro Dalcin PetscInt *regionDims; 471a45dabc8SMatthew G. Knepley PetscInt *regionTags; 472a45dabc8SMatthew G. Knepley char **regionNames; 4730598e1a2SLisandro Dalcin } GmshMesh; 4740598e1a2SLisandro Dalcin 475d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMeshCreate(GmshMesh **mesh) 476d71ae5a4SJacob Faibussowitsch { 4770598e1a2SLisandro Dalcin PetscFunctionBegin; 4789566063dSJacob Faibussowitsch PetscCall(PetscNew(mesh)); 4799566063dSJacob Faibussowitsch PetscCall(PetscSegBufferCreate(sizeof(PetscInt), 0, &(*mesh)->segbuf)); 4803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4810598e1a2SLisandro Dalcin } 4820598e1a2SLisandro Dalcin 483d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMeshDestroy(GmshMesh **mesh) 484d71ae5a4SJacob Faibussowitsch { 485a45dabc8SMatthew G. Knepley PetscInt r; 4860598e1a2SLisandro Dalcin 4870598e1a2SLisandro Dalcin PetscFunctionBegin; 4883ba16761SJacob Faibussowitsch if (!*mesh) PetscFunctionReturn(PETSC_SUCCESS); 4899566063dSJacob Faibussowitsch PetscCall(GmshEntitiesDestroy(&(*mesh)->entities)); 4909566063dSJacob Faibussowitsch PetscCall(GmshNodesDestroy(&(*mesh)->nodelist)); 4919566063dSJacob Faibussowitsch PetscCall(GmshElementsDestroy(&(*mesh)->elements)); 4929566063dSJacob Faibussowitsch PetscCall(PetscFree((*mesh)->periodMap)); 4939566063dSJacob Faibussowitsch PetscCall(PetscFree((*mesh)->vertexMap)); 4949566063dSJacob Faibussowitsch PetscCall(PetscSegBufferDestroy(&(*mesh)->segbuf)); 4959566063dSJacob Faibussowitsch for (r = 0; r < (*mesh)->numRegions; ++r) PetscCall(PetscFree((*mesh)->regionNames[r])); 49690d778b8SLisandro Dalcin PetscCall(PetscFree3((*mesh)->regionDims, (*mesh)->regionTags, (*mesh)->regionNames)); 497*f4f49eeaSPierre Jolivet PetscCall(PetscFree(*mesh)); 4983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4990598e1a2SLisandro Dalcin } 5000598e1a2SLisandro Dalcin 501d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v22(GmshFile *gmsh, GmshMesh *mesh) 502d71ae5a4SJacob Faibussowitsch { 503698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 504698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 505de78e4feSLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 5067d5b9244SMatthew G. Knepley int n, t, num, nid, snum; 5070598e1a2SLisandro Dalcin GmshNodes *nodes; 508de78e4feSLisandro Dalcin 509de78e4feSLisandro Dalcin PetscFunctionBegin; 5109566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 511698a79b9SLisandro Dalcin snum = sscanf(line, "%d", &num); 51208401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 5139566063dSJacob Faibussowitsch PetscCall(GmshNodesCreate(num, &nodes)); 5140598e1a2SLisandro Dalcin mesh->numNodes = num; 5150598e1a2SLisandro Dalcin mesh->nodelist = nodes; 5160598e1a2SLisandro Dalcin for (n = 0; n < num; ++n) { 5170598e1a2SLisandro Dalcin double *xyz = nodes->xyz + n * 3; 5189566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM)); 5199566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE)); 5209566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1)); 5219566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3)); 5220598e1a2SLisandro Dalcin nodes->id[n] = nid; 5237d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1; 52411c56cb0SLisandro Dalcin } 5253ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52611c56cb0SLisandro Dalcin } 52711c56cb0SLisandro Dalcin 528de78e4feSLisandro Dalcin /* Gmsh elements can be of any dimension/co-dimension, so we need to traverse the 529de78e4feSLisandro Dalcin file contents multiple times to figure out the true number of cells and facets 530de78e4feSLisandro Dalcin in the given mesh. To make this more efficient we read the file contents only 531de78e4feSLisandro Dalcin once and store them in memory, while determining the true number of cells. */ 532d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v22(GmshFile *gmsh, GmshMesh *mesh) 533d71ae5a4SJacob Faibussowitsch { 534698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 535698a79b9SLisandro Dalcin PetscBool binary = gmsh->binary; 536698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 537de78e4feSLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 5380598e1a2SLisandro Dalcin int i, c, p, num, ibuf[1 + 4 + 1000], snum; 5390598e1a2SLisandro Dalcin int cellType, numElem, numVerts, numNodes, numTags; 540df032b82SMatthew G. Knepley GmshElement *elements; 5410598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 542df032b82SMatthew G. Knepley 543df032b82SMatthew G. Knepley PetscFunctionBegin; 5449566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 545698a79b9SLisandro Dalcin snum = sscanf(line, "%d", &num); 54608401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 5479566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(num, &elements)); 5480598e1a2SLisandro Dalcin mesh->numElems = num; 5490598e1a2SLisandro Dalcin mesh->elements = elements; 550698a79b9SLisandro Dalcin for (c = 0; c < num;) { 5519566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM)); 5529566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 3)); 5530598e1a2SLisandro Dalcin 5540598e1a2SLisandro Dalcin cellType = binary ? ibuf[0] : ibuf[1]; 5550598e1a2SLisandro Dalcin numElem = binary ? ibuf[1] : 1; 556df032b82SMatthew G. Knepley numTags = ibuf[2]; 5570598e1a2SLisandro Dalcin 5589566063dSJacob Faibussowitsch PetscCall(GmshCellTypeCheck(cellType)); 5590598e1a2SLisandro Dalcin numVerts = GmshCellMap[cellType].numVerts; 5600598e1a2SLisandro Dalcin numNodes = GmshCellMap[cellType].numNodes; 5610598e1a2SLisandro Dalcin 562df032b82SMatthew G. Knepley for (i = 0; i < numElem; ++i, ++c) { 5630598e1a2SLisandro Dalcin GmshElement *element = elements + c; 5640598e1a2SLisandro Dalcin const int off = binary ? 0 : 1, nint = 1 + numTags + numNodes - off; 5650598e1a2SLisandro Dalcin const int *id = ibuf, *nodes = ibuf + 1 + numTags, *tags = ibuf + 1; 5669566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf + off, nint, NULL, PETSC_ENUM)); 5679566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf + off, PETSC_ENUM, nint)); 5680598e1a2SLisandro Dalcin element->id = id[0]; 5690598e1a2SLisandro Dalcin element->dim = GmshCellMap[cellType].dim; 5700598e1a2SLisandro Dalcin element->cellType = cellType; 5710598e1a2SLisandro Dalcin element->numVerts = numVerts; 5720598e1a2SLisandro Dalcin element->numNodes = numNodes; 5737d5b9244SMatthew G. Knepley element->numTags = PetscMin(numTags, GMSH_MAX_TAGS); 5749566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes)); 5750598e1a2SLisandro Dalcin for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 5760598e1a2SLisandro Dalcin for (p = 0; p < element->numTags; p++) element->tags[p] = tags[p]; 577df032b82SMatthew G. Knepley } 578df032b82SMatthew G. Knepley } 5793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 580df032b82SMatthew G. Knepley } 5817d282ae0SMichael Lange 582de78e4feSLisandro Dalcin /* 583de78e4feSLisandro Dalcin $Entities 584de78e4feSLisandro Dalcin numPoints(unsigned long) numCurves(unsigned long) 585de78e4feSLisandro Dalcin numSurfaces(unsigned long) numVolumes(unsigned long) 586de78e4feSLisandro Dalcin // points 587de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 588de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 589de78e4feSLisandro Dalcin numPhysicals(unsigned long) phyisicalTag[...](int) 590de78e4feSLisandro Dalcin ... 591de78e4feSLisandro Dalcin // curves 592de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 593de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 594de78e4feSLisandro Dalcin numPhysicals(unsigned long) physicalTag[...](int) 595de78e4feSLisandro Dalcin numBREPVert(unsigned long) tagBREPVert[...](int) 596de78e4feSLisandro Dalcin ... 597de78e4feSLisandro Dalcin // surfaces 598de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 599de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 600de78e4feSLisandro Dalcin numPhysicals(unsigned long) physicalTag[...](int) 601de78e4feSLisandro Dalcin numBREPCurve(unsigned long) tagBREPCurve[...](int) 602de78e4feSLisandro Dalcin ... 603de78e4feSLisandro Dalcin // volumes 604de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 605de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 606de78e4feSLisandro Dalcin numPhysicals(unsigned long) physicalTag[...](int) 607de78e4feSLisandro Dalcin numBREPSurfaces(unsigned long) tagBREPSurfaces[...](int) 608de78e4feSLisandro Dalcin ... 609de78e4feSLisandro Dalcin $EndEntities 610de78e4feSLisandro Dalcin */ 611d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities_v40(GmshFile *gmsh, GmshMesh *mesh) 612d71ae5a4SJacob Faibussowitsch { 613698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 614698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 615698a79b9SLisandro Dalcin long index, num, lbuf[4]; 616730356f6SLisandro Dalcin int dim, eid, numTags, *ibuf, t; 617698a79b9SLisandro Dalcin PetscInt count[4], i; 618a5ba3d71SLisandro Dalcin GmshEntity *entity = NULL; 619de78e4feSLisandro Dalcin 620de78e4feSLisandro Dalcin PetscFunctionBegin; 6219566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, lbuf, 4, NULL, PETSC_LONG)); 6229566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(lbuf, PETSC_LONG, 4)); 623698a79b9SLisandro Dalcin for (i = 0; i < 4; ++i) count[i] = lbuf[i]; 6249566063dSJacob Faibussowitsch PetscCall(GmshEntitiesCreate(count, &mesh->entities)); 625de78e4feSLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 626730356f6SLisandro Dalcin for (index = 0; index < count[dim]; ++index) { 6279566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &eid, 1, NULL, PETSC_ENUM)); 6289566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&eid, PETSC_ENUM, 1)); 6299566063dSJacob Faibussowitsch PetscCall(GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity)); 6309566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, entity->bbox, 6, NULL, PETSC_DOUBLE)); 6319566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(entity->bbox, PETSC_DOUBLE, 6)); 6329566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &num, 1, NULL, PETSC_LONG)); 6339566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&num, PETSC_LONG, 1)); 6349566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, num, sizeof(int), &ibuf)); 6359566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM)); 6369566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, num)); 6377d5b9244SMatthew G. Knepley entity->numTags = numTags = (int)PetscMin(num, GMSH_MAX_TAGS); 638de78e4feSLisandro Dalcin for (t = 0; t < numTags; ++t) entity->tags[t] = ibuf[t]; 639de78e4feSLisandro Dalcin if (dim == 0) continue; 6409566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &num, 1, NULL, PETSC_LONG)); 6419566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&num, PETSC_LONG, 1)); 6429566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, num, sizeof(int), &ibuf)); 6439566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM)); 6449566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, num)); 645de78e4feSLisandro Dalcin } 646de78e4feSLisandro Dalcin } 6473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 648de78e4feSLisandro Dalcin } 649de78e4feSLisandro Dalcin 650de78e4feSLisandro Dalcin /* 651de78e4feSLisandro Dalcin $Nodes 652de78e4feSLisandro Dalcin numEntityBlocks(unsigned long) numNodes(unsigned long) 653de78e4feSLisandro Dalcin tagEntity(int) dimEntity(int) typeNode(int) numNodes(unsigned long) 654de78e4feSLisandro Dalcin tag(int) x(double) y(double) z(double) 655de78e4feSLisandro Dalcin ... 656de78e4feSLisandro Dalcin ... 657de78e4feSLisandro Dalcin $EndNodes 658de78e4feSLisandro Dalcin */ 659d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v40(GmshFile *gmsh, GmshMesh *mesh) 660d71ae5a4SJacob Faibussowitsch { 661698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 662698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 6637d5b9244SMatthew G. Knepley long block, node, n, t, numEntityBlocks, numTotalNodes, numNodes; 664de78e4feSLisandro Dalcin int info[3], nid; 6650598e1a2SLisandro Dalcin GmshNodes *nodes; 666de78e4feSLisandro Dalcin 667de78e4feSLisandro Dalcin PetscFunctionBegin; 6689566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG)); 6699566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1)); 6709566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numTotalNodes, 1, NULL, PETSC_LONG)); 6719566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numTotalNodes, PETSC_LONG, 1)); 6729566063dSJacob Faibussowitsch PetscCall(GmshNodesCreate(numTotalNodes, &nodes)); 6730598e1a2SLisandro Dalcin mesh->numNodes = numTotalNodes; 6740598e1a2SLisandro Dalcin mesh->nodelist = nodes; 6750598e1a2SLisandro Dalcin for (n = 0, block = 0; block < numEntityBlocks; ++block) { 6769566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM)); 6779566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numNodes, 1, NULL, PETSC_LONG)); 6789566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numNodes, PETSC_LONG, 1)); 679698a79b9SLisandro Dalcin if (gmsh->binary) { 680277f51e8SBarry Smith size_t nbytes = sizeof(int) + 3 * sizeof(double); 681da81f932SPierre Jolivet char *cbuf = NULL; /* dummy value to prevent warning from compiler about possible uninitialized value */ 6829566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numNodes, nbytes, &cbuf)); 6839566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, cbuf, numNodes * nbytes, NULL, PETSC_CHAR)); 6840598e1a2SLisandro Dalcin for (node = 0; node < numNodes; ++node, ++n) { 685de78e4feSLisandro Dalcin char *cnid = cbuf + node * nbytes, *cxyz = cnid + sizeof(int); 6860598e1a2SLisandro Dalcin double *xyz = nodes->xyz + n * 3; 6879566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(cnid, PETSC_ENUM, 1)); 6889566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(cxyz, PETSC_DOUBLE, 3)); 6899566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&nid, cnid, sizeof(int))); 6909566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(xyz, cxyz, 3 * sizeof(double))); 6919566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1)); 6929566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3)); 6930598e1a2SLisandro Dalcin nodes->id[n] = nid; 6947d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1; 695de78e4feSLisandro Dalcin } 696de78e4feSLisandro Dalcin } else { 6970598e1a2SLisandro Dalcin for (node = 0; node < numNodes; ++node, ++n) { 6980598e1a2SLisandro Dalcin double *xyz = nodes->xyz + n * 3; 6999566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM)); 7009566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE)); 7019566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1)); 7029566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3)); 7030598e1a2SLisandro Dalcin nodes->id[n] = nid; 7047d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1; 705de78e4feSLisandro Dalcin } 706de78e4feSLisandro Dalcin } 707de78e4feSLisandro Dalcin } 7083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 709de78e4feSLisandro Dalcin } 710de78e4feSLisandro Dalcin 711de78e4feSLisandro Dalcin /* 712de78e4feSLisandro Dalcin $Elements 713de78e4feSLisandro Dalcin numEntityBlocks(unsigned long) numElements(unsigned long) 714de78e4feSLisandro Dalcin tagEntity(int) dimEntity(int) typeEle(int) numElements(unsigned long) 715de78e4feSLisandro Dalcin tag(int) numVert[...](int) 716de78e4feSLisandro Dalcin ... 717de78e4feSLisandro Dalcin ... 718de78e4feSLisandro Dalcin $EndElements 719de78e4feSLisandro Dalcin */ 720d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v40(GmshFile *gmsh, GmshMesh *mesh) 721d71ae5a4SJacob Faibussowitsch { 722698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 723698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 724de78e4feSLisandro Dalcin long c, block, numEntityBlocks, numTotalElements, elem, numElements; 725de78e4feSLisandro Dalcin int p, info[3], *ibuf = NULL; 7260598e1a2SLisandro Dalcin int eid, dim, cellType, numVerts, numNodes, numTags; 727a5ba3d71SLisandro Dalcin GmshEntity *entity = NULL; 728de78e4feSLisandro Dalcin GmshElement *elements; 7290598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 730de78e4feSLisandro Dalcin 731de78e4feSLisandro Dalcin PetscFunctionBegin; 7329566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG)); 7339566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1)); 7349566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numTotalElements, 1, NULL, PETSC_LONG)); 7359566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numTotalElements, PETSC_LONG, 1)); 7369566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(numTotalElements, &elements)); 7370598e1a2SLisandro Dalcin mesh->numElems = numTotalElements; 7380598e1a2SLisandro Dalcin mesh->elements = elements; 739de78e4feSLisandro Dalcin for (c = 0, block = 0; block < numEntityBlocks; ++block) { 7409566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM)); 7419566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(info, PETSC_ENUM, 3)); 7429371c9d4SSatish Balay eid = info[0]; 7439371c9d4SSatish Balay dim = info[1]; 7449371c9d4SSatish Balay cellType = info[2]; 7459566063dSJacob Faibussowitsch PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity)); 7469566063dSJacob Faibussowitsch PetscCall(GmshCellTypeCheck(cellType)); 7470598e1a2SLisandro Dalcin numVerts = GmshCellMap[cellType].numVerts; 7480598e1a2SLisandro Dalcin numNodes = GmshCellMap[cellType].numNodes; 749730356f6SLisandro Dalcin numTags = entity->numTags; 7509566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numElements, 1, NULL, PETSC_LONG)); 7519566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numElements, PETSC_LONG, 1)); 7529566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, (1 + numNodes) * numElements, sizeof(int), &ibuf)); 7539566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, (1 + numNodes) * numElements, NULL, PETSC_ENUM)); 7549566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, (1 + numNodes) * numElements)); 755de78e4feSLisandro Dalcin for (elem = 0; elem < numElements; ++elem, ++c) { 756de78e4feSLisandro Dalcin GmshElement *element = elements + c; 7570598e1a2SLisandro Dalcin const int *id = ibuf + elem * (1 + numNodes), *nodes = id + 1; 7580598e1a2SLisandro Dalcin element->id = id[0]; 759de78e4feSLisandro Dalcin element->dim = dim; 760de78e4feSLisandro Dalcin element->cellType = cellType; 7610598e1a2SLisandro Dalcin element->numVerts = numVerts; 762de78e4feSLisandro Dalcin element->numNodes = numNodes; 763de78e4feSLisandro Dalcin element->numTags = numTags; 7649566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes)); 7650598e1a2SLisandro Dalcin for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 7660598e1a2SLisandro Dalcin for (p = 0; p < element->numTags; p++) element->tags[p] = entity->tags[p]; 767de78e4feSLisandro Dalcin } 768de78e4feSLisandro Dalcin } 7693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 770698a79b9SLisandro Dalcin } 771698a79b9SLisandro Dalcin 772d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic_v40(GmshFile *gmsh, PetscInt periodicMap[]) 773d71ae5a4SJacob Faibussowitsch { 774698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 775698a79b9SLisandro Dalcin int fileFormat = gmsh->fileFormat; 776698a79b9SLisandro Dalcin PetscBool binary = gmsh->binary; 777698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 778698a79b9SLisandro Dalcin int numPeriodic, snum, i; 779698a79b9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 7800598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 781698a79b9SLisandro Dalcin 782698a79b9SLisandro Dalcin PetscFunctionBegin; 783698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 7849566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 785698a79b9SLisandro Dalcin snum = sscanf(line, "%d", &numPeriodic); 78608401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 787698a79b9SLisandro Dalcin } else { 7889566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numPeriodic, 1, NULL, PETSC_ENUM)); 7899566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numPeriodic, PETSC_ENUM, 1)); 790698a79b9SLisandro Dalcin } 791698a79b9SLisandro Dalcin for (i = 0; i < numPeriodic; i++) { 7929dddd249SSatish Balay int ibuf[3], correspondingDim = -1, correspondingTag = -1, primaryTag = -1, correspondingNode, primaryNode; 793698a79b9SLisandro Dalcin long j, nNodes; 794698a79b9SLisandro Dalcin double affine[16]; 795698a79b9SLisandro Dalcin 796698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 7979566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 3, NULL, PETSC_STRING)); 7989dddd249SSatish Balay snum = sscanf(line, "%d %d %d", &correspondingDim, &correspondingTag, &primaryTag); 79908401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 800698a79b9SLisandro Dalcin } else { 8019566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM)); 8029566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 3)); 8039371c9d4SSatish Balay correspondingDim = ibuf[0]; 8049371c9d4SSatish Balay correspondingTag = ibuf[1]; 8059371c9d4SSatish Balay primaryTag = ibuf[2]; 806698a79b9SLisandro Dalcin } 8079371c9d4SSatish Balay (void)correspondingDim; 8089371c9d4SSatish Balay (void)correspondingTag; 8099371c9d4SSatish Balay (void)primaryTag; /* unused */ 810698a79b9SLisandro Dalcin 811698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 8129566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 813698a79b9SLisandro Dalcin snum = sscanf(line, "%ld", &nNodes); 8144c500f23SPierre Jolivet if (snum != 1) { /* discard transformation and try again */ 8159566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, -PETSC_MAX_PATH_LEN, NULL, PETSC_STRING)); 8169566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 817698a79b9SLisandro Dalcin snum = sscanf(line, "%ld", &nNodes); 81808401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 819698a79b9SLisandro Dalcin } 820698a79b9SLisandro Dalcin } else { 8219566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG)); 8229566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nNodes, PETSC_LONG, 1)); 8234c500f23SPierre Jolivet if (nNodes == -1) { /* discard transformation and try again */ 8249566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, affine, 16, NULL, PETSC_DOUBLE)); 8259566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG)); 8269566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nNodes, PETSC_LONG, 1)); 827698a79b9SLisandro Dalcin } 828698a79b9SLisandro Dalcin } 829698a79b9SLisandro Dalcin 830698a79b9SLisandro Dalcin for (j = 0; j < nNodes; j++) { 831698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 8329566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 2, NULL, PETSC_STRING)); 8339dddd249SSatish Balay snum = sscanf(line, "%d %d", &correspondingNode, &primaryNode); 83408401ef6SPierre Jolivet PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 835698a79b9SLisandro Dalcin } else { 8369566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, 2, NULL, PETSC_ENUM)); 8379566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 2)); 8389371c9d4SSatish Balay correspondingNode = ibuf[0]; 8399371c9d4SSatish Balay primaryNode = ibuf[1]; 840698a79b9SLisandro Dalcin } 8419dddd249SSatish Balay correspondingNode = (int)nodeMap[correspondingNode]; 8429dddd249SSatish Balay primaryNode = (int)nodeMap[primaryNode]; 8439dddd249SSatish Balay periodicMap[correspondingNode] = primaryNode; 844698a79b9SLisandro Dalcin } 845698a79b9SLisandro Dalcin } 8463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 847698a79b9SLisandro Dalcin } 848698a79b9SLisandro Dalcin 8490598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 850698a79b9SLisandro Dalcin $Entities 851698a79b9SLisandro Dalcin numPoints(size_t) numCurves(size_t) 852698a79b9SLisandro Dalcin numSurfaces(size_t) numVolumes(size_t) 853698a79b9SLisandro Dalcin pointTag(int) X(double) Y(double) Z(double) 854698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 855698a79b9SLisandro Dalcin ... 856698a79b9SLisandro Dalcin curveTag(int) minX(double) minY(double) minZ(double) 857698a79b9SLisandro Dalcin maxX(double) maxY(double) maxZ(double) 858698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 859698a79b9SLisandro Dalcin numBoundingPoints(size_t) pointTag(int) ... 860698a79b9SLisandro Dalcin ... 861698a79b9SLisandro Dalcin surfaceTag(int) minX(double) minY(double) minZ(double) 862698a79b9SLisandro Dalcin maxX(double) maxY(double) maxZ(double) 863698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 864698a79b9SLisandro Dalcin numBoundingCurves(size_t) curveTag(int) ... 865698a79b9SLisandro Dalcin ... 866698a79b9SLisandro Dalcin volumeTag(int) minX(double) minY(double) minZ(double) 867698a79b9SLisandro Dalcin maxX(double) maxY(double) maxZ(double) 868698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 869698a79b9SLisandro Dalcin numBoundngSurfaces(size_t) surfaceTag(int) ... 870698a79b9SLisandro Dalcin ... 871698a79b9SLisandro Dalcin $EndEntities 872698a79b9SLisandro Dalcin */ 873d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities_v41(GmshFile *gmsh, GmshMesh *mesh) 874d71ae5a4SJacob Faibussowitsch { 875698a79b9SLisandro Dalcin PetscInt count[4], index, numTags, i; 876698a79b9SLisandro Dalcin int dim, eid, *tags = NULL; 877698a79b9SLisandro Dalcin GmshEntity *entity = NULL; 878698a79b9SLisandro Dalcin 879698a79b9SLisandro Dalcin PetscFunctionBegin; 8809566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, count, 4)); 8819566063dSJacob Faibussowitsch PetscCall(GmshEntitiesCreate(count, &mesh->entities)); 882698a79b9SLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 883698a79b9SLisandro Dalcin for (index = 0; index < count[dim]; ++index) { 8849566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, &eid, 1)); 8859566063dSJacob Faibussowitsch PetscCall(GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity)); 8869566063dSJacob Faibussowitsch PetscCall(GmshReadDouble(gmsh, entity->bbox, (dim == 0) ? 3 : 6)); 8879566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numTags, 1)); 8889566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numTags, sizeof(int), &tags)); 8899566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, tags, numTags)); 8909c0edc59SMatthew G. Knepley PetscCheck(numTags <= GMSH_MAX_TAGS, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PETSc currently supports up to %" PetscInt_FMT " tags per entity, not %" PetscInt_FMT, (PetscInt)GMSH_MAX_TAGS, numTags); 8917d5b9244SMatthew G. Knepley entity->numTags = numTags; 892698a79b9SLisandro Dalcin for (i = 0; i < entity->numTags; ++i) entity->tags[i] = tags[i]; 893698a79b9SLisandro Dalcin if (dim == 0) continue; 8949566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numTags, 1)); 8959566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numTags, sizeof(int), &tags)); 8969566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, tags, numTags)); 89781a1af93SMatthew G. Knepley /* Currently, we do not save the ids for the bounding entities */ 898698a79b9SLisandro Dalcin } 899698a79b9SLisandro Dalcin } 9003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 901698a79b9SLisandro Dalcin } 902698a79b9SLisandro Dalcin 90333a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 904698a79b9SLisandro Dalcin $Nodes 905698a79b9SLisandro Dalcin numEntityBlocks(size_t) numNodes(size_t) 906698a79b9SLisandro Dalcin minNodeTag(size_t) maxNodeTag(size_t) 907698a79b9SLisandro Dalcin entityDim(int) entityTag(int) parametric(int; 0 or 1) numNodesBlock(size_t) 908698a79b9SLisandro Dalcin nodeTag(size_t) 909698a79b9SLisandro Dalcin ... 910698a79b9SLisandro Dalcin x(double) y(double) z(double) 911698a79b9SLisandro Dalcin < u(double; if parametric and entityDim = 1 or entityDim = 2) > 912698a79b9SLisandro Dalcin < v(double; if parametric and entityDim = 2) > 913698a79b9SLisandro Dalcin ... 914698a79b9SLisandro Dalcin ... 915698a79b9SLisandro Dalcin $EndNodes 916698a79b9SLisandro Dalcin */ 917d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v41(GmshFile *gmsh, GmshMesh *mesh) 918d71ae5a4SJacob Faibussowitsch { 91981a1af93SMatthew G. Knepley int info[3], dim, eid, parametric; 9207d5b9244SMatthew G. Knepley PetscInt sizes[4], numEntityBlocks, numTags, t, numNodes, numNodesBlock = 0, block, node, n; 92181a1af93SMatthew G. Knepley GmshEntity *entity = NULL; 9220598e1a2SLisandro Dalcin GmshNodes *nodes; 923698a79b9SLisandro Dalcin 924698a79b9SLisandro Dalcin PetscFunctionBegin; 9259566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, sizes, 4)); 9269371c9d4SSatish Balay numEntityBlocks = sizes[0]; 9279371c9d4SSatish Balay numNodes = sizes[1]; 9289566063dSJacob Faibussowitsch PetscCall(GmshNodesCreate(numNodes, &nodes)); 9290598e1a2SLisandro Dalcin mesh->numNodes = numNodes; 9300598e1a2SLisandro Dalcin mesh->nodelist = nodes; 931698a79b9SLisandro Dalcin for (block = 0, node = 0; block < numEntityBlocks; ++block, node += numNodesBlock) { 9329566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, info, 3)); 9339371c9d4SSatish Balay dim = info[0]; 9349371c9d4SSatish Balay eid = info[1]; 9359371c9d4SSatish Balay parametric = info[2]; 9369566063dSJacob Faibussowitsch PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity)); 9377d5b9244SMatthew G. Knepley numTags = entity->numTags; 93881a1af93SMatthew G. Knepley PetscCheck(!parametric, PETSC_COMM_SELF, PETSC_ERR_SUP, "Parametric coordinates not supported"); 9399566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numNodesBlock, 1)); 9409566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, nodes->id + node, numNodesBlock)); 9419566063dSJacob Faibussowitsch PetscCall(GmshReadDouble(gmsh, nodes->xyz + node * 3, numNodesBlock * 3)); 9427d5b9244SMatthew G. Knepley for (n = 0; n < numNodesBlock; ++n) { 9437d5b9244SMatthew G. Knepley PetscInt *tags = &nodes->tag[node * GMSH_MAX_TAGS]; 9447d5b9244SMatthew G. Knepley 9457d5b9244SMatthew G. Knepley for (t = 0; t < numTags; ++t) tags[n * GMSH_MAX_TAGS + t] = entity->tags[t]; 9467d5b9244SMatthew G. Knepley for (t = numTags; t < GMSH_MAX_TAGS; ++t) tags[n * GMSH_MAX_TAGS + t] = -1; 9477d5b9244SMatthew G. Knepley } 948698a79b9SLisandro Dalcin } 9490598e1a2SLisandro Dalcin gmsh->nodeStart = sizes[2]; 9500598e1a2SLisandro Dalcin gmsh->nodeEnd = sizes[3] + 1; 9513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 952698a79b9SLisandro Dalcin } 953698a79b9SLisandro Dalcin 95433a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 955698a79b9SLisandro Dalcin $Elements 956698a79b9SLisandro Dalcin numEntityBlocks(size_t) numElements(size_t) 957698a79b9SLisandro Dalcin minElementTag(size_t) maxElementTag(size_t) 958698a79b9SLisandro Dalcin entityDim(int) entityTag(int) elementType(int; see below) numElementsBlock(size_t) 959698a79b9SLisandro Dalcin elementTag(size_t) nodeTag(size_t) ... 960698a79b9SLisandro Dalcin ... 961698a79b9SLisandro Dalcin ... 962698a79b9SLisandro Dalcin $EndElements 963698a79b9SLisandro Dalcin */ 964d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v41(GmshFile *gmsh, GmshMesh *mesh) 965d71ae5a4SJacob Faibussowitsch { 9660598e1a2SLisandro Dalcin int info[3], eid, dim, cellType; 9670598e1a2SLisandro Dalcin PetscInt sizes[4], *ibuf = NULL, numEntityBlocks, numElements, numBlockElements, numVerts, numNodes, numTags, block, elem, c, p; 968698a79b9SLisandro Dalcin GmshEntity *entity = NULL; 969698a79b9SLisandro Dalcin GmshElement *elements; 9700598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 971698a79b9SLisandro Dalcin 972698a79b9SLisandro Dalcin PetscFunctionBegin; 9739566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, sizes, 4)); 9749371c9d4SSatish Balay numEntityBlocks = sizes[0]; 9759371c9d4SSatish Balay numElements = sizes[1]; 9769566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(numElements, &elements)); 9770598e1a2SLisandro Dalcin mesh->numElems = numElements; 9780598e1a2SLisandro Dalcin mesh->elements = elements; 979698a79b9SLisandro Dalcin for (c = 0, block = 0; block < numEntityBlocks; ++block) { 9809566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, info, 3)); 9819371c9d4SSatish Balay dim = info[0]; 9829371c9d4SSatish Balay eid = info[1]; 9839371c9d4SSatish Balay cellType = info[2]; 9849566063dSJacob Faibussowitsch PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity)); 9859566063dSJacob Faibussowitsch PetscCall(GmshCellTypeCheck(cellType)); 9860598e1a2SLisandro Dalcin numVerts = GmshCellMap[cellType].numVerts; 9870598e1a2SLisandro Dalcin numNodes = GmshCellMap[cellType].numNodes; 9887d5b9244SMatthew G. Knepley numTags = entity->numTags; 9899566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numBlockElements, 1)); 9909566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, (1 + numNodes) * numBlockElements, sizeof(PetscInt), &ibuf)); 9919566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, ibuf, (1 + numNodes) * numBlockElements)); 992698a79b9SLisandro Dalcin for (elem = 0; elem < numBlockElements; ++elem, ++c) { 993698a79b9SLisandro Dalcin GmshElement *element = elements + c; 9940598e1a2SLisandro Dalcin const PetscInt *id = ibuf + elem * (1 + numNodes), *nodes = id + 1; 995698a79b9SLisandro Dalcin element->id = id[0]; 996698a79b9SLisandro Dalcin element->dim = dim; 997698a79b9SLisandro Dalcin element->cellType = cellType; 9980598e1a2SLisandro Dalcin element->numVerts = numVerts; 999698a79b9SLisandro Dalcin element->numNodes = numNodes; 1000698a79b9SLisandro Dalcin element->numTags = numTags; 10019566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes)); 10020598e1a2SLisandro Dalcin for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 10030598e1a2SLisandro Dalcin for (p = 0; p < element->numTags; p++) element->tags[p] = entity->tags[p]; 1004698a79b9SLisandro Dalcin } 1005698a79b9SLisandro Dalcin } 10063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1007698a79b9SLisandro Dalcin } 1008698a79b9SLisandro Dalcin 10090598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 1010698a79b9SLisandro Dalcin $Periodic 1011698a79b9SLisandro Dalcin numPeriodicLinks(size_t) 10129dddd249SSatish Balay entityDim(int) entityTag(int) entityTagPrimary(int) 1013698a79b9SLisandro Dalcin numAffine(size_t) value(double) ... 1014698a79b9SLisandro Dalcin numCorrespondingNodes(size_t) 10159dddd249SSatish Balay nodeTag(size_t) nodeTagPrimary(size_t) 1016698a79b9SLisandro Dalcin ... 1017698a79b9SLisandro Dalcin ... 1018698a79b9SLisandro Dalcin $EndPeriodic 1019698a79b9SLisandro Dalcin */ 1020d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic_v41(GmshFile *gmsh, PetscInt periodicMap[]) 1021d71ae5a4SJacob Faibussowitsch { 1022698a79b9SLisandro Dalcin int info[3]; 1023698a79b9SLisandro Dalcin double dbuf[16]; 10240598e1a2SLisandro Dalcin PetscInt numPeriodicLinks, numAffine, numCorrespondingNodes, *nodeTags = NULL, link, node; 10250598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 1026698a79b9SLisandro Dalcin 1027698a79b9SLisandro Dalcin PetscFunctionBegin; 10289566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numPeriodicLinks, 1)); 1029698a79b9SLisandro Dalcin for (link = 0; link < numPeriodicLinks; ++link) { 10309566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, info, 3)); 10319566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numAffine, 1)); 10329566063dSJacob Faibussowitsch PetscCall(GmshReadDouble(gmsh, dbuf, numAffine)); 10339566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numCorrespondingNodes, 1)); 10349566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numCorrespondingNodes, sizeof(PetscInt), &nodeTags)); 10359566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, nodeTags, numCorrespondingNodes * 2)); 1036698a79b9SLisandro Dalcin for (node = 0; node < numCorrespondingNodes; ++node) { 10379dddd249SSatish Balay PetscInt correspondingNode = nodeMap[nodeTags[node * 2 + 0]]; 10389dddd249SSatish Balay PetscInt primaryNode = nodeMap[nodeTags[node * 2 + 1]]; 10399dddd249SSatish Balay periodicMap[correspondingNode] = primaryNode; 1040698a79b9SLisandro Dalcin } 1041698a79b9SLisandro Dalcin } 10423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1043698a79b9SLisandro Dalcin } 1044698a79b9SLisandro Dalcin 10450598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 1046d6689ca9SLisandro Dalcin $MeshFormat // same as MSH version 2 1047d6689ca9SLisandro Dalcin version(ASCII double; currently 4.1) 1048d6689ca9SLisandro Dalcin file-type(ASCII int; 0 for ASCII mode, 1 for binary mode) 1049d6689ca9SLisandro Dalcin data-size(ASCII int; sizeof(size_t)) 1050d6689ca9SLisandro Dalcin < int with value one; only in binary mode, to detect endianness > 1051d6689ca9SLisandro Dalcin $EndMeshFormat 1052d6689ca9SLisandro Dalcin */ 1053d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadMeshFormat(GmshFile *gmsh) 1054d71ae5a4SJacob Faibussowitsch { 1055698a79b9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 1056698a79b9SLisandro Dalcin int snum, fileType, fileFormat, dataSize, checkEndian; 1057698a79b9SLisandro Dalcin float version; 1058698a79b9SLisandro Dalcin 1059698a79b9SLisandro Dalcin PetscFunctionBegin; 10609566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 3)); 1061698a79b9SLisandro Dalcin snum = sscanf(line, "%f %d %d", &version, &fileType, &dataSize); 1062a8d4e440SJunchao Zhang fileFormat = (int)roundf(version * 10); 106308401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line); 1064a8d4e440SJunchao Zhang PetscCheck(fileFormat >= 22, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version); 10651dca8a05SBarry Smith PetscCheck((int)version != 3, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version); 1066a8d4e440SJunchao Zhang PetscCheck(fileFormat <= 41, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version); 106708401ef6SPierre Jolivet PetscCheck(!gmsh->binary || fileType, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is binary but Gmsh file is ASCII"); 106808401ef6SPierre Jolivet PetscCheck(gmsh->binary || !fileType, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is ASCII but Gmsh file is binary"); 10691dca8a05SBarry Smith PetscCheck(fileFormat > 40 || dataSize == sizeof(double), PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Data size %d is not valid for a Gmsh file", dataSize); 10701dca8a05SBarry Smith PetscCheck(fileFormat < 41 || dataSize == sizeof(int) || dataSize == sizeof(PetscInt64), PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Data size %d is not valid for a Gmsh file", dataSize); 1071698a79b9SLisandro Dalcin gmsh->fileFormat = fileFormat; 1072698a79b9SLisandro Dalcin gmsh->dataSize = dataSize; 1073698a79b9SLisandro Dalcin gmsh->byteSwap = PETSC_FALSE; 1074698a79b9SLisandro Dalcin if (gmsh->binary) { 10759566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, &checkEndian, 1)); 1076698a79b9SLisandro Dalcin if (checkEndian != 1) { 10779566063dSJacob Faibussowitsch PetscCall(PetscByteSwap(&checkEndian, PETSC_ENUM, 1)); 107808401ef6SPierre Jolivet PetscCheck(checkEndian == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to detect endianness in Gmsh file header: %s", line); 1079698a79b9SLisandro Dalcin gmsh->byteSwap = PETSC_TRUE; 1080698a79b9SLisandro Dalcin } 1081698a79b9SLisandro Dalcin } 10823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1083698a79b9SLisandro Dalcin } 1084698a79b9SLisandro Dalcin 10858749820aSMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 10868749820aSMatthew G. Knepley Neper: https://neper.info/ adds this section 10878749820aSMatthew G. Knepley 10888749820aSMatthew G. Knepley $MeshVersion 10898749820aSMatthew G. Knepley <major>.<minor>,<patch> 10908749820aSMatthew G. Knepley $EndMeshVersion 10918749820aSMatthew G. Knepley */ 10928749820aSMatthew G. Knepley static PetscErrorCode GmshReadMeshVersion(GmshFile *gmsh) 10938749820aSMatthew G. Knepley { 10948749820aSMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 10958749820aSMatthew G. Knepley int snum, major, minor, patch; 10968749820aSMatthew G. Knepley 10978749820aSMatthew G. Knepley PetscFunctionBegin; 10988749820aSMatthew G. Knepley PetscCall(GmshReadString(gmsh, line, 1)); 10998749820aSMatthew G. Knepley snum = sscanf(line, "%d.%d.%d", &major, &minor, &patch); 11008749820aSMatthew G. Knepley PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line); 11018749820aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 11028749820aSMatthew G. Knepley } 11038749820aSMatthew G. Knepley 11048749820aSMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 11058749820aSMatthew G. Knepley Neper: https://neper.info/ adds this section 11068749820aSMatthew G. Knepley 11078749820aSMatthew G. Knepley $Domain 11088749820aSMatthew G. Knepley <shape> 11098749820aSMatthew G. Knepley $EndDomain 11108749820aSMatthew G. Knepley */ 11118749820aSMatthew G. Knepley static PetscErrorCode GmshReadMeshDomain(GmshFile *gmsh) 11128749820aSMatthew G. Knepley { 11138749820aSMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 11148749820aSMatthew G. Knepley 11158749820aSMatthew G. Knepley PetscFunctionBegin; 11168749820aSMatthew G. Knepley PetscCall(GmshReadString(gmsh, line, 1)); 11178749820aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 11188749820aSMatthew G. Knepley } 11198749820aSMatthew G. Knepley 11201f643af3SLisandro Dalcin /* 11211f643af3SLisandro Dalcin PhysicalNames 11221f643af3SLisandro Dalcin numPhysicalNames(ASCII int) 11231f643af3SLisandro Dalcin dimension(ASCII int) physicalTag(ASCII int) "name"(127 characters max) 11241f643af3SLisandro Dalcin ... 11251f643af3SLisandro Dalcin $EndPhysicalNames 11261f643af3SLisandro Dalcin */ 1127d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPhysicalNames(GmshFile *gmsh, GmshMesh *mesh) 1128d71ae5a4SJacob Faibussowitsch { 1129bbcf679cSJacob Faibussowitsch char line[PETSC_MAX_PATH_LEN], name[128 + 2], *p = NULL, *q = NULL, *r = NULL; 1130a45dabc8SMatthew G. Knepley int snum, region, dim, tag; 1131698a79b9SLisandro Dalcin 1132698a79b9SLisandro Dalcin PetscFunctionBegin; 11339566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1)); 1134a45dabc8SMatthew G. Knepley snum = sscanf(line, "%d", ®ion); 1135a45dabc8SMatthew G. Knepley mesh->numRegions = region; 113608401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 113790d778b8SLisandro Dalcin PetscCall(PetscMalloc3(mesh->numRegions, &mesh->regionDims, mesh->numRegions, &mesh->regionTags, mesh->numRegions, &mesh->regionNames)); 1138a45dabc8SMatthew G. Knepley for (region = 0; region < mesh->numRegions; ++region) { 11399566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 2)); 11401f643af3SLisandro Dalcin snum = sscanf(line, "%d %d", &dim, &tag); 114108401ef6SPierre Jolivet PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 11429566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, -(PetscInt)sizeof(line))); 11439566063dSJacob Faibussowitsch PetscCall(PetscStrchr(line, '"', &p)); 114428b400f6SJacob Faibussowitsch PetscCheck(p, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 11459566063dSJacob Faibussowitsch PetscCall(PetscStrrchr(line, '"', &q)); 114608401ef6SPierre Jolivet PetscCheck(q != p, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 11475f5cd6d5SMatthew G. Knepley PetscCall(PetscStrrchr(line, ':', &r)); 11485f5cd6d5SMatthew G. Knepley if (p != r) q = r; 11499566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(name, p + 1, (size_t)(q - p - 1))); 115090d778b8SLisandro Dalcin mesh->regionDims[region] = dim; 1151a45dabc8SMatthew G. Knepley mesh->regionTags[region] = tag; 11529566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(name, &mesh->regionNames[region])); 1153698a79b9SLisandro Dalcin } 11543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1155de78e4feSLisandro Dalcin } 1156de78e4feSLisandro Dalcin 1157d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities(GmshFile *gmsh, GmshMesh *mesh) 1158d71ae5a4SJacob Faibussowitsch { 11590598e1a2SLisandro Dalcin PetscFunctionBegin; 11600598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1161d71ae5a4SJacob Faibussowitsch case 41: 1162d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadEntities_v41(gmsh, mesh)); 1163d71ae5a4SJacob Faibussowitsch break; 1164d71ae5a4SJacob Faibussowitsch default: 1165d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadEntities_v40(gmsh, mesh)); 1166d71ae5a4SJacob Faibussowitsch break; 116796ca5757SLisandro Dalcin } 11683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11690598e1a2SLisandro Dalcin } 11700598e1a2SLisandro Dalcin 1171d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes(GmshFile *gmsh, GmshMesh *mesh) 1172d71ae5a4SJacob Faibussowitsch { 11730598e1a2SLisandro Dalcin PetscFunctionBegin; 11740598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1175d71ae5a4SJacob Faibussowitsch case 41: 1176d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadNodes_v41(gmsh, mesh)); 1177d71ae5a4SJacob Faibussowitsch break; 1178d71ae5a4SJacob Faibussowitsch case 40: 1179d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadNodes_v40(gmsh, mesh)); 1180d71ae5a4SJacob Faibussowitsch break; 1181d71ae5a4SJacob Faibussowitsch default: 1182d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadNodes_v22(gmsh, mesh)); 1183d71ae5a4SJacob Faibussowitsch break; 11840598e1a2SLisandro Dalcin } 11850598e1a2SLisandro Dalcin 11860598e1a2SLisandro Dalcin { /* Gmsh v2.2/v4.0 does not provide min/max node tags */ 11870598e1a2SLisandro Dalcin if (mesh->numNodes > 0 && gmsh->nodeEnd >= gmsh->nodeStart) { 11880598e1a2SLisandro Dalcin PetscInt tagMin = PETSC_MAX_INT, tagMax = PETSC_MIN_INT, n; 11890598e1a2SLisandro Dalcin GmshNodes *nodes = mesh->nodelist; 11900598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) { 11910598e1a2SLisandro Dalcin const PetscInt tag = nodes->id[n]; 11920598e1a2SLisandro Dalcin tagMin = PetscMin(tag, tagMin); 11930598e1a2SLisandro Dalcin tagMax = PetscMax(tag, tagMax); 11940598e1a2SLisandro Dalcin } 11950598e1a2SLisandro Dalcin gmsh->nodeStart = tagMin; 11960598e1a2SLisandro Dalcin gmsh->nodeEnd = tagMax + 1; 11970598e1a2SLisandro Dalcin } 11980598e1a2SLisandro Dalcin } 11990598e1a2SLisandro Dalcin 12000598e1a2SLisandro Dalcin { /* Support for sparse node tags */ 12010598e1a2SLisandro Dalcin PetscInt n, t; 12020598e1a2SLisandro Dalcin GmshNodes *nodes = mesh->nodelist; 12039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(gmsh->nodeEnd - gmsh->nodeStart, &gmsh->nbuf)); 12040598e1a2SLisandro Dalcin for (t = 0; t < gmsh->nodeEnd - gmsh->nodeStart; ++t) gmsh->nbuf[t] = PETSC_MIN_INT; 12050598e1a2SLisandro Dalcin gmsh->nodeMap = gmsh->nbuf - gmsh->nodeStart; 12060598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) { 12070598e1a2SLisandro Dalcin const PetscInt tag = nodes->id[n]; 120863a3b9bcSJacob Faibussowitsch PetscCheck(gmsh->nodeMap[tag] < 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Repeated node tag %" PetscInt_FMT, tag); 12090598e1a2SLisandro Dalcin gmsh->nodeMap[tag] = n; 12100598e1a2SLisandro Dalcin } 12110598e1a2SLisandro Dalcin } 12123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12130598e1a2SLisandro Dalcin } 12140598e1a2SLisandro Dalcin 1215d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements(GmshFile *gmsh, GmshMesh *mesh) 1216d71ae5a4SJacob Faibussowitsch { 12170598e1a2SLisandro Dalcin PetscFunctionBegin; 12180598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1219d71ae5a4SJacob Faibussowitsch case 41: 1220d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadElements_v41(gmsh, mesh)); 1221d71ae5a4SJacob Faibussowitsch break; 1222d71ae5a4SJacob Faibussowitsch case 40: 1223d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadElements_v40(gmsh, mesh)); 1224d71ae5a4SJacob Faibussowitsch break; 1225d71ae5a4SJacob Faibussowitsch default: 1226d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadElements_v22(gmsh, mesh)); 1227d71ae5a4SJacob Faibussowitsch break; 12280598e1a2SLisandro Dalcin } 12290598e1a2SLisandro Dalcin 12300598e1a2SLisandro Dalcin { /* Reorder elements by codimension and polytope type */ 12310598e1a2SLisandro Dalcin PetscInt ne = mesh->numElems; 12320598e1a2SLisandro Dalcin GmshElement *elements = mesh->elements; 1233066ea43fSLisandro Dalcin PetscInt keymap[GMSH_NUM_POLYTOPES], nk = 0; 1234066ea43fSLisandro Dalcin PetscInt offset[GMSH_NUM_POLYTOPES + 1], e, k; 12350598e1a2SLisandro Dalcin 1236066ea43fSLisandro Dalcin for (k = 0; k < GMSH_NUM_POLYTOPES; ++k) keymap[k] = PETSC_MIN_INT; 12379566063dSJacob Faibussowitsch PetscCall(PetscMemzero(offset, sizeof(offset))); 12380598e1a2SLisandro Dalcin 1239066ea43fSLisandro Dalcin keymap[GMSH_TET] = nk++; 1240066ea43fSLisandro Dalcin keymap[GMSH_HEX] = nk++; 1241066ea43fSLisandro Dalcin keymap[GMSH_PRI] = nk++; 1242066ea43fSLisandro Dalcin keymap[GMSH_PYR] = nk++; 1243066ea43fSLisandro Dalcin keymap[GMSH_TRI] = nk++; 1244066ea43fSLisandro Dalcin keymap[GMSH_QUA] = nk++; 1245066ea43fSLisandro Dalcin keymap[GMSH_SEG] = nk++; 1246066ea43fSLisandro Dalcin keymap[GMSH_VTX] = nk++; 12470598e1a2SLisandro Dalcin 12489566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(mesh->numElems, &mesh->elements)); 12490598e1a2SLisandro Dalcin #define key(eid) keymap[GmshCellMap[elements[(eid)].cellType].polytope] 12500598e1a2SLisandro Dalcin for (e = 0; e < ne; ++e) offset[1 + key(e)]++; 12510598e1a2SLisandro Dalcin for (k = 1; k < nk; ++k) offset[k] += offset[k - 1]; 12520598e1a2SLisandro Dalcin for (e = 0; e < ne; ++e) mesh->elements[offset[key(e)]++] = elements[e]; 12530598e1a2SLisandro Dalcin #undef key 12549566063dSJacob Faibussowitsch PetscCall(GmshElementsDestroy(&elements)); 1255066ea43fSLisandro Dalcin } 12560598e1a2SLisandro Dalcin 1257066ea43fSLisandro Dalcin { /* Mesh dimension and order */ 1258066ea43fSLisandro Dalcin GmshElement *elem = mesh->numElems ? mesh->elements : NULL; 1259066ea43fSLisandro Dalcin mesh->dim = elem ? GmshCellMap[elem->cellType].dim : 0; 1260066ea43fSLisandro Dalcin mesh->order = elem ? GmshCellMap[elem->cellType].order : 0; 12610598e1a2SLisandro Dalcin } 12620598e1a2SLisandro Dalcin 12630598e1a2SLisandro Dalcin { 12640598e1a2SLisandro Dalcin PetscBT vtx; 12650598e1a2SLisandro Dalcin PetscInt dim = mesh->dim, e, n, v; 12660598e1a2SLisandro Dalcin 12679566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(mesh->numNodes, &vtx)); 12680598e1a2SLisandro Dalcin 12690598e1a2SLisandro Dalcin /* Compute number of cells and set of vertices */ 12700598e1a2SLisandro Dalcin mesh->numCells = 0; 12710598e1a2SLisandro Dalcin for (e = 0; e < mesh->numElems; ++e) { 12720598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + e; 12730598e1a2SLisandro Dalcin if (elem->dim == dim && dim > 0) mesh->numCells++; 127448a46eb9SPierre Jolivet for (v = 0; v < elem->numVerts; v++) PetscCall(PetscBTSet(vtx, elem->nodes[v])); 12750598e1a2SLisandro Dalcin } 12760598e1a2SLisandro Dalcin 12770598e1a2SLisandro Dalcin /* Compute numbering for vertices */ 12780598e1a2SLisandro Dalcin mesh->numVerts = 0; 12799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mesh->numNodes, &mesh->vertexMap)); 12809371c9d4SSatish Balay for (n = 0; n < mesh->numNodes; ++n) mesh->vertexMap[n] = PetscBTLookup(vtx, n) ? mesh->numVerts++ : PETSC_MIN_INT; 12810598e1a2SLisandro Dalcin 12829566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&vtx)); 12830598e1a2SLisandro Dalcin } 12843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12850598e1a2SLisandro Dalcin } 12860598e1a2SLisandro Dalcin 1287d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic(GmshFile *gmsh, GmshMesh *mesh) 1288d71ae5a4SJacob Faibussowitsch { 12890598e1a2SLisandro Dalcin PetscInt n; 12900598e1a2SLisandro Dalcin 12910598e1a2SLisandro Dalcin PetscFunctionBegin; 12929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mesh->numNodes, &mesh->periodMap)); 12930598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) mesh->periodMap[n] = n; 12940598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1295d71ae5a4SJacob Faibussowitsch case 41: 1296d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadPeriodic_v41(gmsh, mesh->periodMap)); 1297d71ae5a4SJacob Faibussowitsch break; 1298d71ae5a4SJacob Faibussowitsch default: 1299d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadPeriodic_v40(gmsh, mesh->periodMap)); 1300d71ae5a4SJacob Faibussowitsch break; 13010598e1a2SLisandro Dalcin } 13020598e1a2SLisandro Dalcin 13039dddd249SSatish Balay /* Find canonical primary nodes */ 13040598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) 13059371c9d4SSatish Balay while (mesh->periodMap[n] != mesh->periodMap[mesh->periodMap[n]]) mesh->periodMap[n] = mesh->periodMap[mesh->periodMap[n]]; 13060598e1a2SLisandro Dalcin 13079dddd249SSatish Balay /* Renumber vertices (filter out correspondings) */ 13080598e1a2SLisandro Dalcin mesh->numVerts = 0; 13090598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) 13100598e1a2SLisandro Dalcin if (mesh->vertexMap[n] >= 0) /* is vertex */ 13119dddd249SSatish Balay if (mesh->periodMap[n] == n) /* is primary */ 13120598e1a2SLisandro Dalcin mesh->vertexMap[n] = mesh->numVerts++; 13130598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) 13140598e1a2SLisandro Dalcin if (mesh->vertexMap[n] >= 0) /* is vertex */ 13159dddd249SSatish Balay if (mesh->periodMap[n] != n) /* is corresponding */ 13160598e1a2SLisandro Dalcin mesh->vertexMap[n] = mesh->vertexMap[mesh->periodMap[n]]; 13173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13180598e1a2SLisandro Dalcin } 13190598e1a2SLisandro Dalcin 1320066ea43fSLisandro Dalcin #define DM_POLYTOPE_VERTEX DM_POLYTOPE_POINT 1321066ea43fSLisandro Dalcin static const DMPolytopeType DMPolytopeMap[] = { 1322066ea43fSLisandro Dalcin /* GMSH_VTX */ DM_POLYTOPE_VERTEX, 1323066ea43fSLisandro Dalcin /* GMSH_SEG */ DM_POLYTOPE_SEGMENT, 1324066ea43fSLisandro Dalcin /* GMSH_TRI */ DM_POLYTOPE_TRIANGLE, 1325066ea43fSLisandro Dalcin /* GMSH_QUA */ DM_POLYTOPE_QUADRILATERAL, 1326066ea43fSLisandro Dalcin /* GMSH_TET */ DM_POLYTOPE_TETRAHEDRON, 1327066ea43fSLisandro Dalcin /* GMSH_HEX */ DM_POLYTOPE_HEXAHEDRON, 1328066ea43fSLisandro Dalcin /* GMSH_PRI */ DM_POLYTOPE_TRI_PRISM, 13299371c9d4SSatish Balay /* GMSH_PYR */ DM_POLYTOPE_PYRAMID, DM_POLYTOPE_UNKNOWN}; 13300598e1a2SLisandro Dalcin 1331d71ae5a4SJacob Faibussowitsch static inline DMPolytopeType DMPolytopeTypeFromGmsh(PetscInt cellType) 1332d71ae5a4SJacob Faibussowitsch { 1333066ea43fSLisandro Dalcin return DMPolytopeMap[GmshCellMap[cellType].polytope]; 1334066ea43fSLisandro Dalcin } 1335066ea43fSLisandro Dalcin 1336d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshCreateFE(MPI_Comm comm, const char prefix[], PetscBool isSimplex, PetscBool continuity, PetscDTNodeType nodeType, PetscInt dim, PetscInt Nc, PetscInt k, PetscFE *fem) 1337d71ae5a4SJacob Faibussowitsch { 1338066ea43fSLisandro Dalcin DM K; 1339066ea43fSLisandro Dalcin PetscSpace P; 1340066ea43fSLisandro Dalcin PetscDualSpace Q; 1341066ea43fSLisandro Dalcin PetscQuadrature q, fq; 1342066ea43fSLisandro Dalcin PetscBool isTensor = isSimplex ? PETSC_FALSE : PETSC_TRUE; 1343066ea43fSLisandro Dalcin PetscBool endpoint = PETSC_TRUE; 1344066ea43fSLisandro Dalcin char name[32]; 1345066ea43fSLisandro Dalcin 1346066ea43fSLisandro Dalcin PetscFunctionBegin; 1347066ea43fSLisandro Dalcin /* Create space */ 13489566063dSJacob Faibussowitsch PetscCall(PetscSpaceCreate(comm, &P)); 13499566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetType(P, PETSCSPACEPOLYNOMIAL)); 13509566063dSJacob Faibussowitsch PetscCall(PetscSpacePolynomialSetTensor(P, isTensor)); 13519566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumComponents(P, Nc)); 13529566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumVariables(P, dim)); 13539566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetDegree(P, k, PETSC_DETERMINE)); 1354066ea43fSLisandro Dalcin if (prefix) { 13559566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)P, prefix)); 13569566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetFromOptions(P)); 13579566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)P, NULL)); 13589566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetDegree(P, &k, NULL)); 1359066ea43fSLisandro Dalcin } 13609566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetUp(P)); 1361066ea43fSLisandro Dalcin /* Create dual space */ 13629566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceCreate(comm, &Q)); 13639566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(Q, PETSCDUALSPACELAGRANGE)); 13649566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeSetTensor(Q, isTensor)); 13659566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeSetContinuity(Q, continuity)); 13669566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeSetNodeType(Q, nodeType, endpoint, 0)); 13679566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetNumComponents(Q, Nc)); 13689566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetOrder(Q, k)); 13699566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, DMPolytopeTypeSimpleShape(dim, isSimplex), &K)); 13709566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetDM(Q, K)); 13719566063dSJacob Faibussowitsch PetscCall(DMDestroy(&K)); 1372066ea43fSLisandro Dalcin if (prefix) { 13739566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)Q, prefix)); 13749566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetFromOptions(Q)); 13759566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)Q, NULL)); 1376066ea43fSLisandro Dalcin } 13779566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetUp(Q)); 1378066ea43fSLisandro Dalcin /* Create quadrature */ 1379066ea43fSLisandro Dalcin if (isSimplex) { 13809566063dSJacob Faibussowitsch PetscCall(PetscDTStroudConicalQuadrature(dim, 1, k + 1, -1, +1, &q)); 13819566063dSJacob Faibussowitsch PetscCall(PetscDTStroudConicalQuadrature(dim - 1, 1, k + 1, -1, +1, &fq)); 1382066ea43fSLisandro Dalcin } else { 13839566063dSJacob Faibussowitsch PetscCall(PetscDTGaussTensorQuadrature(dim, 1, k + 1, -1, +1, &q)); 13849566063dSJacob Faibussowitsch PetscCall(PetscDTGaussTensorQuadrature(dim - 1, 1, k + 1, -1, +1, &fq)); 1385066ea43fSLisandro Dalcin } 1386066ea43fSLisandro Dalcin /* Create finite element */ 13879566063dSJacob Faibussowitsch PetscCall(PetscFECreate(comm, fem)); 13889566063dSJacob Faibussowitsch PetscCall(PetscFESetType(*fem, PETSCFEBASIC)); 13899566063dSJacob Faibussowitsch PetscCall(PetscFESetNumComponents(*fem, Nc)); 13909566063dSJacob Faibussowitsch PetscCall(PetscFESetBasisSpace(*fem, P)); 13919566063dSJacob Faibussowitsch PetscCall(PetscFESetDualSpace(*fem, Q)); 13929566063dSJacob Faibussowitsch PetscCall(PetscFESetQuadrature(*fem, q)); 13939566063dSJacob Faibussowitsch PetscCall(PetscFESetFaceQuadrature(*fem, fq)); 1394066ea43fSLisandro Dalcin if (prefix) { 13959566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*fem, prefix)); 13969566063dSJacob Faibussowitsch PetscCall(PetscFESetFromOptions(*fem)); 13979566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*fem, NULL)); 1398066ea43fSLisandro Dalcin } 13999566063dSJacob Faibussowitsch PetscCall(PetscFESetUp(*fem)); 1400066ea43fSLisandro Dalcin /* Cleanup */ 14019566063dSJacob Faibussowitsch PetscCall(PetscSpaceDestroy(&P)); 14029566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceDestroy(&Q)); 14039566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&q)); 14049566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&fq)); 1405066ea43fSLisandro Dalcin /* Set finite element name */ 140663a3b9bcSJacob Faibussowitsch PetscCall(PetscSNPrintf(name, sizeof(name), "%s%" PetscInt_FMT, isSimplex ? "P" : "Q", k)); 14079566063dSJacob Faibussowitsch PetscCall(PetscFESetName(*fem, name)); 14083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 140996ca5757SLisandro Dalcin } 141096ca5757SLisandro Dalcin 1411d6689ca9SLisandro Dalcin /*@C 1412a1cb98faSBarry Smith DMPlexCreateGmshFromFile - Create a `DMPLEX` mesh from a Gmsh file 1413d6689ca9SLisandro Dalcin 1414a4e35b19SJacob Faibussowitsch Input Parameters: 1415d6689ca9SLisandro Dalcin + comm - The MPI communicator 1416d6689ca9SLisandro Dalcin . filename - Name of the Gmsh file 1417d6689ca9SLisandro Dalcin - interpolate - Create faces and edges in the mesh 1418d6689ca9SLisandro Dalcin 1419d6689ca9SLisandro Dalcin Output Parameter: 1420a1cb98faSBarry Smith . dm - The `DM` object representing the mesh 1421d6689ca9SLisandro Dalcin 1422d6689ca9SLisandro Dalcin Level: beginner 1423d6689ca9SLisandro Dalcin 14241cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 1425d6689ca9SLisandro Dalcin @*/ 1426d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateGmshFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 1427d71ae5a4SJacob Faibussowitsch { 1428d6689ca9SLisandro Dalcin PetscViewer viewer; 1429d6689ca9SLisandro Dalcin PetscMPIInt rank; 1430d6689ca9SLisandro Dalcin int fileType; 1431d6689ca9SLisandro Dalcin PetscViewerType vtype; 1432d6689ca9SLisandro Dalcin 1433d6689ca9SLisandro Dalcin PetscFunctionBegin; 14349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1435d6689ca9SLisandro Dalcin 1436d6689ca9SLisandro Dalcin /* Determine Gmsh file type (ASCII or binary) from file header */ 1437dd400576SPatrick Sanan if (rank == 0) { 14380598e1a2SLisandro Dalcin GmshFile gmsh[1]; 1439d6689ca9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 1440d6689ca9SLisandro Dalcin int snum; 1441d6689ca9SLisandro Dalcin float version; 1442a8d4e440SJunchao Zhang int fileFormat; 1443d6689ca9SLisandro Dalcin 14449566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(gmsh, 1)); 14459566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(PETSC_COMM_SELF, &gmsh->viewer)); 14469566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(gmsh->viewer, PETSCVIEWERASCII)); 14479566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(gmsh->viewer, FILE_MODE_READ)); 14489566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(gmsh->viewer, filename)); 1449d6689ca9SLisandro Dalcin /* Read only the first two lines of the Gmsh file */ 14509566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 14519566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$MeshFormat", line)); 14529566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 2)); 1453d6689ca9SLisandro Dalcin snum = sscanf(line, "%f %d", &version, &fileType); 1454a8d4e440SJunchao Zhang fileFormat = (int)roundf(version * 10); 145508401ef6SPierre Jolivet PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line); 1456a8d4e440SJunchao Zhang PetscCheck(fileFormat >= 22, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version); 14571dca8a05SBarry Smith PetscCheck((int)version != 3, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version); 1458a8d4e440SJunchao Zhang PetscCheck(fileFormat <= 41, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version); 14599566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&gmsh->viewer)); 1460d6689ca9SLisandro Dalcin } 14619566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&fileType, 1, MPI_INT, 0, comm)); 1462d6689ca9SLisandro Dalcin vtype = (fileType == 0) ? PETSCVIEWERASCII : PETSCVIEWERBINARY; 1463d6689ca9SLisandro Dalcin 1464d6689ca9SLisandro Dalcin /* Create appropriate viewer and build plex */ 14659566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 14669566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, vtype)); 14679566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 14689566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 14699566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGmsh(comm, viewer, interpolate, dm)); 14709566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 14713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1472d6689ca9SLisandro Dalcin } 1473d6689ca9SLisandro Dalcin 1474331830f3SMatthew G. Knepley /*@ 1475a1cb98faSBarry Smith DMPlexCreateGmsh - Create a `DMPLEX` mesh from a Gmsh file viewer 1476331830f3SMatthew G. Knepley 1477d083f849SBarry Smith Collective 1478331830f3SMatthew G. Knepley 1479331830f3SMatthew G. Knepley Input Parameters: 1480331830f3SMatthew G. Knepley + comm - The MPI communicator 1481a1cb98faSBarry Smith . viewer - The `PetscViewer` associated with a Gmsh file 1482331830f3SMatthew G. Knepley - interpolate - Create faces and edges in the mesh 1483331830f3SMatthew G. Knepley 1484331830f3SMatthew G. Knepley Output Parameter: 1485a1cb98faSBarry Smith . dm - The `DM` object representing the mesh 1486331830f3SMatthew G. Knepley 1487a1cb98faSBarry Smith Options Database Keys: 1488df93260fSMatthew G. Knepley + -dm_plex_gmsh_hybrid - Force triangular prisms to use tensor order 1489df93260fSMatthew G. Knepley . -dm_plex_gmsh_periodic - Read Gmsh periodic section and construct a periodic Plex 1490df93260fSMatthew G. Knepley . -dm_plex_gmsh_highorder - Generate high-order coordinates 1491df93260fSMatthew G. Knepley . -dm_plex_gmsh_project - Project high-order coordinates to a different space, use the prefix dm_plex_gmsh_project_ to define the space 14922b205333SMatthew G. Knepley . -dm_plex_gmsh_use_generic - Generate generic labels, i.e. Cell Sets, Face Sets, etc. 1493df93260fSMatthew G. Knepley . -dm_plex_gmsh_use_regions - Generate labels with region names 1494df93260fSMatthew G. Knepley . -dm_plex_gmsh_mark_vertices - Add vertices to generated labels 1495df93260fSMatthew G. Knepley . -dm_plex_gmsh_multiple_tags - Allow multiple tags for default labels 1496df93260fSMatthew G. Knepley - -dm_plex_gmsh_spacedim <d> - Embedding space dimension, if different from topological dimension 1497df93260fSMatthew G. Knepley 14981d27aa22SBarry Smith Level: beginner 14991d27aa22SBarry Smith 15001d27aa22SBarry Smith Notes: 15011d27aa22SBarry Smith The Gmsh file format is described in <http://gmsh.info/doc/texinfo/gmsh.html#MSH-file-format> 1502df93260fSMatthew G. Knepley 15032b205333SMatthew G. Knepley By default, the "Cell Sets", "Face Sets", and "Vertex Sets" labels are created, and only insert the first tag on a point. By using -dm_plex_gmsh_multiple_tags, all tags can be inserted. Alternatively, -dm_plex_gmsh_use_regions creates labels based on the region names from the PhysicalNames section, and all tags are used, but you can retain the generic labels using -dm_plex_gmsh_use_generic. 1504331830f3SMatthew G. Knepley 15051cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()` 1506331830f3SMatthew G. Knepley @*/ 1507d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateGmsh(MPI_Comm comm, PetscViewer viewer, PetscBool interpolate, DM *dm) 1508d71ae5a4SJacob Faibussowitsch { 15090598e1a2SLisandro Dalcin GmshMesh *mesh = NULL; 151011c56cb0SLisandro Dalcin PetscViewer parentviewer = NULL; 15110598e1a2SLisandro Dalcin PetscBT periodicVerts = NULL; 1512eae3dc7dSJacob Faibussowitsch PetscBT *periodicCells = NULL; 15136858538eSMatthew G. Knepley DM cdm, cdmCell = NULL; 15146858538eSMatthew G. Knepley PetscSection cs, csCell = NULL; 15156858538eSMatthew G. Knepley Vec coordinates, coordinatesCell; 15160444adf6SMatthew G. Knepley DMLabel cellSets = NULL, faceSets = NULL, edgeSets = NULL, vertSets = NULL, marker = NULL, *regionSets; 15179db5b827SMatthew G. Knepley PetscInt dim = 0, coordDim = -1, order = 0, maxHeight = 0; 15189db5b827SMatthew G. Knepley PetscInt numNodes = 0, numElems = 0, numVerts = 0, numCells = 0, vStart, vEnd; 1519066ea43fSLisandro Dalcin PetscInt cell, cone[8], e, n, v, d; 15202b205333SMatthew G. Knepley PetscBool usegeneric = PETSC_TRUE, useregions = PETSC_FALSE, markvertices = PETSC_FALSE, multipleTags = PETSC_FALSE; 15212b205333SMatthew G. Knepley PetscBool flg, binary, hybrid = interpolate, periodic = PETSC_TRUE; 1522066ea43fSLisandro Dalcin PetscBool highOrder = PETSC_TRUE, highOrderSet, project = PETSC_FALSE; 1523066ea43fSLisandro Dalcin PetscBool isSimplex = PETSC_FALSE, isHybrid = PETSC_FALSE, hasTetra = PETSC_FALSE; 15240598e1a2SLisandro Dalcin PetscMPIInt rank; 1525331830f3SMatthew G. Knepley 1526331830f3SMatthew G. Knepley PetscFunctionBegin; 15279566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1528d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)viewer); 1529d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Gmsh options"); 1530df93260fSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_gmsh_hybrid", "Force triangular prisms to use tensor order", "DMPlexCreateGmsh", hybrid, &hybrid, NULL)); 15319566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_periodic", "Read Gmsh periodic section", "DMPlexCreateGmsh", periodic, &periodic, NULL)); 15329566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_highorder", "Generate high-order coordinates", "DMPlexCreateGmsh", highOrder, &highOrder, &highOrderSet)); 15339566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_project", "Project high-order coordinates to a different space", "DMPlexCreateGmsh", project, &project, NULL)); 15349566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_use_regions", "Generate labels with region names", "DMPlexCreateGmsh", useregions, &useregions, NULL)); 15352b205333SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_gmsh_use_generic", "Generate generic labels, i.e. Cell Sets, Face Sets, etc", "DMPlexCreateGmsh", usegeneric, &usegeneric, &flg)); 15362b205333SMatthew G. Knepley if (!flg && useregions) usegeneric = PETSC_FALSE; 15379566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_mark_vertices", "Add vertices to generated labels", "DMPlexCreateGmsh", markvertices, &markvertices, NULL)); 1538df93260fSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_gmsh_multiple_tags", "Allow multiple tags for default labels", "DMPlexCreateGmsh", multipleTags, &multipleTags, NULL)); 15399566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_gmsh_spacedim", "Embedding space dimension", "DMPlexCreateGmsh", coordDim, &coordDim, NULL, PETSC_DECIDE)); 15409db5b827SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_localize_height", "Localize edges and faces in addition to cells", "", maxHeight, &maxHeight, NULL, 0)); 1541d0609cedSBarry Smith PetscOptionsHeadEnd(); 1542d0609cedSBarry Smith PetscOptionsEnd(); 15430598e1a2SLisandro Dalcin 15449566063dSJacob Faibussowitsch PetscCall(GmshCellInfoSetUp()); 154511c56cb0SLisandro Dalcin 15469566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 15479566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 15489566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreateGmsh, *dm, NULL, NULL, NULL)); 154911c56cb0SLisandro Dalcin 15509566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &binary)); 155111c56cb0SLisandro Dalcin 155211c56cb0SLisandro Dalcin /* Binary viewers read on all ranks, get subviewer to read only in rank 0 */ 15533b46f529SLisandro Dalcin if (binary) { 155411c56cb0SLisandro Dalcin parentviewer = viewer; 15559566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(parentviewer, PETSC_COMM_SELF, &viewer)); 155611c56cb0SLisandro Dalcin } 155711c56cb0SLisandro Dalcin 1558dd400576SPatrick Sanan if (rank == 0) { 15590598e1a2SLisandro Dalcin GmshFile gmsh[1]; 1560698a79b9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 1561698a79b9SLisandro Dalcin PetscBool match; 1562331830f3SMatthew G. Knepley 15639566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(gmsh, 1)); 1564698a79b9SLisandro Dalcin gmsh->viewer = viewer; 1565698a79b9SLisandro Dalcin gmsh->binary = binary; 1566698a79b9SLisandro Dalcin 15679566063dSJacob Faibussowitsch PetscCall(GmshMeshCreate(&mesh)); 15680598e1a2SLisandro Dalcin 1569698a79b9SLisandro Dalcin /* Read mesh format */ 15709566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 15719566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$MeshFormat", line)); 15729566063dSJacob Faibussowitsch PetscCall(GmshReadMeshFormat(gmsh)); 15739566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndMeshFormat", line)); 157411c56cb0SLisandro Dalcin 15758749820aSMatthew G. Knepley /* OPTIONAL Read mesh version (Neper only) */ 15769566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 15778749820aSMatthew G. Knepley PetscCall(GmshMatch(gmsh, "$MeshVersion", line, &match)); 15788749820aSMatthew G. Knepley if (match) { 15798749820aSMatthew G. Knepley PetscCall(GmshExpect(gmsh, "$MeshVersion", line)); 15808749820aSMatthew G. Knepley PetscCall(GmshReadMeshVersion(gmsh)); 15818749820aSMatthew G. Knepley PetscCall(GmshReadEndSection(gmsh, "$EndMeshVersion", line)); 15828749820aSMatthew G. Knepley /* Initial read for entity section */ 15838749820aSMatthew G. Knepley PetscCall(GmshReadSection(gmsh, line)); 15848749820aSMatthew G. Knepley } 15858749820aSMatthew G. Knepley 15868749820aSMatthew G. Knepley /* OPTIONAL Read mesh domain (Neper only) */ 15878749820aSMatthew G. Knepley PetscCall(GmshMatch(gmsh, "$Domain", line, &match)); 15888749820aSMatthew G. Knepley if (match) { 15898749820aSMatthew G. Knepley PetscCall(GmshExpect(gmsh, "$Domain", line)); 15908749820aSMatthew G. Knepley PetscCall(GmshReadMeshDomain(gmsh)); 15918749820aSMatthew G. Knepley PetscCall(GmshReadEndSection(gmsh, "$EndDomain", line)); 15928749820aSMatthew G. Knepley /* Initial read for entity section */ 15938749820aSMatthew G. Knepley PetscCall(GmshReadSection(gmsh, line)); 15948749820aSMatthew G. Knepley } 15958749820aSMatthew G. Knepley 15968749820aSMatthew G. Knepley /* OPTIONAL Read physical names */ 15979566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$PhysicalNames", line, &match)); 1598dc0ede3bSMatthew G. Knepley if (match) { 15999566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$PhysicalNames", line)); 16009566063dSJacob Faibussowitsch PetscCall(GmshReadPhysicalNames(gmsh, mesh)); 16019566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndPhysicalNames", line)); 1602698a79b9SLisandro Dalcin /* Initial read for entity section */ 16039566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 1604dc0ede3bSMatthew G. Knepley } 160511c56cb0SLisandro Dalcin 1606de78e4feSLisandro Dalcin /* Read entities */ 1607698a79b9SLisandro Dalcin if (gmsh->fileFormat >= 40) { 16089566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Entities", line)); 16099566063dSJacob Faibussowitsch PetscCall(GmshReadEntities(gmsh, mesh)); 16109566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndEntities", line)); 1611698a79b9SLisandro Dalcin /* Initial read for nodes section */ 16129566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 1613de78e4feSLisandro Dalcin } 1614de78e4feSLisandro Dalcin 1615698a79b9SLisandro Dalcin /* Read nodes */ 16169566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Nodes", line)); 16179566063dSJacob Faibussowitsch PetscCall(GmshReadNodes(gmsh, mesh)); 16189566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndNodes", line)); 161911c56cb0SLisandro Dalcin 1620698a79b9SLisandro Dalcin /* Read elements */ 16219566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 16229566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Elements", line)); 16239566063dSJacob Faibussowitsch PetscCall(GmshReadElements(gmsh, mesh)); 16249566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndElements", line)); 1625de78e4feSLisandro Dalcin 16260598e1a2SLisandro Dalcin /* Read periodic section (OPTIONAL) */ 1627698a79b9SLisandro Dalcin if (periodic) { 16289566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 16299566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$Periodic", line, &periodic)); 1630ef12879bSLisandro Dalcin } 1631ef12879bSLisandro Dalcin if (periodic) { 16329566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Periodic", line)); 16339566063dSJacob Faibussowitsch PetscCall(GmshReadPeriodic(gmsh, mesh)); 16349566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndPeriodic", line)); 1635698a79b9SLisandro Dalcin } 1636698a79b9SLisandro Dalcin 16379566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->wbuf)); 16389566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->sbuf)); 16399566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->nbuf)); 16400598e1a2SLisandro Dalcin 16410598e1a2SLisandro Dalcin dim = mesh->dim; 1642066ea43fSLisandro Dalcin order = mesh->order; 16430598e1a2SLisandro Dalcin numNodes = mesh->numNodes; 16440598e1a2SLisandro Dalcin numElems = mesh->numElems; 16450598e1a2SLisandro Dalcin numVerts = mesh->numVerts; 16460598e1a2SLisandro Dalcin numCells = mesh->numCells; 1647066ea43fSLisandro Dalcin 1648066ea43fSLisandro Dalcin { 1649066ea43fSLisandro Dalcin GmshElement *elemA = mesh->numCells > 0 ? mesh->elements : NULL; 16508e3a54c0SPierre Jolivet GmshElement *elemB = PetscSafePointerPlusOffset(elemA, mesh->numCells - 1); 1651066ea43fSLisandro Dalcin int ptA = elemA ? GmshCellMap[elemA->cellType].polytope : -1; 1652066ea43fSLisandro Dalcin int ptB = elemB ? GmshCellMap[elemB->cellType].polytope : -1; 1653066ea43fSLisandro Dalcin isSimplex = (ptA == GMSH_QUA || ptA == GMSH_HEX) ? PETSC_FALSE : PETSC_TRUE; 1654066ea43fSLisandro Dalcin isHybrid = (ptA == ptB) ? PETSC_FALSE : PETSC_TRUE; 1655066ea43fSLisandro Dalcin hasTetra = (ptA == GMSH_TET) ? PETSC_TRUE : PETSC_FALSE; 1656066ea43fSLisandro Dalcin } 1657698a79b9SLisandro Dalcin } 1658698a79b9SLisandro Dalcin 165948a46eb9SPierre Jolivet if (parentviewer) PetscCall(PetscViewerRestoreSubViewer(parentviewer, PETSC_COMM_SELF, &viewer)); 1660698a79b9SLisandro Dalcin 1661066ea43fSLisandro Dalcin { 1662066ea43fSLisandro Dalcin int buf[6]; 1663698a79b9SLisandro Dalcin 1664066ea43fSLisandro Dalcin buf[0] = (int)dim; 1665066ea43fSLisandro Dalcin buf[1] = (int)order; 1666066ea43fSLisandro Dalcin buf[2] = periodic; 1667066ea43fSLisandro Dalcin buf[3] = isSimplex; 1668066ea43fSLisandro Dalcin buf[4] = isHybrid; 1669066ea43fSLisandro Dalcin buf[5] = hasTetra; 1670066ea43fSLisandro Dalcin 16719566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(buf, 6, MPI_INT, 0, comm)); 1672066ea43fSLisandro Dalcin 1673066ea43fSLisandro Dalcin dim = buf[0]; 1674066ea43fSLisandro Dalcin order = buf[1]; 1675066ea43fSLisandro Dalcin periodic = buf[2] ? PETSC_TRUE : PETSC_FALSE; 1676066ea43fSLisandro Dalcin isSimplex = buf[3] ? PETSC_TRUE : PETSC_FALSE; 1677066ea43fSLisandro Dalcin isHybrid = buf[4] ? PETSC_TRUE : PETSC_FALSE; 1678066ea43fSLisandro Dalcin hasTetra = buf[5] ? PETSC_TRUE : PETSC_FALSE; 1679dea2a3c7SStefano Zampini } 1680dea2a3c7SStefano Zampini 1681066ea43fSLisandro Dalcin if (!highOrderSet) highOrder = (order > 1) ? PETSC_TRUE : PETSC_FALSE; 168208401ef6SPierre Jolivet PetscCheck(!highOrder || !isHybrid, comm, PETSC_ERR_SUP, "No support for discretization on hybrid meshes yet"); 1683066ea43fSLisandro Dalcin 16840598e1a2SLisandro Dalcin /* We do not want this label automatically computed, instead we fill it here */ 16859566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "celltype")); 168611c56cb0SLisandro Dalcin 1687a4bb7517SMichael Lange /* Allocate the cell-vertex mesh */ 16889566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(*dm, 0, numCells + numVerts)); 16890598e1a2SLisandro Dalcin for (cell = 0; cell < numCells; ++cell) { 16900598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + cell; 16910598e1a2SLisandro Dalcin DMPolytopeType ctype = DMPolytopeTypeFromGmsh(elem->cellType); 16920598e1a2SLisandro Dalcin if (hybrid && hasTetra && ctype == DM_POLYTOPE_TRI_PRISM) ctype = DM_POLYTOPE_TRI_PRISM_TENSOR; 16939566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(*dm, cell, elem->numVerts)); 16949566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(*dm, cell, ctype)); 1695db397164SMichael Lange } 169648a46eb9SPierre Jolivet for (v = numCells; v < numCells + numVerts; ++v) PetscCall(DMPlexSetCellType(*dm, v, DM_POLYTOPE_POINT)); 16979566063dSJacob Faibussowitsch PetscCall(DMSetUp(*dm)); 169896ca5757SLisandro Dalcin 1699a4bb7517SMichael Lange /* Add cell-vertex connections */ 17000598e1a2SLisandro Dalcin for (cell = 0; cell < numCells; ++cell) { 17010598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + cell; 17020598e1a2SLisandro Dalcin for (v = 0; v < elem->numVerts; ++v) { 17030598e1a2SLisandro Dalcin const PetscInt nn = elem->nodes[v]; 17040598e1a2SLisandro Dalcin const PetscInt vv = mesh->vertexMap[nn]; 17050598e1a2SLisandro Dalcin cone[v] = numCells + vv; 1706db397164SMichael Lange } 17079566063dSJacob Faibussowitsch PetscCall(DMPlexReorderCell(*dm, cell, cone)); 17089566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(*dm, cell, cone)); 1709a4bb7517SMichael Lange } 171096ca5757SLisandro Dalcin 17119566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 17129566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(*dm)); 17139566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(*dm)); 1714331830f3SMatthew G. Knepley if (interpolate) { 17155fd9971aSMatthew G. Knepley DM idm; 1716331830f3SMatthew G. Knepley 17179566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 17189566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 1719331830f3SMatthew G. Knepley *dm = idm; 1720331830f3SMatthew G. Knepley } 17219db5b827SMatthew G. Knepley PetscCall(DMPlexGetDepthStratum(*dm, 0, &vStart, &vEnd)); 1722917266a4SLisandro Dalcin 1723dd400576SPatrick Sanan if (rank == 0) { 1724a45dabc8SMatthew G. Knepley const PetscInt Nr = useregions ? mesh->numRegions : 0; 1725d1a54cefSMatthew G. Knepley 17269566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(Nr, ®ionSets)); 17270598e1a2SLisandro Dalcin for (cell = 0, e = 0; e < numElems; ++e) { 17280598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + e; 17296e1dd89aSLawrence Mitchell 17306e1dd89aSLawrence Mitchell /* Create cell sets */ 17310598e1a2SLisandro Dalcin if (elem->dim == dim && dim > 0) { 17320598e1a2SLisandro Dalcin if (elem->numTags > 0) { 1733df93260fSMatthew G. Knepley PetscInt Nt = elem->numTags, t, r; 1734a45dabc8SMatthew G. Knepley 1735df93260fSMatthew G. Knepley for (t = 0; t < Nt; ++t) { 1736df93260fSMatthew G. Knepley const PetscInt tag = elem->tags[t]; 17372b205333SMatthew G. Knepley const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE; 1738df93260fSMatthew G. Knepley 1739df93260fSMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &cellSets, "Cell Sets", cell, tag)); 1740a45dabc8SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 1741df93260fSMatthew G. Knepley if (mesh->regionDims[r] != dim) continue; 17429566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], cell, tag)); 1743a45dabc8SMatthew G. Knepley } 17446e1dd89aSLawrence Mitchell } 1745df93260fSMatthew G. Knepley } 1746917266a4SLisandro Dalcin cell++; 17476e1dd89aSLawrence Mitchell } 17480c070f12SSander Arens 17490598e1a2SLisandro Dalcin /* Create face sets */ 1750aec57b10SMatthew G. Knepley if (elem->numTags && interpolate && elem->dim == dim - 1) { 17510598e1a2SLisandro Dalcin PetscInt joinSize; 17520598e1a2SLisandro Dalcin const PetscInt *join = NULL; 17530444adf6SMatthew G. Knepley PetscInt Nt = elem->numTags, pdepth; 1754a45dabc8SMatthew G. Knepley 17550598e1a2SLisandro Dalcin /* Find the relevant facet with vertex joins */ 17560598e1a2SLisandro Dalcin for (v = 0; v < elem->numVerts; ++v) { 17570598e1a2SLisandro Dalcin const PetscInt nn = elem->nodes[v]; 17580598e1a2SLisandro Dalcin const PetscInt vv = mesh->vertexMap[nn]; 17590598e1a2SLisandro Dalcin cone[v] = vStart + vv; 17600598e1a2SLisandro Dalcin } 17619566063dSJacob Faibussowitsch PetscCall(DMPlexGetFullJoin(*dm, elem->numVerts, cone, &joinSize, &join)); 176263a3b9bcSJacob Faibussowitsch PetscCheck(joinSize == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Could not determine Plex facet for Gmsh element %" PetscInt_FMT " (Plex cell %" PetscInt_FMT ")", elem->id, e); 17630444adf6SMatthew G. Knepley PetscCall(DMPlexGetPointDepth(*dm, join[0], &pdepth)); 17640444adf6SMatthew G. Knepley PetscCheck(pdepth == dim - 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Plex facet %" PetscInt_FMT " for Gmsh element %" PetscInt_FMT " had depth %" PetscInt_FMT " != %" PetscInt_FMT, join[0], elem->id, pdepth, dim - 1); 17650444adf6SMatthew G. Knepley for (PetscInt t = 0; t < Nt; ++t) { 17665ad74b4fSMatthew G. Knepley const PetscInt tag = elem->tags[t]; 17672b205333SMatthew G. Knepley const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE; 17685ad74b4fSMatthew G. Knepley 1769df93260fSMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &faceSets, "Face Sets", join[0], tag)); 17700444adf6SMatthew G. Knepley for (PetscInt r = 0; r < Nr; ++r) { 1771df93260fSMatthew G. Knepley if (mesh->regionDims[r] != dim - 1) continue; 17729566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], join[0], tag)); 1773a45dabc8SMatthew G. Knepley } 17745ad74b4fSMatthew G. Knepley } 17759566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(*dm, elem->numVerts, cone, &joinSize, &join)); 17760598e1a2SLisandro Dalcin } 17770598e1a2SLisandro Dalcin 1778aec57b10SMatthew G. Knepley /* Create edge sets */ 1779aec57b10SMatthew G. Knepley if (elem->numTags && interpolate && dim > 2 && elem->dim == 1) { 1780aec57b10SMatthew G. Knepley PetscInt joinSize; 1781aec57b10SMatthew G. Knepley const PetscInt *join = NULL; 1782aec57b10SMatthew G. Knepley PetscInt Nt = elem->numTags, t, r; 1783aec57b10SMatthew G. Knepley 1784aec57b10SMatthew G. Knepley /* Find the relevant edge with vertex joins */ 1785aec57b10SMatthew G. Knepley for (v = 0; v < elem->numVerts; ++v) { 1786aec57b10SMatthew G. Knepley const PetscInt nn = elem->nodes[v]; 1787aec57b10SMatthew G. Knepley const PetscInt vv = mesh->vertexMap[nn]; 1788aec57b10SMatthew G. Knepley cone[v] = vStart + vv; 1789aec57b10SMatthew G. Knepley } 1790aec57b10SMatthew G. Knepley PetscCall(DMPlexGetJoin(*dm, elem->numVerts, cone, &joinSize, &join)); 1791aec57b10SMatthew G. Knepley PetscCheck(joinSize == 1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Could not determine Plex edge for Gmsh element %" PetscInt_FMT " (Plex cell %" PetscInt_FMT ")", elem->id, e); 1792aec57b10SMatthew G. Knepley for (t = 0; t < Nt; ++t) { 1793aec57b10SMatthew G. Knepley const PetscInt tag = elem->tags[t]; 17942b205333SMatthew G. Knepley const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE; 1795aec57b10SMatthew G. Knepley 17960444adf6SMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &edgeSets, "Edge Sets", join[0], tag)); 1797aec57b10SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 1798aec57b10SMatthew G. Knepley if (mesh->regionDims[r] != 1) continue; 1799aec57b10SMatthew G. Knepley if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], join[0], tag)); 1800aec57b10SMatthew G. Knepley } 1801aec57b10SMatthew G. Knepley } 1802aec57b10SMatthew G. Knepley PetscCall(DMPlexRestoreJoin(*dm, elem->numVerts, cone, &joinSize, &join)); 1803aec57b10SMatthew G. Knepley } 1804aec57b10SMatthew G. Knepley 18050c070f12SSander Arens /* Create vertex sets */ 1806aec57b10SMatthew G. Knepley if (elem->numTags && elem->dim == 0 && markvertices) { 18070598e1a2SLisandro Dalcin const PetscInt nn = elem->nodes[0]; 18080598e1a2SLisandro Dalcin const PetscInt vv = mesh->vertexMap[nn]; 1809a45dabc8SMatthew G. Knepley const PetscInt tag = elem->tags[0]; 1810a45dabc8SMatthew G. Knepley PetscInt r; 1811a45dabc8SMatthew G. Knepley 18128a3d9825SMatthew G. Knepley if (vv < 0) continue; 18132b205333SMatthew G. Knepley if (usegeneric) PetscCall(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag)); 181481a1af93SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 1815df93260fSMatthew G. Knepley if (mesh->regionDims[r] != 0) continue; 18169566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], vStart + vv, tag)); 181781a1af93SMatthew G. Knepley } 181881a1af93SMatthew G. Knepley } 181981a1af93SMatthew G. Knepley } 182081a1af93SMatthew G. Knepley if (markvertices) { 182181a1af93SMatthew G. Knepley for (v = 0; v < numNodes; ++v) { 182281a1af93SMatthew G. Knepley const PetscInt vv = mesh->vertexMap[v]; 18237d5b9244SMatthew G. Knepley const PetscInt *tags = &mesh->nodelist->tag[v * GMSH_MAX_TAGS]; 18247d5b9244SMatthew G. Knepley PetscInt r, t; 182581a1af93SMatthew G. Knepley 18268a3d9825SMatthew G. Knepley if (vv < 0) continue; 18277d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) { 18287d5b9244SMatthew G. Knepley const PetscInt tag = tags[t]; 18292b205333SMatthew G. Knepley const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE; 18307d5b9244SMatthew G. Knepley 18317d5b9244SMatthew G. Knepley if (tag == -1) continue; 1832df93260fSMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag)); 1833a45dabc8SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 18349566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], vStart + vv, tag)); 18350598e1a2SLisandro Dalcin } 18360598e1a2SLisandro Dalcin } 18370598e1a2SLisandro Dalcin } 18380598e1a2SLisandro Dalcin } 18399566063dSJacob Faibussowitsch PetscCall(PetscFree(regionSets)); 1840a45dabc8SMatthew G. Knepley } 18410598e1a2SLisandro Dalcin 18420444adf6SMatthew G. Knepley { /* Create Cell/Face/Edge/Vertex Sets labels at all processes */ 18439371c9d4SSatish Balay enum { 18440444adf6SMatthew G. Knepley n = 5 18459371c9d4SSatish Balay }; 18467dd454faSLisandro Dalcin PetscBool flag[n]; 18477dd454faSLisandro Dalcin 18487dd454faSLisandro Dalcin flag[0] = cellSets ? PETSC_TRUE : PETSC_FALSE; 18497dd454faSLisandro Dalcin flag[1] = faceSets ? PETSC_TRUE : PETSC_FALSE; 18500444adf6SMatthew G. Knepley flag[2] = edgeSets ? PETSC_TRUE : PETSC_FALSE; 18510444adf6SMatthew G. Knepley flag[3] = vertSets ? PETSC_TRUE : PETSC_FALSE; 18520444adf6SMatthew G. Knepley flag[4] = marker ? PETSC_TRUE : PETSC_FALSE; 18539566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(flag, n, MPIU_BOOL, 0, comm)); 18549566063dSJacob Faibussowitsch if (flag[0]) PetscCall(DMCreateLabel(*dm, "Cell Sets")); 18559566063dSJacob Faibussowitsch if (flag[1]) PetscCall(DMCreateLabel(*dm, "Face Sets")); 18560444adf6SMatthew G. Knepley if (flag[2]) PetscCall(DMCreateLabel(*dm, "Edge Sets")); 18570444adf6SMatthew G. Knepley if (flag[3]) PetscCall(DMCreateLabel(*dm, "Vertex Sets")); 18580444adf6SMatthew G. Knepley if (flag[4]) PetscCall(DMCreateLabel(*dm, "marker")); 18597dd454faSLisandro Dalcin } 18607dd454faSLisandro Dalcin 18610598e1a2SLisandro Dalcin if (periodic) { 18629566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(numVerts, &periodicVerts)); 18630598e1a2SLisandro Dalcin for (n = 0; n < numNodes; ++n) { 18640598e1a2SLisandro Dalcin if (mesh->vertexMap[n] >= 0) { 18650598e1a2SLisandro Dalcin if (PetscUnlikely(mesh->periodMap[n] != n)) { 18660598e1a2SLisandro Dalcin PetscInt m = mesh->periodMap[n]; 18679566063dSJacob Faibussowitsch PetscCall(PetscBTSet(periodicVerts, mesh->vertexMap[n])); 18689566063dSJacob Faibussowitsch PetscCall(PetscBTSet(periodicVerts, mesh->vertexMap[m])); 18690598e1a2SLisandro Dalcin } 18700598e1a2SLisandro Dalcin } 18710598e1a2SLisandro Dalcin } 18729db5b827SMatthew G. Knepley PetscCall(DMGetCoordinateDM(*dm, &cdm)); 1873eae3dc7dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxHeight + 1, &periodicCells)); 18749db5b827SMatthew G. Knepley for (PetscInt h = 0; h <= maxHeight; ++h) { 18759db5b827SMatthew G. Knepley PetscInt pStart, pEnd; 18769db5b827SMatthew G. Knepley 18779db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(*dm, h, &pStart, &pEnd)); 18789db5b827SMatthew G. Knepley PetscCall(PetscBTCreate(pEnd - pStart, &periodicCells[h])); 18799db5b827SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 18809db5b827SMatthew G. Knepley PetscInt *closure = NULL; 18819db5b827SMatthew G. Knepley PetscInt Ncl; 18829db5b827SMatthew G. Knepley 18839db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure)); 18849db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) { 18859db5b827SMatthew G. Knepley if (closure[cl] >= vStart && closure[cl] < vEnd) { 18869db5b827SMatthew G. Knepley if (PetscUnlikely(PetscBTLookup(periodicVerts, closure[cl] - vStart))) { 18879db5b827SMatthew G. Knepley PetscCall(PetscBTSet(periodicCells[h], p - pStart)); 18889371c9d4SSatish Balay break; 18890c070f12SSander Arens } 18900c070f12SSander Arens } 18910c070f12SSander Arens } 18929db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure)); 18939db5b827SMatthew G. Knepley } 18949db5b827SMatthew G. Knepley } 189516ad7e67SMichael Lange } 189616ad7e67SMichael Lange 1897066ea43fSLisandro Dalcin /* Setup coordinate DM */ 18980598e1a2SLisandro Dalcin if (coordDim < 0) coordDim = dim; 18999566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*dm, coordDim)); 19009566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(*dm, &cdm)); 1901066ea43fSLisandro Dalcin if (highOrder) { 1902066ea43fSLisandro Dalcin PetscFE fe; 1903066ea43fSLisandro Dalcin PetscBool continuity = periodic ? PETSC_FALSE : PETSC_TRUE; 1904066ea43fSLisandro Dalcin PetscDTNodeType nodeType = PETSCDTNODES_EQUISPACED; 1905066ea43fSLisandro Dalcin 1906066ea43fSLisandro Dalcin if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */ 1907066ea43fSLisandro Dalcin 19089566063dSJacob Faibussowitsch PetscCall(GmshCreateFE(comm, NULL, isSimplex, continuity, nodeType, dim, coordDim, order, &fe)); 19099566063dSJacob Faibussowitsch PetscCall(PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_fe_view")); 19109566063dSJacob Faibussowitsch PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)fe)); 19119566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 19129566063dSJacob Faibussowitsch PetscCall(DMCreateDS(cdm)); 1913066ea43fSLisandro Dalcin } 19146858538eSMatthew G. Knepley if (periodic) { 19156858538eSMatthew G. Knepley PetscCall(DMClone(cdm, &cdmCell)); 19166858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(*dm, cdmCell)); 19176858538eSMatthew G. Knepley } 1918066ea43fSLisandro Dalcin 1919066ea43fSLisandro Dalcin /* Create coordinates */ 1920066ea43fSLisandro Dalcin if (highOrder) { 1921066ea43fSLisandro Dalcin PetscInt maxDof = GmshNumNodes_HEX(order) * coordDim; 1922066ea43fSLisandro Dalcin double *coords = mesh ? mesh->nodelist->xyz : NULL; 1923066ea43fSLisandro Dalcin PetscSection section; 1924066ea43fSLisandro Dalcin PetscScalar *cellCoords; 1925066ea43fSLisandro Dalcin 19269566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(cdm, NULL)); 19276858538eSMatthew G. Knepley PetscCall(DMGetLocalSection(cdm, &cs)); 19286858538eSMatthew G. Knepley PetscCall(PetscSectionClone(cs, §ion)); 19299566063dSJacob Faibussowitsch PetscCall(DMPlexSetClosurePermutationTensor(cdm, 0, section)); /* XXX Implement DMPlexSetClosurePermutationLexicographic() */ 1930066ea43fSLisandro Dalcin 19319566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 19329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &cellCoords)); 1933066ea43fSLisandro Dalcin for (cell = 0; cell < numCells; ++cell) { 1934066ea43fSLisandro Dalcin GmshElement *elem = mesh->elements + cell; 1935066ea43fSLisandro Dalcin const int *lexorder = GmshCellMap[elem->cellType].lexorder(); 1936b9bf55e5SMatthew G. Knepley int s = 0; 1937066ea43fSLisandro Dalcin for (n = 0; n < elem->numNodes; ++n) { 1938b9bf55e5SMatthew G. Knepley while (lexorder[n + s] < 0) ++s; 1939b9bf55e5SMatthew G. Knepley const PetscInt node = elem->nodes[lexorder[n + s]]; 1940b9bf55e5SMatthew G. Knepley for (d = 0; d < coordDim; ++d) cellCoords[(n + s) * coordDim + d] = (PetscReal)coords[node * 3 + d]; 1941b9bf55e5SMatthew G. Knepley } 1942b9bf55e5SMatthew G. Knepley if (s) { 1943b9bf55e5SMatthew G. Knepley /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */ 1944b9bf55e5SMatthew G. Knepley PetscReal quaCenterWeights[9] = {-0.25, 0.5, -0.25, 0.5, 0.0, 0.5, -0.25, 0.5, -0.25}; 1945b9bf55e5SMatthew G. Knepley /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */ 19469371c9d4SSatish Balay PetscReal hexBottomWeights[27] = {-0.25, 0.5, -0.25, 0.5, 0.0, 0.5, -0.25, 0.5, -0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; 19479371c9d4SSatish Balay PetscReal hexFrontWeights[27] = {-0.25, 0.5, -0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.25, 0.5, -0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; 19489371c9d4SSatish Balay PetscReal hexLeftWeights[27] = {-0.25, 0.0, 0.0, 0.5, 0.0, 0.0, -0.25, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, -0.25, 0.0, 0.0, 0.5, 0.0, 0.0, -0.25, 0.0, 0.0}; 19499371c9d4SSatish Balay PetscReal hexRightWeights[27] = {0.0, 0.0, -0.25, 0.0, 0.0, 0.5, 0.0, 0.0, -0.25, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, -0.25, 0.0, 0.0, 0.5, 0.0, 0.0, -0.25}; 19509371c9d4SSatish Balay PetscReal hexBackWeights[27] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.25, 0.5, -0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.25, 0.5, -0.25}; 19519371c9d4SSatish Balay PetscReal hexTopWeights[27] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.25, 0.5, -0.25, 0.5, 0.0, 0.5, -0.25, 0.5, -0.25}; 19529371c9d4SSatish Balay PetscReal hexCenterWeights[27] = {-0.25, 0.25, -0.25, 0.25, 0.0, 0.25, -0.25, 0.25, -0.25, 0.25, 0.0, 0.25, 0.0, 0.0, 0.0, 0.25, 0.0, 0.25, -0.25, 0.25, -0.25, 0.25, 0.0, 0.25, -0.25, 0.25, -0.25}; 1953b9bf55e5SMatthew G. Knepley PetscReal *sdWeights2[9] = {NULL, NULL, NULL, NULL, quaCenterWeights, NULL, NULL, NULL, NULL}; 19549371c9d4SSatish Balay PetscReal *sdWeights3[27] = {NULL, NULL, NULL, NULL, hexBottomWeights, NULL, NULL, NULL, NULL, NULL, hexFrontWeights, NULL, hexLeftWeights, hexCenterWeights, hexRightWeights, NULL, hexBackWeights, NULL, 1955b9bf55e5SMatthew G. Knepley NULL, NULL, NULL, NULL, hexTopWeights, NULL, NULL, NULL, NULL}; 1956b9bf55e5SMatthew G. Knepley PetscReal **sdWeights[4] = {NULL, NULL, sdWeights2, sdWeights3}; 1957b9bf55e5SMatthew G. Knepley 1958b9bf55e5SMatthew G. Knepley /* Missing entries in serendipity cell, only works for 8-node quad and 20-node hex */ 1959b9bf55e5SMatthew G. Knepley for (n = 0; n < elem->numNodes + s; ++n) { 1960b9bf55e5SMatthew G. Knepley if (lexorder[n] >= 0) continue; 1961b9bf55e5SMatthew G. Knepley for (d = 0; d < coordDim; ++d) cellCoords[n * coordDim + d] = 0.0; 1962b9bf55e5SMatthew G. Knepley for (int bn = 0; bn < elem->numNodes + s; ++bn) { 1963b9bf55e5SMatthew G. Knepley if (lexorder[bn] < 0) continue; 1964b9bf55e5SMatthew G. Knepley const PetscReal *weights = sdWeights[coordDim][n]; 1965b9bf55e5SMatthew G. Knepley const PetscInt bnode = elem->nodes[lexorder[bn]]; 1966b9bf55e5SMatthew G. Knepley for (d = 0; d < coordDim; ++d) cellCoords[n * coordDim + d] += weights[bn] * (PetscReal)coords[bnode * 3 + d]; 1967b9bf55e5SMatthew G. Knepley } 1968b9bf55e5SMatthew G. Knepley } 1969066ea43fSLisandro Dalcin } 19709566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure(cdm, section, coordinates, cell, cellCoords, INSERT_VALUES)); 1971066ea43fSLisandro Dalcin } 19729566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 19739566063dSJacob Faibussowitsch PetscCall(PetscFree(cellCoords)); 1974066ea43fSLisandro Dalcin } else { 1975066ea43fSLisandro Dalcin PetscInt *nodeMap; 1976066ea43fSLisandro Dalcin double *coords = mesh ? mesh->nodelist->xyz : NULL; 1977066ea43fSLisandro Dalcin PetscScalar *pointCoords; 1978066ea43fSLisandro Dalcin 19796858538eSMatthew G. Knepley PetscCall(DMGetCoordinateSection(*dm, &cs)); 19806858538eSMatthew G. Knepley PetscCall(PetscSectionSetNumFields(cs, 1)); 19816858538eSMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(cs, 0, coordDim)); 19826858538eSMatthew G. Knepley PetscCall(PetscSectionSetChart(cs, numCells, numCells + numVerts)); 19836858538eSMatthew G. Knepley for (v = numCells; v < numCells + numVerts; ++v) { 19846858538eSMatthew G. Knepley PetscCall(PetscSectionSetDof(cs, v, coordDim)); 19856858538eSMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(cs, v, 0, coordDim)); 1986f45c9589SStefano Zampini } 19876858538eSMatthew G. Knepley PetscCall(PetscSectionSetUp(cs)); 19886858538eSMatthew G. Knepley 19896858538eSMatthew G. Knepley /* We need to localize coordinates on cells */ 19900598e1a2SLisandro Dalcin if (periodic) { 19919db5b827SMatthew G. Knepley PetscInt newStart = PETSC_MAX_INT, newEnd = -1, pStart, pEnd; 19929db5b827SMatthew G. Knepley 19936858538eSMatthew G. Knepley PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)cdmCell), &csCell)); 19946858538eSMatthew G. Knepley PetscCall(PetscSectionSetNumFields(csCell, 1)); 19956858538eSMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(csCell, 0, coordDim)); 19969db5b827SMatthew G. Knepley for (PetscInt h = 0; h <= maxHeight; h++) { 19979db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, h, &pStart, &pEnd)); 19989db5b827SMatthew G. Knepley newStart = PetscMin(newStart, pStart); 19999db5b827SMatthew G. Knepley newEnd = PetscMax(newEnd, pEnd); 20009db5b827SMatthew G. Knepley } 20019db5b827SMatthew G. Knepley PetscCall(PetscSectionSetChart(csCell, newStart, newEnd)); 20029db5b827SMatthew G. Knepley for (PetscInt h = 0; h <= maxHeight; h++) { 20039db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, h, &pStart, &pEnd)); 20049db5b827SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 20059db5b827SMatthew G. Knepley PetscInt *closure = NULL; 20069db5b827SMatthew G. Knepley PetscInt Ncl, Nv = 0; 20076858538eSMatthew G. Knepley 20089db5b827SMatthew G. Knepley if (PetscUnlikely(PetscBTLookup(periodicCells[h], p - pStart))) { 20099db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure)); 20109db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) { 20119db5b827SMatthew G. Knepley if (closure[cl] >= vStart && closure[cl] < vEnd) ++Nv; 20129db5b827SMatthew G. Knepley } 20139db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure)); 20149db5b827SMatthew G. Knepley PetscCall(PetscSectionSetDof(csCell, p, Nv * coordDim)); 20159db5b827SMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(csCell, p, 0, Nv * coordDim)); 20169db5b827SMatthew G. Knepley } 2017f45c9589SStefano Zampini } 2018f45c9589SStefano Zampini } 20196858538eSMatthew G. Knepley PetscCall(PetscSectionSetUp(csCell)); 20206858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateSection(*dm, PETSC_DETERMINE, csCell)); 2021f45c9589SStefano Zampini } 2022066ea43fSLisandro Dalcin 20239566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 20249566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &pointCoords)); 20256858538eSMatthew G. Knepley PetscCall(PetscMalloc1(numVerts, &nodeMap)); 20266858538eSMatthew G. Knepley for (n = 0; n < numNodes; n++) 20276858538eSMatthew G. Knepley if (mesh->vertexMap[n] >= 0) nodeMap[mesh->vertexMap[n]] = n; 20286858538eSMatthew G. Knepley for (v = 0; v < numVerts; ++v) { 20296858538eSMatthew G. Knepley PetscInt off, node = nodeMap[v]; 20306858538eSMatthew G. Knepley 20316858538eSMatthew G. Knepley PetscCall(PetscSectionGetOffset(cs, numCells + v, &off)); 20326858538eSMatthew G. Knepley for (d = 0; d < coordDim; ++d) pointCoords[off + d] = (PetscReal)coords[node * 3 + d]; 20336858538eSMatthew G. Knepley } 20346858538eSMatthew G. Knepley PetscCall(VecRestoreArray(coordinates, &pointCoords)); 20356858538eSMatthew G. Knepley 20360598e1a2SLisandro Dalcin if (periodic) { 20379db5b827SMatthew G. Knepley PetscInt cStart, cEnd; 20389db5b827SMatthew G. Knepley 20399db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, 0, &cStart, &cEnd)); 20406858538eSMatthew G. Knepley PetscCall(DMCreateLocalVector(cdmCell, &coordinatesCell)); 20416858538eSMatthew G. Knepley PetscCall(VecGetArray(coordinatesCell, &pointCoords)); 20429db5b827SMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) { 20439db5b827SMatthew G. Knepley GmshElement *elem = mesh->elements + c - cStart; 20449db5b827SMatthew G. Knepley PetscInt *closure = NULL; 20459db5b827SMatthew G. Knepley PetscInt verts[8]; 20469db5b827SMatthew G. Knepley PetscInt Ncl, Nv = 0; 20479db5b827SMatthew G. Knepley 20489db5b827SMatthew G. Knepley for (PetscInt v = 0; v < elem->numVerts; ++v) cone[v] = elem->nodes[v]; 20499db5b827SMatthew G. Knepley PetscCall(DMPlexReorderCell(cdmCell, c, cone)); 20509db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(cdmCell, c, PETSC_TRUE, &Ncl, &closure)); 20519db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) { 20529db5b827SMatthew G. Knepley if (closure[cl] >= vStart && closure[cl] < vEnd) verts[Nv++] = closure[cl]; 2053331830f3SMatthew G. Knepley } 20549db5b827SMatthew G. Knepley PetscCheck(Nv == elem->numVerts, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number of vertices %" PetscInt_FMT " in closure does not match number of vertices %" PetscInt_FMT " in Gmsh cell", Nv, elem->numVerts); 20559db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) { 20569db5b827SMatthew G. Knepley const PetscInt point = closure[cl]; 20579db5b827SMatthew G. Knepley PetscInt hStart, h; 20589db5b827SMatthew G. Knepley 20599db5b827SMatthew G. Knepley PetscCall(DMPlexGetPointHeight(cdmCell, point, &h)); 20609db5b827SMatthew G. Knepley if (h > maxHeight) continue; 20619db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, h, &hStart, NULL)); 20629db5b827SMatthew G. Knepley if (PetscUnlikely(PetscBTLookup(periodicCells[h], point - hStart))) { 20639db5b827SMatthew G. Knepley PetscInt *pclosure = NULL; 20649db5b827SMatthew G. Knepley PetscInt Npcl, off, v; 20659db5b827SMatthew G. Knepley 20669db5b827SMatthew G. Knepley PetscCall(PetscSectionGetOffset(csCell, point, &off)); 20679db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(cdmCell, point, PETSC_TRUE, &Npcl, &pclosure)); 20689db5b827SMatthew G. Knepley for (PetscInt pcl = 0; pcl < Npcl * 2; pcl += 2) { 20699db5b827SMatthew G. Knepley if (pclosure[pcl] >= vStart && pclosure[pcl] < vEnd) { 20709db5b827SMatthew G. Knepley for (v = 0; v < Nv; ++v) 20719db5b827SMatthew G. Knepley if (verts[v] == pclosure[pcl]) break; 20729db5b827SMatthew G. Knepley PetscCheck(v < Nv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not find vertex %" PetscInt_FMT " in closure of cell %" PetscInt_FMT, pclosure[pcl], c); 20739db5b827SMatthew G. Knepley for (PetscInt d = 0; d < coordDim; ++d) pointCoords[off++] = (PetscReal)coords[cone[v] * 3 + d]; 20749db5b827SMatthew G. Knepley ++v; 20759db5b827SMatthew G. Knepley } 20769db5b827SMatthew G. Knepley } 20779db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(cdmCell, point, PETSC_TRUE, &Npcl, &pclosure)); 20789db5b827SMatthew G. Knepley } 20799db5b827SMatthew G. Knepley } 20809db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(cdmCell, c, PETSC_TRUE, &Ncl, &closure)); 2081331830f3SMatthew G. Knepley } 20826858538eSMatthew G. Knepley PetscCall(VecSetBlockSize(coordinatesCell, coordDim)); 20836858538eSMatthew G. Knepley PetscCall(VecRestoreArray(coordinatesCell, &pointCoords)); 20846858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(*dm, coordinatesCell)); 20856858538eSMatthew G. Knepley PetscCall(VecDestroy(&coordinatesCell)); 2086331830f3SMatthew G. Knepley } 20879db5b827SMatthew G. Knepley PetscCall(PetscFree(nodeMap)); 20886858538eSMatthew G. Knepley PetscCall(PetscSectionDestroy(&csCell)); 20896858538eSMatthew G. Knepley PetscCall(DMDestroy(&cdmCell)); 2090066ea43fSLisandro Dalcin } 2091066ea43fSLisandro Dalcin 20929566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 20939566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, coordDim)); 20949566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(*dm, coordinates)); 20959566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 209611c56cb0SLisandro Dalcin 20979566063dSJacob Faibussowitsch PetscCall(GmshMeshDestroy(&mesh)); 20989566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&periodicVerts)); 2099eae3dc7dSJacob Faibussowitsch if (periodic) { 2100eae3dc7dSJacob Faibussowitsch for (PetscInt h = 0; h <= maxHeight; ++h) PetscCall(PetscBTDestroy(periodicCells + h)); 2101eae3dc7dSJacob Faibussowitsch PetscCall(PetscFree(periodicCells)); 2102eae3dc7dSJacob Faibussowitsch } 210311c56cb0SLisandro Dalcin 2104066ea43fSLisandro Dalcin if (highOrder && project) { 2105066ea43fSLisandro Dalcin PetscFE fe; 2106066ea43fSLisandro Dalcin const char prefix[] = "dm_plex_gmsh_project_"; 2107066ea43fSLisandro Dalcin PetscBool continuity = periodic ? PETSC_FALSE : PETSC_TRUE; 2108066ea43fSLisandro Dalcin PetscDTNodeType nodeType = PETSCDTNODES_GAUSSJACOBI; 2109066ea43fSLisandro Dalcin 2110066ea43fSLisandro Dalcin if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */ 21119566063dSJacob Faibussowitsch PetscCall(GmshCreateFE(comm, prefix, isSimplex, continuity, nodeType, dim, coordDim, order, &fe)); 21129566063dSJacob Faibussowitsch PetscCall(PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_project_fe_view")); 2113e44f6aebSMatthew G. Knepley PetscCall(DMSetCoordinateDisc(*dm, fe, PETSC_TRUE)); 21149566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 2115066ea43fSLisandro Dalcin } 2116066ea43fSLisandro Dalcin 21179566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreateGmsh, *dm, NULL, NULL, NULL)); 21183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2119331830f3SMatthew G. Knepley } 2120