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 12010dd146fSPierre Jolivet // clang-format off 12110dd146fSPierre Jolivet #define GmshCellEntry(cellType, polytope, dim, order) {cellType, GMSH_##polytope, dim, order, GmshNumNodes_##polytope(1), GmshNumNodes_##polytope(order), GmshLexOrder_##polytope##_##order} 12210dd146fSPierre Jolivet // clang-format on 1230598e1a2SLisandro Dalcin 1240598e1a2SLisandro Dalcin static const GmshCellInfo GmshCellTable[] = { 125066ea43fSLisandro Dalcin GmshCellEntry(15, VTX, 0, 0), 1260598e1a2SLisandro Dalcin 1279371c9d4SSatish Balay GmshCellEntry(1, SEG, 1, 1), GmshCellEntry(8, SEG, 1, 2), GmshCellEntry(26, SEG, 1, 3), 1289371c9d4SSatish Balay GmshCellEntry(27, SEG, 1, 4), GmshCellEntry(28, SEG, 1, 5), GmshCellEntry(62, SEG, 1, 6), 1299371c9d4SSatish Balay GmshCellEntry(63, SEG, 1, 7), GmshCellEntry(64, SEG, 1, 8), GmshCellEntry(65, SEG, 1, 9), 130066ea43fSLisandro Dalcin GmshCellEntry(66, SEG, 1, 10), 1310598e1a2SLisandro Dalcin 1329371c9d4SSatish Balay GmshCellEntry(2, TRI, 2, 1), GmshCellEntry(9, TRI, 2, 2), GmshCellEntry(21, TRI, 2, 3), 1339371c9d4SSatish Balay GmshCellEntry(23, TRI, 2, 4), GmshCellEntry(25, TRI, 2, 5), GmshCellEntry(42, TRI, 2, 6), 1349371c9d4SSatish Balay GmshCellEntry(43, TRI, 2, 7), GmshCellEntry(44, TRI, 2, 8), GmshCellEntry(45, TRI, 2, 9), 135066ea43fSLisandro Dalcin GmshCellEntry(46, TRI, 2, 10), 1360598e1a2SLisandro Dalcin 1379371c9d4SSatish Balay GmshCellEntry(3, QUA, 2, 1), GmshCellEntry(10, QUA, 2, 2), {16, GMSH_QUA, 2, 2, 4, 8, GmshLexOrder_QUA_2_Serendipity}, 1389371c9d4SSatish Balay GmshCellEntry(36, QUA, 2, 3), GmshCellEntry(37, QUA, 2, 4), GmshCellEntry(38, QUA, 2, 5), 1399371c9d4SSatish Balay GmshCellEntry(47, QUA, 2, 6), GmshCellEntry(48, QUA, 2, 7), GmshCellEntry(49, QUA, 2, 8), 1409371c9d4SSatish Balay GmshCellEntry(50, QUA, 2, 9), GmshCellEntry(51, QUA, 2, 10), 1410598e1a2SLisandro Dalcin 1429371c9d4SSatish Balay GmshCellEntry(4, TET, 3, 1), GmshCellEntry(11, TET, 3, 2), GmshCellEntry(29, TET, 3, 3), 1439371c9d4SSatish Balay GmshCellEntry(30, TET, 3, 4), GmshCellEntry(31, TET, 3, 5), GmshCellEntry(71, TET, 3, 6), 1449371c9d4SSatish Balay GmshCellEntry(72, TET, 3, 7), GmshCellEntry(73, TET, 3, 8), GmshCellEntry(74, TET, 3, 9), 145066ea43fSLisandro Dalcin GmshCellEntry(75, TET, 3, 10), 1460598e1a2SLisandro Dalcin 1479371c9d4SSatish Balay GmshCellEntry(5, HEX, 3, 1), GmshCellEntry(12, HEX, 3, 2), {17, GMSH_HEX, 3, 2, 8, 20, GmshLexOrder_HEX_2_Serendipity}, 1489371c9d4SSatish Balay GmshCellEntry(92, HEX, 3, 3), GmshCellEntry(93, HEX, 3, 4), GmshCellEntry(94, HEX, 3, 5), 1499371c9d4SSatish Balay GmshCellEntry(95, HEX, 3, 6), GmshCellEntry(96, HEX, 3, 7), GmshCellEntry(97, HEX, 3, 8), 1509371c9d4SSatish Balay GmshCellEntry(98, HEX, 3, 9), GmshCellEntry(-1, HEX, 3, 10), 1510598e1a2SLisandro Dalcin 1529371c9d4SSatish Balay GmshCellEntry(6, PRI, 3, 1), GmshCellEntry(13, PRI, 3, 2), GmshCellEntry(90, PRI, 3, 3), 1539371c9d4SSatish Balay GmshCellEntry(91, PRI, 3, 4), GmshCellEntry(106, PRI, 3, 5), GmshCellEntry(107, PRI, 3, 6), 1549371c9d4SSatish Balay GmshCellEntry(108, PRI, 3, 7), GmshCellEntry(109, PRI, 3, 8), GmshCellEntry(110, PRI, 3, 9), 155066ea43fSLisandro Dalcin GmshCellEntry(-1, PRI, 3, 10), 1560598e1a2SLisandro Dalcin 1579371c9d4SSatish Balay GmshCellEntry(7, PYR, 3, 1), GmshCellEntry(14, PYR, 3, 2), GmshCellEntry(118, PYR, 3, 3), 1589371c9d4SSatish Balay GmshCellEntry(119, PYR, 3, 4), GmshCellEntry(120, PYR, 3, 5), GmshCellEntry(121, PYR, 3, 6), 1599371c9d4SSatish Balay GmshCellEntry(122, PYR, 3, 7), GmshCellEntry(123, PYR, 3, 8), GmshCellEntry(124, PYR, 3, 9), 160066ea43fSLisandro Dalcin GmshCellEntry(-1, PYR, 3, 10) 1610598e1a2SLisandro Dalcin 1620598e1a2SLisandro Dalcin #if 0 163066ea43fSLisandro Dalcin {20, GMSH_TRI, 2, 3, 3, 9, NULL}, 164066ea43fSLisandro Dalcin {18, GMSH_PRI, 3, 2, 6, 15, NULL}, 165066ea43fSLisandro Dalcin {19, GMSH_PYR, 3, 2, 5, 13, NULL}, 1660598e1a2SLisandro Dalcin #endif 1670598e1a2SLisandro Dalcin }; 1680598e1a2SLisandro Dalcin 1690598e1a2SLisandro Dalcin static GmshCellInfo GmshCellMap[150]; 1700598e1a2SLisandro Dalcin 171d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshCellInfoSetUp(void) 172d71ae5a4SJacob Faibussowitsch { 1730598e1a2SLisandro Dalcin size_t i, n; 1740598e1a2SLisandro Dalcin static PetscBool called = PETSC_FALSE; 1750598e1a2SLisandro Dalcin 1760598e1a2SLisandro Dalcin PetscFunctionBegin; 1774d86920dSPierre Jolivet if (called) PetscFunctionReturn(PETSC_SUCCESS); 1780598e1a2SLisandro Dalcin called = PETSC_TRUE; 179dd39110bSPierre Jolivet n = PETSC_STATIC_ARRAY_LENGTH(GmshCellMap); 1800598e1a2SLisandro Dalcin for (i = 0; i < n; ++i) { 1810598e1a2SLisandro Dalcin GmshCellMap[i].cellType = -1; 182066ea43fSLisandro Dalcin GmshCellMap[i].polytope = -1; 1830598e1a2SLisandro Dalcin } 184dd39110bSPierre Jolivet n = PETSC_STATIC_ARRAY_LENGTH(GmshCellTable); 185066ea43fSLisandro Dalcin for (i = 0; i < n; ++i) { 186066ea43fSLisandro Dalcin if (GmshCellTable[i].cellType <= 0) continue; 187066ea43fSLisandro Dalcin GmshCellMap[GmshCellTable[i].cellType] = GmshCellTable[i]; 188066ea43fSLisandro Dalcin } 1893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1900598e1a2SLisandro Dalcin } 1910598e1a2SLisandro Dalcin 1929371c9d4SSatish Balay #define GmshCellTypeCheck(ct) \ 1939371c9d4SSatish 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_); \ 1949371c9d4SSatish Balay PetscCheck(GmshCellMap[_ct_].polytope != -1, PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported Gmsh element type %d", _ct_);) 1950598e1a2SLisandro Dalcin 1960598e1a2SLisandro Dalcin typedef struct { 197698a79b9SLisandro Dalcin PetscViewer viewer; 198698a79b9SLisandro Dalcin int fileFormat; 199698a79b9SLisandro Dalcin int dataSize; 200698a79b9SLisandro Dalcin PetscBool binary; 201698a79b9SLisandro Dalcin PetscBool byteSwap; 202698a79b9SLisandro Dalcin size_t wlen; 203698a79b9SLisandro Dalcin void *wbuf; 204698a79b9SLisandro Dalcin size_t slen; 205698a79b9SLisandro Dalcin void *sbuf; 2060598e1a2SLisandro Dalcin PetscInt *nbuf; 2070598e1a2SLisandro Dalcin PetscInt nodeStart; 2080598e1a2SLisandro Dalcin PetscInt nodeEnd; 20933a088b6SMatthew G. Knepley PetscInt *nodeMap; 210698a79b9SLisandro Dalcin } GmshFile; 211de78e4feSLisandro Dalcin 212d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshBufferGet(GmshFile *gmsh, size_t count, size_t eltsize, void *buf) 213d71ae5a4SJacob Faibussowitsch { 214de78e4feSLisandro Dalcin size_t size = count * eltsize; 21511c56cb0SLisandro Dalcin 21611c56cb0SLisandro Dalcin PetscFunctionBegin; 217698a79b9SLisandro Dalcin if (gmsh->wlen < size) { 2189566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->wbuf)); 2199566063dSJacob Faibussowitsch PetscCall(PetscMalloc(size, &gmsh->wbuf)); 220698a79b9SLisandro Dalcin gmsh->wlen = size; 221de78e4feSLisandro Dalcin } 222698a79b9SLisandro Dalcin *(void **)buf = size ? gmsh->wbuf : NULL; 2233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 224de78e4feSLisandro Dalcin } 225de78e4feSLisandro Dalcin 226d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshBufferSizeGet(GmshFile *gmsh, size_t count, void *buf) 227d71ae5a4SJacob Faibussowitsch { 228698a79b9SLisandro Dalcin size_t dataSize = (size_t)gmsh->dataSize; 229698a79b9SLisandro Dalcin size_t size = count * dataSize; 230698a79b9SLisandro Dalcin 231698a79b9SLisandro Dalcin PetscFunctionBegin; 232698a79b9SLisandro Dalcin if (gmsh->slen < size) { 2339566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->sbuf)); 2349566063dSJacob Faibussowitsch PetscCall(PetscMalloc(size, &gmsh->sbuf)); 235698a79b9SLisandro Dalcin gmsh->slen = size; 236698a79b9SLisandro Dalcin } 237698a79b9SLisandro Dalcin *(void **)buf = size ? gmsh->sbuf : NULL; 2383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 239698a79b9SLisandro Dalcin } 240698a79b9SLisandro Dalcin 241d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshRead(GmshFile *gmsh, void *buf, PetscInt count, PetscDataType dtype) 242d71ae5a4SJacob Faibussowitsch { 243de78e4feSLisandro Dalcin PetscFunctionBegin; 2449566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(gmsh->viewer, buf, count, NULL, dtype)); 2459566063dSJacob Faibussowitsch if (gmsh->byteSwap) PetscCall(PetscByteSwap(buf, dtype, count)); 2463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 247698a79b9SLisandro Dalcin } 248698a79b9SLisandro Dalcin 249d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadString(GmshFile *gmsh, char *buf, PetscInt count) 250d71ae5a4SJacob Faibussowitsch { 251698a79b9SLisandro Dalcin PetscFunctionBegin; 2529566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(gmsh->viewer, buf, count, NULL, PETSC_STRING)); 2533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 254698a79b9SLisandro Dalcin } 255698a79b9SLisandro Dalcin 256d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMatch(PETSC_UNUSED GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN], PetscBool *match) 257d71ae5a4SJacob Faibussowitsch { 258d6689ca9SLisandro Dalcin PetscFunctionBegin; 2599566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(line, Section, match)); 2603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 261d6689ca9SLisandro Dalcin } 262d6689ca9SLisandro Dalcin 263d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshExpect(GmshFile *gmsh, const char Section[], char line[PETSC_MAX_PATH_LEN]) 264d71ae5a4SJacob Faibussowitsch { 265d6689ca9SLisandro Dalcin PetscBool match; 266d6689ca9SLisandro Dalcin 267d6689ca9SLisandro Dalcin PetscFunctionBegin; 2689566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, Section, line, &match)); 26900045ab3SPierre Jolivet PetscCheck(match, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file, expecting %s, not %s", Section, line); 2703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 271d6689ca9SLisandro Dalcin } 272d6689ca9SLisandro Dalcin 273d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadSection(GmshFile *gmsh, char line[PETSC_MAX_PATH_LEN]) 274d71ae5a4SJacob Faibussowitsch { 275d6689ca9SLisandro Dalcin PetscBool match; 276d6689ca9SLisandro Dalcin 277d6689ca9SLisandro Dalcin PetscFunctionBegin; 278d6689ca9SLisandro Dalcin while (PETSC_TRUE) { 2799566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1)); 2809566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$Comments", line, &match)); 281d6689ca9SLisandro Dalcin if (!match) break; 282d6689ca9SLisandro Dalcin while (PETSC_TRUE) { 2839566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1)); 2849566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$EndComments", line, &match)); 285d6689ca9SLisandro Dalcin if (match) break; 286d6689ca9SLisandro Dalcin } 287d6689ca9SLisandro Dalcin } 2883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 289d6689ca9SLisandro Dalcin } 290d6689ca9SLisandro Dalcin 291d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEndSection(GmshFile *gmsh, const char EndSection[], char line[PETSC_MAX_PATH_LEN]) 292d71ae5a4SJacob Faibussowitsch { 293d6689ca9SLisandro Dalcin PetscFunctionBegin; 2949566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1)); 2959566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, EndSection, line)); 2963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 297d6689ca9SLisandro Dalcin } 298d6689ca9SLisandro Dalcin 299d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadSize(GmshFile *gmsh, PetscInt *buf, PetscInt count) 300d71ae5a4SJacob Faibussowitsch { 301698a79b9SLisandro Dalcin PetscInt i; 302698a79b9SLisandro Dalcin size_t dataSize = (size_t)gmsh->dataSize; 303698a79b9SLisandro Dalcin 304698a79b9SLisandro Dalcin PetscFunctionBegin; 305698a79b9SLisandro Dalcin if (dataSize == sizeof(PetscInt)) { 3069566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, buf, count, PETSC_INT)); 307698a79b9SLisandro Dalcin } else if (dataSize == sizeof(int)) { 308698a79b9SLisandro Dalcin int *ibuf = NULL; 3099566063dSJacob Faibussowitsch PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf)); 3109566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, ibuf, count, PETSC_ENUM)); 311698a79b9SLisandro Dalcin for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 312698a79b9SLisandro Dalcin } else if (dataSize == sizeof(long)) { 313698a79b9SLisandro Dalcin long *ibuf = NULL; 3149566063dSJacob Faibussowitsch PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf)); 3159566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, ibuf, count, PETSC_LONG)); 316698a79b9SLisandro Dalcin for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 317698a79b9SLisandro Dalcin } else if (dataSize == sizeof(PetscInt64)) { 318698a79b9SLisandro Dalcin PetscInt64 *ibuf = NULL; 3199566063dSJacob Faibussowitsch PetscCall(GmshBufferSizeGet(gmsh, count, &ibuf)); 3209566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, ibuf, count, PETSC_INT64)); 321698a79b9SLisandro Dalcin for (i = 0; i < count; ++i) buf[i] = (PetscInt)ibuf[i]; 322698a79b9SLisandro Dalcin } 3233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 324698a79b9SLisandro Dalcin } 325698a79b9SLisandro Dalcin 326d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadInt(GmshFile *gmsh, int *buf, PetscInt count) 327d71ae5a4SJacob Faibussowitsch { 328698a79b9SLisandro Dalcin PetscFunctionBegin; 3299566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, buf, count, PETSC_ENUM)); 3303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 331698a79b9SLisandro Dalcin } 332698a79b9SLisandro Dalcin 333d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadDouble(GmshFile *gmsh, double *buf, PetscInt count) 334d71ae5a4SJacob Faibussowitsch { 335698a79b9SLisandro Dalcin PetscFunctionBegin; 3369566063dSJacob Faibussowitsch PetscCall(GmshRead(gmsh, buf, count, PETSC_DOUBLE)); 3373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 338de78e4feSLisandro Dalcin } 339de78e4feSLisandro Dalcin 3409c0edc59SMatthew G. Knepley #define GMSH_MAX_TAGS 16 3417d5b9244SMatthew G. Knepley 342de78e4feSLisandro Dalcin typedef struct { 3430598e1a2SLisandro Dalcin PetscInt id; /* Entity ID */ 3440598e1a2SLisandro Dalcin PetscInt dim; /* Dimension */ 345de78e4feSLisandro Dalcin double bbox[6]; /* Bounding box */ 346de78e4feSLisandro Dalcin PetscInt numTags; /* Size of tag array */ 3477d5b9244SMatthew G. Knepley int tags[GMSH_MAX_TAGS]; /* Tag array */ 348de78e4feSLisandro Dalcin } GmshEntity; 349de78e4feSLisandro Dalcin 350de78e4feSLisandro Dalcin typedef struct { 351730356f6SLisandro Dalcin GmshEntity *entity[4]; 352730356f6SLisandro Dalcin PetscHMapI entityMap[4]; 353730356f6SLisandro Dalcin } GmshEntities; 354730356f6SLisandro Dalcin 355d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesCreate(PetscInt count[4], GmshEntities **entities) 356d71ae5a4SJacob Faibussowitsch { 357730356f6SLisandro Dalcin PetscInt dim; 358730356f6SLisandro Dalcin 359730356f6SLisandro Dalcin PetscFunctionBegin; 3609566063dSJacob Faibussowitsch PetscCall(PetscNew(entities)); 361730356f6SLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 3629566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(count[dim], &(*entities)->entity[dim])); 3639566063dSJacob Faibussowitsch PetscCall(PetscHMapICreate(&(*entities)->entityMap[dim])); 364730356f6SLisandro Dalcin } 3653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 366730356f6SLisandro Dalcin } 367730356f6SLisandro Dalcin 368d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesDestroy(GmshEntities **entities) 369d71ae5a4SJacob Faibussowitsch { 3700598e1a2SLisandro Dalcin PetscInt dim; 3710598e1a2SLisandro Dalcin 3720598e1a2SLisandro Dalcin PetscFunctionBegin; 3733ba16761SJacob Faibussowitsch if (!*entities) PetscFunctionReturn(PETSC_SUCCESS); 3740598e1a2SLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 3759566063dSJacob Faibussowitsch PetscCall(PetscFree((*entities)->entity[dim])); 3769566063dSJacob Faibussowitsch PetscCall(PetscHMapIDestroy(&(*entities)->entityMap[dim])); 3770598e1a2SLisandro Dalcin } 378f4f49eeaSPierre Jolivet PetscCall(PetscFree(*entities)); 3793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3800598e1a2SLisandro Dalcin } 3810598e1a2SLisandro Dalcin 382d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesAdd(GmshEntities *entities, PetscInt index, PetscInt dim, PetscInt eid, GmshEntity **entity) 383d71ae5a4SJacob Faibussowitsch { 384730356f6SLisandro Dalcin PetscFunctionBegin; 3859566063dSJacob Faibussowitsch PetscCall(PetscHMapISet(entities->entityMap[dim], eid, index)); 386730356f6SLisandro Dalcin entities->entity[dim][index].dim = dim; 387730356f6SLisandro Dalcin entities->entity[dim][index].id = eid; 388730356f6SLisandro Dalcin if (entity) *entity = &entities->entity[dim][index]; 3893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 390730356f6SLisandro Dalcin } 391730356f6SLisandro Dalcin 392d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshEntitiesGet(GmshEntities *entities, PetscInt dim, PetscInt eid, GmshEntity **entity) 393d71ae5a4SJacob Faibussowitsch { 394730356f6SLisandro Dalcin PetscInt index; 395730356f6SLisandro Dalcin 396730356f6SLisandro Dalcin PetscFunctionBegin; 3979566063dSJacob Faibussowitsch PetscCall(PetscHMapIGet(entities->entityMap[dim], eid, &index)); 398730356f6SLisandro Dalcin *entity = &entities->entity[dim][index]; 3993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 400730356f6SLisandro Dalcin } 401730356f6SLisandro Dalcin 4020598e1a2SLisandro Dalcin typedef struct { 4030598e1a2SLisandro Dalcin PetscInt *id; /* Node IDs */ 4040598e1a2SLisandro Dalcin double *xyz; /* Coordinates */ 40581a1af93SMatthew G. Knepley PetscInt *tag; /* Physical tag */ 4060598e1a2SLisandro Dalcin } GmshNodes; 4070598e1a2SLisandro Dalcin 408d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshNodesCreate(PetscInt count, GmshNodes **nodes) 409d71ae5a4SJacob Faibussowitsch { 410730356f6SLisandro Dalcin PetscFunctionBegin; 4119566063dSJacob Faibussowitsch PetscCall(PetscNew(nodes)); 4129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(count * 1, &(*nodes)->id)); 4139566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(count * 3, &(*nodes)->xyz)); 4147d5b9244SMatthew G. Knepley PetscCall(PetscMalloc1(count * GMSH_MAX_TAGS, &(*nodes)->tag)); 4153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 416730356f6SLisandro Dalcin } 4170598e1a2SLisandro Dalcin 418d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshNodesDestroy(GmshNodes **nodes) 419d71ae5a4SJacob Faibussowitsch { 4200598e1a2SLisandro Dalcin PetscFunctionBegin; 4213ba16761SJacob Faibussowitsch if (!*nodes) PetscFunctionReturn(PETSC_SUCCESS); 4229566063dSJacob Faibussowitsch PetscCall(PetscFree((*nodes)->id)); 4239566063dSJacob Faibussowitsch PetscCall(PetscFree((*nodes)->xyz)); 4249566063dSJacob Faibussowitsch PetscCall(PetscFree((*nodes)->tag)); 425f4f49eeaSPierre Jolivet PetscCall(PetscFree(*nodes)); 4263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 427730356f6SLisandro Dalcin } 428730356f6SLisandro Dalcin 429730356f6SLisandro Dalcin typedef struct { 4300598e1a2SLisandro Dalcin PetscInt id; /* Element ID */ 4310598e1a2SLisandro Dalcin PetscInt dim; /* Dimension */ 432de78e4feSLisandro Dalcin PetscInt cellType; /* Cell type */ 4330598e1a2SLisandro Dalcin PetscInt numVerts; /* Size of vertex array */ 434de78e4feSLisandro Dalcin PetscInt numNodes; /* Size of node array */ 4350598e1a2SLisandro Dalcin PetscInt *nodes; /* Vertex/Node array */ 43681a1af93SMatthew G. Knepley PetscInt numTags; /* Size of physical tag array */ 4377d5b9244SMatthew G. Knepley int tags[GMSH_MAX_TAGS]; /* Physical tag array */ 438de78e4feSLisandro Dalcin } GmshElement; 439de78e4feSLisandro Dalcin 440d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshElementsCreate(PetscInt count, GmshElement **elements) 441d71ae5a4SJacob Faibussowitsch { 4420598e1a2SLisandro Dalcin PetscFunctionBegin; 4439566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(count, elements)); 4443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4450598e1a2SLisandro Dalcin } 4460598e1a2SLisandro Dalcin 447d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshElementsDestroy(GmshElement **elements) 448d71ae5a4SJacob Faibussowitsch { 4490598e1a2SLisandro Dalcin PetscFunctionBegin; 4503ba16761SJacob Faibussowitsch if (!*elements) PetscFunctionReturn(PETSC_SUCCESS); 4519566063dSJacob Faibussowitsch PetscCall(PetscFree(*elements)); 4523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4530598e1a2SLisandro Dalcin } 4540598e1a2SLisandro Dalcin 4550598e1a2SLisandro Dalcin typedef struct { 4560598e1a2SLisandro Dalcin PetscInt dim; 457066ea43fSLisandro Dalcin PetscInt order; 4580598e1a2SLisandro Dalcin GmshEntities *entities; 4590598e1a2SLisandro Dalcin PetscInt numNodes; 4600598e1a2SLisandro Dalcin GmshNodes *nodelist; 4610598e1a2SLisandro Dalcin PetscInt numElems; 4620598e1a2SLisandro Dalcin GmshElement *elements; 4630598e1a2SLisandro Dalcin PetscInt numVerts; 4640598e1a2SLisandro Dalcin PetscInt numCells; 4650598e1a2SLisandro Dalcin PetscInt *periodMap; 4660598e1a2SLisandro Dalcin PetscInt *vertexMap; 4670598e1a2SLisandro Dalcin PetscSegBuffer segbuf; 468a45dabc8SMatthew G. Knepley PetscInt numRegions; 46990d778b8SLisandro Dalcin PetscInt *regionDims; 470a45dabc8SMatthew G. Knepley PetscInt *regionTags; 471a45dabc8SMatthew G. Knepley char **regionNames; 4720598e1a2SLisandro Dalcin } GmshMesh; 4730598e1a2SLisandro Dalcin 474d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMeshCreate(GmshMesh **mesh) 475d71ae5a4SJacob Faibussowitsch { 4760598e1a2SLisandro Dalcin PetscFunctionBegin; 4779566063dSJacob Faibussowitsch PetscCall(PetscNew(mesh)); 4789566063dSJacob Faibussowitsch PetscCall(PetscSegBufferCreate(sizeof(PetscInt), 0, &(*mesh)->segbuf)); 4793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4800598e1a2SLisandro Dalcin } 4810598e1a2SLisandro Dalcin 482d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshMeshDestroy(GmshMesh **mesh) 483d71ae5a4SJacob Faibussowitsch { 484a45dabc8SMatthew G. Knepley PetscInt r; 4850598e1a2SLisandro Dalcin 4860598e1a2SLisandro Dalcin PetscFunctionBegin; 4873ba16761SJacob Faibussowitsch if (!*mesh) PetscFunctionReturn(PETSC_SUCCESS); 4889566063dSJacob Faibussowitsch PetscCall(GmshEntitiesDestroy(&(*mesh)->entities)); 4899566063dSJacob Faibussowitsch PetscCall(GmshNodesDestroy(&(*mesh)->nodelist)); 4909566063dSJacob Faibussowitsch PetscCall(GmshElementsDestroy(&(*mesh)->elements)); 4919566063dSJacob Faibussowitsch PetscCall(PetscFree((*mesh)->periodMap)); 4929566063dSJacob Faibussowitsch PetscCall(PetscFree((*mesh)->vertexMap)); 4939566063dSJacob Faibussowitsch PetscCall(PetscSegBufferDestroy(&(*mesh)->segbuf)); 4949566063dSJacob Faibussowitsch for (r = 0; r < (*mesh)->numRegions; ++r) PetscCall(PetscFree((*mesh)->regionNames[r])); 49590d778b8SLisandro Dalcin PetscCall(PetscFree3((*mesh)->regionDims, (*mesh)->regionTags, (*mesh)->regionNames)); 496f4f49eeaSPierre Jolivet PetscCall(PetscFree(*mesh)); 4973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4980598e1a2SLisandro Dalcin } 4990598e1a2SLisandro Dalcin 500d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v22(GmshFile *gmsh, GmshMesh *mesh) 501d71ae5a4SJacob Faibussowitsch { 502698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 503698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 504de78e4feSLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 5057d5b9244SMatthew G. Knepley int n, t, num, nid, snum; 5060598e1a2SLisandro Dalcin GmshNodes *nodes; 507de78e4feSLisandro Dalcin 508de78e4feSLisandro Dalcin PetscFunctionBegin; 5099566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 510698a79b9SLisandro Dalcin snum = sscanf(line, "%d", &num); 51108401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 5129566063dSJacob Faibussowitsch PetscCall(GmshNodesCreate(num, &nodes)); 5130598e1a2SLisandro Dalcin mesh->numNodes = num; 5140598e1a2SLisandro Dalcin mesh->nodelist = nodes; 5150598e1a2SLisandro Dalcin for (n = 0; n < num; ++n) { 5160598e1a2SLisandro Dalcin double *xyz = nodes->xyz + n * 3; 5179566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM)); 5189566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE)); 5199566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1)); 5209566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3)); 5210598e1a2SLisandro Dalcin nodes->id[n] = nid; 5227d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1; 52311c56cb0SLisandro Dalcin } 5243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 52511c56cb0SLisandro Dalcin } 52611c56cb0SLisandro Dalcin 527de78e4feSLisandro Dalcin /* Gmsh elements can be of any dimension/co-dimension, so we need to traverse the 528de78e4feSLisandro Dalcin file contents multiple times to figure out the true number of cells and facets 529de78e4feSLisandro Dalcin in the given mesh. To make this more efficient we read the file contents only 530de78e4feSLisandro Dalcin once and store them in memory, while determining the true number of cells. */ 531d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v22(GmshFile *gmsh, GmshMesh *mesh) 532d71ae5a4SJacob Faibussowitsch { 533698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 534698a79b9SLisandro Dalcin PetscBool binary = gmsh->binary; 535698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 536de78e4feSLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 5370598e1a2SLisandro Dalcin int i, c, p, num, ibuf[1 + 4 + 1000], snum; 5380598e1a2SLisandro Dalcin int cellType, numElem, numVerts, numNodes, numTags; 539df032b82SMatthew G. Knepley GmshElement *elements; 5400598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 541df032b82SMatthew G. Knepley 542df032b82SMatthew G. Knepley PetscFunctionBegin; 5439566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 544698a79b9SLisandro Dalcin snum = sscanf(line, "%d", &num); 54508401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 5469566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(num, &elements)); 5470598e1a2SLisandro Dalcin mesh->numElems = num; 5480598e1a2SLisandro Dalcin mesh->elements = elements; 549698a79b9SLisandro Dalcin for (c = 0; c < num;) { 5509566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM)); 5519566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 3)); 5520598e1a2SLisandro Dalcin 5530598e1a2SLisandro Dalcin cellType = binary ? ibuf[0] : ibuf[1]; 5540598e1a2SLisandro Dalcin numElem = binary ? ibuf[1] : 1; 555df032b82SMatthew G. Knepley numTags = ibuf[2]; 5560598e1a2SLisandro Dalcin 5579566063dSJacob Faibussowitsch PetscCall(GmshCellTypeCheck(cellType)); 5580598e1a2SLisandro Dalcin numVerts = GmshCellMap[cellType].numVerts; 5590598e1a2SLisandro Dalcin numNodes = GmshCellMap[cellType].numNodes; 5600598e1a2SLisandro Dalcin 561df032b82SMatthew G. Knepley for (i = 0; i < numElem; ++i, ++c) { 5620598e1a2SLisandro Dalcin GmshElement *element = elements + c; 5630598e1a2SLisandro Dalcin const int off = binary ? 0 : 1, nint = 1 + numTags + numNodes - off; 5640598e1a2SLisandro Dalcin const int *id = ibuf, *nodes = ibuf + 1 + numTags, *tags = ibuf + 1; 5659566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf + off, nint, NULL, PETSC_ENUM)); 5669566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf + off, PETSC_ENUM, nint)); 5670598e1a2SLisandro Dalcin element->id = id[0]; 5680598e1a2SLisandro Dalcin element->dim = GmshCellMap[cellType].dim; 5690598e1a2SLisandro Dalcin element->cellType = cellType; 5700598e1a2SLisandro Dalcin element->numVerts = numVerts; 5710598e1a2SLisandro Dalcin element->numNodes = numNodes; 5727d5b9244SMatthew G. Knepley element->numTags = PetscMin(numTags, GMSH_MAX_TAGS); 5739566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes)); 5740598e1a2SLisandro Dalcin for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 5750598e1a2SLisandro Dalcin for (p = 0; p < element->numTags; p++) element->tags[p] = tags[p]; 576df032b82SMatthew G. Knepley } 577df032b82SMatthew G. Knepley } 5783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 579df032b82SMatthew G. Knepley } 5807d282ae0SMichael Lange 581de78e4feSLisandro Dalcin /* 582de78e4feSLisandro Dalcin $Entities 583de78e4feSLisandro Dalcin numPoints(unsigned long) numCurves(unsigned long) 584de78e4feSLisandro Dalcin numSurfaces(unsigned long) numVolumes(unsigned long) 585de78e4feSLisandro Dalcin // points 586de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 587de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 588de78e4feSLisandro Dalcin numPhysicals(unsigned long) phyisicalTag[...](int) 589de78e4feSLisandro Dalcin ... 590de78e4feSLisandro Dalcin // curves 591de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 592de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 593de78e4feSLisandro Dalcin numPhysicals(unsigned long) physicalTag[...](int) 594de78e4feSLisandro Dalcin numBREPVert(unsigned long) tagBREPVert[...](int) 595de78e4feSLisandro Dalcin ... 596de78e4feSLisandro Dalcin // surfaces 597de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 598de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 599de78e4feSLisandro Dalcin numPhysicals(unsigned long) physicalTag[...](int) 600de78e4feSLisandro Dalcin numBREPCurve(unsigned long) tagBREPCurve[...](int) 601de78e4feSLisandro Dalcin ... 602de78e4feSLisandro Dalcin // volumes 603de78e4feSLisandro Dalcin tag(int) boxMinX(double) boxMinY(double) boxMinZ(double) 604de78e4feSLisandro Dalcin boxMaxX(double) boxMaxY(double) boxMaxZ(double) 605de78e4feSLisandro Dalcin numPhysicals(unsigned long) physicalTag[...](int) 606de78e4feSLisandro Dalcin numBREPSurfaces(unsigned long) tagBREPSurfaces[...](int) 607de78e4feSLisandro Dalcin ... 608de78e4feSLisandro Dalcin $EndEntities 609de78e4feSLisandro Dalcin */ 610d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities_v40(GmshFile *gmsh, GmshMesh *mesh) 611d71ae5a4SJacob Faibussowitsch { 612698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 613698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 614698a79b9SLisandro Dalcin long index, num, lbuf[4]; 615730356f6SLisandro Dalcin int dim, eid, numTags, *ibuf, t; 616698a79b9SLisandro Dalcin PetscInt count[4], i; 617a5ba3d71SLisandro Dalcin GmshEntity *entity = NULL; 618de78e4feSLisandro Dalcin 619de78e4feSLisandro Dalcin PetscFunctionBegin; 6209566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, lbuf, 4, NULL, PETSC_LONG)); 6219566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(lbuf, PETSC_LONG, 4)); 622698a79b9SLisandro Dalcin for (i = 0; i < 4; ++i) count[i] = lbuf[i]; 6239566063dSJacob Faibussowitsch PetscCall(GmshEntitiesCreate(count, &mesh->entities)); 624de78e4feSLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 625730356f6SLisandro Dalcin for (index = 0; index < count[dim]; ++index) { 6269566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &eid, 1, NULL, PETSC_ENUM)); 6279566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&eid, PETSC_ENUM, 1)); 6289566063dSJacob Faibussowitsch PetscCall(GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity)); 6299566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, entity->bbox, 6, NULL, PETSC_DOUBLE)); 6309566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(entity->bbox, PETSC_DOUBLE, 6)); 6319566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &num, 1, NULL, PETSC_LONG)); 6329566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&num, PETSC_LONG, 1)); 6339566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, num, sizeof(int), &ibuf)); 6349566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM)); 6359566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, num)); 6367d5b9244SMatthew G. Knepley entity->numTags = numTags = (int)PetscMin(num, GMSH_MAX_TAGS); 637de78e4feSLisandro Dalcin for (t = 0; t < numTags; ++t) entity->tags[t] = ibuf[t]; 638de78e4feSLisandro Dalcin if (dim == 0) continue; 6399566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &num, 1, NULL, PETSC_LONG)); 6409566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&num, PETSC_LONG, 1)); 6419566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, num, sizeof(int), &ibuf)); 6429566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, num, NULL, PETSC_ENUM)); 6439566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, num)); 644de78e4feSLisandro Dalcin } 645de78e4feSLisandro Dalcin } 6463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 647de78e4feSLisandro Dalcin } 648de78e4feSLisandro Dalcin 649de78e4feSLisandro Dalcin /* 650de78e4feSLisandro Dalcin $Nodes 651de78e4feSLisandro Dalcin numEntityBlocks(unsigned long) numNodes(unsigned long) 652de78e4feSLisandro Dalcin tagEntity(int) dimEntity(int) typeNode(int) numNodes(unsigned long) 653de78e4feSLisandro Dalcin tag(int) x(double) y(double) z(double) 654de78e4feSLisandro Dalcin ... 655de78e4feSLisandro Dalcin ... 656de78e4feSLisandro Dalcin $EndNodes 657de78e4feSLisandro Dalcin */ 658d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v40(GmshFile *gmsh, GmshMesh *mesh) 659d71ae5a4SJacob Faibussowitsch { 660698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 661698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 6627d5b9244SMatthew G. Knepley long block, node, n, t, numEntityBlocks, numTotalNodes, numNodes; 663de78e4feSLisandro Dalcin int info[3], nid; 6640598e1a2SLisandro Dalcin GmshNodes *nodes; 665de78e4feSLisandro Dalcin 666de78e4feSLisandro Dalcin PetscFunctionBegin; 6679566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG)); 6689566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1)); 6699566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numTotalNodes, 1, NULL, PETSC_LONG)); 6709566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numTotalNodes, PETSC_LONG, 1)); 6719566063dSJacob Faibussowitsch PetscCall(GmshNodesCreate(numTotalNodes, &nodes)); 6720598e1a2SLisandro Dalcin mesh->numNodes = numTotalNodes; 6730598e1a2SLisandro Dalcin mesh->nodelist = nodes; 6740598e1a2SLisandro Dalcin for (n = 0, block = 0; block < numEntityBlocks; ++block) { 6759566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM)); 6769566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numNodes, 1, NULL, PETSC_LONG)); 6779566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numNodes, PETSC_LONG, 1)); 678698a79b9SLisandro Dalcin if (gmsh->binary) { 679277f51e8SBarry Smith size_t nbytes = sizeof(int) + 3 * sizeof(double); 680da81f932SPierre Jolivet char *cbuf = NULL; /* dummy value to prevent warning from compiler about possible uninitialized value */ 6819566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numNodes, nbytes, &cbuf)); 6829566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, cbuf, numNodes * nbytes, NULL, PETSC_CHAR)); 6830598e1a2SLisandro Dalcin for (node = 0; node < numNodes; ++node, ++n) { 684de78e4feSLisandro Dalcin char *cnid = cbuf + node * nbytes, *cxyz = cnid + sizeof(int); 6850598e1a2SLisandro Dalcin double *xyz = nodes->xyz + n * 3; 6869566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(cnid, PETSC_ENUM, 1)); 6879566063dSJacob Faibussowitsch if (!PetscBinaryBigEndian()) PetscCall(PetscByteSwap(cxyz, PETSC_DOUBLE, 3)); 6889566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&nid, cnid, sizeof(int))); 6899566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(xyz, cxyz, 3 * sizeof(double))); 6909566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1)); 6919566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3)); 6920598e1a2SLisandro Dalcin nodes->id[n] = nid; 6937d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1; 694de78e4feSLisandro Dalcin } 695de78e4feSLisandro Dalcin } else { 6960598e1a2SLisandro Dalcin for (node = 0; node < numNodes; ++node, ++n) { 6970598e1a2SLisandro Dalcin double *xyz = nodes->xyz + n * 3; 6989566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nid, 1, NULL, PETSC_ENUM)); 6999566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, xyz, 3, NULL, PETSC_DOUBLE)); 7009566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nid, PETSC_ENUM, 1)); 7019566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(xyz, PETSC_DOUBLE, 3)); 7020598e1a2SLisandro Dalcin nodes->id[n] = nid; 7037d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) nodes->tag[n * GMSH_MAX_TAGS + t] = -1; 704de78e4feSLisandro Dalcin } 705de78e4feSLisandro Dalcin } 706de78e4feSLisandro Dalcin } 7073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 708de78e4feSLisandro Dalcin } 709de78e4feSLisandro Dalcin 710de78e4feSLisandro Dalcin /* 711de78e4feSLisandro Dalcin $Elements 712de78e4feSLisandro Dalcin numEntityBlocks(unsigned long) numElements(unsigned long) 713de78e4feSLisandro Dalcin tagEntity(int) dimEntity(int) typeEle(int) numElements(unsigned long) 714de78e4feSLisandro Dalcin tag(int) numVert[...](int) 715de78e4feSLisandro Dalcin ... 716de78e4feSLisandro Dalcin ... 717de78e4feSLisandro Dalcin $EndElements 718de78e4feSLisandro Dalcin */ 719d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements_v40(GmshFile *gmsh, GmshMesh *mesh) 720d71ae5a4SJacob Faibussowitsch { 721698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 722698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 723de78e4feSLisandro Dalcin long c, block, numEntityBlocks, numTotalElements, elem, numElements; 724de78e4feSLisandro Dalcin int p, info[3], *ibuf = NULL; 7250598e1a2SLisandro Dalcin int eid, dim, cellType, numVerts, numNodes, numTags; 726a5ba3d71SLisandro Dalcin GmshEntity *entity = NULL; 727de78e4feSLisandro Dalcin GmshElement *elements; 7280598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 729de78e4feSLisandro Dalcin 730de78e4feSLisandro Dalcin PetscFunctionBegin; 7319566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numEntityBlocks, 1, NULL, PETSC_LONG)); 7329566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numEntityBlocks, PETSC_LONG, 1)); 7339566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numTotalElements, 1, NULL, PETSC_LONG)); 7349566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numTotalElements, PETSC_LONG, 1)); 7359566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(numTotalElements, &elements)); 7360598e1a2SLisandro Dalcin mesh->numElems = numTotalElements; 7370598e1a2SLisandro Dalcin mesh->elements = elements; 738de78e4feSLisandro Dalcin for (c = 0, block = 0; block < numEntityBlocks; ++block) { 7399566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, info, 3, NULL, PETSC_ENUM)); 7409566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(info, PETSC_ENUM, 3)); 7419371c9d4SSatish Balay eid = info[0]; 7429371c9d4SSatish Balay dim = info[1]; 7439371c9d4SSatish Balay cellType = info[2]; 7449566063dSJacob Faibussowitsch PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity)); 7459566063dSJacob Faibussowitsch PetscCall(GmshCellTypeCheck(cellType)); 7460598e1a2SLisandro Dalcin numVerts = GmshCellMap[cellType].numVerts; 7470598e1a2SLisandro Dalcin numNodes = GmshCellMap[cellType].numNodes; 748730356f6SLisandro Dalcin numTags = entity->numTags; 7499566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numElements, 1, NULL, PETSC_LONG)); 7509566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numElements, PETSC_LONG, 1)); 7519566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, (1 + numNodes) * numElements, sizeof(int), &ibuf)); 7529566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, (1 + numNodes) * numElements, NULL, PETSC_ENUM)); 7539566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, (1 + numNodes) * numElements)); 754de78e4feSLisandro Dalcin for (elem = 0; elem < numElements; ++elem, ++c) { 755de78e4feSLisandro Dalcin GmshElement *element = elements + c; 7560598e1a2SLisandro Dalcin const int *id = ibuf + elem * (1 + numNodes), *nodes = id + 1; 7570598e1a2SLisandro Dalcin element->id = id[0]; 758de78e4feSLisandro Dalcin element->dim = dim; 759de78e4feSLisandro Dalcin element->cellType = cellType; 7600598e1a2SLisandro Dalcin element->numVerts = numVerts; 761de78e4feSLisandro Dalcin element->numNodes = numNodes; 762de78e4feSLisandro Dalcin element->numTags = numTags; 7639566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes)); 7640598e1a2SLisandro Dalcin for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 7650598e1a2SLisandro Dalcin for (p = 0; p < element->numTags; p++) element->tags[p] = entity->tags[p]; 766de78e4feSLisandro Dalcin } 767de78e4feSLisandro Dalcin } 7683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 769698a79b9SLisandro Dalcin } 770698a79b9SLisandro Dalcin 771d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic_v40(GmshFile *gmsh, PetscInt periodicMap[]) 772d71ae5a4SJacob Faibussowitsch { 773698a79b9SLisandro Dalcin PetscViewer viewer = gmsh->viewer; 774698a79b9SLisandro Dalcin int fileFormat = gmsh->fileFormat; 775698a79b9SLisandro Dalcin PetscBool binary = gmsh->binary; 776698a79b9SLisandro Dalcin PetscBool byteSwap = gmsh->byteSwap; 777698a79b9SLisandro Dalcin int numPeriodic, snum, i; 778698a79b9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 7790598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 780698a79b9SLisandro Dalcin 781698a79b9SLisandro Dalcin PetscFunctionBegin; 782698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 7839566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 784698a79b9SLisandro Dalcin snum = sscanf(line, "%d", &numPeriodic); 78508401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 786698a79b9SLisandro Dalcin } else { 7879566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &numPeriodic, 1, NULL, PETSC_ENUM)); 7889566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&numPeriodic, PETSC_ENUM, 1)); 789698a79b9SLisandro Dalcin } 790698a79b9SLisandro Dalcin for (i = 0; i < numPeriodic; i++) { 7919dddd249SSatish Balay int ibuf[3], correspondingDim = -1, correspondingTag = -1, primaryTag = -1, correspondingNode, primaryNode; 792698a79b9SLisandro Dalcin long j, nNodes; 793698a79b9SLisandro Dalcin double affine[16]; 794698a79b9SLisandro Dalcin 795698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 7969566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 3, NULL, PETSC_STRING)); 7979dddd249SSatish Balay snum = sscanf(line, "%d %d %d", &correspondingDim, &correspondingTag, &primaryTag); 79808401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 799698a79b9SLisandro Dalcin } else { 8009566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, 3, NULL, PETSC_ENUM)); 8019566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 3)); 8029371c9d4SSatish Balay correspondingDim = ibuf[0]; 8039371c9d4SSatish Balay correspondingTag = ibuf[1]; 8049371c9d4SSatish Balay primaryTag = ibuf[2]; 805698a79b9SLisandro Dalcin } 8069371c9d4SSatish Balay (void)correspondingDim; 8079371c9d4SSatish Balay (void)correspondingTag; 8089371c9d4SSatish Balay (void)primaryTag; /* unused */ 809698a79b9SLisandro Dalcin 810698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 8119566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 812698a79b9SLisandro Dalcin snum = sscanf(line, "%ld", &nNodes); 8134c500f23SPierre Jolivet if (snum != 1) { /* discard transformation and try again */ 8149566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, -PETSC_MAX_PATH_LEN, NULL, PETSC_STRING)); 8159566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 1, NULL, PETSC_STRING)); 816698a79b9SLisandro Dalcin snum = sscanf(line, "%ld", &nNodes); 81708401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 818698a79b9SLisandro Dalcin } 819698a79b9SLisandro Dalcin } else { 8209566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG)); 8219566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nNodes, PETSC_LONG, 1)); 8224c500f23SPierre Jolivet if (nNodes == -1) { /* discard transformation and try again */ 8239566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, affine, 16, NULL, PETSC_DOUBLE)); 8249566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, &nNodes, 1, NULL, PETSC_LONG)); 8259566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(&nNodes, PETSC_LONG, 1)); 826698a79b9SLisandro Dalcin } 827698a79b9SLisandro Dalcin } 828698a79b9SLisandro Dalcin 829698a79b9SLisandro Dalcin for (j = 0; j < nNodes; j++) { 830698a79b9SLisandro Dalcin if (fileFormat == 22 || !binary) { 8319566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 2, NULL, PETSC_STRING)); 8329dddd249SSatish Balay snum = sscanf(line, "%d %d", &correspondingNode, &primaryNode); 83308401ef6SPierre Jolivet PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 834698a79b9SLisandro Dalcin } else { 8359566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, ibuf, 2, NULL, PETSC_ENUM)); 8369566063dSJacob Faibussowitsch if (byteSwap) PetscCall(PetscByteSwap(ibuf, PETSC_ENUM, 2)); 8379371c9d4SSatish Balay correspondingNode = ibuf[0]; 8389371c9d4SSatish Balay primaryNode = ibuf[1]; 839698a79b9SLisandro Dalcin } 8409dddd249SSatish Balay correspondingNode = (int)nodeMap[correspondingNode]; 8419dddd249SSatish Balay primaryNode = (int)nodeMap[primaryNode]; 8429dddd249SSatish Balay periodicMap[correspondingNode] = primaryNode; 843698a79b9SLisandro Dalcin } 844698a79b9SLisandro Dalcin } 8453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 846698a79b9SLisandro Dalcin } 847698a79b9SLisandro Dalcin 8480598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 849698a79b9SLisandro Dalcin $Entities 850698a79b9SLisandro Dalcin numPoints(size_t) numCurves(size_t) 851698a79b9SLisandro Dalcin numSurfaces(size_t) numVolumes(size_t) 852698a79b9SLisandro Dalcin pointTag(int) X(double) Y(double) Z(double) 853698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 854698a79b9SLisandro Dalcin ... 855698a79b9SLisandro Dalcin curveTag(int) minX(double) minY(double) minZ(double) 856698a79b9SLisandro Dalcin maxX(double) maxY(double) maxZ(double) 857698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 858698a79b9SLisandro Dalcin numBoundingPoints(size_t) pointTag(int) ... 859698a79b9SLisandro Dalcin ... 860698a79b9SLisandro Dalcin surfaceTag(int) minX(double) minY(double) minZ(double) 861698a79b9SLisandro Dalcin maxX(double) maxY(double) maxZ(double) 862698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 863698a79b9SLisandro Dalcin numBoundingCurves(size_t) curveTag(int) ... 864698a79b9SLisandro Dalcin ... 865698a79b9SLisandro Dalcin volumeTag(int) minX(double) minY(double) minZ(double) 866698a79b9SLisandro Dalcin maxX(double) maxY(double) maxZ(double) 867698a79b9SLisandro Dalcin numPhysicalTags(size_t) physicalTag(int) ... 868698a79b9SLisandro Dalcin numBoundngSurfaces(size_t) surfaceTag(int) ... 869698a79b9SLisandro Dalcin ... 870698a79b9SLisandro Dalcin $EndEntities 871698a79b9SLisandro Dalcin */ 872d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities_v41(GmshFile *gmsh, GmshMesh *mesh) 873d71ae5a4SJacob Faibussowitsch { 874698a79b9SLisandro Dalcin PetscInt count[4], index, numTags, i; 875698a79b9SLisandro Dalcin int dim, eid, *tags = NULL; 876698a79b9SLisandro Dalcin GmshEntity *entity = NULL; 877698a79b9SLisandro Dalcin 878698a79b9SLisandro Dalcin PetscFunctionBegin; 8799566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, count, 4)); 8809566063dSJacob Faibussowitsch PetscCall(GmshEntitiesCreate(count, &mesh->entities)); 881698a79b9SLisandro Dalcin for (dim = 0; dim < 4; ++dim) { 882698a79b9SLisandro Dalcin for (index = 0; index < count[dim]; ++index) { 8839566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, &eid, 1)); 8849566063dSJacob Faibussowitsch PetscCall(GmshEntitiesAdd(mesh->entities, (PetscInt)index, dim, eid, &entity)); 8859566063dSJacob Faibussowitsch PetscCall(GmshReadDouble(gmsh, entity->bbox, (dim == 0) ? 3 : 6)); 8869566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numTags, 1)); 8879566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numTags, sizeof(int), &tags)); 8889566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, tags, numTags)); 8899c0edc59SMatthew 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); 8907d5b9244SMatthew G. Knepley entity->numTags = numTags; 891698a79b9SLisandro Dalcin for (i = 0; i < entity->numTags; ++i) entity->tags[i] = tags[i]; 892698a79b9SLisandro Dalcin if (dim == 0) continue; 8939566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numTags, 1)); 8949566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numTags, sizeof(int), &tags)); 8959566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, tags, numTags)); 89681a1af93SMatthew G. Knepley /* Currently, we do not save the ids for the bounding entities */ 897698a79b9SLisandro Dalcin } 898698a79b9SLisandro Dalcin } 8993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 900698a79b9SLisandro Dalcin } 901698a79b9SLisandro Dalcin 90233a088b6SMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 903698a79b9SLisandro Dalcin $Nodes 904698a79b9SLisandro Dalcin numEntityBlocks(size_t) numNodes(size_t) 905698a79b9SLisandro Dalcin minNodeTag(size_t) maxNodeTag(size_t) 906698a79b9SLisandro Dalcin entityDim(int) entityTag(int) parametric(int; 0 or 1) numNodesBlock(size_t) 907698a79b9SLisandro Dalcin nodeTag(size_t) 908698a79b9SLisandro Dalcin ... 909698a79b9SLisandro Dalcin x(double) y(double) z(double) 910698a79b9SLisandro Dalcin < u(double; if parametric and entityDim = 1 or entityDim = 2) > 911698a79b9SLisandro Dalcin < v(double; if parametric and entityDim = 2) > 912698a79b9SLisandro Dalcin ... 913698a79b9SLisandro Dalcin ... 914698a79b9SLisandro Dalcin $EndNodes 915698a79b9SLisandro Dalcin */ 916d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes_v41(GmshFile *gmsh, GmshMesh *mesh) 917d71ae5a4SJacob Faibussowitsch { 91881a1af93SMatthew G. Knepley int info[3], dim, eid, parametric; 9197d5b9244SMatthew G. Knepley PetscInt sizes[4], numEntityBlocks, numTags, t, numNodes, numNodesBlock = 0, block, node, n; 92081a1af93SMatthew G. Knepley GmshEntity *entity = NULL; 9210598e1a2SLisandro Dalcin GmshNodes *nodes; 922698a79b9SLisandro Dalcin 923698a79b9SLisandro Dalcin PetscFunctionBegin; 9249566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, sizes, 4)); 9259371c9d4SSatish Balay numEntityBlocks = sizes[0]; 9269371c9d4SSatish Balay numNodes = sizes[1]; 9279566063dSJacob Faibussowitsch PetscCall(GmshNodesCreate(numNodes, &nodes)); 9280598e1a2SLisandro Dalcin mesh->numNodes = numNodes; 9290598e1a2SLisandro Dalcin mesh->nodelist = nodes; 930*e43c9757SMatthew G. Knepley if (numEntityBlocks && !mesh->entities) PetscCall(PetscInfo(NULL, "File specifies %" PetscInt_FMT " entity blocks, but was missing the $Entities section\n", numEntityBlocks)); 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]; 936*e43c9757SMatthew G. Knepley if (mesh->entities) PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity)); 937*e43c9757SMatthew G. Knepley numTags = entity ? entity->numTags : 0; 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; 979*e43c9757SMatthew G. Knepley if (numEntityBlocks && !mesh->entities) PetscCall(PetscInfo(NULL, "File specifies %" PetscInt_FMT " entity blocks, but was missing the $Entities section\n", numEntityBlocks)); 980698a79b9SLisandro Dalcin for (c = 0, block = 0; block < numEntityBlocks; ++block) { 9819566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, info, 3)); 9829371c9d4SSatish Balay dim = info[0]; 9839371c9d4SSatish Balay eid = info[1]; 9849371c9d4SSatish Balay cellType = info[2]; 985*e43c9757SMatthew G. Knepley if (mesh->entities) PetscCall(GmshEntitiesGet(mesh->entities, dim, eid, &entity)); 9869566063dSJacob Faibussowitsch PetscCall(GmshCellTypeCheck(cellType)); 9870598e1a2SLisandro Dalcin numVerts = GmshCellMap[cellType].numVerts; 9880598e1a2SLisandro Dalcin numNodes = GmshCellMap[cellType].numNodes; 989*e43c9757SMatthew G. Knepley numTags = entity ? entity->numTags : 0; 9909566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numBlockElements, 1)); 9919566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, (1 + numNodes) * numBlockElements, sizeof(PetscInt), &ibuf)); 9929566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, ibuf, (1 + numNodes) * numBlockElements)); 993698a79b9SLisandro Dalcin for (elem = 0; elem < numBlockElements; ++elem, ++c) { 994698a79b9SLisandro Dalcin GmshElement *element = elements + c; 9950598e1a2SLisandro Dalcin const PetscInt *id = ibuf + elem * (1 + numNodes), *nodes = id + 1; 996698a79b9SLisandro Dalcin element->id = id[0]; 997698a79b9SLisandro Dalcin element->dim = dim; 998698a79b9SLisandro Dalcin element->cellType = cellType; 9990598e1a2SLisandro Dalcin element->numVerts = numVerts; 1000698a79b9SLisandro Dalcin element->numNodes = numNodes; 1001698a79b9SLisandro Dalcin element->numTags = numTags; 10029566063dSJacob Faibussowitsch PetscCall(PetscSegBufferGet(mesh->segbuf, (size_t)element->numNodes, &element->nodes)); 10030598e1a2SLisandro Dalcin for (p = 0; p < element->numNodes; p++) element->nodes[p] = nodeMap[nodes[p]]; 10040598e1a2SLisandro Dalcin for (p = 0; p < element->numTags; p++) element->tags[p] = entity->tags[p]; 1005698a79b9SLisandro Dalcin } 1006698a79b9SLisandro Dalcin } 10073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1008698a79b9SLisandro Dalcin } 1009698a79b9SLisandro Dalcin 10100598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 1011698a79b9SLisandro Dalcin $Periodic 1012698a79b9SLisandro Dalcin numPeriodicLinks(size_t) 10139dddd249SSatish Balay entityDim(int) entityTag(int) entityTagPrimary(int) 1014698a79b9SLisandro Dalcin numAffine(size_t) value(double) ... 1015698a79b9SLisandro Dalcin numCorrespondingNodes(size_t) 10169dddd249SSatish Balay nodeTag(size_t) nodeTagPrimary(size_t) 1017698a79b9SLisandro Dalcin ... 1018698a79b9SLisandro Dalcin ... 1019698a79b9SLisandro Dalcin $EndPeriodic 1020698a79b9SLisandro Dalcin */ 1021d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic_v41(GmshFile *gmsh, PetscInt periodicMap[]) 1022d71ae5a4SJacob Faibussowitsch { 1023698a79b9SLisandro Dalcin int info[3]; 1024698a79b9SLisandro Dalcin double dbuf[16]; 10250598e1a2SLisandro Dalcin PetscInt numPeriodicLinks, numAffine, numCorrespondingNodes, *nodeTags = NULL, link, node; 10260598e1a2SLisandro Dalcin PetscInt *nodeMap = gmsh->nodeMap; 1027698a79b9SLisandro Dalcin 1028698a79b9SLisandro Dalcin PetscFunctionBegin; 10299566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numPeriodicLinks, 1)); 1030698a79b9SLisandro Dalcin for (link = 0; link < numPeriodicLinks; ++link) { 10319566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, info, 3)); 10329566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numAffine, 1)); 10339566063dSJacob Faibussowitsch PetscCall(GmshReadDouble(gmsh, dbuf, numAffine)); 10349566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, &numCorrespondingNodes, 1)); 10359566063dSJacob Faibussowitsch PetscCall(GmshBufferGet(gmsh, numCorrespondingNodes, sizeof(PetscInt), &nodeTags)); 10369566063dSJacob Faibussowitsch PetscCall(GmshReadSize(gmsh, nodeTags, numCorrespondingNodes * 2)); 1037698a79b9SLisandro Dalcin for (node = 0; node < numCorrespondingNodes; ++node) { 10389dddd249SSatish Balay PetscInt correspondingNode = nodeMap[nodeTags[node * 2 + 0]]; 10399dddd249SSatish Balay PetscInt primaryNode = nodeMap[nodeTags[node * 2 + 1]]; 10409dddd249SSatish Balay periodicMap[correspondingNode] = primaryNode; 1041698a79b9SLisandro Dalcin } 1042698a79b9SLisandro Dalcin } 10433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1044698a79b9SLisandro Dalcin } 1045698a79b9SLisandro Dalcin 10460598e1a2SLisandro Dalcin /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 1047d6689ca9SLisandro Dalcin $MeshFormat // same as MSH version 2 1048d6689ca9SLisandro Dalcin version(ASCII double; currently 4.1) 1049d6689ca9SLisandro Dalcin file-type(ASCII int; 0 for ASCII mode, 1 for binary mode) 1050d6689ca9SLisandro Dalcin data-size(ASCII int; sizeof(size_t)) 1051d6689ca9SLisandro Dalcin < int with value one; only in binary mode, to detect endianness > 1052d6689ca9SLisandro Dalcin $EndMeshFormat 1053d6689ca9SLisandro Dalcin */ 1054d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadMeshFormat(GmshFile *gmsh) 1055d71ae5a4SJacob Faibussowitsch { 1056698a79b9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 1057698a79b9SLisandro Dalcin int snum, fileType, fileFormat, dataSize, checkEndian; 1058698a79b9SLisandro Dalcin float version; 1059698a79b9SLisandro Dalcin 1060698a79b9SLisandro Dalcin PetscFunctionBegin; 10619566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 3)); 1062698a79b9SLisandro Dalcin snum = sscanf(line, "%f %d %d", &version, &fileType, &dataSize); 1063a8d4e440SJunchao Zhang fileFormat = (int)roundf(version * 10); 106408401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line); 1065a8d4e440SJunchao Zhang PetscCheck(fileFormat >= 22, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version); 10661dca8a05SBarry Smith PetscCheck((int)version != 3, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version); 1067a8d4e440SJunchao Zhang PetscCheck(fileFormat <= 41, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version); 106808401ef6SPierre Jolivet PetscCheck(!gmsh->binary || fileType, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is binary but Gmsh file is ASCII"); 106908401ef6SPierre Jolivet PetscCheck(gmsh->binary || !fileType, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Viewer is ASCII but Gmsh file is binary"); 10701dca8a05SBarry 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); 10711dca8a05SBarry 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); 1072698a79b9SLisandro Dalcin gmsh->fileFormat = fileFormat; 1073698a79b9SLisandro Dalcin gmsh->dataSize = dataSize; 1074698a79b9SLisandro Dalcin gmsh->byteSwap = PETSC_FALSE; 1075698a79b9SLisandro Dalcin if (gmsh->binary) { 10769566063dSJacob Faibussowitsch PetscCall(GmshReadInt(gmsh, &checkEndian, 1)); 1077698a79b9SLisandro Dalcin if (checkEndian != 1) { 10789566063dSJacob Faibussowitsch PetscCall(PetscByteSwap(&checkEndian, PETSC_ENUM, 1)); 107908401ef6SPierre Jolivet PetscCheck(checkEndian == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to detect endianness in Gmsh file header: %s", line); 1080698a79b9SLisandro Dalcin gmsh->byteSwap = PETSC_TRUE; 1081698a79b9SLisandro Dalcin } 1082698a79b9SLisandro Dalcin } 10833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1084698a79b9SLisandro Dalcin } 1085698a79b9SLisandro Dalcin 10868749820aSMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 10878749820aSMatthew G. Knepley Neper: https://neper.info/ adds this section 10888749820aSMatthew G. Knepley 10898749820aSMatthew G. Knepley $MeshVersion 10908749820aSMatthew G. Knepley <major>.<minor>,<patch> 10918749820aSMatthew G. Knepley $EndMeshVersion 10928749820aSMatthew G. Knepley */ 10938749820aSMatthew G. Knepley static PetscErrorCode GmshReadMeshVersion(GmshFile *gmsh) 10948749820aSMatthew G. Knepley { 10958749820aSMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 10968749820aSMatthew G. Knepley int snum, major, minor, patch; 10978749820aSMatthew G. Knepley 10988749820aSMatthew G. Knepley PetscFunctionBegin; 10998749820aSMatthew G. Knepley PetscCall(GmshReadString(gmsh, line, 1)); 11008749820aSMatthew G. Knepley snum = sscanf(line, "%d.%d.%d", &major, &minor, &patch); 11018749820aSMatthew G. Knepley PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line); 11028749820aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 11038749820aSMatthew G. Knepley } 11048749820aSMatthew G. Knepley 11058749820aSMatthew G. Knepley /* http://gmsh.info/dev/doc/texinfo/gmsh.html#MSH-file-format 11068749820aSMatthew G. Knepley Neper: https://neper.info/ adds this section 11078749820aSMatthew G. Knepley 11088749820aSMatthew G. Knepley $Domain 11098749820aSMatthew G. Knepley <shape> 11108749820aSMatthew G. Knepley $EndDomain 11118749820aSMatthew G. Knepley */ 11128749820aSMatthew G. Knepley static PetscErrorCode GmshReadMeshDomain(GmshFile *gmsh) 11138749820aSMatthew G. Knepley { 11148749820aSMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 11158749820aSMatthew G. Knepley 11168749820aSMatthew G. Knepley PetscFunctionBegin; 11178749820aSMatthew G. Knepley PetscCall(GmshReadString(gmsh, line, 1)); 11188749820aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 11198749820aSMatthew G. Knepley } 11208749820aSMatthew G. Knepley 11211f643af3SLisandro Dalcin /* 11221f643af3SLisandro Dalcin PhysicalNames 11231f643af3SLisandro Dalcin numPhysicalNames(ASCII int) 11241f643af3SLisandro Dalcin dimension(ASCII int) physicalTag(ASCII int) "name"(127 characters max) 11251f643af3SLisandro Dalcin ... 11261f643af3SLisandro Dalcin $EndPhysicalNames 11271f643af3SLisandro Dalcin */ 1128d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPhysicalNames(GmshFile *gmsh, GmshMesh *mesh) 1129d71ae5a4SJacob Faibussowitsch { 1130bbcf679cSJacob Faibussowitsch char line[PETSC_MAX_PATH_LEN], name[128 + 2], *p = NULL, *q = NULL, *r = NULL; 1131a45dabc8SMatthew G. Knepley int snum, region, dim, tag; 1132698a79b9SLisandro Dalcin 1133698a79b9SLisandro Dalcin PetscFunctionBegin; 11349566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 1)); 1135a45dabc8SMatthew G. Knepley snum = sscanf(line, "%d", ®ion); 1136a45dabc8SMatthew G. Knepley mesh->numRegions = region; 113708401ef6SPierre Jolivet PetscCheck(snum == 1, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 113890d778b8SLisandro Dalcin PetscCall(PetscMalloc3(mesh->numRegions, &mesh->regionDims, mesh->numRegions, &mesh->regionTags, mesh->numRegions, &mesh->regionNames)); 1139a45dabc8SMatthew G. Knepley for (region = 0; region < mesh->numRegions; ++region) { 11409566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 2)); 11411f643af3SLisandro Dalcin snum = sscanf(line, "%d %d", &dim, &tag); 114208401ef6SPierre Jolivet PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 11439566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, -(PetscInt)sizeof(line))); 11449566063dSJacob Faibussowitsch PetscCall(PetscStrchr(line, '"', &p)); 114528b400f6SJacob Faibussowitsch PetscCheck(p, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 11469566063dSJacob Faibussowitsch PetscCall(PetscStrrchr(line, '"', &q)); 114708401ef6SPierre Jolivet PetscCheck(q != p, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "File is not a valid Gmsh file"); 11485f5cd6d5SMatthew G. Knepley PetscCall(PetscStrrchr(line, ':', &r)); 11495f5cd6d5SMatthew G. Knepley if (p != r) q = r; 11509566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(name, p + 1, (size_t)(q - p - 1))); 115190d778b8SLisandro Dalcin mesh->regionDims[region] = dim; 1152a45dabc8SMatthew G. Knepley mesh->regionTags[region] = tag; 11539566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(name, &mesh->regionNames[region])); 1154698a79b9SLisandro Dalcin } 11553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1156de78e4feSLisandro Dalcin } 1157de78e4feSLisandro Dalcin 1158d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadEntities(GmshFile *gmsh, GmshMesh *mesh) 1159d71ae5a4SJacob Faibussowitsch { 11600598e1a2SLisandro Dalcin PetscFunctionBegin; 11610598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1162d71ae5a4SJacob Faibussowitsch case 41: 1163d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadEntities_v41(gmsh, mesh)); 1164d71ae5a4SJacob Faibussowitsch break; 1165d71ae5a4SJacob Faibussowitsch default: 1166d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadEntities_v40(gmsh, mesh)); 1167d71ae5a4SJacob Faibussowitsch break; 116896ca5757SLisandro Dalcin } 11693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11700598e1a2SLisandro Dalcin } 11710598e1a2SLisandro Dalcin 1172d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadNodes(GmshFile *gmsh, GmshMesh *mesh) 1173d71ae5a4SJacob Faibussowitsch { 11740598e1a2SLisandro Dalcin PetscFunctionBegin; 11750598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1176d71ae5a4SJacob Faibussowitsch case 41: 1177d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadNodes_v41(gmsh, mesh)); 1178d71ae5a4SJacob Faibussowitsch break; 1179d71ae5a4SJacob Faibussowitsch case 40: 1180d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadNodes_v40(gmsh, mesh)); 1181d71ae5a4SJacob Faibussowitsch break; 1182d71ae5a4SJacob Faibussowitsch default: 1183d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadNodes_v22(gmsh, mesh)); 1184d71ae5a4SJacob Faibussowitsch break; 11850598e1a2SLisandro Dalcin } 11860598e1a2SLisandro Dalcin 11870598e1a2SLisandro Dalcin { /* Gmsh v2.2/v4.0 does not provide min/max node tags */ 11880598e1a2SLisandro Dalcin if (mesh->numNodes > 0 && gmsh->nodeEnd >= gmsh->nodeStart) { 11890598e1a2SLisandro Dalcin PetscInt tagMin = PETSC_MAX_INT, tagMax = PETSC_MIN_INT, n; 11900598e1a2SLisandro Dalcin GmshNodes *nodes = mesh->nodelist; 11910598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) { 11920598e1a2SLisandro Dalcin const PetscInt tag = nodes->id[n]; 11930598e1a2SLisandro Dalcin tagMin = PetscMin(tag, tagMin); 11940598e1a2SLisandro Dalcin tagMax = PetscMax(tag, tagMax); 11950598e1a2SLisandro Dalcin } 11960598e1a2SLisandro Dalcin gmsh->nodeStart = tagMin; 11970598e1a2SLisandro Dalcin gmsh->nodeEnd = tagMax + 1; 11980598e1a2SLisandro Dalcin } 11990598e1a2SLisandro Dalcin } 12000598e1a2SLisandro Dalcin 12010598e1a2SLisandro Dalcin { /* Support for sparse node tags */ 12020598e1a2SLisandro Dalcin PetscInt n, t; 12030598e1a2SLisandro Dalcin GmshNodes *nodes = mesh->nodelist; 12049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(gmsh->nodeEnd - gmsh->nodeStart, &gmsh->nbuf)); 12050598e1a2SLisandro Dalcin for (t = 0; t < gmsh->nodeEnd - gmsh->nodeStart; ++t) gmsh->nbuf[t] = PETSC_MIN_INT; 12060598e1a2SLisandro Dalcin gmsh->nodeMap = gmsh->nbuf - gmsh->nodeStart; 12070598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) { 12080598e1a2SLisandro Dalcin const PetscInt tag = nodes->id[n]; 120963a3b9bcSJacob Faibussowitsch PetscCheck(gmsh->nodeMap[tag] < 0, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Repeated node tag %" PetscInt_FMT, tag); 12100598e1a2SLisandro Dalcin gmsh->nodeMap[tag] = n; 12110598e1a2SLisandro Dalcin } 12120598e1a2SLisandro Dalcin } 12133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12140598e1a2SLisandro Dalcin } 12150598e1a2SLisandro Dalcin 1216d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadElements(GmshFile *gmsh, GmshMesh *mesh) 1217d71ae5a4SJacob Faibussowitsch { 12180598e1a2SLisandro Dalcin PetscFunctionBegin; 12190598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1220d71ae5a4SJacob Faibussowitsch case 41: 1221d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadElements_v41(gmsh, mesh)); 1222d71ae5a4SJacob Faibussowitsch break; 1223d71ae5a4SJacob Faibussowitsch case 40: 1224d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadElements_v40(gmsh, mesh)); 1225d71ae5a4SJacob Faibussowitsch break; 1226d71ae5a4SJacob Faibussowitsch default: 1227d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadElements_v22(gmsh, mesh)); 1228d71ae5a4SJacob Faibussowitsch break; 12290598e1a2SLisandro Dalcin } 12300598e1a2SLisandro Dalcin 12310598e1a2SLisandro Dalcin { /* Reorder elements by codimension and polytope type */ 12320598e1a2SLisandro Dalcin PetscInt ne = mesh->numElems; 12330598e1a2SLisandro Dalcin GmshElement *elements = mesh->elements; 1234066ea43fSLisandro Dalcin PetscInt keymap[GMSH_NUM_POLYTOPES], nk = 0; 1235066ea43fSLisandro Dalcin PetscInt offset[GMSH_NUM_POLYTOPES + 1], e, k; 12360598e1a2SLisandro Dalcin 1237066ea43fSLisandro Dalcin for (k = 0; k < GMSH_NUM_POLYTOPES; ++k) keymap[k] = PETSC_MIN_INT; 12389566063dSJacob Faibussowitsch PetscCall(PetscMemzero(offset, sizeof(offset))); 12390598e1a2SLisandro Dalcin 1240066ea43fSLisandro Dalcin keymap[GMSH_TET] = nk++; 1241066ea43fSLisandro Dalcin keymap[GMSH_HEX] = nk++; 1242066ea43fSLisandro Dalcin keymap[GMSH_PRI] = nk++; 1243066ea43fSLisandro Dalcin keymap[GMSH_PYR] = nk++; 1244066ea43fSLisandro Dalcin keymap[GMSH_TRI] = nk++; 1245066ea43fSLisandro Dalcin keymap[GMSH_QUA] = nk++; 1246066ea43fSLisandro Dalcin keymap[GMSH_SEG] = nk++; 1247066ea43fSLisandro Dalcin keymap[GMSH_VTX] = nk++; 12480598e1a2SLisandro Dalcin 12499566063dSJacob Faibussowitsch PetscCall(GmshElementsCreate(mesh->numElems, &mesh->elements)); 12504ad8454bSPierre Jolivet #define key(eid) keymap[GmshCellMap[elements[eid].cellType].polytope] 12510598e1a2SLisandro Dalcin for (e = 0; e < ne; ++e) offset[1 + key(e)]++; 12520598e1a2SLisandro Dalcin for (k = 1; k < nk; ++k) offset[k] += offset[k - 1]; 12530598e1a2SLisandro Dalcin for (e = 0; e < ne; ++e) mesh->elements[offset[key(e)]++] = elements[e]; 12540598e1a2SLisandro Dalcin #undef key 12559566063dSJacob Faibussowitsch PetscCall(GmshElementsDestroy(&elements)); 1256066ea43fSLisandro Dalcin } 12570598e1a2SLisandro Dalcin 1258066ea43fSLisandro Dalcin { /* Mesh dimension and order */ 1259066ea43fSLisandro Dalcin GmshElement *elem = mesh->numElems ? mesh->elements : NULL; 1260066ea43fSLisandro Dalcin mesh->dim = elem ? GmshCellMap[elem->cellType].dim : 0; 1261066ea43fSLisandro Dalcin mesh->order = elem ? GmshCellMap[elem->cellType].order : 0; 12620598e1a2SLisandro Dalcin } 12630598e1a2SLisandro Dalcin 12640598e1a2SLisandro Dalcin { 12650598e1a2SLisandro Dalcin PetscBT vtx; 12660598e1a2SLisandro Dalcin PetscInt dim = mesh->dim, e, n, v; 12670598e1a2SLisandro Dalcin 12689566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(mesh->numNodes, &vtx)); 12690598e1a2SLisandro Dalcin 12700598e1a2SLisandro Dalcin /* Compute number of cells and set of vertices */ 12710598e1a2SLisandro Dalcin mesh->numCells = 0; 12720598e1a2SLisandro Dalcin for (e = 0; e < mesh->numElems; ++e) { 12730598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + e; 12740598e1a2SLisandro Dalcin if (elem->dim == dim && dim > 0) mesh->numCells++; 127548a46eb9SPierre Jolivet for (v = 0; v < elem->numVerts; v++) PetscCall(PetscBTSet(vtx, elem->nodes[v])); 12760598e1a2SLisandro Dalcin } 12770598e1a2SLisandro Dalcin 12780598e1a2SLisandro Dalcin /* Compute numbering for vertices */ 12790598e1a2SLisandro Dalcin mesh->numVerts = 0; 12809566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mesh->numNodes, &mesh->vertexMap)); 12819371c9d4SSatish Balay for (n = 0; n < mesh->numNodes; ++n) mesh->vertexMap[n] = PetscBTLookup(vtx, n) ? mesh->numVerts++ : PETSC_MIN_INT; 12820598e1a2SLisandro Dalcin 12839566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&vtx)); 12840598e1a2SLisandro Dalcin } 12853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12860598e1a2SLisandro Dalcin } 12870598e1a2SLisandro Dalcin 1288d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshReadPeriodic(GmshFile *gmsh, GmshMesh *mesh) 1289d71ae5a4SJacob Faibussowitsch { 12900598e1a2SLisandro Dalcin PetscInt n; 12910598e1a2SLisandro Dalcin 12920598e1a2SLisandro Dalcin PetscFunctionBegin; 12939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(mesh->numNodes, &mesh->periodMap)); 12940598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) mesh->periodMap[n] = n; 12950598e1a2SLisandro Dalcin switch (gmsh->fileFormat) { 1296d71ae5a4SJacob Faibussowitsch case 41: 1297d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadPeriodic_v41(gmsh, mesh->periodMap)); 1298d71ae5a4SJacob Faibussowitsch break; 1299d71ae5a4SJacob Faibussowitsch default: 1300d71ae5a4SJacob Faibussowitsch PetscCall(GmshReadPeriodic_v40(gmsh, mesh->periodMap)); 1301d71ae5a4SJacob Faibussowitsch break; 13020598e1a2SLisandro Dalcin } 13030598e1a2SLisandro Dalcin 13049dddd249SSatish Balay /* Find canonical primary nodes */ 13050598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) 13069371c9d4SSatish Balay while (mesh->periodMap[n] != mesh->periodMap[mesh->periodMap[n]]) mesh->periodMap[n] = mesh->periodMap[mesh->periodMap[n]]; 13070598e1a2SLisandro Dalcin 13089dddd249SSatish Balay /* Renumber vertices (filter out correspondings) */ 13090598e1a2SLisandro Dalcin mesh->numVerts = 0; 13100598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) 13110598e1a2SLisandro Dalcin if (mesh->vertexMap[n] >= 0) /* is vertex */ 13129dddd249SSatish Balay if (mesh->periodMap[n] == n) /* is primary */ 13130598e1a2SLisandro Dalcin mesh->vertexMap[n] = mesh->numVerts++; 13140598e1a2SLisandro Dalcin for (n = 0; n < mesh->numNodes; ++n) 13150598e1a2SLisandro Dalcin if (mesh->vertexMap[n] >= 0) /* is vertex */ 13169dddd249SSatish Balay if (mesh->periodMap[n] != n) /* is corresponding */ 13170598e1a2SLisandro Dalcin mesh->vertexMap[n] = mesh->vertexMap[mesh->periodMap[n]]; 13183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 13190598e1a2SLisandro Dalcin } 13200598e1a2SLisandro Dalcin 1321066ea43fSLisandro Dalcin #define DM_POLYTOPE_VERTEX DM_POLYTOPE_POINT 1322066ea43fSLisandro Dalcin static const DMPolytopeType DMPolytopeMap[] = { 1323066ea43fSLisandro Dalcin /* GMSH_VTX */ DM_POLYTOPE_VERTEX, 1324066ea43fSLisandro Dalcin /* GMSH_SEG */ DM_POLYTOPE_SEGMENT, 1325066ea43fSLisandro Dalcin /* GMSH_TRI */ DM_POLYTOPE_TRIANGLE, 1326066ea43fSLisandro Dalcin /* GMSH_QUA */ DM_POLYTOPE_QUADRILATERAL, 1327066ea43fSLisandro Dalcin /* GMSH_TET */ DM_POLYTOPE_TETRAHEDRON, 1328066ea43fSLisandro Dalcin /* GMSH_HEX */ DM_POLYTOPE_HEXAHEDRON, 1329066ea43fSLisandro Dalcin /* GMSH_PRI */ DM_POLYTOPE_TRI_PRISM, 13309371c9d4SSatish Balay /* GMSH_PYR */ DM_POLYTOPE_PYRAMID, DM_POLYTOPE_UNKNOWN}; 13310598e1a2SLisandro Dalcin 1332d71ae5a4SJacob Faibussowitsch static inline DMPolytopeType DMPolytopeTypeFromGmsh(PetscInt cellType) 1333d71ae5a4SJacob Faibussowitsch { 1334066ea43fSLisandro Dalcin return DMPolytopeMap[GmshCellMap[cellType].polytope]; 1335066ea43fSLisandro Dalcin } 1336066ea43fSLisandro Dalcin 1337d71ae5a4SJacob Faibussowitsch static PetscErrorCode GmshCreateFE(MPI_Comm comm, const char prefix[], PetscBool isSimplex, PetscBool continuity, PetscDTNodeType nodeType, PetscInt dim, PetscInt Nc, PetscInt k, PetscFE *fem) 1338d71ae5a4SJacob Faibussowitsch { 1339066ea43fSLisandro Dalcin DM K; 1340066ea43fSLisandro Dalcin PetscSpace P; 1341066ea43fSLisandro Dalcin PetscDualSpace Q; 1342066ea43fSLisandro Dalcin PetscQuadrature q, fq; 1343066ea43fSLisandro Dalcin PetscBool isTensor = isSimplex ? PETSC_FALSE : PETSC_TRUE; 1344066ea43fSLisandro Dalcin PetscBool endpoint = PETSC_TRUE; 1345066ea43fSLisandro Dalcin char name[32]; 1346066ea43fSLisandro Dalcin 1347066ea43fSLisandro Dalcin PetscFunctionBegin; 1348066ea43fSLisandro Dalcin /* Create space */ 13499566063dSJacob Faibussowitsch PetscCall(PetscSpaceCreate(comm, &P)); 13509566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetType(P, PETSCSPACEPOLYNOMIAL)); 13519566063dSJacob Faibussowitsch PetscCall(PetscSpacePolynomialSetTensor(P, isTensor)); 13529566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumComponents(P, Nc)); 13539566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetNumVariables(P, dim)); 13549566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetDegree(P, k, PETSC_DETERMINE)); 1355066ea43fSLisandro Dalcin if (prefix) { 13569566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)P, prefix)); 13579566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetFromOptions(P)); 13589566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)P, NULL)); 13599566063dSJacob Faibussowitsch PetscCall(PetscSpaceGetDegree(P, &k, NULL)); 1360066ea43fSLisandro Dalcin } 13619566063dSJacob Faibussowitsch PetscCall(PetscSpaceSetUp(P)); 1362066ea43fSLisandro Dalcin /* Create dual space */ 13639566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceCreate(comm, &Q)); 13649566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetType(Q, PETSCDUALSPACELAGRANGE)); 13659566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeSetTensor(Q, isTensor)); 13669566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeSetContinuity(Q, continuity)); 13679566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceLagrangeSetNodeType(Q, nodeType, endpoint, 0)); 13689566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetNumComponents(Q, Nc)); 13699566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetOrder(Q, k)); 13709566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, DMPolytopeTypeSimpleShape(dim, isSimplex), &K)); 13719566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetDM(Q, K)); 13729566063dSJacob Faibussowitsch PetscCall(DMDestroy(&K)); 1373066ea43fSLisandro Dalcin if (prefix) { 13749566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)Q, prefix)); 13759566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetFromOptions(Q)); 13769566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)Q, NULL)); 1377066ea43fSLisandro Dalcin } 13789566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceSetUp(Q)); 1379066ea43fSLisandro Dalcin /* Create quadrature */ 1380066ea43fSLisandro Dalcin if (isSimplex) { 13819566063dSJacob Faibussowitsch PetscCall(PetscDTStroudConicalQuadrature(dim, 1, k + 1, -1, +1, &q)); 13829566063dSJacob Faibussowitsch PetscCall(PetscDTStroudConicalQuadrature(dim - 1, 1, k + 1, -1, +1, &fq)); 1383066ea43fSLisandro Dalcin } else { 13849566063dSJacob Faibussowitsch PetscCall(PetscDTGaussTensorQuadrature(dim, 1, k + 1, -1, +1, &q)); 13859566063dSJacob Faibussowitsch PetscCall(PetscDTGaussTensorQuadrature(dim - 1, 1, k + 1, -1, +1, &fq)); 1386066ea43fSLisandro Dalcin } 1387066ea43fSLisandro Dalcin /* Create finite element */ 13889566063dSJacob Faibussowitsch PetscCall(PetscFECreate(comm, fem)); 13899566063dSJacob Faibussowitsch PetscCall(PetscFESetType(*fem, PETSCFEBASIC)); 13909566063dSJacob Faibussowitsch PetscCall(PetscFESetNumComponents(*fem, Nc)); 13919566063dSJacob Faibussowitsch PetscCall(PetscFESetBasisSpace(*fem, P)); 13929566063dSJacob Faibussowitsch PetscCall(PetscFESetDualSpace(*fem, Q)); 13939566063dSJacob Faibussowitsch PetscCall(PetscFESetQuadrature(*fem, q)); 13949566063dSJacob Faibussowitsch PetscCall(PetscFESetFaceQuadrature(*fem, fq)); 1395066ea43fSLisandro Dalcin if (prefix) { 13969566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*fem, prefix)); 13979566063dSJacob Faibussowitsch PetscCall(PetscFESetFromOptions(*fem)); 13989566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*fem, NULL)); 1399066ea43fSLisandro Dalcin } 14009566063dSJacob Faibussowitsch PetscCall(PetscFESetUp(*fem)); 1401066ea43fSLisandro Dalcin /* Cleanup */ 14029566063dSJacob Faibussowitsch PetscCall(PetscSpaceDestroy(&P)); 14039566063dSJacob Faibussowitsch PetscCall(PetscDualSpaceDestroy(&Q)); 14049566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&q)); 14059566063dSJacob Faibussowitsch PetscCall(PetscQuadratureDestroy(&fq)); 1406066ea43fSLisandro Dalcin /* Set finite element name */ 140763a3b9bcSJacob Faibussowitsch PetscCall(PetscSNPrintf(name, sizeof(name), "%s%" PetscInt_FMT, isSimplex ? "P" : "Q", k)); 14089566063dSJacob Faibussowitsch PetscCall(PetscFESetName(*fem, name)); 14093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 141096ca5757SLisandro Dalcin } 141196ca5757SLisandro Dalcin 1412cc4c1da9SBarry Smith /*@ 1413a1cb98faSBarry Smith DMPlexCreateGmshFromFile - Create a `DMPLEX` mesh from a Gmsh file 1414d6689ca9SLisandro Dalcin 1415a4e35b19SJacob Faibussowitsch Input Parameters: 1416d6689ca9SLisandro Dalcin + comm - The MPI communicator 1417d6689ca9SLisandro Dalcin . filename - Name of the Gmsh file 1418d6689ca9SLisandro Dalcin - interpolate - Create faces and edges in the mesh 1419d6689ca9SLisandro Dalcin 1420d6689ca9SLisandro Dalcin Output Parameter: 1421a1cb98faSBarry Smith . dm - The `DM` object representing the mesh 1422d6689ca9SLisandro Dalcin 1423d6689ca9SLisandro Dalcin Level: beginner 1424d6689ca9SLisandro Dalcin 14251cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 1426d6689ca9SLisandro Dalcin @*/ 1427d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateGmshFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 1428d71ae5a4SJacob Faibussowitsch { 1429d6689ca9SLisandro Dalcin PetscViewer viewer; 1430d6689ca9SLisandro Dalcin PetscMPIInt rank; 1431d6689ca9SLisandro Dalcin int fileType; 1432d6689ca9SLisandro Dalcin PetscViewerType vtype; 1433d6689ca9SLisandro Dalcin 1434d6689ca9SLisandro Dalcin PetscFunctionBegin; 14359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1436d6689ca9SLisandro Dalcin 1437d6689ca9SLisandro Dalcin /* Determine Gmsh file type (ASCII or binary) from file header */ 1438dd400576SPatrick Sanan if (rank == 0) { 14390598e1a2SLisandro Dalcin GmshFile gmsh[1]; 1440d6689ca9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 1441d6689ca9SLisandro Dalcin int snum; 1442d6689ca9SLisandro Dalcin float version; 1443a8d4e440SJunchao Zhang int fileFormat; 1444d6689ca9SLisandro Dalcin 14459566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(gmsh, 1)); 14469566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(PETSC_COMM_SELF, &gmsh->viewer)); 14479566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(gmsh->viewer, PETSCVIEWERASCII)); 14489566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(gmsh->viewer, FILE_MODE_READ)); 14499566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(gmsh->viewer, filename)); 1450d6689ca9SLisandro Dalcin /* Read only the first two lines of the Gmsh file */ 14519566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 14529566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$MeshFormat", line)); 14539566063dSJacob Faibussowitsch PetscCall(GmshReadString(gmsh, line, 2)); 1454d6689ca9SLisandro Dalcin snum = sscanf(line, "%f %d", &version, &fileType); 1455a8d4e440SJunchao Zhang fileFormat = (int)roundf(version * 10); 145608401ef6SPierre Jolivet PetscCheck(snum == 2, PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED, "Unable to parse Gmsh file header: %s", line); 1457a8d4e440SJunchao Zhang PetscCheck(fileFormat >= 22, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at least 2.2", (double)version); 14581dca8a05SBarry Smith PetscCheck((int)version != 3, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f not supported", (double)version); 1459a8d4e440SJunchao Zhang PetscCheck(fileFormat <= 41, PETSC_COMM_SELF, PETSC_ERR_SUP, "Gmsh file version %3.1f must be at most 4.1", (double)version); 14609566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&gmsh->viewer)); 1461d6689ca9SLisandro Dalcin } 14629566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(&fileType, 1, MPI_INT, 0, comm)); 1463d6689ca9SLisandro Dalcin vtype = (fileType == 0) ? PETSCVIEWERASCII : PETSCVIEWERBINARY; 1464d6689ca9SLisandro Dalcin 1465d6689ca9SLisandro Dalcin /* Create appropriate viewer and build plex */ 14669566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 14679566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, vtype)); 14689566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 14699566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 14709566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGmsh(comm, viewer, interpolate, dm)); 14719566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 14723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1473d6689ca9SLisandro Dalcin } 1474d6689ca9SLisandro Dalcin 1475331830f3SMatthew G. Knepley /*@ 1476a1cb98faSBarry Smith DMPlexCreateGmsh - Create a `DMPLEX` mesh from a Gmsh file viewer 1477331830f3SMatthew G. Knepley 1478d083f849SBarry Smith Collective 1479331830f3SMatthew G. Knepley 1480331830f3SMatthew G. Knepley Input Parameters: 1481331830f3SMatthew G. Knepley + comm - The MPI communicator 1482a1cb98faSBarry Smith . viewer - The `PetscViewer` associated with a Gmsh file 1483331830f3SMatthew G. Knepley - interpolate - Create faces and edges in the mesh 1484331830f3SMatthew G. Knepley 1485331830f3SMatthew G. Knepley Output Parameter: 1486a1cb98faSBarry Smith . dm - The `DM` object representing the mesh 1487331830f3SMatthew G. Knepley 1488a1cb98faSBarry Smith Options Database Keys: 1489df93260fSMatthew G. Knepley + -dm_plex_gmsh_hybrid - Force triangular prisms to use tensor order 1490df93260fSMatthew G. Knepley . -dm_plex_gmsh_periodic - Read Gmsh periodic section and construct a periodic Plex 1491df93260fSMatthew G. Knepley . -dm_plex_gmsh_highorder - Generate high-order coordinates 1492df93260fSMatthew 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 14932b205333SMatthew G. Knepley . -dm_plex_gmsh_use_generic - Generate generic labels, i.e. Cell Sets, Face Sets, etc. 1494df93260fSMatthew G. Knepley . -dm_plex_gmsh_use_regions - Generate labels with region names 1495df93260fSMatthew G. Knepley . -dm_plex_gmsh_mark_vertices - Add vertices to generated labels 1496df93260fSMatthew G. Knepley . -dm_plex_gmsh_multiple_tags - Allow multiple tags for default labels 1497df93260fSMatthew G. Knepley - -dm_plex_gmsh_spacedim <d> - Embedding space dimension, if different from topological dimension 1498df93260fSMatthew G. Knepley 14991d27aa22SBarry Smith Level: beginner 15001d27aa22SBarry Smith 15011d27aa22SBarry Smith Notes: 15021d27aa22SBarry Smith The Gmsh file format is described in <http://gmsh.info/doc/texinfo/gmsh.html#MSH-file-format> 1503df93260fSMatthew G. Knepley 15042b205333SMatthew 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. 1505331830f3SMatthew G. Knepley 15061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()` 1507331830f3SMatthew G. Knepley @*/ 1508d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateGmsh(MPI_Comm comm, PetscViewer viewer, PetscBool interpolate, DM *dm) 1509d71ae5a4SJacob Faibussowitsch { 15100598e1a2SLisandro Dalcin GmshMesh *mesh = NULL; 151111c56cb0SLisandro Dalcin PetscViewer parentviewer = NULL; 15120598e1a2SLisandro Dalcin PetscBT periodicVerts = NULL; 1513eae3dc7dSJacob Faibussowitsch PetscBT *periodicCells = NULL; 15146858538eSMatthew G. Knepley DM cdm, cdmCell = NULL; 15156858538eSMatthew G. Knepley PetscSection cs, csCell = NULL; 15166858538eSMatthew G. Knepley Vec coordinates, coordinatesCell; 15170444adf6SMatthew G. Knepley DMLabel cellSets = NULL, faceSets = NULL, edgeSets = NULL, vertSets = NULL, marker = NULL, *regionSets; 15189db5b827SMatthew G. Knepley PetscInt dim = 0, coordDim = -1, order = 0, maxHeight = 0; 15199db5b827SMatthew G. Knepley PetscInt numNodes = 0, numElems = 0, numVerts = 0, numCells = 0, vStart, vEnd; 1520066ea43fSLisandro Dalcin PetscInt cell, cone[8], e, n, v, d; 15212b205333SMatthew G. Knepley PetscBool usegeneric = PETSC_TRUE, useregions = PETSC_FALSE, markvertices = PETSC_FALSE, multipleTags = PETSC_FALSE; 15222b205333SMatthew G. Knepley PetscBool flg, binary, hybrid = interpolate, periodic = PETSC_TRUE; 1523066ea43fSLisandro Dalcin PetscBool highOrder = PETSC_TRUE, highOrderSet, project = PETSC_FALSE; 1524066ea43fSLisandro Dalcin PetscBool isSimplex = PETSC_FALSE, isHybrid = PETSC_FALSE, hasTetra = PETSC_FALSE; 15250598e1a2SLisandro Dalcin PetscMPIInt rank; 1526331830f3SMatthew G. Knepley 1527331830f3SMatthew G. Knepley PetscFunctionBegin; 15289566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1529d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)viewer); 1530d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Gmsh options"); 1531df93260fSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_gmsh_hybrid", "Force triangular prisms to use tensor order", "DMPlexCreateGmsh", hybrid, &hybrid, NULL)); 15329566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_periodic", "Read Gmsh periodic section", "DMPlexCreateGmsh", periodic, &periodic, NULL)); 15339566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_highorder", "Generate high-order coordinates", "DMPlexCreateGmsh", highOrder, &highOrder, &highOrderSet)); 15349566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_project", "Project high-order coordinates to a different space", "DMPlexCreateGmsh", project, &project, NULL)); 15359566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_use_regions", "Generate labels with region names", "DMPlexCreateGmsh", useregions, &useregions, NULL)); 15362b205333SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_gmsh_use_generic", "Generate generic labels, i.e. Cell Sets, Face Sets, etc", "DMPlexCreateGmsh", usegeneric, &usegeneric, &flg)); 15372b205333SMatthew G. Knepley if (!flg && useregions) usegeneric = PETSC_FALSE; 15389566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_gmsh_mark_vertices", "Add vertices to generated labels", "DMPlexCreateGmsh", markvertices, &markvertices, NULL)); 1539df93260fSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_gmsh_multiple_tags", "Allow multiple tags for default labels", "DMPlexCreateGmsh", multipleTags, &multipleTags, NULL)); 15409566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_gmsh_spacedim", "Embedding space dimension", "DMPlexCreateGmsh", coordDim, &coordDim, NULL, PETSC_DECIDE)); 15419db5b827SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_localize_height", "Localize edges and faces in addition to cells", "", maxHeight, &maxHeight, NULL, 0)); 1542d0609cedSBarry Smith PetscOptionsHeadEnd(); 1543d0609cedSBarry Smith PetscOptionsEnd(); 15440598e1a2SLisandro Dalcin 15459566063dSJacob Faibussowitsch PetscCall(GmshCellInfoSetUp()); 154611c56cb0SLisandro Dalcin 15479566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 15489566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 15499566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreateGmsh, *dm, NULL, NULL, NULL)); 155011c56cb0SLisandro Dalcin 15519566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &binary)); 155211c56cb0SLisandro Dalcin 155311c56cb0SLisandro Dalcin /* Binary viewers read on all ranks, get subviewer to read only in rank 0 */ 15543b46f529SLisandro Dalcin if (binary) { 155511c56cb0SLisandro Dalcin parentviewer = viewer; 15569566063dSJacob Faibussowitsch PetscCall(PetscViewerGetSubViewer(parentviewer, PETSC_COMM_SELF, &viewer)); 155711c56cb0SLisandro Dalcin } 155811c56cb0SLisandro Dalcin 1559dd400576SPatrick Sanan if (rank == 0) { 15600598e1a2SLisandro Dalcin GmshFile gmsh[1]; 1561698a79b9SLisandro Dalcin char line[PETSC_MAX_PATH_LEN]; 1562698a79b9SLisandro Dalcin PetscBool match; 1563331830f3SMatthew G. Knepley 15649566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(gmsh, 1)); 1565698a79b9SLisandro Dalcin gmsh->viewer = viewer; 1566698a79b9SLisandro Dalcin gmsh->binary = binary; 1567698a79b9SLisandro Dalcin 15689566063dSJacob Faibussowitsch PetscCall(GmshMeshCreate(&mesh)); 15690598e1a2SLisandro Dalcin 1570698a79b9SLisandro Dalcin /* Read mesh format */ 15719566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 15729566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$MeshFormat", line)); 15739566063dSJacob Faibussowitsch PetscCall(GmshReadMeshFormat(gmsh)); 15749566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndMeshFormat", line)); 157511c56cb0SLisandro Dalcin 15768749820aSMatthew G. Knepley /* OPTIONAL Read mesh version (Neper only) */ 15779566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 15788749820aSMatthew G. Knepley PetscCall(GmshMatch(gmsh, "$MeshVersion", line, &match)); 15798749820aSMatthew G. Knepley if (match) { 15808749820aSMatthew G. Knepley PetscCall(GmshExpect(gmsh, "$MeshVersion", line)); 15818749820aSMatthew G. Knepley PetscCall(GmshReadMeshVersion(gmsh)); 15828749820aSMatthew G. Knepley PetscCall(GmshReadEndSection(gmsh, "$EndMeshVersion", line)); 15838749820aSMatthew G. Knepley /* Initial read for entity section */ 15848749820aSMatthew G. Knepley PetscCall(GmshReadSection(gmsh, line)); 15858749820aSMatthew G. Knepley } 15868749820aSMatthew G. Knepley 15878749820aSMatthew G. Knepley /* OPTIONAL Read mesh domain (Neper only) */ 15888749820aSMatthew G. Knepley PetscCall(GmshMatch(gmsh, "$Domain", line, &match)); 15898749820aSMatthew G. Knepley if (match) { 15908749820aSMatthew G. Knepley PetscCall(GmshExpect(gmsh, "$Domain", line)); 15918749820aSMatthew G. Knepley PetscCall(GmshReadMeshDomain(gmsh)); 15928749820aSMatthew G. Knepley PetscCall(GmshReadEndSection(gmsh, "$EndDomain", line)); 15938749820aSMatthew G. Knepley /* Initial read for entity section */ 15948749820aSMatthew G. Knepley PetscCall(GmshReadSection(gmsh, line)); 15958749820aSMatthew G. Knepley } 15968749820aSMatthew G. Knepley 15978749820aSMatthew G. Knepley /* OPTIONAL Read physical names */ 15989566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$PhysicalNames", line, &match)); 1599dc0ede3bSMatthew G. Knepley if (match) { 16009566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$PhysicalNames", line)); 16019566063dSJacob Faibussowitsch PetscCall(GmshReadPhysicalNames(gmsh, mesh)); 16029566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndPhysicalNames", line)); 1603698a79b9SLisandro Dalcin /* Initial read for entity section */ 16049566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 1605dc0ede3bSMatthew G. Knepley } 160611c56cb0SLisandro Dalcin 1607*e43c9757SMatthew G. Knepley /* OPTIONAL Read entities */ 1608698a79b9SLisandro Dalcin if (gmsh->fileFormat >= 40) { 1609*e43c9757SMatthew G. Knepley PetscCall(GmshMatch(gmsh, "$Entities", line, &match)); 1610*e43c9757SMatthew G. Knepley if (match) { 16119566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Entities", line)); 16129566063dSJacob Faibussowitsch PetscCall(GmshReadEntities(gmsh, mesh)); 16139566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndEntities", line)); 1614698a79b9SLisandro Dalcin /* Initial read for nodes section */ 16159566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 1616de78e4feSLisandro Dalcin } 1617*e43c9757SMatthew G. Knepley } 1618de78e4feSLisandro Dalcin 1619698a79b9SLisandro Dalcin /* Read nodes */ 16209566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Nodes", line)); 16219566063dSJacob Faibussowitsch PetscCall(GmshReadNodes(gmsh, mesh)); 16229566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndNodes", line)); 162311c56cb0SLisandro Dalcin 1624698a79b9SLisandro Dalcin /* Read elements */ 16259566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 16269566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Elements", line)); 16279566063dSJacob Faibussowitsch PetscCall(GmshReadElements(gmsh, mesh)); 16289566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndElements", line)); 1629de78e4feSLisandro Dalcin 16300598e1a2SLisandro Dalcin /* Read periodic section (OPTIONAL) */ 1631698a79b9SLisandro Dalcin if (periodic) { 16329566063dSJacob Faibussowitsch PetscCall(GmshReadSection(gmsh, line)); 16339566063dSJacob Faibussowitsch PetscCall(GmshMatch(gmsh, "$Periodic", line, &periodic)); 1634ef12879bSLisandro Dalcin } 1635ef12879bSLisandro Dalcin if (periodic) { 16369566063dSJacob Faibussowitsch PetscCall(GmshExpect(gmsh, "$Periodic", line)); 16379566063dSJacob Faibussowitsch PetscCall(GmshReadPeriodic(gmsh, mesh)); 16389566063dSJacob Faibussowitsch PetscCall(GmshReadEndSection(gmsh, "$EndPeriodic", line)); 1639698a79b9SLisandro Dalcin } 1640698a79b9SLisandro Dalcin 16419566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->wbuf)); 16429566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->sbuf)); 16439566063dSJacob Faibussowitsch PetscCall(PetscFree(gmsh->nbuf)); 16440598e1a2SLisandro Dalcin 16450598e1a2SLisandro Dalcin dim = mesh->dim; 1646066ea43fSLisandro Dalcin order = mesh->order; 16470598e1a2SLisandro Dalcin numNodes = mesh->numNodes; 16480598e1a2SLisandro Dalcin numElems = mesh->numElems; 16490598e1a2SLisandro Dalcin numVerts = mesh->numVerts; 16500598e1a2SLisandro Dalcin numCells = mesh->numCells; 1651066ea43fSLisandro Dalcin 1652066ea43fSLisandro Dalcin { 1653066ea43fSLisandro Dalcin GmshElement *elemA = mesh->numCells > 0 ? mesh->elements : NULL; 16548e3a54c0SPierre Jolivet GmshElement *elemB = PetscSafePointerPlusOffset(elemA, mesh->numCells - 1); 1655066ea43fSLisandro Dalcin int ptA = elemA ? GmshCellMap[elemA->cellType].polytope : -1; 1656066ea43fSLisandro Dalcin int ptB = elemB ? GmshCellMap[elemB->cellType].polytope : -1; 1657066ea43fSLisandro Dalcin isSimplex = (ptA == GMSH_QUA || ptA == GMSH_HEX) ? PETSC_FALSE : PETSC_TRUE; 1658066ea43fSLisandro Dalcin isHybrid = (ptA == ptB) ? PETSC_FALSE : PETSC_TRUE; 1659066ea43fSLisandro Dalcin hasTetra = (ptA == GMSH_TET) ? PETSC_TRUE : PETSC_FALSE; 1660066ea43fSLisandro Dalcin } 1661698a79b9SLisandro Dalcin } 1662698a79b9SLisandro Dalcin 166348a46eb9SPierre Jolivet if (parentviewer) PetscCall(PetscViewerRestoreSubViewer(parentviewer, PETSC_COMM_SELF, &viewer)); 1664698a79b9SLisandro Dalcin 1665066ea43fSLisandro Dalcin { 1666066ea43fSLisandro Dalcin int buf[6]; 1667698a79b9SLisandro Dalcin 1668066ea43fSLisandro Dalcin buf[0] = (int)dim; 1669066ea43fSLisandro Dalcin buf[1] = (int)order; 1670066ea43fSLisandro Dalcin buf[2] = periodic; 1671066ea43fSLisandro Dalcin buf[3] = isSimplex; 1672066ea43fSLisandro Dalcin buf[4] = isHybrid; 1673066ea43fSLisandro Dalcin buf[5] = hasTetra; 1674066ea43fSLisandro Dalcin 16759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(buf, 6, MPI_INT, 0, comm)); 1676066ea43fSLisandro Dalcin 1677066ea43fSLisandro Dalcin dim = buf[0]; 1678066ea43fSLisandro Dalcin order = buf[1]; 1679066ea43fSLisandro Dalcin periodic = buf[2] ? PETSC_TRUE : PETSC_FALSE; 1680066ea43fSLisandro Dalcin isSimplex = buf[3] ? PETSC_TRUE : PETSC_FALSE; 1681066ea43fSLisandro Dalcin isHybrid = buf[4] ? PETSC_TRUE : PETSC_FALSE; 1682066ea43fSLisandro Dalcin hasTetra = buf[5] ? PETSC_TRUE : PETSC_FALSE; 1683dea2a3c7SStefano Zampini } 1684dea2a3c7SStefano Zampini 1685066ea43fSLisandro Dalcin if (!highOrderSet) highOrder = (order > 1) ? PETSC_TRUE : PETSC_FALSE; 168608401ef6SPierre Jolivet PetscCheck(!highOrder || !isHybrid, comm, PETSC_ERR_SUP, "No support for discretization on hybrid meshes yet"); 1687066ea43fSLisandro Dalcin 16880598e1a2SLisandro Dalcin /* We do not want this label automatically computed, instead we fill it here */ 16899566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "celltype")); 169011c56cb0SLisandro Dalcin 1691a4bb7517SMichael Lange /* Allocate the cell-vertex mesh */ 16929566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(*dm, 0, numCells + numVerts)); 16930598e1a2SLisandro Dalcin for (cell = 0; cell < numCells; ++cell) { 16940598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + cell; 16950598e1a2SLisandro Dalcin DMPolytopeType ctype = DMPolytopeTypeFromGmsh(elem->cellType); 16960598e1a2SLisandro Dalcin if (hybrid && hasTetra && ctype == DM_POLYTOPE_TRI_PRISM) ctype = DM_POLYTOPE_TRI_PRISM_TENSOR; 16979566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(*dm, cell, elem->numVerts)); 16989566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(*dm, cell, ctype)); 1699db397164SMichael Lange } 170048a46eb9SPierre Jolivet for (v = numCells; v < numCells + numVerts; ++v) PetscCall(DMPlexSetCellType(*dm, v, DM_POLYTOPE_POINT)); 17019566063dSJacob Faibussowitsch PetscCall(DMSetUp(*dm)); 170296ca5757SLisandro Dalcin 1703a4bb7517SMichael Lange /* Add cell-vertex connections */ 17040598e1a2SLisandro Dalcin for (cell = 0; cell < numCells; ++cell) { 17050598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + cell; 17060598e1a2SLisandro Dalcin for (v = 0; v < elem->numVerts; ++v) { 17070598e1a2SLisandro Dalcin const PetscInt nn = elem->nodes[v]; 17080598e1a2SLisandro Dalcin const PetscInt vv = mesh->vertexMap[nn]; 17090598e1a2SLisandro Dalcin cone[v] = numCells + vv; 1710db397164SMichael Lange } 17119566063dSJacob Faibussowitsch PetscCall(DMPlexReorderCell(*dm, cell, cone)); 17129566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(*dm, cell, cone)); 1713a4bb7517SMichael Lange } 171496ca5757SLisandro Dalcin 17159566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 17169566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(*dm)); 17179566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(*dm)); 1718331830f3SMatthew G. Knepley if (interpolate) { 17195fd9971aSMatthew G. Knepley DM idm; 1720331830f3SMatthew G. Knepley 17219566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 17229566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 1723331830f3SMatthew G. Knepley *dm = idm; 1724331830f3SMatthew G. Knepley } 17259db5b827SMatthew G. Knepley PetscCall(DMPlexGetDepthStratum(*dm, 0, &vStart, &vEnd)); 1726917266a4SLisandro Dalcin 1727dd400576SPatrick Sanan if (rank == 0) { 1728a45dabc8SMatthew G. Knepley const PetscInt Nr = useregions ? mesh->numRegions : 0; 1729d1a54cefSMatthew G. Knepley 17309566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(Nr, ®ionSets)); 17310598e1a2SLisandro Dalcin for (cell = 0, e = 0; e < numElems; ++e) { 17320598e1a2SLisandro Dalcin GmshElement *elem = mesh->elements + e; 17336e1dd89aSLawrence Mitchell 17346e1dd89aSLawrence Mitchell /* Create cell sets */ 17350598e1a2SLisandro Dalcin if (elem->dim == dim && dim > 0) { 17360598e1a2SLisandro Dalcin if (elem->numTags > 0) { 1737df93260fSMatthew G. Knepley PetscInt Nt = elem->numTags, t, r; 1738a45dabc8SMatthew G. Knepley 1739df93260fSMatthew G. Knepley for (t = 0; t < Nt; ++t) { 1740df93260fSMatthew G. Knepley const PetscInt tag = elem->tags[t]; 17412b205333SMatthew G. Knepley const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE; 1742df93260fSMatthew G. Knepley 1743df93260fSMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &cellSets, "Cell Sets", cell, tag)); 1744a45dabc8SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 1745df93260fSMatthew G. Knepley if (mesh->regionDims[r] != dim) continue; 17469566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], cell, tag)); 1747a45dabc8SMatthew G. Knepley } 17486e1dd89aSLawrence Mitchell } 1749df93260fSMatthew G. Knepley } 1750917266a4SLisandro Dalcin cell++; 17516e1dd89aSLawrence Mitchell } 17520c070f12SSander Arens 17530598e1a2SLisandro Dalcin /* Create face sets */ 1754aec57b10SMatthew G. Knepley if (elem->numTags && interpolate && elem->dim == dim - 1) { 17550598e1a2SLisandro Dalcin PetscInt joinSize; 17560598e1a2SLisandro Dalcin const PetscInt *join = NULL; 17570444adf6SMatthew G. Knepley PetscInt Nt = elem->numTags, pdepth; 1758a45dabc8SMatthew G. Knepley 17590598e1a2SLisandro Dalcin /* Find the relevant facet with vertex joins */ 17600598e1a2SLisandro Dalcin for (v = 0; v < elem->numVerts; ++v) { 17610598e1a2SLisandro Dalcin const PetscInt nn = elem->nodes[v]; 17620598e1a2SLisandro Dalcin const PetscInt vv = mesh->vertexMap[nn]; 17630598e1a2SLisandro Dalcin cone[v] = vStart + vv; 17640598e1a2SLisandro Dalcin } 17659566063dSJacob Faibussowitsch PetscCall(DMPlexGetFullJoin(*dm, elem->numVerts, cone, &joinSize, &join)); 176663a3b9bcSJacob 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); 17670444adf6SMatthew G. Knepley PetscCall(DMPlexGetPointDepth(*dm, join[0], &pdepth)); 17680444adf6SMatthew 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); 17690444adf6SMatthew G. Knepley for (PetscInt t = 0; t < Nt; ++t) { 17705ad74b4fSMatthew G. Knepley const PetscInt tag = elem->tags[t]; 17712b205333SMatthew G. Knepley const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE; 17725ad74b4fSMatthew G. Knepley 1773df93260fSMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &faceSets, "Face Sets", join[0], tag)); 17740444adf6SMatthew G. Knepley for (PetscInt r = 0; r < Nr; ++r) { 1775df93260fSMatthew G. Knepley if (mesh->regionDims[r] != dim - 1) continue; 17769566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], join[0], tag)); 1777a45dabc8SMatthew G. Knepley } 17785ad74b4fSMatthew G. Knepley } 17799566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(*dm, elem->numVerts, cone, &joinSize, &join)); 17800598e1a2SLisandro Dalcin } 17810598e1a2SLisandro Dalcin 1782aec57b10SMatthew G. Knepley /* Create edge sets */ 1783aec57b10SMatthew G. Knepley if (elem->numTags && interpolate && dim > 2 && elem->dim == 1) { 1784aec57b10SMatthew G. Knepley PetscInt joinSize; 1785aec57b10SMatthew G. Knepley const PetscInt *join = NULL; 1786aec57b10SMatthew G. Knepley PetscInt Nt = elem->numTags, t, r; 1787aec57b10SMatthew G. Knepley 1788aec57b10SMatthew G. Knepley /* Find the relevant edge with vertex joins */ 1789aec57b10SMatthew G. Knepley for (v = 0; v < elem->numVerts; ++v) { 1790aec57b10SMatthew G. Knepley const PetscInt nn = elem->nodes[v]; 1791aec57b10SMatthew G. Knepley const PetscInt vv = mesh->vertexMap[nn]; 1792aec57b10SMatthew G. Knepley cone[v] = vStart + vv; 1793aec57b10SMatthew G. Knepley } 1794aec57b10SMatthew G. Knepley PetscCall(DMPlexGetJoin(*dm, elem->numVerts, cone, &joinSize, &join)); 1795aec57b10SMatthew 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); 1796aec57b10SMatthew G. Knepley for (t = 0; t < Nt; ++t) { 1797aec57b10SMatthew G. Knepley const PetscInt tag = elem->tags[t]; 17982b205333SMatthew G. Knepley const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE; 1799aec57b10SMatthew G. Knepley 18000444adf6SMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &edgeSets, "Edge Sets", join[0], tag)); 1801aec57b10SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 1802aec57b10SMatthew G. Knepley if (mesh->regionDims[r] != 1) continue; 1803aec57b10SMatthew G. Knepley if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], join[0], tag)); 1804aec57b10SMatthew G. Knepley } 1805aec57b10SMatthew G. Knepley } 1806aec57b10SMatthew G. Knepley PetscCall(DMPlexRestoreJoin(*dm, elem->numVerts, cone, &joinSize, &join)); 1807aec57b10SMatthew G. Knepley } 1808aec57b10SMatthew G. Knepley 18090c070f12SSander Arens /* Create vertex sets */ 1810aec57b10SMatthew G. Knepley if (elem->numTags && elem->dim == 0 && markvertices) { 18110598e1a2SLisandro Dalcin const PetscInt nn = elem->nodes[0]; 18120598e1a2SLisandro Dalcin const PetscInt vv = mesh->vertexMap[nn]; 1813a45dabc8SMatthew G. Knepley const PetscInt tag = elem->tags[0]; 1814a45dabc8SMatthew G. Knepley PetscInt r; 1815a45dabc8SMatthew G. Knepley 18168a3d9825SMatthew G. Knepley if (vv < 0) continue; 18172b205333SMatthew G. Knepley if (usegeneric) PetscCall(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag)); 181881a1af93SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 1819df93260fSMatthew G. Knepley if (mesh->regionDims[r] != 0) continue; 18209566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], vStart + vv, tag)); 182181a1af93SMatthew G. Knepley } 182281a1af93SMatthew G. Knepley } 182381a1af93SMatthew G. Knepley } 182481a1af93SMatthew G. Knepley if (markvertices) { 182581a1af93SMatthew G. Knepley for (v = 0; v < numNodes; ++v) { 182681a1af93SMatthew G. Knepley const PetscInt vv = mesh->vertexMap[v]; 18277d5b9244SMatthew G. Knepley const PetscInt *tags = &mesh->nodelist->tag[v * GMSH_MAX_TAGS]; 18287d5b9244SMatthew G. Knepley PetscInt r, t; 182981a1af93SMatthew G. Knepley 18308a3d9825SMatthew G. Knepley if (vv < 0) continue; 18317d5b9244SMatthew G. Knepley for (t = 0; t < GMSH_MAX_TAGS; ++t) { 18327d5b9244SMatthew G. Knepley const PetscInt tag = tags[t]; 18332b205333SMatthew G. Knepley const PetscBool generic = usegeneric && (!t || multipleTags) ? PETSC_TRUE : PETSC_FALSE; 18347d5b9244SMatthew G. Knepley 18357d5b9244SMatthew G. Knepley if (tag == -1) continue; 1836df93260fSMatthew G. Knepley if (generic) PetscCall(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vStart + vv, tag)); 1837a45dabc8SMatthew G. Knepley for (r = 0; r < Nr; ++r) { 18389566063dSJacob Faibussowitsch if (mesh->regionTags[r] == tag) PetscCall(DMSetLabelValue_Fast(*dm, ®ionSets[r], mesh->regionNames[r], vStart + vv, tag)); 18390598e1a2SLisandro Dalcin } 18400598e1a2SLisandro Dalcin } 18410598e1a2SLisandro Dalcin } 18420598e1a2SLisandro Dalcin } 18439566063dSJacob Faibussowitsch PetscCall(PetscFree(regionSets)); 1844a45dabc8SMatthew G. Knepley } 18450598e1a2SLisandro Dalcin 18460444adf6SMatthew G. Knepley { /* Create Cell/Face/Edge/Vertex Sets labels at all processes */ 18479371c9d4SSatish Balay enum { 18480444adf6SMatthew G. Knepley n = 5 18499371c9d4SSatish Balay }; 18507dd454faSLisandro Dalcin PetscBool flag[n]; 18517dd454faSLisandro Dalcin 18527dd454faSLisandro Dalcin flag[0] = cellSets ? PETSC_TRUE : PETSC_FALSE; 18537dd454faSLisandro Dalcin flag[1] = faceSets ? PETSC_TRUE : PETSC_FALSE; 18540444adf6SMatthew G. Knepley flag[2] = edgeSets ? PETSC_TRUE : PETSC_FALSE; 18550444adf6SMatthew G. Knepley flag[3] = vertSets ? PETSC_TRUE : PETSC_FALSE; 18560444adf6SMatthew G. Knepley flag[4] = marker ? PETSC_TRUE : PETSC_FALSE; 18579566063dSJacob Faibussowitsch PetscCallMPI(MPI_Bcast(flag, n, MPIU_BOOL, 0, comm)); 18589566063dSJacob Faibussowitsch if (flag[0]) PetscCall(DMCreateLabel(*dm, "Cell Sets")); 18599566063dSJacob Faibussowitsch if (flag[1]) PetscCall(DMCreateLabel(*dm, "Face Sets")); 18600444adf6SMatthew G. Knepley if (flag[2]) PetscCall(DMCreateLabel(*dm, "Edge Sets")); 18610444adf6SMatthew G. Knepley if (flag[3]) PetscCall(DMCreateLabel(*dm, "Vertex Sets")); 18620444adf6SMatthew G. Knepley if (flag[4]) PetscCall(DMCreateLabel(*dm, "marker")); 18637dd454faSLisandro Dalcin } 18647dd454faSLisandro Dalcin 18650598e1a2SLisandro Dalcin if (periodic) { 18669566063dSJacob Faibussowitsch PetscCall(PetscBTCreate(numVerts, &periodicVerts)); 18670598e1a2SLisandro Dalcin for (n = 0; n < numNodes; ++n) { 18680598e1a2SLisandro Dalcin if (mesh->vertexMap[n] >= 0) { 18690598e1a2SLisandro Dalcin if (PetscUnlikely(mesh->periodMap[n] != n)) { 18700598e1a2SLisandro Dalcin PetscInt m = mesh->periodMap[n]; 18719566063dSJacob Faibussowitsch PetscCall(PetscBTSet(periodicVerts, mesh->vertexMap[n])); 18729566063dSJacob Faibussowitsch PetscCall(PetscBTSet(periodicVerts, mesh->vertexMap[m])); 18730598e1a2SLisandro Dalcin } 18740598e1a2SLisandro Dalcin } 18750598e1a2SLisandro Dalcin } 18769db5b827SMatthew G. Knepley PetscCall(DMGetCoordinateDM(*dm, &cdm)); 1877eae3dc7dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxHeight + 1, &periodicCells)); 18789db5b827SMatthew G. Knepley for (PetscInt h = 0; h <= maxHeight; ++h) { 18799db5b827SMatthew G. Knepley PetscInt pStart, pEnd; 18809db5b827SMatthew G. Knepley 18819db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(*dm, h, &pStart, &pEnd)); 18829db5b827SMatthew G. Knepley PetscCall(PetscBTCreate(pEnd - pStart, &periodicCells[h])); 18839db5b827SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 18849db5b827SMatthew G. Knepley PetscInt *closure = NULL; 18859db5b827SMatthew G. Knepley PetscInt Ncl; 18869db5b827SMatthew G. Knepley 18879db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure)); 18889db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) { 18899db5b827SMatthew G. Knepley if (closure[cl] >= vStart && closure[cl] < vEnd) { 18909db5b827SMatthew G. Knepley if (PetscUnlikely(PetscBTLookup(periodicVerts, closure[cl] - vStart))) { 18919db5b827SMatthew G. Knepley PetscCall(PetscBTSet(periodicCells[h], p - pStart)); 18929371c9d4SSatish Balay break; 18930c070f12SSander Arens } 18940c070f12SSander Arens } 18950c070f12SSander Arens } 18969db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure)); 18979db5b827SMatthew G. Knepley } 18989db5b827SMatthew G. Knepley } 189916ad7e67SMichael Lange } 190016ad7e67SMichael Lange 1901066ea43fSLisandro Dalcin /* Setup coordinate DM */ 19020598e1a2SLisandro Dalcin if (coordDim < 0) coordDim = dim; 19039566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*dm, coordDim)); 19049566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(*dm, &cdm)); 1905066ea43fSLisandro Dalcin if (highOrder) { 1906066ea43fSLisandro Dalcin PetscFE fe; 1907066ea43fSLisandro Dalcin PetscBool continuity = periodic ? PETSC_FALSE : PETSC_TRUE; 1908066ea43fSLisandro Dalcin PetscDTNodeType nodeType = PETSCDTNODES_EQUISPACED; 1909066ea43fSLisandro Dalcin 1910066ea43fSLisandro Dalcin if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */ 1911066ea43fSLisandro Dalcin 19129566063dSJacob Faibussowitsch PetscCall(GmshCreateFE(comm, NULL, isSimplex, continuity, nodeType, dim, coordDim, order, &fe)); 19139566063dSJacob Faibussowitsch PetscCall(PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_fe_view")); 19149566063dSJacob Faibussowitsch PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)fe)); 19159566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 19169566063dSJacob Faibussowitsch PetscCall(DMCreateDS(cdm)); 1917066ea43fSLisandro Dalcin } 19186858538eSMatthew G. Knepley if (periodic) { 19196858538eSMatthew G. Knepley PetscCall(DMClone(cdm, &cdmCell)); 19206858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(*dm, cdmCell)); 19216858538eSMatthew G. Knepley } 1922066ea43fSLisandro Dalcin 1923066ea43fSLisandro Dalcin /* Create coordinates */ 1924066ea43fSLisandro Dalcin if (highOrder) { 1925066ea43fSLisandro Dalcin PetscInt maxDof = GmshNumNodes_HEX(order) * coordDim; 1926066ea43fSLisandro Dalcin double *coords = mesh ? mesh->nodelist->xyz : NULL; 1927066ea43fSLisandro Dalcin PetscSection section; 1928066ea43fSLisandro Dalcin PetscScalar *cellCoords; 1929066ea43fSLisandro Dalcin 19309566063dSJacob Faibussowitsch PetscCall(DMSetLocalSection(cdm, NULL)); 19316858538eSMatthew G. Knepley PetscCall(DMGetLocalSection(cdm, &cs)); 19326858538eSMatthew G. Knepley PetscCall(PetscSectionClone(cs, §ion)); 19339566063dSJacob Faibussowitsch PetscCall(DMPlexSetClosurePermutationTensor(cdm, 0, section)); /* XXX Implement DMPlexSetClosurePermutationLexicographic() */ 1934066ea43fSLisandro Dalcin 19359566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 19369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(maxDof, &cellCoords)); 1937066ea43fSLisandro Dalcin for (cell = 0; cell < numCells; ++cell) { 1938066ea43fSLisandro Dalcin GmshElement *elem = mesh->elements + cell; 1939066ea43fSLisandro Dalcin const int *lexorder = GmshCellMap[elem->cellType].lexorder(); 1940b9bf55e5SMatthew G. Knepley int s = 0; 1941066ea43fSLisandro Dalcin for (n = 0; n < elem->numNodes; ++n) { 1942b9bf55e5SMatthew G. Knepley while (lexorder[n + s] < 0) ++s; 1943b9bf55e5SMatthew G. Knepley const PetscInt node = elem->nodes[lexorder[n + s]]; 1944b9bf55e5SMatthew G. Knepley for (d = 0; d < coordDim; ++d) cellCoords[(n + s) * coordDim + d] = (PetscReal)coords[node * 3 + d]; 1945b9bf55e5SMatthew G. Knepley } 1946b9bf55e5SMatthew G. Knepley if (s) { 1947b9bf55e5SMatthew G. Knepley /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */ 1948b9bf55e5SMatthew G. Knepley PetscReal quaCenterWeights[9] = {-0.25, 0.5, -0.25, 0.5, 0.0, 0.5, -0.25, 0.5, -0.25}; 1949b9bf55e5SMatthew G. Knepley /* For the coordinate mapping we weight vertices by -1/4 and edges by 1/2, which we get from Q_2 interpolation */ 19509371c9d4SSatish 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}; 19519371c9d4SSatish 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}; 19529371c9d4SSatish 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}; 19539371c9d4SSatish 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}; 19549371c9d4SSatish 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}; 19559371c9d4SSatish 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}; 19569371c9d4SSatish 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}; 1957b9bf55e5SMatthew G. Knepley PetscReal *sdWeights2[9] = {NULL, NULL, NULL, NULL, quaCenterWeights, NULL, NULL, NULL, NULL}; 19589371c9d4SSatish Balay PetscReal *sdWeights3[27] = {NULL, NULL, NULL, NULL, hexBottomWeights, NULL, NULL, NULL, NULL, NULL, hexFrontWeights, NULL, hexLeftWeights, hexCenterWeights, hexRightWeights, NULL, hexBackWeights, NULL, 1959b9bf55e5SMatthew G. Knepley NULL, NULL, NULL, NULL, hexTopWeights, NULL, NULL, NULL, NULL}; 1960b9bf55e5SMatthew G. Knepley PetscReal **sdWeights[4] = {NULL, NULL, sdWeights2, sdWeights3}; 1961b9bf55e5SMatthew G. Knepley 1962b9bf55e5SMatthew G. Knepley /* Missing entries in serendipity cell, only works for 8-node quad and 20-node hex */ 1963b9bf55e5SMatthew G. Knepley for (n = 0; n < elem->numNodes + s; ++n) { 1964b9bf55e5SMatthew G. Knepley if (lexorder[n] >= 0) continue; 1965b9bf55e5SMatthew G. Knepley for (d = 0; d < coordDim; ++d) cellCoords[n * coordDim + d] = 0.0; 1966b9bf55e5SMatthew G. Knepley for (int bn = 0; bn < elem->numNodes + s; ++bn) { 1967b9bf55e5SMatthew G. Knepley if (lexorder[bn] < 0) continue; 1968b9bf55e5SMatthew G. Knepley const PetscReal *weights = sdWeights[coordDim][n]; 1969b9bf55e5SMatthew G. Knepley const PetscInt bnode = elem->nodes[lexorder[bn]]; 1970b9bf55e5SMatthew G. Knepley for (d = 0; d < coordDim; ++d) cellCoords[n * coordDim + d] += weights[bn] * (PetscReal)coords[bnode * 3 + d]; 1971b9bf55e5SMatthew G. Knepley } 1972b9bf55e5SMatthew G. Knepley } 1973066ea43fSLisandro Dalcin } 19749566063dSJacob Faibussowitsch PetscCall(DMPlexVecSetClosure(cdm, section, coordinates, cell, cellCoords, INSERT_VALUES)); 1975066ea43fSLisandro Dalcin } 19769566063dSJacob Faibussowitsch PetscCall(PetscSectionDestroy(§ion)); 19779566063dSJacob Faibussowitsch PetscCall(PetscFree(cellCoords)); 1978066ea43fSLisandro Dalcin } else { 1979066ea43fSLisandro Dalcin PetscInt *nodeMap; 1980066ea43fSLisandro Dalcin double *coords = mesh ? mesh->nodelist->xyz : NULL; 1981066ea43fSLisandro Dalcin PetscScalar *pointCoords; 1982066ea43fSLisandro Dalcin 19836858538eSMatthew G. Knepley PetscCall(DMGetCoordinateSection(*dm, &cs)); 19846858538eSMatthew G. Knepley PetscCall(PetscSectionSetNumFields(cs, 1)); 19856858538eSMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(cs, 0, coordDim)); 19866858538eSMatthew G. Knepley PetscCall(PetscSectionSetChart(cs, numCells, numCells + numVerts)); 19876858538eSMatthew G. Knepley for (v = numCells; v < numCells + numVerts; ++v) { 19886858538eSMatthew G. Knepley PetscCall(PetscSectionSetDof(cs, v, coordDim)); 19896858538eSMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(cs, v, 0, coordDim)); 1990f45c9589SStefano Zampini } 19916858538eSMatthew G. Knepley PetscCall(PetscSectionSetUp(cs)); 19926858538eSMatthew G. Knepley 19936858538eSMatthew G. Knepley /* We need to localize coordinates on cells */ 19940598e1a2SLisandro Dalcin if (periodic) { 19959db5b827SMatthew G. Knepley PetscInt newStart = PETSC_MAX_INT, newEnd = -1, pStart, pEnd; 19969db5b827SMatthew G. Knepley 19976858538eSMatthew G. Knepley PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)cdmCell), &csCell)); 19986858538eSMatthew G. Knepley PetscCall(PetscSectionSetNumFields(csCell, 1)); 19996858538eSMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(csCell, 0, coordDim)); 20009db5b827SMatthew G. Knepley for (PetscInt h = 0; h <= maxHeight; h++) { 20019db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, h, &pStart, &pEnd)); 20029db5b827SMatthew G. Knepley newStart = PetscMin(newStart, pStart); 20039db5b827SMatthew G. Knepley newEnd = PetscMax(newEnd, pEnd); 20049db5b827SMatthew G. Knepley } 20059db5b827SMatthew G. Knepley PetscCall(PetscSectionSetChart(csCell, newStart, newEnd)); 20069db5b827SMatthew G. Knepley for (PetscInt h = 0; h <= maxHeight; h++) { 20079db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, h, &pStart, &pEnd)); 20089db5b827SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 20099db5b827SMatthew G. Knepley PetscInt *closure = NULL; 20109db5b827SMatthew G. Knepley PetscInt Ncl, Nv = 0; 20116858538eSMatthew G. Knepley 20129db5b827SMatthew G. Knepley if (PetscUnlikely(PetscBTLookup(periodicCells[h], p - pStart))) { 20139db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure)); 20149db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) { 20159db5b827SMatthew G. Knepley if (closure[cl] >= vStart && closure[cl] < vEnd) ++Nv; 20169db5b827SMatthew G. Knepley } 20179db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(*dm, p, PETSC_TRUE, &Ncl, &closure)); 20189db5b827SMatthew G. Knepley PetscCall(PetscSectionSetDof(csCell, p, Nv * coordDim)); 20199db5b827SMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(csCell, p, 0, Nv * coordDim)); 20209db5b827SMatthew G. Knepley } 2021f45c9589SStefano Zampini } 2022f45c9589SStefano Zampini } 20236858538eSMatthew G. Knepley PetscCall(PetscSectionSetUp(csCell)); 20246858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateSection(*dm, PETSC_DETERMINE, csCell)); 2025f45c9589SStefano Zampini } 2026066ea43fSLisandro Dalcin 20279566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 20289566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &pointCoords)); 20296858538eSMatthew G. Knepley PetscCall(PetscMalloc1(numVerts, &nodeMap)); 20306858538eSMatthew G. Knepley for (n = 0; n < numNodes; n++) 20316858538eSMatthew G. Knepley if (mesh->vertexMap[n] >= 0) nodeMap[mesh->vertexMap[n]] = n; 20326858538eSMatthew G. Knepley for (v = 0; v < numVerts; ++v) { 20336858538eSMatthew G. Knepley PetscInt off, node = nodeMap[v]; 20346858538eSMatthew G. Knepley 20356858538eSMatthew G. Knepley PetscCall(PetscSectionGetOffset(cs, numCells + v, &off)); 20366858538eSMatthew G. Knepley for (d = 0; d < coordDim; ++d) pointCoords[off + d] = (PetscReal)coords[node * 3 + d]; 20376858538eSMatthew G. Knepley } 20386858538eSMatthew G. Knepley PetscCall(VecRestoreArray(coordinates, &pointCoords)); 20396858538eSMatthew G. Knepley 20400598e1a2SLisandro Dalcin if (periodic) { 20419db5b827SMatthew G. Knepley PetscInt cStart, cEnd; 20429db5b827SMatthew G. Knepley 20439db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, 0, &cStart, &cEnd)); 20446858538eSMatthew G. Knepley PetscCall(DMCreateLocalVector(cdmCell, &coordinatesCell)); 20456858538eSMatthew G. Knepley PetscCall(VecGetArray(coordinatesCell, &pointCoords)); 20469db5b827SMatthew G. Knepley for (PetscInt c = cStart; c < cEnd; ++c) { 20479db5b827SMatthew G. Knepley GmshElement *elem = mesh->elements + c - cStart; 20489db5b827SMatthew G. Knepley PetscInt *closure = NULL; 20499db5b827SMatthew G. Knepley PetscInt verts[8]; 20509db5b827SMatthew G. Knepley PetscInt Ncl, Nv = 0; 20519db5b827SMatthew G. Knepley 20529db5b827SMatthew G. Knepley for (PetscInt v = 0; v < elem->numVerts; ++v) cone[v] = elem->nodes[v]; 20539db5b827SMatthew G. Knepley PetscCall(DMPlexReorderCell(cdmCell, c, cone)); 20549db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(cdmCell, c, PETSC_TRUE, &Ncl, &closure)); 20559db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) { 20569db5b827SMatthew G. Knepley if (closure[cl] >= vStart && closure[cl] < vEnd) verts[Nv++] = closure[cl]; 2057331830f3SMatthew G. Knepley } 20589db5b827SMatthew 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); 20599db5b827SMatthew G. Knepley for (PetscInt cl = 0; cl < Ncl * 2; cl += 2) { 20609db5b827SMatthew G. Knepley const PetscInt point = closure[cl]; 20619db5b827SMatthew G. Knepley PetscInt hStart, h; 20629db5b827SMatthew G. Knepley 20639db5b827SMatthew G. Knepley PetscCall(DMPlexGetPointHeight(cdmCell, point, &h)); 20649db5b827SMatthew G. Knepley if (h > maxHeight) continue; 20659db5b827SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(cdmCell, h, &hStart, NULL)); 20669db5b827SMatthew G. Knepley if (PetscUnlikely(PetscBTLookup(periodicCells[h], point - hStart))) { 20679db5b827SMatthew G. Knepley PetscInt *pclosure = NULL; 20689db5b827SMatthew G. Knepley PetscInt Npcl, off, v; 20699db5b827SMatthew G. Knepley 20709db5b827SMatthew G. Knepley PetscCall(PetscSectionGetOffset(csCell, point, &off)); 20719db5b827SMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(cdmCell, point, PETSC_TRUE, &Npcl, &pclosure)); 20729db5b827SMatthew G. Knepley for (PetscInt pcl = 0; pcl < Npcl * 2; pcl += 2) { 20739db5b827SMatthew G. Knepley if (pclosure[pcl] >= vStart && pclosure[pcl] < vEnd) { 20749db5b827SMatthew G. Knepley for (v = 0; v < Nv; ++v) 20759db5b827SMatthew G. Knepley if (verts[v] == pclosure[pcl]) break; 20769db5b827SMatthew 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); 20779db5b827SMatthew G. Knepley for (PetscInt d = 0; d < coordDim; ++d) pointCoords[off++] = (PetscReal)coords[cone[v] * 3 + d]; 20789db5b827SMatthew G. Knepley ++v; 20799db5b827SMatthew G. Knepley } 20809db5b827SMatthew G. Knepley } 20819db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(cdmCell, point, PETSC_TRUE, &Npcl, &pclosure)); 20829db5b827SMatthew G. Knepley } 20839db5b827SMatthew G. Knepley } 20849db5b827SMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(cdmCell, c, PETSC_TRUE, &Ncl, &closure)); 2085331830f3SMatthew G. Knepley } 20866858538eSMatthew G. Knepley PetscCall(VecSetBlockSize(coordinatesCell, coordDim)); 20876858538eSMatthew G. Knepley PetscCall(VecRestoreArray(coordinatesCell, &pointCoords)); 20886858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(*dm, coordinatesCell)); 20896858538eSMatthew G. Knepley PetscCall(VecDestroy(&coordinatesCell)); 2090331830f3SMatthew G. Knepley } 20919db5b827SMatthew G. Knepley PetscCall(PetscFree(nodeMap)); 20926858538eSMatthew G. Knepley PetscCall(PetscSectionDestroy(&csCell)); 20936858538eSMatthew G. Knepley PetscCall(DMDestroy(&cdmCell)); 2094066ea43fSLisandro Dalcin } 2095066ea43fSLisandro Dalcin 20969566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 20979566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, coordDim)); 20989566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(*dm, coordinates)); 20999566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 210011c56cb0SLisandro Dalcin 21019566063dSJacob Faibussowitsch PetscCall(GmshMeshDestroy(&mesh)); 21029566063dSJacob Faibussowitsch PetscCall(PetscBTDestroy(&periodicVerts)); 2103eae3dc7dSJacob Faibussowitsch if (periodic) { 2104eae3dc7dSJacob Faibussowitsch for (PetscInt h = 0; h <= maxHeight; ++h) PetscCall(PetscBTDestroy(periodicCells + h)); 2105eae3dc7dSJacob Faibussowitsch PetscCall(PetscFree(periodicCells)); 2106eae3dc7dSJacob Faibussowitsch } 210711c56cb0SLisandro Dalcin 2108066ea43fSLisandro Dalcin if (highOrder && project) { 2109066ea43fSLisandro Dalcin PetscFE fe; 2110066ea43fSLisandro Dalcin const char prefix[] = "dm_plex_gmsh_project_"; 2111066ea43fSLisandro Dalcin PetscBool continuity = periodic ? PETSC_FALSE : PETSC_TRUE; 2112066ea43fSLisandro Dalcin PetscDTNodeType nodeType = PETSCDTNODES_GAUSSJACOBI; 2113066ea43fSLisandro Dalcin 2114066ea43fSLisandro Dalcin if (isSimplex) continuity = PETSC_FALSE; /* XXX FIXME Requires DMPlexSetClosurePermutationLexicographic() */ 21159566063dSJacob Faibussowitsch PetscCall(GmshCreateFE(comm, prefix, isSimplex, continuity, nodeType, dim, coordDim, order, &fe)); 21169566063dSJacob Faibussowitsch PetscCall(PetscFEViewFromOptions(fe, NULL, "-dm_plex_gmsh_project_fe_view")); 2117e44f6aebSMatthew G. Knepley PetscCall(DMSetCoordinateDisc(*dm, fe, PETSC_TRUE)); 21189566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 2119066ea43fSLisandro Dalcin } 2120066ea43fSLisandro Dalcin 21219566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreateGmsh, *dm, NULL, NULL, NULL)); 21223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2123331830f3SMatthew G. Knepley } 2124